:- ensure_loaded(type_union4).
:- ensure_loaded(utilities).
 

 % next try: interleave  permutation and lp acceptability

 % compile_lp(+SubcatList,+LPrules,-ListOfSubcatLists)
 % finds all permutations of the subcat list that are lp acceptable,
 % does this while constructing the permutations

compile_lp([],_LP,[]).
compile_lp(Subcat,LP,Result):-
	findall(NewSubcat,
	        permutation_and_lp(Subcat,NewSubcat,LP),
		Result).
        
 
 % permutation_and_lp/4, insert_if_lp/4 are variations of the code found
 % in library(lists) 

permutation_and_lp(List, Perm, LP) :-
	permutation_and_lp(List, Perm, Perm, LP).

permutation_and_lp([], [], [], _).
permutation_and_lp([X|Xs], Ys1, [_|Zs], LP) :-
	permutation_and_lp(Xs, Ys, Zs ,LP),
	insert_if_lp(Ys, X, Ys1, LP).

insert_if_lp(L, X, [X|L], LP):-
	lp_acceptable(LP,X,L).
insert_if_lp([H|T], X, [H|L],LP) :-
	insert_if_lp(T, X, L,LP),
	lp_acceptable(LP,H,L).


 % lp_acceptable(LP_Rules,FirstOfSubcat,RestOfSubcat)
 % First and Rest are separate arguments because insert_if_lp/4 needs
 % them this way and so I keep it that way
 % unpacks the FSs from the lp wrapper

lp_acceptable([],_First,_Rest).
lp_acceptable([lp(FS1,FS2)|T],First,Rest):-
	lp_aux_1(Rest,First,FS1,FS2),
	lp_acceptable(T,First,Rest).


 % lp_aux_1(RestList,First,FS1,FS2)
 % checks whether First unifies with the second FS2 of the lp rule, if
 % this is not the case, it is not necessary to check lp acceptability
 % for this constellation; if it is the case, it remains to be checked
 % whether one of the elements from the RestList unifies with FS1 ->
 % violation of the lp rule.
 % To make this deterministic, I wrote [H|T] in lp_aux_1 and LP_aux
 % though it would have been easier to have just one variable in this
 % place. 

lp_aux_1([],_,_,_).
lp_aux_1([H|T],First,FS1,FS2):-
	(unify_fs(First,FS2,_) ->
	    lp_aux([H|T],FS1)
	;
	    true
	).

 % lp_aux(SubcatList,FS)
 % checks whether an element of SubcatList unifies with FS -> fails in
 % this case since a violation of an LP rule has occured.

lp_aux([],_FS1).
lp_aux([Next|T],FS1):-
	\+ unify_fs(Next,FS1,_),
	lp_aux(T,FS1).
