/*
    go(Constraint_number, Update_operation, Relation_being_updated)

    Main top-level procedure to do everything.
    Example: go(1,insert,sale).
*/

go(N,Op,Rel) :-

    stage1(N,Op,Rel,TIME1),
    write('Time, stage 1 '), write(TIME1), bell,nl,

    stage2(TIME2),
    write('Time, stage 2 '), write(TIME2), bell,nl,

    stage3(TIME3),
    write('Time, stage 3 '), write(TIME3), bell,nl,

    stage4(TIME4),
    write('Time, stage 4 '), write(TIME4), bell,nl,

    log(N,Op,Rel,TIME1,TIME2,TIME3,TIME4),

    !.

/*
    go2(Constraint_number, Update_operation, Relation_being_updated)

    Another top-level procedure.  Stages 2 and 3 are skipped.
    (No resolution is done -- it goes straight to the iff test.)
    Example: go2(1,insert,sale).
*/

go2(N,Op,Rel) :-

    stage1(N,Op,Rel,TIME1),
    write('Time, stage 1 '), write(TIME1), bell,nl,

    init_axioms(Iax),
    init_sos(Isos),
    init_hbg(Ihbg),
    init_demod(Idemod),

    assert(axioms(Iax)),
    assert(sos(Isos)),
    assert(hbg(Ihbg)),
    assert(demod(Idemod)),
    
    append_and(Iax,Isos,RED),

    assert(reduced(RED)),
    assert(dependent(true)),

    stage4(TIME4),
    write('Time, stage 4 '), write(TIME4), bell,nl,

    log(N,Op,Rel,TIME1,0,0,TIME4),

    !.
/*
    go3(Constraint_number, Update_operation, Relation_being_updated)

    Another top-level procedure.  Stages 2 and 3 are skipped.
    (No resolution is done -- it goes straight to the iff test.)
    Example: go2(1,insert,sale).
*/

go3(N,Op,Rel) :-

    clean_all_but_log,

    get_seconds(TIME1),

    constraint(N,Constraint),
    update(Op,Rel,Relold,Tax),

    assert(curr_constraint(Constraint)),
    assert(curr_update(Tax)),

    subst(Rel,Constraint,Relold,Cold),

    nnf(Cold,Cold1),
    unique_vars(Cold1,Coldnnf),
    assert(coldnnf(Coldnnf)),

 %   clausify(Coldnnf,V11),

    Tax =.. [iff,Left,Right],
    Left =.. [Relnew|Varlist],
    subst(Rel,Constraint,Relnew,Cnew),
    taxsub(Cnew,Relnew,Varlist,Right,Ctax),

    assert(axioms(true)),
    assert(sos(true)),
    assert(hbg(true)),
    assert(demod(true)),

    assert(init_axioms(true)),
    assert(init_sos(true)),
    assert(init_hbg(true)),
    assert(init_demod(true)),
    
    assert(reduced(true)),
    assert(dependent(true)),

  %  mini7(Ctax,R4),
  %  nnf(~R4,R5),
  %  mini7(R5,R6),
  %  nnf(~R6,F2),

    nnf2(~Ctax,R4),
    mini7(R4,R5),
    nnf(~R5,R6),
    mini7(R6,F2),

    assert(extra_tests(F2)),  % not really extra tests

    copy_new_vars(Coldnnf, Cold_copy),

    s2_conj(Cold_copy, F2, F3),

    rdnf(F3, F4),

    assert(iff_test(F4)),

    get_seconds(TIME3),

    TIME2 is TIME3 - TIME1,

    write('Time, go3 '), write(TIME2), bell,nl,

    log3(N,Op,Rel,TIME2),
    !.
    
/* 
    stage1(N,Op,Rel,Time) - Convert C[RNEW] and ~C[TAX] to clauses,
    pick an initial sos, then assert the clauses.
*/

stage1(X,Op,Rel,TIME2) :-

    clean_all_but_log,

    get_seconds(TIME1),

    constraint(X,Constraint),
    update(Op,Rel,Relold,Tax),

    assert(curr_constraint(Constraint)),
    assert(curr_update(Tax)),

    subst(Rel,Constraint,Relold,Cold),

    nnf(Cold,Cold1),
    unique_vars(Cold1,Coldnnf),
    assert(coldnnf(Coldnnf)),

    clausify(Coldnnf,V11),

    Tax =.. [iff,Left,Right],
    Left =.. [Relnew|Varlist],
    subst(Rel,Constraint,Relnew,Cnew),
    taxsub(Cnew,Relnew,Varlist,Right,Ctax),

    clausify(~Ctax,V14),

  ( flag(verbose) ->
	write('C[OLD] in clauses:'),nl,
	pcllist(V11),nl,
	write('~C[TAX] in clauses:'),nl,
	pcllist(V14),nl ; true),

    picksos(V11,V14,AX,SOS),
    
    assert(init_axioms(AX)),
    assert(init_sos(SOS)),
    assert(init_hbg(true)),
    assert(init_demod(true)),
    
    get_seconds(TIME3),

    TIME2 is TIME3 - TIME1,

    !.

