sbv-11.4: SMT Based Verification: Symbolic Haskell theorem prover using SMT solving.
Copyright(c) Levent Erkok
LicenseBSD3
Maintainererkokl@gmail.com
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Data.SBV.Tools.KnuckleDragger

Description

A lightweight theorem proving like interface, built on top of SBV. Inspired by and modeled after Philip Zucker's tool with the same name, see http://github.com/philzook58/knuckledragger.

See the directory Documentation.SBV.Examples.KnuckleDragger for various examples.

Synopsis

Propositions and their proofs

type Proposition a = (QNot a, QuantifiedBool a, QSaturate Symbolic a, Skolemize (NegatesTo a), Satisfiable (Symbolic (SkolemsTo (NegatesTo a))), Constraint Symbolic (SkolemsTo (NegatesTo a)), Typeable a) Source #

A proposition is something SBV is capable of proving/disproving in KnuckleDragger.

data Proof Source #

Proof for a property. This type is left abstract, i.e., the only way to create on is via a call to lemma/theorem etc., ensuring soundness. (Note that the trusted-code base here is still large: The underlying solver, SBV, and KnuckleDragger kernel itself. But this mechanism ensures we can't create proven things out of thin air, following the standard LCF methodology.)

Instances

Instances details
NFData Proof Source #

NFData ignores the getProp field

Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

rnf :: Proof -> () #

Show Proof Source #

Show instance for Proof

Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

showsPrec :: Int -> Proof -> ShowS #

show :: Proof -> String #

showList :: [Proof] -> ShowS #

Adding axioms/definitions

axiom :: Proposition a => String -> a -> KD Proof Source #

Accept the given definition as a fact. Usually used to introduce definitial axioms, giving meaning to uninterpreted symbols. Note that we perform no checks on these propositions, if you assert nonsense, then you get nonsense back. So, calls to axiom should be limited to definitions, or basic axioms (like commutativity, associativity) of uninterpreted function symbols.

Basic proofs

lemma :: Proposition a => String -> a -> [Proof] -> KD Proof Source #

Prove a given statement, using auxiliaries as helpers. Using the default solver.

lemmaWith :: Proposition a => SMTConfig -> String -> a -> [Proof] -> KD Proof Source #

Prove a given statement, using auxiliaries as helpers. Using the given solver.

theorem :: Proposition a => String -> a -> [Proof] -> KD Proof Source #

Prove a given statement, using auxiliaries as helpers. Essentially the same as lemma, except for the name, using the default solver.

theoremWith :: Proposition a => SMTConfig -> String -> a -> [Proof] -> KD Proof Source #

Prove a given statement, using auxiliaries as helpers. Essentially the same as lemmaWith, except for the name.

Reasoning via calculation

calc :: CalcLemma a steps => String -> a -> steps -> KD Proof Source #

Prove a property via a series of equality steps, using the default solver. Let H be a list of already established lemmas. Let P be a property we wanted to prove, named name. Consider a call of the form calc name P (cond, [A, B, C, D]) H. Note that H is a list of already proven facts, ensured by the type signature. We proceed as follows:

  • Prove: (H && cond) -> (A == B)
  • Prove: (H && cond && A == B) -> (B == C)
  • Prove: (H && cond && A == B && B == C) -> (C == D)
  • Prove: (H && (cond -> (A == B && B == C && C == D))) -> P
  • If all of the above steps succeed, conclude P.

cond acts as the context. Typically, if you are trying to prove Y -> Z, then you want cond to be Y. (This is similar to intros commands in theorem provers.)

So, calc-lemma is essentially modus-ponens, applied in a sequence of stepwise equality reasoning in the case of non-boolean steps.

If there are no helpers given (i.e., if H is empty), then this call is equivalent to lemmaWith. If H is a singleton, then we bail out. A single step in H indicates a usage mistake, since there's no sequence of steps to reason about.

calcWith :: CalcLemma a steps => SMTConfig -> String -> a -> steps -> KD Proof Source #

Prove a property via a series of equality steps, using the given solver.

calcThm :: CalcLemma a steps => String -> a -> steps -> KD Proof Source #

Same as calc, except tagged as Theorem

calcThmWith :: CalcLemma a steps => SMTConfig -> String -> a -> steps -> KD Proof Source #

Same as calcWith, except tagged as Theorem

Reasoning via regular induction

induct :: Inductive a steps => String -> a -> (Proof -> steps) -> KD Proof Source #

Inductively prove a lemma, using the default config. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

inductWith :: Inductive a steps => SMTConfig -> String -> a -> (Proof -> steps) -> KD Proof Source #

Same as induct, but with the given solver configuration. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

inductThm :: Inductive a steps => String -> a -> (Proof -> steps) -> KD Proof Source #

Inductively prove a theorem. Same as induct, but tagged as a theorem, using the default config. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

inductThmWith :: Inductive a steps => SMTConfig -> String -> a -> (Proof -> steps) -> KD Proof Source #

Same as inductThm, but with the given solver configuration. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

Reasoning via strong induction

sInduct :: Inductive a steps => String -> a -> (Proof -> steps) -> KD Proof Source #

Inductively prove a lemma, using strong induction, using the default config. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

sInductWith :: Inductive a steps => SMTConfig -> String -> a -> (Proof -> steps) -> KD Proof Source #

Same as sInduct, but with the given solver configuration. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

sInductThm :: Inductive a steps => String -> a -> (Proof -> steps) -> KD Proof Source #

Inductively prove a theorem, using strong induction. Same as sInduct, but tagged as a theorem, using the default config. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

sInductThmWith :: Inductive a steps => SMTConfig -> String -> a -> (Proof -> steps) -> KD Proof Source #

Same as sInductThm, but with the given solver configuration. Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only partial correctness is guaranteed if non-terminating functions are involved.

Creating instances of proofs

at :: Instantiatable a => Proof -> a -> Proof Source #

Apply a universal proof to some arguments, creating an instance of the proof itself.

newtype Inst (nm :: Symbol) a Source #

Instantiation for a universally quantified variable

Constructors

Inst (SBV a) 

Instances

Instances details
KnownSymbol nm => Show (Inst nm a) Source # 
Instance details

Defined in Data.SBV.Tools.KD.KnuckleDragger

Methods

showsPrec :: Int -> Inst nm a -> ShowS #

show :: Inst nm a -> String #

showList :: [Inst nm a] -> ShowS #

Faking proofs

sorry :: Proof Source #

A manifestly false theorem. This is useful when we want to prove a theorem that the underlying solver cannot deal with, or if we want to postpone the proof for the time being. KnuckleDragger will keep track of the uses of sorry and will print them appropriately while printing proofs.

Running KnuckleDragger proofs

data KD a Source #

Monad for running KnuckleDragger proofs in.

Instances

Instances details
Applicative KD Source # 
Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

pure :: a -> KD a #

(<*>) :: KD (a -> b) -> KD a -> KD b #

liftA2 :: (a -> b -> c) -> KD a -> KD b -> KD c #

(*>) :: KD a -> KD b -> KD b #

(<*) :: KD a -> KD b -> KD a #

Functor KD Source # 
Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

fmap :: (a -> b) -> KD a -> KD b #

(<$) :: a -> KD b -> KD a #

Monad KD Source # 
Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

(>>=) :: KD a -> (a -> KD b) -> KD b #

(>>) :: KD a -> KD b -> KD b #

return :: a -> KD a #

MonadFail KD Source # 
Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

fail :: String -> KD a #

MonadIO KD Source # 
Instance details

Defined in Data.SBV.Tools.KD.Utils

Methods

liftIO :: IO a -> KD a #

runKD :: KD a -> IO a Source #

Run a KD proof, using the default configuration.

runKDWith :: SMTConfig -> KD a -> IO a Source #

Run a KD proof, using the given configuration.

use :: IO Proof -> KD Proof Source #

Bring an IO proof into current proof context.

Starting a calculation proof

(|-) :: [SBool] -> [ProofStep a] -> (SBool, [ProofStep a]) infixl 0 Source #

Start a calculational proof, with the given hypothesis. Use [] as the first argument if the calculation holds unconditionally. The first argument is typically used to introduce hypotheses in proofs of implications such as A .=> B .=> C, where we would put [A, B] as the starting assumption. You can name these and later use in the derivation steps.

(⊢) :: [SBool] -> [ProofStep a] -> (SBool, [ProofStep a]) infixl 0 Source #

Alternative unicode for |-.

Sequence of calculation steps

(=:) :: ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a infixr 1 Source #

Chain steps in a calculational proof.

(≡) :: ChainStep a (ChainsTo a) => a -> ChainsTo a -> ChainsTo a infixr 1 Source #

Unicode alternative for =:.

Supplying hints for a calculation step

(??) :: ProofHint a b => a -> b -> ProofStep a infixl 2 Source #

Specify a helper for the given proof step

(⁇) :: ProofHint a b => a -> b -> ProofStep a infixl 2 Source #

Alternative unicode for ??.

hprf :: Proof -> Helper Source #

Smart constructor for creating a helper from a boolean. This is hardly needed, unless you're mixing proofs and booleans in one group of hints.

hyp :: SBool -> Helper Source #

Smart constructor for creating a helper from a boolean. This is hardly needed, unless you're mixing proofs and booleans in one group of hints.

Case splits

cases :: String -> [SBool] -> Helper Source #

Specifying a case-split

Finishing up a calculational proof

qed :: [ProofStep a] Source #

Mark the end of a calculational proof.