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
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") ->
41 (ProofEngineTypes.Fail
42 "Rewrite: the argument is not a proof of an equality")
45 let gty' = CicSubstitution.lift 1 gty in
46 let t1' = CicSubstitution.lift 1 t1 in
48 ProofEngineReduction.replace_lifting
49 ~equality:ProofEngineReduction.syntactic_equality
50 ~what:t1' ~with_what:(C.Rel 1) ~where:gty'
52 C.Lambda (C.Name "dummy_for_rewrite", ty, gty'')
54 prerr_endline ("##### Atteso: " ^ CicPp.ppterm
55 (C.Lambda (C.Name "x", ty,
57 [C.MutInd (U.uri_of_string "cic:/Coq/Init/Logic/Equality/eq.ind",0,0) ;
58 ty ; C.Rel 3 ; C.Rel 1]))
60 prerr_endline ("#### Sintetizzato: " ^ CicPp.ppterm pred);
63 (U.uri_of_string "cic:/Coq/Init/Logic/Logic_lemmas/eq_ind_r.con",0) in
64 let fresh_meta = ProofEngineHelpers.new_meta proof in
66 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
67 let metasenv' = (fresh_meta,context,C.Appl [pred ; t2])::metasenv in
68 PrimitiveTactics.exact_tac
70 [eq_ind_r ; ty ; t2 ; pred ; C.Meta (fresh_meta,irl) ; t1 ;equality])
71 ((curi,metasenv',pbo,pty),goal)
74 (******************** THE FOURIER TACTIC ***********************)
76 (* La tactique Fourier ne fonctionne de manière sûre que si les coefficients
77 des inéquations et équations sont entiers. En attendant la tactique Field.
83 let debug x = print_string ("____ "^x) ; flush stdout;;
85 let debug_pcontext x =
87 List.iter (fun y -> match y with Some(Cic.Name(a),_) -> str := !str ^ a ^ " " | _ ->()) x ;
88 debug ("contesto : "^ (!str) ^ "\n")
91 (******************************************************************************
92 Operations on linear combinations.
94 Opérations sur les combinaisons linéaires affines.
95 La partie homogène d'une combinaison linéaire est en fait une table de hash
96 qui donne le coefficient d'un terme du calcul des constructions,
97 qui est zéro si le terme n'y est pas.
103 The type for linear combinations
105 type flin = {fhom:(Cic.term , rational)Hashtbl.t;fcste:rational}
109 @return an empty flin
111 let flin_zero () = {fhom = Hashtbl.create 50;fcste=r0}
117 @return the rational associated with x (coefficient)
121 (Hashtbl.find f.fhom x)
127 Adds c to the coefficient of x
134 let cx = flin_coef f x in
135 Hashtbl.remove f.fhom x;
136 Hashtbl.add f.fhom x (rplus cx c);
145 let flin_add_cste f c =
147 fcste=rplus f.fcste c}
151 @return a empty flin with r1 in fcste
153 let flin_one () = flin_add_cste (flin_zero()) r1;;
158 let flin_plus f1 f2 =
159 let f3 = flin_zero() in
160 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
161 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f2.fhom;
162 flin_add_cste (flin_add_cste f3 f1.fcste) f2.fcste;
168 let flin_minus f1 f2 =
169 let f3 = flin_zero() in
170 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
171 Hashtbl.iter (fun x c -> let _=flin_add f3 x (rop c) in ()) f2.fhom;
172 flin_add_cste (flin_add_cste f3 f1.fcste) (rop f2.fcste);
179 let f2 = flin_zero() in
180 Hashtbl.iter (fun x c -> let _=flin_add f2 x (rmult a c) in ()) f.fhom;
181 flin_add_cste f2 (rmult a f.fcste);
185 (*****************************************************************************)
190 @return proiection on string of t
192 let rec string_of_term t =
194 Cic.Cast (t1,t2) -> string_of_term t1
195 |Cic.Const (u,boh) -> UriManager.string_of_uri u
196 |Cic.Var (u) -> UriManager.string_of_uri u
197 | _ -> "not_of_constant"
201 let string_of_constr = string_of_term
207 @raise Failure if conversion is impossible
208 @return rational proiection of t
210 let rec rational_of_term t =
211 (* fun to apply f to the first and second rational-term of l *)
212 let rat_of_binop f l =
213 let a = List.hd l and
214 b = List.hd(List.tl l) in
215 f (rational_of_term a) (rational_of_term b)
217 (* as before, but f is unary *)
218 let rat_of_unop f l =
219 f (rational_of_term (List.hd l))
222 | Cic.Cast (t1,t2) -> (rational_of_term t1)
223 | Cic.Appl (t1::next) ->
226 (match (UriManager.string_of_uri u) with
227 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
229 |"cic:/Coq/Reals/Rdefinitions/Rinv.con" ->
230 rat_of_unop rinv next
231 |"cic:/Coq/Reals/Rdefinitions/Rmult.con" ->
232 rat_of_binop rmult next
233 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con" ->
234 rat_of_binop rdiv next
235 |"cic:/Coq/Reals/Rdefinitions/Rplus.con" ->
236 rat_of_binop rplus next
237 |"cic:/Coq/Reals/Rdefinitions/Rminus.con" ->
238 rat_of_binop rminus next
239 | _ -> failwith "not a rational")
240 | _ -> failwith "not a rational")
241 | Cic.Const (u,boh) ->
242 (match (UriManager.string_of_uri u) with
243 "cic:/Coq/Reals/Rdefinitions/R1.con" -> r1
244 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> r0
245 | _ -> failwith "not a rational")
246 | _ -> failwith "not a rational"
250 let rational_of_const = rational_of_term;;
254 let rec flin_of_term t =
255 let fl_of_binop f l =
256 let a = List.hd l and
257 b = List.hd(List.tl l) in
258 f (flin_of_term a) (flin_of_term b)
262 | Cic.Cast (t1,t2) -> (flin_of_term t1)
263 | Cic.Appl (t1::next) ->
268 match (UriManager.string_of_uri u) with
269 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
270 flin_emult (rop r1) (flin_of_term (List.hd next))
271 |"cic:/Coq/Reals/Rdefinitions/Rplus.con"->
272 fl_of_binop flin_plus next
273 |"cic:/Coq/Reals/Rdefinitions/Rminus.con"->
274 fl_of_binop flin_minus next
275 |"cic:/Coq/Reals/Rdefinitions/Rmult.con"->
277 let arg1 = (List.hd next) and
278 arg2 = (List.hd(List.tl next))
282 let a = rational_of_term arg1 in
285 let b = (rational_of_term arg2) in
286 (flin_add_cste (flin_zero()) (rmult a b))
289 _ -> (flin_add (flin_zero()) arg2 a)
292 _-> (flin_add (flin_zero()) arg1 (rational_of_term arg2 ))
294 |"cic:/Coq/Reals/Rdefinitions/Rinv.con"->
295 let a=(rational_of_term (List.hd next)) in
296 flin_add_cste (flin_zero()) (rinv a)
297 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con"->
299 let b=(rational_of_term (List.hd(List.tl next))) in
302 let a = (rational_of_term (List.hd next)) in
303 (flin_add_cste (flin_zero()) (rdiv a b))
306 _-> (flin_add (flin_zero()) (List.hd next) (rinv b))
312 | Cic.Const (u,boh) ->
314 match (UriManager.string_of_uri u) with
315 "cic:/Coq/Reals/Rdefinitions/R1.con" -> flin_one ()
316 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> flin_zero ()
320 with _ -> flin_add (flin_zero()) t r1
324 let flin_of_constr = flin_of_term;;
328 Translates a flin to (c,x) list
330 @return something like (c1,x1)::(c2,x2)::...::(cn,xn)
332 let flin_to_alist f =
334 Hashtbl.iter (fun x c -> res:=(c,x)::(!res)) f;
338 (* Représentation des hypothèses qui sont des inéquations ou des équations.
342 The structure for ineq
344 type hineq={hname:Cic.term; (* le nom de l'hypothèse *)
345 htype:string; (* Rlt, Rgt, Rle, Rge, eqTLR ou eqTRL *)
352 (* Transforme une hypothese h:t en inéquation flin<0 ou flin<=0
355 let ineq1_of_term (h,t) =
356 match t with (* match t *)
357 Cic.Appl (t1::next) ->
358 let arg1= List.hd next in
359 let arg2= List.hd(List.tl next) in
360 (match t1 with (* match t1 *)
362 (match UriManager.string_of_uri u with (* match u *)
363 "cic:/Coq/Reals/Rdefinitions/Rlt.con" ->
368 hflin= flin_minus (flin_of_term arg1)
371 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" ->
376 hflin= flin_minus (flin_of_term arg2)
379 |"cic:/Coq/Reals/Rdefinitions/Rle.con" ->
384 hflin= flin_minus (flin_of_term arg1)
387 |"cic:/Coq/Reals/Rdefinitions/Rge.con" ->
392 hflin= flin_minus (flin_of_term arg2)
395 |_->assert false)(* match u *)
396 | Cic.MutInd (u,i,o) ->
397 (match UriManager.string_of_uri u with
398 "cic:/Coq/Init/Logic_Type/eqT.con" ->
401 let arg2= List.hd(List.tl (List.tl next)) in
404 (match UriManager.string_of_uri u with
405 "cic:/Coq/Reals/Rdefinitions/R.con"->
410 hflin= flin_minus (flin_of_term arg1)
417 hflin= flin_minus (flin_of_term arg2)
423 |_-> assert false)(* match t1 *)
424 |_-> assert false (* match t *)
427 let ineq1_of_constr = ineq1_of_term;;
430 (* Applique la méthode de Fourier à une liste d'hypothèses (type hineq)
436 | a::next -> Fourier.print_rational a ; print_string " " ; print_rl next
439 let rec print_sys l =
442 | (a,b)::next -> (print_rl a;
443 print_string (if b=true then "strict\n"else"\n");
448 Hashtbl.iter (fun x y -> print_string ("("^"-"^","^"-"^")")) h
451 let fourier_lineq lineq1 =
453 let hvar=Hashtbl.create 50 in (* la table des variables des inéquations *)
455 Hashtbl.iter (fun x c ->
456 try (Hashtbl.find hvar x;())
457 with _-> nvar:=(!nvar)+1;
458 Hashtbl.add hvar x (!nvar))
462 debug("Il numero di incognite e' "^string_of_int (!nvar+1)^"\n");
463 let sys= List.map (fun h->
464 let v=Array.create ((!nvar)+1) r0 in
465 Hashtbl.iter (fun x c -> v.(Hashtbl.find hvar x)<-c)
467 ((Array.to_list v)@[rop h.hflin.fcste],h.hstrict))
469 debug ("chiamo unsolvable sul sistema di "^ string_of_int (List.length sys) ^"\n");
474 (******************************************************************************
475 Construction de la preuve en cas de succès de la méthode de Fourier,
476 i.e. on obtient une contradiction.
480 let _False = Cic.MutInd (UriManager.uri_of_string "cic:/Coq/Init/Logic/False.ind") 0 0 ;;
481 let _not = Cic.Const (UriManager.uri_of_string "cic:/Coq/Init/Logic/not.con") 0;;
482 let _R0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R0.con") 0 ;;
483 let _R1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R1.con") 0 ;;
484 let _R = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R.con") 0 ;;
485 let _Rfourier_eqLR_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqLR_to_le.con") 0 ;;
486 let _Rfourier_eqRL_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqRL_to_le.con") 0 ;;
487 let _Rfourier_ge_to_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_ge_to_le.con") 0 ;;
488 let _Rfourier_gt_to_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_gt_to_lt.con") 0 ;;
489 let _Rfourier_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le.con") 0 ;;
490 let _Rfourier_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_le.con") 0 ;;
491 let _Rfourier_le_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_lt.con") 0 ;;
492 let _Rfourier_lt=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt.con") 0 ;;
493 let _Rfourier_lt_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_le.con") 0 ;;
494 let _Rfourier_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_lt.con") 0 ;;
495 let _Rfourier_not_ge_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_ge_lt.con") 0 ;;
496 let _Rfourier_not_gt_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_gt_le.con") 0 ;;
497 let _Rfourier_not_le_gt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_le_gt.con") 0 ;;
498 let _Rfourier_not_lt_ge = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_lt_ge.con") 0 ;;
499 let _Rinv = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rinv.con") 0 ;;
500 let _Rinv_R1 = Cic.Const(UriManager.uri_of_string "cic:/Coq/Reals/Rbase/Rinv_R1.con" ) 0;;
501 let _Rle = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rle.con") 0 ;;
502 let _Rle_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_mult_inv_pos.con") 0 ;;
503 let _Rle_not_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_not_lt.con") 0 ;;
504 let _Rle_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_1.con") 0 ;;
505 let _Rle_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_pos_plus1.con") 0 ;;
506 let _Rle_zero_zero = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_zero.con") 0 ;;
507 let _Rlt = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rlt.con") 0 ;;
508 let _Rlt_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_mult_inv_pos.con") 0 ;;
509 let _Rlt_not_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_not_le.con") 0 ;;
510 let _Rlt_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_1.con") 0 ;;
511 let _Rlt_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_pos_plus1.con") 0 ;;
512 let _Rminus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rminus.con") 0 ;;
513 let _Rmult = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rmult.con") 0 ;;
514 let _Rnot_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_le_le.con") 0 ;;
515 let _Rnot_lt0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt0.con") 0 ;;
516 let _Rnot_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt_lt.con") 0 ;;
517 let _Ropp = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Ropp.con") 0 ;;
518 let _Rplus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rplus.con") 0 ;;
519 let _sym_eqT = Cic.Const(UriManager.uri_of_string "/Coq/Init/Logic_Type/Equality_is_a_congruence/sym_eqT.con") 0 ;;
520 (*****************************************************************************************************)
521 let is_int x = (x.den)=1
524 (* fraction = couple (num,den) *)
525 let rec rational_to_fraction x= (x.num,x.den)
528 (* traduction -3 -> (Ropp (Rplus R1 (Rplus R1 R1)))
531 let rec int_to_real_aux n =
533 0 -> _R0 (* o forse R0 + R0 ????? *)
535 | _ -> Cic.Appl [ _Rplus ; _R1 ; int_to_real_aux (n-1) ]
540 let x = int_to_real_aux (abs n) in
542 Cic.Appl [ _Ropp ; x ]
548 (* -1/2 -> (Rmult (Ropp R1) (Rinv (Rplus R1 R1)))
551 let rational_to_real x =
552 let (n,d)=rational_to_fraction x in
553 Cic.Appl [ _Rmult ; int_to_real n ; Cic.Appl [ _Rinv ; int_to_real d ] ]
556 (* preuve que 0<n*1/d
561 let tac_zero_inf_pos gl (n,d) =
562 (*let cste = pf_parse_constr gl in*)
563 let tacn=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
564 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
566 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacn); done;
568 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
569 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos) ~continuations:[!tacn;!tacd])
571 let tac_zero_inf_pos (n,d) ~status =
572 (*let cste = pf_parse_constr gl in*)
573 let pall str ~status:(proof,goal) t =
574 debug ("tac "^str^" :\n" );
575 let curi,metasenv,pbo,pty = proof in
576 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
577 debug ("th = "^ CicPp.ppterm t ^"\n");
578 debug ("ty = "^ CicPp.ppterm ty^"\n");
581 (fun ~status -> pall "n0" ~status _Rlt_zero_1 ;PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
583 (fun ~status -> pall "d0" ~status _Rlt_zero_1 ;PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
587 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;
589 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;
593 debug("TAC ZERO INF POS\n");
595 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos)
604 (* preuve que 0<=n*1/d
607 let tac_zero_infeq_pos gl (n,d) =
608 (*let cste = pf_parse_constr gl in*)
609 let tacn = ref (if n=0 then
610 (PrimitiveTactics.apply_tac ~term:_Rle_zero_zero )
612 (PrimitiveTactics.apply_tac ~term:_Rle_zero_1 ))
614 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
616 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_zero_pos_plus1) ~continuation:!tacn); done;
618 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
619 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rle_mult_inv_pos) ~continuations:[!tacn;!tacd])
624 (* preuve que 0<(-n)*(1/d) => False
627 let tac_zero_inf_false gl (n,d) =
628 if n=0 then (PrimitiveTactics.apply_tac ~term:_Rnot_lt0)
630 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_not_lt)
631 ~continuation:(tac_zero_infeq_pos gl (-n,d)))
634 (* preuve que 0<=(-n)*(1/d) => False
637 let tac_zero_infeq_false gl (n,d) =
638 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_not_le)
639 ~continuation:(tac_zero_inf_pos (-n,d)))
643 (* *********** ********** ******** ??????????????? *********** **************)
645 let apply_type_tac ~cast:t ~applist:al ~status:(proof,goal) =
646 let curi,metasenv,pbo,pty = proof in
647 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
648 let fresh_meta = ProofEngineHelpers.new_meta proof in
650 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
651 let metasenv' = (fresh_meta,context,t)::metasenv in
652 let proof' = curi,metasenv',pbo,pty in
654 PrimitiveTactics.apply_tac ~term:(Cic.Appl ((Cic.Cast (Cic.Meta (fresh_meta,irl),t))::al)) ~status:(proof',goal)
656 proof'',fresh_meta::goals
663 let my_cut ~term:c ~status:(proof,goal)=
664 let curi,metasenv,pbo,pty = proof in
665 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
667 let fresh_meta = ProofEngineHelpers.new_meta proof in
669 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
670 let metasenv' = (fresh_meta,context,c)::metasenv in
671 let proof' = curi,metasenv',pbo,pty in
673 apply_type_tac ~cast:(Cic.Prod(Cic.Name "Anonymous",c,CicSubstitution.lift 1 ty)) ~applist:[Cic.Meta(fresh_meta,irl)] ~status:(proof',goal)
675 (* We permute the generated goals to be consistent with Coq *)
678 | he::tl -> proof'',he::fresh_meta::tl
682 let exact = PrimitiveTactics.exact_tac;;
684 let tac_use h ~status:(proof,goal as status) =
685 debug("Inizio TC_USE\n");
686 let curi,metasenv,pbo,pty = proof in
687 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
688 debug ("hname = "^ CicPp.ppterm h.hname ^"\n");
689 debug ("ty = "^ CicPp.ppterm ty^"\n");
693 "Rlt" -> exact ~term:h.hname ~status
694 |"Rle" -> exact ~term:h.hname ~status
695 |"Rgt" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_gt_to_lt)
696 ~continuation:(exact ~term:h.hname)) ~status
697 |"Rge" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_ge_to_le)
698 ~continuation:(exact ~term:h.hname)) ~status
699 |"eqTLR" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqLR_to_le)
700 ~continuation:(exact ~term:h.hname)) ~status
701 |"eqTRL" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqRL_to_le)
702 ~continuation:(exact ~term:h.hname)) ~status
705 debug("Fine TAC_USE\n");
713 Cic.Appl ( Cic.Const(u,boh)::next) ->
714 (match (UriManager.string_of_uri u) with
715 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> true
716 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> true
717 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> true
718 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> true
719 |"cic:/Coq/Init/Logic_Type/eqT.con" ->
720 (match (List.hd next) with
721 Cic.Const (uri,_) when
722 UriManager.string_of_uri uri =
723 "cic:/Coq/Reals/Rdefinitions/R.con" -> true
729 let list_of_sign s = List.map (fun (x,_,z)->(x,z)) s;;
732 Cic.Appl(Array.to_list a)
735 (* Résolution d'inéquations linéaires dans R *)
736 let rec strip_outer_cast c = match c with
737 | Cic.Cast (c,_) -> strip_outer_cast c
741 let find_in_context id context =
742 let rec find_in_context_aux c n =
744 [] -> failwith (id^" not found in context")
745 | a::next -> (match a with
746 Some (Cic.Name(name),_) when name = id -> n
747 (*? magari al posto di _ qualcosaltro?*)
748 | _ -> find_in_context_aux next (n+1))
750 find_in_context_aux context 1
753 (* mi sembra quadratico *)
754 let rec filter_real_hyp context cont =
757 | Some(Cic.Name(h),Cic.Decl(t))::next -> (
758 let n = find_in_context h cont in
759 [(Cic.Rel(n),t)] @ filter_real_hyp next cont)
760 | a::next -> debug(" no\n"); filter_real_hyp next cont
763 (* lifts everithing at the conclusion level *)
764 let rec superlift c n=
767 | Some(name,Cic.Decl(a))::next -> [Some(name,Cic.Decl(CicSubstitution.lift n a))] @ superlift next (n+1)
768 | Some(name,Cic.Def(a))::next -> [Some(name,Cic.Def(CicSubstitution.lift n a))] @ superlift next (n+1)
769 | _::next -> superlift next (n+1) (*?? ??*)
773 (* fix !!!!!!!!!! this may not work *)
774 let equality_replace a b ~status =
775 let proof,goal = status in
776 let curi,metasenv,pbo,pty = proof in
777 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
778 prerr_endline ("<MY_CUT: " ^ CicPp.ppterm a ^ " <=> " ^ CicPp.ppterm b) ;
779 prerr_endline ("### IN MY_CUT: ") ;
780 prerr_endline ("@ " ^ CicPp.ppterm ty) ;
781 List.iter (function Some (n,Cic.Decl t) -> prerr_endline ("# " ^ CicPp.ppterm t)) context ;
782 prerr_endline ("##- IN MY_CUT ") ;
784 let _eqT_ind = Cic.Const( UriManager.uri_of_string "cic:/Coq/Init/Logic_Type/eqT_ind.con" ) 0 in
785 (*CSC: codice ad-hoc per questo caso!!! Non funge in generale *)
786 PrimitiveTactics.apply_tac ~term:(Cic.Appl [_eqT_ind;_R;b;Cic.Lambda(Cic.Name "pippo",_R,Cic.Appl [_not; Cic.Appl [_Rlt;_R0;Cic.Rel 1]])]) ~status
788 prerr_endline "EUREKA" ;
792 let tcl_fail a ~status:(proof,goal) =
794 1 -> raise (ProofEngineTypes.Fail "fail-tactical")
799 let assumption_tac ~status:(proof,goal)=
800 let curi,metasenv,pbo,pty = proof in
801 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
803 let tac_list = List.map
804 ( fun x -> num := !num + 1;
806 Some(Cic.Name(nm),t) -> (nm,exact ~term:(Cic.Rel(!num)))
807 | _ -> ("fake",tcl_fail 1)
811 Tacticals.try_tactics ~tactics:tac_list ~status:(proof,goal)
814 (* !!!!! fix !!!!!!!!!! *)
815 let contradiction_tac ~status:(proof,goal)=
817 ~start:(PrimitiveTactics.intros_tac ~name:"bo?" )
818 ~continuation:(Tacticals.then_
819 ~start:(Ring.elim_type_tac ~term:_False)
820 ~continuation:(assumption_tac))
824 (* ********************* TATTICA ******************************** *)
826 let rec fourier ~status:(s_proof,s_goal)=
827 let s_curi,s_metasenv,s_pbo,s_pty = s_proof in
828 let s_metano,s_context,s_ty = List.find (function (m,_,_) -> m=s_goal) s_metasenv in
830 debug ("invoco fourier_tac sul goal "^string_of_int(s_goal)^" e contesto :\n");
831 debug_pcontext s_context;
833 let fhyp = String.copy "new_hyp_for_fourier" in
835 (* here we need to negate the thesis, but to do this we nned to apply the right theoreme,
836 so let's parse our thesis *)
838 let th_to_appl = ref _Rfourier_not_le_gt in
840 Cic.Appl ( Cic.Const(u,boh)::args) ->
841 (match UriManager.string_of_uri u with
842 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> th_to_appl := _Rfourier_not_ge_lt
843 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> th_to_appl := _Rfourier_not_gt_le
844 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> th_to_appl := _Rfourier_not_le_gt
845 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> th_to_appl := _Rfourier_not_lt_ge
846 |_-> failwith "fourier can't be applyed")
847 |_-> failwith "fourier can't be applyed"); (* fix maybe strip_outer_cast goes here?? *)
849 (* now let's change our thesis applying the th and put it with hp *)
851 let proof,gl = Tacticals.then_
852 ~start:(PrimitiveTactics.apply_tac ~term:!th_to_appl)
853 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp)
854 ~status:(s_proof,s_goal) in
855 let goal = if List.length gl = 1 then List.hd gl else failwith "a new goal" in
857 debug ("port la tesi sopra e la nego. contesto :\n");
858 debug_pcontext s_context;
860 (* now we have all the right environment *)
862 let curi,metasenv,pbo,pty = proof in
863 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
866 (* now we want to convert hp to inequations, but first we must lift
867 everyting to thesis level, so that a variable has the save Rel(n)
868 in each hp ( needed by ineq1_of_term ) *)
870 (* ? fix if None ?????*)
871 (* fix change superlift with a real name *)
873 let l_context = superlift context 1 in
874 let hyps = filter_real_hyp l_context l_context in
876 debug ("trasformo in diseq. "^ string_of_int (List.length hyps)^" ipotesi\n");
880 (* transform hyps into inequations *)
882 List.iter (fun h -> try (lineq:=(ineq1_of_term h)@(!lineq))
887 debug ("applico fourier a "^ string_of_int (List.length !lineq)^" disequazioni\n");
889 let res=fourier_lineq (!lineq) in
890 let tac=ref Ring.id_tac in
892 (print_string "Tactic Fourier fails.\n";flush stdout;failwith "fourier_tac fails")
895 match res with (*match res*)
898 (* in lc we have the coefficient to "reduce" the system *)
900 print_string "Fourier's method can prove the goal...\n";flush stdout;
902 debug "I coeff di moltiplicazione rit sono: ";
906 (fun (h,c) -> if c<>r0 then (lutil:=(h,c)::(!lutil);
907 (* DBG *)Fourier.print_rational(c);print_string " "(* DBG *))
909 (List.combine (!lineq) lc);
911 print_string (" quindi lutil e' lunga "^string_of_int (List.length (!lutil))^"\n");
913 (* on construit la combinaison linéaire des inéquation *)
915 (match (!lutil) with (*match (!lutil) *)
918 debug ("elem di lutil ");Fourier.print_rational c1;print_string "\n";
920 let s=ref (h1.hstrict) in
922 (* let t1=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hleft|]) in
923 let t2=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hright|]) in
926 let t1 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hleft] ) in
927 let t2 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hright]) in
929 List.iter (fun (h,c) ->
930 s:=(!s)||(h.hstrict);
931 t1:=(Cic.Appl [_Rplus;!t1;Cic.Appl [_Rmult;rational_to_real c;h.hleft ] ]);
932 t2:=(Cic.Appl [_Rplus;!t2;Cic.Appl [_Rmult;rational_to_real c;h.hright] ]))
935 let ineq=Cic.Appl [(if (!s) then _Rlt else _Rle);!t1;!t2 ] in
936 let tc=rational_to_real cres in
939 (* ora ho i termini che descrivono i passi di fourier per risolvere il sistema *)
941 debug "inizio a costruire tac1\n";
942 Fourier.print_rational(c1);
944 let tac1=ref ( fun ~status ->
945 debug ("Sotto tattica t1 "^(if h1.hstrict then "strict" else "lasc")^"\n");
947 (Tacticals.thens ~start:(
949 debug ("inizio t1 strict\n");
950 let curi,metasenv,pbo,pty = proof in
951 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
952 debug ("th = "^ CicPp.ppterm _Rfourier_lt ^"\n");
953 debug ("ty = "^ CicPp.ppterm ty^"\n");
955 PrimitiveTactics.apply_tac ~term:_Rfourier_lt ~status)
956 ~continuations:[tac_use h1;
958 tac_zero_inf_pos (rational_to_fraction c1)] ~status
962 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le)
963 ~continuations:[tac_use h1;tac_zero_inf_pos (rational_to_fraction c1)] ~status))
968 List.iter (fun (h,c) ->
972 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac
973 ~term:_Rfourier_lt_lt)
974 ~continuations:[!tac1;tac_use h;
976 (rational_to_fraction c)]))
980 Fourier.print_rational(c1);
981 tac1:=(Tacticals.thens ~start:(
983 debug("INIZIO TAC 1 2\n");
985 let curi,metasenv,pbo,pty = proof in
986 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
987 debug ("th = "^ CicPp.ppterm _Rfourier_lt_le ^"\n");
988 debug ("ty = "^ CicPp.ppterm ty^"\n");
990 PrimitiveTactics.apply_tac ~term:_Rfourier_lt_le ~status
993 ~continuations:[!tac1;tac_use h;
995 tac_zero_inf_pos (rational_to_fraction c)
1004 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_lt)
1005 ~continuations:[!tac1;tac_use h;
1007 (rational_to_fraction c)]))
1011 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_le)
1012 ~continuations:[!tac1;tac_use h;
1014 (rational_to_fraction c)]))
1018 s:=(!s)||(h.hstrict))
1019 lutil;(*end List.iter*)
1021 let tac2= if sres then
1022 tac_zero_inf_false goal (rational_to_fraction cres)
1024 tac_zero_infeq_false goal (rational_to_fraction cres)
1026 tac:=(Tacticals.thens ~start:(my_cut ~term:ineq)
1027 ~continuations:[Tacticals.then_ (* ?????????????????????????????? *)
1028 ~start:(fun ~status:(proof,goal as status) ->
1029 let curi,metasenv,pbo,pty = proof in
1030 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
1031 PrimitiveTactics.change_tac ~what:ty ~with_what:(Cic.Appl [ _not; ineq]) ~status)
1032 ~continuation:(Tacticals.then_
1033 ~start:(PrimitiveTactics.apply_tac
1034 ~term:(if sres then _Rnot_lt_lt else _Rnot_le_le))
1035 ~continuation:Ring.id_tac
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);;