%
% the implicit fuser
% will be consulted by fuse.pl
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ifuse/3
%
% implicit fusion by finding all unifying links among vars
% the CIF itself may be changed as fusing with EQCs involves cloning
%
% ifuse(+Cif,-Groups,-Links)
%
% Cif		=	list of CIF to be fused
% Groups	=	a list of groups as a result of fusion (clones may be created)
% Links		=	list of unifications found
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ifuse(Cif,Groups,Links) :-
	sort_cif(Cif,Sorted_cif),					%sort it so that UQCs go before EQCs
	ifuse_into_group(Sorted_cif,fused(_,link(Uu,Eu),Groups)),	%fuse it
	my_union(Uu,Eu,Links).						%make join the 2 groups of link together

%
% ifuse_into_group/2
%
% implicitly fuse constraints by finding unification links between vars
%
% ifuse_into_group(+Cif,-Fused)
%
% Cif	=	list of CIF to be fused
% Fused	=	the fused CIF in a "fused/3" structure
%
ifuse_into_group([],fused(gen([],[]),link([],[]),group([]))).	%end of CIF, no more gen & links

ifuse_into_group([C|Cs],Fused) :-
	ifuse_into_group(Cs,Temp_fused),			%fuse the tail 1st
	ifuse_into_group(C,Temp_fused,Fused).			%then fuse head into the fused-tail

%
% ifuse_into_group/3
%
% ifuse_into_group(+C,+Fused,-New_fused)
%
% C	=	a QC to be fused into Fused
% Fused	=	a fused CIF in a "fused/3" structure
% New_fused	=	the new result as a fused/3
%

%
% no U-gen nor E-gen in "Fused", no fusion needed
% just return C1 as a group in fused/3
%
ifuse_into_group(C1,fused(gen([],[]),link(_,_),group(_)),Fused) :-
	C1=restrict_subquery(_,_,_),						%C1 is a QC
	!,
	get_all_gens(C1,Ug_of_c1,Eg_of_c1),					%get all gens in C1
	make_into_group(C1,C1_group),						%make C1 into a group
	Fused=fused(gen(Ug_of_c1,Eg_of_c1),link([],[]),[C1_group]).		%compose the fused structure

%
% something in gen, possible fusion
%
ifuse_into_group(C1,Fused,New_fused) :-
	C1=restrict_subquery(_,_,_),						%C1 is a QC
	!,
	get_all_gens(C1,Ug_of_c1,Eg_of_c1),					%get gens in C1
	%
	% STEP 1:	find UU-links between C1 & fused
	%
	ifuse_into_group_step1(C1,Ug_of_c1,Eg_of_c1,Fused,Temp_fused_1,Uu_flag),
	%
	% STEP 2:	find EU-links between C1's UQCs  & fused's EQCs
	%
	ifuse_into_group_step2(C1,Ug_of_c1,Eg_of_c1,Temp_fused_1,Temp_fused_2,Ue_flag),
	%
	% STEP 3:	find EU-links between C1's EQCs & fused's UQCs
	%
	ifuse_into_group_step3(C1,Ug_of_c1,Eg_of_c1,Temp_fused_2,Temp_fused_3,Eu_flag),
	%
	% now if C1 hasn't been added, add it
	%
	% NOTE:	in fact, we only add C1 in UU-matches
	%	UE & EU never add C1 but it's clone
	%
	(	(	Uu_flag=not_added,					%if there is no fusion taken place
			Ue_flag=not_added,					%put C1 into the result
			Eu_flag=not_added,
			!,
			Temp_fused_3=fused(gen(Temp_ug3,Temp_eg3),Temp_link_3,Temp_groups_3),
			append_cif(Ug_of_c1,Temp_ug3,New_ug),			%more U-gen
			append_cif(Eg_of_c1,Temp_eg3,New_eg),			%more E-gen
			New_gens=gen(New_ug,New_eg),				%the new gen
			New_link=Temp_link_3,					%no change in links
			make_into_group(C1,C1_group),
			New_groups=[C1_group|Temp_groups_3],			%add C1's group
			New_fused=fused(New_gens,New_link,New_groups)		%the new fused structure
		);
		(	New_fused=Temp_fused_3					%otherwise C1 must be put in
		)
	).

