345 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
/*==============================================================================
 | 
						||
 *	LPAD and CP-Logic reasoning suite
 | 
						||
 *	File: parsing.pl
 | 
						||
 *	Parses predicates to load LPADs (main predicate: parse(FileNameNoExt)
 | 
						||
 *	Copyright (c) 2009, Stefano Bragaglia
 | 
						||
 *============================================================================*/
 | 
						||
  
 | 
						||
:- dynamic rule/4, def_rule/2.
 | 
						||
 | 
						||
:- use_module(params).
 | 
						||
:- use_module(utility).
 | 
						||
 | 
						||
% :- source.
 | 
						||
% :- yap_flag(single_var_warnings, on).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* parse(File) 
 | 
						||
 * -----------
 | 
						||
 * This predicate parses the given .cpl file. 
 | 
						||
 *
 | 
						||
 * Note: it can be called more than once without exiting yap 
 | 
						||
 *
 | 
						||
 * INPUT
 | 
						||
 *  - File: .cpl file to parse, without extension.
 | 
						||
 */
 | 
						||
parse(File) :- 
 | 
						||
	atom_concat(File, '.cpl', FileName),
 | 
						||
	open(FileName, read, FileHandle), 
 | 
						||
	read_clauses(FileHandle, Clauses), 
 | 
						||
	close(FileHandle), 
 | 
						||
	retractall(rule_by_num(_, _, _, _, _)), 
 | 
						||
	retractall(rule(_, _, _, _, _, _, _, _)), 
 | 
						||
	retractall(def_rule(_, _)), 
 | 
						||
	process_clauses(Clauses, 1).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* assert_rules()
 | 
						||
 * --------------
 | 
						||
 * This tail recursive predicate parses the given list of (Head:Prob) couples
 | 
						||
 * and stores them incrementally as rules along with the other parameters.
 | 
						||
 *
 | 
						||
 * INPUT
 | 
						||
 *  - Head: current head part.
 | 
						||
 *  - Prob: probability of the current head part.
 | 
						||
 *  - Index: index of the current head part.
 | 
						||
 *  - Subst: substitution for the current head part.
 | 
						||
 *  - Choices: list of current head parts indexes.
 | 
						||
 *  - HeadList: complete head or list of its parts.
 | 
						||
 *  - BodyList: complete body or list of its parts.
 | 
						||
 */
 | 
						||
assert_rules([], _Index, _HeadList, _BodyList, _Choices, _Id, _Subst) :- !. % Closing condition.
 | 
						||
 | 
						||
assert_rules(['':_Prob], _Index, _HeadList, _BodyList, _Choices, _Id, _Subst) :- !.
 | 
						||
 | 
						||
assert_rules([Head:Prob|Tail], Index, HeadList, BodyList, Choices, Id, Subst) :- 
 | 
						||
	assertz(rule(Head, Prob, Index, Id, Subst, Choices, HeadList, BodyList)), 
 | 
						||
	Next is Index + 1, 
 | 
						||
	assert_rules(Tail, Next, Id, Subst, Choices, HeadList, BodyList).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
delete_var(_Var, [], []).
 | 
						||
 | 
						||
delete_var(Var, [Current|Tail], [Current|Next]) :- 
 | 
						||
	Var \== Current, !, 
 | 
						||
	delete_var(Var, Tail, Next).
 | 
						||
 | 
						||
delete_var(_Var, [_Head|Tail], Tail).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
extract_vars(Variable, Var0, Var1) :- 
 | 
						||
	var(Variable), !, 
 | 
						||
	(member_eq(Variable, Var0) ->
 | 
						||
		Var1 = Var0;
 | 
						||
		append(Var0, [Variable], Var1)).
 | 
						||
 | 
						||
extract_vars(Term, Var0, Var1) :- 
 | 
						||
	Term=..[_F|Args], 
 | 
						||
	extract_vars_list(Args, Var0, Var1).
 | 
						||
 | 
						||
 | 
						||
 
 | 
						||
extract_vars_clause(end_of_file, []).
 | 
						||
 | 
						||
extract_vars_clause(Clause, VarNames, Couples) :- 
 | 
						||
	(Clause = (Head :- _Body) ->
 | 
						||
		true;
 | 
						||
		Head = Clause), 
 | 
						||
	extract_vars(Head, [], Vars), 
 | 
						||
	pair(VarNames, Vars, Couples).
 | 
						||
	
 | 
						||
 | 
						||
 | 
						||
extract_vars_list([], Var, Var).
 | 
						||
 | 
						||
extract_vars_list([Term|Tail], Var0, Var1) :- 
 | 
						||
	extract_vars(Term, Var0, Var), 
 | 
						||
	extract_vars_list(Tail, Var, Var1).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
get_var(Var, [Var]) :- 
 | 
						||
	var(Var), !. % Succeeds if Var is currently a free variable, otherwise fails. 
 | 
						||
 | 
						||
get_var(Var, Value) :- 
 | 
						||
	Var=..[_F|Args],
 | 
						||
	get_var_list(Args, Value).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
get_var_list([], []).
 | 
						||
 | 
						||
get_var_list([Head|Tail], [Head|Next]) :- 
 | 
						||
	var(Head), !, 
 | 
						||
	get_var_list(Tail, Next).
 | 
						||
 | 
						||
get_var_list([Head|Tail], Vars) :- !, 
 | 
						||
	get_var(Head, Var), 
 | 
						||
	append(Var, Next, Vars), 
 | 
						||
	get_var_list(Tail, Next).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* ground_prob(HeadList)
 | 
						||
 * ---------------------
 | 
						||
 * This tail recursive predicate verifies if the given HeadList is ground.
 | 
						||
 *
 | 
						||
 * INPUT
 | 
						||
 *  - HeadList: list of heads to verify its groundness.
 | 
						||
 */
 | 
						||
ground_prob([]).
 | 
						||
 | 
						||
ground_prob([_Head:ProbHead|Tail]) :- 
 | 
						||
	ground(ProbHead), % Succeeds if there are no free variables in the term ProbHead.
 | 
						||
	ground_prob(Tail).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
pair(_VarName, [], []).
 | 
						||
 | 
						||
pair([VarName = _Var|TailVarName], [Var|TailVar], [VarName = Var|Tail]) :- 
 | 
						||
	pair(TailVarName, TailVar, Tail).	
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* process_head(HeadList, CompleteHeadList)
 | 
						||
 * ----------------------------------------
 | 
						||
 * Note: if the annotation in the head are not ground, the null atom is not 
 | 
						||
 *       added and the eventual formulas are not evaluated.
 | 
						||
 */	
 | 
						||
process_head(HeadList, GroundHeadList) :- 
 | 
						||
	ground_prob(HeadList), !,
 | 
						||
	process_head_ground(HeadList, 0, GroundHeadList);
 | 
						||
	 
 | 
						||
process_head(HeadList, HeadList).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* process_head_ground([Head:ProbHead], Prob, [Head:ProbHead|Null])
 | 
						||
 * ----------------------------------------------------------------
 | 
						||
 */
 | 
						||
process_head_ground([Head:ProbHead], Prob, [Head:ProbHead|Null]) :- 
 | 
						||
	ProbLast is 1 - Prob - ProbHead, 
 | 
						||
	setting(epsilon_parsing, Eps), 
 | 
						||
	EpsNeg is - Eps, 
 | 
						||
	ProbLast > EpsNeg, 
 | 
						||
	(ProbLast > Eps ->
 | 
						||
		Null = ['':ProbLast];
 | 
						||
		Null = []). 
 | 
						||
 | 
						||
process_head_ground([Head:ProbHead|Tail], Prob, [Head:ProbHead|Next]) :- 
 | 
						||
	ProbNext is Prob + ProbHead, 
 | 
						||
	process_head_ground(Tail, ProbNext, Next).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/* process_body(BodyList, Vars0, Vars1)
 | 
						||
 * ------------------------------------
 | 
						||
 * Note: setof must have a goal in the form B^G, where B is a term containing 
 | 
						||
 *       the existential variables.
 | 
						||
 */
 | 
						||
process_body([], Vars, Vars).
 | 
						||
 | 
						||
process_body([setof(A, B^_G, _L)|Tail], Vars0, Vars1) :- !, 
 | 
						||
	get_var(A, VarsA), 
 | 
						||
	get_var(B, VarsB), 
 | 
						||
	remove_vars(VarsA, Vars0, Vars3), 
 | 
						||
	remove_vars(VarsB, Vars3, Vars2), 
 | 
						||
	process_body(Tail, Vars2, Vars1).
 | 
						||
 | 
						||
process_body([setof(A, _G, _L)|Tail], Vars0, Vars1) :- !, 
 | 
						||
	get_var(A, VarsA), 
 | 
						||
	remove_vars(VarsA, Vars0, Vars2), 
 | 
						||
	process_body(Tail, Vars2, Vars1).
 | 
						||
 | 
						||
process_body([bagof(A, B^_G, _L)|Tail], Vars0, Vars1) :- !, 
 | 
						||
	get_var(A, VarsA), 
 | 
						||
	get_var(B, VarsB), 
 | 
						||
	remove_vars(VarsA, Vars0, Vars3), 
 | 
						||
	remove_vars(VarsB, Vars3, Vars2), 
 | 
						||
	process_body(Tail, Vars2, Vars1).
 | 
						||
 | 
						||
process_body([bagof(A, _G, _L)|Tail], Vars0, Vars1) :- !, 
 | 
						||
	get_var(A, VarsA), 
 | 
						||
	remove_vars(VarsA, Vars0, Vars2), 
 | 
						||
	process_body(Tail, Vars2, Vars1).
 | 
						||
 | 
						||
process_body([_Head|Tail], Vars0, Vars1) :- !, 
 | 
						||
	process_body(Tail, Vars0, Vars1).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
process_clauses([(end_of_file, [])], _Id).
 | 
						||
 | 
						||
/* NB: il seguente predicato <20> stato commentato perch<63> usa predicati non conformi
 | 
						||
 *     a quelli attesi (vedi 'rule\5').
 | 
						||
 * /
 | 
						||
process_clauses([((Head :- Body), Value)|Tail], Id) :- 
 | 
						||
	Head=uniform(A, P, L), !, 
 | 
						||
	list2and(BodyList, Body), 
 | 
						||
	process_body(BodyList, Value, BodyListValue), 
 | 
						||
	remove_vars([P], BodyListValue, V2), 
 | 
						||
	append(BodyList, [length(L, Tot), nth0(Number, L, P)], BL1), 
 | 
						||
	append(V2, ['Tot'=Tot], V3), 
 | 
						||
	assertz(rule(Id, V3, _NH, uniform(A:1/Tot, L, Number), BL1)), 
 | 
						||
	assertz(rule_uniform(A, Id, V3, _NH, 1/Tot, L, Number, BL1)), 
 | 
						||
	N1 is Id+1, 
 | 
						||
	process_clauses(Tail, N1). */
 | 
						||
 | 
						||
process_clauses([((Head :- Body), Value)|Tail], Id) :- 
 | 
						||
	Head = (_;_), !, 
 | 
						||
	list2or(HeadListOr, Head), 
 | 
						||
	process_head(HeadListOr, HeadList), 
 | 
						||
	list2and(BodyList, Body), 
 | 
						||
	process_body(BodyList, Value, BodyListValue), 
 | 
						||
	length(HeadList, LH), 
 | 
						||
	listN(0, LH, NH), 
 | 
						||
	assert_rules(HeadList, 0, HeadList, BodyList, NH, Id, BodyListValue), 
 | 
						||
	assertz(rule_by_num(Id, BodyListValue, NH, HeadList, BodyList)), 
 | 
						||
	N1 is Id+1, 
 | 
						||
	process_clauses(Tail, N1).
 | 
						||
 | 
						||
