Clover Coverage Report
Coverage timestamp: Fri Feb 14 2014 07:28:57 UTC
../../../../../../img/srcFileCovDistChart7.png 74% of files have more coverage
197   513   82   7.3
90   434   0.42   27
27     3.04  
1    
 
  FormalProofCheckerExecutor       Line # 71 197 82 62.1% 0.6210191
 
  (8)
 
1    /* This file is part of the project "Hilbert II" - 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.service.logic;
17   
18   
19    import org.qedeq.base.io.Parameters;
20    import org.qedeq.base.io.Version;
21    import org.qedeq.base.trace.Trace;
22    import org.qedeq.base.utility.StringUtility;
23    import org.qedeq.kernel.bo.log.QedeqLog;
24    import org.qedeq.kernel.bo.logic.ProofCheckerFactoryImpl;
25    import org.qedeq.kernel.bo.logic.common.FormulaUtility;
26    import org.qedeq.kernel.bo.logic.common.FunctionKey;
27    import org.qedeq.kernel.bo.logic.common.LogicalCheckExceptionList;
28    import org.qedeq.kernel.bo.logic.common.PredicateKey;
29    import org.qedeq.kernel.bo.logic.common.ReferenceResolver;
30    import org.qedeq.kernel.bo.logic.proof.checker.ProofCheckException;
31    import org.qedeq.kernel.bo.logic.proof.common.ProofCheckerFactory;
32    import org.qedeq.kernel.bo.logic.proof.common.RuleChecker;
33    import org.qedeq.kernel.bo.module.InternalModuleServiceCall;
34    import org.qedeq.kernel.bo.module.KernelModuleReferenceList;
35    import org.qedeq.kernel.bo.module.KernelQedeqBo;
36    import org.qedeq.kernel.bo.module.Reference;
37    import org.qedeq.kernel.bo.service.basis.ControlVisitor;
38    import org.qedeq.kernel.bo.service.basis.ModuleServicePluginExecutor;
39    import org.qedeq.kernel.se.base.list.Element;
40    import org.qedeq.kernel.se.base.list.ElementList;
41    import org.qedeq.kernel.se.base.module.Axiom;
42    import org.qedeq.kernel.se.base.module.ChangedRule;
43    import org.qedeq.kernel.se.base.module.ChangedRuleList;
44    import org.qedeq.kernel.se.base.module.FormalProof;
45    import org.qedeq.kernel.se.base.module.FormalProofLineList;
46    import org.qedeq.kernel.se.base.module.FunctionDefinition;
47    import org.qedeq.kernel.se.base.module.Header;
48    import org.qedeq.kernel.se.base.module.InitialFunctionDefinition;
49    import org.qedeq.kernel.se.base.module.InitialPredicateDefinition;
50    import org.qedeq.kernel.se.base.module.PredicateDefinition;
51    import org.qedeq.kernel.se.base.module.Proposition;
52    import org.qedeq.kernel.se.base.module.Rule;
53    import org.qedeq.kernel.se.common.CheckLevel;
54    import org.qedeq.kernel.se.common.ModuleContext;
55    import org.qedeq.kernel.se.common.ModuleDataException;
56    import org.qedeq.kernel.se.common.ModuleService;
57    import org.qedeq.kernel.se.common.RuleKey;
58    import org.qedeq.kernel.se.common.SourceFileException;
59    import org.qedeq.kernel.se.common.SourceFileExceptionList;
60    import org.qedeq.kernel.se.dto.list.DefaultAtom;
61    import org.qedeq.kernel.se.dto.list.DefaultElementList;
62    import org.qedeq.kernel.se.state.FormallyProvedState;
63    import org.qedeq.kernel.se.visitor.InterruptException;
64   
65   
66    /**
67    * Checks if all propositions have a correct formal proof.
68    *
69    * @author Michael Meyling
70    */
 
