Caw.pl

:- dynamic debug/1.
/**
predicates may have different combinations of modes
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,2,0]],50,6,[[a,1]],[[d,1]],[],Program).
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,1,1]],50,7,[[a,1]],[[b,1]],[],Program).
Program = [f,[1,b]],[[f,[a,b],:-,[[=,[b,a]]]]],[[b,1]]
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,1,1]],50,7,[[a,[1,2]]],[[b,[1,2]]],[],Program).
Program = [f,[[1,2],b]],[[f,[a,b],:-,[[=,[b,a]]]]],[[b,[1,2]]]
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,1,1]],50,4,[[a,1],[b,2]],[[c,[1,2]]],[],Program).
Program = interpret(off,[f,[1,2,c]],[[f,[a,b,c],:-,[[append,[a,b,g]],[=,[c,g]]]]],[[c,[1,2]]])
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,1,1]],50,6,[[a,1],[b,2],[c,3]],[[d,[1,2,3]]],[],Program).
Program = [interpret(off,[f,[1,2,3,d]],[[f,[a,b,c,d],:-,[[append,[a,b,e]],[append,[e,c,f]],[=,[d,f]]]]],[[d,[1,2,3]]])]
edit out repeats
test rule,var
better arg finders
caw00(off,f,[[append,2,1],[delete,2,1],[head,1,1],[tail,1,1],[member,1,1]],50,7,[[a,[4,1,2,3]],[b,1]],[[d,[4,2,3]]],[],Program).
[debug]  ?- optimise([[append,[a,b,c]],[append,[c,d,e]]],[a,b,d],[a,b,c,d],[e],P).                           
P = [[append, [a, b, c]], [append, [c, d, e]]] ;
%% choose latest var as output, remove duplicate args in rules x (max 2), reverse optimise input, new rules have old outputs as args v
[debug]  ?- optimise([[append,[a,b,c]],[append,[a,b,c]]],[a,b],[a,b,c],[c],P). 
P = [[append, [a, b, c]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[a,b,c]]],[a,b],[a,b,c],[c],P).
P = [[append, [a, b, c]], [delete, [a, b, c]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[a,b,x]]],[a,b],[a,b,c,x],[c],P).
P = [[append, [a, b, c]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[c,b,d]],[member,[c,d]]],[a,b],[a,b,c,d],[d],P).
P = [[append, [a, b, c]], [delete, [c, b, d]], [member, [c, d]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[c,b,d]],[member,[a,d]]],[a,b],[a,b,c,d],[d],P).
P = [[append, [a, b, c]], [delete, [c, b, d]], [member, [a, d]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[c,b,d]],[member,[a,x]]],[a,b],[a,b,c,d],[d],P).
P = [[append, [a, b, c]], [delete, [c, b, d]]] ;
[debug]  ?- optimise([[append,[a,b,c]],[delete,[c,b,d]],[member,[c,x]]],[a,b],[a,b,c,d],[d],P).
P = [[append, [a, b, c]], [delete, [c, b, d]]] ;
Wantedly fail:
optimise([[append,[a,e,c]]],[a],[a,e,c],[c],P).
optimise([[append,[a,b,c]],[append,[c,d,e]]],[a,d],[a,b,c,d],[e],P).
optimise([[append,[a,b,c]],[append,[c,d,e]]],[a,b],[a,b,c,d],[e],P).
optimise([[delete,[a,e,c]],[append,[a,a,e]]],[a,e],[a,e,c],[c],P).
P = [[delete, [a, e, c]], [append, [a, a, e]]] .
optimise([[append,[a,a,e]],[delete,[a,e,c]]],[a,e],[a,e,c],[c],P).
P = [[append, [a, a, e]], [delete, [a, e, c]]] .
optimise([[append,[a,e,c]]],[a,e,c],[a,e,c],[c],P).
P = [[append, [a, e, c]]] .
findrulesflowingtopv1([[append,[a,e,c]],[member,[a,e]]],[a],[a,e,c],[c],[],R,F).
R = [[append, [a, e, c]], [member, [a, e]]]
check optimise works with member ef v
member ef and member in inputvars2 (cde) v
optimise - aeg (remove e), v
does optimise work with multiple rules with same output v
delete returning progs in optimise v
cut rule -
aea cant point to itself in optimise - needs iterative deepening
aec where e not in iv1 or another pred, try first or second in prog v
don't pass rule to lower predicates v
don't choose outputs from non new var v
don't run repeat preds
make predicate, clause writer
member predicates returning no output
**/
caw00(Debug,PredicateName,Rules,MaxLength,TotalVars,InputVarList,OutputVarList,Program1,Program2) :-
retractall(debug(_)),
    assertz(debug(Debug)),
