1
(************************************************************************)
2
(* v * The Coq Proof Assistant / The Coq Development Team *)
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
4
(* \VV/ **************************************************************)
5
(* // * This file is distributed under the terms of the *)
6
(* * GNU Lesser General Public License Version 2.1 *)
7
(************************************************************************)
9
(* Micromega: A reflexive tactic using the Positivstellensatz *)
11
(* Frédéric Besson (Irisa/Inria) 2006-2008 *)
13
(************************************************************************)
20
module Ml2C = Mutils.CamlToCoq
21
module C2Ml = Mutils.CoqToCaml
29
let rec expr_to_term = function
30
| PEc z -> Const (C2Ml.q_to_num z)
31
| PEX v -> Var ("x"^(string_of_int (C2Ml.index v)))
33
let p1 = expr_to_term p1 in
34
let p2 = expr_to_term p2 in
35
let res = Mul(p1,p2) in res
37
| PEadd(p1,p2) -> Add(expr_to_term p1, expr_to_term p2)
38
| PEsub(p1,p2) -> Sub(expr_to_term p1, expr_to_term p2)
39
| PEpow(p,n) -> Pow(expr_to_term p , C2Ml.n n)
40
| PEopp p -> Opp (expr_to_term p)
45
(* let term_to_expr e =
46
let e' = term_to_expr e in
48
then Printf.printf "term_to_expr : %s - %s\n"
49
(string_of_poly (poly_of_term e))
50
(string_of_poly (poly_of_term (expr_to_term e')));
62
let rec canonical_sum_to_string = function s -> failwith "not implemented"
64
let print_canonical_sum m = Format.print_string (canonical_sum_to_string m)
66
let print_list_term l =
67
print_string "print_list_term\n";
68
List.iter (fun (Mc.Pair(e,k)) -> Printf.printf "q: %s %s ;"
69
(string_of_poly (poly_of_term (expr_to_term e)))
73
| Mc.NonStrict -> ">= "
74
| _ -> failwith "not_implemented")) l ;
78
let partition_expr l =
79
let rec f i = function
82
let (eq,ge,neq) = f (i+1) l in
84
| Mc.Equal -> ((e,i)::eq,ge,neq)
85
| Mc.NonStrict -> (eq,(e,Axiom_le i)::ge,neq)
86
| Mc.Strict -> (* e > 0 == e >= 0 /\ e <> 0 *)
87
(eq, (e,Axiom_lt i)::ge,(e,Axiom_lt i)::neq)
88
| Mc.NonEqual -> (eq,ge,(e,Axiom_eq i)::neq)
89
(* Not quite sure -- Coq interface has changed *)
93
let rec sets_of_list l =
96
| e::l -> let s = sets_of_list l in
97
s@(List.map (fun s0 -> e::s0) s)
99
(* The exploration is probably not complete - for simple cases, it works... *)
100
let real_nonlinear_prover d l =
102
let (eq,ge,neq) = partition_expr l in
104
let rec elim_const = function
106
| (x,y)::l -> let p = poly_of_term (expr_to_term x) in
109
else (p,y)::(elim_const l) in
111
let eq = elim_const eq in
112
let peq = List.map fst eq in
115
(fun (e,psatz) -> poly_of_term (expr_to_term e),psatz) ge in
117
let monoids = List.map (fun m -> (List.fold_right (fun (p,kd) y ->
118
let p = poly_of_term (expr_to_term p) in
120
| Axiom_lt i -> poly_mul p y
121
| Axiom_eq i -> poly_mul (poly_pow p 2) y
122
| _ -> failwith "monoids") m (poly_const (Int 1)) , map snd m))
123
(sets_of_list neq) in
125
let (cert_ideal, cert_cone,monoid) = deepen_until d (fun d ->
126
list_try_find (fun m -> let (ci,cc) =
127
real_positivnullstellensatz_general false d peq pge (poly_neg (fst m) ) in
128
(ci,cc,snd m)) monoids) 0 in
130
let proofs_ideal = map2 (fun q i -> Eqmul(term_of_poly q,Axiom_eq i))
131
cert_ideal (List.map snd eq) in
133
let proofs_cone = map term_of_sos cert_cone in
136
let (neq , lt) = List.partition
137
(function Axiom_eq _ -> true | _ -> false ) monoid in
139
(List.map (function Axiom_eq i -> i | _ -> failwith "error") neq)
141
| [] -> Rational_lt (Int 1)
143
List.fold_right (fun x y -> Product(x,y)) lt sq in
145
let proof = list_fold_right_elements
146
(fun s t -> Sum(s,t)) (proof_ne :: proofs_ideal @ proofs_cone) in
149
| Sos.TooDeep -> None
152
(* This is somewhat buggy, over Z, strict inequality vanish... *)
154
(* If there is no strict inequality,
155
I should nonetheless be able to try something - over Z > is equivalent to -1 >= *)
157
let l = List.combine l (interval 0 (length l -1)) in
158
let (lt,i) = try (List.find (fun (x,_) -> snd' x = Mc.Strict) l)
159
with Not_found -> List.hd l in
160
let plt = poly_neg (poly_of_term (expr_to_term (fst' lt))) in
161
let (n,polys) = sumofsquares plt in (* n * (ci * pi^2) *)
162
let pos = Product (Rational_lt n,
163
List.fold_right (fun (c,p) rst -> Sum (Product (Rational_lt c, Square
164
(term_of_poly p)), rst))
165
polys (Rational_lt (Int 0))) in
166
let proof = Sum(Axiom_lt i, pos) in
167
(* let s,proof' = scale_certificate proof in
168
let cert = snd (cert_of_pos proof') in *)
171
| Not_found -> (* This is no strict inequality *) None
175
type micromega_polys = (Micromega.q Mc.pExpr, Mc.op1) Micromega.prod list
176
type csdp_certificate = Sos.positivstellensatz option
177
type provername = string * int option
180
if Array.length Sys.argv <> 3 then
181
(Printf.printf "Usage: csdpcert inputfile outputfile\n"; exit 1);
182
let input_file = Sys.argv.(1) in
183
let output_file = Sys.argv.(2) in
184
let inch = open_in input_file in
185
let (prover,poly) = (input_value inch : provername * micromega_polys) in
189
| "real_nonlinear_prover", Some d -> real_nonlinear_prover d poly
190
| "pure_sos", None -> pure_sos poly
191
| prover, _ -> (Printf.printf "unknown prover: %s\n" prover; exit 1) in
192
let outch = open_out output_file in
193
output_value outch (cert:csdp_certificate);
197
let _ = main () in ()