% less expensive: ignore some candidate braches; settle with shared points -- higher accurracy.
% This version will ignore the candidates which has smaller coverage 
% ** only changed at combine_and_competing


/* no longer record Description Length and EITI
It turns out the extraction of EITI is inevitable for CurrentNode, then it actually save time to extract again when 

EIs is not only for scoring, but also for later grouping. 
DL is necessarily when sorting within each same EI
*/

% Main difference from flux record, is that the flux is passed top-down: (1)expandNode
% this is to match the flux record in coverageSorted_fluxRecord
% this is based on 'hypothesisSelection_noEIs_combineCheck.pl', but the candidateSelection is different, where grouping based on EI coverage is done first. 

/*
The scoreing is -(coverage-descriptionLength) -- so the smaller the better a score. This leads to: when same score, teh samller the descriptionLength, the better is a candidate;
Need to change the combine_and_competing, not to start the last one, since the better one is not at the top of list. 
*/




% apart from checking combinable when combining two candidates; you also need to lose the constraint that not always the best one.

% call hypothesisSelection(startNode,FinalHypothesis)
% output is a candidate hypothesis which include the current node. This hypothesis is accompanied by its properties: DL-EITIs-H. H = sets of ClaID with their coverage. 
% why EITIs, rather than EIs -- that will make the scoring even easier? -- But when you calculate the intersection with current node, EITI will make it easy. -- that is why EIs is not included, because it will be changed after computing the intersection.

hypothesisSelection(CurrentNode-CurrendNodeEITIs,BestCandidates):-
%write('------------------------Another round: CurrentNode is '),portray_clause(CurrentNode-CurrendNodeEITIs),nl,
	expandNode(CurrentNode-CurrendNodeEITIs,ChildNodes),
	extractEndNode(ChildNodes,EndNodeEITIs0,NonEndChildNodes),sort(EndNodeEITIs0,EndNodeEITIs), 
	%write('expanded results'),write({NonEndChildNodes,endNode-EndNodeEITIs}),nl,
	maplist(hypothesisSelection,NonEndChildNodes,ReturnedCandidates), % each in ReturnedCandidates is a set of candidates from one branch

	%write('Time to Compete and Combine'),nl,print_list(ReturnedCandidates),nl,
	(EndNodeEITIs0==[]->
		candidateSelection(ReturnedCandidates,CurrentNode-CurrendNodeEITIs,BestCandidates);
		exExtraction(EndNodeEITIs,EndNodeEIs),
		candidateSelection([[0-EndNodeEIs-[(endNode-EndNodeEITIs)-EndNodeEITIs]]|ReturnedCandidates],CurrentNode-CurrendNodeEITIs,BestCandidates)).


expandNode(CurrentNode-CurrendNodeEITIs,ChildNodes):-
	findall(Child-NewFlux,(connect(CurrentNode,Child,Flux0),ord_intersection(Flux0,CurrendNodeEITIs,NewFlux),NewFlux\==[]),ChildNodes).

extractEndNode([],[],[]).
extractEndNode([ChildNode|ChildNodes],EndNodeCoverge,NonEndNode):-
	extractEndNode(ChildNodes,PreEndNodeCoverge,PreNonEndNode),
	(ChildNode=endNode-EI-TI-EITIs ->
		EndNodeCoverge=[EI-TI|PreEndNodeCoverge], NonEndNode=PreNonEndNode;	
		EndNodeCoverge=PreEndNodeCoverge, NonEndNode=[ChildNode|PreNonEndNode]
	).
	

% The returned candidate include the current node, while the scoring doesn't: when combining, don't want to include the current node repeatedly.
% score, then sort, then combine -- start from the highest score
% group is done before scoring? there is scoring and sorting within each group 
% then another scoring and sorting for those chosen from the group.

t(X).

% each ReturnCanidate0 is a set of candidate from one branch. 
% ReturnedCandidates= each is Score-DL-EIs-Candidate

% when detected a pair a related, removing any what if that one has other related?