process_clauses([((Head :- Body), Value)|Tail], Id) :- 
 | 
						||
	Head = (_:_), !, 
 | 
						||
	list2or(HeadListOr, Head), 
 | 
						||
	process_head(HeadListOr, HeadList), 
 | 
						||
	list2and(BodyList, Body), 
 | 
						||
	process_body(BodyList, Value, BodyListValue), 
 | 
						||
	length(HeadList, LH), 
 | 
						||
	listN(0, LH, NH), 
 | 
						||
	assert_rules(HeadList, 0, HeadList, BodyList, NH, Id, BodyListValue), 
 | 
						||
	assertz(rule_by_num(Id, BodyListValue, NH, HeadList, BodyList)), 
 | 
						||
	N1 is Id+1, 
 | 
						||
	process_clauses(Tail, N1).
 | 
						||
	
 | 
						||
process_clauses([((Head :- Body), _V)|Tail], Id) :- !, 
 | 
						||
	list2and(BodyList, Body), 
 | 
						||
	assert(def_rule(Head, BodyList)), 
 | 
						||
	process_clauses(Tail, Id).
 | 
						||
 | 
						||
process_clauses([(Head, Value)|Tail], Id) :- 
 | 
						||
	Head=(_;_), !, 
 | 
						||
	list2or(HeadListOr, Head), 
 | 
						||
	process_head(HeadListOr, HeadList), 
 | 
						||
	length(HeadList, LH), 
 | 
						||
	listN(0, LH, NH), 
 | 
						||
	assert_rules(HeadList, 0, HeadList, [], NH, Id, Value), 
 | 
						||
	assertz(rule_by_num(Id, Value, NH, HeadList, [])), 
 | 
						||
	N1 is Id+1, 
 | 
						||
	process_clauses(Tail, N1).
 | 
						||
 | 
						||
process_clauses([(Head, Value)|Tail], Id) :- 
 | 
						||
	Head=(_:_), !, 
 | 
						||
	list2or(HeadListOr, Head), 
 | 
						||
	process_head(HeadListOr, HeadList), 
 | 
						||
	length(HeadList, LH), 
 | 
						||
	listN(0, LH, NH), 
 | 
						||
	assert_rules(HeadList, 0, HeadList, [], NH, Id, Value), 
 | 
						||
	assertz(rule_by_num(Id, Value, NH, HeadList, [])), 
 | 
						||
	N1 is Id+1, 
 | 
						||
	process_clauses(Tail, N1).
 | 
						||
	
 | 
						||
process_clauses([(Head, _V)|Tail], Id) :- 
 | 
						||
	assert(def_rule(Head, [])), 
 | 
						||
	process_clauses(Tail, Id).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
read_clauses(Stream, Clauses) :- 
 | 
						||
	(setting(ground_body, true) ->
 | 
						||
		read_clauses_ground_body(Stream, Clauses);
 | 
						||
		read_clauses_exist_body(Stream, Clauses)).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
read_clauses_exist_body(Stream, [(Clause, Vars)|Next]) :- 
 | 
						||
	read_term(Stream, Clause, [variable_names(VarNames)]), 
 | 
						||
	extract_vars_clause(Clause, VarNames, Vars), 
 | 
						||
	(Clause = end_of_file ->
 | 
						||
		Next = [];
 | 
						||
		read_clauses_exist_body(Stream, Next)).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
read_clauses_ground_body(Stream, [(Clause, Vars)|Next]) :- 
 | 
						||
	read_term(Stream, Clause, [variable_names(Vars)]), 
 | 
						||
	(Clause = end_of_file ->
 | 
						||
		Next = [];
 | 
						||
		read_clauses_ground_body(Stream, Next)).
 | 
						||
 | 
						||
 | 
						||
 | 
						||
remove_vars([], Vars, Vars).
 | 
						||
 | 
						||
remove_vars([Head|Tail], Vars0, Vars1) :- 
 | 
						||
	delete_var(Head, Vars0, Vars2), 
 | 
						||
	remove_vars(Tail, Vars2, Vars1).
 |