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/.
28 (* La tactique Fourier ne fonctionne de manière sûre que si les coefficients
29 des inéquations et équations sont entiers. En attendant la tactique Field.
35 let debug x = print_string ("____ "^x) ; flush stdout;;
37 let debug_pcontext x =
39 List.iter (fun y -> match y with Some(Cic.Name(a),_) -> str := !str ^ a ^ " " | _ ->()) x ;
40 debug ("contesto : "^ (!str) ^ "\n")
43 (******************************************************************************
44 Operations on linear combinations.
46 Opérations sur les combinaisons linéaires affines.
47 La partie homogène d'une combinaison linéaire est en fait une table de hash
48 qui donne le coefficient d'un terme du calcul des constructions,
49 qui est zéro si le terme n'y est pas.
55 The type for linear combinations
57 type flin = {fhom:(Cic.term , rational)Hashtbl.t;fcste:rational}
63 let flin_zero () = {fhom = Hashtbl.create 50;fcste=r0}
69 @return the rational associated with x (coefficient)
73 (Hashtbl.find f.fhom x)
79 Adds c to the coefficient of x
86 let cx = flin_coef f x in
87 Hashtbl.remove f.fhom x;
88 Hashtbl.add f.fhom x (rplus cx c);
97 let flin_add_cste f c =
99 fcste=rplus f.fcste c}
103 @return a empty flin with r1 in fcste
105 let flin_one () = flin_add_cste (flin_zero()) r1;;
110 let flin_plus f1 f2 =
111 let f3 = flin_zero() in
112 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
113 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f2.fhom;
114 flin_add_cste (flin_add_cste f3 f1.fcste) f2.fcste;
120 let flin_minus f1 f2 =
121 let f3 = flin_zero() in
122 Hashtbl.iter (fun x c -> let _=flin_add f3 x c in ()) f1.fhom;
123 Hashtbl.iter (fun x c -> let _=flin_add f3 x (rop c) in ()) f2.fhom;
124 flin_add_cste (flin_add_cste f3 f1.fcste) (rop f2.fcste);
131 let f2 = flin_zero() in
132 Hashtbl.iter (fun x c -> let _=flin_add f2 x (rmult a c) in ()) f.fhom;
133 flin_add_cste f2 (rmult a f.fcste);
137 (*****************************************************************************)
142 @return proiection on string of t
144 let rec string_of_term t =
146 Cic.Cast (t1,t2) -> string_of_term t1
147 |Cic.Const (u,boh) -> UriManager.string_of_uri u
148 |Cic.Var (u) -> UriManager.string_of_uri u
149 | _ -> "not_of_constant"
153 let string_of_constr = string_of_term
159 @raise Failure if conversion is impossible
160 @return rational proiection of t
162 let rec rational_of_term t =
163 (* fun to apply f to the first and second rational-term of l *)
164 let rat_of_binop f l =
165 let a = List.hd l and
166 b = List.hd(List.tl l) in
167 f (rational_of_term a) (rational_of_term b)
169 (* as before, but f is unary *)
170 let rat_of_unop f l =
171 f (rational_of_term (List.hd l))
174 | Cic.Cast (t1,t2) -> (rational_of_term t1)
175 | Cic.Appl (t1::next) ->
178 (match (UriManager.string_of_uri u) with
179 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
181 |"cic:/Coq/Reals/Rdefinitions/Rinv.con" ->
182 rat_of_unop rinv next
183 |"cic:/Coq/Reals/Rdefinitions/Rmult.con" ->
184 rat_of_binop rmult next
185 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con" ->
186 rat_of_binop rdiv next
187 |"cic:/Coq/Reals/Rdefinitions/Rplus.con" ->
188 rat_of_binop rplus next
189 |"cic:/Coq/Reals/Rdefinitions/Rminus.con" ->
190 rat_of_binop rminus next
191 | _ -> failwith "not a rational")
192 | _ -> failwith "not a rational")
193 | Cic.Const (u,boh) ->
194 (match (UriManager.string_of_uri u) with
195 "cic:/Coq/Reals/Rdefinitions/R1.con" -> r1
196 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> r0
197 | _ -> failwith "not a rational")
198 | _ -> failwith "not a rational"
202 let rational_of_const = rational_of_term;;
206 let rec flin_of_term t =
207 let fl_of_binop f l =
208 let a = List.hd l and
209 b = List.hd(List.tl l) in
210 f (flin_of_term a) (flin_of_term b)
214 | Cic.Cast (t1,t2) -> (flin_of_term t1)
215 | Cic.Appl (t1::next) ->
220 match (UriManager.string_of_uri u) with
221 "cic:/Coq/Reals/Rdefinitions/Ropp.con" ->
222 flin_emult (rop r1) (flin_of_term (List.hd next))
223 |"cic:/Coq/Reals/Rdefinitions/Rplus.con"->
224 fl_of_binop flin_plus next
225 |"cic:/Coq/Reals/Rdefinitions/Rminus.con"->
226 fl_of_binop flin_minus next
227 |"cic:/Coq/Reals/Rdefinitions/Rmult.con"->
229 let arg1 = (List.hd next) and
230 arg2 = (List.hd(List.tl next))
234 let a = rational_of_term arg1 in
237 let b = (rational_of_term arg2) in
238 (flin_add_cste (flin_zero()) (rmult a b))
241 _ -> (flin_add (flin_zero()) arg2 a)
244 _-> (flin_add (flin_zero()) arg1 (rational_of_term arg2 ))
246 |"cic:/Coq/Reals/Rdefinitions/Rinv.con"->
247 let a=(rational_of_term (List.hd next)) in
248 flin_add_cste (flin_zero()) (rinv a)
249 |"cic:/Coq/Reals/Rdefinitions/Rdiv.con"->
251 let b=(rational_of_term (List.hd(List.tl next))) in
254 let a = (rational_of_term (List.hd next)) in
255 (flin_add_cste (flin_zero()) (rdiv a b))
258 _-> (flin_add (flin_zero()) (List.hd next) (rinv b))
264 | Cic.Const (u,boh) ->
266 match (UriManager.string_of_uri u) with
267 "cic:/Coq/Reals/Rdefinitions/R1.con" -> flin_one ()
268 |"cic:/Coq/Reals/Rdefinitions/R0.con" -> flin_zero ()
272 with _ -> flin_add (flin_zero()) t r1
276 let flin_of_constr = flin_of_term;;
280 Translates a flin to (c,x) list
282 @return something like (c1,x1)::(c2,x2)::...::(cn,xn)
284 let flin_to_alist f =
286 Hashtbl.iter (fun x c -> res:=(c,x)::(!res)) f;
290 (* Représentation des hypothèses qui sont des inéquations ou des équations.
294 The structure for ineq
296 type hineq={hname:Cic.term; (* le nom de l'hypothèse *)
297 htype:string; (* Rlt, Rgt, Rle, Rge, eqTLR ou eqTRL *)
304 (* Transforme une hypothese h:t en inéquation flin<0 ou flin<=0
307 let ineq1_of_term (h,t) =
308 match t with (* match t *)
309 Cic.Appl (t1::next) ->
310 let arg1= List.hd next in
311 let arg2= List.hd(List.tl next) in
312 (match t1 with (* match t1 *)
314 (match UriManager.string_of_uri u with (* match u *)
315 "cic:/Coq/Reals/Rdefinitions/Rlt.con" ->
320 hflin= flin_minus (flin_of_term arg1)
323 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" ->
328 hflin= flin_minus (flin_of_term arg2)
331 |"cic:/Coq/Reals/Rdefinitions/Rle.con" ->
336 hflin= flin_minus (flin_of_term arg1)
339 |"cic:/Coq/Reals/Rdefinitions/Rge.con" ->
344 hflin= flin_minus (flin_of_term arg2)
347 |_->assert false)(* match u *)
348 | Cic.MutInd (u,i,o) ->
349 (match UriManager.string_of_uri u with
350 "cic:/Coq/Init/Logic_Type/eqT.con" ->
353 let arg2= List.hd(List.tl (List.tl next)) in
356 (match UriManager.string_of_uri u with
357 "cic:/Coq/Reals/Rdefinitions/R.con"->
362 hflin= flin_minus (flin_of_term arg1)
369 hflin= flin_minus (flin_of_term arg2)
375 |_-> assert false)(* match t1 *)
376 |_-> assert false (* match t *)
379 let ineq1_of_constr = ineq1_of_term;;
382 (* Applique la méthode de Fourier à une liste d'hypothèses (type hineq)
388 | a::next -> Fourier.print_rational a ; print_string " " ; print_rl next
391 let rec print_sys l =
394 | (a,b)::next -> (print_rl a;
395 print_string (if b=true then "strict\n"else"\n");
400 Hashtbl.iter (fun x y -> print_string ("("^"-"^","^"-"^")")) h
403 let fourier_lineq lineq1 =
405 let hvar=Hashtbl.create 50 in (* la table des variables des inéquations *)
407 Hashtbl.iter (fun x c ->
408 try (Hashtbl.find hvar x;())
409 with _-> nvar:=(!nvar)+1;
410 Hashtbl.add hvar x (!nvar))
414 debug("Il numero di incognite e' "^string_of_int (!nvar+1)^"\n");
415 let sys= List.map (fun h->
416 let v=Array.create ((!nvar)+1) r0 in
417 Hashtbl.iter (fun x c -> v.(Hashtbl.find hvar x)<-c)
419 ((Array.to_list v)@[rop h.hflin.fcste],h.hstrict))
421 debug ("chiamo unsolvable sul sistema di "^ string_of_int (List.length sys) ^"\n");
426 (******************************************************************************
427 Construction de la preuve en cas de succès de la méthode de Fourier,
428 i.e. on obtient une contradiction.
431 let _R0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R0.con") 0 ;;
432 let _R1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/R1.con") 0 ;;
433 let _Rinv = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rinv.con") 0 ;;
434 let _Rle_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_mult_inv_pos.con") 0 ;;
435 let _Rle_not_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_not_lt.con") 0 ;;
436 let _Rle_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_1.con") 0 ;;
437 let _Rle_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_pos_plus1.con") 0 ;;
438 let _Rle_zero_zero = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rle_zero_zero.con") 0 ;;
439 let _Rlt_mult_inv_pos = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/_Rlt_mult_inv_pos.con") 0 ;;
440 let _Rlt_not_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_not_le.con") 0 ;;
441 let _Rlt_zero_1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_1.con") 0 ;;
442 let _Rlt_zero_pos_plus1 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rlt_zero_pos_plus1.con") 0 ;;
443 let _Rmult = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rmult.con") 0 ;;
444 let _Rminus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rminus.con") 0 ;;
446 let _Rnot_lt0 = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt0.con") 0 ;;
447 let _Ropp = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Ropp.con") 0 ;;
448 let _Rplus = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rplus.con") 0 ;;
449 let _Rfourier_not_ge_lt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_ge_lt.con") 0 ;;
450 let _Rfourier_not_gt_le = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_gt_le.con") 0 ;;
451 let _Rfourier_not_le_gt = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_le_gt.con") 0 ;;
452 let _Rfourier_not_lt_ge = Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_not_lt_ge.con") 0 ;;
453 let _Rfourier_gt_to_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_gt_to_lt.con") 0 ;;
455 let _Rfourier_ge_to_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_ge_to_le.con") 0 ;;
456 let _Rfourier_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_lt.con") 0 ;;
457 let _Rfourier_lt_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt_le.con") 0 ;;
458 let _Rfourier_le_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_lt.con") 0 ;;
459 let _Rfourier_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le_le.con") 0 ;;
461 let _Rfourier_eqLR_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqLR_to_le.con") 0 ;;
463 let _Rfourier_eqRL_to_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_eqRL_to_le.con") 0 ;;
464 let _Rlt = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rlt.con") 0 ;;
465 let _Rle = Cic.Const (UriManager.uri_of_string "cic:/Coq/Reals/Rdefinitions/Rle.con") 0 ;;
466 let _not = Cic.Const (UriManager.uri_of_string "cic:/Coq/Init/Logic/not.con") 0;;
468 let _sym_eqT = Cic.Const(UriManager.uri_of_string "/Coq/Init/Logic_Type/Equality_is_a_congruence/sym_eqT.con") 0 ;;
470 let _Rfourier_lt=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_lt.con") 0 ;;
471 let _Rfourier_le=Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rfourier_le.con") 0 ;;
473 let _False = Cic.MutConstruct(UriManager.uri_of_string "cic:/Coq/Init/Datatypes/bool.ind") 0 1 0 ;;
475 let _Rinv_R1 = Cic.Const(UriManager.uri_of_string "cic:/Coq/Reals/Rbase/Rinv_R1.con" ) 0;;
478 let _Rnot_lt_lt =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_lt_lt.con") 0 ;;
479 let _Rnot_le_le =Cic.Const (UriManager.uri_of_string "cic:/Coq/fourier/Fourier_util/Rnot_le_le.con") 0 ;;
486 let is_int x = (x.den)=1
489 (* fraction = couple (num,den) *)
490 let rec rational_to_fraction x= (x.num,x.den)
493 (* traduction -3 -> (Ropp (Rplus R1 (Rplus R1 R1)))
496 let rec int_to_real_aux n =
498 0 -> _R0 (* o forse R0 + R0 ????? *)
499 | _ -> Cic.Appl [ _Rplus ; _R1 ; int_to_real_aux (n-1) ]
504 let x = int_to_real_aux (abs n) in
506 Cic.Appl [ _Ropp ; x ]
512 (* -1/2 -> (Rmult (Ropp R1) (Rinv (Rplus R1 R1)))
515 let rational_to_real x =
516 let (n,d)=rational_to_fraction x in
517 Cic.Appl [ _Rmult ; int_to_real n ; Cic.Appl [ _Rinv ; int_to_real d ] ]
520 (* preuve que 0<n*1/d
523 let tac_zero_inf_pos gl (n,d) =
524 (*let cste = pf_parse_constr gl in*)
525 let tacn=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
526 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
528 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacn); done;
530 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
531 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_mult_inv_pos) ~continuations:[!tacn;!tacd])
537 (* preuve que 0<=n*1/d
540 let tac_zero_infeq_pos gl (n,d) =
541 (*let cste = pf_parse_constr gl in*)
542 let tacn = ref (if n=0 then
543 (PrimitiveTactics.apply_tac ~term:_Rle_zero_zero )
545 (PrimitiveTactics.apply_tac ~term:_Rle_zero_1 ))
547 let tacd=ref (PrimitiveTactics.apply_tac ~term:_Rlt_zero_1 ) in
549 tacn:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_zero_pos_plus1) ~continuation:!tacn); done;
551 tacd:=(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_zero_pos_plus1) ~continuation:!tacd); done;
552 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rle_mult_inv_pos) ~continuations:[!tacn;!tacd])
557 (* preuve que 0<(-n)*(1/d) => False
560 let tac_zero_inf_false gl (n,d) =
561 if n=0 then (PrimitiveTactics.apply_tac ~term:_Rnot_lt0)
563 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rle_not_lt)
564 ~continuation:(tac_zero_infeq_pos gl (-n,d)))
567 (* preuve que 0<=(-n)*(1/d) => False
570 let tac_zero_infeq_false gl (n,d) =
571 (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rlt_not_le)
572 ~continuation:(tac_zero_inf_pos gl (-n,d)))
576 (* *********** ********** ******** ??????????????? *********** **************)
578 let mkMeta (proof,goal) =
579 let curi,metasenv,pbo,pty = proof in
580 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
581 Cic.Meta (ProofEngineHelpers.new_meta proof)
582 (ProofEngineHelpers.identity_relocation_list_for_metavariable context)
585 let apply_type_tac ~cast:t ~applist:al ~status:(proof,goal) =
586 let new_m = mkMeta (proof,goal) in
587 PrimitiveTactics.apply_tac ~term:(Cic.Appl ((Cic.Cast (new_m,t))::al)) ~status:(proof,goal)
594 let my_cut ~term:c ~status:(proof,goal)=
595 let curi,metasenv,pbo,pty = proof in
596 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
597 apply_type_tac ~cast:(Cic.Prod(Cic.Name "Anonymous",c,ty)) ~applist:[mkMeta(proof,goal)] ~status:(proof,goal)
601 let exact = PrimitiveTactics.exact_tac;;
603 let tac_use h = match h.htype with
604 "Rlt" -> exact ~term:h.hname
605 |"Rle" -> exact ~term:h.hname
606 |"Rgt" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_gt_to_lt)
607 ~continuation:(exact ~term:h.hname))
608 |"Rge" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_ge_to_le)
609 ~continuation:(exact ~term:h.hname))
610 |"eqTLR" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqLR_to_le)
611 ~continuation:(exact ~term:h.hname))
612 |"eqTRL" -> (Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_eqRL_to_le)
613 ~continuation:(exact ~term:h.hname))
621 Cic.Appl ( Cic.Const(u,boh)::next) ->
622 (match (UriManager.string_of_uri u) with
623 "cic:/Coq/Reals/Rdefinitions/Rlt.con" -> true
624 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" -> true
625 |"cic:/Coq/Reals/Rdefinitions/Rle.con" -> true
626 |"cic:/Coq/Reals/Rdefinitions/Rge.con" -> true
627 |"cic:/Coq/Init/Logic_Type/eqT.con" ->
628 (match (List.hd next) with
629 Cic.Const (uri,_) when
630 UriManager.string_of_uri uri =
631 "cic:/Coq/Reals/Rdefinitions/R.con" -> true
637 let list_of_sign s = List.map (fun (x,_,z)->(x,z)) s;;
640 Cic.Appl(Array.to_list a)
643 (* Résolution d'inéquations linéaires dans R *)
644 let rec strip_outer_cast c = match c with
645 | Cic.Cast (c,_) -> strip_outer_cast c
649 let find_in_context id context =
650 let rec find_in_context_aux c n =
652 [] -> failwith (id^" not found in context")
653 | a::next -> (match a with
654 Some (Cic.Name(name),_) when name = id -> n
655 (*? magari al posto di _ qualcosaltro?*)
656 | _ -> find_in_context_aux next (n+1))
658 find_in_context_aux context 1
661 (* mi sembra quadratico *)
662 let rec filter_real_hyp context cont =
665 | Some(Cic.Name(h),Cic.Decl(t))::next -> (
666 let n = find_in_context h cont in
667 [(Cic.Rel(n),t)] @ filter_real_hyp next cont)
668 | a::next -> debug(" no\n"); filter_real_hyp next cont
671 (* lifts everithing at the conclusion level *)
672 let rec superlift c n=
675 | Some(name,Cic.Decl(a))::next -> [Some(name,Cic.Decl(CicSubstitution.lift n a))] @ superlift next (n+1)
676 | Some(name,Cic.Def(a))::next -> [Some(name,Cic.Def(CicSubstitution.lift n a))] @ superlift next (n+1)
677 | _::next -> superlift next (n+1) (*?? ??*)
681 (* fix !!!!!!!!!! this may not work *)
682 let equality_replace a b =
683 let _eqT_ind = Cic.Const( UriManager.uri_of_string "cic:/Coq/Init/Logic_Type/eqT_ind.con" ) 0 in
684 PrimitiveTactics.apply_tac ~term:(Cic.Appl [_eqT_ind;a;b])
687 let tcl_fail a ~status:(proof,goal) =
689 1 -> raise (ProofEngineTypes.Fail "fail-tactical")
694 let assumption_tac ~status:(proof,goal)=
695 let curi,metasenv,pbo,pty = proof in
696 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
697 let num = ref (-1) in
698 let tac_list = List.map
699 ( fun x -> num := !num + 1;
701 Some(Cic.Name(nm),t) -> (nm,exact ~term:(Cic.Rel(!num)))
702 | _ -> ("fake",tcl_fail 1)
706 Tacticals.try_tactics ~tactics:tac_list ~status:(proof,goal)
709 (* !!!!! fix !!!!!!!!!! *)
710 let contradiction_tac ~status:(proof,goal)=
712 ~start:(PrimitiveTactics.intros_tac ~name:"bo?" )
713 ~continuation:(Tacticals.then_
714 ~start:(Ring.elim_type_tac ~term:_False)
715 ~continuation:(assumption_tac))
719 (* ********************* TATTICA ******************************** *)
721 let rec fourier ~status:(proof,goal)=
722 let curi,metasenv,pbo,pty = proof in
723 let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in
725 debug ("invoco fourier_tac sul goal "^string_of_int(goal)^" e contesto :\n");
726 debug_pcontext context;
728 (* il goal di prima dovrebbe essere ty
730 let goal = strip_outer_cast (pf_concl gl) in *)
732 let fhyp = String.copy "new_hyp_for_fourier" in
733 (* si le but est une inéquation, on introduit son contraire,
734 et le but à prouver devient False *)
738 Cic.Appl ( Cic.Const(u,boh)::args) ->
739 (match UriManager.string_of_uri u with
740 "cic:/Coq/Reals/Rdefinitions/Rlt.con" ->
742 ~start:(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_not_ge_lt)
743 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp))
744 ~continuation:fourier)
745 |"cic:/Coq/Reals/Rdefinitions/Rle.con" ->
747 ~start:(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_not_gt_le)
748 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp))
749 ~continuation:fourier)
750 |"cic:/Coq/Reals/Rdefinitions/Rgt.con" ->
752 ~start:(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_not_le_gt)
753 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp))
754 ~continuation:fourier)
755 |"cic:/Coq/Reals/Rdefinitions/Rge.con" ->
757 ~start:(Tacticals.then_ ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_not_lt_ge)
758 ~continuation:(PrimitiveTactics.intros_tac ~name:fhyp))
759 ~continuation:fourier)
762 in tac (proof,goal) )
767 (* ? fix if None ?????*)
768 let new_context = superlift context 1 in
769 let hyps = filter_real_hyp new_context new_context in
770 debug ("trasformo in diseq. "^ string_of_int (List.length hyps)^" ipotesi\n");
772 List.iter (fun h -> try (lineq:=(ineq1_of_term h)@(!lineq))
777 (* lineq = les inéquations découlant des hypothèses *)
779 debug ("applico fourier a "^ string_of_int (List.length !lineq)^" disequazioni\n");
781 let res=fourier_lineq (!lineq) in
782 let tac=ref Ring.id_tac in
783 if res=[] then (print_string "Tactic Fourier fails.\n";flush stdout)
784 (* l'algorithme de Fourier a réussi: on va en tirer une preuve Coq *)
787 match res with (*match res*)
789 (* lc=coefficients multiplicateurs des inéquations
790 qui donnent 0<cres ou 0<=cres selon sres *)
793 print_string "Fourier's method can prove the goal...\n";flush stdout;
797 debug "I coeff di moltiplicazione rit sono: ";
799 (fun (h,c) -> if c<>r0 then (lutil:=(h,c)::(!lutil);
800 Fourier.print_rational(c);print_string " ")
802 (List.combine (!lineq) lc);
803 print_string (" quindi lutil e' lunga "^string_of_int (List.length (!lutil))^"\n");
804 (* on construit la combinaison linéaire des inéquation *)
807 (match (!lutil) with (*match (!lutil) *)
809 debug ("elem di lutil ");Fourier.print_rational c1;print_string "\n";
810 let s=ref (h1.hstrict) in
811 (* let t1=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hleft|]) in
812 let t2=ref (mkAppL [|parse "Rmult";parse (rational_to_real c1);h1.hright|]) in*)
813 let t1 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hleft] ) in
814 let t2 = ref (Cic.Appl [_Rmult;rational_to_real c1;h1.hright]) in
816 List.iter (fun (h,c) ->
817 s:=(!s)||(h.hstrict);
818 t1:=(Cic.Appl [_Rplus;!t1;Cic.Appl [_Rmult;rational_to_real c;h.hleft ] ]);
819 t2:=(Cic.Appl [_Rplus;!t2;Cic.Appl [_Rmult;rational_to_real c;h.hright] ]))
822 let ineq=Cic.Appl [(if (!s) then _Rlt else _Rle);!t1;!t2 ] in
823 let tc=rational_to_real cres in
827 debug "inizio a costruire tac1\n";
828 let tac1=ref ( if h1.hstrict then
829 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_lt)
830 ~continuations:[tac_use h1;tac_zero_inf_pos goal
831 (rational_to_fraction c1)])
833 (Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le)
834 ~continuations:[tac_use h1;tac_zero_inf_pos goal
835 (rational_to_fraction c1)]))
839 List.iter (fun (h,c) ->
842 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac
843 ~term:_Rfourier_lt_lt)
844 ~continuations:[!tac1;tac_use h;
845 tac_zero_inf_pos goal
846 (rational_to_fraction c)])
848 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac
849 ~term:_Rfourier_lt_le)
850 ~continuations:[!tac1;tac_use h;
851 tac_zero_inf_pos goal
852 (rational_to_fraction c)])
856 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_lt)
857 ~continuations:[!tac1;tac_use h;
858 tac_zero_inf_pos goal
859 (rational_to_fraction c)])
861 tac1:=(Tacticals.thens ~start:(PrimitiveTactics.apply_tac ~term:_Rfourier_le_le)
862 ~continuations:[!tac1;tac_use h;
863 tac_zero_inf_pos goal
864 (rational_to_fraction c)])));
865 s:=(!s)||(h.hstrict))
866 lutil;(*end List.iter*)
868 let tac2= if sres then
869 tac_zero_inf_false goal (rational_to_fraction cres)
871 tac_zero_infeq_false goal (rational_to_fraction cres)
873 tac:=(Tacticals.thens ~start:(my_cut ~term:ineq)
874 ~continuations:[Tacticals.then_ (* ?????????????????????????????? *)
875 ~start:(PrimitiveTactics.change_tac ~what:ty ~with_what:(Cic.Appl [ _not; ineq] ))
876 ~continuation:(Tacticals.then_
877 ~start:(PrimitiveTactics.apply_tac
878 ~term:(if sres then _Rnot_lt_lt else _Rnot_le_le))
879 ~continuation:(Tacticals.thens
880 ~start:(equality_replace (Cic.Appl [_Rminus;!t2;!t1] ) tc)
881 ~continuations:[tac2;(Tacticals.thens
882 ~start:(equality_replace (Cic.Appl[_Rinv;_R1]) _R1)
884 (* en attendant Field, ça peut aider Ring de remplacer 1/1 par 1 ... *)
885 [Tacticals.try_tactics
886 (* ???????????????????????????? *)
887 ~tactics:[ "ring", Ring.ring_tac ; "id", Ring.id_tac]
890 ~start:(PrimitiveTactics.apply_tac ~term:_sym_eqT)
891 ~continuation:(PrimitiveTactics.apply_tac ~term:_Rinv_R1)
895 ] (* end continuations before comment *)
900 tac:=(Tacticals.thens ~start:(PrimitiveTactics.cut_tac ~term:_False)
901 ~continuations:[Tacticals.then_
902 (* ???????????????????????????????
904 ~start:(PrimitiveTactics.intros_tac ~name:(String.copy "??"))
905 (* ????????????????????????????? *)
907 ~continuation:contradiction_tac;!tac])
910 |_-> assert false)(*match (!lutil) *)
911 |_-> assert false); (*match res*)
913 debug ("finalmente applico t1\n");
914 (!tac ~status:(proof,goal))
918 let fourier_tac ~status:(proof,goal) = fourier ~status:(proof,goal);;