Skip to content
Snippets Groups Projects
Commit 715289cc authored by Eric Würbel's avatar Eric Würbel
Browse files

Initialisation.

parents
No related branches found
No related tags found
No related merge requests found
asp.pl 0 → 100644
%% -*- prolog -*-
/*
Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
This file is part of PASP. PASP is free software: you
can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.
PASP is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with PASP. If not, see <http://www.gnu.org/licenses/>.
PASP implements the simulation of possibilistic ASP with
a classical ASP solver.
This module implements predicates which runs an ASP solver on some
program. It also declares necessary operators for ASP programs
generation.
*/
:-module(asp,[
run/2,
run/3,
op(900,fy,not),
op(900,fy,'#minimize'),
op(900,fy,'#domain'),
op(900,fy,'#hide'),
op(700,xfy,'..'),
op(700,xfx,'!=')
]).
:-use_module(utils,[chars_codes/2]).
:-use_module(library(process)).
:-use_module(library(readutil)).
:-use_module(library(charsio)).
:-use_module(library(clpfd)).
%% run(+File,-Results)
%
% Runs an asp solver on the specified File and collect
% Results. At this time, the only supportedd solver is solver is
% clingo.
run(File,Results) :-
run(File,Results,[opt(none)])
.
%% run(+File,-Results,+Options)
%
% Runs an asp solver on the specified File and collect
% Results. At this time, the only supportedd solver is solver is
% clingo. Option is a list of options. Actually, the supported
% options are :
% - opt(none) synonym for no option
% - opt(inclmin) keep removed sets which are minimal with respect
% to set inclusion. Beware, this is performed by a
% post-processing, i.e. all removed sets are computed, and then
% the minimal ones are filtered.
% - opt(prog) : keep the removed sets computed by the optimization
% implemented inthe program.
run(File,Results,[]) :-
run(File,Results,[opt(none)]).
run(File,Results,[Opt]) :-
nb_getval(clasppath, Path),
% --opt-mode=optN is the new syntax of --opt-all (clingo 4.4.0)
nb_getval(claspver, V),
( V #= 3
-> OPTOPT = '--opt-all'
; OPTOPT = '--opt-mode=optN'
),
process_create(Path, [0, OPTOPT,File], [stdout(pipe(PH)),detached(true)]),
collect_results(PH,Results1),
close(PH,[force(true)]), % hack
post_process(Results1,Results,Opt)
.
%% post_process(+InResults, -OutResults, +Option)
%
% Do some post processing on collected results.
% Option is a opt/1 term with the following significance :
% none : no optimization : collect all answer sets (i.e. all
% potiential removed sets).
% inclmin : keep inclusion-minimal potential remove sets.
% prog : keep removed sets given by the optimization implemented
% in the program.
% TODO : séparer (et autoriser) trois cas :
% - inclmin seul : comme avant : on garde les incl-min de tous les
% answer sets.
% - prog seul : comme avant : on garde les answer sets optimisés
% du prog.
% - prog+inclmin : on garde les answer sets optimisés, et parmi
% ceux-ci on garde les minimaux suivants l'inclusion.
post_process(InResults, OutResults,opt(none)) :-
filter_nonopt_results(InResults,OutResults)
.
post_process(InResults, OutResults,opt(inclmin)) :-
filter_nonopt_results(InResults,R1),
keep_inclmin(R1,OutResults)
.
post_process(InResults, OutResults,opt(prog)) :-
filter_results(InResults,R1),
keep_min_opt(R1,[],R2),
final_list(R2,OutResults)
.
%% collect_results(+Stream, -Results)
%
% Reads, analyzes and collect results from clasp solver.
collect_results(Stream,Results) :-
read_line_to_codes(Stream,Line),
chars_codes(LineC,Line),
( Line = end_of_file ->
Results = [];
% ->
parse_result_line(LineC,R),
( R = end ->
Results = [];
% true
( R = garbage ->
collect_results(Stream, Results);
% true
Results = [R|Results1],
collect_results(Stream,Results1)
)
)
)
.
%% filter_nonopt_results(+In,-Out)
%
% Removes garbage from ASP solver output, i.e. keep only answer
% sets lines.
%
% !! CUT !!
filter_nonopt_results([],[]) :- !.
filter_nonopt_results([as(AS)|L1],[AS|L2]) :-
!,
filter_nonopt_results(L1,L2).
filter_nonopt_results([_|L1],L2) :-
filter_nonopt_results(L1,L2)
.
%% filter_results(+In, -Out)
%
% Removes garbage, writes triples (Answer #, optimisation value,
% answer set) in a compact way.
%
% !! CUT !!
filter_results([],[]) :- !.
filter_results([garbage|L1],L2) :- !,
filter_results(L1,L2)
.
filter_results([answer_num(N),as(AS),optimization(O)|L1],[N/O/AS|L2]) :-
filter_results(L1,L2)
.
%% keep_inclmin(+Collection,?MinIncl)
%
% Succeeds if MinIncl is the collection of inclusion-minimal
% sets of Collection.
keep_inclmin(Collection,MinIncl) :-
keep_inclmin([],[],Collection,MinIncl)
.
%% keep_inclmin(+Choosen,+Rejected,+Collection,?Result)
%
% Upon success, Result contains the sets from Collection
% which are minimal according to set inclusion in Collection U
% Rejected, plus the sets which are initially in Chosen. The set
% inclusion test is performed on rsf/2 atoms only.
% See keep_inclmin/2 for everyday use !
keep_inclmin(S,_,[],S) :- !.
keep_inclmin(InS,R,[AS|L],OutS) :-
append([InS,R,L],Compare),
is_incl_min(AS,Compare), !,
keep_inclmin([AS|InS],R,L,OutS)
.
keep_inclmin(InS,R,[AS|L],OutS) :-
keep_inclmin(InS,[AS|R],L,OutS)
.
%% is_incl_min(+Set, +Collection)
%
% Tests wether Set is minimal according to set inclusion in
% Collection. The set inclusion test is erformed on rsf/2 atoms
% only.
is_incl_min(_,[]).
is_incl_min(S,[S1|L]) :-
\+ rsubset(S1,S),
is_incl_min(S,L)
.
is_incl_min(S,[S1|L]) :-
rsubset(S1,S),
rsubset(S,S1),
is_incl_min(S,L)
.
%% rsubset(?S1,?S2)
%
% True if all rsf/2 atoms in S1 are also in S2.
rsubset([],_).
rsubset([rsf(X,Y)|L],S2) :-
member(rsf(X,Y),S2),
rsubset(L,S2)
.
rsubset([A|L],S2) :-
A \= rsf(_,_),
rsubset(L,S2)
.
%% Keep minimize optimization results
keep_min_opt([],L,L).
keep_min_opt([N/O/AS|L],[],Final) :-
keep_min_opt(L,[N/O/AS],Final)
.
keep_min_opt([N/O/AS|L],[_/O1/_|_],Final) :-
O #< O1,
keep_min_opt(L,[N/O/AS],Final)
.
keep_min_opt([N/O/AS|L],[N1/O1/AS1|L1],Final) :-
O #= O1,
keep_min_opt(L,[N/O/AS,N1/O1/AS1|L1],Final)
.
keep_min_opt([_/O/_|L],[N1/O1/AS1|L1],Final) :-
O #> O1,
keep_min_opt(L,[N1/O1/AS1|L1],Final)
.
%% Remove AS number and optimization info.
final_list([],[]).
final_list([_/_/AS|L1],[AS|L2]) :-
final_list(L1,L2)
.
%% Answer set solver results parser.
parse_result_line(Line,R) :-
phrase(result_line(R),Line,_)
.
result_line(garbage) -->
['c','l','i','n','g','o'], space ,['v','e','r','s','i','o','n'], space,
versionspec(_)
.
result_line(garbage) -->
['R','e','a','d','i','n','g'], space, ['f','r','o','m'], space,
dirspec(_)
.
result_line(garbage) -->
['S','o','l','v','i','n','g','.','.','.']
.
result_line(answer_num(Num)) -->
answernum(Num)
.
result_line(optimization(Num)) -->
optimize(Num)
.
result_line(end) -->
['O','P','T','I','M','U','M',' ','F','O','U','N','D']
.
result_line(end) -->
['S','A','T','I','S','F','I','A','B','L','E']
.
result_line(as(AS)) -->
answer_set(AS)
.
%% version specification (unused for now)
versionspec([V|VS]) -->
number(V),
subversion(VS).
subversion([V|VS]) -->
['.'],
number(V),
subversion(VS)
.
subversion([]) -->
[]
.
dirspec([C|DS]) -->
[C],
{\+ char_type(C, space)},
dirspec(DS)
.
dirspec([]) -->
[]
.
%% Interpret the "Answer:" lines of clingo output.
answernum(Num) -->
['A','n','s','w','e','r',':'], space, number(Num)
.
%% Interpret the "Optimization" lines of clingo output.
optimize(Num) -->
['O','p','t','i','m','i','z','a','t','i','o','n',':'], space, number(Num)
.
%% collect answer sets from clingo output
answer_set([T|L]) -->
term(LT),
{
LT \= [],
chars_to_term(LT,T)
},
end_answer_set(L)
.
end_answer_set([T|L]) -->
[' '],
term(LT),
{
LT \= [],
chars_to_term(LT, T)
},
end_answer_set(L)
.
end_answer_set([]) -->
[' ']
.
end_answer_set([]) -->
[]
.
term([C|L]) -->
[C],
{\+ char_type(C,space)},
term(L)
.
term([]) -->
[]
.
space -->
[' '], space
.
space -->
[]
.
number(N) -->
digit(D0),
digits(D),
{ number_chars(N, [D0|D]) }
.
digits([D|T]) -->
digit(D),
digits(T).
digits([]) --> [].
digit(D) -->
[D],
{ char_type(D,digit) }
.
chars_to_term(Chars,Term) :-
append(Chars,['.'],Chars1),
open_chars_stream(Chars1,S),
read(S,Term),
close(S)
.
#! /bin/bash
# builing script for pasp.
function usage() {
echo "syntax : $0 [-e]" >&2
echo >&2
echo "Builds a standalone executable for pasp and paspfilter." >&2
echo >&2
echo "options:" >&2
echo "-e\tSpecifies that external libs should be embeded in the executable" >&2
}
ext=false
while getopts "e" o; do
case "$o" in
e) ext=true;;
[?]) usage; exit 1;;
esac
done
opts=""
if [ "$ext" = "true" ] ; then
opts="--foreign=save"
fi
swipl $opts --stand_alone=true --goal="go,halt" --toplevel="halt(1)" -o pasp -c loader.pl
swipl $opts --stand_alone=true --goal="go,halt" --toplevel="halt(1)" -o paspfilter -c postfilter_loader.pl
echo "=================================================================================="
echo "Compilation finished."
echo "The command line executable is available in the pasp file."
echo "The command line executable of the postfilter is available in the paspfilter file."
echo "=================================================================================="
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any qlater version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This module defines predicates for handling the generation of an ASP
%% progam from a PASP program
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-module(generator, [
certp/2,
necessity/2,
pasp_to_asp/3
]).
:-use_module(library(clpfd)).
:-use_module(library(apply)).
:-use_module(logic).
:-use_module(asp).
%% cert(+Wff, -Cert)
%
% compute the cert set (see Bauters & al 2013)
cert((A,B),Cert) :-
cert(A,CertA),
cert(B,CertB),
union(CertA,CertB,Cert)
.
cert((:-B),[N]) :-
conjunct_member(nec__(N),B)
.
cert((_:-B), [N]) :-
conjunct_member(nec__(N),B)
.
%% certp(+Wff, -Certp)
%
% Compute the cert+ set
certp(Wff,Certp) :-
cert(Wff,Cert1),
nec_complement(Cert1,L2),
reverse(L2,Cert2),
union(Cert1,Cert2,Cert3),
union(Cert3,[0, 50, 100],Certp1),
sort(Certp1,Certp)
.
nec_complement([],[]).
nec_complement([N1|L1],[N2|L2]) :-
N2 #= 100 - N1,
nec_complement(L1,L2)
.
%% necessity(+Rule, -Necessity)
%
% Necessity measure of a rule.
necessity((:-B),N) :-
conjunct_member(nec__(N),B)
.
necessity((_:-B),N) :-
conjunct_member(nec__(N),B)
.
%% necesity(+Rule, -NewRule, -Necessity)
%
% Necessity measure of a rule. NewRule is the rule without the
% necessity atom.
necessity((:-B),(:-NewB),N) :-
conjunct_member(nec__(N),B),
apply_to_conjuncts(B,is_necessity,B1),
flatten_conjunction(B1,NewB)
.
necessity((H:-B),(H:-NewB),N) :-
conjunct_member(nec__(N),B),
apply_to_conjuncts(B,is_necessity,B1),
flatten_conjunction(B1,NewB)
.
is_necessity(nec__(_),true) :- !.
is_necessity(A,A).
%% pasp_to_asp(+Pasp, +Certp, -ASP)
%
% Generate an ASP program from a PASP program, using a cert+ set.
%
pasp_to_asp(PASP,Certp,ASP) :-
collect_pasp_to_asp(PASP,Certp,true,ASP).
collect_pasp_to_asp((A,B),Certp,InASP,OutASP) :-
collect_pasp_to_asp(A,Certp,InASP,OutASP1),
collect_pasp_to_asp(B,Certp,OutASP1,OutASP)
.
collect_pasp_to_asp((:-B),Certp,InASP,OutASP) :-
pasp_rule_to_asp_rules((:-B),Certp,InASP,OutASP)
.
collect_pasp_to_asp((H:-B),Certp,InASP,OutASP) :-
pasp_rule_to_asp_rules((H:-B),Certp,InASP,OutASP)
.
%% pasp_rule_to_asp_rules(+Rule, +Certp, +InASP, -OutASP)
%
% Generate the ASP rules corresponding to a PASP rule.
pasp_rule_to_asp_rules((H:-B),Certp,InASP,OutASP) :-
necessity((H:-B),(H:-NewB),N),
include(between(0,N),Certp,[0|L]),
rule2rules((H:-NewB),Certp,L,Rules),
conjoin(InASP,Rules,OutASP)
.
pasp_rule_to_asp_rules((:-B),Certp,InASP,OutASP) :-
necessity((:-B),(:-NewB),N),
include(between(0,N),Certp,[0|L]),
rule2rules((:-NewB),Certp,L,Rules),
conjoin(InASP,Rules,OutASP)
.
rule2rules(_,_,[],true).
rule2rules((H:-B),Certp,[Cp|L],Rules) :-
splitbody(B,PB,NB),
% NB \= true, % peut etre inutile. À voir.
D #= 100 - Cp,
include(between(D,100),Certp,[V1,V2|_]),
( V1 =:= D
-> MaxD = V2
; MaxD = V1
),
newlit(H,Cp,H1),
( PB = true
-> PosB = true
; new_posbody(PB,Cp,PosB)
),
( NB = true
-> NegB = true
; new_negbody(NB,MaxD,NegB)
),
conjoin(PosB,NegB,B1),
flatten_conjunction(B1,Body),
rule2rules((H:-B),Certp,L,Rules1),
( Body = true
-> conjoin(H1,Rules1,Rules)
; conjoin((H1:-Body),Rules1,Rules)
)
.
rule2rules((:-B),Certp,[Cp|L],Rules) :-
splitbody(B,PB,NB),
% NB \= true, % peut etre inutile. À voir.
D #= 100 - Cp,
include(between(D,100),Certp,[V1,V2|_]),
( V1 =:= D
-> MaxD = V2
; MaxD = V1
),
( PB = true
-> PosB = true
; new_posbody(PB,Cp,PosB)
),
( NB = true
-> NegB = true
; new_negbody(NB,MaxD,NegB)
),
conjoin(PosB,NegB,B1),
flatten_conjunction(B1,Body),
rule2rules((:-B),Certp,L,Rules1),
( Body = true
-> error('empty constraint : ~w~n', [(:-B)])
; conjoin((:-Body),Rules1,Rules)
)
.
newlit(-A,V,-Lit) :-
atom(A),
Lit =.. [A,V]
.
newlit(A,V,Lit) :-
atom(A), A \= -_,
Lit =.. [A,V]
.
newlit(-A,V,-Lit) :-
compound(A),
A =.. [F|Args],
append(Args,[V],NArgs),
Lit =.. [F|NArgs]
.
newlit(A,V,Lit) :-
A \= -_,
compound(A),
A =.. [F|Args],
append(Args,[V],NArgs),
Lit =.. [F|NArgs]
.
new_posbody((A,B),V,PosB) :-
new_posbody(A,V,A1),
new_posbody(B,V,B1),
conjoin(A1,B1,PosB)
.
new_posbody(Lit,V,NewLit) :-
Lit \= (_,_),
is_asp_literal(Lit),
newlit(Lit,V,NewLit)
.
new_negbody((A,B),V,NegB) :-
new_negbody(A,V,A1),
new_negbody(B,V,B1),
conjoin(A1,B1,NegB)
.
new_negbody((not Lit),V,(not NewLit)) :-
Lit \= (_,_),
is_asp_literal(Lit),
newlit(Lit,V,NewLit)
.
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of pasp. pasp is free
%% software: you can redistribute it and/or modify it under the
%% terms of the GNU General Public License as published by the Free
%% Software Foundation, either version 3 of the License, or (at
%% your option) any later version.
%%
%% pasp is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PLRsf-solver. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% pasp implements possibilistic answer set programming.
%%
%% This file is the initialization file of the pasp standalone
%% executable.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-ensure_loaded('pasp.pl').
logic.pl 0 → 100644
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any later version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This module defines logical formulae manipulation predicates.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-module(logic, [
conjoin/3,
n_conjoin/2,
apply_to_conjuncts/3,
apply_to_conjuncts/4,
flatten_conjunction/2,
conjunct_size/2,
conjunct_member/2,
splitbody/3,
is_asp_atom/1,
is_asp_literal/1
]).
:-meta_predicate apply_to_conjuncts(?,2,?).
:-meta_predicate apply_to_conjuncts(?,3,?,?).
:- use_module(asp).
:- use_module(library(clpfd)).
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% logic syntax manipulation predicates.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% conjoin(?A, ?B, ?C)
%%
%% C unifies with the conjunction of A and B. Conjonction is
%% represented à la prolog, that is with a comma.
%% (from Mark Stickel's PTTP)
conjoin(A,B,C) :-
A == true ->
C = B;
B == true ->
C = A;
A == false ->
C = false;
B == false ->
C = false;
A == B ->
C = A;
(B = (B1,_), A == B1) ->
C = B;
(A = (_,A2), B == A2) ->
C = A;
%true ->
C = (A , B).
%% n_conjoin(?List, ?C)
%%
%% unbounded arity version of conjoin/3.
n_conjoin([],true).
n_conjoin([C|L],Conj) :-
conjoin(C,C1,Conj),
n_conjoin(L,C1)
.
%% apply_to_conjuncts(?Wff,+P,?Wff1)
%%
%% apply P/2 predicate to each conjunt in Wff and Wff1.
%% That is, for all conjunct X,Y in Wff, call P(X,X1), P(Y,Y1), and
%% then conjunct X1 and Y1 to build Wff1 (from Mark Stickel's PTTP)
apply_to_conjuncts(Wff,P,Wff1) :-
Wff = (A , B) ->
apply_to_conjuncts(A,P,A1),
apply_to_conjuncts(B,P,B1),
conjoin(A1,B1,Wff1);
%true ->
call(P,Wff,Wff1)
.
%% apply_to_conjuncts(?Wff,+P, ?Arg, ?Wff1)
%%
%% Same as apply_to_conjuncts/3, but each call to P is of the form
%% P(X,Arg,Y), where X is in Wff. See apply_to_conjuncts/3 for more
%% info.
apply_to_conjuncts(Wff,P,Arg,Wff1) :-
Wff = (A , B) ->
apply_to_conjuncts(A,P,Arg,A1),
apply_to_conjuncts(B,P,Arg,B1),
conjoin(A1,B1,Wff1);
%true ->
call(P,Wff,Arg,Wff1)
.
%% flatten_conjunction(+Wff,-FWff)
%%
%% FWff is unified with the flattened version of Wff.
%% (from Mark Stickel's PTTP)
flatten_conjunction( Wff, FWff ) :-
flatten_conjunction(Wff,true,FWff).
flatten_conjunction( Wff, AWff, FWff ) :-
Wff = (Wff1,Wff2) ->
flatten_conjunction(Wff2,AWff,FWff1),
flatten_conjunction(Wff1,FWff1,FWff);
AWff = true ->
FWff = Wff;
%true ->
FWff = (Wff,AWff)
.
%% conjunct_size(C, S)
%%
%% True if S is the size of the conjunction C. The conjunction
% needs to be flat, eg : (r1, (r2, ...(r(n-1),rn)...))
conjunct_size((_,B),S) :-
S #= S1 + 1,
conjunct_size(B,S1)
.
conjunct_size(R,1) :-
R \= (_,_)
.
%% conjunct_member(M, C)
%
% True if M is a member of the conjunct C. The conjunct needs to
% be flat.
conjunct_member(M, (M, _)).
conjunct_member(M, (A, B)) :-
M \= A,
conjunct_member(M, B)
.
conjunct_member(M, M) :-
M \= (_, _)
.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Logic program rules handling.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% splitbody(?B,?PB,?NB)
%
% True if body B consists in positive body PB conjoined with
% negative body NB.
%
splitbody((A, B),PB,NB) :-
splitbody(A,PB1,NB1),
splitbody(B,PB2,NB2),
conjoin(NB1,NB2,NB),
conjoin(PB1,PB2,PB)
.
splitbody((not A),true,(not A)).
splitbody(-A,-A,true).
splitbody(A,A,true) :-
A \= (_,_),
A \= (not _),
A \= -_
.
%% is_asp_atom(+A)
%
% True if A is a valid ASP atom.
is_asp_atom(A) :-
atom(A).
is_asp_atom(A) :-
A \= -_,
compound(A)
.
%% is_asp_literal(+A)
%
% True if A is a valid ASP literal.
is_asp_literal(A) :-
is_asp_atom(A)
.
is_asp_literal(-A) :-
is_asp_atom(A)
.
pasp 0 → 100755
File added
pasp.pl 0 → 100644
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any qlater version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This file contains the main predicates.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% written for swi-prolog
%% Command line specification.
:-use_module(utils).
:-use_module(paspio).
:-use_module(generator).
go :-
current_prolog_flag(argv, [_|InputFiles]),
( InputFiles = []
-> error("no input files")
; true
),
load_pasp_programs(InputFiles,Wff),
certp(Wff,Certp),
pasp_to_asp(Wff,Certp,ASP),
write_conjunct(ASP,user_output)
.
test(Files) :-
load_pasp_programs(Files,Wff),
certp(Wff,Certp),
pasp_to_asp(Wff,Certp,ASP),
write_conjunct(ASP,user_output)
.
File added
paspio.pl 0 → 100644
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any later version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This module defines predicates for handling the loading of
%% programs.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-module(paspio, [
load_pasp_programs/2,
load_pasp_program/2,
write_clauses/2,
write_conjunct/2,
write_answer_sets/2
]).
:-use_module(utils).
:-use_module(logic, [conjoin/3]).
:-use_module(asp).
%% load_pasp_programs(+Filenames, -Wffs)
%
% Load pasp programs.
load_pasp_programs([],true).
load_pasp_programs([FileName|FL],Wffs) :-
load_pasp_program(FileName,Wff),
load_pasp_programs(FL,Wffs1),
conjoin(Wff,Wffs1,Wffs)
.
%% load_pasp_program(+Filename, -Wff)
%
% Load a PASP program
load_pasp_program(Filename, Wff) :-
exists_file(Filename),
open(Filename,read,Stream),
read_wff_loop(Stream,Wff)
.
load_pasp_program(Filename, _) :-
\+ exists_file(Filename),
error('~w: not found~n', [Filename])
.
read_wff_loop(Stream,Wff) :-
read_term(Stream,Wff1,[module(asp)]),
(Wff1 == end_of_file ->
Wff = true;
%true ->
read_wff_loop(Stream,Wff2),
conjoin(Wff1,Wff2,Wff))
.
write_clauses(Conjunct, File) :-
open(File,write,Stream),
write_conjunct(Conjunct,Stream),
close(Stream)
.
write_conjunct((A, B),Stream) :-
!,
write_conjunct(A,Stream),
write_conjunct(B,Stream)
.
write_conjunct(R,Stream) :-
write_term(Stream,R,[max_depth(0),numbervars(true),portray(true),module(asp)]),
put(Stream,'.'),
nl(Stream)
.
%% write_answer_sets(+Stream, +ASL)
%
% Write the answer sets list ASL on Stream.
write_answer_sets(_,[]).
write_answer_sets(Stream,[as(N,AS)|L]) :-
format(Stream,'Answer: ~10r~n',[N]),
write_as(Stream,AS),
nl(Stream),
write_answer_sets(Stream,L)
.
write_as(_,[]).
write_as(Stream,[At|L]) :-
write_term(Stream,At,[max_depth(0),portray(true)]),
put(Stream,' '),
write_as(Stream,L)
.
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any qlater version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This module defines predicates for handling the filtering of the
%% models of the resulting ASP simulation program.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-module(postfilter, [
collect_results/2,
filter_answer_sets/2
]).
:-use_module(utils,[chars_codes/2]).
:-use_module(library(readutil)).
:-use_module(library(charsio)).
%% collect_results(+Stream, -Results)
%
% Reads, analyzes and collect results from clasp solver.
collect_results(Stream,Results) :-
read_line_to_codes(Stream,Line),
chars_codes(LineC,Line),
( Line = end_of_file ->
Results = [];
% ->
parse_result_line(LineC,R),
( R = end ->
Results = [];
% true
( R = garbage ->
collect_results(Stream, Results);
% true
Results = [R|Results1],
collect_results(Stream,Results1)
)
)
)
.
%% filter_answer_sets(+ASL,-FASL)
%
% Filters a list of answer sets.
filter_answer_sets([],[]).
filter_answer_sets([answer_num(N),as(AS)|ASL],[as(N,FAS)|FASL]) :-
filter_as(AS,FAS),
filter_answer_sets(ASL,FASL)
.
%% filter_as(+AS,-FAS)
%
% Filters an answer set. The filtering process is as follows : for
% each atoms in the model which differ only on the necessity
% degree, keep the one with the greatest necessity degree.
filter_as([],[]).
filter_as([A|L1],[MaxA|L2]) :-
collect_identical_atoms(A,L1,LID,LRest),
max_member(MaxA,[A|LID]),
filter_as(LRest,L2)
.
%% collect_identical_atoms(+At,?InList,?IDList,?RestList)
%
% InList is a list of ASP atoms (prolog terms).
% IDList and RestList is a partition of Inlist. IDlist contains
% atoms similar to At : same functor, same arity, same arguments
% except the last one which is always a number (thus the arity of
% terms is at least 1).
collect_identical_atoms(_,[],[],[]).
collect_identical_atoms(At,[A|L1],[A|L2],L3) :-
At =.. [F|Args1],
A =.. [F|Args2],
length(Args1,Lg),
length(Args2,Lg),
eq_except_last(Args1,Args2),
!,
collect_identical_atoms(At,L1,L2,L3)
.
collect_identical_atoms(At,[A|L1],L2,[A|L3]) :-
collect_identical_atoms(At,L1,L2,L3)
.
%% eq_except_last(?L1,?L2)
%
% L1 and L2 are identical, i.E. their elements are equal in the
% sense of ==, except their last element.
eq_except_last([E1],[E2]) :- E1 \== E2.
eq_except_last([E1|L1],[E2|L2]) :-
E1 == E2,
eq_except_last(L1,L2)
.
%% Answer set solver results parser.
parse_result_line(Line,R) :-
phrase(result_line(R),Line,_)
.
result_line(garbage) -->
['c','l','i','n','g','o'], space ,['v','e','r','s','i','o','n'], space,
versionspec(_)
.
result_line(garbage) -->
['R','e','a','d','i','n','g'], space, ['f','r','o','m'], space,
dirspec(_)
.
result_line(garbage) -->
['S','o','l','v','i','n','g','.','.','.']
.
result_line(answer_num(Num)) -->
answernum(Num)
.
result_line(optimization(Num)) -->
optimize(Num)
.
result_line(end) -->
['O','P','T','I','M','U','M',' ','F','O','U','N','D']
.
result_line(end) -->
['S','A','T','I','S','F','I','A','B','L','E']
.
result_line(as(AS)) -->
answer_set(AS)
.
%% version specification (unused for now)
versionspec([V|VS]) -->
number(V),
subversion(VS).
subversion([V|VS]) -->
['.'],
number(V),
subversion(VS)
.
subversion([]) -->
[]
.
dirspec([C|DS]) -->
[C],
{\+ char_type(C, space)},
dirspec(DS)
.
dirspec([]) -->
[]
.
%% Interpret the "Answer:" lines of clingo output.
answernum(Num) -->
['A','n','s','w','e','r',':'], space, number(Num)
.
%% Interpret the "Optimization" lines of clingo output.
optimize(Num) -->
['O','p','t','i','m','i','z','a','t','i','o','n',':'], space, number(Num)
.
%% collect answer sets from clingo output
answer_set([T|L]) -->
term(LT),
{
LT \= [],
chars_to_term(LT,T)
},
end_answer_set(L)
.
end_answer_set([T|L]) -->
[' '],
term(LT),
{
LT \= [],
chars_to_term(LT, T)
},
end_answer_set(L)
.
end_answer_set([]) -->
[' ']
.
end_answer_set([]) -->
[]
.
term([C|L]) -->
[C],
{\+ char_type(C,space)},
term(L)
.
term([]) -->
[]
.
space -->
[' '], space
.
space -->
[]
.
number(N) -->
digit(D0),
digits(D),
{ number_chars(N, [D0|D]) }
.
digits([D|T]) -->
digit(D),
digits(T).
digits([]) --> [].
digit(D) -->
[D],
{ char_type(D,digit) }
.
chars_to_term(Chars,Term) :-
append(Chars,['.'],Chars1),
open_chars_stream(Chars1,S),
read(S,Term),
close(S)
.
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any qlater version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% This file is the initialization file of the pasp standalone
%% executable.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-ensure_loaded('postfilter_main.pl').
%% -*- prolog -*-
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright 2016 Éric Würbel, LSIS-CNRS, AMU
%%
%% This file is part of PASP, a possibilistic ASP solver.
%% PASP is free software: you can redistribute it and/or
%% modify it under the terms of the GNU General Public License as
%% published by the Free Software Foundation, either version 3 of
%% the License, or (at your option) any later version.
%%
%% PASP is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with PASP. If not, see
%% <http://www.gnu.org/licenses/>.
%%
%% PASP implements the simulation of possibilistic ASP with
%% a classical ASP solver.
%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:-use_module(postfilter).
:-use_module(paspio).
go :-
collect_results(user_input,Results),
filter_answer_sets(Results,FResults),
write_answer_sets(user_output,FResults)
.
test(Filename) :-
open(Filename,read,Stream),
collect_results(Stream,Results),
filter_answer_sets(Results,FResults),
write_answer_sets(user_output,FResults)
.
concertBooked :- nec__(100).
longDrive :- concertBooked, not canceled, nec__(100).
canceled :- nec__(20).
clingo version 4.5.4
Solving...
Answer: 1
concertBooked(20) concertBooked(50) concertBooked(80) concertBooked(100) canceled(20) longDrive(20) longDrive(50) longDrive(80)
SATISFIABLE
Models : 1
Calls : 1
Time : 0.012s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.000s
utils.pl 0 → 100644
%% -*-prolog-*-
/*
Copyright 2012-2014 Éric Würbel, LSIS-CNRS, Université de Toulon.
This file is part of PLRsf-solver.
PLRsf-Solver is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
PLRsf-Solver is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with Rsf-solver. If not, see
<http://www.gnu.org/licenses/>.
PLRsf-Solver implements removed set fusion of
knowledge bases represented by logic programs.
Various useful predicates.
*/
:-module(utils,[
error/2,
error/1,
chars_codes/2,
integer_enum/3,
integer_enuml/3
]).
:-use_module(library(clpfd)).
%% error(+Msg)
%
% Writes an error message ont the user_error stream and throws a
% plrsf_exception with the same message as argument.
error(Msg) :-
write(user_error,Msg),
throw(plrsf_exception(Msg))
.
%% error(+Fmt, +Args)
%
% Formats a message, writes it ont the user_error stream, then
% throws a plrsf_exception with the same formatted message as
% argument.
error(Fmt, Args) :-
format(user_error,Fmt,Args),
format(atom(A),Fmt,Args),
throw(plrsf_exception(A))
.
%% char_codes (?Chars, Codes)
%
% From lists of chars to lists of codes.
chars_codes([],[]).
chars_codes([Ch|L1],[Co|L2]) :-
char_code(Ch, Co),
chars_codes(L1,L2)
.
%% integer_enum(?Min, ?Max, ?List)
%
% List is a list of consecutive integers from Min to Max
% (inclusive).
integer_enum(V, V, [V]).
integer_enum(Min, Max, [Min|L]) :-
Min #< Max,
Min1 #= Min+1,
integer_enum(Min1,Max,L)
.
%% integer_enuml(?Min, ?Max, ?List)
%
% List is a list of singleton lists containing consecutive
% integers from Min to Max (inclusive).
integer_enuml(V, V, [[V]]).
integer_enuml(Min, Max, [[Min]|L]) :-
Min #< Max,
Min1 #= Min+1,
integer_enuml(Min1,Max,L)
.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment