src/Provers/Arith/fast_lin_arith.ML
changeset 20254 58b71535ed00
parent 20217 25b068a99d2b
child 20268 1fe9aed8fcac
equal deleted inserted replaced
20253:636ac45d100f 20254:58b71535ed00
   464 
   464 
   465       fun simp thm =
   465       fun simp thm =
   466         let val thm' = trace_thm "Simplified:" (full_simplify simpset' thm)
   466         let val thm' = trace_thm "Simplified:" (full_simplify simpset' thm)
   467         in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end
   467         in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end
   468 
   468 
   469       fun mk (Asm i) = trace_thm "Asm" (nth asms i)
   469       fun mk (Asm i)              = trace_thm "Asm" (nth asms i)
   470         | mk (Nat i) = trace_thm "Nat" (LA_Logic.mk_nat_thm sg (nth atoms i))
   470         | mk (Nat i)              = trace_thm "Nat" (LA_Logic.mk_nat_thm sg (nth atoms i))
   471         | mk (LessD(j)) = trace_thm "L" (hd([mk j] RL lessD))
   471         | mk (LessD j)            = trace_thm "L" (hd ([mk j] RL lessD))
   472         | mk (NotLeD(j)) = trace_thm "NLe" (mk j RS LA_Logic.not_leD)
   472         | mk (NotLeD j)           = trace_thm "NLe" (mk j RS LA_Logic.not_leD)
   473         | mk (NotLeDD(j)) = trace_thm "NLeD" (hd([mk j RS LA_Logic.not_leD] RL lessD))
   473         | mk (NotLeDD j)          = trace_thm "NLeD" (hd ([mk j RS LA_Logic.not_leD] RL lessD))
   474         | mk (NotLessD(j)) = trace_thm "NL" (mk j RS LA_Logic.not_lessD)
   474         | mk (NotLessD j)         = trace_thm "NL" (mk j RS LA_Logic.not_lessD)
   475         | mk (Added(j1,j2)) = simp (trace_thm "+" (addthms (mk j1) (mk j2)))
   475         | mk (Added (j1, j2))     = simp (trace_thm "+" (addthms (mk j1) (mk j2)))
   476         | mk (Multiplied(n,j)) = (trace_msg("*"^IntInf.toString n); trace_thm "*" (multn(n,mk j)))
   476         | mk (Multiplied (n, j))  = (trace_msg ("*" ^ IntInf.toString n); trace_thm "*" (multn (n, mk j)))
   477         | mk (Multiplied2(n,j)) = simp (trace_msg("**"^IntInf.toString n); trace_thm "**" (multn2(n,mk j)))
   477         | mk (Multiplied2 (n, j)) = simp (trace_msg ("**" ^ IntInf.toString n); trace_thm "**" (multn2 (n, mk j)))
   478 
   478 
   479   in trace_msg "mkthm";
   479   in trace_msg "mkthm";
   480      let val thm = trace_thm "Final thm:" (mk just)
   480      let val thm = trace_thm "Final thm:" (mk just)
   481      in let val fls = simplify simpset' thm
   481      in let val fls = simplify simpset' thm
   482         in trace_thm "After simplification:" fls;
   482         in trace_thm "After simplification:" fls;
   588 (*        should be intertwined: separate the first (fully split) case,      *)
   588 (*        should be intertwined: separate the first (fully split) case,      *)
   589 (*        refute it, continue with splitting and refuting.  Terminate with   *)
   589 (*        refute it, continue with splitting and refuting.  Terminate with   *)
   590 (*        failure as soon as a case could not be refuted; i.e. delay further *)
   590 (*        failure as soon as a case could not be refuted; i.e. delay further *)
   591 (*        splitting until after a refutation for other cases has been found. *)
   591 (*        splitting until after a refutation for other cases has been found. *)
   592 
   592 
   593 (* Theory.theory -> bool -> typ list * term list -> (typ list * (decompT * int) list) list *)
   593 (* Theory.theory -> typ list * term list -> (typ list * (decompT * int) list) list *)
   594 
   594 
   595 fun split_items sg do_pre (Ts, terms) =
   595 fun split_items sg (Ts, terms) =
   596   let
   596   let
   597 (*
   597 (*
   598       val _ = trace_msg ("split_items: do_pre is " ^ Bool.toString do_pre ^ "\n" ^
   598       val _ = trace_msg ("split_items: Ts    = " ^ string_of_list (Sign.string_of_typ sg) Ts ^ "\n" ^
   599                          "  Ts    = " ^ string_of_list (Sign.string_of_typ sg) Ts ^ "\n" ^
   599                          "             terms = " ^ string_of_list (Sign.string_of_term sg) terms)
   600                          "  terms = " ^ string_of_list (Sign.string_of_term sg) terms)
       
   601 *)
   600 *)
   602       (* splits inequalities '~=' into '<' and '>'; this corresponds to *)
   601       (* splits inequalities '~=' into '<' and '>'; this corresponds to *)
   603       (* 'REPEAT_DETERM (eresolve_tac neqE i)' at the theorem/tactic    *)
   602       (* 'REPEAT_DETERM (eresolve_tac neqE i)' at the theorem/tactic    *)
   604       (* level                                                          *)
   603       (* level                                                          *)
   605       (* decompT option list -> decompT option list list *)
   604       (* decompT option list -> decompT option list list *)
   614         | number_hyps n (NONE::xs)     = number_hyps (n+1) xs
   613         | number_hyps n (NONE::xs)     = number_hyps (n+1) xs
   615         | number_hyps n ((SOME x)::xs) = (x, n) :: number_hyps (n+1) xs
   614         | number_hyps n ((SOME x)::xs) = (x, n) :: number_hyps (n+1) xs
   616 
   615 
   617       val result = (Ts, terms) |> (* user-defined preprocessing of the subgoal *)
   616       val result = (Ts, terms) |> (* user-defined preprocessing of the subgoal *)
   618                                   (* (typ list * term list) list *)
   617                                   (* (typ list * term list) list *)
   619                                   (if do_pre then LA_Data.pre_decomp sg else Library.single)
   618                                   LA_Data.pre_decomp sg
   620                                |> (* compute the internal encoding of (in-)equalities *)
   619                                |> (* compute the internal encoding of (in-)equalities *)
   621                                   (* (typ list * decompT option list) list *)
   620                                   (* (typ list * decompT option list) list *)
   622                                   map (apsnd (map (LA_Data.decomp sg)))
   621                                   map (apsnd (map (LA_Data.decomp sg)))
   623                                |> (* splitting of inequalities *)
   622                                |> (* splitting of inequalities *)
   624                                   (* (typ list * decompT option list) list list *)
   623                                   (* (typ list * decompT option list) list list *)
   693     | refute [] js = SOME js
   692     | refute [] js = SOME js
   694 in refute end;
   693 in refute end;
   695 
   694 
   696 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> term list -> injust list option *)
   695 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> term list -> injust list option *)
   697 
   696 
   698 fun refute sg params show_ex do_pre terms =
   697 fun refute sg params show_ex terms =
   699   refutes sg params show_ex (split_items sg do_pre (map snd params, terms)) [];
   698   refutes sg params show_ex (split_items sg (map snd params, terms)) [];
   700 
       
   701 (* MetaSimplifier.simpset -> int * injust list -> Tactical.tactic *)
       
   702 
       
   703 fun refute_tac ss (i, justs) =
       
   704   fn state =>
       
   705     let val _ = trace_thm ("refute_tac (on subgoal " ^ Int.toString i ^ ", with " ^ Int.toString (length justs) ^ " justification(s)):") state
       
   706         val sg          = theory_of_thm state
       
   707         val {neqE, ...} = Data.get sg
       
   708         fun just1 j =
       
   709           REPEAT_DETERM (eresolve_tac neqE i) THEN                  (* eliminate inequalities *)
       
   710             METAHYPS (fn asms => rtac (mkthm (sg, ss) asms j) 1) i  (* use theorems generated from the actual justifications *)
       
   711     in DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN  (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *)
       
   712        DETERM (LA_Data.pre_tac i) THEN                               (* user-defined preprocessing of the subgoal *)
       
   713        PRIMITIVE (trace_thm "State after pre_tac:") THEN
       
   714        EVERY (map just1 justs)                                       (* prove every resulting subgoal, using its justification *)
       
   715     end  state;
       
   716 
   699 
   717 (* ('a -> bool) -> 'a list -> int *)
   700 (* ('a -> bool) -> 'a list -> int *)
   718 
   701 
   719 fun count P xs = length (List.filter P xs);
   702 fun count P xs = length (List.filter P xs);
   720 
   703 
   723 *)
   706 *)
   724 val fast_arith_neq_limit = ref 9;
   707 val fast_arith_neq_limit = ref 9;
   725 
   708 
   726 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> Term.term list -> Term.term -> injust list option *)
   709 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> Term.term list -> Term.term -> injust list option *)
   727 
   710 
   728 fun prove sg params show_ex do_pre Hs concl =
   711 fun prove sg params show_ex Hs concl =
   729   let
   712   let
   730     (* append the negated conclusion to 'Hs' -- this corresponds to     *)
   713     (* append the negated conclusion to 'Hs' -- this corresponds to     *)
   731     (* 'DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i)' at the *)
   714     (* 'DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i)' at the *)
   732     (* theorem/tactic level                                             *)
   715     (* theorem/tactic level                                             *)
   733     val Hs' = Hs @ [LA_Logic.neg_prop concl]
   716     val Hs' = Hs @ [LA_Logic.neg_prop concl]
   739     if count is_neq (map (LA_Data.decomp sg) Hs')
   722     if count is_neq (map (LA_Data.decomp sg) Hs')
   740       > !fast_arith_neq_limit then (
   723       > !fast_arith_neq_limit then (
   741       trace_msg ("fast_arith_neq_limit exceeded (current value is " ^ string_of_int (!fast_arith_neq_limit) ^ ")");
   724       trace_msg ("fast_arith_neq_limit exceeded (current value is " ^ string_of_int (!fast_arith_neq_limit) ^ ")");
   742       NONE
   725       NONE
   743     ) else
   726     ) else
   744       refute sg params show_ex do_pre Hs'
   727       refute sg params show_ex Hs'
   745   end;
   728   end;
       
   729 
       
   730 (* MetaSimplifier.simpset -> int * injust list -> Tactical.tactic *)
       
   731 
       
   732 fun refute_tac ss (i, justs) =
       
   733   fn state =>
       
   734     let val _ = trace_thm ("refute_tac (on subgoal " ^ Int.toString i ^ ", with " ^ Int.toString (length justs) ^ " justification(s)):") state
       
   735         val sg          = theory_of_thm state
       
   736         val {neqE, ...} = Data.get sg
       
   737         fun just1 j =
       
   738           REPEAT_DETERM (eresolve_tac neqE i) THEN                  (* eliminate inequalities *)
       
   739             METAHYPS (fn asms => rtac (mkthm (sg, ss) asms j) 1) i  (* use theorems generated from the actual justifications *)
       
   740     in DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN  (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *)
       
   741        DETERM (LA_Data.pre_tac i) THEN                               (* user-defined preprocessing of the subgoal *)
       
   742        PRIMITIVE (trace_thm "State after pre_tac:") THEN
       
   743        EVERY (map just1 justs)                                       (* prove every resulting subgoal, using its justification *)
       
   744     end  state;
   746 
   745 
   747 (*
   746 (*
   748 Fast but very incomplete decider. Only premises and conclusions
   747 Fast but very incomplete decider. Only premises and conclusions
   749 that are already (negated) (in)equations are taken into account.
   748 that are already (negated) (in)equations are taken into account.
   750 *)
   749 *)
   751 fun simpset_lin_arith_tac ss show_ex i st = SUBGOAL (fn (A,_) =>
   750 fun simpset_lin_arith_tac ss show_ex i st = SUBGOAL (fn (A,_) =>
   752   let val params = rev (Logic.strip_params A)
   751   let val params = rev (Logic.strip_params A)
   753       val Hs     = Logic.strip_assums_hyp A
   752       val Hs     = Logic.strip_assums_hyp A
   754       val concl  = Logic.strip_assums_concl A
   753       val concl  = Logic.strip_assums_concl A
   755   in trace_thm ("Trying to refute subgoal " ^ string_of_int i) st;
   754   in trace_thm ("Trying to refute subgoal " ^ string_of_int i) st;
   756      case prove (Thm.sign_of_thm st) params show_ex true Hs concl of
   755      case prove (Thm.sign_of_thm st) params show_ex Hs concl of
   757        NONE => (trace_msg "Refutation failed."; no_tac)
   756        NONE => (trace_msg "Refutation failed."; no_tac)
   758      | SOME js => (trace_msg "Refutation succeeded."; refute_tac ss (i, js))
   757      | SOME js => (trace_msg "Refutation succeeded."; refute_tac ss (i, js))
   759   end) i st;
   758   end) i st;
   760 
   759 
   761 fun lin_arith_tac show_ex i st =
   760 fun lin_arith_tac show_ex i st =
   766   cut_facts_tac (Simplifier.prems_of_ss ss) i THEN
   765   cut_facts_tac (Simplifier.prems_of_ss ss) i THEN
   767   simpset_lin_arith_tac ss false i;
   766   simpset_lin_arith_tac ss false i;
   768 
   767 
   769 (** Forward proof from theorems **)
   768 (** Forward proof from theorems **)
   770 
   769 
   771 (* More tricky code. Needs to arrange the proofs of the multiple cases (due
       
   772 to splits of ~= premises) such that it coincides with the order of the cases
       
   773 generated by function split_items. *)
       
   774 
       
   775 datatype splittree = Tip of thm list
       
   776                    | Spl of thm * cterm * splittree * cterm * splittree
       
   777 
       
   778 (* the cterm "(ct1 ==> ?R) ==> (ct2 ==> ?R) ==> ?R" is taken to (ct1, ct2) *)
       
   779 
       
   780 (* Thm.cterm -> Thm.cterm * Thm.cterm *)
       
   781 
       
   782 fun extract imp =
       
   783 let val (Il, r)    = Thm.dest_comb imp
       
   784     val (_, imp1)  = Thm.dest_comb Il
       
   785     val (Ict1, _)  = Thm.dest_comb imp1
       
   786     val (_, ct1)   = Thm.dest_comb Ict1
       
   787     val (Ir, _)    = Thm.dest_comb r
       
   788     val (_, Ict2r) = Thm.dest_comb Ir
       
   789     val (Ict2, _)  = Thm.dest_comb Ict2r
       
   790     val (_, ct2)   = Thm.dest_comb Ict2
       
   791 in (ct1, ct2) end;
       
   792 
       
   793 (* Theory.theory -> Thm.thm list -> splittree *)
       
   794 
       
   795 fun splitasms sg asms =
       
   796 let val {neqE, ...} = Data.get sg
       
   797     fun elim_neq (asms', []) = Tip (rev asms')
       
   798       | elim_neq (asms', asm::asms) =
       
   799       (case get_first (fn th => SOME (asm COMP th) handle THM _ => NONE) neqE of
       
   800         SOME spl =>
       
   801           let val (ct1, ct2) = extract (cprop_of spl)
       
   802               val thm1 = assume ct1
       
   803               val thm2 = assume ct2
       
   804           in Spl (spl, ct1, elim_neq (asms', asms@[thm1]), ct2, elim_neq (asms', asms@[thm2]))
       
   805           end
       
   806       | NONE => elim_neq (asm::asms', asms))
       
   807 in elim_neq ([], asms) end;
       
   808 
       
   809 (* Theory.theory * MetaSimplifier.simpset -> splittree -> injust list -> (Thm.thm, injust list) *)
       
   810 
       
   811 fun fwdproof ctxt (Tip asms) (j::js) = (mkthm ctxt asms j, js)
       
   812   | fwdproof ctxt (Spl (thm, ct1, tree1, ct2, tree2)) js =
       
   813     let val (thm1, js1) = fwdproof ctxt tree1 js
       
   814         val (thm2, js2) = fwdproof ctxt tree2 js1
       
   815         val thm1' = implies_intr ct1 thm1
       
   816         val thm2' = implies_intr ct2 thm2
       
   817     in (thm2' COMP (thm1' COMP thm), js2) end;
       
   818 (* needs handle THM _ => NONE ? *)
       
   819 
       
   820 (* Theory.theory * MetaSimplifier.simpset -> Thm.thm list -> Term.term -> injust list -> bool -> Thm.thm option *)
   770 (* Theory.theory * MetaSimplifier.simpset -> Thm.thm list -> Term.term -> injust list -> bool -> Thm.thm option *)
   821 
   771 
   822 fun prover (ctxt as (sg, ss)) thms Tconcl js pos =
   772 fun prover (ctxt as (sg, ss)) thms Tconcl js pos =
   823 let 
   773 let
   824 (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *)
       
   825 (* Use this code instead if lin_arith_prover calls prove with do_pre set to true *)
       
   826     (* There is no "forward version" of 'pre_tac'.  Therefore we combine the     *)
   774     (* There is no "forward version" of 'pre_tac'.  Therefore we combine the     *)
   827     (* available theorems into a single proof state and perform "backward proof" *)
   775     (* available theorems into a single proof state and perform "backward proof" *)
   828     (* using 'refute_tac'.                                                       *)
   776     (* using 'refute_tac'.                                                       *)
   829 (*
       
   830     val Hs    = map prop_of thms
   777     val Hs    = map prop_of thms
   831     val Prop  = fold (curry Logic.mk_implies) (rev Hs) Tconcl
   778     val Prop  = fold (curry Logic.mk_implies) (rev Hs) Tconcl
   832     val cProp = cterm_of sg Prop
   779     val cProp = cterm_of sg Prop
   833     val concl = Goal.init cProp
   780     val concl = Goal.init cProp
   834                   |> refute_tac ss (1, js)
   781                   |> refute_tac ss (1, js)
   835                   |> Seq.hd
   782                   |> Seq.hd
   836                   |> Goal.finish
   783                   |> Goal.finish
   837                   |> fold (fn thA => fn thAB => implies_elim thAB thA) thms
   784                   |> fold (fn thA => fn thAB => implies_elim thAB thA) thms
   838 *)
       
   839 (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *)
       
   840     val nTconcl       = LA_Logic.neg_prop Tconcl
       
   841     val cnTconcl      = cterm_of sg nTconcl
       
   842     val nTconclthm    = assume cnTconcl
       
   843     val tree          = splitasms sg (thms @ [nTconclthm])
       
   844     val (Falsethm, _) = fwdproof ctxt tree js
       
   845     val contr         = if pos then LA_Logic.ccontr else LA_Logic.notI
       
   846     val concl         = implies_intr cnTconcl Falsethm COMP contr
       
   847 in SOME (trace_thm "Proved by lin. arith. prover:"
   785 in SOME (trace_thm "Proved by lin. arith. prover:"
   848           (LA_Logic.mk_Eq concl)) end
   786           (LA_Logic.mk_Eq concl)) end
   849 (* in case concl contains ?-var, which makes assume fail: *)
   787 (* in case concl contains ?-var, which makes assume fail: *)
   850 handle THM _ => NONE;
   788 handle THM _ => NONE;
   851 
   789 
   865 (*
   803 (*
   866     val _ = trace_msg "lin_arith_prover"
   804     val _ = trace_msg "lin_arith_prover"
   867     val _ = map (trace_thm "thms:") thms
   805     val _ = map (trace_thm "thms:") thms
   868     val _ = trace_msg ("concl:" ^ Sign.string_of_term sg concl)
   806     val _ = trace_msg ("concl:" ^ Sign.string_of_term sg concl)
   869 *)
   807 *)
   870 in case prove sg [] false false Hs Tconcl of (* concl provable? *)
   808 in case prove sg [] false Hs Tconcl of (* concl provable? *)
   871      SOME js => prover (sg, ss) thms Tconcl js true
   809      SOME js => prover (sg, ss) thms Tconcl js true
   872    | NONE => let val nTconcl = LA_Logic.neg_prop Tconcl
   810    | NONE => let val nTconcl = LA_Logic.neg_prop Tconcl
   873           in case prove sg [] false false Hs nTconcl of (* ~concl provable? *)
   811           in case prove sg [] false Hs nTconcl of (* ~concl provable? *)
   874                SOME js => prover (sg, ss) thms nTconcl js false
   812                SOME js => prover (sg, ss) thms nTconcl js false
   875              | NONE => NONE
   813              | NONE => NONE
   876           end
   814           end
   877 end;
   815 end;
   878 
   816