sepIsolatedMet([],WholeSet,[],[]).
sepIsolatedMet([OneEICluster-Explanations|PostSet],PreSet,NewIsolatedEIExplanations,NewToBeCombinedEIsExplanations):-
	sepIsolatedMet(PostSet,[OneEICluster-Explanations|PreSet],IsolatedEIExplanations,ToBeCombinedEIsExplanations),
	((checkIntersection(OneEICluster,PreSet);checkIntersection(OneEICluster,PostSet))->
		NewIsolatedEIExplanations=IsolatedEIExplanations,NewToBeCombinedEIsExplanations=[OneEICluster-Explanations|ToBeCombinedEIsExplanations];		
		NewIsolatedEIExplanations=[OneEICluster-Explanations|IsolatedEIExplanations],NewToBeCombinedEIsExplanations=ToBeCombinedEIsExplanations
	).

	
checkIntersection(EIs,[OneEICluster-Explanations|Set]):-
	ord_intersect(EIs,OneEICluster),!.
checkIntersection(EIs,[OneEICluster-Explanations|Set]):-
	checkIntersection(EIs,Set).


candidateSelection(ScoredCandidates0,startNode-CurrentCoverage,[IsolatedEIExplanations,NewCandidates]):-
	!,
	flatten(ScoredCandidates0,ScoredCandidates),
	group_basedOn_EI(ScoredCandidates,EIGroupedCandidates),%write('*** Candidates are group as here'),nl,print_list(GroupedCandidates),nl,
	maplist(group_basedOn_score_withinEachEIGroup,EIGroupedCandidates,EIs_EachScoreGrouped_Candidates),
	sepIsolatedMet(EIs_EachScoreGrouped_Candidates,[],IsolatedEIExplanations,ToBeCombinedEIsExplanations0),
	
	sortByEI(ToBeCombinedEIsExplanations0,ToBeCombinedEIsExplanations),
	print_list(ToBeCombinedEIsExplanations),
	[IsolatedEIExplanations,NewCandidates]=[IsolatedEIExplanations,[]].
	%combine_and_competing(ToBeCombinedEIsExplanations,[[]],NewCandidates0),
	%maplist(addCurrentNode_and_addInfo(CurrentNode),NewCandidates0,NewCandidates).


sortByEI(EIs_EachScoreGrouped_Candidates,EIs_EachScoreGrouped_Candidates2):-
	maplist(scoreByEINum,EIs_EachScoreGrouped_Candidates,ScoredEIs_EachScoreGrouped_Candidates1),
	sort(ScoredEIs_EachScoreGrouped_Candidates1,ScoredEIs_EachScoreGrouped_Candidates2),
	reverse(ScoredEIs_EachScoreGrouped_Candidates2,ScoredEIs_EachScoreGrouped_Candidates3),
	maplist(scoreByEINum,EIs_EachScoreGrouped_Candidates2,ScoredEIs_EachScoreGrouped_Candidates3).


candidateSelection(ScoredCandidates0,CurrentNode-CurrentCoverage,NewCandidates):-
	flatten(ScoredCandidates0,ScoredCandidates),
	%maplist(scoreCandidateBranches,ReturnedCandidates,ScoredCandidates),
	%ScoredCandidates0=ScoredCandidates, % whether to filter out those negative score -- no compression branch
	%selectlist(nonEmptyCandidate,ScoredCandidates0,ScoredCandidates),	% filter out those empty EI list -- when returning back, intersection maybe empty

	group_basedOn_EI(ScoredCandidates,EIGroupedCandidates),%write('*** Candidates are group as here'),nl,print_list(GroupedCandidates),nl,
	maplist(group_basedOn_score_withinEachEIGroup,EIGroupedCandidates,EIs_EachScoreGrouped_Candidates),
	sortByEI(EIs_EachScoreGrouped_Candidates,EINumSorted_EIs_EachScoreGrouped_Candidates),
	combine_and_competing(EINumSorted_EIs_EachScoreGrouped_Candidates,[[]],NewCandidates0),
	maplist(addCurrentNode_and_addInfo(CurrentNode),NewCandidates0,NewCandidates).


sortByEI(EIs_EachScoreGrouped_Candidates,EIs_EachScoreGrouped_Candidates2):-
	maplist(scoreByEINum,EIs_EachScoreGrouped_Candidates,ScoredEIs_EachScoreGrouped_Candidates1),
	sort(ScoredEIs_EachScoreGrouped_Candidates1,ScoredEIs_EachScoreGrouped_Candidates2),
	reverse(ScoredEIs_EachScoreGrouped_Candidates2,ScoredEIs_EachScoreGrouped_Candidates3),
	maplist(scoreByEINum,EIs_EachScoreGrouped_Candidates2,ScoredEIs_EachScoreGrouped_Candidates3).


scoreByEINum(EIs-GroupedCandidate,EINum-EIs-GroupedCandidate):-
	length(EIs,EINum).




% This includes scoring. Due to the extra info like Description Length, it is not separated as a function which only return score.
addCurrentNode_and_addInfo(CurrentNode,Candidate,DescriptionLength-EIs-[CurrentNode-EITIs|Candidate]):-
	extractEITI(Candidate,EITIs),
	exExtraction(EITIs,EIs), 	
	length(EIs,EINum),	
	descriptionLength([CurrentNode-EITIs|Candidate],DescriptionLength).
	%Score is CandidateDescriptionLength-10*EINum. % we don't need to score, since they are grouped by EI, then followed by their description length
	



%nonNegativeScoreBranch(Score-DL-EIs-EITIs-CandidateBranch):- Score>=0.
%nonEmptyCombinedCandidate(DL-EIRemovedNum-CombinedCandidate):- CombinedCandidate\== []. %?? why do I need this at that time? I guess it only happen when the combined are about endNode
%nonEmptyCandidate(Score-DL-EIs-CandidateBranch):-EIs\==[]. % can't remember why 



% Input is [1-1,1-2,2-1,2-2,2-3], then the output is [1,2] 
exExtraction([],[]).
exExtraction([EI-TI|Record],EIs):- 
	exExtraction(Record,PreEIs),
	(PreEIs=[EI|Rest] ->
		EIs=PreEIs;
		EIs=[EI|PreEIs]
	).

extractEITI(Candidate,EITIs):-maplist(getEITIs,Candidate,EITIs0),ord_union(EITIs0,EITIs).

getEITIs(ClaID-EITIs,EITIs).

exExtractionFromCandidate(Candidate,EIs):-
	 extractEITI(Candidate,EITIs),
	 exExtraction(EITIs,EIs).



% Before scoring, it is CandidateDescriptionLength-EITIs-Candidate; 
% After scoring, it is Score-DL-EITIs-Candidate
/*
can the score also give EI, so that later, 
In terms of complexity, it will better to group first, then sorting, since, the O(Nlog(N)) is smaller. 
Since you'll need to compare their maximum later, so perhaps it is easier to 
*/

% Input is a list of Score-CandidateDescriptionLength-NewEIs-NewEITIs-EITIupdated_Candidate; Output is a list of SameEIs-[Candidate1,Candidate2]


group_basedOn_EI([],[]).
group_basedOn_EI([DL-EIs-Candidate|Rest],GroupResult):-
	group_basedOn_EI(Rest,PreGroupResult),
	(append(Pre,[EIs-EIsCandidates|Post],PreGroupResult)->
		 append(Pre,[EIs-[DL-Candidate|EIsCandidates]|Post],GroupResult);
		 GroupResult=[EIs-[DL-Candidate]|PreGroupResult]
	).


group_basedOn_score_withinEachEIGroup(EIs-EIsGroup,EIs-SortedScoreGrouped):-
	group_basedOn_score(EIsGroup,ScoreGrouped),
	sort(ScoreGrouped,SortedScoreGrouped).
	%maplist(removeScore,SortedScoreGrouped0,SortedScoreGrouped).

%removeScore(Score-Candidates,Candidates).

% The scores here are essentially Description Length
group_basedOn_score([],[]).
group_basedOn_score([Score-Candidate|Rest],GroupResult):-
	group_basedOn_score(Rest,PreGroupResult),
	(append(Pre,[Score-SameScoreCandidates|Post],PreGroupResult)->
		 append(Pre,[Score-[Candidate|SameScoreCandidates]|Post],GroupResult);
		 GroupResult=[Score-[Candidate]|PreGroupResult]
	).


% initiate the sofar with 
% query with combine_and_competing(GroupedCandidates,0-[]-[],DL-EITIs-Candidate)
% still too too greedy -- those has lower score at that time, may not to be worse later -- but that is the problem by DAG.
% CandidatesSofar is a set of candidate [ClaID1-EITIs1,ClaID2-EITIs2,...]




