/* * Copyright (C) 2009-2012 University of Freiburg * * This file is part of SMTInterpol. * * SMTInterpol is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SMTInterpol is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>. */ package de.uni_freiburg.informatik.ultimate.smtinterpol.proof; import java.util.ArrayDeque; import java.util.HashSet; import java.util.Set; import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Literal; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; /** * A proof checker for the propositional structure of a proof. This class only * checks the resolution chain. * @author Juergen Christ */ public class PropProofChecker { /** * The list of clauses still to resolve. */ private final ArrayDeque<Clause> mTodo = new ArrayDeque<Clause>(); /** * The set of clauses that contain a valid proof. */ private final HashSet<Clause> mCorrect = new HashSet<Clause>(); public boolean check(Clause refutation) { mTodo.add(refutation); return run(); } @SuppressWarnings({ "rawtypes", "unchecked" }) private boolean run() { while (!mTodo.isEmpty()) { final Clause clause = mTodo.removeLast(); if (!mCorrect.contains(clause)) { final ProofNode pn = clause.getProof(); if (pn.isLeaf()) { // I assume all leaves are correct! mCorrect.add(clause); } else { final Antecedent[] antes = ((ResolutionNode) pn).getAntecedents(); final Clause prim = ((ResolutionNode) pn).getPrimary(); boolean unknownChild = false; if (!mCorrect.contains(prim)) { if (!unknownChild) { // We add ourselves in front of all unknown // children to be reevaluated after they have // been processed. mTodo.addLast(clause); } unknownChild = true; mTodo.addLast(prim); } for (final Antecedent ante : antes) { if (!mCorrect.contains(ante.mAntecedent)) { if (!unknownChild) { // We add ourselves in front of all unknown // children to be reevaluated after they have // been processed. mTodo.addLast(clause); } unknownChild = true; mTodo.addLast(ante.mAntecedent); } } if (!unknownChild) { // All children were known to be correct => check clause final HashSet<Literal> clauselits = new HashSet<Literal>(); for (int i = 0; i < prim.getSize(); ++i) { clauselits.add(prim.getLiteral(i)); } for (final Antecedent ante : antes) { final Clause antecls = ante.mAntecedent; if (!antecls.contains(ante.mPivot)) { System.err.println("Pivot literal " + ante.mPivot + " not in antecedent"); return false; } if (!clauselits.remove(ante.mPivot.negate())) { System.err.println("Negated pivot literal " + ante.mPivot.negate() + " not in primary"); return false; } for (int i = 0; i < antecls.getSize(); ++i) { final Literal lit = antecls.getLiteral(i); if (lit != ante.mPivot) { clauselits.add(lit); } } } // Here, we have done all resolution steps. Check the // resulting clause final HashSet<Literal> clslits = new HashSet<Literal>(); for (int i = 0; i < clause.getSize(); ++i) { clslits.add(clause.getLiteral(i)); } if (clauselits.containsAll(clslits) && clslits.containsAll(clauselits)) { mCorrect.add(clause); } else { System.err.println("Result of resolution incorrect"); System.err.println(); System.err.println("Result misses:"); final Set<Literal> clauseremain = (Set)clauselits.clone(); clauseremain.removeAll(clslits); System.err.println(clauseremain); System.err.println(); System.err.println("Result additionally has:"); final Set<Literal> clsremain = (Set)clslits.clone(); clsremain.removeAll(clauselits); System.err.println(clsremain); return false; } } } } } // System.err.println("Proof propositionally correct!"); return true; } }