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

Initialisation.

parents
Branches
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