combine_and_competing([],Candidates,Candidates).
/*combine_and_competing([EIs-EIs_EachScoreGrouped_Candidates|GroupedCandidates],CandidatesSofar,NewCandidates):- % ** only changed
	CandidatesSofar=[CandidateSofar|_],
	exExtractionFromCandidate(CandidateSofar,EIsSofar),
	ord_subset(EIs,EIsSofar),!, write('This branch removed'),nl,
	combine_and_competing(GroupedCandidates,CandidatesSofar,NewCandidates). % simply ignore that branch if its EIs is already covered by 
*/
combine_and_competing([EIs-EIs_EachScoreGrouped_Candidates|GroupedCandidates],CandidatesSofar,NewCandidates):-
	
	maplist(oneCandidateSofar_multiply_ASetOfCandidates(EIs-EIs_EachScoreGrouped_Candidates),CandidatesSofar,PossibleCombinations0),

	flatten(PossibleCombinations0,PossibleCombinations), % each of ReturnedCandidates0 is still a list

	%write('*** Possible Combinations'),
	sort(PossibleCombinations,SortedPossibleCombinations),%print_list(PossibleCombinations),nl,write('Non redundant version'),print_list(SortedPossibleCombinations),nl,
/*	length(PossibleCombinations,L1),length(SortedPossibleCombinations,L2),
	(L1==L2 ->
		Foo=0;
		write('Redundant Here'),nl
	),*/
	
	% no need to pass all of them to the next iteration -- but choose the best set
	group_basedOn_score(SortedPossibleCombinations,ScoreGrouped),ScoreGrouped=SortedScoreGrouped, %sort(ScoreGrouped,SortedScoreGrouped),
	member(MinDL-CandidatesUpdated,SortedScoreGrouped), %write('what passed to next iteration are'),write(MinDL),print_list(CandidatesUpdated),nl,
	combine_and_competing(GroupedCandidates,CandidatesUpdated,NewCandidates).


oneCandidateSofar_multiply_ASetOfCandidates(EIs-EIs_EachScoreGrouped_Candidates,CandidateSofar,[CandidateSofarDL-CandidateSofar]):-
	h(1),
	exExtractionFromCandidate(CandidateSofar,EIsSofar),
	ord_subset(EIs,EIsSofar),!,h(2),
	descriptionLength(CandidateSofar,CandidateSofarDL).

oneCandidateSofar_multiply_ASetOfCandidates(EIs-EIs_EachScoreGrouped_Candidates,CandidateSofar,PossibleCombinations):-
	exExtractionFromCandidate(CandidateSofar,EIsSofar),identifyComputingPart(EIs,EIsSofar,CompetingEIs,SubsetSign),	%nl,write('oneCandidateSofar_multiply_ASetOfCandidates  '),write({CompetingEIs,SubsetSign,EIsSofar,EIs}),nl,
	member(Score-BestCandidates,EIs_EachScoreGrouped_Candidates),% get the top subset from a list


/*
	remove_duplicates(CandidatesSofar,CheckRedundantCandidatesSofar),
	(CandidatesSofar==CheckRedundantCandidatesSofar -> Foo=0;write('CandidateSofar redundant')),
		remove_duplicates(BestCandidates,CheckRedundantBestCandidates),
	(BestCandidates==CheckRedundantBestCandidates -> Foo=0;write('addedCandidates redundant')),
*/

	maplist(combine_and_competing_OneCandidate({SubsetSign-CompetingEIs,CandidateSofar}),BestCandidates,PossibleCombinations0),
	(SubsetSign=totalSubset ->
		descriptionLength(CandidateSofar,CandidateSofarDL),
		PossibleCombinations=[[CandidateSofarDL-CandidateSofar]|PossibleCombinations0]; % this is to put itself back 
		PossibleCombinations=PossibleCombinations0
	).
	
		

% this alone will be a set -- for the competing EI, whose to be included?
combine_and_competing_OneCandidate({SubsetSign-[],CandidateSofar},BestCandidate,[DescriptionLength-NewCandidate]):- 
	% notice that the returned is a set of new candidates--in this case, there is only one candidate in that set.
	!,combineTwoCandidate(BestCandidate,CandidateSofar,NewCandidate),
	descriptionLength(NewCandidate,DescriptionLength).

combine_and_competing_OneCandidate({totalSubset-CompetingEIs,CandidateSofar},BestCandidate,ScoredPossibleCombinations):-
		powersets(CompetingEIs,[[]|Possibles]), % take out the one that may represent itself--it is to generate the pair 
		maplist(getCompensatedPair(CompetingEIs),Possibles,CompensatedPairs),
		maplist(combineTwoCompetingCandidates({BestCandidate,CandidateSofar}),CompensatedPairs,ScoredPossibleCombinations0),
		selectlist(nonUnCombinedCandidate,ScoredPossibleCombinations0,ScoredPossibleCombinations).