%
% step 1:	find UU-links between C1 & Fused
%
ifuse_into_group_step1(C1,Ug_of_c1,_,Fused,New_fused,Flag) :-
	Fused=fused(gen(Ug,_),_,_),
	find_matches(Ug_of_c1,Ug,Uu_matches),						%find matches between 2 Gs
	(	(	%
			% when there is no UU-match, we do not add C1
			%
			Uu_matches=[],							%no UU-link found
			!,
			Flag=not_added,							%no match found, C1 not added
			New_fused=Fused							%no change being made
		);
		(
			%
			% whenever there is a UU-match, C1 will be added
			%
			Flag=added,							%match(es) found
			ifuse_update_fused_from_uu_matches(C1,Fused,Uu_matches,New_fused)
		)
	).


%
% step 2:	find UE-links between C1 & Fused
%		potential cloning of C1 possible
%
ifuse_into_group_step2(C1,Ug_of_c1,_,Fused,New_fused,Flag) :-
	Fused=fused(gen(_,Eg),_,_),
	find_matches(Ug_of_c1,Eg,Ue_matches),						%find UE-matches
	%
	% NOTE:	no matter there is a UE-match or not, we don NOT add C1
	%
	(	(	Ue_matches=[],							%if no match found
			!,
			Flag=not_added,							%no match found, C1 not added
			New_fused=Fused							%no change at all
		);
		(	%
			% Now given this "bag" of UE-matches, we try to clone C1 (as many as needed)
			% and get the UE-links between these cloned-C1s & fused's EQCs
			% As C1 is being cloned, more vars are created and we have to
			% update U-gen & E-gen as well
			%
			Flag=not_added,						%match(es) found
			ifuse_update_fused_from_ue_matches(C1,Fused,Ue_matches,New_fused)
		)
	).


%
% step 3:	find EU-links between C1 & Fused
%		some groups in Fused may be cloned
%
ifuse_into_group_step3(C1,_,Eg_of_c1,Fused,New_fused,Flag) :-
	Fused=fused(gen(Ug,_),_,_),
	find_matches(Eg_of_c1,Ug,Eu_matches),						%find EU-matches
	%
	% NOTE:	no matter there is a EU-match or not, we don NOT add C1
	%
	(	(	Eu_matches=[],							%if no match found
			!,
			Flag=not_added,							%no match found, C1 not added
			New_fused=Fused							%no change at all
		);
		(	%
			% with the bag of EU-matches, we try to clone those matching groups in Fused
			%
			%
			Flag=not_added,							%match(es) found
			ifuse_update_fused_from_eu_matches(C1,Fused,Eu_matches,New_fused)
		)
	).

%------------------------------------------------------------
%
% ifuse_update_fused_from_to_fuse/3
%
% update the fused structure according to the list of to_fuse
%
% ifuse_update_fused_from_to_fuse(+Fused,+To_fuse,-New_fused)
%
% Fused		=	the current fused structure
% To_fuse	=	the list of updates in to_fuse/5
% New_fused	=	the updated fused structure
%
%------------------------------------------------------------

%
% end of update, just pass back the current fused structure
%
ifuse_update_fused_from_to_fuse(Fused,[],Fused).

%
% update the fused structure according to the to_fuse list
%
ifuse_update_fused_from_to_fuse(Fused,[To|Tos],New_fused) :-
	To=to_fuse(_,More_uu,More_eu,To_add_ug,To_add_eg,To_add_group),	%get the links and parts to fuse
	Fused=fused(gen(Ug,Eg),link(Uu,Eu),Current_groups),		%the current fused structure
	%
	% update gens
	%
	append_cif(To_add_ug,Ug,Temp_ug),				%more U-gen
	append_cif(To_add_eg,Eg,Temp_eg),				%more E-gen
	Temp_gen=gen(Temp_ug,Temp_eg),					%the temp gen structure
	%
	% update links
	%
	my_union(More_uu,Uu,Temp_uu),					%more UU-links
	my_union(More_eu,Eu,Temp_eu),					%more UU-links
	Temp_link=link(Temp_uu,Temp_eu),
	%
	% update groups
	%
	my_union(More_uu,More_eu,Links),				%get all links in this match
	groups_involved(Links,Current_groups,Involved,Left),		%find involved groups & left-behind in C2
	flatten([To_add_group|Involved],To_merge),			%put all related groups into a list
	merge_groups(To_merge,Merged_group),				%merge the 2 groups
	Temp_group=[Merged_group|Left],					%put back those left-behind
	Temp_fused=fused(Temp_gen,Temp_link,Temp_group),		%the current fused structure
	ifuse_update_fused_from_to_fuse(Temp_fused,Tos,New_fused).