71    public final class FormalProofCheckerExecutor extends ControlVisitor implements ModuleServicePluginExecutor,
72    ReferenceResolver, RuleChecker {
73   
74    /** This class. */
75    private static final Class CLASS = FormalProofCheckerExecutor.class;
76   
77    /** Factory for generating new checkers. */
78    private ProofCheckerFactory checkerFactory = null;
79   
80    /** Rule version the module claims to use at maximum. */
81    private Version ruleVersion;
82   
83    /**
84    * Constructor.
85    *
86    * @param plugin This plugin we work for.
87    * @param qedeq QEDEQ BO object.
88    * @param parameters Parameters.
89    */
 
90  11 toggle FormalProofCheckerExecutor(final ModuleService plugin, final KernelQedeqBo qedeq,
91    final Parameters parameters) {
92  11 super(plugin, qedeq);
93  11 final String method = "FormalProofCheckerExecutor(Plugin, KernelQedeqBo, Map)";
94  11 final String checkerFactoryClass = parameters.getString("checkerFactory");
95  11 if (checkerFactoryClass != null && checkerFactoryClass.length() > 0) {
96  11 try {
97  11 Class cl = Class.forName(checkerFactoryClass);
98  11 checkerFactory = (ProofCheckerFactory) cl.newInstance();
99    } catch (ClassNotFoundException e) {
100  0 Trace.fatal(CLASS, this, method, "ProofCheckerFactory class not in class path: "
101    + checkerFactoryClass, e);
102    } catch (InstantiationException e) {
103  0 Trace.fatal(CLASS, this, method, "ProofCheckerFactory class could not be instanciated: "
104    + checkerFactoryClass, e);
105    } catch (IllegalAccessException e) {
106  0 Trace.fatal(CLASS, this, method,
107    "Programming error, access for instantiation failed for model: "
108    + checkerFactoryClass, e);
109    } catch (RuntimeException e) {
110  0 Trace.fatal(CLASS, this, method,
111    "Programming error, instantiation failed for model: " + checkerFactoryClass, e);
112    }
113    }
114    // fallback is the default checker factory
115  11 if (checkerFactory == null) {
116  0 checkerFactory = new ProofCheckerFactoryImpl();
117    }
118    }
119   
 
120  11 toggle public Object executePlugin(final InternalModuleServiceCall call, final Object data) throws InterruptException {
121    // we set this as module rule version, and hope it will be changed
122  11 ruleVersion = new Version("0.00.00");
123  11 QedeqLog.getInstance().logRequest(
124    "Check logical correctness", getKernelQedeqBo().getUrl());
125  11 getServices().checkWellFormedness(call.getInternalServiceProcess(), getKernelQedeqBo());
126  11 if (!getKernelQedeqBo().isWellFormed()) {
127  0 final String msg = "Check of logical correctness failed";
128  0 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
129    "Module is not even well formed.");
130  0 return Boolean.FALSE;
131    }
132  11 getKernelQedeqBo().setFormallyProvedProgressState(FormallyProvedState.STATE_EXTERNAL_CHECKING);
133  11 getKernelQedeqBo().getLabels().resetNodesToProvedUnchecked();
134  11 final KernelModuleReferenceList list = getKernelQedeqBo().getKernelRequiredModules();
135  11 for (int i = 0; i < list.size(); i++) {
136  0 Trace.trace(CLASS, "check(DefaultQedeqBo)", "checking label", list.getLabel(i));
137  0 getServices().checkFormallyProved(call.getInternalServiceProcess(), list.getKernelQedeqBo(i));
138  0 if (list.getKernelQedeqBo(i).hasErrors()) {
139  0 addError(new CheckRequiredModuleException(
140    LogicErrors.MODULE_IMPORT_CHECK_FAILED_CODE,
141    LogicErrors.MODULE_IMPORT_CHECK_FAILED_TEXT
142    + list.getQedeqBo(i).getModuleAddress(),
143    list.getModuleContext(i)));
144    }
145    }
146    // has at least one import errors?
147  11 if (getKernelQedeqBo().hasErrors()) {
148  0 getKernelQedeqBo().setFormallyProvedFailureState(FormallyProvedState.STATE_EXTERNAL_CHECKING_FAILED,
149    getErrorList());
150  0 final String msg = "Check of logical correctness failed";
151  0 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
152    StringUtility.replace(getKernelQedeqBo().getErrors().getMessage(), "\n", "\n\t"));
153  0 return Boolean.FALSE;
154    }
155  11 getKernelQedeqBo().setFormallyProvedProgressState(FormallyProvedState.STATE_INTERNAL_CHECKING);
156  11 try {
157  11 traverse(call.getInternalServiceProcess());
158    } catch (SourceFileExceptionList e) {
159  5 getKernelQedeqBo().setFormallyProvedFailureState(FormallyProvedState.STATE_INTERNAL_CHECKING_FAILED,
160    getErrorList());
161  5 final String msg = "Check of logical correctness failed";
162  5 QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(),
163    StringUtility.replace(e.getMessage(), "\n", "\n\t"));
164  5 return Boolean.FALSE;
165    }
166  6 getKernelQedeqBo().setFormallyProvedProgressState(FormallyProvedState.STATE_CHECKED);
167  6 QedeqLog.getInstance().logSuccessfulReply(
168    "Check of logical correctness successful", getKernelQedeqBo().getUrl());
169  6 return Boolean.TRUE;
170    }
171   
 
