/*
    reslist(Clause,List,Lin,Lout) - Generate the set of resolvents
    from Clause and clauses in List.  Append the resolvents to Lin
    to form Lout.  If flag(first_lit), then the first literal only
    of Clause is resolved upon.
*/


reslist(CL,and(X,Y),Lin,Lout) :-
    !,
    reslist(CL,X,Lin,L1),
    reslist(CL,Y,L1,Lout),
    !.
reslist(CL1,CL2,Lin,Lout) :-
    newvars(CL2, CL2n),
    res2cl(CL1,CL1,CL2n,Lin,Lout),
    !.

/*
    rescl(C1,C2,Rout) - Binary resolution.  Rout is the
    set of binary resolvents from clauses C1 and C2.  If 
    flag(first_lit), then only the first literal of C1 is
    resolved upon.
*/

rescl(C1,C2,Rout) :-
    newvars(C2, C2n),
    res2cl(C1,C1,C2n,true,Rout),
    !.

res2cl(or(X,_),C1,C2,Rin,Rout) :-
    flag(first_lit),
    !,
    res2cl(X,C1,C2,Rin,Rout).
res2cl(or(X,Y),C1,C2,Rin,Rout) :-
    !,
    res2cl(X,C1,C2,Rin,R1),
    res2cl(Y,C1,C2,R1,Rout).
res2cl(L1,C1,C2,Rin,Rout) :-
    res1cl(L1,C1,C2,C2,Rin,Rout).

res1cl(L1,C1,or(X,Y),C2,Rin,Rout) :-
    !,
    res1cl(L1,C1,X,C2,Rin,R1),
    res1cl(L1,C1,Y,C2,R1,Rout).
res1cl(L1,C1,L2,C2,Rin,Rout) :-
    resolvents(L1,C1,L2,C2,Rin,Rout).

resolvents(L1,C1,~(L2),C2,Rin,Rout) :-
    increment(res_unify_attempts),
    unify(L1,L2,[[],[]],Sub),
    !,
    increment(binary_resolutions),
    genres(L1,~(L2),or(C1,C2),Sub,false,R),
    normalize(R,R1),
    andon(Rin,R1,Rout),
    !.
resolvents(~(L1),C1,L2,C2,Rin,Rout) :-
    increment(res_unify_attempts),
    unify(L1,L2,[[],[]],Sub),
    !,
    increment(binary_resolutions),
    genres(~(L1),L2,or(C1,C2),Sub,false,R),
    normalize(R,R1),
    andon(Rin,R1,Rout),
    !.
resolvents(_,_,_,_,Rin,Rin) :-
    !.

genres(L1,L2,or(X,Y),Sub,Lin,Lout) :-
    !,
    genres(L1,L2,X,Sub,Lin,LT),
    genres(L1,L2,Y,Sub,LT,Lout),
    !.
genres(_,L2,L2,_,Lin,Lin) :-
    !.
genres(L1,_,L1,_,Lin,Lin) :-
    !.
genres(_,_,L3,[V,T],Lin,Lout) :-
    !,
    simsub(V,L3,T,L4),
    oron(Lin,L4,Lout),
    !.

/*
    picklightest(Lin,Light,Lout) - Extract the clause (Light) with
    fewest symbols from Lin.  Lout is Lin - Light.
*/

picklightest(Lin,Light,Lout) :-
    lightest(Lin,Light,_),
    extract(Lin,Light,Lout),
    !.

/*
    pickheavy(Lin,Heavy,Lout) - Extract the clause (Heavy) with
    most symbols from Lin.  Lout is Lin - Heavy.
*/

pickheavy(Lin,Heavy,Lout) :-
    heavy(Lin,Heavy,_),
    extract(Lin,Heavy,Lout),
    !.

lightest(and(X,Y),CL,WT) :-
    !,
    lightest(X,CLX,WTX),
    lightest(Y,CLY,WTY),
    min2(CLX,WTX,CLY,WTY,CL,WT),
    !.
lightest(X,X,WT) :-
    symct(X,WT),
    !.

heavy(and(X,Y),CL,WT) :-
    !,
    heavy(X,CLX,WTX),
    heavy(Y,CLY,WTY),
    max2(CLX,WTX,CLY,WTY,CL,WT),
    !.
heavy(X,X,WT) :-
    symct(X,WT),
    !.

min2(C1,W1,_,W2,C1,W1) :-
    W1 =< W2,
    !.
min2(_,_,C2,W2,C2,W2).

max2(C1,W1,_,W2,C1,W1) :-
    W1 >= W2,
    !.
max2(_,_,C2,W2,C2,W2).

symct(T,1) :-
    atomic(T),
    !.
symct(T,N) :-
    T =.. L,
    symctrec(L,N).

symctrec([H|T],N) :-
    symct(H,N1),
    symctrec(T,N2),
    N is N1 + N2.
symctrec([],0).

extract(and(X,Y),Z,and(X1,Y1)) :-
    !,
    extract(X,Z,X1),
    extract(Y,Z,Y1).
extract(X,C,true) :-
    X == C,
    !.
extract(X,_,X).