combine_and_competing_OneCandidate({nonSubset-CompetingEIs,CandidateSofar},BestCandidate,ScoredPossibleCombinations):-
		powersets(CompetingEIs,Possibles),
		maplist(getCompensatedPair(CompetingEIs),Possibles,CompensatedPairs),
		maplist(combineTwoCompetingCandidates({BestCandidate,CandidateSofar}),CompensatedPairs,ScoredPossibleCombinations0),
		selectlist(nonUnCombinedCandidate,ScoredPossibleCombinations0,ScoredPossibleCombinations).

nonUnCombinedCandidate(CombinedCandidate):- CombinedCandidate\==unCombinable.

		/*
		sort(ScoredPossibleCombinations,SortedScoredPossibleCombinations), write('Here are the possible Combinations'),print_list(SortedScoredPossibleCombinations),nl,nl,
		getBestSet_removeScore(SortedScoredPossibleCombinations,NewCandidates).
		% member(DLUpdated-CandidateUpdated,SortedScoredPossibleCombinations)  % choose the head:the one with lowest DL. 
		*/
	
  


      

% Different from previous, here the input is EIs, rather than EITIs
identifyComputingPart(EIs,PreEIs,CompetingEIs,SubsetSign):-
		ord_intersection(EIs,PreEIs,CompetingEIs),
		(EIs==CompetingEIs ->
			SubsetSign=totalSubset;
			SubsetSign=nonSubset
		).

% please notice the order -- rather than {Set,CompensatedSet}, this is to make Set=[] generate a pair {TotalSet,[]} -- the second variable represent the EI to be removed/isolated from CandidateSofar
getCompensatedPair(TotalSet,Set,{CompensatedSet,Set}):-
	ord_subtract(TotalSet,Set,CompensatedSet).

% another function that take in such a pair -- produce a candidate -- re-score(remove-duplicate(be careful -- they may just have different EI_Coverage)->description length -- their EI coverage remains the same -- all is comparisons about description length )	
combineTwoCompetingCandidates({Candidate1,Candidate2},{EIs1,EIs2},Returned):-
	isolation(Candidate1,EIs1,RemainCandidate1), %OverlapEITIs-CandidateOverlapPart),
	isolation(Candidate2,EIs2,RemainCandidate2),	
	(combineTwoCandidate(RemainCandidate1,RemainCandidate2,CombinedCandidate)->
		descriptionLength(CombinedCandidate,NewDL),
		Returned=NewDL-CombinedCandidate;
		Returned=unCombinable
	).
	%length(EIs2,NumRemovedEIs). -- no longer record NumRemovedEIs -- that just to make preference to those keep the same as previous.
	


% *** when you remove certain bits, the EITI coverage is changed! -- the EITI is not simply the isolation you have now


combineTwoCandidate([],PreCandidate,PreCandidate).
combineTwoCandidate([ClaID-ClaEITIs|Candidate],PreCandidate,NewCandidateUpdated):-
	combineTwoCandidate(Candidate,PreCandidate,NewCandidate),
	%write('---Checking'),
	checkCombinable(ClaID,PreCandidate),%write('good, pass checking'),nl,
	(append(PreClas,[ClaID-ClaPreEITIs|AfterClas],NewCandidate) ->
		ord_union(ClaEITIs,ClaPreEITIs,ClaNewEITIs),
		append(PreClas,[ClaID-ClaNewEITIs|AfterClas],NewCandidateUpdated);
		NewCandidateUpdated=[ClaID-ClaEITIs|NewCandidate]		
	).

%/* this is for syngenta project
checkCombinable(endNode-EndNodeEITIs,PreCandidate):-!. %endNode is always combinable
checkCombinable(ClaID,PreCandidate):-
	ClaID=[rs-{ReactionID,LimitingType,State,Time}],
	(member([rs-{ReactionID,LimitingType2,State2,Time}]-ClaEITIs,PreCandidate)-> 
		State2==State, LimitingType2==LimitingType;		
		Foo=0
	).
checkCombinable(ClaID,PreCandidate):-
	ClaID=[met-{MID,Change,Time}],
	(member([met-{MID,Change1,Time}]-ClaEITIs,PreCandidate)-> 
		Change1==Change;		
		Foo=0
	).
%*/