%-----------------------------------------------------------
%
% ifuse_update_fused_from_uu_matches/4
%
% update fused structure according to UU-match instances
%
% if there is only 1 single matching instance between 2 CIFs
% then no cloning is required and just more links are added
%
% if there are multiple matching instances betweeen 2 CIFs
% then we need to clone
%
%-----------------------------------------------------------

ifuse_update_fused_from_uu_matches(C1,Fused,Matches,New_fused) :-
	ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,Fused,Matches,[],To_fuse),	%prepare a list of to_fuse structure
	ifuse_update_fused_from_to_fuse(Fused,To_fuse,New_fused).				%execute the to_fuse


%-----------------------------------------------------
%
% ifuse_update_fused_from_uu_matches_prepare_to_fuse/5
%
% prepare things to be fused from the matching list
%
% NOTE:	whenever there is a UU-match, C1 will be added
%
%-----------------------------------------------------

%
% end of matching list
%
ifuse_update_fused_from_uu_matches_prepare_to_fuse(_,_,[],_,[]).

%
% some vars in C1 have taken part in a previous match
% have to clone C1 and put it into a to_fuse/5 structure
%
ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(Var_in_c1:_,Match),							%there is a matching pair
	member(Var_in_c1:_,Previous_matches),						%the var in C1 has taken part in a previous match
	!,										%has to clone C1
	%
	% make a clone of C1 as a group
	%
	clone(C1,C1_clone,C1_to_clone_map),						%clone C1
	match_to_link(Match,Links),							%convert matches to links
	replace_var_in_links(C1_to_clone_map,Links,Replaced_links),			%use Clone's var names in links
	make_into_group(C1_clone,C1_clone_group),					%make C1_clone a group
	%
	% the to_fuse structure
	%
	% NOTE:	if C1 is cloned, we don't have to worry about
	%	adding the original C1 as it will be handled
	%	by a previous match
	%
	To_add=C1_clone_group,								%C1_clone will be added
	get_all_gens(To_add,More_ug,More_eg),						%find gens to add
	%
	% make replacement map from Clone to C2
	%
	swap_matches(C1_to_clone_map,Clone_to_c1_map),
	merge_replacement(Clone_to_c1_map,Match,Clone_to_c2_map),
	replace_var_in_cif(Clone_to_c2_map,More_ug,To_add_ug),				%use C2's var names in U-gen
	replace_var_in_cif(Clone_to_c2_map,More_eg,To_add_eg),				%use C2's var names in E-gen
	replace_var_in_match_with_info(C1_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,Replaced_links,[],To_add_ug,To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).

%
% some vars in C2 (as a fused structure) have taken part in a previous match
% have to clone C2 and put it into a to_fuse/5 structure
%
ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(_:Var_in_c2,Match),							%there is a matching pair
	member(_:Var_in_c2,Previous_matches),						%this var in C2 has taken part in a previous match
	!,
	%
	% make a clone of involved groups in C2
	%
	match_to_link(Match,Links),							%convert match to links
	C2_as_fused=fused(_,_,C2_groups),						%find groups in C2
	groups_involved(Links,C2_groups,Involved,_),					%find involved groups in C2
	clone(Involved,C2_involved_clone,C2_to_clone_map),				%clone involved groups in C2
	replace_var_in_links(C2_to_clone_map,Links,Replaced_links),			%use Clone's var names in links
	%
	% find all gens in the new clone
	%
	To_add=C2_involved_clone,
	get_all_gens(To_add,More_ug,More_eg),						%find gens to add
	replace_var_in_cif(C2_to_clone_map,More_ug,To_add_ug),				%use C2's var names in U-gen
	replace_var_in_cif(C2_to_clone_map,More_eg,To_add_eg),				%use C2's var names in U-gen
	replace_var_in_match_with_info(C2_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,Replaced_links,[],To_add_ug,To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).

