(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* Const (C2Ml.q_to_num z) | PEX v -> Var ("x" ^ string_of_int (C2Ml.index v)) | PEmul (p1, p2) -> let p1 = expr_to_term p1 in let p2 = expr_to_term p2 in let res = Mul (p1, p2) in res | PEadd (p1, p2) -> Add (expr_to_term p1, expr_to_term p2) | PEsub (p1, p2) -> Sub (expr_to_term p1, expr_to_term p2) | PEpow (p, n) -> Pow (expr_to_term p, C2Ml.n n) | PEopp p -> Opp (expr_to_term p) end open M let partition_expr l = let rec f i = function | [] -> ([], [], []) | (e, k) :: l -> ( let eq, ge, neq = f (i + 1) l in match k with | Mc.Equal -> ((e, i) :: eq, ge, neq) | Mc.NonStrict -> (eq, (e, Axiom_le i) :: ge, neq) | Mc.Strict -> (* e > 0 == e >= 0 /\ e <> 0 *) (eq, (e, Axiom_lt i) :: ge, (e, Axiom_lt i) :: neq) | Mc.NonEqual -> (eq, ge, (e, Axiom_eq i) :: neq) ) (* Not quite sure -- Coq interface has changed *) in f 0 l let rec sets_of_list l = match l with | [] -> [[]] | e :: l -> let s = sets_of_list l in s @ List.map (fun s0 -> e :: s0) s (* The exploration is probably not complete - for simple cases, it works... *) let real_nonlinear_prover d l = let l = List.map (fun (e, op) -> (Mc.denorm e, op)) l in try let eq, ge, neq = partition_expr l in let rec elim_const = function | [] -> [] | (x, y) :: l -> let p = poly_of_term (expr_to_term x) in if poly_isconst p then elim_const l else (p, y) :: elim_const l in let eq = elim_const eq in let peq = List.map fst eq in let pge = List.map (fun (e, psatz) -> (poly_of_term (expr_to_term e), psatz)) ge in let monoids = List.map (fun m -> ( List.fold_right (fun (p, kd) y -> let p = poly_of_term (expr_to_term p) in match kd with | Axiom_lt i -> poly_mul p y | Axiom_eq i -> poly_mul (poly_pow p 2) y | _ -> failwith "monoids") m (poly_const Q.one) , List.map snd m )) (sets_of_list neq) in let cert_ideal, cert_cone, monoid = deepen_until d (fun d -> tryfind (fun m -> let ci, cc = real_positivnullstellensatz_general false d peq pge (poly_neg (fst m)) in (ci, cc, snd m)) monoids) 0 in let proofs_ideal = List.map2 (fun q i -> Eqmul (term_of_poly q, Axiom_eq i)) cert_ideal (List.map snd eq) in let proofs_cone = List.map term_of_sos cert_cone in let proof_ne = let neq, lt = List.partition (function Axiom_eq _ -> true | _ -> false) monoid in let sq = match List.map (function Axiom_eq i -> i | _ -> failwith "error") neq with | [] -> Rational_lt Q.one | l -> Monoid l in List.fold_right (fun x y -> Product (x, y)) lt sq in let proof = end_itlist (fun s t -> Sum (s, t)) ((proof_ne :: proofs_ideal) @ proofs_cone) in S (Some proof) with | Sos_lib.TooDeep -> S None | any -> F (Printexc.to_string any) (* This is somewhat buggy, over Z, strict inequality vanish... *) let pure_sos l = let l = List.map (fun (e, o) -> (Mc.denorm e, o)) l in (* If there is no strict inequality, I should nonetheless be able to try something - over Z > is equivalent to -1 >= *) try let l = List.combine l (CList.interval 0 (List.length l - 1)) in let lt, i = try List.find (fun (x, _) -> snd x = Mc.Strict) l with Not_found -> List.hd l in let plt = poly_neg (poly_of_term (expr_to_term (fst lt))) in let n, polys = sumofsquares plt in (* n * (ci * pi^2) *) let pos = Product ( Rational_lt n , List.fold_right (fun (c, p) rst -> Sum (Product (Rational_lt c, Square (term_of_poly p)), rst)) polys (Rational_lt Q.zero) ) in let proof = Sum (Axiom_lt i, pos) in (* let s,proof' = scale_certificate proof in let cert = snd (cert_of_pos proof') in *) S (Some proof) with (* | Sos.CsdpNotFound -> F "Sos.CsdpNotFound" *) | any -> (* May be that could be refined *) S None let run_prover prover pb = match prover with | "real_nonlinear_prover", Some d -> real_nonlinear_prover d pb | "pure_sos", None -> pure_sos pb | prover, _ -> Printf.printf "unknown prover: %s\n" prover; exit 1 let main () = try let (prover, poly) = (input_value stdin : provername * micromega_polys) in let cert = run_prover prover poly in (* Printf.fprintf chan "%a -> %a" print_list_term poly output_csdp_certificate cert ; close_out chan ; *) output_value stdout (cert : csdp_certificate); flush stdout; Marshal.to_channel chan (cert : csdp_certificate) []; flush chan; exit 0 with any -> Printf.fprintf chan "error %s" (Printexc.to_string any); exit 1 ;; let _ = main () in () (* Local Variables: *) (* coding: utf-8 *) (* End: *)