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
(* ========================================================================= *) (* Relation between FOL and propositonal logic; Herbrand theorem. *) (* *) (* Copyright (c) 2003, John Harrison. (See "LICENSE.txt" for details.) *) (* ========================================================================= *) (* ------------------------------------------------------------------------- *) (* We want to generalize a formula before negating and refuting. *) (* ------------------------------------------------------------------------- *) let generalize fm = itlist (fun x p -> Forall(x,p)) (fv fm) fm;; (* ------------------------------------------------------------------------- *) (* Propositional valuation. *) (* ------------------------------------------------------------------------- *) let pholds d fm = eval fm (fun p -> d(Atom p));; (* ------------------------------------------------------------------------- *) (* Characteristic function of Herbrand interpretation for p. *) (* ------------------------------------------------------------------------- *) let rec herbdom funcs tm = match tm with Var _ -> false | Fn(f,a) -> mem (f,length a) funcs & forall (herbdom funcs) a;; (* ------------------------------------------------------------------------- *) (* Get the constants for Herbrand base, adding nullary one if necessary. *) (* ------------------------------------------------------------------------- *) let herbfuns fm = let cns,fns = partition (fun (_,ar) -> ar = 0) (functions fm) in if cns = [] then ["c",0],fns else cns,fns;; (* ------------------------------------------------------------------------- *) (* Enumeration of ground terms and m-tuples, ordered by total fns. *) (* ------------------------------------------------------------------------- *) let rec groundterms cntms funcs n = if n = 0 then cntms else itlist (fun (f,m) -> (@) (map (fun args -> Fn(f,args)) (groundtuples cntms funcs (n - 1) m))) funcs [] and groundtuples cntms funcs n m = if m = 0 then if n = 0 then [[]] else [] else itlist (fun k -> (@) (allpairs (fun h t -> h::t) (groundterms cntms funcs k) (groundtuples cntms funcs (n - k) (m - 1)))) (0 -- n) [];; (* ------------------------------------------------------------------------- *) (* Iterate modifier "mfn" over ground terms till "tfn" fails. *) (* ------------------------------------------------------------------------- *) let rec herbloop mfn tfn fl0 cntms funcs fvs n fl tried tuples = print_string(string_of_int(length tried)^" ground instances tried; "^ string_of_int(length fl)^" items in list"); print_newline(); match tuples with [] -> let newtups = groundtuples cntms funcs n (length fvs) in herbloop mfn tfn fl0 cntms funcs fvs (n + 1) fl tried newtups | tup::tups -> let fl' = mfn fl0 (formsubst(instantiate fvs tup)) fl in if not(tfn fl') then tup::tried else herbloop mfn tfn fl0 cntms funcs fvs n fl' (tup::tried) tups;; (* ------------------------------------------------------------------------- *) (* Hence a simple Gilmore-type procedure. *) (* ------------------------------------------------------------------------- *) let gilmore_loop = let mfn djs0 ifn djs = filter (non contradictory) (distrib (smap (smap ifn) djs0) djs) in herbloop mfn (fun djs -> djs <> []);; let gilmore fm = let sfm = skolemize(Not(generalize fm)) in let fvs = fv sfm and consts,funcs = herbfuns sfm in let cntms = smap (fun (c,_) -> Fn(c,[])) consts in length(gilmore_loop (simpdnf sfm) cntms funcs fvs 0 [[]] [] []);; (* ------------------------------------------------------------------------- *) (* First example and a little tracing. *) (* ------------------------------------------------------------------------- *) START_INTERACTIVE;; gilmore < P(y)>>;; let sfm = skolemize(Not < P(y)>>);; (* ------------------------------------------------------------------------- *) (* Quick examples. *) (* ------------------------------------------------------------------------- *) let p19 = gilmore < Q(z)) ==> P(x) ==> Q(x)>>;; let p24 = gilmore <<~(exists x. U(x) /\ Q(x)) /\ (forall x. P(x) ==> Q(x) \/ R(x)) /\ ~(exists x. P(x) ==> (exists x. Q(x))) /\ (forall x. Q(x) /\ R(x) ==> U(x)) ==> (exists x. P(x) /\ R(x))>>;; let p39 = gilmore <<~(exists x. forall y. P(y,x) <=> ~P(y,y))>>;; let p42 = gilmore <<~(exists y. forall x. P(x,y) <=> ~(exists z. P(x,z) /\ P(z,x)))>>;; let p44 = gilmore <<(forall x. P(x) ==> (exists y. G(y) /\ H(x,y)) /\ (exists y. G(y) /\ ~H(x,y))) /\ (exists x. J(x) /\ (forall y. G(y) ==> H(x,y))) ==> (exists x. J(x) /\ ~P(x))>>;; let p59 = gilmore <<(forall x. P(x) <=> ~P(f(x))) ==> (exists x. P(x) /\ ~P(f(x)))>>;; (* ------------------------------------------------------------------------- *) (* Slightly less easy examples. *) (* ------------------------------------------------------------------------- *) let p45 = gilmore <<(forall x. P(x) /\ (forall y. G(y) /\ H(x,y) ==> J(x,y)) ==> (forall y. G(y) /\ H(x,y) ==> R(y))) /\ ~(exists y. L(y) /\ R(y)) /\ (exists x. P(x) /\ (forall y. H(x,y) ==> L(y)) /\ (forall y. G(y) /\ H(x,y) ==> J(x,y))) ==> (exists x. P(x) /\ ~(exists y. G(y) /\ H(x,y)))>>;; let p60 = gilmore < exists y. (forall z. P(z,y) ==> P(z,f(x))) /\ P(x,y)>>;; let p43 = gilmore <<(forall x y. Q(x,y) <=> forall z. P(z,x) <=> P(z,y)) ==> forall x y. Q(x,y) <=> Q(y,x)>>;; END_INTERACTIVE;; (* ------------------------------------------------------------------------- *) (* The Davis-Putnam procedure for first order logic. *) (* ------------------------------------------------------------------------- *) let clausal fm = smap (smap negate) (simpdnf(nnf(Not fm)));; let dp_mfn cjs0 ifn cjs = union (smap (smap ifn) cjs0) cjs;; let dp_loop = herbloop dp_mfn dpll;; let davisputnam fm = let sfm = skolemize(Not(generalize fm)) in if sfm = False then 0 else if sfm = True then failwith "davisputnam" else let fvs = fv sfm and consts,funcs = herbfuns sfm in let cntms = smap (fun (c,_) -> Fn(c,[])) consts in length(dp_loop (clausal sfm) cntms funcs fvs 0 [] [] []);; (* ------------------------------------------------------------------------- *) (* Show how much better than the Gilmore procedure this can be. *) (* ------------------------------------------------------------------------- *) START_INTERACTIVE;; let p20 = davisputnam <<(forall x y. exists z. forall w. P(x) /\ Q(y) ==> R(z) /\ U(w)) ==> (exists x y. P(x) /\ Q(y)) ==> (exists z. R(z))>>;; END_INTERACTIVE;; (* ------------------------------------------------------------------------- *) (* Show the sensitivity to order: try also with variant suggested. *) (* ------------------------------------------------------------------------- *) let rec herbloop' mfn tfn fl0 cntms funcs fvs n fl tried tuples = print_string(string_of_int(length tried)^" ground instances tried; "^ string_of_int(length fl)^" items in list"); print_newline(); match tuples with [] -> let newtups = rev(groundtuples cntms funcs n (length fvs)) in herbloop' mfn tfn fl0 cntms funcs fvs (n + 1) fl tried newtups | tup::tups -> let fl' = mfn fl0 (formsubst(instantiate fvs tup)) fl in if not(tfn fl') then tup::tried else herbloop' mfn tfn fl0 cntms funcs fvs n fl' (tup::tried) tups;; let dp_loop' = herbloop' (fun cjs0 ifn cjs -> union (smap (smap ifn) cjs0) cjs) dpll;; let davisputnam' fm = let sfm = skolemize(Not(generalize fm)) in if sfm = False then 0 else if sfm = True then failwith "davisputnam" else let fvs = fv sfm and consts,funcs = herbfuns sfm in let cntms = smap (fun (c,_) -> Fn(c,[])) consts in length(dp_loop' (clausal sfm) cntms funcs fvs 0 [] [] []);; START_INTERACTIVE;; let p36 = davisputnam <<(forall x. exists y. P(x,y)) /\ (forall x. exists y. G(x,y)) /\ (forall x y. P(x,y) \/ G(x,y) ==> (forall z. P(y,z) \/ G(y,z) ==> H(x,z))) ==> (forall x. exists y. H(x,y))>>;; let p36 = davisputnam' <<(forall x. exists y. P(x,y)) /\ (forall x. exists y. G(x,y)) /\ (forall x y. P(x,y) \/ G(x,y) ==> (forall z. P(y,z) \/ G(y,z) ==> H(x,z))) ==> (forall x. exists y. H(x,y))>>;; let p29 = davisputnam <<(exists x. P(x)) /\ (exists x. G(x)) ==> ((forall x. P(x) ==> H(x)) /\ (forall x. G(x) ==> J(x)) <=> (forall x y. P(x) /\ G(y) ==> H(x) /\ J(y)))>>;; let p29 = davisputnam' <<(exists x. P(x)) /\ (exists x. G(x)) ==> ((forall x. P(x) ==> H(x)) /\ (forall x. G(x) ==> J(x)) <=> (forall x y. P(x) /\ G(y) ==> H(x) /\ J(y)))>>;; END_INTERACTIVE;; (* ------------------------------------------------------------------------- *) (* Try to cut out useless instantiations in final result. *) (* ------------------------------------------------------------------------- *) let rec dp_refine cjs0 fvs dunno need = match dunno with [] -> need | cl::dknow -> let mfn = dp_mfn cjs0 ** formsubst ** instantiate fvs in let need' = if dpll(itlist mfn (need @ dknow) []) then cl::need else need in dp_refine cjs0 fvs dknow need';; let dp_refine_loop cjs0 cntms funcs fvs n cjs tried tuples = let tups = dp_loop cjs0 cntms funcs fvs n cjs tried tuples in dp_refine cjs0 fvs tups [];; (* ------------------------------------------------------------------------- *) (* Show how few of the instances we really need. Hence unification! *) (* ------------------------------------------------------------------------- *) let davisputnam'' fm = let sfm = skolemize(Not(generalize fm)) in if sfm = False then 0 else if sfm = True then failwith "davisputnam" else let fvs = fv sfm and consts,funcs = herbfuns sfm in let cntms = smap (fun (c,_) -> Fn(c,[])) consts in length(dp_refine_loop (clausal sfm) cntms funcs fvs 0 [] [] []);; START_INTERACTIVE;; let p36 = davisputnam'' <<(forall x. exists y. P(x,y)) /\ (forall x. exists y. G(x,y)) /\ (forall x y. P(x,y) \/ G(x,y) ==> (forall z. P(y,z) \/ G(y,z) ==> H(x,z))) ==> (forall x. exists y. H(x,y))>>;; let p29 = davisputnam'' <<(exists x. P(x)) /\ (exists x. G(x)) ==> ((forall x. P(x) ==> H(x)) /\ (forall x. G(x) ==> J(x)) <=> (forall x y. P(x) /\ G(y) ==> H(x) /\ J(y)))>>;; END_INTERACTIVE;;