172  11 toggle public void visitEnter(final Header header) throws ModuleDataException {
173  11 if (header.getSpecification() == null
174    || header.getSpecification().getRuleVersion() == null) {
175  0 return;
176    }
177  11 final String context = getCurrentContext().getLocationWithinModule();
178  11 setLocationWithinModule(context + ".getSpecification().getRuleVersion()");
179  11 final String version = header.getSpecification().getRuleVersion().trim();
180  11 if (!checkerFactory.isRuleVersionSupported(version)) {
181  0 addError(new ProofCheckException(
182    LogicErrors.RULE_VERSION_HAS_STILL_NO_PROOF_CHECKER_CODE,
183    LogicErrors.RULE_VERSION_HAS_STILL_NO_PROOF_CHECKER_TEXT + version,
184    getCurrentContext()));
185    } else {
186  11 try {
187  11 ruleVersion = new Version(version);
188    } catch (RuntimeException e) {
189  0 addError(new ProofCheckException(
190    LogicErrors.THIS_IS_NOT_VALID_VERSION_FORMAT_CODE,
191    LogicErrors.THIS_IS_NOT_VALID_VERSION_FORMAT_TEXT + version,
192    getCurrentContext()));
193    }
194    }
195  11 setLocationWithinModule(context);
196    }
197   
 
198  62 toggle public void visitEnter(final Axiom axiom) throws ModuleDataException {
199  62 if (getNodeBo().isWellFormed()) {
200  62 getNodeBo().setProved(CheckLevel.SUCCESS);
201    } else {
202  0 getNodeBo().setProved(CheckLevel.FAILURE);
203  0 addError(new ProofCheckException(
204    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
205    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
206    getCurrentContext()));
207  0 return;
208    }
209  62 setBlocked(true);
210    }
211   
 
212  62 toggle public void visitLeave(final Axiom axiom) {
213  62 setBlocked(false);
214    }
215   
 
216  0 toggle public void visitEnter(final PredicateDefinition definition)
217    throws ModuleDataException {
218  0 if (getNodeBo().isWellFormed()) {
219  0 getNodeBo().setProved(CheckLevel.SUCCESS);
220    } else {
221  0 getNodeBo().setProved(CheckLevel.FAILURE);
222  0 addError(new ProofCheckException(
223    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
224    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
225    getCurrentContext()));
226  0 return;
227    }
228  0 setBlocked(true);
229    }
230   
 
