package G4ip;
import pizza.util.Hashtable;
import java.util.Vector;
import G4ip.Form.*;
import G4ip.ProofDisplay.*;
import G4ip.Sequent.*;
/** The Gi4p prover.<p>
* The prover is a thread in order to suspend the proof search
* after one proof is found and to let the user make a choice
* of whether to stop or to continue with the proof search.
* @author Christian Urban
*/
public class Prover extends Thread
{ ProverApplet parent; // the parent of the prover;
boolean once; // if true then at least one proof was found
Sequent sequ; // the root sequent to be proved
Vector frames; // to record all frames which have been opened
int index ;
Hashtable<int,Sequent> proof; // keeps a record of the proof
/** The constructor creates a prover which proves a specific sequent.<p>
* The parameter parent is for access to the applet buttons.
*/
public Prover(Sequent init_sequ, ProverApplet init_parent) {
super("Prover");
parent = init_parent;
once = false;
sequ = new Sequent(init_sequ);
frames = new Vector();
index = 1;
proof = new Hashtable();
}
/** Starts the thread; calls prove and stops the thread when
* the proof search is finished.
*/
public void run()
{ prove(1,sequ,initial_sc);
if (once == true) {
parent.messages.setText("No more proofs.");
parent.messages.repaint();
parent.repaint();
}
else {
parent.messages.setText("Not provable.");
parent.messages.repaint();
parent.repaint();
}
parent.switch_into_input_mode();
this.stop(); // everything is done, stop the thread
}
/** Closes all frames which have been opened.
*/
public void finalize() {
for (int i=0; i<frames.size();i++) {
if (frames.elementAt != null)
{ ((ProofDisplay)frames.elementAt(i)).dispose(); }
}
}
/** The tactic of the proof search.<p>
* Method prove first enumerates all formulae on the LHS
* as being the principal formula and attempts to apply left-rules,
* subsequently it analyses the goal formula.
*/
public void prove(int index, Sequent is,(() -> void) sc) {
Form principal;
proof.put(index,new Sequent(is)); // add sequence to proof
rightrules(index,is,sc);
for (int i=0;i<is.Gamma.size();i++) {
principal = (Form)is.Gamma.elementAt(i);
is.Gamma.removeElement(principal); // Gamma minus principal formula
leftrules(index,principal,is,sc);
is.Gamma.insertElementAt(principal,i); // put principal formula
} // back into Gamma
//rightrules(index,is,sc);
proof.remove(index); // remove sequence from proof
}
/** Analyses the goal formula.
*/
public void rightrules(int index, Sequent sequ,(() -> void) sc) {
Context Gamma = sequ.Gamma;
switch(sequ.G) {
/** And-R
* Gamma => A Gamma => B
* --------------------------
* Gamma => A and B
*/
case And(Form A,Form B):
prove(2*index,new Sequent(Gamma,A),
fun() -> void { prove(2*index+1,new Sequent(Gamma,B),sc); } );
break;
/** Imp-R
* Gamma,A => B
* -----------------
* Gamma => A imp B
*/
case Imp(Form A,Form B):
prove(2*index,new Sequent(Gamma.add(A),B),sc); break;
/** Or-R
* Gamma => A Gamma => B
* ----------------- or -----------------
* Gamma => A or B Gamma => A or B
*/
case Or(Form A,Form B):
prove(2*index,new Sequent(Gamma,A),sc);
prove(2*index,new Sequent(Gamma,B),sc); break;
/** Equ-R
* Gamma => A -> B Gamma => B -> A
* --------------------------------
* Gamma => A <-> B
*/
}
}
/** Analyses the principal formula on the LHS.
*/
public void leftrules(int index,Form principal,Sequent sequ,(() -> void) sc){
Context Gamma = sequ.Gamma;
Form G = sequ.G;
switch(principal) {
/** false-L
* --------------------
* false, Gamma => G
*/
case False(): sc(); break;
/** Axiom
* ---------------
* Gamma, G => G G being atomic
*/
case Atm(String c):
if (G instanceof Atm) {
if (((Atm)G).c.compareTo(c) == 0) { sc(); }
}
break;
/** And-L
* Gamma, A, B => G
* --------------------
* Gamma, A and B => G
*/
case And(Form A, Form B):
prove(2*index,new Sequent(Gamma.add(A,B),G),sc); break;
/** Or-R
* Gamma, A => G Gamma, B => G
* -------------------------------
* Gamma, A or B => G
*/
case Or(Form A, Form B):
prove(2*index,new Sequent(Gamma.add(A),G),
fun() -> void {prove(2*index+1,new Sequent(Gamma.add(B),G),sc);});
break;
/** Imp-L 2
* Gamma, A imp (B imp C) => G
* ------------------------------
* Gamma, (A and B) imp C => G
*/
case Imp(And(Form A, Form B), Form C):
prove(2*index,new Sequent(Gamma.add(Imp(A,Imp(B,C))),G),sc); break;
/** Imp-L 3
* Gamma, (A imp C), (B imp C) => G
* ----------------------------------
* Gamma, (A or B) imp C => G
*/
case Imp(Or(Form A, Form B), Form C):
prove(2*index,new Sequent(Gamma.add(Imp(A,C),Imp(B,C)),G),sc); break;
/** Imp-L 4
* Gamma, (B imp C) => (A imp B) Gamma, C => G
* ------------------------------------------------
* Gamma, (A imp B) imp C => G
*/
case Imp(Imp(Form A, Form B), Form C):
prove(2*index,new Sequent(Gamma.add(Imp(B,C)),Imp(A,B)),
fun() -> void { prove(2*index+1,new Sequent(Gamma.add(C),G),sc);});
break;
/** Imp-L 1
* Gamma(A), B => G A being atomic
* ------------------------ Gamma(A) means:
* Gamma(A), A imp B => G Gamma contains A
*/
case Imp(Form A, Form B):
if (A instanceof Atm) {
if (Gamma.includes(A)) {
{ prove(2*index,new Sequent(Gamma.add(B),G),sc); }
}
}
break;
}
}
/** The initial success continuation.
* Suspends the thread when a proof is found.
*/
public void initial_sc() {
once = true;
ProofDisplay p = new ProofDisplay(proof);
frames.addElement(p); // keep a record for later disposal
try { // suspend the proof search,
suspend(); } // it might be resumed later on by the user
catch(SecurityException sec_exc)
{ /* this catch is neccessary for Netscape 3.0 (Linux) */ }
}
}