retractall(totalvars(_)),
    assertz(totalvars(TotalVars)),
caw0(PredicateName,Rules,MaxLength,InputVarList,OutputVarList,Program1,Program2).
caw0(PredicateName,Rules,MaxLength,InputVarList,OutputVarList,Program1,Program2) :-
varnames(InputVarList,[],InputVars,[],InputValues),
varnames(OutputVarList,[],OutputVars,[],_OutputValues),
retractall(outputvars(_)),
    assertz(outputvars(OutputVars)),
append(InputVars,OutputVars,Vars11),
%%Vars11=InputVars,
%%Vars12=InputVars,
append(InputValues,OutputVars,Vars2),
%%append(InputValues,OutputValues,Values),
Query=[PredicateName,Vars2],
caw1(Query,PredicateName,Rules,MaxLength,Vars11,InputVars,InputVars,_,OutputVarList,OutputVars,Program1,Program2).
caw1(_,_,_,0,_,_,_,_,_,_,_) :- fail, !.
caw1(Query,PredicateName,_,_,_VarList,InputVars1,InputVars2,_,OutputVarList,OutputVars,Program1,Program2) :-
addrules0(InputVars2,OutputVars,OutputVars,[],Program3),
%%writeln([addrules(InputVars2,OutputVars,OutputVars,[],PenultimateVars,[],Program3)]),	
%%optimise(Program1,InputVars1,InputVars2,PenultimateVars,Program4), %% IV2->3
%%writeln([optimise(Program1,InputVars1,InputVars2,PenultimateVars,Program4)]),
append(Program1,Program3,Program5),
append(InputVars1,OutputVars,Vars2),
Program2=[
        [PredicateName,Vars2,(:-),
                Program5
        ]
        ],debug(Debug),
        %%writeln([interpret(Debug,Query,Program2,OutputVarList)]),
interpret(Debug,Query,Program2,OutputVarList).
caw1(Query,PredicateName,Rules,MaxLength,VarList,InputVars1,InputVars2,InputVars3,OutputVarList,OutputVars,Program1,Program4) :-
%%writeln([caw(Query,PredicateName,Rules,MaxLength,VarList,InputVars1,InputVars2,OutputVarList,OutputVars,Program1,Program4)]),
MaxLength2 is MaxLength - 1,
%%writeln(["ml",MaxLength2]),
reverse(InputVars2,InputVars5),
member([RuleName,NumInputs,NumOutputs],Rules),
%%writeln([member([RuleName,NumInputs,NumOutputs],Rules)]),
%%writeln([rule(RuleName,NumInputs,NumOutputs,VarList,VarList2,Rule)]),
rule(RuleName,NumInputs,NumOutputs,InputVars5,InputVars4,VarList,VarList2,Rule),
%%writeln([inputVars1,InputVars1]),
%%	writeln([rule(RuleName,NumInputs,NumOutputs,InputVars5,InputVars4,VarList,VarList2,Rule)]),
append(Program1,[Rule],Program3),
%%writeln([inputVars3,InputVars3]),
%%InputVars2=InputVars3,
%%writeln([program4,Program4]),
caw(Query,PredicateName,Rules,MaxLength2,VarList2,InputVars1,InputVars4,InputVars3,OutputVarList,OutputVars,Program3,Program4).
caw(_,_,_,0,_,_,_,_,_,_,_) :- fail, !.
caw(Query,PredicateName,_,_,_VarList,InputVars1,InputVars2,_,OutputVarList,OutputVars,Program1,Program2) :-
addrules(InputVars2,OutputVars,OutputVars,[],_PenultimateVars,[],Program3),
%%writeln([addrules(InputVars2,OutputVars,OutputVars,[],PenultimateVars,[],Program3)]),	
%%optimise(Program1,InputVars1,InputVars2,PenultimateVars,Program4), %% IV2->3
%%writeln([optimise(Program1,InputVars1,InputVars2,PenultimateVars,Program4)]),
append(Program1,Program3,Program5),
append(InputVars1,OutputVars,Vars2),
Program2=[
        [PredicateName,Vars2,(:-),
                Program5
        ]
        ],debug(Debug),
