(* ========================================================================= *) (* First order logic with equality. *) (* *) (* Copyright (c) 2003-2007, John Harrison. (See "LICENSE.txt" for details.) *) (* ========================================================================= *) let is_eq = function (Atom(R("=",_))) -> true | _ -> false;; let mk_eq s t = Atom(R("=",[s;t]));; let dest_eq fm = match fm with Atom(R("=",[s;t])) -> s,t | _ -> failwith "dest_eq: not an equation";; let lhs eq = fst(dest_eq eq) and rhs eq = snd(dest_eq eq);; (* ------------------------------------------------------------------------- *) (* The set of predicates in a formula. *) (* ------------------------------------------------------------------------- *) let rec predicates fm = atom_union (fun (R(p,a)) -> [p,length a]) fm;; (* ------------------------------------------------------------------------- *) (* Code to generate equality axioms for functions. *) (* ------------------------------------------------------------------------- *) let function_congruence (f,n) = if n = 0 then [] else let argnames_x = map (fun n -> "x"^(string_of_int n)) (1 -- n) and argnames_y = map (fun n -> "y"^(string_of_int n)) (1 -- n) in let args_x = map (fun x -> Var x) argnames_x and args_y = map (fun x -> Var x) argnames_y in let ant = end_itlist mk_and (map2 mk_eq args_x args_y) and con = mk_eq (Fn(f,args_x)) (Fn(f,args_y)) in [itlist mk_forall (argnames_x @ argnames_y) (Imp(ant,con))];; (* ------------------------------------------------------------------------- *) (* Example. *) (* ------------------------------------------------------------------------- *) START_INTERACTIVE;; function_congruence ("f",3);; function_congruence ("+",2);; END_INTERACTIVE;; (* ------------------------------------------------------------------------- *) (* And for predicates. *) (* ------------------------------------------------------------------------- *) let predicate_congruence (p,n) = if n = 0 then [] else let argnames_x = map (fun n -> "x"^(string_of_int n)) (1 -- n) and argnames_y = map (fun n -> "y"^(string_of_int n)) (1 -- n) in let args_x = map (fun x -> Var x) argnames_x and args_y = map (fun x -> Var x) argnames_y in let ant = end_itlist mk_and (map2 mk_eq args_x args_y) and con = Imp(Atom(R(p,args_x)),Atom(R(p,args_y))) in [itlist mk_forall (argnames_x @ argnames_y) (Imp(ant,con))];; (* ------------------------------------------------------------------------- *) (* Hence implement logic with equality just by adding equality "axioms". *) (* ------------------------------------------------------------------------- *) let equivalence_axioms = [<>; < y = z>>];; let equalitize fm = let allpreds = predicates fm in if not (mem ("=",2) allpreds) then fm else let preds = subtract allpreds ["=",2] and funcs = functions fm in let axioms = itlist (union ** function_congruence) funcs (itlist (union ** predicate_congruence) preds equivalence_axioms) in Imp(end_itlist mk_and axioms,fm);; (* ------------------------------------------------------------------------- *) (* A simple example (see EWD1266a and the application to Morley's theorem). *) (* ------------------------------------------------------------------------- *) START_INTERACTIVE;; let ewd = equalitize <<(forall x. f(x) ==> g(x)) /\ (exists x. f(x)) /\ (forall x y. g(x) /\ g(y) ==> x = y) ==> forall y. g(y) ==> f(y)>>;; meson ewd;; (* ------------------------------------------------------------------------- *) (* Wishnu Prasetya's example (even nicer with an "exists unique" primitive). *) (* ------------------------------------------------------------------------- *) let wishnu = equalitize <<(exists x. x = f(g(x)) /\ forall x'. x' = f(g(x')) ==> x = x') <=> (exists y. y = g(f(y)) /\ forall y'. y' = g(f(y')) ==> y = y')>>;; time meson wishnu;; (* ------------------------------------------------------------------------- *) (* More challenging equational problems. (Size 18, 61814 seconds.) *) (* ------------------------------------------------------------------------- *) (********* (meson ** equalitize) <<(forall x y z. x * (y * z) = (x * y) * z) /\ (forall x. 1 * x = x) /\ (forall x. i(x) * x = 1) ==> forall x. x * i(x) = 1>>;; ********) (* ------------------------------------------------------------------------- *) (* Other variants not mentioned in book. *) (* ------------------------------------------------------------------------- *) (************* (meson ** equalitize) <<(forall x y z. x * (y * z) = (x * y) * z) /\ (forall x. 1 * x = x) /\ (forall x. x * 1 = x) /\ (forall x. x * x = 1) ==> forall x y. x * y = y * x>>;; (* ------------------------------------------------------------------------- *) (* With symmetry at leaves and one-sided congruences (Size = 16, 54659 s). *) (* ------------------------------------------------------------------------- *) let fm = <<(forall x. x = x) /\ (forall x y z. x * (y * z) = (x * y) * z) /\ (forall x y z. =((x * y) * z,x * (y * z))) /\ (forall x. 1 * x = x) /\ (forall x. x = 1 * x) /\ (forall x. i(x) * x = 1) /\ (forall x. 1 = i(x) * x) /\ (forall x y. x = y ==> i(x) = i(y)) /\ (forall x y z. x = y ==> x * z = y * z) /\ (forall x y z. x = y ==> z * x = z * y) /\ (forall x y z. x = y /\ y = z ==> x = z) ==> forall x. x * i(x) = 1>>;; time meson fm;; (* ------------------------------------------------------------------------- *) (* Newer version of stratified equalities. *) (* ------------------------------------------------------------------------- *) let fm = <<(forall x y z. axiom(x * (y * z),(x * y) * z)) /\ (forall x y z. axiom((x * y) * z,x * (y * z)) /\ (forall x. axiom(1 * x,x)) /\ (forall x. axiom(x,1 * x)) /\ (forall x. axiom(i(x) * x,1)) /\ (forall x. axiom(1,i(x) * x)) /\ (forall x x'. x = x' ==> cchain(i(x),i(x'))) /\ (forall x x' y y'. x = x' /\ y = y' ==> cchain(x * y,x' * y'))) /\ (forall s t. axiom(s,t) ==> achain(s,t)) /\ (forall s t u. axiom(s,t) /\ (t = u) ==> achain(s,u)) /\ (forall x x' u. x = x' /\ achain(i(x'),u) ==> cchain(i(x),u)) /\ (forall x x' y y' u. x = x' /\ y = y' /\ achain(x' * y',u) ==> cchain(x * y,u)) /\ (forall s t. cchain(s,t) ==> s = t) /\ (forall s t. achain(s,t) ==> s = t) /\ (forall t. t = t) ==> forall x. x * i(x) = 1>>;; time meson fm;; let fm = <<(forall x y z. axiom(x * (y * z),(x * y) * z)) /\ (forall x y z. axiom((x * y) * z,x * (y * z)) /\ (forall x. axiom(1 * x,x)) /\ (forall x. axiom(x,1 * x)) /\ (forall x. axiom(i(x) * x,1)) /\ (forall x. axiom(1,i(x) * x)) /\ (forall x x'. x = x' ==> cong(i(x),i(x'))) /\ (forall x x' y y'. x = x' /\ y = y' ==> cong(x * y,x' * y'))) /\ (forall s t. axiom(s,t) ==> achain(s,t)) /\ (forall s t. cong(s,t) ==> cchain(s,t)) /\ (forall s t u. axiom(s,t) /\ (t = u) ==> achain(s,u)) /\ (forall s t u. cong(s,t) /\ achain(t,u) ==> cchain(s,u)) /\ (forall s t. cchain(s,t) ==> s = t) /\ (forall s t. achain(s,t) ==> s = t) /\ (forall t. t = t) ==> forall x. x * i(x) = 1>>;; time meson fm;; (* ------------------------------------------------------------------------- *) (* Showing congruence closure. *) (* ------------------------------------------------------------------------- *) let fm = equalitize < f(c) = c>>;; time meson fm;; let fm = < achain(s,t)) /\ (forall s t. cong(s,t) ==> cchain(s,t)) /\ (forall s t u. axiom(s,t) /\ (t = u) ==> achain(s,u)) /\ (forall s t u. cong(s,t) /\ achain(t,u) ==> cchain(s,u)) /\ (forall s t. cchain(s,t) ==> s = t) /\ (forall s t. achain(s,t) ==> s = t) /\ (forall t. t = t) /\ (forall x y. x = y ==> cong(f(x),f(y))) ==> f(c) = c>>;; time meson fm;; (* ------------------------------------------------------------------------- *) (* With stratified equalities. *) (* ------------------------------------------------------------------------- *) let fm = <<(forall x y z. eqA (x * (y * z),(x * y) * z)) /\ (forall x y z. eqA ((x * y) * z)) /\ (forall x. eqA (1 * x,x)) /\ (forall x. eqA (x,1 * x)) /\ (forall x. eqA (i(x) * x,1)) /\ (forall x. eqA (1,i(x) * x)) /\ (forall x. eqA (x,x)) /\ (forall x y. eqA (x,y) ==> eqC (i(x),i(y))) /\ (forall x y. eqC (x,y) ==> eqC (i(x),i(y))) /\ (forall x y. eqT (x,y) ==> eqC (i(x),i(y))) /\ (forall w x y z. eqA (w,x) /\ eqA (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqA (w,x) /\ eqC (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqA (w,x) /\ eqT (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqC (w,x) /\ eqA (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqC (w,x) /\ eqC (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqC (w,x) /\ eqT (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqT (w,x) /\ eqA (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqT (w,x) /\ eqC (y,z) ==> eqC (w * y,x * z)) /\ (forall w x y z. eqT (w,x) /\ eqT (y,z) ==> eqC (w * y,x * z)) /\ (forall x y z. eqA (x,y) /\ eqA (y,z) ==> eqT (x,z)) /\ (forall x y z. eqC (x,y) /\ eqA (y,z) ==> eqT (x,z)) /\ (forall x y z. eqA (x,y) /\ eqC (y,z) ==> eqT (x,z)) /\ (forall x y z. eqA (x,y) /\ eqT (y,z) ==> eqT (x,z)) /\ (forall x y z. eqC (x,y) /\ eqT (y,z) ==> eqT (x,z)) ==> forall x. eqT (x * i(x),1)>>;; (* ------------------------------------------------------------------------- *) (* With transitivity chains... *) (* ------------------------------------------------------------------------- *) let fm = <<(forall x y z. eqA (x * (y * z),(x * y) * z)) /\ (forall x y z. eqA ((x * y) * z)) /\ (forall x. eqA (1 * x,x)) /\ (forall x. eqA (x,1 * x)) /\ (forall x. eqA (i(x) * x,1)) /\ (forall x. eqA (1,i(x) * x)) /\ (forall x y. eqA (x,y) ==> eqC (i(x),i(y))) /\ (forall x y. eqC (x,y) ==> eqC (i(x),i(y))) /\ (forall w x y. eqA (w,x) ==> eqC (w * y,x * y)) /\ (forall w x y. eqC (w,x) ==> eqC (w * y,x * y)) /\ (forall x y z. eqA (y,z) ==> eqC (x * y,x * z)) /\ (forall x y z. eqC (y,z) ==> eqC (x * y,x * z)) /\ (forall x y z. eqA (x,y) /\ eqA (y,z) ==> eqT (x,z)) /\ (forall x y z. eqC (x,y) /\ eqA (y,z) ==> eqT (x,z)) /\ (forall x y z. eqA (x,y) /\ eqC (y,z) ==> eqT (x,z)) /\ (forall x y z. eqC (x,y) /\ eqC (y,z) ==> eqT (x,z)) /\ (forall x y z. eqA (x,y) /\ eqT (y,z) ==> eqT (x,z)) /\ (forall x y z. eqC (x,y) /\ eqT (y,z) ==> eqT (x,z)) ==> forall x. eqT (x * i(x),1) \/ eqC (x * i(x),1)>>;; time meson fm;; (* ------------------------------------------------------------------------- *) (* Enforce canonicity (proof size = 20). *) (* ------------------------------------------------------------------------- *) let fm = <<(forall x y z. eq1(x * (y * z),(x * y) * z)) /\ (forall x y z. eq1((x * y) * z,x * (y * z))) /\ (forall x. eq1(1 * x,x)) /\ (forall x. eq1(x,1 * x)) /\ (forall x. eq1(i(x) * x,1)) /\ (forall x. eq1(1,i(x) * x)) /\ (forall x y z. eq1(x,y) ==> eq1(x * z,y * z)) /\ (forall x y z. eq1(x,y) ==> eq1(z * x,z * y)) /\ (forall x y z. eq1(x,y) /\ eq2(y,z) ==> eq2(x,z)) /\ (forall x y. eq1(x,y) ==> eq2(x,y)) ==> forall x. eq2(x,i(x))>>;; time meson fm;; ******************) END_INTERACTIVE;;