231  0 toggle public void visitLeave(final PredicateDefinition definition) {
232  0 setBlocked(false);
233    }
234   
 
235  1 toggle public void visitEnter(final InitialPredicateDefinition definition)
236    throws ModuleDataException {
237  1 if (getNodeBo().isWellFormed()) {
238  1 getNodeBo().setProved(CheckLevel.SUCCESS);
239    } else {
240  0 getNodeBo().setProved(CheckLevel.FAILURE);
241  0 addError(new ProofCheckException(
242    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
243    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
244    getCurrentContext()));
245  0 return;
246    }
247  1 setBlocked(true);
248    }
249   
 
250  1 toggle public void visitLeave(final InitialPredicateDefinition definition) {
251  1 setBlocked(false);
252    }
253   
 
254  1 toggle public void visitEnter(final InitialFunctionDefinition definition)
255    throws ModuleDataException {
256  1 if (getNodeBo().isWellFormed()) {
257  1 getNodeBo().setProved(CheckLevel.SUCCESS);
258    } else {
259  0 getNodeBo().setProved(CheckLevel.FAILURE);
260  0 addError(new ProofCheckException(
261    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
262    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
263    getCurrentContext()));
264  0 return;
265    }
266  1 setBlocked(true);
267    }
268   
 
269  1 toggle public void visitLeave(final InitialFunctionDefinition definition) {
270  1 setBlocked(false);
271    }
272   
 
273  0 toggle public void visitEnter(final FunctionDefinition definition)
274    throws ModuleDataException {
275  0 if (getNodeBo().isWellFormed()) {
276  0 getNodeBo().setProved(CheckLevel.SUCCESS);
277    } else {
278  0 getNodeBo().setProved(CheckLevel.FAILURE);
279  0 addError(new ProofCheckException(
280    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
281    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
282    getCurrentContext()));
283  0 return;
284    }
285  0 setBlocked(true);
286    }
287   
 
288  0 toggle public void visitLeave(final FunctionDefinition definition) {
289  0 setBlocked(false);
290    }
291   
 
292  78 toggle public void visitEnter(final Proposition proposition)
293    throws ModuleDataException {
294    // we only check this node, if the well formed check was successful
295  78 if (!getNodeBo().isWellFormed()) {
296  0 getNodeBo().setProved(CheckLevel.FAILURE);
297  0 addError(new ProofCheckException(
298    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_CODE,
299    LogicErrors.NODE_FORMULAS_MUST_BE_WELL_FORMED_TEXT,
300    getCurrentContext()));
301  0 return;
302    }
303  78 getNodeBo().setProved(CheckLevel.UNCHECKED);
304  78 if (proposition.getFormula() == null) {
305  0 getNodeBo().setProved(CheckLevel.FAILURE);
306  0 addError(new ProofCheckException(
307    LogicErrors.PROPOSITION_FORMULA_MUST_NOT_BE_NULL_CODE,
308    LogicErrors.PROPOSITION_FORMULA_MUST_NOT_BE_NULL_TEXT,
309    getCurrentContext()));
310  0 return;
311    }
312  78 final String context = getCurrentContext().getLocationWithinModule();
313  78 boolean correctProofFound = false;
314    // we start checking
315  78 if (proposition.getFormalProofList() != null) {
316  144 for (int i = 0; i < proposition.getFormalProofList().size(); i++) {
317  72 final FormalProof proof = proposition.getFormalProofList().get(i);
318  72 if (proof != null) {
319  72 final FormalProofLineList list = proof.getFormalProofLineList();
320  72 if (list != null) {
321  72 setLocationWithinModule(context + ".getFormalProofList().get("
322    + i + ").getFormalProofLineList()");
323  72 LogicalCheckExceptionList eList
324    = checkerFactory.createProofChecker(ruleVersion).checkProof(
325    proposition.getFormula().getElement(), list, this,
326    getCurrentContext(),
327    this);
328  72 if (!correctProofFound && eList.size() == 0) {
329  62 correctProofFound = true;
330    }
331  140 for (int j = 0; j < eList.size(); j++) {
332  68 addError(eList.get(j));
333    }
334    }
335    }
336    }
337    }
338  78 setLocationWithinModule(context + ".getFormula()");
339    // only if we found at least one error free formal proof
340  78 if (correctProofFound) {
341  62 getNodeBo().setProved(CheckLevel.SUCCESS);
342    } else {
343  16 getNodeBo().setProved(CheckLevel.FAILURE);
344  16 addError(new ProofCheckException(
345    LogicErrors.NO_FORMAL_PROOF_FOUND_CODE,
346    LogicErrors.NO_FORMAL_PROOF_FOUND_TEXT,
347    getCurrentContext()));
348    }
349  78 setBlocked(true);
350    }
351   
 