%
% a "fresh" match, just remember UU-links for later use
%
ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	%
	% make C1 into a group
	%
	Match_with_info=match(Match,_,_,_),
	match_to_link(Match,Links),						%convert match to links
	make_into_group(C1,C1_group),						%make C1 into a group
	%
	% prepare the to_fuse structure
	%
	To_add=C1_group,							%C1 will be added
	get_all_gens(To_add,More_ug,More_eg),					%find gens to add
	replace_var_in_cif(Match,More_ug,To_add_ug),				%use C2's var names
	replace_var_in_cif(Match,More_eg,To_add_eg),				%use C2's var names
	To_fuse=to_fuse(Match_with_info,Links,[],To_add_ug,To_add_eg,To_add),	%the to_fuse structure
	my_union(Match,Previous_matches,New_previous),				%more previous matches
	ifuse_update_fused_from_uu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).



%--------------------------------------------------
%
% ifuse_update_fused_from_ue_matches/6
%
% update fused structure from EU-matches
%
% for every matching instance, create a clone of C1
% and add it into the fused structure
%
%--------------------------------------------------

ifuse_update_fused_from_ue_matches(C1,Fused,Matches,New_fused) :-
	ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,Fused,Matches,[],To_fuse),	%prepare a list of to_fuse structure
	ifuse_update_fused_from_to_fuse(Fused,To_fuse,New_fused).				%execute the to_fuse

%
% ifuse_update_fused_from_ue_matches_prepare_to_fuse/5
%
% prepare to_fuse structures for UE-matches
%
% ifuse_update_fused_from_ue_matches_prepare_to_fuse(+C1,+C2_as_fused,+Matches,+Previous,-To_fuse)
%
% C1		=	CIF1
% C2_as_fused	=	C2 in fused/3
% Matches	=	list of matches in match/4
% Previous	=	previous matches in the form var1:var2
% To_fuse	=	the returned list of to_fuse/5 structures
%
ifuse_update_fused_from_ue_matches_prepare_to_fuse(_,_,[],_,[]).			%end of match


%
% some vars in C1 have taken part in a previous match
% clone C1 and put this clone into a to_fuse/5 structure
%
% NOTE:	we don't have to add C1 as it must be added by the previous match
%
ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(Var_in_c1:_,Match),							%there is a matching pair
	member(Var_in_c1:_,Previous_matches),						%the var in C1 has taken part in a previous match
	!,										%has to clone C1
	%
	% make a clone of C1 as a group, & get its gens
	%
	clone(C1,C1_clone,C1_to_clone_map),						%clone C1
	match_to_link(Match,Links),							%convert matches to links
	replace_var_in_links(C1_to_clone_map,Links,Replaced_links),			%use Clone's var names in links
	make_into_group(C1_clone,C1_clone_group),					%make C1_clone a group
	get_all_gens(C1_clone_group,C1_clone_ug,C1_clone_eg),				%get gens from C1_clone
	%
	% find the gens to add, using C2's var names
	% more U-gens may come from C1 but all gens in C1_clone go into E-gens
	%
	swap_matches(C1_to_clone_map,Clone_to_c1_map),					%get map from C1_clone to C1
	merge_replacement(Clone_to_c1_map,Match,Clone_to_c2_map),			%merge maps to get map from Clone to C2
	replace_var_in_cif(Clone_to_c2_map,C1_clone_ug,To_add_clone_ug),		%use C2's var names in U-gen
	replace_var_in_cif(Clone_to_c2_map,C1_clone_eg,To_add_clone_eg),		%use C2's var names in E-gen
	append_cif(To_add_clone_ug,To_add_clone_eg,To_add_eg),				%U-gen & E-gen of C1_clone go to E-gen
	%
	% create to_fuse/5 w/ UE-links
	%
	To_add=C1_clone_group,								%we only have to add C1's clone
	replace_var_in_match_with_info(C1_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,[],To_add_eg,To_add),		%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).