/*
    stage2(TIME) - Apply binary resolution (with forward/backward 
    subsumption, forward/back demodulation) until a proof is found 
    or the sos is empty.  (The given, have-been-given, sos algorithm 
    is used.)
*/

stage2(TIME2) :-
    
    get_seconds(TIME1),

    abolish(axioms,1),
    abolish(sos,1),
    abolish(hbg,1),
    abolish(demod,1),

    init_axioms(Iax),
    init_sos(Isos),
    init_hbg(Ihbg),
    init_demod(Idemod),

    assert(axioms(Iax)),
    assert(sos(Isos)),
    assert(hbg(Ihbg)),
    assert(demod(Idemod)),
    
  repeat,

    retract(axioms(AX)),
    retract(hbg(HBG)),
    retract(sos(SOS)),
    retract(demod(DEMOD)),

  ( flag(verbose) ->
        nl,
        write('***********************************************'),nl, nl,
        write('axoims: '), nl,
        pcllist(AX), nl,

        write('have been given:'), nl,
        pcllist(HBG), nl,

        write('set of support:'), nl,
        pcllist(SOS), nl  ;true),

    picklightest(SOS,GIVEN,SOS2),

    reslist(GIVEN,and(AX,HBG),true,RES),

  ( flag(verbose) ->
        write('given clause: '),
        pcllist(GIVEN), nl,
	write('resolvents: '), nl,
	pcllist(RES),nl ; true),

    process5(RES,AX,HBG and GIVEN,SOS2,DEMOD,AXF,HBGF,SOSF,DEMODF),

    cleanup(AXF,AXFF),
    cleanup(HBGF,HBGFF),
    cleanup(SOSF,SOSFF),
    cleanup(DEMODF,DEMODFF),

    asserta(axioms(AXFF)),
    asserta(hbg(HBGFF)),
    asserta(sos(SOSFF)),
    asserta(demod(DEMODFF)),

    SOSFF == true,

    get_seconds(TIME3),

    TIME2 is TIME3 - TIME1,

    !.

/*
    stage3(TIME) - Pick out the dependent clauses from the 
    have-been-given list.
*/

stage3(TIME2) :-

    get_seconds(TIME1),

    abolish(reduced,1),
    abolish(dependent,1),
    axioms(AX),
    hbg(HBG),
    eqfirst(HBG,HBG1),
    delred(AX,HBG1,S1,S2),
    cleanup(S1,S15),
    cleanup(S2,S25),
    asserta(reduced(S15)),
    asserta(dependent(S25)),

    get_seconds(TIME3),

    TIME2 is TIME3 - TIME1,

    !.

/*
    stage4(TIME) - Generate the iff test from the reduced set of 
    clauses, and generate the extra tests from the dependent set.
*/

stage4(TIME2) :-

    get_seconds(TIME1),

    abolish(extra_tests,1),
    abolish(iff_test,1),

    dependent(R1),
    extratests(R1,R2),
    assert(extra_tests(R2)),

    reduced(F1),
    coldnnf(C),
    ifftest(F1,C,F2),
    assert(iff_test(F2)),

    get_seconds(TIME3),

    TIME2 is TIME3 - TIME1,

    !.


/*
    log(N,Op,Rel,T1,T2,T3,T4) - Log everything to a file.
*/

log(X,Op,Rel,TIME1,TIME2,TIME3,TIME4) :-
    flag(log),
    gensym(log,F),
    tell(F),
    write(go(X,Op,Rel)),
    T5 is TIME1 + TIME2 + TIME3 + TIME4,
    write('.  Total time is '), write(T5), write(' seconds.'), nl,
    write(TIME1), write(' | '),
    write(TIME2), write(' | '),
    write(TIME3), write(' | '),
    write(TIME4), nl, nl,
    curr_constraint(CONST),
    write('Constraint: '), nl,
    write(CONST), nl, nl,
    curr_update(UPD),
    write('Update: '), nl,
    write(UPD), nl, nl,
    write('-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-'),nl,
    init_clauses, nl,
    write('-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-'),nl, nl,
    write('After resolution: '), nl,
    clauses, nl,
    write('-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-3-'),nl,
    cl3, nl,
    write('-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-4-'),nl,
    tests, nl,
    write('-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-'),nl,

    listing(flag),
    listing(count),
    listing(option),
    listing(commutative),
    listing(currentnum),
    
    told,
    !.
log(_,_,_,_,_,_,_) :-
    told,
    !.

