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/eq.ind") ->
40 (U.uri_of_string "cic:/Coq/Init/Logic/eq_ind_r.con",[])
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",[])
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
60 ~equality:ProofEngineReduction.alpha_equivalence
61 ~what:t1' ~with_what:(C.Rel 1) ~where:gty'
63 C.Lambda (C.Name "dummy_for_rewrite", ty, gty'')
65 prerr_endline ("#### Sintetizzato: " ^ CicPp.ppterm pred);
66 let fresh_meta = ProofEngineHelpers.new_meta proof in
68 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
69 let metasenv' = (fresh_meta,context,C.Appl [pred ; t2])::metasenv in
72 PrimitiveTactics.exact_tac
74 [eq_ind_r ; ty ; t2 ; pred ; C.Meta (fresh_meta,irl) ; t1 ;equality])
75 ~status:((curi,metasenv',pbo,pty),goal)
77 assert (List.length goals = 0) ;
83 let simpl_tac ~status:(proof,goal) =
84 let curi,metasenv,pbo,pty = proof in
85 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
87 prerr_endline("simpl_tac su "^CicPp.ppterm ty);
89 let new_ty = ProofEngineReduction.simpl context ty in
91 prerr_endline("ritorna "^CicPp.ppterm new_ty);
96 (n,_,_) when n = metano -> (metano,context,new_ty)
100 (curi,new_metasenv,pbo,pty), [metano]
104 let rewrite_simpl_tac ~term ~status =
106 Tacticals.then_ ~start:(rewrite_tac ~term) ~continuation:simpl_tac ~status
110 (******************** THE FOURIER TACTIC ***********************)
112 (* La tactique Fourier ne fonctionne de manière sûre que si les coefficients
113 des inéquations et équations sont entiers. En attendant la tactique Field.
119 let debug x = print_string ("____ "^x) ; flush stdout;;
121 let debug_pcontext x =
123 List.iter (fun y -> match y with Some(Cic.Name(a),_) -> str := !str ^
124 a ^ " " | _ ->()) x ;
125 debug ("contesto : "^ (!str) ^ "\n")
128 (******************************************************************************
129 Operations on linear combinations.
131 Opérations sur les combinaisons linéaires affines.
132 La partie homogène d'une combinaison linéaire est en fait une table de hash
133 qui donne le coefficient d'un terme du calcul des constructions,
134 qui est zéro si le terme n'y est pas.
140 The type for linear combinations
142 type flin = {fhom:(Cic.term , rational)Hashtbl.t;fcste:rational}
146 @return an empty flin
148 let flin_zero () = {fhom = Hashtbl.create 50;fcste=r0}
154 @return the rational associated with x (coefficient)
158 (Hashtbl.find f.fhom x)
164 Adds c to the coefficient of x
171 let cx = flin_coef f x in
172 Hashtbl.remove f.fhom x;
173 Hashtbl.add f.fhom x (rplus cx c);
182 let flin_add_cste f c =
184 fcste=rplus f.fcste c}
188 @return a empty flin with r1 in fcste
190 let flin_one () = flin_add_cste (flin_zero()) r1;;
195 let flin_plus f1 f2 =
196 let f3 = flin_zero() in
197 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
198 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f2.fhom;
199 flin_add_cste (flin_add_cste f3 f1.fcste) f2.fcste;
205 let flin_minus f1 f2 =
206 let f3 = flin_zero() in
207 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
208 Hashtbl.iter (fun x c -> let _=flin_add f3 x (rop c) in ()) f2.fhom;
209 flin_add_cste (flin_add_cste f3 f1.fcste) (rop f2.fcste);
216 let f2 = flin_zero() in
217 Hashtbl.iter (fun x c -> let _=flin_add f2 x (rmult a c) in ()) f.fhom;
218 flin_add_cste f2 (rmult a f.fcste);
222 (*****************************************************************************)
227 @return proiection on string of t
229 let rec string_of_term t =
231 Cic.Cast (t,_) -> string_of_term t
232 |Cic.Const (u,_) -> UriManager.string_of_uri u
233 |Cic.Var (u,_) -> UriManager.string_of_uri u
234 | _ -> "not_of_constant"
238 let string_of_constr = string_of_term
244 @raise Failure if conversion is impossible
245 @return rational proiection of t
247 let rec rational_of_term t =
248 (* fun to apply f to the first and second rational-term of l *)
249 let rat_of_binop f l =
250 let a = List.hd l and
251 b = List.hd(List.tl l) in
252 f (rational_of_term a) (rational_of_term b)
254 (* as before, but f is unary *)
255 let rat_of_unop f l =
256 f (rational_of_term (List.hd l))
259 | Cic.Cast (t1,t2) -> (rational_of_term t1)
260 | Cic.Appl (t1::next) ->
263 (match (UriManager.string_of_uri u) with
264 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
266 |"cic:/Coq/Reals/Rdefinitions/Rinv.con" ->
267 rat_of_unop rinv next
268 |"cic:/Coq/Reals/Rdefinitions/Rmult.con" ->
269 rat_of_binop rmult next
270 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con" ->
271 rat_of_binop rdiv next
272 |"cic:/Coq/Reals/Rdefinitions/Rplus.con" ->
273 rat_of_binop rplus next
274 |"cic:/Coq/Reals/Rdefinitions/Rminus.con" ->
275 rat_of_binop rminus next
276 | _ -> failwith "not a rational")
277 | _ -> failwith "not a rational")
278 | Cic.Const (u,boh) ->
279 (match (UriManager.string_of_uri u) with
280 "cic:/Coq/Reals/Rdefinitions/R1.con" -> r1
281 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> r0
282 | _ -> failwith "not a rational")
283 | _ -> failwith "not a rational"
287 let rational_of_const = rational_of_term;;
291 let rec flin_of_term t =
292 let fl_of_binop f l =
293 let a = List.hd l and
294 b = List.hd(List.tl l) in
295 f (flin_of_term a) (flin_of_term b)
299 | Cic.Cast (t1,t2) -> (flin_of_term t1)
300 | Cic.Appl (t1::next) ->
305 match (UriManager.string_of_uri u) with
306 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
307 flin_emult (rop r1) (flin_of_term (List.hd next))
308 |"cic:/Coq/Reals/Rdefinitions/Rplus.con"->
309 fl_of_binop flin_plus next
310 |"cic:/Coq/Reals/Rdefinitions/Rminus.con"->
311 fl_of_binop flin_minus next
312 |"cic:/Coq/Reals/Rdefinitions/Rmult.con"->
314 let arg1 = (List.hd next) and
315 arg2 = (List.hd(List.tl next))
319 let a = rational_of_term arg1 in
322 let b = (rational_of_term arg2) in
323 (flin_add_cste (flin_zero()) (rmult a b))
326 _ -> (flin_add (flin_zero()) arg2 a)
329 _-> (flin_add(flin_zero()) arg1 (rational_of_term arg2))
331 |"cic:/Coq/Reals/Rdefinitions/Rinv.con"->
332 let a=(rational_of_term (List.hd next)) in
333 flin_add_cste (flin_zero()) (rinv a)
334 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con"->
336 let b=(rational_of_term (List.hd(List.tl next))) in
339 let a = (rational_of_term (List.hd next)) in
340 (flin_add_cste (flin_zero()) (rdiv a b))
343 _-> (flin_add (flin_zero()) (List.hd next) (rinv b))
349 | Cic.Const (u,boh) ->
351 match (UriManager.string_of_uri u) with
352 "cic:/Coq/Reals/Rdefinitions/R1.con" -> flin_one ()
353 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> flin_zero ()
357 with _ -> flin_add (flin_zero()) t r1
361 let flin_of_constr = flin_of_term;;
365 Translates a flin to (c,x) list
367 @return something like (c1,x1)::(c2,x2)::...::(cn,xn)
369 let flin_to_alist f =
371 Hashtbl.iter (fun x c -> res:=(c,x)::(!res)) f;
375 (* Représentation des hypothèses qui sont des inéquations ou des équations.
379 The structure for ineq
381 type hineq={hname:Cic.term; (* le nom de l'hypothèse *)
382 htype:string; (* Rlt, Rgt, Rle, Rge, eqTLR ou eqTRL *)
389 (* Transforme une hypothese h:t en inéquation flin<0 ou flin<=0
392 let ineq1_of_term (h,t) =
393 match t with (* match t *)
394 Cic.Appl (t1::next) ->
395 let arg1= List.hd next in
396 let arg2= List.hd(List.tl next) in
397 (match t1 with (* match t1 *)
399 (match UriManager.string_of_uri u with (* match u *)
400 "cic:/Coq/Reals/Rdefinitions/Rlt.con" ->
405 hflin= flin_minus (flin_of_term arg1)
408 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" ->
413 hflin= flin_minus (flin_of_term arg2)
416 |"cic:/Coq/Reals/Rdefinitions/Rle.con" ->
421 hflin= flin_minus (flin_of_term arg1)
424 |"cic:/Coq/Reals/Rdefinitions/Rge.con" ->
429 hflin= flin_minus (flin_of_term arg2)
432 |_->assert false)(* match u *)
433 | Cic.MutInd (u,i,o) ->
434 (match UriManager.string_of_uri u with
435 "cic:/Coq/Init/Logic_Type/eqT.con" ->
438 let arg2= List.hd(List.tl (List.tl next)) in
441 (match UriManager.string_of_uri u with
442 "cic:/Coq/Reals/Rdefinitions/R.con"->
447 hflin= flin_minus (flin_of_term arg1)
454 hflin= flin_minus (flin_of_term arg2)
460 |_-> assert false)(* match t1 *)
461 |_-> assert false (* match t *)
464 let ineq1_of_constr = ineq1_of_term;;
467 (* Applique la méthode de Fourier à une liste d'hypothèses (type hineq)
473 | a::next -> Fourier.print_rational a ; print_string " " ; print_rl next
476 let rec print_sys l =
479 | (a,b)::next -> (print_rl a;
480 print_string (if b=true then "strict\n"else"\n");
485 Hashtbl.iter (fun x y -> print_string ("("^"-"^","^"-"^")")) h
488 let fourier_lineq lineq1 =
490 let hvar=Hashtbl.create 50 in (* la table des variables des inéquations *)
492 Hashtbl.iter (fun x c ->
493 try (Hashtbl.find hvar x;())
494 with _-> nvar:=(!nvar)+1;
495 Hashtbl.add hvar x (!nvar))
499 debug("Il numero di incognite e' "^string_of_int (!nvar+1)^"\n");
500 let sys= List.map (fun h->
501 let v=Array.create ((!nvar)+1) r0 in
502 Hashtbl.iter (fun x c -> v.(Hashtbl.find hvar x)<-c)
504 ((Array.to_list v)@[rop h.hflin.fcste],h.hstrict))
506 debug ("chiamo unsolvable sul sistema di "^
507 string_of_int (List.length sys) ^"\n");
512 (*****************************************************************************
513 Construction de la preuve en cas de succès de la méthode de Fourier,
514 i.e. on obtient une contradiction.
519 Cic.MutInd (UriManager.uri_of_string "cic:/Coq/Init/Logic_Type/eqT.ind") 0 [];;
521 Cic.MutInd (UriManager.uri_of_string "cic:/Coq/Init/Logic/False.ind") 0 [];;
523 Cic.Const (UriManager.uri_of_string "cic:/Coq/Init/Logic/not.con") [];;
525 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R0.con") [];;
527 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R1.con") [];;
529 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R.con") [];;
530 let _Rfourier_eqLR_to_le=
532 (UriManager.uri_of_string
533 "cic:/Coq/fourier/Fourier_util/Rfourier_eqLR_to_le.con") [];;
534 let _Rfourier_eqRL_to_le =
536 (UriManager.uri_of_string
537 "cic:/Coq/fourier/Fourier_util/Rfourier_eqRL_to_le.con") [];;
538 let _Rfourier_ge_to_le =
540 (UriManager.uri_of_string
541 "cic:/Coq/fourier/Fourier_util/Rfourier_ge_to_le.con") [];;
542 let _Rfourier_gt_to_lt =
544 (UriManager.uri_of_string
545 "cic:/Coq/fourier/Fourier_util/Rfourier_gt_to_lt.con") [];;
548 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le.con")[];;
549 let _Rfourier_le_le =
551 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_le.con")
553 let _Rfourier_le_lt =
555 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_lt.con")
559 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt.con") []
561 let _Rfourier_lt_le =
563 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_le.con")
566 let _Rfourier_lt_lt =
568 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_lt.con")
571 let _Rfourier_not_ge_lt =
573 (UriManager.uri_of_string
574 "cic:/Coq/fourier/Fourier_util/Rfourier_not_ge_lt.con") [];;
575 let _Rfourier_not_gt_le =
577 (UriManager.uri_of_string
578 "cic:/Coq/fourier/Fourier_util/Rfourier_not_gt_le.con") [];;
579 let _Rfourier_not_le_gt =
581 (UriManager.uri_of_string
582 "cic:/Coq/fourier/Fourier_util/Rfourier_not_le_gt.con") [];;
583 let _Rfourier_not_lt_ge =
585 (UriManager.uri_of_string
586 "cic:/Coq/fourier/Fourier_util/Rfourier_not_lt_ge.con") [];;
588 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rinv.con")[];;
590 Cic.Const(UriManager.uri_of_string "cic:/Coq/Reals/Rbase/Rinv_R1.con" ) [];;
592 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rle.con") [];;
593 let _Rle_mult_inv_pos =
595 (UriManager.uri_of_string
596 "cic:/Coq/fourier/Fourier_util/Rle_mult_inv_pos.con") [];;
599 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_not_lt.con") [];;
602 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_1.con") [];;
603 let _Rle_zero_pos_plus1 =
605 (UriManager.uri_of_string
606 "cic:/Coq/fourier/Fourier_util/Rle_zero_pos_plus1.con") [];;
609 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_zero.con")
613 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rlt.con") [];;
614 let _Rlt_mult_inv_pos =
616 (UriManager.uri_of_string
617 "cic:/Coq/fourier/Fourier_util/Rlt_mult_inv_pos.con") [];;
620 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_not_le.con") [];;
623 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_1.con") [];;
624 let _Rlt_zero_pos_plus1 =
626 (UriManager.uri_of_string
627 "cic:/Coq/fourier/Fourier_util/Rlt_zero_pos_plus1.con") [];;
629 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rminus.con")
633 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rmult.con")
638 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_le_le.con") [];;
641 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt0.con") [];;
644 (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt_lt.con") [];;
646 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Ropp.con") []
649 Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rplus.con") []
653 (UriManager.uri_of_string
654 "cic:/Coq/Init/Logic_Type/Equality_is_a_congruence/sym_eqT.con") [];;
656 (******************************************************************************)
658 let is_int x = (x.den)=1
661 (* fraction = couple (num,den) *)
662 let rec rational_to_fraction x= (x.num,x.den)
665 (* traduction -3 -> (Ropp (Rplus R1 (Rplus R1 R1)))
668 let rec int_to_real_aux n =
670 0 -> _R0 (* o forse R0 + R0 ????? *)
672 | _ -> Cic.Appl [ _Rplus ; _R1 ; int_to_real_aux (n-1) ]
677 let x = int_to_real_aux (abs n) in
679 Cic.Appl [ _Ropp ; x ]
685 (* -1/2 -> (Rmult (Ropp R1) (Rinv (Rplus R1 R1)))
688 let rational_to_real x =
689 let (n,d)=rational_to_fraction x in
690 Cic.Appl [ _Rmult ; int_to_real n ; Cic.Appl [ _Rinv ; int_to_real d ] ]
693 (* preuve que 0<n*1/d
696 let tac_zero_inf_pos (n,d) ~status =
697 (*let cste = pf_parse_constr gl in*)
698 let pall str ~status:(proof,goal) t =
699 debug ("tac "^str^" :\n" );
700 let curi,metasenv,pbo,pty = proof in
701 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
702 debug ("th = "^ CicPp.ppterm t ^"\n");
703 debug ("ty = "^ CicPp.ppterm ty^"\n");
706 (fun ~status -> pall "n0" ~status _Rlt_zero_1 ;
707 PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
709 (fun ~status -> pall "d0" ~status _Rlt_zero_1 ;
710 PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ~status ) in
714 tacn:=(Tacticals.then_ ~start:(fun ~status -> pall ("n"^string_of_int i)
715 ~status _Rlt_zero_pos_plus1;
716 PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1 ~status)
717 ~continuation:!tacn);
720 tacd:=(Tacticals.then_ ~start:(fun ~status -> pall "d"
721 ~status _Rlt_zero_pos_plus1 ;PrimitiveTactics.apply_tac
722 ~term:_Rlt_zero_pos_plus1 ~status) ~continuation:!tacd);
727 debug("TAC ZERO INF POS\n");
729 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos)
738 (* preuve que 0<=n*1/d
741 let tac_zero_infeq_pos gl (n,d) ~status =
742 (*let cste = pf_parse_constr gl in*)
743 debug("inizio tac_zero_infeq_pos\n");
746 (PrimitiveTactics.apply_tac ~term:_Rle_zero_zero )
748 (PrimitiveTactics.apply_tac ~term:_Rle_zero_1 )
751 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
753 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
754 ~term:_Rle_zero_pos_plus1) ~continuation:!tacn);
757 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
758 ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd);
761 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac
762 ~term:_Rle_mult_inv_pos) ~continuations:[!tacn;!tacd]) ~status in
763 debug("fine tac_zero_infeq_pos\n");
769 (* preuve que 0<(-n)*(1/d) => False
772 let tac_zero_inf_false gl (n,d) ~status=
773 debug("inizio tac_zero_inf_false\n");
775 (debug "1\n";let r =(PrimitiveTactics.apply_tac ~term:_Rnot_lt0 ~status) in
779 (debug "2\n";let r = (Tacticals.then_ ~start:(
780 fun ~status:(proof,goal as status) ->
781 let curi,metasenv,pbo,pty = proof in
782 let metano,context,ty =List.find (function (m,_,_) -> m=goal) metasenv in
783 debug("!!!!!!!!!1: unify "^CicPp.ppterm _Rle_not_lt^" with "
784 ^ CicPp.ppterm ty ^"\n");
785 let r = PrimitiveTactics.apply_tac ~term:_Rle_not_lt ~status in
786 debug("!!!!!!!!!2\n");
789 ~continuation:(tac_zero_infeq_pos gl (-n,d))) ~status in
795 (* preuve que 0<=(-n)*(1/d) => False
798 let tac_zero_infeq_false gl (n,d) ~status=
799 debug("stat tac_zero_infeq_false");
801 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_not_le)
802 ~continuation:(tac_zero_inf_pos (-n,d))) ~status in
803 debug("stat tac_zero_infeq_false");
808 (* *********** ********** ******** ??????????????? *********** **************)
810 let apply_type_tac ~cast:t ~applist:al ~status:(proof,goal) =
811 let curi,metasenv,pbo,pty = proof in
812 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
813 let fresh_meta = ProofEngineHelpers.new_meta proof in
815 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
816 let metasenv' = (fresh_meta,context,t)::metasenv in
817 let proof' = curi,metasenv',pbo,pty in
819 PrimitiveTactics.apply_tac ~term:(Cic.Appl ((Cic.Cast (Cic.Meta
820 (fresh_meta,irl),t))::al)) ~status:(proof',goal)
822 proof'',fresh_meta::goals
829 let my_cut ~term:c ~status:(proof,goal)=
830 let curi,metasenv,pbo,pty = proof in
831 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
833 let fresh_meta = ProofEngineHelpers.new_meta proof in
835 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
836 let metasenv' = (fresh_meta,context,c)::metasenv in
837 let proof' = curi,metasenv',pbo,pty in
839 apply_type_tac ~cast:(Cic.Prod(Cic.Name "Anonymous",c,
840 CicSubstitution.lift 1 ty)) ~applist:[Cic.Meta(fresh_meta,irl)]
841 ~status:(proof',goal)
843 (* We permute the generated goals to be consistent with Coq *)
846 | he::tl -> proof'',he::fresh_meta::tl
850 let exact = PrimitiveTactics.exact_tac;;
852 let tac_use h ~status:(proof,goal as status) =
853 debug("Inizio TC_USE\n");
854 let curi,metasenv,pbo,pty = proof in
855 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
856 debug ("hname = "^ CicPp.ppterm h.hname ^"\n");
857 debug ("ty = "^ CicPp.ppterm ty^"\n");
861 "Rlt" -> exact ~term:h.hname ~status
862 |"Rle" -> exact ~term:h.hname ~status
863 |"Rgt" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
864 ~term:_Rfourier_gt_to_lt)
865 ~continuation:(exact ~term:h.hname)) ~status
866 |"Rge" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
867 ~term:_Rfourier_ge_to_le)
868 ~continuation:(exact ~term:h.hname)) ~status
869 |"eqTLR" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
870 ~term:_Rfourier_eqLR_to_le)
871 ~continuation:(exact ~term:h.hname)) ~status
872 |"eqTRL" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac
873 ~term:_Rfourier_eqRL_to_le)
874 ~continuation:(exact ~term:h.hname)) ~status
877 debug("Fine TAC_USE\n");
885 Cic.Appl ( Cic.Const(u,boh)::next) ->
886 (match (UriManager.string_of_uri u) with
887 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> true
888 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> true
889 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> true
890 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> true
891 |"cic:/Coq/Init/Logic_Type/eqT.con" ->
892 (match (List.hd next) with
893 Cic.Const (uri,_) when
894 UriManager.string_of_uri uri =
895 "cic:/Coq/Reals/Rdefinitions/R.con" -> true
901 let list_of_sign s = List.map (fun (x,_,z)->(x,z)) s;;
904 Cic.Appl(Array.to_list a)
907 (* Résolution d'inéquations linéaires dans R *)
908 let rec strip_outer_cast c = match c with
909 | Cic.Cast (c,_) -> strip_outer_cast c
913 let find_in_context id context =
914 let rec find_in_context_aux c n =
916 [] -> failwith (id^" not found in context")
917 | a::next -> (match a with
918 Some (Cic.Name(name),_) when name = id -> n
919 (*? magari al posto di _ qualcosaltro?*)
920 | _ -> find_in_context_aux next (n+1))
922 find_in_context_aux context 1
925 (* mi sembra quadratico *)
926 let rec filter_real_hyp context cont =
929 | Some(Cic.Name(h),Cic.Decl(t))::next -> (
930 let n = find_in_context h cont in
931 [(Cic.Rel(n),t)] @ filter_real_hyp next cont)
932 | a::next -> debug(" no\n"); filter_real_hyp next cont
935 (* lifts everithing at the conclusion level *)
936 let rec superlift c n=
939 | Some(name,Cic.Decl(a))::next -> [Some(name,Cic.Decl(
940 CicSubstitution.lift n a))] @ superlift next (n+1)
941 | Some(name,Cic.Def(a))::next -> [Some(name,Cic.Def(
942 CicSubstitution.lift n a))] @ superlift next (n+1)
943 | _::next -> superlift next (n+1) (*?? ??*)
947 let equality_replace a b ~status =
948 debug("inizio EQ\n");
949 let module C = Cic in
950 let proof,goal = status in
951 let curi,metasenv,pbo,pty = proof in
952 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
953 let a_eq_b = C.Appl [ _eqT ; _R ; a ; b ] in
954 let fresh_meta = ProofEngineHelpers.new_meta proof in
956 ProofEngineHelpers.identity_relocation_list_for_metavariable context in
957 let metasenv' = (fresh_meta,context,a_eq_b)::metasenv in
958 debug("chamo rewrite tac su"^CicPp.ppterm (C.Meta (fresh_meta,irl)));
960 rewrite_simpl_tac ~term:(C.Meta (fresh_meta,irl))
961 ~status:((curi,metasenv',pbo,pty),goal)
963 let new_goals = fresh_meta::goals in
964 debug("fine EQ -> goals : "^string_of_int( List.length new_goals) ^" = "
965 ^string_of_int( List.length goals)^"+ meta\n");
969 let tcl_fail a ~status:(proof,goal) =
971 1 -> raise (ProofEngineTypes.Fail "fail-tactical")
976 let assumption_tac ~status:(proof,goal)=
977 let curi,metasenv,pbo,pty = proof in
978 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
980 let tac_list = List.map
981 ( fun x -> num := !num + 1;
983 Some(Cic.Name(nm),t) -> (nm,exact ~term:(Cic.Rel(!num)))
984 | _ -> ("fake",tcl_fail 1)
988 Tacticals.try_tactics ~tactics:tac_list ~status:(proof,goal)
991 (* !!!!! fix !!!!!!!!!! *)
992 let contradiction_tac ~status:(proof,goal)=
994 ~start:(PrimitiveTactics.intros_tac ~name:"bo?" )
995 ~continuation:(Tacticals.then_
996 ~start:(Ring.elim_type_tac ~term:_False)
997 ~continuation:(assumption_tac))
1001 (* ********************* TATTICA ******************************** *)
1003 let rec fourier ~status:(s_proof,s_goal)=
1004 let s_curi,s_metasenv,s_pbo,s_pty = s_proof in
1005 let s_metano,s_context,s_ty = List.find (function (m,_,_) -> m=s_goal)
1008 debug ("invoco fourier_tac sul goal "^string_of_int(s_goal)^" e contesto :\n");
1009 debug_pcontext s_context;
1011 let fhyp = String.copy "new_hyp_for_fourier" in
1013 (* here we need to negate the thesis, but to do this we need to apply the right
1014 theoreme,so let's parse our thesis *)
1016 let th_to_appl = ref _Rfourier_not_le_gt in
1018 Cic.Appl ( Cic.Const(u,boh)::args) ->
1019 (match UriManager.string_of_uri u with
1020 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> th_to_appl :=
1022 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> th_to_appl :=
1024 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> th_to_appl :=
1026 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> th_to_appl :=
1028 |_-> failwith "fourier can't be applyed")
1029 |_-> failwith "fourier can't be applyed");
1030 (* fix maybe strip_outer_cast goes here?? *)
1032 (* now let's change our thesis applying the th and put it with hp *)
1034 let proof,gl = Tacticals.then_
1035 ~start:(PrimitiveTactics.apply_tac ~term:!th_to_appl)
1036 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp)
1037 ~status:(s_proof,s_goal) in
1038 let goal = if List.length gl = 1 then List.hd gl
1039 else failwith "a new goal" in
1041 debug ("port la tesi sopra e la nego. contesto :\n");
1042 debug_pcontext s_context;
1044 (* now we have all the right environment *)
1046 let curi,metasenv,pbo,pty = proof in
1047 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
1050 (* now we want to convert hp to inequations, but first we must lift
1051 everyting to thesis level, so that a variable has the save Rel(n)
1052 in each hp ( needed by ineq1_of_term ) *)
1054 (* ? fix if None ?????*)
1055 (* fix change superlift with a real name *)
1057 let l_context = superlift context 1 in
1058 let hyps = filter_real_hyp l_context l_context in
1060 debug ("trasformo in diseq. "^ string_of_int (List.length hyps)^" ipotesi\n");
1062 let lineq =ref [] in
1064 (* transform hyps into inequations *)
1066 List.iter (fun h -> try (lineq:=(ineq1_of_term h)@(!lineq))
1071 debug ("applico fourier a "^ string_of_int (List.length !lineq)^
1074 let res=fourier_lineq (!lineq) in
1075 let tac=ref Ring.id_tac in
1077 (print_string "Tactic Fourier fails.\n";flush stdout;
1078 failwith "fourier_tac fails")
1081 match res with (*match res*)
1084 (* in lc we have the coefficient to "reduce" the system *)
1086 print_string "Fourier's method can prove the goal...\n";flush stdout;
1088 debug "I coeff di moltiplicazione rit sono: ";
1092 (fun (h,c) -> if c<>r0 then (lutil:=(h,c)::(!lutil);
1093 (* DBG *)Fourier.print_rational(c);print_string " "(* DBG *))
1095 (List.combine (!lineq) lc);
1097 print_string (" quindi lutil e' lunga "^
1098 string_of_int (List.length (!lutil))^"\n");
1100 (* on construit la combinaison linéaire des inéquation *)
1102 (match (!lutil) with (*match (!lutil) *)
1104 debug ("elem di lutil ");Fourier.print_rational c1;print_string "\n";
1106 let s=ref (h1.hstrict) in
1109 let t1 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hleft] ) in
1110 let t2 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hright]) in
1112 List.iter (fun (h,c) ->
1113 s:=(!s)||(h.hstrict);
1114 t1:=(Cic.Appl [_Rplus;!t1;Cic.Appl
1115 [_Rmult;rational_to_real c;h.hleft ] ]);
1116 t2:=(Cic.Appl [_Rplus;!t2;Cic.Appl
1117 [_Rmult;rational_to_real c;h.hright] ]))
1120 let ineq=Cic.Appl [(if (!s) then _Rlt else _Rle);!t1;!t2 ] in
1121 let tc=rational_to_real cres in
1124 (* ora ho i termini che descrivono i passi di fourier per risolvere il sistema *)
1126 debug "inizio a costruire tac1\n";
1127 Fourier.print_rational(c1);
1129 let tac1=ref ( fun ~status ->
1134 debug ("inizio t1 strict\n");
1135 let curi,metasenv,pbo,pty = proof in
1136 let metano,context,ty = List.find
1137 (function (m,_,_) -> m=goal) metasenv in
1138 debug ("th = "^ CicPp.ppterm _Rfourier_lt ^"\n");
1139 debug ("ty = "^ CicPp.ppterm ty^"\n");
1140 PrimitiveTactics.apply_tac ~term:_Rfourier_lt ~status)
1141 ~continuations:[tac_use h1;tac_zero_inf_pos
1142 (rational_to_fraction c1)]
1147 ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le)
1148 ~continuations:[tac_use h1;tac_zero_inf_pos
1149 (rational_to_fraction c1)] ~status
1155 List.iter (fun (h,c) ->
1159 tac1:=(Tacticals.thens
1160 ~start:(PrimitiveTactics.apply_tac
1161 ~term:_Rfourier_lt_lt)
1162 ~continuations:[!tac1;tac_use h;tac_zero_inf_pos
1163 (rational_to_fraction c)])
1167 Fourier.print_rational(c1);
1168 tac1:=(Tacticals.thens
1171 debug("INIZIO TAC 1 2\n");
1172 let curi,metasenv,pbo,pty = proof in
1173 let metano,context,ty = List.find (function (m,_,_) -> m=goal)
1175 debug ("th = "^ CicPp.ppterm _Rfourier_lt_le ^"\n");
1176 debug ("ty = "^ CicPp.ppterm ty^"\n");
1177 PrimitiveTactics.apply_tac ~term:_Rfourier_lt_le ~status)
1178 ~continuations:[!tac1;tac_use h;tac_zero_inf_pos
1179 (rational_to_fraction c)])
1185 tac1:=(Tacticals.thens
1186 ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_lt)
1187 ~continuations:[!tac1;tac_use h;tac_zero_inf_pos
1188 (rational_to_fraction c)])
1192 tac1:=(Tacticals.thens
1193 ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_le)
1194 ~continuations:[!tac1;tac_use h;tac_zero_inf_pos
1195 (rational_to_fraction c)])
1199 s:=(!s)||(h.hstrict)) lutil;(*end List.iter*)
1203 tac_zero_inf_false goal (rational_to_fraction cres)
1205 tac_zero_infeq_false goal (rational_to_fraction cres)
1207 tac:=(Tacticals.thens
1208 ~start:(my_cut ~term:ineq)
1209 ~continuations:[Tacticals.then_
1210 ~start:(fun ~status:(proof,goal as status) ->
1211 let curi,metasenv,pbo,pty = proof in
1212 let metano,context,ty = List.find (function (m,_,_) -> m=goal)
1214 PrimitiveTactics.change_tac ~what:ty
1215 ~with_what:(Cic.Appl [ _not; ineq]) ~status)
1216 ~continuation:(Tacticals.then_
1217 ~start:(PrimitiveTactics.apply_tac ~term:
1218 (if sres then _Rnot_lt_lt else _Rnot_le_le))
1219 ~continuation:(Tacticals.thens
1222 let r = equality_replace (Cic.Appl [_Rminus;!t2;!t1] ) tc
1225 (match r with (p,gl) ->
1226 debug("eq1 ritorna "^string_of_int(List.length gl)^"\n" ));
1228 ~continuations:[(Tacticals.thens
1231 let r = equality_replace (Cic.Appl[_Rinv;_R1]) _R1 ~status in
1232 (match r with (p,gl) ->
1233 debug("eq2 ritorna "^string_of_int(List.length gl)^"\n" ));
1236 [PrimitiveTactics.apply_tac ~term:_Rinv_R1
1237 (* CSC: Il nostro goal e' 1^-1 = 1 e non 1 = 1^-1. Quindi non c'e' bisogno
1238 di applicare sym_eqT. Perche' in Coq il goal e' al contrario? Forse i
1239 parametri della equality_replace vengono passati al contrario? Oppure la
1240 tattica usa i parametri al contrario?
1241 ~continuations:[Tacticals.then_
1243 fun ~status:(proof,goal as status) ->
1245 let curi,metasenv,pbo,pty = proof in
1246 let metano,context,ty = List.find (function (m,_,_) -> m=
1248 debug("ty = "^CicPp.ppterm ty^"\n");
1249 let r = PrimitiveTactics.apply_tac ~term:_sym_eqT
1251 debug("fine ECCOCI\n");
1253 ~continuation:(PrimitiveTactics.apply_tac ~term:_Rinv_R1)
1255 ;Tacticals.try_tactics
1256 ~tactics:[ "ring", (fun ~status ->
1257 debug("begin RING\n");
1258 let r = Ring.ring_tac ~status in
1259 debug ("end RING\n");
1261 ; "id", Ring.id_tac]
1263 (* CSC: NOW THE BUG IS HERE: tac2 DOES NOT WORK ANY MORE *)
1265 ;!tac1]);(*end tac:=*)
1266 tac:=(Tacticals.thens
1267 ~start:(PrimitiveTactics.cut_tac ~term:_False)
1268 ~continuations:[Tacticals.then_
1269 ~start:(PrimitiveTactics.intros_tac ~name:"??")
1270 ~continuation:contradiction_tac
1274 |_-> assert false)(*match (!lutil) *)
1275 |_-> assert false); (*match res*)
1276 debug ("finalmente applico tac\n");
1277 (!tac ~status:(proof,goal))
1280 let fourier_tac ~status:(proof,goal) = fourier ~status:(proof,goal);;