/* This is for grammar example
checkCombinable(endNode-EndNodeEITIs,PreCandidate):-!. %endNode is always combinable
checkCombinable([Predicate-Word],PreCandidate):- !,
	(member([PrePredicate-Word]-ClaEITIs,PreCandidate)-> 
		Predicate == PrePredicate;		
		Foo=0
	).
checkCombinable(RestClaTypes,Candidate). % check redundency. no worry, it is taken care when addign. 
*/


	
	
% number of CompetingEIs is to be removed, so the less it is, the more remain.
% remove the ClaID from Candidate, if it contains CompetingEIs alone *** need to update the corresponding RemainEITIs as well!
isolation(Candidate,CompetingEIs,RemainCandidate_noRedundant):-
	clasSeparation(Candidate,CompetingEIs,RemainEITIs0-RemainCandidate,OverlapEITIs-CandidateOverlapPart),
	maplist(removeAlones(OverlapEITIs),RemainCandidate,RemainCandidate_noRedundant).


% you can make this part more efficient, by doing ord_union at the end, rather than every time do a ord_union
clasSeparation([],CompetingEIs,[]-[],[]-[]).
clasSeparation([ClaID-ClaEITIs|Candidate],CompetingEIs,RemainEITIs-RemainCandidate,OverlapEITIs-CandidateOverlapPart):-
		clasSeparation(Candidate,CompetingEIs,PreRemainEITIs-PreRemainCandidate,PreOverlapEITIs-PreCandidateOverlapPart),
		exExtraction(ClaEITIs,ClaEIs),
		(ord_subset(ClaEIs,CompetingEIs)-> 	% if it has some parts not in CompetingEIs, then it shouldn't be removed
				RemainEITIs-RemainCandidate=PreRemainEITIs-PreRemainCandidate,
				ord_union(ClaEITIs,PreOverlapEITIs,OverlapEITIs),
				CandidateOverlapPart=[ClaID-ClaEITIs|PreCandidateOverlapPart];
				OverlapEITIs-CandidateOverlapPart=PreOverlapEITIs-PreCandidateOverlapPart,
				ord_union(ClaEITIs,PreRemainEITIs,RemainEITIs),
				RemainCandidate=[ClaID-ClaEITIs|PreRemainCandidate]
		).
	
removeAlones(AloneEITIs,ClaID-EITIs,ClaID-EITIsNoAlone):-
	%nl,write({EITIs,AloneEITIs}), write('check whether they are in order'),nl,
	ord_subtract(EITIs,AloneEITIs,EITIsNoAlone). % EITIs doesn't necessarily include everything in the AloneEITIs, but  



% if a subset, then remove that clause -- update the EITI in the rest of the clauses. 
% what if the remaining become uncompressed because -- no worry, it will be removed when new branch come. -- simply check whether the remaining still has coverage -- remove the one with single coverage -- long description: e.g. two computing components -- you can't simply remove that branch, maybe the rest still worth for that -- you are allowing the flexibility to decompose the module. % no worry, you can make the selection at this step more complicated later.


% selectlist(extractCompetingCla(CompetingEIs),) % no, it is better to isolate 
% for each claID, removing those belongs -- for the competing part, it doesn't necessarily always one branch, maybe a combination. 



descriptionLength([],0).
descriptionLength([ClaID-ClaEITIs|Candidate],DescriptionLength):-
	descriptionLength(Candidate,PreDescriptionLength),
	%claInterprete(ClaID,Cla),length(Cla,ClaDescriptionLength), -- don't worry about translate them more than once, since there is no redundant node -- probably there is (due to the DAG)
	
	exExtraction(ClaEITIs,ClaEICoverage), 
	claLength(ClaID,ClaEICoverage,ClaDescriptionLength),
	DescriptionLength is PreDescriptionLength+ClaDescriptionLength.

/*
claLength(endNode-EITIs,0):-!.
claLength(startNode,0):-!.
claLength(ClaID,ClaDescriptionLength):-
	claInterpreter(ClaID,Cla),
	length(Cla,ClaDescriptionLength).
*/
% if you are looking for problem-specific scoring, like the Syngenta data, where GE degree is used to compute the score. 

claLength(startNode,ClaEICoverage,0):-!.
claLength(endNode-EITIs,ClaEICoverage,0):-!.
