aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/romega/refl_omega.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/romega/refl_omega.ml')
-rw-r--r--contrib/romega/refl_omega.ml855
1 files changed, 855 insertions, 0 deletions
diff --git a/contrib/romega/refl_omega.ml b/contrib/romega/refl_omega.ml
new file mode 100644
index 000000000..3974ab39c
--- /dev/null
+++ b/contrib/romega/refl_omega.ml
@@ -0,0 +1,855 @@
+(*************************************************************************
+
+ PROJET RNRT Calife - 2001
+ Author: Pierre Crégut - France Télécom R&D
+ Licence : LGPL version 2.1
+
+ *************************************************************************)
+
+open Const_omega
+
+
+(* \section{Utilitaires} *)
+
+let debug = ref false
+
+let (>>) = Tacticals.tclTHEN
+
+let index t =
+ let rec loop i = function
+ | (u::l) -> if u = t then i else loop (i+1) l
+ | [] -> raise Not_found in
+ loop 0
+
+let mkApp = Term.mkApp
+
+(* \section{Formules réifiables} *)
+type oformula =
+ | Oplus of oformula * oformula
+ | Ominus of oformula * oformula
+ | Oinv of oformula
+ | Otimes of oformula * oformula
+ | Oatom of int
+ | Oz of int
+ | Oufo of oformula
+
+let rec oprint = function
+ | Oplus(t1,t2) ->
+ print_string "("; oprint t1; print_string "+";
+ oprint t2; print_string ")"
+ | Ominus(t1,t2) ->
+ print_string "("; oprint t1; print_string "-";
+ oprint t2; print_string ")"
+ | Oinv t -> print_string "~"; oprint t
+ | Otimes (t1,t2) ->
+ print_string "("; oprint t1; print_string "*";
+ oprint t2; print_string ")"
+ | Oatom i ->print_string "V"; print_int i
+ | Oz i -> print_int i
+ | Oufo f -> print_string "?"
+
+(* \section{Tables} *)
+
+let get_hyp env_hyp id =
+ try index id env_hyp
+ with Not_found -> failwith ("get_hyp " ^ string_of_int id)
+
+let tag_equation,tag_of_equation, clear_tags =
+ let l = ref ([]:(int * Names.identifier) list) in
+ (fun id h -> l := (h,id):: !l),
+ (fun h -> try List.assoc h !l with Not_found-> failwith "tag_hypothesis"),
+ (fun () -> l := [])
+
+let add_atom t env =
+ try index t env, env
+ with Not_found -> List.length env, (env@[t])
+
+let get_atom v env =
+ try List.nth v env with _ -> failwith "get_atom"
+
+(* compilation des environnements *)
+
+let intern_id, intern_id_force, unintern_id, clear_intern =
+ let c = ref 0 in
+ let l = ref [] in
+ (fun t ->
+ try List.assoc t !l
+ with Not_found -> incr c; let v = !c in l := (t,v)::!l; v),
+ (fun t v -> l := (t,v) :: !l),
+ (fun i ->
+ let rec loop = function
+ [] -> failwith "unintern"
+ | ((t,j)::l) -> if i = j then t else loop l in
+ loop !l),
+ (fun () -> c := 0; l := [])
+
+(* Le poids d'un terme : fondamental pour classer les variables *)
+
+let rec weight = function
+ | Oatom _ as c -> intern_id c
+ | Oz _ -> -1
+ | Oinv c -> weight c
+ | Otimes(c,_) -> weight c
+ | Oplus _ -> failwith "weight"
+ | Ominus _ -> failwith "weight minus"
+ | Oufo _ -> -1
+
+(* \section{Passage entre oformules et
+ représentation interne de Omega} *)
+
+(* \subsection{Oformula vers Omega} *)
+
+let compile name kind =
+ let rec loop accu = function
+ | Oplus(Otimes(v,Oz n),r) ->
+ loop ({Omega.v=intern_id v; Omega.c=n} :: accu) r
+ | Oz n ->
+ let id = Omega.new_id () in
+ tag_equation name id;
+ {Omega.kind = kind; Omega.body = List.rev accu;
+ Omega.constant = n; Omega.id = id}
+ | t -> print_string "CO"; oprint t; failwith "compile_equation" in
+ loop []
+
+(* \subsection{Omega vers Oformula} *)
+
+let rec decompile af =
+ let rec loop = function
+ | ({Omega.v=v; Omega.c=n}::r) -> Oplus(Otimes(unintern_id v,Oz n),loop r)
+ | [] -> Oz af.Omega.constant in
+ loop af.Omega.body
+
+(* \subsection{Oformula vers COQ reel} *)
+
+let rec coq_of_formula env t =
+ let rec loop = function
+ | Oplus (t1,t2) -> mkApp(Lazy.force coq_Zplus, [| loop t1; loop t2 |])
+ | Oinv t -> mkApp(Lazy.force coq_Zopp, [| loop t |])
+ | Otimes(t1,t2) -> mkApp(Lazy.force coq_Zmult, [| loop t1; loop t2 |])
+ | Oz v -> mk_Z v
+ | Oufo t -> loop t
+ | Oatom i -> get_atom env i
+ | Ominus(t1,t2) -> mkApp(Lazy.force coq_Zminus, [| loop t1; loop t2 |]) in
+ loop t
+
+(* \subsection{Oformula vers COQ reifié} *)
+
+let rec val_of_formula = function
+ | Oplus (t1,t2) ->
+ mkApp(Lazy.force coq_t_plus, [| val_of_formula t1; val_of_formula t2 |])
+ | Oinv t ->
+ mkApp(Lazy.force coq_t_opp, [| val_of_formula t |])
+ | Otimes(t1,t2) ->
+ mkApp(Lazy.force coq_t_mult, [| val_of_formula t1; val_of_formula t2 |])
+ | Oz v -> mkApp (Lazy.force coq_t_nat, [| mk_Z v |])
+ | Oufo t -> val_of_formula t
+ | Oatom i -> mkApp(Lazy.force coq_t_var, [| mk_nat i |])
+ | Ominus(t1,t2) ->
+ mkApp(Lazy.force coq_t_minus, [| val_of_formula t1; val_of_formula t2 |])
+
+(* \subsection{Omega vers COQ réifié} *)
+
+let val_of body constant =
+ let coeff_constant =
+ mkApp(Lazy.force coq_t_nat, [| mk_Z constant |]) in
+ let mk_coeff {Omega.c=c; Omega.v=v} t =
+ let coef = mkApp(Lazy.force coq_t_mult,
+ [|val_of_formula (unintern_id v );
+ mkApp(Lazy.force coq_t_nat, [| mk_Z c |]) |]) in
+ mkApp(Lazy.force coq_t_plus, [|coef; t |]) in
+ List.fold_right mk_coeff body coeff_constant
+
+(* \section{Opérations sur les équations}
+Ces fonctions préparent les traces utilisées par la tactique réfléchie
+pour faire des opérations de normalisation sur les équations. *)
+
+(* \subsection{Multiplication par un scalaire} *)
+let rec scalar n = function
+ Oplus(t1,t2) ->
+ let tac1,t1' = scalar n t1 and
+ tac2,t2' = scalar n t2 in
+ do_list [Lazy.force coq_c_mult_plus_distr; do_both tac1 tac2],
+ Oplus(t1',t2')
+ | Oinv t ->
+ do_list [Lazy.force coq_c_mult_opp_left], Otimes(t,Oz(-n))
+ | Otimes(t1,Oz x) ->
+ do_list [Lazy.force coq_c_mult_assoc_reduced], Otimes(t1,Oz (n*x))
+ | Otimes(t1,t2) ->
+ Util.error "Omega: Can't solve a goal with non-linear products"
+ | (Oatom _ as t) -> do_list [], Otimes(t,Oz n)
+ | Oz i -> do_list [Lazy.force coq_c_reduce],Oz(n*i)
+ | (Oufo _ as t)-> do_list [], Oufo (Otimes(t,Oz n))
+ | Ominus _ -> failwith "scalar minus"
+
+(* \subsection{Propagation de l'inversion} *)
+let rec negate = function
+ Oplus(t1,t2) ->
+ let tac1,t1' = negate t1 and
+ tac2,t2' = negate t2 in
+ do_list [Lazy.force coq_c_opp_plus ; (do_both tac1 tac2)],
+ Oplus(t1',t2')
+ | Oinv t ->
+ do_list [Lazy.force coq_c_opp_opp], t
+ | Otimes(t1,Oz x) ->
+ do_list [Lazy.force coq_c_opp_mult_r], Otimes(t1,Oz (-x))
+ | Otimes(t1,t2) ->
+ Util.error "Omega: Can't solve a goal with non-linear products"
+ | (Oatom _ as t) ->
+ do_list [Lazy.force coq_c_opp_one], Otimes(t,Oz(-1))
+ | Oz i -> do_list [Lazy.force coq_c_reduce] ,Oz(-i)
+ | Oufo c -> do_list [], Oufo (Oinv c)
+ | Ominus _ -> failwith "negate minus"
+
+let rec norm l = (List.length l)
+
+(* \subsection{Mélange (fusion) de deux équations} *)
+
+let rec shuffle_path k1 e1 k2 e2 =
+ let rec loop = function
+ (({Omega.c=c1;Omega.v=v1}::l1) as l1'),
+ (({Omega.c=c2;Omega.v=v2}::l2) as l2') ->
+ if v1 = v2 then
+ if k1*c1 + k2 * c2 = 0 then (
+ Lazy.force coq_f_cancel :: loop (l1,l2))
+ else (
+ Lazy.force coq_f_equal :: loop (l1,l2) )
+ else if v1 > v2 then (
+ Lazy.force coq_f_left :: loop(l1,l2'))
+ else (
+ Lazy.force coq_f_right :: loop(l1',l2))
+ | ({Omega.c=c1;Omega.v=v1}::l1), [] ->
+ Lazy.force coq_f_left :: loop(l1,[])
+ | [],({Omega.c=c2;Omega.v=v2}::l2) ->
+ Lazy.force coq_f_right :: loop([],l2)
+ | [],[] -> flush stdout; [] in
+ mk_shuffle_list (loop (e1,e2))
+
+let rec shuffle (t1,t2) =
+ match t1,t2 with
+ Oplus(l1,r1), Oplus(l2,r2) ->
+ if weight l1 > weight l2 then
+ let l_action,t' = shuffle (r1,t2) in
+ do_list [Lazy.force coq_c_plus_assoc_r;do_right l_action], Oplus(l1,t')
+ else
+ let l_action,t' = shuffle (t1,r2) in
+ do_list [Lazy.force coq_c_plus_permute;do_right l_action], Oplus(l2,t')
+ | Oplus(l1,r1), t2 ->
+ if weight l1 > weight t2 then
+ let (l_action,t') = shuffle (r1,t2) in
+ do_list [Lazy.force coq_c_plus_assoc_r;do_right l_action],Oplus(l1, t')
+ else do_list [Lazy.force coq_c_plus_sym], Oplus(t2,t1)
+ | t1,Oplus(l2,r2) ->
+ if weight l2 > weight t1 then
+ let (l_action,t') = shuffle (t1,r2) in
+ do_list [Lazy.force coq_c_plus_permute;do_right l_action], Oplus(l2,t')
+ else do_list [],Oplus(t1,t2)
+ | Oz t1,Oz t2 ->
+ do_list [Lazy.force coq_c_reduce], Oz(t1+t2)
+ | t1,t2 ->
+ if weight t1 < weight t2 then
+ do_list [Lazy.force coq_c_plus_sym], Oplus(t2,t1)
+ else do_list [],Oplus(t1,t2)
+
+(* \subsection{Fusion avec réduction} *)
+let shrink_pair f1 f2 =
+ begin match f1,f2 with
+ Oatom v,Oatom _ ->
+ Lazy.force coq_c_red1, Otimes(Oatom v,Oz 2)
+ | Oatom v, Otimes(_,c2) ->
+ Lazy.force coq_c_red2, Otimes(Oatom v,Oplus(c2,Oz 1))
+ | Otimes (v1,c1),Oatom v ->
+ Lazy.force coq_c_red3, Otimes(Oatom v,Oplus(c1,Oz 1))
+ | Otimes (Oatom v,c1),Otimes (v2,c2) ->
+ Lazy.force coq_c_red4, Otimes(Oatom v,Oplus(c1,c2))
+ | t1,t2 ->
+ oprint t1; print_newline (); oprint t2; print_newline ();
+ flush Pervasives.stdout; Util.error "shrink.1"
+ end
+
+(* \subsection{Calcul d'une sous formule constante} *)
+let reduce_factor = function
+ Oatom v ->
+ let r = Otimes(Oatom v,Oz 1) in
+ [Lazy.force coq_c_red0],r
+ | Otimes(Oatom v,Oz n) as f -> [],f
+ | Otimes(Oatom v,c) ->
+ let rec compute = function
+ Oz n -> n
+ | Oplus(t1,t2) -> compute t1 + compute t2
+ | _ -> Util.error "condense.1" in
+ [Lazy.force coq_c_reduce], Otimes(Oatom v,Oz(compute c))
+ | t -> Util.error "reduce_factor.1"
+
+(* \subsection{Réordonancement} *)
+
+let rec condense = function
+ Oplus(f1,(Oplus(f2,r) as t)) ->
+ if weight f1 = weight f2 then begin
+ let shrink_tac,t = shrink_pair f1 f2 in
+ let assoc_tac = Lazy.force coq_c_plus_assoc_l in
+ let tac_list,t' = condense (Oplus(t,r)) in
+ assoc_tac :: do_left (do_list [shrink_tac]) :: tac_list, t'
+ end else begin
+ let tac,f = reduce_factor f1 in
+ let tac',t' = condense t in
+ [do_both (do_list tac) (do_list tac')], Oplus(f,t')
+ end
+ | (Oplus(f1,Oz n) as t) ->
+ let tac,f1' = reduce_factor f1 in
+ [do_left (do_list tac)],Oplus(f1',Oz n)
+ | Oplus(f1,f2) ->
+ if weight f1 = weight f2 then begin
+ let tac_shrink,t = shrink_pair f1 f2 in
+ let tac,t' = condense t in
+ tac_shrink :: tac,t'
+ end else begin
+ let tac,f = reduce_factor f1 in
+ let tac',t' = condense f2 in
+ [do_both (do_list tac) (do_list tac')],Oplus(f,t')
+ end
+ | (Oz _ as t)-> [],t
+ | t ->
+ let tac,t' = reduce_factor t in
+ let final = Oplus(t',Oz 0) in
+ tac @ [Lazy.force coq_c_red6], final
+
+(* \subsection{Elimination des zéros} *)
+
+let rec clear_zero = function
+ Oplus(Otimes(Oatom v,Oz 0),r) ->
+ let tac',t = clear_zero r in
+ Lazy.force coq_c_red5 :: tac',t
+ | Oplus(f,r) ->
+ let tac,t = clear_zero r in
+ (if tac = [] then [] else [do_right (do_list tac)]),Oplus(f,t)
+ | t -> [],t;;
+
+(* \section{Transformation des hypothèses} *)
+
+let rec reduce = function
+ Oplus(t1,t2) ->
+ let t1', trace1 = reduce t1 in
+ let t2', trace2 = reduce t2 in
+ let trace3,t' = shuffle (t1',t2') in
+ t', do_list [do_both trace1 trace2; trace3]
+ | Ominus(t1,t2) ->
+ let t,trace = reduce (Oplus(t1, Oinv t2)) in
+ t, do_list [Lazy.force coq_c_minus; trace]
+ | Otimes(t1,t2) as t ->
+ let t1', trace1 = reduce t1 in
+ let t2', trace2 = reduce t2 in
+ begin match t1',t2' with
+ | (_, Oz n) ->
+ let tac,t' = scalar n t1' in
+ t', do_list [do_both trace1 trace2; tac]
+ | (Oz n,_) ->
+ let tac,t' = scalar n t2' in
+ t', do_list [do_both trace1 trace2; Lazy.force coq_c_mult_sym; tac]
+ | _ -> Oufo t, Lazy.force coq_c_nop
+ end
+ | Oinv t ->
+ let t',trace = reduce t in
+ let trace',t'' = negate t' in
+ t'', do_list [do_left trace; trace']
+ | (Oz _ | Oatom _ | Oufo _) as t -> t, Lazy.force coq_c_nop
+
+let rec ocompile env t =
+ try match destructurate t with
+ | Kapp("Zplus",[t1;t2]) ->
+ let t1',env1 = ocompile env t1 in
+ let t2',env2 = ocompile env1 t2 in
+ (Oplus (t1',t2'), env2)
+ | Kapp("Zminus",[t1;t2]) ->
+ let t1',env1 = ocompile env t1 in
+ let t2',env2 = ocompile env1 t2 in
+ (Ominus (t1',t2'), env2)
+ | Kapp("Zmult",[t1;t2]) ->
+ let t1',env1 = ocompile env t1 in
+ let t2',env2 = ocompile env1 t2 in
+ (Otimes (t1',t2'), env2)
+ | Kapp(("POS"|"NEG"|"ZERO"),_) ->
+ begin try (Oz(recognize_number t),env)
+ with _ ->
+ let v,env' = add_atom t env in Oatom v, env'
+ end
+ | Kvar s ->
+ let v,env' = add_atom t env in Oatom v, env'
+ | Kapp("Zopp",[t]) ->
+ let t',env1 = ocompile env t in Oinv t', env1
+ | _ ->
+ let v,env' = add_atom t env in Oatom(v), env'
+ with e when Logic.catchable_exception e ->
+ let v,env' = add_atom t env in Oatom(v), env'
+
+(*i | Kapp("Zs",[t1]) ->
+ | Kapp("inject_nat",[t']) -> i*)
+
+let normalize_equation t =
+ let t1,trace1 = reduce t in
+ let trace2,t2 = condense t1 in
+ let trace3,t3 = clear_zero t2 in
+ do_list [trace1; do_list trace2; do_list trace3], t3
+
+let destructure_omega gl (trace_norm, system, env) (id,c) =
+ let mk_step t1 t2 f kind coq_t_oper =
+ let o1,env1 = ocompile env t1 in
+ let o2,env2 = ocompile env1 t2 in
+ let t = f o1 o2 in
+ let trace, oterm = normalize_equation t in
+ let equa = compile id kind oterm in
+ let tterm =
+ mkApp (Lazy.force coq_t_oper,
+ [| val_of_formula o1; val_of_formula o2 |]) in
+ ((id,(trace,tterm)) :: trace_norm), (equa :: system), env2 in
+
+ try match destructurate c with
+ | Kapp("eq",[typ;t1;t2]) when destructurate (Tacmach.pf_nf gl typ) =
+ Kapp("Z",[]) ->
+ mk_step t1 t2 (fun o1 o2 -> Oplus (o1,Oinv o2)) Omega.EQUA coq_t_equal
+ | Kapp("Zne",[t1;t2]) ->
+ mk_step t1 t2 (fun o1 o2 -> Oplus (o1,Oinv o2)) Omega.DISE coq_t_neq
+ | Kapp("Zle",[t1;t2]) ->
+ mk_step t1 t2 (fun o1 o2 -> Oplus (o2,Oinv o1)) Omega.INEQ coq_t_leq
+ | Kapp("Zlt",[t1;t2]) ->
+ mk_step t1 t2
+ (fun o1 o2 -> Oplus (Oplus(o2,Oz (-1)),Oinv o1)) Omega.INEQ coq_t_lt
+ | Kapp("Zge",[t1;t2]) ->
+ mk_step t1 t2 (fun o1 o2 -> Oplus (o1,Oinv o2)) Omega.INEQ coq_t_geq
+ | Kapp("Zgt",[t1;t2]) ->
+ mk_step t1 t2
+ (fun o1 o2 -> Oplus (Oplus(o1,Oz (-1)),Oinv o2)) Omega.INEQ coq_t_gt
+ | _ -> trace_norm, system, env
+ with e when Logic.catchable_exception e -> trace_norm, system, env
+
+(* \section{Rejouer l'historique} *)
+
+let replay_history env_hyp =
+ let rec loop env_hyp t =
+ match t with
+ | Omega.CONTRADICTION (e1,e2) :: l ->
+ let trace = mk_nat (List.length e1.Omega.body) in
+ mkApp (Lazy.force coq_s_contradiction,
+ [| trace ; mk_nat (get_hyp env_hyp e1.Omega.id);
+ mk_nat (get_hyp env_hyp e2.Omega.id) |])
+ | Omega.DIVIDE_AND_APPROX (e1,e2,k,d) :: l ->
+ mkApp (Lazy.force coq_s_div_approx,
+ [| mk_Z k; mk_Z d; val_of e2.Omega.body e2.Omega.constant;
+ mk_nat (List.length e2.Omega.body);
+ loop env_hyp l; mk_nat (get_hyp env_hyp e1.Omega.id) |])
+ | Omega.NOT_EXACT_DIVIDE (e1,k) :: l ->
+ let e2_constant = Omega.floor_div e1.Omega.constant k in
+ let d = e1.Omega.constant - e2_constant * k in
+ let e2_body = Omega.map_eq_linear (fun c -> c / k) e1.Omega.body in
+ mkApp (Lazy.force coq_s_not_exact_divide,
+ [|mk_Z k; mk_Z d; val_of e2_body e2_constant;
+ mk_nat (List.length e2_body);
+ mk_nat (get_hyp env_hyp e1.Omega.id)|])
+ | Omega.EXACT_DIVIDE (e1,k) :: l ->
+ let e2_body = Omega.map_eq_linear (fun c -> c / k) e1.Omega.body in
+ let e2_constant = Omega.floor_div e1.Omega.constant k in
+ mkApp (Lazy.force coq_s_exact_divide,
+ [|mk_Z k; val_of e2_body e2_constant;
+ mk_nat (List.length e2_body);
+ loop env_hyp l; mk_nat (get_hyp env_hyp e1.Omega.id)|])
+ | (Omega.MERGE_EQ(e3,e1,e2)) :: l ->
+ let n1 = get_hyp env_hyp e1.Omega.id and n2 = get_hyp env_hyp e2 in
+ mkApp (Lazy.force coq_s_merge_eq,
+ [| mk_nat (List.length e1.Omega.body);
+ mk_nat n1; mk_nat n2;
+ loop (e3:: env_hyp) l |])
+ | Omega.SUM(e3,(k1,e1),(k2,e2)) :: l ->
+ let n1 = get_hyp env_hyp e1.Omega.id
+ and n2 = get_hyp env_hyp e2.Omega.id in
+ let trace = shuffle_path k1 e1.Omega.body k2 e2.Omega.body in
+ mkApp (Lazy.force coq_s_sum,
+ [| mk_Z k1; mk_nat n1; mk_Z k2;
+ mk_nat n2; trace; (loop (e3 :: env_hyp) l) |])
+ | Omega.CONSTANT_NOT_NUL(e,k) :: l ->
+ mkApp (Lazy.force coq_s_constant_not_nul,
+ [| mk_nat (get_hyp env_hyp e) |])
+ | Omega.CONSTANT_NEG(e,k) :: l ->
+ mkApp (Lazy.force coq_s_constant_neg,
+ [| mk_nat (get_hyp env_hyp e) |])
+ | Omega.STATE (new_eq,def,orig,m,sigma) :: l ->
+ let n1 = get_hyp env_hyp orig.Omega.id
+ and n2 = get_hyp env_hyp def.Omega.id in
+ let v = unintern_id sigma in
+ let o_def = decompile def in
+ let o_orig = decompile orig in
+ let body =
+ Oplus (o_orig,Otimes (Oplus (Oinv v,o_def), Oz m)) in
+ let trace,_ = normalize_equation body in
+ mkApp (Lazy.force coq_s_state,
+ [| mk_Z m; trace; mk_nat n1; mk_nat n2;
+ loop (new_eq.Omega.id :: env_hyp) l |])
+ | Omega.HYP _ :: l -> loop env_hyp l
+ | Omega.CONSTANT_NUL e :: l ->
+ mkApp (Lazy.force coq_s_constant_nul,
+ [| mk_nat (get_hyp env_hyp e) |])
+ | Omega.NEGATE_CONTRADICT(e1,e2,b) :: l ->
+ mkApp (Lazy.force coq_s_negate_contradict,
+ [| mk_nat (get_hyp env_hyp e1.Omega.id);
+ mk_nat (get_hyp env_hyp e2.Omega.id) |])
+ | Omega.SPLIT_INEQ(e,(e1,l1),(e2,l2)) :: l ->
+ let i = get_hyp env_hyp e.Omega.id in
+ let r1 = loop (e1 :: env_hyp) l1 in
+ let r2 = loop (e2 :: env_hyp) l2 in
+ mkApp (Lazy.force coq_s_split_ineq,
+ [| mk_nat (List.length e.Omega.body); mk_nat i; r1 ; r2 |])
+ | (Omega.FORGET_C _ | Omega.FORGET _ | Omega.FORGET_I _) :: l ->
+ loop env_hyp l
+ | (Omega.WEAKEN _ ) :: l -> failwith "not_treated"
+ | [] -> failwith "no contradiction"
+ in loop env_hyp
+
+let show_goal gl =
+ if !debug then Pp.pPNL (Tacmach.pr_gls gl); Tacticals.tclIDTAC gl
+
+(* Cette fonction prépare le rejeu puis l'appelle :
+ \begin{itemize}
+ \item elle isole les hypothèses utiles et les mets dans
+ le but réifié
+ \item elle prépare l'introduction de nouvelles variables pour le test
+ de Banerjee (opération STATE)
+ \end{itemize}
+*)
+
+let prepare_and_play env tac_hyps trace_solution =
+ let rec loop ((l_tac_norm, l_terms, l_id, l_e) as result) = function
+ Omega.HYP e :: l ->
+ let id = tag_of_equation e.Omega.id in
+ let (tac_norm,term) =
+ try List.assoc id tac_hyps
+ with Not_found -> failwith "what eqn" in
+ loop (tac_norm :: l_tac_norm,term :: l_terms,
+ Term.mkVar id :: l_id, e.Omega.id :: l_e ) l
+ | Omega.SPLIT_INEQ(e,(e1,l1),(e2,l2)) :: l ->
+ loop (loop result l1) l2
+ | _ :: l -> loop result l
+ | [] -> result in
+ let l_tac_norms, l_terms,l_generalized, l_e =
+ loop ([],[],[],[]) trace_solution in
+
+ let rec loop ((env,l_tac_norm, l_terms,l_gener, l_e) as result) = function
+ Omega.STATE (new_eq,def,orig,m,sigma) :: l ->
+ let o_def = decompile def in
+ let coq_def = coq_of_formula env o_def in
+ let v,env' = add_atom coq_def env in
+ intern_id_force (Oatom v) sigma;
+ let term_to_generalize =
+ mkApp(Lazy.force coq_refl_equal,[|Lazy.force coq_Z; coq_def|]) in
+ let reified_term =
+ mkApp (Lazy.force coq_t_equal,
+ [| val_of_formula o_def; val_of_formula (Oatom v) |]) in
+ loop (env', Lazy.force coq_c_nop :: l_tac_norm,
+ reified_term :: l_terms ,term_to_generalize :: l_gener,
+ def.Omega.id :: l_e) l
+ | Omega.SPLIT_INEQ(e,(e1,l1),(e2,l2)) :: l ->
+ loop (loop result l1) l2
+ | _ :: l -> loop result l
+ | [] -> result in
+ let env, l_tac_norms, l_terms,l_generalized, l_e =
+ loop (env, l_tac_norms, l_terms,l_generalized, l_e) trace_solution in
+
+ (* Attention Generalize ajoute les buts dans l'ordre inverse *)
+ let l_reified_terms = mk_list (Lazy.force coq_proposition) l_terms in
+ let l_reified_tac_norms = mk_list (Lazy.force coq_step) l_tac_norms in
+ let env_reified = mk_list (Lazy.force coq_Z) env in
+ let reified =
+ mkApp(Lazy.force coq_interp_sequent, [| env_reified; l_reified_terms |]) in
+ let reified_trace_solution = replay_history l_e trace_solution in
+ if !debug then begin
+ Pp.pPNL [< Printer.prterm reified>];
+ Pp.pPNL [< Printer.prterm l_reified_tac_norms>];
+ Pp.pPNL [< Printer.prterm reified_trace_solution>];
+ end;
+ Tactics.generalize l_generalized >>
+ Tactics.change_in_concl reified >>
+ Tacticals.tclTRY
+ (Tactics.apply (mkApp (Lazy.force coq_normalize_sequent,
+ [|l_reified_tac_norms |]))) >>
+ Tacticals.tclTRY
+ (Tactics.apply (mkApp (Lazy.force coq_execute_sequent,
+ [|reified_trace_solution |]))) >>
+ Tactics.normalise_in_concl >> Auto.auto 5 []
+
+let coq_omega gl =
+ clear_tags (); clear_intern ();
+ let tactic_hyps, system, env =
+ List.fold_left (destructure_omega gl) ([],[],[])
+ (Tacmach.pf_hyps_types gl) in
+ if !debug then begin Omega.display_system system; print_newline () end;
+ begin try
+ let trace = Omega.simplify_strong system in
+ if !debug then Omega.display_action trace;
+ prepare_and_play env tactic_hyps trace gl
+ with Omega.NO_CONTRADICTION -> Util.error "Omega can't solve this system"
+ end
+
+let refl_omega = Tacmach.hide_atomic_tactic "StepOmega" coq_omega
+
+(* \section{Encapsulation ROMEGA} *)
+
+(* Toute cette partie est héritée de [OMEGA]. Seule modification : l'appel
+ à [coq_omega] qui correspond à la version réflexive. Il suffirait de
+ paramétrer le code par cette tactique.
+
+ \paragraph{Note :} cette partie aussi devrait être réfléchie. *)
+
+open Reduction
+open Proof_type
+open Ast
+open Names
+open Term
+open Environ
+open Sign
+open Inductive
+open Tacmach
+open Tactics
+open Clenv
+open Logic
+open Omega
+
+let nat_inject gl = Coq_omega.nat_inject gl
+let elim_id id gl = simplest_elim (pf_global gl id) gl
+let resolve_id id gl = apply (pf_global gl id) gl
+let generalize_tac = Coq_omega.generalize_tac
+let coq_imp_simp = Coq_omega.coq_imp_simp
+let decidability = Coq_omega.decidability
+let coq_not_or = Coq_omega.coq_not_or
+let coq_not_and = Coq_omega.coq_not_and
+let coq_not_imp = Coq_omega.coq_not_imp
+let coq_not_not = Coq_omega.coq_not_not
+let coq_not_Zle = Coq_omega.coq_not_Zle
+let coq_not_Zge = Coq_omega.coq_not_Zge
+let coq_not_Zlt = Coq_omega.coq_not_Zlt
+let coq_not_Zgt = Coq_omega.coq_not_Zgt
+let coq_not_le = Coq_omega.coq_not_le
+let coq_not_ge = Coq_omega.coq_not_ge
+let coq_not_lt = Coq_omega.coq_not_lt
+let coq_not_gt = Coq_omega.coq_not_gt
+let coq_not_eq = Coq_omega.coq_not_eq
+let coq_not_Zeq = Coq_omega.coq_not_Zeq
+let coq_neq = Coq_omega.coq_neq
+let coq_Zne = Coq_omega.coq_Zne
+let coq_dec_not_not = Coq_omega.coq_dec_not_not
+let old_style_flag = Coq_omega.old_style_flag
+let unfold = Coq_omega.unfold
+let sp_not = Coq_omega.sp_not
+let all_time = Coq_omega.all_time
+let mkNewMeta = Coq_omega.mkNewMeta
+
+let destructure_hyps gl =
+ let rec loop evbd = function
+ | [] -> (tclTHEN nat_inject coq_omega)
+ | (i,t)::lit ->
+ begin try match destructurate t with
+ | Kapp(("Zle"|"Zge"|"Zgt"|"Zlt"|"Zne"),[t1;t2]) -> loop evbd lit
+ | Kapp("or",[t1;t2]) ->
+ (tclTHENS ((tclTHEN ((tclTHEN (elim_id i) (clear [i])))
+ (intros_using [i])))
+ ([ loop evbd ((i,t1)::lit); loop evbd ((i,t2)::lit) ]))
+ | Kapp("and",[t1;t2]) ->
+ let i1 = id_of_string (string_of_id i ^ "_left") in
+ let i2 = id_of_string (string_of_id i ^ "_right") in
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN (elim_id i) (clear [i]))
+ (intros_using [i1;i2]))
+ (loop (i1::i2::evbd) ((i1,t1)::(i2,t2)::lit)))
+ | Kimp(t1,t2) ->
+ if isprop (pf_type_of gl t1) & closed0 t2 then begin
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_imp_simp, [|
+ t1; t2;
+ decidability gl t1;
+ mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd ((i,mk_or (mk_not t1) t2)::lit)))
+ end else loop evbd lit
+ | Kapp("not",[t]) ->
+ begin match destructurate t with
+ Kapp("or",[t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_or,[|
+ t1; t2; mkVar i |])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd ((i,mk_and (mk_not t1) (mk_not t2)):: lit)))
+ | Kapp("and",[t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac
+ [mkApp (Lazy.force coq_not_and, [| t1; t2;
+ decidability gl t1;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd ((i,mk_or (mk_not t1) (mk_not t2))::lit)))
+ | Kimp(t1,t2) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac
+ [mkApp (Lazy.force coq_not_imp, [| t1; t2;
+ decidability gl t1;mkVar i |])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd ((i,mk_and t1 (mk_not t2)) :: lit)))
+ | Kapp("not",[t]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac
+ [mkApp (Lazy.force coq_not_not, [| t;
+ decidability gl t; mkVar i |])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd ((i,t)::lit)))
+ | Kapp("Zle", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_Zle,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("Zge", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_Zge,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("Zlt", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_Zlt,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("Zgt", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_Zgt,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("le", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_le,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("ge", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_ge,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("lt", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_lt,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("gt", [t1;t2]) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (generalize_tac [mkApp (Lazy.force coq_not_gt,
+ [| t1;t2;mkVar i|])])
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("eq",[typ;t1;t2]) ->
+ if !old_style_flag then begin
+ match destructurate (pf_nf gl typ) with
+ | Kapp("nat",_) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (simplest_elim
+ (applist
+ (Lazy.force coq_not_eq,
+ [t1;t2;mkVar i])))
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | Kapp("Z",_) ->
+ (tclTHEN
+ (tclTHEN
+ (tclTHEN
+ (simplest_elim
+ (applist
+ (Lazy.force coq_not_Zeq,
+ [t1;t2;mkVar i])))
+ (clear [i]))
+ (intros_using [i]))
+ (loop evbd lit))
+ | _ -> loop evbd lit
+ end else begin
+ match destructurate (pf_nf gl typ) with
+ | Kapp("nat",_) ->
+ (tclTHEN
+ (convert_hyp i
+ (mkApp (Lazy.force coq_neq, [| t1;t2|])))
+ (loop evbd lit))
+ | Kapp("Z",_) ->
+ (tclTHEN
+ (convert_hyp i
+ (mkApp (Lazy.force coq_Zne, [| t1;t2|])))
+ (loop evbd lit))
+ | _ -> loop evbd lit
+ end
+ | _ -> loop evbd lit
+ end
+ | _ -> loop evbd lit
+ with e when catchable_exception e -> loop evbd lit
+ end
+ in
+ loop (pf_ids_of_hyps gl) (pf_hyps_types gl) gl
+
+let omega_solver gl =
+ let concl = pf_concl gl in
+ let rec loop t =
+ match destructurate t with
+ | Kapp("not",[t1;t2]) ->
+ (tclTHEN
+ (tclTHEN (unfold sp_not) intro)
+ destructure_hyps)
+ | Kimp(a,b) -> (tclTHEN intro (loop b))
+ | Kapp("False",[]) -> destructure_hyps
+ | _ ->
+ (tclTHEN
+ (tclTHEN
+ (Tactics.refine
+ (mkApp (Lazy.force coq_dec_not_not, [| t;
+ decidability gl t; mkNewMeta () |])))
+ intro)
+ (destructure_hyps))
+ in
+ (loop concl) gl
+
+let omega = hide_atomic_tactic "ReflOmega" omega_solver