345 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			345 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
|   | /*============================================================================== | |||
|  |  *	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 <EFBFBD> stato commentato perch<EFBFBD> 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). |