%%***
%% () choose iv1 as args during caw, () eliminate e problem, could move forward in optimiser but don't need it v
%% should have a leading edge of 1 immediately previous (new output) as an arg in latest rule v, go backwards to choose latest possible args x, 3 x rules can have same as previous rule's output as an output x: at a time
%% chunks will solve having at least 1 rule that connects to last output
%% can optimise number of inputs
%% test member, = in caw
writeln([interpret(Debug,Query,Program2,OutputVarList)]),
interpret(Debug,Query,Program2,OutputVarList).
caw(Query,PredicateName,Rules,MaxLength,VarList,InputVars1,InputVars2,InputVars3,OutputVarList,OutputVars,Program1,Program4) :-
%%writeln([caw(Query,PredicateName,Rules,MaxLength,VarList,InputVars1,InputVars2,OutputVarList,OutputVars,Program1,Program4)]),
MaxLength2 is MaxLength - 1,
%%writeln(["ml",MaxLength2]),
member([RuleName,NumInputs,NumOutputs],Rules),
%%writeln([member([RuleName,NumInputs,NumOutputs],Rules)]),
%%writeln([rule(RuleName,NumInputs,NumOutputs,VarList,VarList2,Rule)]),
rule(RuleName,NumInputs,NumOutputs,InputVars2,InputVars4,VarList,VarList2,Rule),
%%writeln([inputVars1,InputVars1]),
%%	writeln([rule(RuleName,NumInputs,NumOutputs,InputVars2,InputVars4,VarList,VarList2,Rule)]),
append(Program1,[Rule],Program3),
%%writeln([inputVars3,InputVars3]),
%%InputVars2=InputVars3,
%%writeln([program4,Program4]),
caw(Query,PredicateName,Rules,MaxLength2,VarList2,InputVars1,InputVars4,InputVars3,OutputVarList,OutputVars,Program3,Program4).
varnames([],Vars,Vars,Values,Values) :- !.
varnames(VarList,Vars1,Vars2,Values1,Values2) :-
VarList=[Var|Vars3],
Var=[VarName,Value],
append(Vars1,[VarName],Vars4),
append(Values1,[Value],Values3),
varnames(Vars3,Vars4,Vars2,Values3,Values2),!.
addrules0(_,_,[],Program,Program).
addrules0(VarList,OutputVars1,OutputVars2,Program1,Program2) :-
OutputVars2=[OutputVar|OutputVars3],
member(Var,VarList),
member(OutputVar,OutputVars1),
append(Program1,[[=,[OutputVar,Var]]],Program3),
addrules0(VarList,OutputVars1,OutputVars3,Program3,Program2).
addrules(_,_,[],PV,PV,Program,Program) :- !.
addrules(VarList,OutputVars1,OutputVars2,PenultimateVars1,PenultimateVars2,Program1,Program2) :-
restlast(VarList,[],_,Var),
%%OutputVars2=[OutputVar|OutputVars3],
member(OutputVar,OutputVars2),
delete(OutputVars1,OutputVar,OutputVars3),
%%	member(Var,VarList),
member(OutputVar,OutputVars1),
append(Program1,[[=,[OutputVar,Var]]],Program3),
append(PenultimateVars1,[Var],PenultimateVars3),
addrules2(VarList,OutputVars1,OutputVars3,PenultimateVars3,PenultimateVars2,Program3,Program2).
addrules2(_,_,[],PV,PV,Program,Program) :- !.
addrules2(VarList,OutputVars1,OutputVars2,PenultimateVars1,PenultimateVars2,Program1,Program2) :-
%%	restlast(VarList,[],_,Var),
OutputVars2=[OutputVar|OutputVars3],
member(Var,VarList),
not(member(Var,PenultimateVars1)),
member(OutputVar,OutputVars1),
append(Program1,[[=,[OutputVar,Var]]],Program3),
append(PenultimateVars1,[Var],PenultimateVars3),
addrules2(VarList,OutputVars1,OutputVars3,PenultimateVars3,PenultimateVars2,Program3,Program2).
%% optimise([[append,[a,a,d]],[append,[a,a,e]],[append,[a,a,f]],[append,[a,b,g]]],[g],P).
/**
optimise(Program1,InputVars1,InputVars2,PenultimateVars,Program2) :-
reverse(Program1,Program4),
findrulesflowingtopv1(Program4,InputVars1,InputVars2,PenultimateVars,[],Rules,true),
%%findrulesflowingtopv1a(Program1,_Program32,InputVars1,InputVars2,PenultimateVars,[],_Rules1),
intersection(Program1,Rules,Program3),
unique1(Program3,[],Program2).
findrulesflowingtopv1(_,_,_,[],Rules,Rules,false).
findrulesflowingtopv1(Program0,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1) :-
(atom(Var);length(Var,1)),
findrulesflowingtopv20(Program0,Program0,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1).
findrulesflowingtopv1(Program0,InputVars1,InputVars2,Vars1,Rules1,Rules2,IV1Flag1) :-
Vars1=[Var|Vars2],
findrulesflowingtopv20(Program0,Program0,InputVars1,InputVars2,Var,Rules1,Rules3,IV1Flag2), 
findrulesflowingtopv1(Program0,InputVars1,InputVars2,Vars2,Rules3,Rules2,IV1Flag3),
iv1flagdisjunction(IV1Flag2,IV1Flag3,IV1Flag1).
%%findrulesflowingtopv2([],Program,Program,_,_,Rules,Rules).
findrulesflowingtopv20(_,[],_InputVars1,_InputVars2,_Var,Rules,Rules,false).
findrulesflowingtopv20(Program0,Rules4,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1) :-
Rules4=[Rule|Rules],
(findrulesflowingtopv2(Program0,Rule,InputVars1,InputVars2,Var,Rules1,Rules3,IV1Flag2)->true;(Rules3=Rules1,IV1Flag2=false)),
%%delete(Program0,Rule,Program1),
findrulesflowingtopv20(Program0,Rules,InputVars1,InputVars2,Var,Rules3,Rules2,IV1Flag3),%%p1->0
iv1flagdisjunction(IV1Flag2,IV1Flag3,IV1Flag1).
%%findrulesflowingtopv2(_,[],[],_,_,_,Rules,Rules).
findrulesflowingtopv2(Program0,Rule,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1) :-
Rule=[_PredicateName,Vars],
restlast(Vars,[],Rest,Var),
%%delete(Program1,[PredicateName,Vars],Program2),
%%Program2=Program1,
%%(not(intersection(Rulesx,Rules1))-> x
%% append, append, unique1
%%append(Rules1,[Rule],Rules3);Rules3=Rules1),
%%member(Var2,Rest),
%%member(Var2,InputVars1),
length(Rest,Length1), Length1>=1,
subtract(Rest,InputVars1,IV3s),
length(IV3s,Length3),
subtract(Rest,IV3s,IV1s),
length(IV1s,Length2), Length2>=1,
subtract(IV3s,InputVars2,[]),
IV1Flag2=true,
%%delete(Program0,Rule,Program1),
%%(delete(Program0,Rule,Program3),
%%iv3s1(IV3s,Program3,IV3s,[]),
(Length3>=1->
(findrulesflowingtopv1(Program0,InputVars1,InputVars2,IV3s,[],Rules5,IV1Flag3),not(Rules5=[]));
(Rules5=[],IV1Flag3=false)),
iv1flagdisjunction(IV1Flag2,IV1Flag3,IV1Flag4),
%%->true; Rules5=[],IV1Flag1=IV1Flag4),
((findrulesflowingtopv1(Program0,InputVars1,InputVars2,IV1s,[],Rules6,IV1Flag5), %%iv1s->rest, etc
iv1flagdisjunction(IV1Flag4,IV1Flag5,IV1Flag1))->true;(Rules6=[],IV1Flag1=IV1Flag4)),
append([Rule],Rules1,Rules9),
append(Rules9,Rules5,Rules7),
append(Rules7,Rules6,Rules8),
unique1(Rules8,[],Rules2).
/**
findrulesflowingtopv2(_Program0,Rule,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1) :-
Rule=[_PredicateName,Vars],
restlast(Vars,[],Rest,Var),
%%delete(Program1,[PredicateName,Vars],Program2),
%%Program2=Program1,
(not(member(Rule,Rules1))->
append(Rules1,[Rule],Rules2);Rules2=Rules1),
subset(Rest,InputVars2),
intersection(Rest,InputVars1,Intersection),
length(Intersection,0),
%%	not((member(Var2,Rest),
%%	member(Var2,InputVars1))),
IV1Flag1=false.
**/
/**
findrulesflowingtopv2(Program0,Rule,InputVars1,InputVars2,Var,Rules1,Rules2,IV1Flag1) :-
Rule=[_PredicateName,Vars],
restlast(Vars,[],Rest,Var),	
%%delete(Program1,[PredicateName,Vars],Program3),
%%Program3=Program1,
%%append(Rules1,[Rule],Rules3),
subset(Rest,InputVars2),
intersection(Rest,InputVars1,Intersection),
length(Intersection,0),
%%	not((member(Var2,Rest),
%%	member(Var2,InputVars1))),
%%	delete(Program0,Rule,Program1),
IV1Flag2=false,
findrulesflowingtopv1(Program0,InputVars1,InputVars2,Rest,[],Rules4,IV1Flag3),
%%not(Rules4=[]),
iv1flagdisjunction(IV1Flag2,IV1Flag3,IV1Flag1),
append(Rules1,[Rule],Rules7),
append(Rules7,Rules4,Rules8),
unique1(Rules8,[],Rules2).
**/
/**
%%->true;(Program2=Program1,Rules2=Rules1)).
findrulesflowingtopv2(Rule,Program0,Program1,_Program2,InputVars1,InputVars,Var,Rules1,Rules2,IV1Flag1) :-
Rule=[PredicateName,Vars],
restlast(Vars,[],Rest,Var),
%%delete(Program1,[PredicateName,Vars],Program4),
%%Program4=Program1,
append(Rules1,[[PredicateName,Vars]],Rules3),
findrulesflowingtopv1(Program0,Program1,_Program2,InputVars1,InputVars,Rest,Rules3,Rules2,IV1Flag3),
iv1flagdisjunction(IV1Flag2,IV1Flag3,IV1Flag1).
%%findrulesflowingtopv2(Program5,Program2,Rest,Rules3,Rules2).
**/
iv1flagdisjunction(A,B,true) :-
(A=true); (B=true).
iv1flagdisjunction(_,_,false).
/**
iv3s0([],_,IV3s1,IV3s2).
iv3s0(IV3s,Program0,IV3s1,IV3s2).
IV3s=[IV3|IV3s3],
iv3s1(IV3,Program0,IV3s1,IV3s4),
iv3s0(IV3s3,Program0,IV3s4,IV3s2).
iv3s1(_,[],IV3s,IV3s).	
iv3s1(IV3,Program0,IV3s1,IV3s2) :-
Program0=[Rule|Rules],
iv3s2(IV3,Rule,IV3s1,IV3s3),
iv3s1(IV3,Rules,IV3s3,IV3s2).
iv3s2(IV3,Rule,IV3s,IV3s1,IV3s2).
Rule=[_PredicateName,Vars],
restlast(Vars,[],_Rest,IV3),	
delete(IV3s1,IV3,IV3s2).
findrulesflowingtopv1a(_,_,_,_,[],Rules,Rules).
findrulesflowingtopv1a(Program1,Program2,InputVars1,InputVars2,Var,Rules1,Rules2) :-
atom(Var),
findrulesflowingtopv2a(Program1,Program2,InputVars1,InputVars2,Var,Rules1,Rules2).
findrulesflowingtopv1a(Program1,Program2,InputVars1,InputVars2,Vars1,Rules1,Rules2) :-
Vars1=[Var|Vars2],
findrulesflowingtopv2(Program1,Program3,InputVars1,InputVars2,Var,Rules1,Rules3),
findrulesflowingtopv1a(Program3,Program2,InputVars1,InputVars2,Vars2,Rules3,Rules2).
%%findrulesflowingtopv2([],Program,Program,_,_,Rules,Rules).
findrulesflowingtopv2a([],[],_,_,_,Rules,Rules).
findrulesflowingtopv2a(Program1,Program2,_InputVars1,InputVars2,Var,Rules1,Rules2) :-
member([PredicateName,Vars],Program1),
restlast(Vars,[],Rest,Var),
(
%%delete(Program1,[PredicateName,Vars],Program2),
Program2=Program1,
append(Rules1,[[PredicateName,Vars]],Rules2),
subset(Rest,InputVars2)).
findrulesflowingtopv2a(Program1,Program2,InputVars1,InputVars2,Var,Rules1,Rules2) :-
member([PredicateName,Vars],Program1),
restlast(Vars,[],Rest,Var),
(
%%delete(Program1,[PredicateName,Vars],Program3),
Program3=Program1,
append(Rules1,[[PredicateName,Vars]],Rules3),
subset(Rest,InputVars2)),
findrulesflowingtopv1a(Program3,Program2,InputVars1,InputVars2,Rest,Rules3,Rules2).
%%->true;(Program2=Program1,Rules2=Rules1)).
findrulesflowingtopv2a(Program1,Program2,InputVars1,InputVars,Var,Rules1,Rules2) :-
member([PredicateName,Vars],Program1),
restlast(Vars,[],Rest,Var),
%%delete(Program1,[PredicateName,Vars],Program4),
Program4=Program1,
append(Rules1,[[PredicateName,Vars]],Rules3),
findrulesflowingtopv1a(Program4,Program2,InputVars1,InputVars,Rest,Rules3,Rules2).
%%findrulesflowingtopv2(Program5,Program2,Rest,Rules3,Rules2).
**/
**/
restlast([],_,_,_) :- fail, !.	
restlast([Last],Rest,Rest,Last) :-
atom(Last),!.
restlast(Last,Rest,Rest,Last) :-
length(Last,1),!.
restlast(Vars1,Rest1,Rest2,Last) :-
Vars1=[Var|Vars2],
append(Rest1,[Var],Rest3),
restlast(Vars2,Rest3,Rest2,Last),!.
rule(RuleName,1,1,InputVars1,InputVars2,VarList,VarList2,Rule) :-
member(Var,InputVars1),
rule2(RuleName,Var,VarList,VarList2,Rule,Var1),
restlast(InputVars1,[],_,Last), %% Last should be outputs - 2nd last rule?
(Var=Last;Last=Var1),
append(InputVars1,[Var1],InputVars2).
rule2(RuleName,Var,VarList,VarList2,Rule,Var1) :-
var(VarList,Var1,VarList2),
Rule=[RuleName,[Var,Var1]].%%,
%%member(Var,!.
rule(RuleName,1,2,InputVars1,InputVars2,VarList,VarList2,Rule) :-
        member(Var,InputVars1),
        rule3(RuleName,Var,VarList,VarList2,Rule,Var1,Var2),
restlast(InputVars1,[],_,Last),
(Var=Last;
(Last=Var1;Last=Var2)),
append(InputVars1,[Var1,Var2],InputVars2).
rule3(RuleName,Var,VarList,VarList3,Rule,Var1,Var2) :-
        var(VarList,Var1,VarList2),
        var(VarList2,Var2,VarList3),
        Rule=[RuleName,[Var,Var1,Var2]],!.
rule(RuleName,2,0,InputVars,InputVars,VarList,VarList,Rule) :-
%%writeln([rule(RuleName,2,1,InputVars1,InputVars2,VarList,VarList2,Rule)]),
        member(Var,InputVars),
        member(Vara,InputVars),
        rule6(RuleName,Var,Vara,_VarList,_VarList2,Rule),
restlast(InputVars,[],_,Last),
%%writeln([last,Last]),
(Var=Last;Vara=Last).
rule6(RuleName,Var,Vara,_VarList,_VarList2,Rule) :-
        Rule=[RuleName,[Var,Vara]],!.
rule(RuleName,2,1,InputVars1,InputVars2,VarList,VarList2,Rule) :-
%%writeln([rule(RuleName,2,1,InputVars1,InputVars2,VarList,VarList2,Rule)]),
        member(Var,InputVars1),
        member(Vara,InputVars1),
        rule4(RuleName,Var,Vara,VarList,VarList2,Rule,Var1),
restlast(InputVars1,[],_,Last),
%%writeln([last,Last]),
((Var=Last;Vara=Last);
(Last=Var1)),
%%writeln([var,Var,vara,Vara]),
append(InputVars1,[Var1],InputVars2).
rule4(RuleName,Var,Vara,VarList,VarList2,Rule,Var1) :-
        var(VarList,Var1,VarList2),
        Rule=[RuleName,[Var,Vara,Var1]],!.
%%ae be with predicate support also
rule(RuleName,2,2,InputVars1,InputVars2,VarList,VarList2,Rule) :-
        member(Var,InputVars),
        member(Vara,InputVars),
        rule5(RuleName,Var,Vara,VarList,VarList2,Rule,Var1,Var2),
restlast(InputVars1,[],_,Last),
((Var=Last;Vara=Last);
(Last=Var1;Last=Var2)), %% make last var2, use different inputs from previous rule, make this line usea version of previous line as well (args from rule before that) - redo rules based on past programming
append(InputVars1,[Var1,Var2],InputVars2).
rule5(RuleName,Var,Vara,VarList,VarList3,Rule,Var1,Var2) :-
        var(VarList,Var1,VarList2),
        var(VarList2,Var2,VarList3),
        Rule=[RuleName,[Var,Vara,Var1,Var2]],!.
%%var(Item,Var,Vars,Vars) :-
%%	member([Item,Var],Vars).
var(Vars1,Var1,Vars2) :-
length(Vars1,Vars1Length1),
Vars1Length2 is Vars1Length1-1,
length(Vars3,Vars1Length2),
append(Vars3,[Var2],Vars1),
char_code(Var2,Var2Code1),
Var2Code2 is Var2Code1 + 1,
var2(Var2Code2,Var1),
append(Vars1,[Var1],Vars2),!.
var2(Code,Var1) :-
outputvars(OutputVars),
totalvars(TotalVars),
Code2 is 96+TotalVars,
Code =< Code2, %% 122
char_code(Var1,Code),
not(member(Var1,OutputVars)),!.
var2(Var2Code,Code3) :-
Var2Code2 is Var2Code + 1,	
totalvars(TotalVars),
Code2 is 96+TotalVars,
Var2Code2 =< Code2,
var2(Var2Code2,Code3),!.
%% this goes from e.g. c not a to TotalVars
%% skip over vars, start from a x reassign vars to abc etc
%% if returning 12 from 12345 remove 345 args
%% try lowest possible number of vars first (return shortest program first), then keep on adding number of vars
%% can elimininate same program both here and in assessment verification