Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
(* ========================================================================= *) (* Goals, LCF-like tactics and Mizar-like proofs. *) (* *) (* Copyright (c) 2003, John Harrison. (See "LICENSE.txt" for details.) *) (* ========================================================================= *) type goals = Goals of ((string * fol formula) list * fol formula)list * (Proven.thm list -> Proven.thm);; (* ------------------------------------------------------------------------- *) (* Printer for goals (just shows first goal plus total number). *) (* ------------------------------------------------------------------------- *) let print_goal = let print_hyp (l,fm) = open_hbox(); print_string(l^":"); print_space(); print_formula print_atom 0 fm; print_newline(); close_box() in fun (Goals(gls,jfn)) -> match gls with (asl,w)::ogls -> print_newline(); (if ogls = [] then print_string "1 subgoal:" else (print_int (length gls); print_string " subgoals starting with")); print_newline(); do_list print_hyp (rev asl); print_string "---> "; open_hvbox 0; print_formula print_atom 0 w; close_box(); print_newline() | [] -> print_string "No subgoals";; START_INTERACTIVE;; #install_printer print_goal;; END_INTERACTIVE;; (* ------------------------------------------------------------------------- *) (* Setting up goals and terminating them in a theorem. *) (* ------------------------------------------------------------------------- *) let set_goal fm = let chk th = if concl th = fm then th else failwith "wrong theorem" in Goals([[],fm],fun [th] -> chk(modusponens th truth));; let extract_thm gls = match gls with Goals([],jfn) -> jfn [] | _ -> failwith "extract_thm: unsolved goals";; (* ------------------------------------------------------------------------- *) (* Running a series of proof steps one by one on goals. *) (* ------------------------------------------------------------------------- *) let run prf g = itlist (fun f -> f) (rev prf) g;; (* ------------------------------------------------------------------------- *) (* Handy idiom for tactic that does not split subgoals. *) (* ------------------------------------------------------------------------- *) let jmodify jfn tfn ths = match ths with (th::oths) -> jfn(tfn th :: oths) | _ -> failwith "jmodify: no first theorem";; (* ------------------------------------------------------------------------- *) (* Append contextual hypothesis to unconditional theorem. *) (* ------------------------------------------------------------------------- *) let assumptate (Goals((asl,w)::gls,jfn)) th = add_assum (list_conj (map snd asl)) th;; (* ------------------------------------------------------------------------- *) (* Turn assumptions p1,...,pn into theorems |- p1 /\ ... /\ pn ==> pi *) (* ------------------------------------------------------------------------- *) let rec assumps asl = match asl with [] -> [] | [l,p] -> [l,imp_refl p] | (l,p)::lps -> let ths = assumps lps in let q = antecedent(concl(snd(hd ths))) in let rth = and_right p q in (l,and_left p q)::map (fun (l,th) -> l,imp_trans rth th) ths;; let firstassum asl = let p = snd(hd asl) and q = list_conj(map snd (tl asl)) in if tl asl = [] then imp_refl p else and_left p q;; (* ------------------------------------------------------------------------- *) (* Another inference rule: |- P[t] ==> exists x. P[x] *) (* ------------------------------------------------------------------------- *) let right_exists x t p = let th1 = ispec t (Forall(x,Not p)) in let Not(p') = consequent(concl th1) in let th2 = imp_trans th1 (iff_imp1(axiom_not p')) in let th3 = imp_add_concl False th2 in let th4 = imp_trans (imp_swap(imp_refl(Imp(p',False)))) th3 in let th5 = imp_trans th4 (iff_imp2(axiom_not(Forall(x,Not p)))) in imp_trans th5 (iff_imp2(axiom_exists x p));; (* ------------------------------------------------------------------------- *) (* Two simple natural deduction constructs. *) (* ------------------------------------------------------------------------- *) let fix a (Goals((asl,(Forall(x,p) as fm))::gls,jfn)) = if exists (mem a ** fv ** snd) asl then failwith "fix: variable free in assumptions" else let p' = formsubst(x := Var a) p in let jfn' = jmodify jfn (fun th -> imp_trans (gen_right a th) (alpha x (Forall(a,p')))) in Goals((asl,p')::gls,jfn');; let take s (Goals((asl,(Exists(x,p) as fm))::gls,jfn)) = let t = parset s in let p' = formsubst(x := t) p in let jfn' = jmodify jfn (fun th -> imp_trans th (right_exists x t p)) in Goals((asl,p')::gls,jfn');; (* ------------------------------------------------------------------------- *) (* Parse a labelled formula, recognizing "thesis" and "antecedent" *) (* ------------------------------------------------------------------------- *) let expand_atom thesis at = match at with R("antecedent",[]) -> (try fst(dest_imp thesis) with Failure _ -> Atom at) | R("thesis",[]) -> thesis | _ -> Atom at;; let expand thesis fm = onatoms (expand_atom thesis) fm;; (* ------------------------------------------------------------------------- *) (* Restore old version. *) (* ------------------------------------------------------------------------- *) let thesis = "thesis";; let parself (Goals((asl,w)::gls,jfn)) toks = match toks with name::":"::toks -> let fm,toks' = parse_formula parse_atom [] toks in (name,expand w fm),toks' | toks -> let fm,toks' = parse_formula parse_atom [] toks in ("",expand w fm),toks';; let rec parselfs g toks = let res1,toks' = parself g toks in match toks' with "and"::toks'' -> let ress,toks''' = parselfs g toks'' in res1::ress,toks''' | _ -> [res1],toks';; let parse_labelled_formulas g s = let fms,l = parselfs g (lex(explode s)) in let fm = end_itlist (fun p q -> And(p,q)) (map snd fms) in if l = [] then fms,fm else failwith "parse_labelled_formulas: unparsed input";; let parse_labelled_formula g s = match parse_labelled_formulas g s with [s,p],p' -> s,p | _ -> failwith "too many formulas";; (* ------------------------------------------------------------------------- *) (* |- p1 /\ .. /\ pn ==> q to |- pi+1 /\ ... /\ pn ==> p1 /\ .. /\ pi ==> q *) (* ------------------------------------------------------------------------- *) let multishunt i th = let th1 = funpow i (imp_swap ** shunt) th in let th2 = funpow (i-1) (ante_conj ** imp_front 2) (imp_swap th1) in imp_swap th2;; (* ------------------------------------------------------------------------- *) (* Add labelled formulas to the assumption list. *) (* ------------------------------------------------------------------------- *) let assume s (Goals((asl,Imp(p,q))::gls,jfn) as gl) = let (lps,p') = parse_labelled_formulas gl s in if p <> p' then failwith "assume: doesn't match antecedent" else let jfn' = jmodify jfn (fun th -> if asl = [] then add_assum True th else multishunt (length lps) th) in Goals((lps@asl,q)::gls,jfn');; (* ------------------------------------------------------------------------- *) (* Delayed version of tableau rule, for speed of first phase. *) (* ------------------------------------------------------------------------- *) let delayed_tab_rule fm0 = let fvs = fv fm0 in let fm1 = itlist (fun x p -> Forall(x,p)) fvs fm0 in let fm = nnf(simplify(Not fm1)) in let sfm,sks = gaskolemize fm in let _,proof = tabrefute_log [sfm] in fun () -> let thn = iff_imp1((then_conv simplify_conv nnf_conv) (Not fm1)) in let skts,[] = exinsts proof [fm,undefined,sks] [] in let rfn = itlist2 (fun k t -> t |-> Var("_"^string_of_int k)) (1 -- length skts) skts undefined in let skins = skolem_hyps rfn sks skts in let shyps = sortskohyps(itlist (@) skins []) [] in let th1,[] = reconstruct shyps rfn proof [fm,skins] [] in let th2 = funpow (length shyps) (skoscrub ** imp_swap) th1 in let th3 = imp_trans (imp_trans (iff_imp2(axiom_not fm1)) thn) th2 in let th4 = modusponens (axiom_doubleneg fm1) th3 in itlist (fun x -> spec (Var x)) (rev fvs) th4;; (* ------------------------------------------------------------------------- *) (* Main automatic justification step. *) (* ------------------------------------------------------------------------- *) let justify byfn hyps gl p = let ps,ths = byfn hyps p gl in if ps = [p] then fun () -> hd(ths()) else let fm = itlist (fun a b -> Imp(a,b)) ps p in let fn = delayed_tab_rule fm in fun () -> if ps = [] then assumptate gl (fn()) else imp_trans_chain (ths()) (fn());; (* ------------------------------------------------------------------------- *) (* Produce canonical theorem from list of theorems or assumption labels. *) (* ------------------------------------------------------------------------- *) let by hyps p (Goals((asl,w)::gls,jfn)) = map (fun s -> assoc s asl) hyps, fun () -> let ths = assumps asl in map (fun s -> assoc s ths) hyps;; (* ------------------------------------------------------------------------- *) (* Import "external" theorem. *) (* ------------------------------------------------------------------------- *) let using ths p g = let ths' = map (fun th -> itlist gen (fv(concl th)) th) ths in map concl ths',fun () -> map (assumptate g) ths';; (* ------------------------------------------------------------------------- *) (* Trivial justification, producing no hypotheses. *) (* ------------------------------------------------------------------------- *) let at once p gl = ([],fun x -> []) and once = [];; (* ------------------------------------------------------------------------- *) (* Main actions on canonical theorem. *) (* ------------------------------------------------------------------------- *) let have s byfn hyps (Goals((asl,w)::gls,jfn) as gl) = let (l,p) = parse_labelled_formula gl s in let th = justify byfn hyps gl p in let mfn = if asl = [] then fun pth -> imp_trans (th()) pth else fun pth -> imp_unduplicate (imp_trans (th()) (shunt pth)) in Goals(((l,p)::asl,w)::gls,jmodify jfn mfn);; let case_split s byfn hyps (Goals((asl,w)::gls,jfn) as gl) = let (l,(Or(p,q) as fm)) = parse_labelled_formula gl s in let th = justify byfn hyps gl fm in let jfn' (pth::qth::ths) = let th1 = ante_disj (shunt pth) (shunt qth) in let th2 = imp_unduplicate(imp_trans (th()) th1) in jfn (th2::ths) in Goals(((l,p)::asl,w)::((l,q)::asl,w)::gls,jfn');; let consider (a,s) byfn hyps (Goals((asl,w)::gls,jfn) as gl) = if exists (mem a ** fv) (w::map snd asl) then failwith "consider: variable free in assumptions" else let (l,p) = parse_labelled_formula gl s in let th = justify byfn hyps gl (Exists(a,p)) in let jfn' = jmodify jfn (fun pth -> imp_unduplicate (imp_trans (th()) (exists_left a (shunt pth)))) in Goals(((l,p)::asl,w)::gls,jfn');; (* ------------------------------------------------------------------------- *) (* Thesis modification. *) (* ------------------------------------------------------------------------- *) let modifythesis fm thesis = if fm = thesis then (True,fun fth tth -> fth) else match thesis with And(p,q) -> if fm <> p then failwith "modifythesis: doesn't match first conjunct" else (q,fun pth qth -> imp_trans_chain [pth; qth] (and_pair p q)) | Iff(p,q) -> if fm <> Imp(p,q) then failwith "modifythesis: doesn't match implication" else (Imp(q,p),fun pth qth -> imp_trans_chain [pth; qth] (axiom_impiff p q)) | _ -> failwith "modifythesis: don't have anything to do";; (* ------------------------------------------------------------------------- *) (* Terminating steps. *) (* ------------------------------------------------------------------------- *) let thus s byfn hyps gl0 = let (Goals((asl,w)::gls,jfn) as gl) = have s byfn hyps gl0 in let fm = snd(hd asl) in let (p,rfn) = modifythesis fm w in Goals((asl,p)::gls,fun (pth::ths) -> let th = firstassum asl in jfn((rfn th pth) :: ths));; let qed (Goals((asl,w)::gls,jfn) as gl) = if w <> True then failwith "qed: unproven thesis" else Goals(gls,fun ths -> jfn(truth :: ths));; (* ------------------------------------------------------------------------- *) (* The "so" continuation. *) (* ------------------------------------------------------------------------- *) let so cont args byfn hyps (Goals((asl,w)::gls,jfn) as gl) = cont args (fun hyps p g -> let ps,ths = byfn hyps p g in snd(hd asl)::ps,fun () -> firstassum asl::ths()) hyps gl;; let hence args byfn hyps gl = so thus args byfn hyps gl;; (* ------------------------------------------------------------------------- *) (* Nested sub-proof using same model. *) (* ------------------------------------------------------------------------- *) let proof prf p (Goals((asl,w)::gls,jfn)) = match (run prf (Goals([asl,p],hd))) with Goals([],fn) -> [p],(fun () -> [fn []]) | _ -> failwith "unsolved goals in nested proof";; (* ------------------------------------------------------------------------- *) (* General proof construct. *) (* ------------------------------------------------------------------------- *) let prove fm prf = let gls = run prf (set_goal fm) in print_string "Goals proved; reconstructing..."; print_newline(); extract_thm gls;; (* ------------------------------------------------------------------------- *) (* Examples. *) (* ------------------------------------------------------------------------- *) START_INTERACTIVE;; prove < (forall x. p(x) ==> p(f(x))) ==> exists y. p(y) /\ p(f(y))>> [thus thesis at once; qed];; prove <<(forall x. x <= x) /\ (forall x y z. x <= y /\ y <= z ==> x <= z) /\ (forall x y. f(x) <= y <=> x <= g(y)) ==> (forall x y. x <= y ==> f(x) <= f(y)) /\ (forall x y. x <= y ==> g(x) <= g(y))>> [assume "A: antecedent"; hence "forall x y. x <= y ==> f(x) <= f(y)" at once; thus thesis by ["A"]; qed];; prove <<(exists x. p(x)) ==> (forall x. p(x) ==> p(f(x))) ==> exists y. p(f(f(f(f(y)))))>> [assume "A: exists x. p(x)"; assume "B: forall x. p(x) ==> p(f(x))"; have "C: forall x. p(x) ==> p(f(f(f(f(x)))))" proof [have "forall x. p(x) ==> p(f(f(x)))" by ["B"]; hence thesis at once; qed]; consider ("a","p(a)") by ["A"]; take "a"; hence thesis by ["C"]; qed];; END_INTERACTIVE;;