log3(X,Op,Rel,TIME4) :-
    flag(log),
    gensym(log,F),
    tell(F),
    write(go3(X,Op,Rel)),
    write('.  Total time is '), write(TIME4), write(' seconds.'), nl, nl,
    curr_constraint(CONST),
    write('Constraint: '), nl,
    write(CONST), nl, nl,
    curr_update(UPD),
    write('Update: '), nl,
    write(UPD), nl, nl,

    write('-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-T-'),nl,
    iff_test(F1),
    nl, write('iff test assuming COLD: '), nl,
    printdis(F1), nl,
    extra_tests(F2), % not really extra tests
    nl, write('iff test NOT assuming COLD: '), nl,
    printdis(F2), nl, nl,
    write('-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-S-'),nl,

    listing(flag),
    listing(count),
    listing(option),
    listing(commutative),
    listing(currentnum),
    
    told,
    !.
log3(_,_,_,_) :-
    told,
    !.

/*
    ifftest(Rin,Cold,Rout) - Convert a reduced set of clauses (Rin)
    to an iff test (Rout).  Cold is the constraint -- it is used to
    simplify (subsume parts of) the test.
*/
    
ifftest(Rin,Cold,Rout) :-
    mini7(Cold,C1),
    unsk_conj(Rin,R1),
    mini7(R1,R25),
    s2_conj(C1,R25,R3),
    nnf(~R3,R5),
    rcnf(R5,R55),
    s2_conj(C1,R55,R6),
    rdnf(R6, Rout),
    !.

/*
    extratests(Din,Dout) -  Transform a conjunction of clauses into
    a disjunction of extra tests.  This is done by unSkolemizing
    and simplifying them individually, then negating the whole
    conjunction to get a disjunction of extra tests.
*/

extratests(Din,Dout) :-
    ex1(Din,D1),
    nnf(~D1,D2),
    cleanup(D2,Dout),
    !.

ex1(X and Y,X1 and Y1) :-
    !,
    ex1(X,X1),
    ex1(Y,Y1).
ex1(X,Y) :-
    unsk_conj(X,X1),
    !,
    mini7(X1,Y).
ex1(_,true).

/*
    process5(Clauses,AXin ,HBGin ,SOSin ,DEMODin,
		     AXout,HBGout,SOSout,DEMODout)

    Process a conjunction of clauses.  This involves forward
    demodulation, forward/back subsumption, back demodulation,
    and recursively processing back demodulants.
*/

process5(true,AX,HBG,SOS,DEMOD,AX,HBG,SOS,DEMOD) :-
    !.

process5(X and Y,AX,HBG,SOS,DEMOD,AXout,HBGout,SOSout,DEMODout) :-
    !,
    process5(X,AX,HBG,SOS,DEMOD,AX1,HBG1,SOS1,DEMOD1),
    process5(Y,AX1,HBG1,SOS1,DEMOD1,AXout,HBGout,SOSout,DEMODout),
    !.

process5(RES,AX,HBG,SOS,DEMOD,AXout,HBGout,SOSout,DEMODout) :-


    demodulate(DEMOD,RES,RES2),
    simplify(RES2,RES3),
    subsumelist(AX and HBG and SOS,RES3,RES4),


    subsumelist(RES4,AX and HBG and SOS and DEMOD,
		     AX1 and HBG1 and SOS1 and DEMOD1),

    newdemods(RES4,true,true,NDMD,DMD),


    append_and(SOS1,NDMD,SOS15),

    bd1(DMD,DEMOD1,AX1 and HBG1 and SOS15,true,
	    DEMOD2,AX2 and HBG2 and SOS2,MOD),

  ( flag(verbose) ->
        write('++++++++++++++++processing++++++++++++++++'), nl,
        pcllist(RES), nl,
        write('demodulate and simplify :'), nl,
        pcllist(RES3), nl,
        write('after forward subsumption:'), nl,
        pcllist(RES4), nl,
         write('new demodulator:'), nl,
        pcllist(DMD), nl ; true),

    /* possibly not put demodulator on sos */

    deld(DMD,DEMOD3), 

    append_and(SOS2,DEMOD3,SOS3),

    cleanup(MOD,MOD1),

    process5(MOD1,AX2,HBG2,SOS3,DEMOD2,AXout,HBGout,SOSout,DEMODout),
     
    !.

clean_all_but_log :- 

    abolish(count,2),
    abolish(curr_constraint,1),
    abolish(curr_update,1),

    clean_currentnum(uu),
    clean_currentnum(vv),
    clean_currentnum(ww),
    clean_currentnum(xx),
    clean_currentnum(yy),
    clean_currentnum(zz),
    clean_currentnum(f ),
    clean_currentnum(g ),

    abolish(axioms,1),
    abolish(sos,1),
    abolish(hbg,1),
    abolish(demod,1),

    abolish(reduced,1),
    abolish(dependent,1),

    abolish(coldnnf,1),

    abolish(init_axioms,1),
    abolish(init_sos,1),
    abolish(init_hbg,1),
    abolish(init_demod,1),

    abolish(extra_tests,1),
    abolish(iff_test,1),

    !.
