View Javadoc

1   /* This file is part of the project "Hilbert II" - http://www.qedeq.org" target="alexandria_uri">http://www.qedeq.org
2    *
3    * Copyright 2000-2014,  Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU General Public License for more details.
14   */
15  
16  package org.qedeq.kernel.bo.logic.proof.checker;
17  
18  import java.util.HashMap;
19  import java.util.Map;
20  
21  import org.qedeq.base.io.Version;
22  import org.qedeq.base.utility.Enumerator;
23  import org.qedeq.base.utility.EqualsUtility;
24  import org.qedeq.base.utility.StringUtility;
25  import org.qedeq.kernel.bo.logic.common.FormulaUtility;
26  import org.qedeq.kernel.bo.logic.common.LogicalCheckExceptionList;
27  import org.qedeq.kernel.bo.logic.common.Operators;
28  import org.qedeq.kernel.bo.logic.common.ReferenceResolver;
29  import org.qedeq.kernel.bo.logic.proof.common.ProofChecker;
30  import org.qedeq.kernel.bo.logic.proof.common.RuleChecker;
31  import org.qedeq.kernel.se.base.list.Element;
32  import org.qedeq.kernel.se.base.list.ElementList;
33  import org.qedeq.kernel.se.base.module.Add;
34  import org.qedeq.kernel.se.base.module.Existential;
35  import org.qedeq.kernel.se.base.module.FormalProofLine;
36  import org.qedeq.kernel.se.base.module.FormalProofLineList;
37  import org.qedeq.kernel.se.base.module.ModusPonens;
38  import org.qedeq.kernel.se.base.module.Reason;
39  import org.qedeq.kernel.se.base.module.Rename;
40  import org.qedeq.kernel.se.base.module.Rule;
41  import org.qedeq.kernel.se.base.module.SubstFree;
42  import org.qedeq.kernel.se.base.module.SubstFunc;
43  import org.qedeq.kernel.se.base.module.SubstPred;
44  import org.qedeq.kernel.se.base.module.Universal;
45  import org.qedeq.kernel.se.common.ModuleContext;
46  import org.qedeq.kernel.se.common.RuleKey;
47  import org.qedeq.kernel.se.dto.list.DefaultElementList;
48  import org.qedeq.kernel.se.dto.list.ElementSet;
49  
50  
51  /**
52   * Formal proof checker for basic rules.
53   *
54   * @author  Michael Meyling
55   */
56  public class ProofChecker1Impl implements ProofChecker {
57  
58      /** Proof we want to check. */
59      private FormalProofLineList proof;
60  
61      /** Module context of proof line list. */
62      private ModuleContext moduleContext;
63  
64      /** Current context. */
65      private ModuleContext currentContext;
66  
67      /** Resolver for external references. */
68      private ReferenceResolver resolver;
69  
70      /** All exceptions that occurred during checking. */
71      private LogicalCheckExceptionList exceptions;
72  
73      /** Array with proof status for each proof line. */
74      private boolean[] lineProved;
75  
76      /** Maps local proof line labels to local line number Integers. */
77      private Map label2line;
78  
79      /** Rule version we can check. */
80      private final Version ruleVersion;
81  
82      /** Rule existence checker. */
83      private RuleChecker checker;
84  
85      /**
86       * Constructor.
87       *
88       */
89      public ProofChecker1Impl() {
90          this.ruleVersion = new Version("0.01.00");
91      }
92  
93      public LogicalCheckExceptionList checkRule(final Rule rule,
94              final ModuleContext context, final RuleChecker checker,
95              final ReferenceResolver resolver) {
96          exceptions = new LogicalCheckExceptionList();
97          final RuleKey ruleKey = new RuleKey(rule.getName(), rule.getVersion());
98          if (rule.getVersion() == null || !ruleVersion.equals(rule.getVersion())) {
99              final ProofCheckException ex = new ProofCheckException(
100                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
101                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + ruleKey
102                 + BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT2 + "{" + ruleVersion + "}",
103                 context);
104             exceptions.add(ex);
105         }
106         return exceptions;
107     }
108 
109     public LogicalCheckExceptionList checkProof(final Element formula,
110             final FormalProofLineList proof,
111             final RuleChecker checker,
112             final ModuleContext moduleContext,
113             final ReferenceResolver resolver) {
114         this.proof = proof;
115         this.resolver = resolver;
116         this.moduleContext = moduleContext;
117         this.checker = checker;
118         // use copy constructor for changing context
119         currentContext = new ModuleContext(moduleContext);
120         exceptions = new LogicalCheckExceptionList();
121         final String context = moduleContext.getLocationWithinModule();
122         lineProved = new boolean[proof.size()];
123         label2line = new HashMap();
124         for (int i = 0; i < proof.size(); i++) {
125             boolean ok = true;
126             setLocationWithinModule(context + ".get("  + i + ")");
127             final FormalProofLine line = proof.get(i);
128             if (line == null || line.getFormula() == null
129                     || line.getFormula().getElement() == null) {
130                 ok = false;
131                 handleProofCheckException(
132                     BasicProofErrors.PROOF_LINE_MUST_NOT_BE_NULL_CODE,
133                     BasicProofErrors.PROOF_LINE_MUST_NOT_BE_NULL_TEXT,
134                     getCurrentContext());
135                 continue;
136             }
137             setLocationWithinModule(context + ".get(" + i + ").getReason()");
138             final Reason reason = line.getReason();
139             if (reason == null) {
140                 ok = false;
141                 handleProofCheckException(
142                     BasicProofErrors.REASON_MUST_NOT_BE_NULL_CODE,
143                     BasicProofErrors.REASON_MUST_NOT_BE_NULL_TEXT,
144                     getCurrentContext());
145                 continue;
146             }
147             if (line.getLabel() != null && line.getLabel().length() > 0) {
148                 final Integer n = (Integer) label2line.get(line.getLabel());
149                 if (n != null) {
150                     final ModuleContext lc = new ModuleContext(moduleContext.getModuleLocation(),
151                         moduleContext.getLocationWithinModule() + ".get("
152                         + label2line.get(line.getLabel())
153                         + ").getLabel()");
154                     setLocationWithinModule(context + ".get("  + i + ").getLabel()");
155                     handleProofCheckException(
156                         BasicProofErrors.LOCAL_LABEL_ALREADY_EXISTS_CODE,
157                         BasicProofErrors.LOCAL_LABEL_ALREADY_EXISTS_TEXT
158                         + line.getLabel(),
159                         getCurrentContext(),
160                         lc);
161                 }
162                 label2line.put(line.getLabel(), new Integer(i));
163             }
164             // check if only basis rules are used
165             // TODO 20110316 m31: this is a dirty trick to get the context of the reason
166             //                    perhaps we can solve this more elegantly?
167             String getReason = ".get" + StringUtility.getClassName(reason.getClass());
168             if (getReason.endsWith("Vo")) {
169                 getReason = getReason.substring(0, getReason.length() - 2) + "()";
170                 setLocationWithinModule(context + ".get("  + i + ").getReason()"
171                     + getReason);
172             }
173             if (reason instanceof Add) {
174                 ok = check((Add) reason, i, line.getFormula().getElement());
175             } else if (reason instanceof Rename) {
176                 ok = check((Rename) reason, i, line.getFormula().getElement());
177             } else if (reason instanceof ModusPonens) {
178                 ok = check((ModusPonens) reason, i, line.getFormula().getElement());
179             } else if (reason instanceof SubstFree) {
180                 ok = check((SubstFree) reason, i, line.getFormula().getElement());
181             } else if (reason instanceof SubstPred) {
182                 ok = check((SubstPred) reason, i, line.getFormula().getElement());
183             } else if (reason instanceof SubstFunc) {
184                 ok = check((SubstFunc) reason, i, line.getFormula().getElement());
185             } else if (reason instanceof Universal) {
186                 ok = check((Universal) reason, i, line.getFormula().getElement());
187             } else if (reason instanceof Existential) {
188                 ok = check((Existential) reason, i, line.getFormula().getElement());
189             } else {
190                 ok = false;
191                 handleProofCheckException(
192                     BasicProofErrors.THIS_IS_NO_ALLOWED_BASIC_REASON_CODE,
193                     BasicProofErrors.THIS_IS_NO_ALLOWED_BASIC_REASON_TEXT
194                     + reason.getName(),
195                     getCurrentContext());
196             }
197             lineProved[i] = ok;
198             // check if last proof line is identical with proposition formula
199             if (i == proof.size() - 1) {
200                 if (!formula.equals(line.getFormula().getElement())) {
201                     handleProofCheckException(
202                         BasicProofErrors.LAST_PROOF_LINE_MUST_BE_IDENTICAL_TO_PROPOSITION_CODE,
203                         BasicProofErrors.LAST_PROOF_LINE_MUST_BE_IDENTICAL_TO_PROPOSITION_TEXT
204                         + reason.getName(),
205                         getModuleContextOfProofLineFormula(i));
206                 }
207             }
208         }
209         return exceptions;
210     }
211 
212     private boolean check(final Add add, final int i, final Element element) {
213         final String context = currentContext.getLocationWithinModule();
214         boolean ok = true;
215         if (add.getReference() == null) {
216             ok = false;
217             setLocationWithinModule(context + ".getReference()");
218             handleProofCheckException(
219                 BasicProofErrors.REFERENCE_TO_PROVED_FORMULA_IS_MISSING_CODE,
220                 BasicProofErrors.REFERENCE_TO_PROVED_FORMULA_IS_MISSING_TEXT,
221                 getCurrentContext());
222             return ok;
223         }
224         if (!resolver.isProvedFormula(add.getReference())) {
225             ok = false;
226             setLocationWithinModule(context + ".getReference()");
227             handleProofCheckException(
228                 BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
229                 BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
230                 + add.getReference(),
231                 getCurrentContext());
232             return ok;
233         }
234         final Element expected = resolver.getNormalizedReferenceFormula(add.getReference());
235         final Element current = resolver.getNormalizedFormula(element);
236         if (!EqualsUtility.equals(expected, current)) {
237             ok = false;
238             handleProofCheckException(
239                 BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
240                 BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
241                 + add.getReference(),
242                 getDiffModuleContextOfProofLineFormula(i, expected));
243             return ok;
244         }
245         final RuleKey defined = checker.getRule(add.getName());
246         if (defined == null) {
247             ok = false;
248             handleProofCheckException(
249                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
250                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
251                 + add.getName(),
252                 getCurrentContext());
253             return ok;
254         } else if (!ruleVersion.equals(defined.getVersion())) {
255             ok = false;
256             handleProofCheckException(
257                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
258                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
259                 getCurrentContext());
260             return ok;
261         }
262         return ok;
263     }
264 
265     private boolean check(final Rename rename, final int i, final Element element) {
266         final String context = currentContext.getLocationWithinModule();
267         boolean ok = true;
268         final Integer n = (Integer) label2line.get(rename.getReference());
269         if (n == null) {
270             ok = false;
271             setLocationWithinModule(context + ".getReference()");
272             handleProofCheckException(
273                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
274                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
275                 + rename.getReference(),
276                 getCurrentContext());
277 //        } else if (!lineProved[n.intValue()]) {
278 //            ok = false;
279 //            setLocationWithinModule(context + ".getReference()");
280 //            handleProofCheckException(
281 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
282 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
283 //                + rename.getReference(),
284 //                getCurrentContext());
285         } else {
286             final Element f = getNormalizedProofLine(n);
287             final Element expected = FormulaUtility.replaceSubjectVariableQuantifier(
288                 rename.getOriginalSubjectVariable(),
289                 rename.getReplacementSubjectVariable(), f, rename.getOccurrence(),
290                 new Enumerator());
291             final Element current = resolver.getNormalizedFormula(element);
292             if (!EqualsUtility.equals(expected, current)) {
293                 ok = false;
294                 handleProofCheckException(
295                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
296                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
297                     + rename.getReference(),
298                     getDiffModuleContextOfProofLineFormula(i, expected));
299             } else {
300                 ok = true;
301             }
302         }
303         final RuleKey defined = checker.getRule(rename.getName());
304         if (defined == null) {
305             ok = false;
306             handleProofCheckException(
307                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
308                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
309                 + rename.getName(),
310                 getCurrentContext());
311             return ok;
312         } else if (!ruleVersion.equals(defined.getVersion())) {
313             ok = false;
314             handleProofCheckException(
315                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
316                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
317                 getCurrentContext());
318             return ok;
319         }
320         return ok;
321     }
322 
323     private boolean check(final SubstFree substFree, final int i, final Element element) {
324         final String context = currentContext.getLocationWithinModule();
325         boolean ok = true;
326         final Integer n = (Integer) label2line.get(substFree.getReference());
327         if (n == null) {
328             ok = false;
329             setLocationWithinModule(context + ".getReference()");
330             handleProofCheckException(
331                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
332                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
333                 + substFree.getReference(),
334                 getCurrentContext());
335 //        } else if (!lineProved[n.intValue()]) {
336 //            ok = false;
337 //            setLocationWithinModule(context + ".getReference()");
338 //            handleProofCheckException(
339 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
340 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
341 //                + substfree.getReference(),
342 //                getCurrentContext());
343         } else {
344             final Element f = getNormalizedProofLine(n);
345             final Element current = resolver.getNormalizedFormula(element);
346             final Element expected = f.replace(substFree.getSubjectVariable(),
347                 resolver.getNormalizedFormula(substFree.getSubstituteTerm()));
348             if (!EqualsUtility.equals(current, expected)) {
349                 ok = false;
350                 handleProofCheckException(
351                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
352                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
353                     + substFree.getReference(),
354                     getDiffModuleContextOfProofLineFormula(i, expected));
355                 return ok;
356             }
357         }
358         final RuleKey defined = checker.getRule(substFree.getName());
359         if (defined == null) {
360             ok = false;
361             handleProofCheckException(
362                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
363                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
364                 + substFree.getName(),
365                 getCurrentContext());
366             return ok;
367         } else if (!ruleVersion.equals(defined.getVersion())) {
368             ok = false;
369             handleProofCheckException(
370                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
371                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
372                 getCurrentContext());
373             return ok;
374         }
375         return ok;
376     }
377 
378     private boolean check(final SubstPred substPred, final int i, final Element element) {
379         final String context = currentContext.getLocationWithinModule();
380         boolean ok = true;
381         final Integer n = (Integer) label2line.get(substPred.getReference());
382         if (n == null) {
383             ok = false;
384             setLocationWithinModule(context + ".getReference()");
385             handleProofCheckException(
386                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
387                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
388                 + substPred.getReference(),
389                 getCurrentContext());
390 //        } else if (!lineProved[n.intValue()]) {
391 //            ok = false;
392 //            setLocationWithinModule(context + ".getReference()");
393 //            handleProofCheckException(
394 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
395 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
396 //                + substpred.getReference(),
397 //                getCurrentContext());
398         } else {
399             final Element alpha = getNormalizedProofLine(n);
400             final Element current = resolver.getNormalizedFormula(element);
401             if (substPred.getSubstituteFormula() == null) {
402                 ok = false;
403                 handleProofCheckException(
404                     BasicProofErrors.SUBSTITUTION_FORMULA_IS_MISSING_CODE,
405                     BasicProofErrors.SUBSTITUTION_FORMULA_IS_MISSING_TEXT,
406                     getCurrentContext());
407                 return ok;
408             }
409             final Element p = resolver.getNormalizedFormula(substPred.getPredicateVariable());
410             final Element beta = resolver.getNormalizedFormula(substPred.getSubstituteFormula());
411             final Element expected = FormulaUtility.replaceOperatorVariable(alpha, p, beta);
412             if (!EqualsUtility.equals(current, expected)) {
413                 ok = false;
414                 handleProofCheckException(
415                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
416                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
417                     + substPred.getReference(),
418                     getDiffModuleContextOfProofLineFormula(i, expected));
419                 return ok;
420             }
421             // check precondition: predicate variable p must have n pairwise different free subject
422             // variables as arguments
423             final ElementSet predFree = FormulaUtility.getFreeSubjectVariables(p);
424             if (predFree.size() != p.getList().size() - 1) {
425                 ok = false;
426                 setLocationWithinModule(context + ".getPredicateVariable()");
427                 handleProofCheckException(
428                     BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_CODE,
429                     BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_TEXT,
430                     getDiffModuleContextOfProofLineFormula(i, expected));
431                 return ok;
432             }
433             for (int j = 1; j < p.getList().size(); j++) {
434                 if (!FormulaUtility.isSubjectVariable(p.getList().getElement(j))) {
435                     ok = false;
436                     setLocationWithinModule(context + ".getPredicateVariable()");
437                     handleProofCheckException(
438                         BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_CODE,
439                         BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_TEXT,
440                         getCurrentContext());
441                     return ok;
442                 }
443             }
444             // check precondition: the free variables of $\beta(x_1, \ldots, x_n)$ without
445             // $x_1$, \ldots, $x_n$ do not occur as bound variables in $\alpha$
446             final ElementSet fBound = FormulaUtility.getBoundSubjectVariables(alpha);
447             final ElementSet betaFree = FormulaUtility.getFreeSubjectVariables(beta);
448             if (!fBound.intersection(betaFree.minus(predFree)).isEmpty()) {
449                 ok = false;
450                 setLocationWithinModule(context + ".getSubstituteFormula()");
451                 handleProofCheckException(
452                     BasicProofErrors.FREE_SUBJECT_VARIABLES_SHOULD_NOT_GET_BOUND_CODE,
453                     BasicProofErrors.FREE_SUBJECT_VARIABLES_SHOULD_NOT_GET_BOUND_TEXT,
454                     getCurrentContext());
455                 return ok;
456             }
457             // check precondition: each occurrence of $p(t_1, \ldots, t_n)$ in $\alpha$ contains
458             // no bound variable of $\beta(x_1, \ldots, x_n)$
459             final ElementSet betaBound = FormulaUtility.getBoundSubjectVariables(beta);
460             if (!FormulaUtility.testOperatorVariable(alpha, p, betaBound)) {
461                 ok = false;
462                 setLocationWithinModule(context + ".getSubstituteFormula()");
463                 handleProofCheckException(
464                     BasicProofErrors.SUBSTITUTION_LOCATION_CONTAINS_BOUND_SUBJECT_VARIABLE_CODE,
465                     BasicProofErrors.SUBSTITUTION_LOCATION_CONTAINS_BOUND_SUBJECT_VARIABLE_TEXT,
466                     getCurrentContext());
467                 return ok;
468             }
469             // check precondition: resulting formula is well formed was already done by well formed
470             // checker
471         }
472         final RuleKey defined = checker.getRule(substPred.getName());
473         if (defined == null) {
474             ok = false;
475             handleProofCheckException(
476                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
477                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
478                 + substPred.getName(),
479                 getCurrentContext());
480             return ok;
481         } else if (!ruleVersion.equals(defined.getVersion())) {
482             ok = false;
483             handleProofCheckException(
484                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
485                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
486                 getCurrentContext());
487             return ok;
488         }
489         return ok;
490     }
491 
492     private boolean check(final SubstFunc substFunc, final int i, final Element element) {
493         final String context = currentContext.getLocationWithinModule();
494         boolean ok = true;
495         final Integer n = (Integer) label2line.get(substFunc.getReference());
496         if (n == null) {
497             ok = false;
498             setLocationWithinModule(context + ".getReference()");
499             handleProofCheckException(
500                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
501                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
502                 + substFunc.getReference(),
503                 getCurrentContext());
504 //        } else if (!lineProved[n.intValue()]) {
505 //            ok = false;
506 //            setLocationWithinModule(context + ".getReference()");
507 //            handleProofCheckException(
508 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
509 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
510 //                + substfunc.getReference(),
511 //                getCurrentContext());
512         } else {
513             final Element alpha = getNormalizedProofLine(n);
514             final Element current = resolver.getNormalizedFormula(element);
515             if (substFunc.getSubstituteTerm() == null) {
516                 ok = false;
517                 handleProofCheckException(
518                     BasicProofErrors.SUBSTITUTION_FORMULA_IS_MISSING_CODE,
519                     BasicProofErrors.SUBSTITUTION_FORMULA_IS_MISSING_TEXT,
520                     getCurrentContext());
521                 return ok;
522             }
523             final Element sigma = resolver.getNormalizedFormula(substFunc.getFunctionVariable());
524             final Element tau = resolver.getNormalizedFormula(substFunc.getSubstituteTerm());
525             final Element expected = FormulaUtility.replaceOperatorVariable(alpha, sigma, tau);
526             if (!EqualsUtility.equals(current, expected)) {
527                 ok = false;
528                 handleProofCheckException(
529                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
530                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
531                     + substFunc.getReference(),
532                     getDiffModuleContextOfProofLineFormula(i, expected));
533                 return ok;
534             }
535             // check precondition: function variable $\sigma$ must have n pairwise different free
536             // subject variables as arguments
537             final ElementSet funcFree = FormulaUtility.getFreeSubjectVariables(sigma);
538             if (funcFree.size() != sigma.getList().size() - 1) {
539                 ok = false;
540                 setLocationWithinModule(context + ".getPredicateVariable()");
541                 handleProofCheckException(
542                     BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_CODE,
543                     BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_TEXT,
544                     getDiffModuleContextOfProofLineFormula(i, expected));
545                 return ok;
546             }
547             for (int j = 1; j < sigma.getList().size(); j++) {
548                 if (!FormulaUtility.isSubjectVariable(sigma.getList().getElement(j))) {
549                     ok = false;
550                     setLocationWithinModule(context + ".getPredicateVariable()");
551                     handleProofCheckException(
552                         BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_CODE,
553                         BasicProofErrors.ONLY_FREE_SUBJECT_VARIABLES_ALLOWED_TEXT,
554                         getCurrentContext());
555                     return ok;
556                 }
557             }
558             // check precondition: the free variables of $\tau(x_1, \ldots, x_n)$
559             // without $x_1$, \ldots, $x_n$ do not occur as bound variables in $\alpha$
560             final ElementSet fBound = FormulaUtility.getBoundSubjectVariables(alpha);
561             final ElementSet sigmaFree = FormulaUtility.getFreeSubjectVariables(tau);
562             if (!fBound.intersection(sigmaFree.minus(funcFree)).isEmpty()) {
563                 ok = false;
564                 setLocationWithinModule(context + ".getSubstituteFormula()");
565                 handleProofCheckException(
566                     BasicProofErrors.FREE_SUBJECT_VARIABLES_SHOULD_NOT_GET_BOUND_CODE,
567                     BasicProofErrors.FREE_SUBJECT_VARIABLES_SHOULD_NOT_GET_BOUND_TEXT,
568                     getCurrentContext());
569                 return ok;
570             }
571             // check precondition: each occurrence of $\sigma(t_1, \ldots, t_n)$ in $\alpha$
572             // contains no bound variable of $\tau(x_1, \ldots, x_n)$
573             final ElementSet sigmaBound = FormulaUtility.getBoundSubjectVariables(tau);
574             if (!FormulaUtility.testOperatorVariable(alpha, sigma, sigmaBound)) {
575                 ok = false;
576                 setLocationWithinModule(context + ".getSubstituteFormula()");
577                 handleProofCheckException(
578                     BasicProofErrors.SUBSTITUTION_LOCATION_CONTAINS_BOUND_SUBJECT_VARIABLE_CODE,
579                     BasicProofErrors.SUBSTITUTION_LOCATION_CONTAINS_BOUND_SUBJECT_VARIABLE_TEXT,
580                     getCurrentContext());
581                 return ok;
582             }
583             // check precondition: resulting formula is well formed was already done by well formed
584             // checker
585         }
586         final RuleKey defined = checker.getRule(substFunc.getName());
587         if (defined == null) {
588             ok = false;
589             handleProofCheckException(
590                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
591                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
592                 + substFunc.getName(),
593                 getCurrentContext());
594             return ok;
595         } else if (!ruleVersion.equals(defined.getVersion())) {
596             ok = false;
597             handleProofCheckException(
598                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
599                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
600                 getCurrentContext());
601             return ok;
602         }
603         return ok;
604     }
605 
606     private boolean check(final ModusPonens mp, final int i, final Element element) {
607         final String context = currentContext.getLocationWithinModule();
608         boolean ok = true;
609         final Integer n1 = (Integer) label2line.get(mp.getReference1());
610         if (n1 == null) {
611             ok = false;
612             setLocationWithinModule(context + ".getReference1()");
613             handleProofCheckException(
614                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
615                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
616                 + mp.getReference1(),
617                 getCurrentContext());
618 //        } else if (!lineProved[n1.intValue()]) {
619 //            ok = false;
620 //            setLocationWithinModule(context + ".getReference1()");
621 //            handleProofCheckException(
622 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
623 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
624 //                + mp.getReference1(),
625 //                getCurrentContext());
626         }
627         final Integer n2 = (Integer) label2line.get(mp.getReference2());
628         if (n2 == null) {
629             ok = false;
630             setLocationWithinModule(context + ".getReference2()");
631             handleProofCheckException(
632                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
633                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
634                 + mp.getReference2(),
635                 getCurrentContext());
636 //        } else if (!lineProved[n2.intValue()]) {
637 //            ok = false;
638 //            setLocationWithinModule(context + ".getReference2()");
639 //            handleProofCheckException(
640 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
641 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
642 //                + mp.getReference1(),
643 //                getCurrentContext());
644         }
645         if (ok) {
646             final Element f1 = getNormalizedProofLine(n1);
647             final Element f2 = getNormalizedProofLine(n2);
648             final Element current = getNormalizedProofLine(i);
649             if (!FormulaUtility.isImplication(f1)) {
650                 ok = false;
651                 setLocationWithinModule(context + ".getReference1()");
652                 handleProofCheckException(
653                     BasicProofErrors.IMPLICATION_EXPECTED_CODE,
654                     BasicProofErrors.IMPLICATION_EXPECTED_TEXT
655                     + mp.getReference1(),
656                     getCurrentContext());
657             } else if (!f2.equals(f1.getList().getElement(0))) {
658                 ok = false;
659                 setLocationWithinModule(context + ".getReference2()");
660                 handleProofCheckException(
661                     BasicProofErrors.MUST_BE_HYPOTHESIS_OF_FIRST_REFERENCE_CODE,
662                     BasicProofErrors.MUST_BE_HYPOTHESIS_OF_FIRST_REFERENCE_TEXT
663                     + mp.getReference2(),
664                     getCurrentContext(),
665                     getModuleContextOfProofLineFormula(n1.intValue()));
666             } else if (!current.equals(f1.getList().getElement(1))) {
667                 ok = false;
668                 setLocationWithinModule(context + ".getReference1()");
669                 handleProofCheckException(
670                     BasicProofErrors.CURRENT_MUST_BE_CONCLUSION_CODE,
671                     BasicProofErrors.CURRENT_MUST_BE_CONCLUSION_TEXT
672                     + mp.getReference1(),
673                     getCurrentContext(),
674                     getModuleContextOfProofLineFormula(n1.intValue()));
675             } else {
676                 ok = true;
677             }
678         }
679         final RuleKey defined = checker.getRule(mp.getName());
680         if (defined == null) {
681             ok = false;
682             handleProofCheckException(
683                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
684                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
685                 + mp.getName(),
686                 getCurrentContext());
687             return ok;
688         } else if (!ruleVersion.equals(defined.getVersion())) {
689             ok = false;
690             handleProofCheckException(
691                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
692                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
693                 getCurrentContext());
694             return ok;
695         }
696         return ok;
697     }
698 
699     private boolean check(final Universal universal, final int i, final Element element) {
700         final String context = currentContext.getLocationWithinModule();
701         boolean ok = true;
702         final Integer n = (Integer) label2line.get(universal.getReference());
703         if (n == null) {
704             ok = false;
705             setLocationWithinModule(context + ".getReference()");
706             handleProofCheckException(
707                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
708                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
709                 + universal.getReference(),
710                 getCurrentContext());
711 //        } else if (!lineProved[n.intValue()]) {
712 //            ok = false;
713 //            setLocationWithinModule(context + ".getReference()");
714 //            handleProofCheckException(
715 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
716 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
717 //                + universal.getReference(),
718 //                getCurrentContext());
719         } else {
720             final Element f = getNormalizedProofLine(n);
721             final Element current = resolver.getNormalizedFormula(element);
722             if (!FormulaUtility.isImplication(f)) {
723                 ok = false;
724                 setLocationWithinModule(context + ".getReference()");
725                 handleProofCheckException(
726                     BasicProofErrors.IMPLICATION_EXPECTED_CODE,
727                     BasicProofErrors.IMPLICATION_EXPECTED_TEXT
728                     + universal.getReference(),
729                     getCurrentContext());
730                 return ok;
731             }
732             if (!FormulaUtility.isSubjectVariable(universal.getSubjectVariable())) {
733                 ok = false;
734                 setLocationWithinModule(context + ".getSubjectVariable()");
735                 handleProofCheckException(
736                     BasicProofErrors.SUBJECT_VARIABLE_IS_MISSING_CODE,
737                     BasicProofErrors.SUBJECT_VARIABLE_IS_MISSING_TEXT,
738                     getCurrentContext());
739                 return ok;
740             }
741             final DefaultElementList expected = new DefaultElementList(Operators.IMPLICATION_OPERATOR);
742             expected.add((f.getList().getElement(0)));
743             final ElementList uni = new DefaultElementList(Operators.UNIVERSAL_QUANTIFIER_OPERATOR);
744             uni.add(universal.getSubjectVariable());
745             uni.add(f.getList().getElement(1));
746             expected.add(uni);
747             if (!EqualsUtility.equals(current, expected)) {
748                 ok = false;
749                 handleProofCheckException(
750                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
751                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
752                     + universal.getReference(),
753                     getDiffModuleContextOfProofLineFormula(i, expected));
754                 return ok;
755             }
756         }
757         final RuleKey defined = checker.getRule(universal.getName());
758         if (defined == null) {
759             ok = false;
760             handleProofCheckException(
761                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
762                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
763                 + universal.getName(),
764                 getCurrentContext());
765             return ok;
766         } else if (!ruleVersion.equals(defined.getVersion())) {
767             ok = false;
768             handleProofCheckException(
769                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
770                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
771                 getCurrentContext());
772             return ok;
773         }
774         return ok;
775     }
776 
777     private boolean check(final Existential existential, final int i, final Element element) {
778         final String context = currentContext.getLocationWithinModule();
779         boolean ok = true;
780         final Integer n = (Integer) label2line.get(existential.getReference());
781         if (n == null) {
782             ok = false;
783             setLocationWithinModule(context + ".getReference()");
784             handleProofCheckException(
785                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_CODE,
786                 BasicProofErrors.SUCH_A_LOCAL_LABEL_DOESNT_EXIST_TEXT
787                 + existential.getReference(),
788                 getCurrentContext());
789 //        } else if (!lineProved[n.intValue()]) {
790 //            ok = false;
791 //            setLocationWithinModule(context + ".getReference()");
792 //            handleProofCheckException(
793 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_CODE,
794 //                BasicProofErrors.THIS_IS_NO_REFERENCE_TO_A_PROVED_FORMULA_TEXT
795 //                + existential.getReference(),
796 //                getCurrentContext());
797         } else {
798             final Element f = getNormalizedProofLine(n);
799             final Element current = resolver.getNormalizedFormula(element);
800             if (!FormulaUtility.isImplication(f)) {
801                 ok = false;
802                 setLocationWithinModule(context + ".getReference()");
803                 handleProofCheckException(
804                     BasicProofErrors.IMPLICATION_EXPECTED_CODE,
805                     BasicProofErrors.IMPLICATION_EXPECTED_TEXT
806                     + existential.getReference(),
807                     getCurrentContext());
808                 return ok;
809             }
810             if (!FormulaUtility.isSubjectVariable(existential.getSubjectVariable())) {
811                 ok = false;
812                 setLocationWithinModule(context + ".getSubjectVariable()");
813                 handleProofCheckException(
814                     BasicProofErrors.SUBJECT_VARIABLE_IS_MISSING_CODE,
815                     BasicProofErrors.SUBJECT_VARIABLE_IS_MISSING_TEXT,
816                     getCurrentContext());
817                 return ok;
818             }
819             final DefaultElementList expected = new DefaultElementList(f.getList().getOperator());
820             final ElementList exi = new DefaultElementList(
821                 Operators.EXISTENTIAL_QUANTIFIER_OPERATOR);
822             exi.add(existential.getSubjectVariable());
823             exi.add(f.getList().getElement(0));
824             expected.add(exi);
825             expected.add((f.getList().getElement(1)));
826             if (!EqualsUtility.equals(current, expected)) {
827                 ok = false;
828                 handleProofCheckException(
829                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_CODE,
830                     BasicProofErrors.EXPECTED_FORMULA_DIFFERS_TEXT
831                     + existential.getReference(),
832                     getDiffModuleContextOfProofLineFormula(i, expected));
833                 return ok;
834             }
835         }
836         final RuleKey defined = checker.getRule(existential.getName());
837         if (defined == null) {
838             ok = false;
839             handleProofCheckException(
840                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_CODE,
841                 BasicProofErrors.PROOF_METHOD_WAS_NOT_DEFINED_YET_TEXT
842                 + existential.getName(),
843                 getCurrentContext());
844             return ok;
845         } else if (!ruleVersion.equals(defined.getVersion())) {
846             ok = false;
847             handleProofCheckException(
848                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_CODE,
849                 BasicProofErrors.PROOF_METHOD_IS_NOT_SUPPORTED_TEXT + defined.getVersion(),
850                 getCurrentContext());
851             return ok;
852         }
853         return ok;
854     }
855 
856     private ModuleContext getModuleContextOfProofLineFormula(final int i) {
857         return new ModuleContext(moduleContext.getModuleLocation(),
858             moduleContext.getLocationWithinModule() + ".get(" + i
859             + ").getFormula().getElement()");
860     }
861 
862     private ModuleContext getDiffModuleContextOfProofLineFormula(final int i,
863             final Element expected) {
864         final String diff = FormulaUtility.getDifferenceLocation(
865             proof.get(i).getFormula().getElement(),  expected);
866         return new ModuleContext(moduleContext.getModuleLocation(),
867             moduleContext.getLocationWithinModule() + ".get(" + i
868             + ").getFormula().getElement()" + diff);
869     }
870 
871     private Element getNormalizedProofLine(final Integer n) {
872         if (n == null) {
873             return null;
874         }
875         return getNormalizedProofLine(n.intValue());
876     }
877 
878     private Element getNormalizedProofLine(final int i) {
879         if (i < 0 || i >= proof.size()) {
880             return null;
881         }
882         return resolver.getNormalizedFormula(proof.get(i).getFormula().getElement());
883     }
884 
885     /**
886      * Add new {@link ProofCheckException} to exception list.
887      *
888      * @param code      Error code.
889      * @param msg       Error message.
890      * @param context   Error context.
891      */
892     private void handleProofCheckException(final int code, final String msg,
893             final ModuleContext context) {
894 //        System.out.println(context);
895 //        System.setProperty("qedeq.test.xmlLocationFailures", "true");
896         final ProofCheckException ex = new ProofCheckException(code, msg, context);
897         exceptions.add(ex);
898     }
899 
900     /**
901      * Add new {@link ProofCheckException} to exception list.
902      *
903      * @param code              Error code.
904      * @param msg               Error message.
905      * @param context           Error context.
906      * @param referenceContext  Reference context.
907      */
908     private void handleProofCheckException(final int code, final String msg,
909             final ModuleContext context, final ModuleContext referenceContext) {
910 //        System.out.println(context);
911 //        System.setProperty("qedeq.test.xmlLocationFailures", "true");
912         final ProofCheckException ex = new ProofCheckException(code, msg, null, context,
913             referenceContext);
914         exceptions.add(ex);
915     }
916 
917     /**
918      * Set location information where are we within the original module.
919      *
920      * @param   locationWithinModule    Location within module.
921      */
922     protected void setLocationWithinModule(final String locationWithinModule) {
923         getCurrentContext().setLocationWithinModule(locationWithinModule);
924     }
925 
926     /**
927      * Get current context within original.
928      *
929      * @return  Current context.
930      */
931     protected final ModuleContext getCurrentContext() {
932         return currentContext;
933     }
934 
935 
936 }