|
1 package G4ip; |
|
2 |
|
3 |
|
4 import pizza.util.Hashtable; |
|
5 import java.util.Vector; |
|
6 import G4ip.Form.*; |
|
7 import G4ip.ProofDisplay.*; |
|
8 import G4ip.Sequent.*; |
|
9 |
|
10 |
|
11 /** The Gi4p prover.<p> |
|
12 * The prover is a thread in order to suspend the proof search |
|
13 * after one proof is found and to let the user make a choice |
|
14 * of whether to stop or to continue with the proof search. |
|
15 * @author Christian Urban |
|
16 */ |
|
17 public class Prover extends Thread |
|
18 { ProverApplet parent; // the parent of the prover; |
|
19 boolean once; // if true then at least one proof was found |
|
20 Sequent sequ; // the root sequent to be proved |
|
21 Vector frames; // to record all frames which have been opened |
|
22 int index ; |
|
23 Hashtable<int,Sequent> proof; // keeps a record of the proof |
|
24 |
|
25 |
|
26 /** The constructor creates a prover which proves a specific sequent.<p> |
|
27 * The parameter parent is for access to the applet buttons. |
|
28 */ |
|
29 public Prover(Sequent init_sequ, ProverApplet init_parent) { |
|
30 super("Prover"); |
|
31 parent = init_parent; |
|
32 once = false; |
|
33 sequ = new Sequent(init_sequ); |
|
34 frames = new Vector(); |
|
35 index = 1; |
|
36 proof = new Hashtable(); |
|
37 } |
|
38 |
|
39 /** Starts the thread; calls prove and stops the thread when |
|
40 * the proof search is finished. |
|
41 */ |
|
42 public void run() |
|
43 { prove(1,sequ,initial_sc); |
|
44 if (once == true) { |
|
45 parent.messages.setText("No more proofs."); |
|
46 parent.messages.repaint(); |
|
47 parent.repaint(); |
|
48 } |
|
49 else { |
|
50 parent.messages.setText("Not provable."); |
|
51 parent.messages.repaint(); |
|
52 parent.repaint(); |
|
53 } |
|
54 parent.switch_into_input_mode(); |
|
55 this.stop(); // everything is done, stop the thread |
|
56 } |
|
57 |
|
58 /** Closes all frames which have been opened. |
|
59 */ |
|
60 public void finalize() { |
|
61 for (int i=0; i<frames.size();i++) { |
|
62 if (frames.elementAt != null) |
|
63 { ((ProofDisplay)frames.elementAt(i)).dispose(); } |
|
64 } |
|
65 } |
|
66 |
|
67 /** The tactic of the proof search.<p> |
|
68 * Method prove first enumerates all formulae on the LHS |
|
69 * as being the principal formula and attempts to apply left-rules, |
|
70 * subsequently it analyses the goal formula. |
|
71 */ |
|
72 public void prove(int index, Sequent is,(() -> void) sc) { |
|
73 Form principal; |
|
74 proof.put(index,new Sequent(is)); // add sequence to proof |
|
75 rightrules(index,is,sc); |
|
76 for (int i=0;i<is.Gamma.size();i++) { |
|
77 principal = (Form)is.Gamma.elementAt(i); |
|
78 is.Gamma.removeElement(principal); // Gamma minus principal formula |
|
79 leftrules(index,principal,is,sc); |
|
80 is.Gamma.insertElementAt(principal,i); // put principal formula |
|
81 } // back into Gamma |
|
82 //rightrules(index,is,sc); |
|
83 proof.remove(index); // remove sequence from proof |
|
84 } |
|
85 |
|
86 /** Analyses the goal formula. |
|
87 */ |
|
88 public void rightrules(int index, Sequent sequ,(() -> void) sc) { |
|
89 Context Gamma = sequ.Gamma; |
|
90 switch(sequ.G) { |
|
91 /** And-R |
|
92 * Gamma => A Gamma => B |
|
93 * -------------------------- |
|
94 * Gamma => A and B |
|
95 */ |
|
96 case And(Form A,Form B): |
|
97 prove(2*index,new Sequent(Gamma,A), |
|
98 fun() -> void { prove(2*index+1,new Sequent(Gamma,B),sc); } ); |
|
99 break; |
|
100 |
|
101 /** Imp-R |
|
102 * Gamma,A => B |
|
103 * ----------------- |
|
104 * Gamma => A imp B |
|
105 */ |
|
106 case Imp(Form A,Form B): |
|
107 prove(2*index,new Sequent(Gamma.add(A),B),sc); break; |
|
108 |
|
109 /** Or-R |
|
110 * Gamma => A Gamma => B |
|
111 * ----------------- or ----------------- |
|
112 * Gamma => A or B Gamma => A or B |
|
113 */ |
|
114 case Or(Form A,Form B): |
|
115 prove(2*index,new Sequent(Gamma,A),sc); |
|
116 prove(2*index,new Sequent(Gamma,B),sc); break; |
|
117 |
|
118 /** Equ-R |
|
119 * Gamma => A -> B Gamma => B -> A |
|
120 * -------------------------------- |
|
121 * Gamma => A <-> B |
|
122 */ |
|
123 } |
|
124 } |
|
125 |
|
126 /** Analyses the principal formula on the LHS. |
|
127 */ |
|
128 public void leftrules(int index,Form principal,Sequent sequ,(() -> void) sc){ |
|
129 Context Gamma = sequ.Gamma; |
|
130 Form G = sequ.G; |
|
131 switch(principal) { |
|
132 /** false-L |
|
133 * -------------------- |
|
134 * false, Gamma => G |
|
135 */ |
|
136 case False(): sc(); break; |
|
137 |
|
138 /** Axiom |
|
139 * --------------- |
|
140 * Gamma, G => G G being atomic |
|
141 */ |
|
142 case Atm(String c): |
|
143 if (G instanceof Atm) { |
|
144 if (((Atm)G).c.compareTo(c) == 0) { sc(); } |
|
145 } |
|
146 break; |
|
147 |
|
148 /** And-L |
|
149 * Gamma, A, B => G |
|
150 * -------------------- |
|
151 * Gamma, A and B => G |
|
152 */ |
|
153 |
|
154 case And(Form A, Form B): |
|
155 prove(2*index,new Sequent(Gamma.add(A,B),G),sc); break; |
|
156 |
|
157 /** Or-R |
|
158 * Gamma, A => G Gamma, B => G |
|
159 * ------------------------------- |
|
160 * Gamma, A or B => G |
|
161 */ |
|
162 case Or(Form A, Form B): |
|
163 prove(2*index,new Sequent(Gamma.add(A),G), |
|
164 fun() -> void {prove(2*index+1,new Sequent(Gamma.add(B),G),sc);}); |
|
165 break; |
|
166 |
|
167 /** Imp-L 2 |
|
168 * Gamma, A imp (B imp C) => G |
|
169 * ------------------------------ |
|
170 * Gamma, (A and B) imp C => G |
|
171 */ |
|
172 case Imp(And(Form A, Form B), Form C): |
|
173 prove(2*index,new Sequent(Gamma.add(Imp(A,Imp(B,C))),G),sc); break; |
|
174 |
|
175 |
|
176 /** Imp-L 3 |
|
177 * Gamma, (A imp C), (B imp C) => G |
|
178 * ---------------------------------- |
|
179 * Gamma, (A or B) imp C => G |
|
180 */ |
|
181 case Imp(Or(Form A, Form B), Form C): |
|
182 prove(2*index,new Sequent(Gamma.add(Imp(A,C),Imp(B,C)),G),sc); break; |
|
183 |
|
184 /** Imp-L 4 |
|
185 * Gamma, (B imp C) => (A imp B) Gamma, C => G |
|
186 * ------------------------------------------------ |
|
187 * Gamma, (A imp B) imp C => G |
|
188 */ |
|
189 case Imp(Imp(Form A, Form B), Form C): |
|
190 prove(2*index,new Sequent(Gamma.add(Imp(B,C)),Imp(A,B)), |
|
191 fun() -> void { prove(2*index+1,new Sequent(Gamma.add(C),G),sc);}); |
|
192 break; |
|
193 /** Imp-L 1 |
|
194 * Gamma(A), B => G A being atomic |
|
195 * ------------------------ Gamma(A) means: |
|
196 * Gamma(A), A imp B => G Gamma contains A |
|
197 */ |
|
198 case Imp(Form A, Form B): |
|
199 if (A instanceof Atm) { |
|
200 if (Gamma.includes(A)) { |
|
201 { prove(2*index,new Sequent(Gamma.add(B),G),sc); } |
|
202 } |
|
203 } |
|
204 break; |
|
205 } |
|
206 |
|
207 } |
|
208 |
|
209 |
|
210 /** The initial success continuation. |
|
211 * Suspends the thread when a proof is found. |
|
212 */ |
|
213 public void initial_sc() { |
|
214 once = true; |
|
215 ProofDisplay p = new ProofDisplay(proof); |
|
216 frames.addElement(p); // keep a record for later disposal |
|
217 try { // suspend the proof search, |
|
218 suspend(); } // it might be resumed later on by the user |
|
219 catch(SecurityException sec_exc) |
|
220 { /* this catch is neccessary for Netscape 3.0 (Linux) */ } |
|
221 } |
|
222 |
|
223 } |