%
% some vars in C2 have taken part in a previous match
% clone C2 and put it into a to_fuse/5 structure for later processing
%
% NOTE:	similarly, we don't have to add C1 as it must be added by the previous match
%
ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(_:Var_in_c2,Match),						%there is a matching pair
	member(_:Var_in_c2,Previous_matches),					%this var in C2 has taken part in a previous match
	!,
	%
	% make a clone of involved groups in C2
	%
	match_to_link(Match,Links),						%convert match to links
	C2_as_fused=fused(_,_,C2_groups),					%find groups in C2
	groups_involved(Links,C2_groups,Involved,_),				%find involved groups in C2
	clone(Involved,C2_involved_clone,C2_to_clone_map),			%clone involved groups in C2
	replace_var_in_links(C2_to_clone_map,Links,Replaced_links),		%use Clone's var names in links
	%
	% find all gens in C2's clone
	%
	To_add=C2_involved_clone,
	get_all_gens(To_add,C2_clone_ug,C2_clone_eg),				%find gens to add
	append_cif(C2_clone_ug,C2_clone_eg,To_add_eg),
	replace_var_in_match_with_info(C2_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,[],To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),				%more previous matches
	ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).


%
% a fresh match
% have to add a clone of C1
% NOTE:	we are NOT adding C1 as it will be handle by the outter predicate
%
ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	%
	% make a clone of C1 as a group, & get its gens
	%
	Match_with_info=match(Match,_,_,_),
	clone(C1,C1_clone,C1_to_clone_map),						%clone C1
	match_to_link(Match,Links),							%convert matches to links
	replace_var_in_links(C1_to_clone_map,Links,Replaced_links),			%use Clone's var names in links
	make_into_group(C1_clone,C1_clone_group),					%make C1_clone a group
	get_all_gens(C1_clone_group,C1_clone_ug,C1_clone_eg),				%get gens from C1_clone
	%
	% find the gens to add, using C2's var names
	% more U-gens may come from C1 but all gens in C1_clone go into E-gens
	%
	swap_matches(C1_to_clone_map,Clone_to_c1_map),					%get map from C1_clone to C1
	merge_replacement(Clone_to_c1_map,Match,Clone_to_c2_map),			%merge maps to get map from Clone to C2
	replace_var_in_cif(Clone_to_c2_map,C1_clone_ug,To_add_clone_ug),		%use C2's var names in U-gen
	replace_var_in_cif(Clone_to_c2_map,C1_clone_eg,To_add_clone_eg),		%use C2's var names in E-gen
	%
	% create to_fuse/4 w/ UE-links
	%
	To_add_ug=[],									%no U-gen to add
	append_cif(To_add_clone_ug,To_add_clone_eg,To_add_eg),				%U-gen & E-gen of C1_clone go to E-gen
	To_add=[C1_clone_group],							%we have to add C1 & its clone as groups
	replace_var_in_match_with_info(C1_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,To_add_ug,To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_ue_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).




%-------------------------------------
%
% ifuse_update_fused_from_eu_matches/6
%
% prepare to_fuse/5 from EU-matches
%
%-------------------------------------

ifuse_update_fused_from_eu_matches(C1,Fused,Matches,New_fused) :-
	ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,Fused,Matches,[],To_fuse),	%prepare a list of to_fuse structure
	ifuse_update_fused_from_to_fuse(Fused,To_fuse,New_fused).				%execute the to_fuse

%
% ifuse_update_fused_from_eu_matches_prepare_to_fuse/5
%
% prepare to_fuse/4 structures from EU-matches
%
% ifuse_update_fused_from_eu_matches_prepare_to_fuse(+C1,+C2_as_fused,+Matches,+Previous,-To_fuse)
%
% C1		=	CIF1
% C2_as_fused	=	C2 in fused/3
% Matches	=	list of matches in match/4
% Previous	=	previous matches in the form var1:var2
% To_fuse	=	the returned list of to_fuse/5 structures
%
ifuse_update_fused_from_eu_matches_prepare_to_fuse(_,_,[],_,[]).