352  78 toggle public void visitLeave(final Proposition definition) {
353  78 setBlocked(false);
354    }
355   
 
356  83 toggle public void visitEnter(final Rule rule) throws ModuleDataException {
357  83 final String context = getCurrentContext().getLocationWithinModule();
358    // FIXME 20110618 m31: check if this is really a higher version than before?
359    // FIXME 20130413 m31: why we don't use the following method:
360    /// checkerFactory.createProofChecker(ruleVersion).checkRule
361  83 getNodeBo().setProved(CheckLevel.UNCHECKED);
362  83 final ChangedRuleList list = rule.getChangedRuleList();
363  91 for (int i = 0; list != null && i < list.size(); i++) {
364  8 setLocationWithinModule(context + ".getChangedRuleList().get(" + i + ").getVersion()");
365  8 final ChangedRule r = list.get(i);
366  8 if (!Version.equals(rule.getVersion(), r.getVersion())) {
367  0 addError(new ProofCheckException(
368    LogicErrors.OTHER_RULE_VERSION_EXPECTED_CODE,
369    LogicErrors.OTHER_RULE_VERSION_EXPECTED_TEXT1 + rule.getVersion()
370    + LogicErrors.OTHER_RULE_VERSION_EXPECTED_TEXT2 + r.getVersion(),
371    getCurrentContext()));
372    }
373    }
374   
375  83 if (getNodeBo().isNotProved()) {
376  0 getNodeBo().setProved(CheckLevel.SUCCESS);
377    } else {
378  83 getNodeBo().setProved(CheckLevel.FAILURE);
379    }
380    }
381   
 
382  84 toggle protected void addError(final ModuleDataException me) {
383  84 if (getNodeBo() != null) {
384  84 getNodeBo().setProved(CheckLevel.FAILURE);
385    }
386  84 super.addError(me);
387    }
388   
 
389  84 toggle protected void addError(final SourceFileException me) {
390  84 if (getNodeBo() != null) {
391  84 getNodeBo().setProved(CheckLevel.FAILURE);
392    }
393  84 super.addError(me);
394    }
395   
 
396  318 toggle public boolean isProvedFormula(final String reference) {
397  318 final String method = "hasProvedFormula";
398  318 final Reference ref = getReference(reference, getCurrentContext(), false, false);
399  318 if (ref == null) {
400  0 Trace.info(CLASS, method, "ref == null");
401  0 return false;
402    }
403  318 if (ref.isExternalModuleReference()) {
404  0 Trace.info(CLASS, method, "ref is external module");
405  0 return false;
406    }
407  318 if (!ref.isNodeReference()) {
408  0 Trace.info(CLASS, method, "ref is no node reference");
409  0 return false;
410    }
411  318 if (null == ref.getNode()) {
412  3 Trace.info(CLASS, method, "ref node == null");
413  3 return false;
414    }
415  315 if (ref.isSubReference()) {
416  0 return false;
417    }
418  315 if (!ref.isProofLineReference()) {
419  315 if (!ref.getNode().isProved()) {
420  1 Trace.info(CLASS, method, "ref node is not marked as proved: " + reference);
421    }
422  315 if (!ref.getNode().isProved()) {
423  1 return false;
424    }
425  314 if (!ref.getNode().hasFormula()) {
426  0 Trace.info(CLASS, method, "node has no formula: " + reference);
427  0 return false;
428    }
429  314 return ref.getNode().isProved();
430    }
431  0 Trace.info(CLASS, method, "proof line references are not ok!");
432  0 return false;
433    }
434   
 
