| module Checker.Kernel (checkCertificate, CheckResult(..)) where | |
| import Proof.Certificate | |
| import SAT.CNF (Clause, Literal(..), litVar) | |
| import Data.List (nub, sort) | |
| data CheckResult | |
| = Verified String | |
| | Rejected String String | |
| deriving (Eq, Show) | |
| checkCertificate :: ProofCertificate -> CheckResult | |
| checkCertificate cert = | |
| case proofConclusion cert of | |
| Valid -> checkValidityProof cert | |
| Unsatisfiable -> checkUNSATProof cert | |
| CounterExample ce -> checkCounterExample cert ce | |
| checkValidityProof :: ProofCertificate -> CheckResult | |
| checkValidityProof cert = | |
| let steps = proofSteps cert | |
| in if all validStep steps | |
| then Verified (proofName cert) | |
| else Rejected (proofName cert) "Invalid proof step" | |
| checkUNSATProof :: ProofCertificate -> CheckResult | |
| checkUNSATProof cert = | |
| let steps = proofSteps cert | |
| in if derivesEmpty steps | |
| then Verified (proofName cert) | |
| else Rejected (proofName cert) "UNSAT proof does not derive empty clause" | |
| checkCounterExample :: ProofCertificate -> [(Int, Bool)] -> CheckResult | |
| checkCounterExample cert ce = | |
| if not (null ce) | |
| then Verified (proofName cert) | |
| else Rejected (proofName cert) "Empty counterexample" | |
| validStep :: ProofStep -> Bool | |
| validStep (Assumption _) = True | |
| validStep (Learned _ _) = True | |
| validStep (Resolution c1 c2 resolvent pivot) = | |
| case verifyResolution c1 c2 pivot of | |
| Just expected -> sort (nub resolvent) == sort (nub expected) | |
| Nothing -> False | |
| derivesEmpty :: [ProofStep] -> Bool | |
| derivesEmpty steps = any isEmpty (concatMap stepClauses steps) | |
| where | |
| isEmpty [] = True | |
| isEmpty _ = False | |
| stepClauses (Resolution _ _ r _) = [r] | |
| stepClauses (Assumption c) = [c] | |
| stepClauses (Learned c _) = [c] | |