CookBook/Recipes/ExternalSolver.thy
changeset 61 64c9540f2f84
child 79 a53c7810e38b
equal deleted inserted replaced
60:5b9c6010897b 61:64c9540f2f84
       
     1 theory ExternalSolver
       
     2 imports "../Base"
       
     3 begin
       
     4 
       
     5 section {* Using an External Solver *} 
       
     6 
       
     7 text {*
       
     8   {\bf Problem:}
       
     9   You want to use an external solver, say, because it is more efficient in
       
    10   deciding particular formulas than any Isabelle tactic.
       
    11   \smallskip
       
    12 
       
    13   {\bf Solution:} The easiest way to do this is writing an oracle.
       
    14   To yield results checked by Isabelle's kernel, one can reconstruct the
       
    15   proofs.
       
    16   \smallskip
       
    17 
       
    18   \begin{readmore}
       
    19   A short introduction to oracles can be found in [isar-ref: no suitable label
       
    20   for section 3.11]. A simple example is given in 
       
    21   @{ML_file "FOL/ex/IffOracle"}.
       
    22   (TODO: add more references to the code)
       
    23   \end{readmore}
       
    24 
       
    25   The general layout will be as follows. Given a goal G, we transform it into
       
    26   the syntactical respresentation of the external solver, and invoke the
       
    27   solver. The solver's result is then used inside the oracle to either return
       
    28   the proved goal or raise an exception meaning that the solver was unable to
       
    29   prove the goal.
       
    30 
       
    31   For communication with external programs, there are the primitives
       
    32   @{ML_text system} and @{ML_text system_out}, the latter of which captures
       
    33   the invoked program's output. For simplicity, here, we will use metis, an
       
    34   external solver included in the Isabelle destribution. Since it is written
       
    35   in ML, we can call it directly without the detour of invoking an external
       
    36   program.
       
    37 
       
    38   We will restrict ourselves to proving formulas of propositional logic, a
       
    39   task metis is very good at.
       
    40   *}
       
    41 
       
    42 
       
    43 ML {*
       
    44 fun trans t =
       
    45   (case t of
       
    46     @{term Trueprop} $ t => trans t
       
    47   | @{term True} => Metis.Formula.True
       
    48   | @{term False} => Metis.Formula.False
       
    49   | @{term Not} $ t => Metis.Formula.Not (trans t)
       
    50   | @{term "op &"} $ t1 $ t2 => Metis.Formula.And (trans t1, trans t2)
       
    51   | @{term "op |"} $ t1 $ t2 => Metis.Formula.Or (trans t1, trans t2)
       
    52   | @{term "op -->"} $ t1 $ t2 => Metis.Formula.Imp (trans t1, trans t2)
       
    53   | @{term "op = :: bool => bool => bool"} $ t1 $ t2 => 
       
    54       Metis.Formula.Iff (trans t1, trans t2)
       
    55   | Free (n, @{typ bool}) => Metis.Formula.Atom (n, [])
       
    56   | _ => error "inacceptable term")
       
    57 *}
       
    58 
       
    59 
       
    60 ML {*
       
    61 fun solve f =
       
    62   let
       
    63     open Metis
       
    64     fun fromLiterals fms = LiteralSet.fromList (map Literal.fromFormula fms)
       
    65     fun fromClause fm = fromLiterals (Formula.stripDisj fm)
       
    66     fun fromCnf fm = map fromClause (Formula.stripConj fm)
       
    67 
       
    68     val mk_cnfs = map fromCnf o Normalize.cnf o Formula.Not
       
    69     fun refute cls =
       
    70       let val res = Resolution.new Resolution.default (map Thm.axiom cls)
       
    71       in
       
    72         (case Resolution.loop res of
       
    73           Resolution.Contradiction _ => true
       
    74         | Resolution.Satisfiable _ => false)
       
    75       end
       
    76   in List.all refute (mk_cnfs f) end
       
    77 *}
       
    78 
       
    79 
       
    80 ML {*
       
    81 fun prop_dp (thy, t) = if solve (trans t) then Thm.cterm_of thy t 
       
    82   else error "Proof failed."
       
    83 *}
       
    84 
       
    85 oracle prop_oracle = prop_dp
       
    86 
       
    87 ML {*
       
    88 fun prop_oracle_tac ctxt = 
       
    89   SUBGOAL (fn (goal, i) => 
       
    90     (case try prop_oracle (ProofContext.theory_of ctxt, goal) of
       
    91       SOME thm => rtac thm i
       
    92     | NONE => no_tac))
       
    93 *}
       
    94 
       
    95 method_setup prop_oracle = {*
       
    96   Method.ctxt_args (fn ctxt => Method.SIMPLE_METHOD' (prop_oracle_tac ctxt))
       
    97 *} "Oracle-based decision procedure for propositional logic"
       
    98 
       
    99 lemma "p \<or> \<not>p"
       
   100   by prop_oracle
       
   101 
       
   102 lemma "((p \<longrightarrow> q) \<longrightarrow> p) \<longrightarrow> p"
       
   103   by prop_oracle
       
   104 
       
   105 lemma "\<forall>x::nat. x \<ge> 0"
       
   106   sorry
       
   107 
       
   108 
       
   109 (* TODO: proof reconstruction *)
       
   110 
       
   111 
       
   112 end