435  157 toggle public Element getNormalizedReferenceFormula(final String reference) {
436  157 if (!isProvedFormula(reference)) {
437  0 return null;
438    }
439  157 final Reference ref = getReference(reference, getCurrentContext(), false, false);
440  157 final Element formula = ref.getNode().getFormula();
441  157 return getNormalizedFormula(ref.getNode().getQedeqBo(), formula);
442    }
443   
 
444  2017 toggle public Element getNormalizedFormula(final Element formula) {
445  2017 return getNormalizedFormula(getKernelQedeqBo(), formula);
446    }
447   
 
448  25672 toggle private Element getNormalizedFormula(final KernelQedeqBo qedeq, final Element formula) {
449  25672 if (formula == null) {
450  3 return null;
451    }
452  25669 if (formula.isAtom()) {
453  9780 return new DefaultAtom(formula.getAtom().getString());
454    }
455  15889 return getNormalizedFormula(qedeq, formula.getList());
456    }
457   
 
458  15889 toggle private ElementList getNormalizedFormula(final KernelQedeqBo qedeq, final ElementList formula) {
459  15889 final ElementList result = new DefaultElementList(formula.getOperator());
460  15889 if (FormulaUtility.isPredicateConstant(formula)) {
461  0 final PredicateKey key = new PredicateKey(formula.getElement(0).getAtom().getString(),
462    "" + (formula.getList().size() - 1));
463  0 final DefaultAtom atom = new DefaultAtom(
464    qedeq.getExistenceChecker().get(key).getContext().getModuleLocation().getUrl()
465    + "$" + key.getName());
466  0 result.add(atom);
467  0 for (int i = 1; i < formula.size(); i++) {
468  0 result.add(getNormalizedFormula(qedeq, formula.getElement(i)));
469    }
470  15889 } else if (FormulaUtility.isFunctionConstant(formula)) {
471  0 final FunctionKey key = new FunctionKey(formula.getElement(0).getAtom().getString(),
472    "" + (formula.getList().size() - 1));
473  0 final DefaultAtom atom = new DefaultAtom(
474    qedeq.getExistenceChecker().get(key).getContext().getModuleLocation().getUrl()
475    + "$" + key.getName());
476  0 result.add(atom);
477  0 for (int i = 1; i < formula.size(); i++) {
478  0 result.add(getNormalizedFormula(qedeq, formula.getElement(i)));
479    }
480    } else {
481  39387 for (int i = 0; i < formula.size(); i++) {
482  23498 result.add(getNormalizedFormula(qedeq, formula.getElement(i)));
483    }
484    }
485  15889 return result;
486    }
487   
 
488  397 toggle public boolean isLocalProofLineReference(final String reference) {
489    // here we have no proof lines
490  397 return false;
491    }
492   
 
493  0 toggle public ModuleContext getReferenceContext(final String reference) {
494    // here we have no proof lines
495  0 return null;
496    }
497   
 
498  0 toggle public Element getNormalizedLocalProofLineReference(final String reference) {
499    // here we have no proof lines
500  0 return null;
501    }
502   
 
503  732 toggle public RuleKey getRule(final String ruleName) {
504  732 final RuleKey local = getLocalRuleKey(ruleName);
505  732 if (local == null) {
506  0 return getKernelQedeqBo().getExistenceChecker().getParentRuleKey(
507    ruleName);
508    }
509  732 return local;
510    }
511   
512   
513    }