1 (* Copyright (C) 2002, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
27 (******************** OTHER USEFUL TACTICS **********************)
29 let rewrite_tac ~term:equality ~status:(proof,goal) =
31 let module U = UriManager in
32 let curi,metasenv,pbo,pty = proof in
33 let metano,context,gty = List.find (function (m,_,_) -> m=goal) metasenv in
34 let eq_ind_r,ty,t1,t2 =
35 match CicTypeChecker.type_of_aux' metasenv context equality with
36 C.Appl [C.MutInd (uri,_,0) ; ty ; t1 ; t2]
37 when U.eq uri (U.uri_of_string "cic:/Coq/Init/Logic/Equality/eq.ind") ->
40 (U.uri_of_string "cic:/Coq/Init/Logic/Logic_lemmas/eq_ind_r.con",0)
43 | C.Appl [C.MutInd (uri,_,0) ; ty ; t1 ; t2]
44 when U.eq uri (U.uri_of_string "cic:/Coq/Init/Logic_Type/eqT.ind") ->
47 (U.uri_of_string "cic:/Coq/Init/Logic_Type/eqT_ind_r.con",0)
52 (ProofEngineTypes.Fail
53 "Rewrite: the argument is not a proof of an equality")
56 let gty' = CicSubstitution.lift 1 gty in
57 let t1' = CicSubstitution.lift 1 t1 in
59 ProofEngineReduction.replace_lifting
61 (ProofEngineReduction.syntactic_equality ~alpha_equivalence:true)
62 ~what:t1' ~with_what:(C.Rel 1) ~where:gty'
64 C.Lambda (C.Name "dummy_for_rewrite", ty, gty'')
66 prerr_endline ("#### Sintetizzato: " ^ CicPp.ppterm pred);
67 let fresh_meta = ProofEngineHelpers.new_meta proof in
69 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
70 let metasenv' = (fresh_meta,context,C.Appl [pred ; t2])::metasenv in
71 PrimitiveTactics.exact_tac
73 [eq_ind_r ; ty ; t2 ; pred ; C.Meta (fresh_meta,irl) ; t1 ;equality])
74 ((curi,metasenv',pbo,pty),goal)
77 (******************** THE FOURIER TACTIC ***********************)
79 (* La tactique Fourier ne fonctionne de manière sûre que si les coefficients
80 des inéquations et équations sont entiers. En attendant la tactique Field.
86 let debug x = print_string ("____ "^x) ; flush stdout;;
88 let debug_pcontext x =
90 List.iter (fun y -> match y with Some(Cic.Name(a),_) -> str := !str ^ a ^ " " | _ ->()) x ;
91 debug ("contesto : "^ (!str) ^ "\n")
94 (******************************************************************************
95 Operations on linear combinations.
97 Opérations sur les combinaisons linéaires affines.
98 La partie homogène d'une combinaison linéaire est en fait une table de hash
99 qui donne le coefficient d'un terme du calcul des constructions,
100 qui est zéro si le terme n'y est pas.
106 The type for linear combinations
108 type flin = {fhom:(Cic.term , rational)Hashtbl.t;fcste:rational}
112 @return an empty flin
114 let flin_zero () = {fhom = Hashtbl.create 50;fcste=r0}
120 @return the rational associated with x (coefficient)
124 (Hashtbl.find f.fhom x)
130 Adds c to the coefficient of x
137 let cx = flin_coef f x in
138 Hashtbl.remove f.fhom x;
139 Hashtbl.add f.fhom x (rplus cx c);
148 let flin_add_cste f c =
150 fcste=rplus f.fcste c}
154 @return a empty flin with r1 in fcste
156 let flin_one () = flin_add_cste (flin_zero()) r1;;
161 let flin_plus f1 f2 =
162 let f3 = flin_zero() in
163 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
164 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f2.fhom;
165 flin_add_cste (flin_add_cste f3 f1.fcste) f2.fcste;
171 let flin_minus f1 f2 =
172 let f3 = flin_zero() in
173 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
174 Hashtbl.iter (fun x c -> let _=flin_add f3 x (rop c) in ()) f2.fhom;
175 flin_add_cste (flin_add_cste f3 f1.fcste) (rop f2.fcste);
182 let f2 = flin_zero() in
183 Hashtbl.iter (fun x c -> let _=flin_add f2 x (rmult a c) in ()) f.fhom;
184 flin_add_cste f2 (rmult a f.fcste);
188 (*****************************************************************************)
193 @return proiection on string of t
195 let rec string_of_term t =
197 Cic.Cast (t1,t2) -> string_of_term t1
198 |Cic.Const (u,boh) -> UriManager.string_of_uri u
199 |Cic.Var (u) -> UriManager.string_of_uri u
200 | _ -> "not_of_constant"
204 let string_of_constr = string_of_term
210 @raise Failure if conversion is impossible
211 @return rational proiection of t
213 let rec rational_of_term t =
214 (* fun to apply f to the first and second rational-term of l *)
215 let rat_of_binop f l =
216 let a = List.hd l and
217 b = List.hd(List.tl l) in
218 f (rational_of_term a) (rational_of_term b)
220 (* as before, but f is unary *)
221 let rat_of_unop f l =
222 f (rational_of_term (List.hd l))
225 | Cic.Cast (t1,t2) -> (rational_of_term t1)
226 | Cic.Appl (t1::next) ->
229 (match (UriManager.string_of_uri u) with
230 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
232 |"cic:/Coq/Reals/Rdefinitions/Rinv.con" ->
233 rat_of_unop rinv next
234 |"cic:/Coq/Reals/Rdefinitions/Rmult.con" ->
235 rat_of_binop rmult next
236 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con" ->
237 rat_of_binop rdiv next
238 |"cic:/Coq/Reals/Rdefinitions/Rplus.con" ->
239 rat_of_binop rplus next
240 |"cic:/Coq/Reals/Rdefinitions/Rminus.con" ->
241 rat_of_binop rminus next
242 | _ -> failwith "not a rational")
243 | _ -> failwith "not a rational")
244 | Cic.Const (u,boh) ->
245 (match (UriManager.string_of_uri u) with
246 "cic:/Coq/Reals/Rdefinitions/R1.con" -> r1
247 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> r0
248 | _ -> failwith "not a rational")
249 | _ -> failwith "not a rational"
253 let rational_of_const = rational_of_term;;
257 let rec flin_of_term t =
258 let fl_of_binop f l =
259 let a = List.hd l and
260 b = List.hd(List.tl l) in
261 f (flin_of_term a) (flin_of_term b)
265 | Cic.Cast (t1,t2) -> (flin_of_term t1)
266 | Cic.Appl (t1::next) ->
271 match (UriManager.string_of_uri u) with
272 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
273 flin_emult (rop r1) (flin_of_term (List.hd next))
274 |"cic:/Coq/Reals/Rdefinitions/Rplus.con"->
275 fl_of_binop flin_plus next
276 |"cic:/Coq/Reals/Rdefinitions/Rminus.con"->
277 fl_of_binop flin_minus next
278 |"cic:/Coq/Reals/Rdefinitions/Rmult.con"->
280 let arg1 = (List.hd next) and
281 arg2 = (List.hd(List.tl next))
285 let a = rational_of_term arg1 in
288 let b = (rational_of_term arg2) in
289 (flin_add_cste (flin_zero()) (rmult a b))
292 _ -> (flin_add (flin_zero()) arg2 a)
295 _-> (flin_add (flin_zero()) arg1 (rational_of_term arg2 ))
297 |"cic:/Coq/Reals/Rdefinitions/Rinv.con"->
298 let a=(rational_of_term (List.hd next)) in
299 flin_add_cste (flin_zero()) (rinv a)
300 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con"->
302 let b=(rational_of_term (List.hd(List.tl next))) in
305 let a = (rational_of_term (List.hd next)) in
306 (flin_add_cste (flin_zero()) (rdiv a b))
309 _-> (flin_add (flin_zero()) (List.hd next) (rinv b))
315 | Cic.Const (u,boh) ->
317 match (UriManager.string_of_uri u) with
318 "cic:/Coq/Reals/Rdefinitions/R1.con" -> flin_one ()
319 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> flin_zero ()
323 with _ -> flin_add (flin_zero()) t r1
327 let flin_of_constr = flin_of_term;;
331 Translates a flin to (c,x) list
333 @return something like (c1,x1)::(c2,x2)::...::(cn,xn)
335 let flin_to_alist f =
337 Hashtbl.iter (fun x c -> res:=(c,x)::(!res)) f;
341 (* Représentation des hypothèses qui sont des inéquations ou des équations.
345 The structure for ineq
347 type hineq={hname:Cic.term; (* le nom de l'hypothèse *)
348 htype:string; (* Rlt, Rgt, Rle, Rge, eqTLR ou eqTRL *)
355 (* Transforme une hypothese h:t en inéquation flin<0 ou flin<=0
358 let ineq1_of_term (h,t) =
359 match t with (* match t *)
360 Cic.Appl (t1::next) ->
361 let arg1= List.hd next in
362 let arg2= List.hd(List.tl next) in
363 (match t1 with (* match t1 *)
365 (match UriManager.string_of_uri u with (* match u *)
366 "cic:/Coq/Reals/Rdefinitions/Rlt.con" ->
371 hflin= flin_minus (flin_of_term arg1)
374 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" ->
379 hflin= flin_minus (flin_of_term arg2)
382 |"cic:/Coq/Reals/Rdefinitions/Rle.con" ->
387 hflin= flin_minus (flin_of_term arg1)
390 |"cic:/Coq/Reals/Rdefinitions/Rge.con" ->
395 hflin= flin_minus (flin_of_term arg2)
398 |_->assert false)(* match u *)
399 | Cic.MutInd (u,i,o) ->
400 (match UriManager.string_of_uri u with
401 "cic:/Coq/Init/Logic_Type/eqT.con" ->
404 let arg2= List.hd(List.tl (List.tl next)) in
407 (match UriManager.string_of_uri u with
408 "cic:/Coq/Reals/Rdefinitions/R.con"->
413 hflin= flin_minus (flin_of_term arg1)
420 hflin= flin_minus (flin_of_term arg2)
426 |_-> assert false)(* match t1 *)
427 |_-> assert false (* match t *)
430 let ineq1_of_constr = ineq1_of_term;;
433 (* Applique la méthode de Fourier à une liste d'hypothèses (type hineq)
439 | a::next -> Fourier.print_rational a ; print_string " " ; print_rl next
442 let rec print_sys l =
445 | (a,b)::next -> (print_rl a;
446 print_string (if b=true then "strict\n"else"\n");
451 Hashtbl.iter (fun x y -> print_string ("("^"-"^","^"-"^")")) h
454 let fourier_lineq lineq1 =
456 let hvar=Hashtbl.create 50 in (* la table des variables des inéquations *)
458 Hashtbl.iter (fun x c ->
459 try (Hashtbl.find hvar x;())
460 with _-> nvar:=(!nvar)+1;
461 Hashtbl.add hvar x (!nvar))
465 debug("Il numero di incognite e' "^string_of_int (!nvar+1)^"\n");
466 let sys= List.map (fun h->
467 let v=Array.create ((!nvar)+1) r0 in
468 Hashtbl.iter (fun x c -> v.(Hashtbl.find hvar x)<-c)
470 ((Array.to_list v)@[rop h.hflin.fcste],h.hstrict))
472 debug ("chiamo unsolvable sul sistema di "^ string_of_int (List.length sys) ^"\n");
477 (******************************************************************************
478 Construction de la preuve en cas de succès de la méthode de Fourier,
479 i.e. on obtient une contradiction.
483 let _eqT = Cic.MutInd(UriManager.uri_of_string "cic:/Coq/Init/Logic_Type/eqT.ind") 0 0 ;;
484 let _False = Cic.MutInd (UriManager.uri_of_string "cic:/Coq/Init/Logic/False.ind") 0 0 ;;
485 let _not = Cic.Const (UriManager.uri_of_string "cic:/Coq/Init/Logic/not.con") 0;;
486 let _R0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R0.con") 0 ;;
487 let _R1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R1.con") 0 ;;
488 let _R = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R.con") 0 ;;
489 let _Rfourier_eqLR_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqLR_to_le.con") 0 ;;
490 let _Rfourier_eqRL_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqRL_to_le.con") 0 ;;
491 let _Rfourier_ge_to_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_ge_to_le.con") 0 ;;
492 let _Rfourier_gt_to_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_gt_to_lt.con") 0 ;;
493 let _Rfourier_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le.con") 0 ;;
494 let _Rfourier_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_le.con") 0 ;;
495 let _Rfourier_le_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_lt.con") 0 ;;
496 let _Rfourier_lt=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt.con") 0 ;;
497 let _Rfourier_lt_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_le.con") 0 ;;
498 let _Rfourier_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_lt.con") 0 ;;
499 let _Rfourier_not_ge_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_ge_lt.con") 0 ;;
500 let _Rfourier_not_gt_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_gt_le.con") 0 ;;
501 let _Rfourier_not_le_gt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_le_gt.con") 0 ;;
502 let _Rfourier_not_lt_ge = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_lt_ge.con") 0 ;;
503 let _Rinv = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rinv.con") 0 ;;
504 let _Rinv_R1 = Cic.Const(UriManager.uri_of_string "cic:/Coq/Reals/Rbase/Rinv_R1.con" ) 0;;
505 let _Rle = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rle.con") 0 ;;
506 let _Rle_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_mult_inv_pos.con") 0 ;;
507 let _Rle_not_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_not_lt.con") 0 ;;
508 let _Rle_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_1.con") 0 ;;
509 let _Rle_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_pos_plus1.con") 0 ;;
510 let _Rle_zero_zero = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_zero.con") 0 ;;
511 let _Rlt = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rlt.con") 0 ;;
512 let _Rlt_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_mult_inv_pos.con") 0 ;;
513 let _Rlt_not_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_not_le.con") 0 ;;
514 let _Rlt_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_1.con") 0 ;;
515 let _Rlt_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_pos_plus1.con") 0 ;;
516 let _Rminus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rminus.con") 0 ;;
517 let _Rmult = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rmult.con") 0 ;;
518 let _Rnot_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_le_le.con") 0 ;;
519 let _Rnot_lt0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt0.con") 0 ;;
520 let _Rnot_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt_lt.con") 0 ;;
521 let _Ropp = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Ropp.con") 0 ;;
522 let _Rplus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rplus.con") 0 ;;
523 let _sym_eqT = Cic.Const(UriManager.uri_of_string "/Coq/Init/Logic_Type/Equality_is_a_congruence/sym_eqT.con") 0 ;;
524 (*****************************************************************************************************)
525 let is_int x = (x.den)=1
528 (* fraction = couple (num,den) *)
529 let rec rational_to_fraction x= (x.num,x.den)
532 (* traduction -3 -> (Ropp (Rplus R1 (Rplus R1 R1)))
535 let rec int_to_real_aux n =
537 0 -> _R0 (* o forse R0 + R0 ????? *)
539 | _ -> Cic.Appl [ _Rplus ; _R1 ; int_to_real_aux (n-1) ]
544 let x = int_to_real_aux (abs n) in
546 Cic.Appl [ _Ropp ; x ]
552 (* -1/2 -> (Rmult (Ropp R1) (Rinv (Rplus R1 R1)))
555 let rational_to_real x =
556 let (n,d)=rational_to_fraction x in
557 Cic.Appl [ _Rmult ; int_to_real n ; Cic.Appl [ _Rinv ; int_to_real d ] ]
560 (* preuve que 0<n*1/d
565 let tac_zero_inf_pos gl (n,d) =
566 (*let cste = pf_parse_constr gl in*)
567 let tacn=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
568 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
570 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacn); done;
572 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
573 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos) ~continuations:[!tacn;!tacd])
575 let tac_zero_inf_pos (n,d) ~status =
576 (*let cste = pf_parse_constr gl in*)
577 let pall str ~status:(proof,goal) t =
578 debug ("tac "^str^" :\n" );
579 let curi,metasenv,pbo,pty = proof in
580 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
581 debug ("th = "^ CicPp.ppterm t ^"\n");
582 debug ("ty = "^ CicPp.ppterm ty^"\n");
585 (fun ~status -> pall "n0" ~status _Rlt_zero_1 ;PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
587 (fun ~status -> pall "d0" ~status _Rlt_zero_1 ;PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
591 tacn:=(Tacticals.then_ ~start:(fun ~status -> pall ("n"^string_of_int i) ~status _Rlt_zero_pos_plus1;PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1 ~status) ~continuation:!tacn); done;
593 tacd:=(Tacticals.then_ ~start:(fun ~status -> pall "d" ~status _Rlt_zero_pos_plus1 ;PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1 ~status) ~continuation:!tacd); done;
597 debug("TAC ZERO INF POS\n");
599 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos)
608 (* preuve que 0<=n*1/d
611 let tac_zero_infeq_pos gl (n,d) =
612 (*let cste = pf_parse_constr gl in*)
613 let tacn = ref (if n=0 then
614 (PrimitiveTactics.apply_tac ~term:_Rle_zero_zero )
616 (PrimitiveTactics.apply_tac ~term:_Rle_zero_1 ))
618 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
620 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_zero_pos_plus1) ~continuation:!tacn); done;
622 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
623 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rle_mult_inv_pos) ~continuations:[!tacn;!tacd])
628 (* preuve que 0<(-n)*(1/d) => False
631 let tac_zero_inf_false gl (n,d) =
632 if n=0 then (PrimitiveTactics.apply_tac ~term:_Rnot_lt0)
634 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_not_lt)
635 ~continuation:(tac_zero_infeq_pos gl (-n,d)))
638 (* preuve que 0<=(-n)*(1/d) => False
641 let tac_zero_infeq_false gl (n,d) =
642 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_not_le)
643 ~continuation:(tac_zero_inf_pos (-n,d)))
647 (* *********** ********** ******** ??????????????? *********** **************)
649 let apply_type_tac ~cast:t ~applist:al ~status:(proof,goal) =
650 let curi,metasenv,pbo,pty = proof in
651 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
652 let fresh_meta = ProofEngineHelpers.new_meta proof in
654 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
655 let metasenv' = (fresh_meta,context,t)::metasenv in
656 let proof' = curi,metasenv',pbo,pty in
658 PrimitiveTactics.apply_tac ~term:(Cic.Appl ((Cic.Cast (Cic.Meta (fresh_meta,irl),t))::al)) ~status:(proof',goal)
660 proof'',fresh_meta::goals
667 let my_cut ~term:c ~status:(proof,goal)=
668 let curi,metasenv,pbo,pty = proof in
669 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
671 let fresh_meta = ProofEngineHelpers.new_meta proof in
673 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
674 let metasenv' = (fresh_meta,context,c)::metasenv in
675 let proof' = curi,metasenv',pbo,pty in
677 apply_type_tac ~cast:(Cic.Prod(Cic.Name "Anonymous",c,CicSubstitution.lift 1 ty)) ~applist:[Cic.Meta(fresh_meta,irl)] ~status:(proof',goal)
679 (* We permute the generated goals to be consistent with Coq *)
682 | he::tl -> proof'',he::fresh_meta::tl
686 let exact = PrimitiveTactics.exact_tac;;
688 let tac_use h ~status:(proof,goal as status) =
689 debug("Inizio TC_USE\n");
690 let curi,metasenv,pbo,pty = proof in
691 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
692 debug ("hname = "^ CicPp.ppterm h.hname ^"\n");
693 debug ("ty = "^ CicPp.ppterm ty^"\n");
697 "Rlt" -> exact ~term:h.hname ~status
698 |"Rle" -> exact ~term:h.hname ~status
699 |"Rgt" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_gt_to_lt)
700 ~continuation:(exact ~term:h.hname)) ~status
701 |"Rge" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_ge_to_le)
702 ~continuation:(exact ~term:h.hname)) ~status
703 |"eqTLR" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqLR_to_le)
704 ~continuation:(exact ~term:h.hname)) ~status
705 |"eqTRL" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqRL_to_le)
706 ~continuation:(exact ~term:h.hname)) ~status
709 debug("Fine TAC_USE\n");
717 Cic.Appl ( Cic.Const(u,boh)::next) ->
718 (match (UriManager.string_of_uri u) with
719 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> true
720 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> true
721 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> true
722 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> true
723 |"cic:/Coq/Init/Logic_Type/eqT.con" ->
724 (match (List.hd next) with
725 Cic.Const (uri,_) when
726 UriManager.string_of_uri uri =
727 "cic:/Coq/Reals/Rdefinitions/R.con" -> true
733 let list_of_sign s = List.map (fun (x,_,z)->(x,z)) s;;
736 Cic.Appl(Array.to_list a)
739 (* Résolution d'inéquations linéaires dans R *)
740 let rec strip_outer_cast c = match c with
741 | Cic.Cast (c,_) -> strip_outer_cast c
745 let find_in_context id context =
746 let rec find_in_context_aux c n =
748 [] -> failwith (id^" not found in context")
749 | a::next -> (match a with
750 Some (Cic.Name(name),_) when name = id -> n
751 (*? magari al posto di _ qualcosaltro?*)
752 | _ -> find_in_context_aux next (n+1))
754 find_in_context_aux context 1
757 (* mi sembra quadratico *)
758 let rec filter_real_hyp context cont =
761 | Some(Cic.Name(h),Cic.Decl(t))::next -> (
762 let n = find_in_context h cont in
763 [(Cic.Rel(n),t)] @ filter_real_hyp next cont)
764 | a::next -> debug(" no\n"); filter_real_hyp next cont
767 (* lifts everithing at the conclusion level *)
768 let rec superlift c n=
771 | Some(name,Cic.Decl(a))::next -> [Some(name,Cic.Decl(CicSubstitution.lift n a))] @ superlift next (n+1)
772 | Some(name,Cic.Def(a))::next -> [Some(name,Cic.Def(CicSubstitution.lift n a))] @ superlift next (n+1)
773 | _::next -> superlift next (n+1) (*?? ??*)
777 let equality_replace a b ~status =
778 let module C = Cic in
779 let proof,goal = status in
780 let curi,metasenv,pbo,pty = proof in
781 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
782 let a_eq_b = C.Appl [ _eqT ; _R ; a ; b ] in
783 let fresh_meta = ProofEngineHelpers.new_meta proof in
785 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
786 let metasenv' = (fresh_meta,context,a_eq_b)::metasenv in
788 rewrite_tac ~term:(C.Meta (fresh_meta,irl))
789 ~status:((curi,metasenv',pbo,pty),goal)
791 (proof,fresh_meta::goals)
794 let tcl_fail a ~status:(proof,goal) =
796 1 -> raise (ProofEngineTypes.Fail "fail-tactical")
801 let assumption_tac ~status:(proof,goal)=
802 let curi,metasenv,pbo,pty = proof in
803 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
805 let tac_list = List.map
806 ( fun x -> num := !num + 1;
808 Some(Cic.Name(nm),t) -> (nm,exact ~term:(Cic.Rel(!num)))
809 | _ -> ("fake",tcl_fail 1)
813 Tacticals.try_tactics ~tactics:tac_list ~status:(proof,goal)
816 (* !!!!! fix !!!!!!!!!! *)
817 let contradiction_tac ~status:(proof,goal)=
819 ~start:(PrimitiveTactics.intros_tac ~name:"bo?" )
820 ~continuation:(Tacticals.then_
821 ~start:(Ring.elim_type_tac ~term:_False)
822 ~continuation:(assumption_tac))
826 (* ********************* TATTICA ******************************** *)
828 let rec fourier ~status:(s_proof,s_goal)=
829 let s_curi,s_metasenv,s_pbo,s_pty = s_proof in
830 let s_metano,s_context,s_ty = List.find (function (m,_,_) -> m=s_goal) s_metasenv in
832 debug ("invoco fourier_tac sul goal "^string_of_int(s_goal)^" e contesto :\n");
833 debug_pcontext s_context;
835 let fhyp = String.copy "new_hyp_for_fourier" in
837 (* here we need to negate the thesis, but to do this we nned to apply the right theoreme,
838 so let's parse our thesis *)
840 let th_to_appl = ref _Rfourier_not_le_gt in
842 Cic.Appl ( Cic.Const(u,boh)::args) ->
843 (match UriManager.string_of_uri u with
844 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> th_to_appl := _Rfourier_not_ge_lt
845 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> th_to_appl := _Rfourier_not_gt_le
846 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> th_to_appl := _Rfourier_not_le_gt
847 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> th_to_appl := _Rfourier_not_lt_ge
848 |_-> failwith "fourier can't be applyed")
849 |_-> failwith "fourier can't be applyed"); (* fix maybe strip_outer_cast goes here?? *)
851 (* now let's change our thesis applying the th and put it with hp *)
853 let proof,gl = Tacticals.then_
854 ~start:(PrimitiveTactics.apply_tac ~term:!th_to_appl)
855 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp)
856 ~status:(s_proof,s_goal) in
857 let goal = if List.length gl = 1 then List.hd gl else failwith "a new goal" in
859 debug ("port la tesi sopra e la nego. contesto :\n");
860 debug_pcontext s_context;
862 (* now we have all the right environment *)
864 let curi,metasenv,pbo,pty = proof in
865 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
868 (* now we want to convert hp to inequations, but first we must lift
869 everyting to thesis level, so that a variable has the save Rel(n)
870 in each hp ( needed by ineq1_of_term ) *)
872 (* ? fix if None ?????*)
873 (* fix change superlift with a real name *)
875 let l_context = superlift context 1 in
876 let hyps = filter_real_hyp l_context l_context in
878 debug ("trasformo in diseq. "^ string_of_int (List.length hyps)^" ipotesi\n");
882 (* transform hyps into inequations *)
884 List.iter (fun h -> try (lineq:=(ineq1_of_term h)@(!lineq))
889 debug ("applico fourier a "^ string_of_int (List.length !lineq)^" disequazioni\n");
891 let res=fourier_lineq (!lineq) in
892 let tac=ref Ring.id_tac in
894 (print_string "Tactic Fourier fails.\n";flush stdout;failwith "fourier_tac fails")
897 match res with (*match res*)
900 (* in lc we have the coefficient to "reduce" the system *)
902 print_string "Fourier's method can prove the goal...\n";flush stdout;
904 debug "I coeff di moltiplicazione rit sono: ";
908 (fun (h,c) -> if c<>r0 then (lutil:=(h,c)::(!lutil);
909 (* DBG *)Fourier.print_rational(c);print_string " "(* DBG *))
911 (List.combine (!lineq) lc);
913 print_string (" quindi lutil e' lunga "^string_of_int (List.length (!lutil))^"\n");
915 (* on construit la combinaison linéaire des inéquation *)
917 (match (!lutil) with (*match (!lutil) *)
920 debug ("elem di lutil ");Fourier.print_rational c1;print_string "\n";
922 let s=ref (h1.hstrict) in
924 (* let t1=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hleft|]) in
925 let t2=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hright|]) in
928 let t1 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hleft] ) in
929 let t2 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hright]) in
931 List.iter (fun (h,c) ->
932 s:=(!s)||(h.hstrict);
933 t1:=(Cic.Appl [_Rplus;!t1;Cic.Appl [_Rmult;rational_to_real c;h.hleft ] ]);
934 t2:=(Cic.Appl [_Rplus;!t2;Cic.Appl [_Rmult;rational_to_real c;h.hright] ]))
937 let ineq=Cic.Appl [(if (!s) then _Rlt else _Rle);!t1;!t2 ] in
938 let tc=rational_to_real cres in
941 (* ora ho i termini che descrivono i passi di fourier per risolvere il sistema *)
943 debug "inizio a costruire tac1\n";
944 Fourier.print_rational(c1);
946 let tac1=ref ( fun ~status ->
947 debug ("Sotto tattica t1 "^(if h1.hstrict then "strict" else "lasc")^"\n");
949 (Tacticals.thens ~start:(
951 debug ("inizio t1 strict\n");
952 let curi,metasenv,pbo,pty = proof in
953 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
954 debug ("th = "^ CicPp.ppterm _Rfourier_lt ^"\n");
955 debug ("ty = "^ CicPp.ppterm ty^"\n");
957 PrimitiveTactics.apply_tac ~term:_Rfourier_lt ~status)
958 ~continuations:[tac_use h1;
960 tac_zero_inf_pos (rational_to_fraction c1)] ~status
964 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le)
965 ~continuations:[tac_use h1;tac_zero_inf_pos (rational_to_fraction c1)] ~status))
970 List.iter (fun (h,c) ->
974 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac
975 ~term:_Rfourier_lt_lt)
976 ~continuations:[!tac1;tac_use h;
978 (rational_to_fraction c)]))
982 Fourier.print_rational(c1);
983 tac1:=(Tacticals.thens ~start:(
985 debug("INIZIO TAC 1 2\n");
987 let curi,metasenv,pbo,pty = proof in
988 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
989 debug ("th = "^ CicPp.ppterm _Rfourier_lt_le ^"\n");
990 debug ("ty = "^ CicPp.ppterm ty^"\n");
992 PrimitiveTactics.apply_tac ~term:_Rfourier_lt_le ~status
995 ~continuations:[!tac1;tac_use h;
997 tac_zero_inf_pos (rational_to_fraction c)
1006 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_lt)
1007 ~continuations:[!tac1;tac_use h;
1009 (rational_to_fraction c)]))
1013 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_le)
1014 ~continuations:[!tac1;tac_use h;
1016 (rational_to_fraction c)]))
1020 s:=(!s)||(h.hstrict))
1021 lutil;(*end List.iter*)
1023 let tac2= if sres then
1024 tac_zero_inf_false goal (rational_to_fraction cres)
1026 tac_zero_infeq_false goal (rational_to_fraction cres)
1028 tac:=(Tacticals.thens ~start:(my_cut ~term:ineq)
1029 ~continuations:[Tacticals.then_ (* ?????????????????????????????? *)
1030 ~start:(fun ~status:(proof,goal as status) ->
1031 let curi,metasenv,pbo,pty = proof in
1032 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
1033 PrimitiveTactics.change_tac ~what:ty ~with_what:(Cic.Appl [ _not; ineq]) ~status)
1034 ~continuation:(Tacticals.then_
1035 ~start:(PrimitiveTactics.apply_tac
1036 ~term:(if sres then _Rnot_lt_lt else _Rnot_le_le))
1037 ~continuation:(Tacticals.thens
1038 ~start:(equality_replace (Cic.Appl [_Rminus;!t2;!t1] ) tc)
1039 ~continuations:[tac2;(Tacticals.thens
1040 ~start:(equality_replace (Cic.Appl[_Rinv;_R1]) _R1)
1042 (* en attendant Field, ça peut aider Ring de remplacer 1/1 par 1 ... *)
1043 [Tacticals.try_tactics
1044 (* ???????????????????????????? *)
1045 ~tactics:[ "ring", Ring.ring_tac ; "id", Ring.id_tac]
1048 ~start:(PrimitiveTactics.apply_tac ~term:_sym_eqT)
1049 ~continuation:(PrimitiveTactics.apply_tac ~term:_Rinv_R1)
1053 ] (* end continuations before comment *)
1058 tac:=(Tacticals.thens ~start:(PrimitiveTactics.cut_tac ~term:_False)
1059 ~continuations:[Tacticals.then_
1060 (* ???????????????????????????????
1062 ~start:(PrimitiveTactics.intros_tac ~name:(String.copy "??"))
1063 (* ????????????????????????????? *)
1065 ~continuation:contradiction_tac;!tac])
1068 |_-> assert false)(*match (!lutil) *)
1069 |_-> assert false); (*match res*)
1071 debug ("finalmente applico tac\n");
1072 (!tac ~status:(proof,goal))
1076 let fourier_tac ~status:(proof,goal) = fourier ~status:(proof,goal);;