%
% some vars in C1 have taken part in a previous match
% clone C1 and put it into a to_fuse/5
%
% NOTE:	we don't have to add C1 as it must be added by the previous match
%
ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(Var_in_c1:_,Match),						%there is a matching pair
	member(Var_in_c1:_,Previous_matches),					%the var in C1 has taken part in a previous match
	!,									%has to clone C1
	%
	% make a clone of C1 as a group
	%
	clone(C1,C1_clone,C1_to_clone_map),					%clone C1
	match_to_link(Match,Links),						%convert matches to links
	replace_var_in_links(C1_to_clone_map,Links,Replaced_links),		%use Clone's var names in links
	make_into_group(C1_clone,C1_clone_group),				%make C1_clone a group
	%
	% the to_fuse structure
	%
	% make replacement map from Clone to C2
	%
	To_add=C1_clone_group,							%C1_clone will be added
	get_all_gens(To_add,C1_clone_ug,C1_clone_eg),				%find gens to add
	swap_matches(C1_to_clone_map,Clone_to_c1_map),				%get Clone_to_c1 map from C1_to_clone map
	merge_replacement(Clone_to_c1_map,Match,Clone_to_c2_map),		%merge Clone_to_c1 w/ Match to give Clone_to_c2 map
	replace_var_in_cif(Clone_to_c2_map,C1_clone_ug,Clone_ug),		%use C2's var names in U-gen
	replace_var_in_cif(Clone_to_c2_map,C1_clone_eg,Clone_eg),		%use C2's var names in E-gen
	append_cif(Clone_ug,Clone_eg,To_add_eg),				%all gens go into E-gen
	replace_var_in_match_with_info(C1_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,[],To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),				%more previous matches
	ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).

%
% some vars in C2 have taken part in a previous match
% clone C2 and put it into a to_fuse/5
%
% NOTE:	we don't have to add C1 as it must be added by the previous match
%
ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	Match_with_info=match(Match,_,_,_),
	member(_:Var_in_c2,Match),							%there is a matching pair
	member(_:Var_in_c2,Previous_matches),						%this var in C2 has taken part in a previous match
	!,
	%
	% make a clone of involved groups in C2
	%
	match_to_link(Match,Links),							%convert match to links
	C2_as_fused=fused(_,_,C2_groups),						%find groups in C2
	groups_involved(Links,C2_groups,Involved,_),					%find involved groups in C2
	clone(Involved,C2_involved_clone,C2_to_clone_map),				%clone involved groups in C2
	replace_var_in_links(C2_to_clone_map,Links,Replaced_links),			%use Clone's var names in links
	%
	% find all gens in C2's clone
	%
	To_add=C2_involved_clone,
	get_all_gens(To_add,C2_clone_ug,C2_clone_eg),					%find gens to add
	append_cif(C2_clone_ug,C2_clone_eg,To_add_eg),
	replace_var_in_match_with_info(C2_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,[],To_add_eg,To_add),		%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).


%
% a fresh match
% add a clone of C2 and put it into a to_fuse/5
%
% NOTE:	we do NOT have to add C1 here as it will be handle by the outter predicate
%
ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,[Match_with_info|Ms],Previous_matches,[To_fuse|Ts]) :-
	%
	% make a clone of C2 as a group, & get its gens
	%
	Match_with_info=match(Match,_,_,_),
	match_to_link(Match,Links),							%convert matches to links
	C2_as_fused=fused(_,_,C2_groups),						%find groups in C2
	groups_involved(Links,C2_groups,Involved,_),					%find involved groups in C2
	clone(Involved,Involved_clone,C2_to_clone_map),					%clone involved groups in C2
	get_all_gens(Involved_clone,C2_clone_ug,C2_clone_eg),				%get gens of clone
	replace_var_in_links(C2_to_clone_map,Links,Replaced_links),			%use Clone's var names in links, C2 remains free
	%
	% create to_fuse/4 w/ UE-links
	%
	To_add_ug=[],
	append_cif(C2_clone_ug,C2_clone_eg,To_add_eg),					%*** U-gen & E-gen of C2 clone go to E-gen!
	To_add=[Involved_clone],							%have to add C1 & C2's clone
	replace_var_in_match_with_info(C2_to_clone_map,Match_with_info,Replaced_match),	%use Clone's var names in the match
	To_fuse=to_fuse(Replaced_match,[],Replaced_links,To_add_ug,To_add_eg,To_add),	%the to_fuse structure
	%
	% work on remaining matching instances
	%
	my_union(Match,Previous_matches,New_previous),					%more previous matches
	ifuse_update_fused_from_eu_matches_prepare_to_fuse(C1,C2_as_fused,Ms,New_previous,Ts).

