mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 03:05:31 -05:00
feat: reinstate LRA theory and terms
This commit is contained in:
parent
e66a27229b
commit
f0041f9dae
14 changed files with 207 additions and 213 deletions
|
|
@ -1,8 +1,6 @@
|
||||||
open Types_
|
|
||||||
open Sidekick_core
|
open Sidekick_core
|
||||||
module T = Term
|
module T = Term
|
||||||
|
|
||||||
type ty = Term.t
|
|
||||||
type term = Term.t
|
type term = Term.t
|
||||||
|
|
||||||
type 'a view = 'a Sidekick_core.Bool_view.t =
|
type 'a view = 'a Sidekick_core.Bool_view.t =
|
||||||
|
|
@ -42,8 +40,6 @@ let ops : Const.ops =
|
||||||
|
|
||||||
(* ### view *)
|
(* ### view *)
|
||||||
|
|
||||||
exception Not_a_th_term
|
|
||||||
|
|
||||||
let view (t : T.t) : T.t view =
|
let view (t : T.t) : T.t view =
|
||||||
let hd, args = T.unfold_app t in
|
let hd, args = T.unfold_app t in
|
||||||
match T.view hd, args with
|
match T.view hd, args with
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ let ops : Const.ops =
|
||||||
end)
|
end)
|
||||||
|
|
||||||
let real tst = Ty.real tst
|
let real tst = Ty.real tst
|
||||||
|
let has_ty_real t = Ty.is_real (T.ty t)
|
||||||
|
|
||||||
let const tst q : term =
|
let const tst q : term =
|
||||||
Term.const tst (Const.make (Const q) ops ~ty:(real tst))
|
Term.const tst (Const.make (Const q) ops ~ty:(real tst))
|
||||||
|
|
@ -56,8 +57,17 @@ let op tst op t1 t2 : term =
|
||||||
let view (t : term) : _ View.t =
|
let view (t : term) : _ View.t =
|
||||||
let f, args = Term.unfold_app t in
|
let f, args = Term.unfold_app t in
|
||||||
match T.view f, args with
|
match T.view f, args with
|
||||||
|
| T.E_const { Const.c_view = T.C_eq; _ }, [ _; a; b ] when has_ty_real a ->
|
||||||
|
View.LRA_pred (Pred.Eq, a, b)
|
||||||
| T.E_const { Const.c_view = Const q; _ }, [] -> View.LRA_const q
|
| T.E_const { Const.c_view = Const q; _ }, [] -> View.LRA_const q
|
||||||
| T.E_const { Const.c_view = Pred p; _ }, [ a; b ] -> View.LRA_pred (p, a, b)
|
| T.E_const { Const.c_view = Pred p; _ }, [ a; b ] -> View.LRA_pred (p, a, b)
|
||||||
| T.E_const { Const.c_view = Op op; _ }, [ a; b ] -> View.LRA_op (op, a, b)
|
| T.E_const { Const.c_view = Op op; _ }, [ a; b ] -> View.LRA_op (op, a, b)
|
||||||
| T.E_const { Const.c_view = Mult_by q; _ }, [ a ] -> View.LRA_mult (q, a)
|
| T.E_const { Const.c_view = Mult_by q; _ }, [ a ] -> View.LRA_mult (q, a)
|
||||||
| _ -> View.LRA_other t
|
| _ -> View.LRA_other t
|
||||||
|
|
||||||
|
let term_of_view store = function
|
||||||
|
| View.LRA_const q -> const store q
|
||||||
|
| View.LRA_mult (n, t) -> mult_by store n t
|
||||||
|
| View.LRA_pred (p, a, b) -> pred store p a b
|
||||||
|
| View.LRA_op (o, a, b) -> op store o a b
|
||||||
|
| View.LRA_other x -> x
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ type term = Term.t
|
||||||
type ty = Term.t
|
type ty = Term.t
|
||||||
|
|
||||||
val real : Term.store -> ty
|
val real : Term.store -> ty
|
||||||
|
val has_ty_real : term -> bool
|
||||||
val pred : Term.store -> Pred.t -> term -> term -> term
|
val pred : Term.store -> Pred.t -> term -> term -> term
|
||||||
val mult_by : Term.store -> Q.t -> term -> term
|
val mult_by : Term.store -> Q.t -> term -> term
|
||||||
val op : Term.store -> Op.t -> term -> term -> term
|
val op : Term.store -> Op.t -> term -> term -> term
|
||||||
|
|
@ -14,3 +15,5 @@ val const : Term.store -> Q.t -> term
|
||||||
|
|
||||||
val view : term -> term View.t
|
val view : term -> term View.t
|
||||||
(** View as LRA *)
|
(** View as LRA *)
|
||||||
|
|
||||||
|
val term_of_view : Term.store -> term View.t -> term
|
||||||
|
|
|
||||||
|
|
@ -33,35 +33,11 @@ module Config = Config
|
||||||
module LRA_term = LRA_term
|
module LRA_term = LRA_term
|
||||||
module Th_data = Th_data
|
module Th_data = Th_data
|
||||||
module Th_bool = Th_bool
|
module Th_bool = Th_bool
|
||||||
(* FIXME
|
module Th_lra = Th_lra
|
||||||
module Th_lra = Th_lra
|
|
||||||
*)
|
|
||||||
|
|
||||||
let k_th_bool_config = Th_bool.k_config
|
let k_th_bool_config = Th_bool.k_config
|
||||||
let th_bool = Th_bool.theory
|
let th_bool = Th_bool.theory
|
||||||
let th_bool_dyn : Solver.theory = Th_bool.theory_dyn
|
let th_bool_dyn : Solver.theory = Th_bool.theory_dyn
|
||||||
let th_bool_static : Solver.theory = Th_bool.theory_static
|
let th_bool_static : Solver.theory = Th_bool.theory_static
|
||||||
let th_data : Solver.theory = Th_data.theory
|
let th_data : Solver.theory = Th_data.theory
|
||||||
|
let th_lra : Solver.theory = Th_lra.theory
|
||||||
(* FIXME
|
|
||||||
let th_lra : Solver.theory = Th_lra.theory
|
|
||||||
*)
|
|
||||||
|
|
||||||
(* TODO
|
|
||||||
|
|
||||||
module Value = Value
|
|
||||||
module Statement = Statement
|
|
||||||
module Data = Data
|
|
||||||
module Select = Select
|
|
||||||
|
|
||||||
module LRA_view = Types_.LRA_view
|
|
||||||
module LRA_pred = Base_types.LRA_pred
|
|
||||||
module LRA_op = Base_types.LRA_op
|
|
||||||
module LIA_view = Base_types.LIA_view
|
|
||||||
module LIA_pred = Base_types.LIA_pred
|
|
||||||
module LIA_op = Base_types.LIA_op
|
|
||||||
*)
|
|
||||||
|
|
||||||
(*
|
|
||||||
module Proof_quip = Proof_quip
|
|
||||||
*)
|
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,21 @@
|
||||||
(* TODO
|
(** Theory of Linear Rational Arithmetic *)
|
||||||
|
|
||||||
|
open Sidekick_core
|
||||||
|
module T = Term
|
||||||
|
module Q = Sidekick_zarith.Rational
|
||||||
|
open LRA_term
|
||||||
|
|
||||||
(** Theory of Linear Rational Arithmetic *)
|
let mk_eq = Form.eq
|
||||||
module Th_lra = Sidekick_arith_lra.Make (struct
|
let mk_bool = T.bool
|
||||||
module S = Solver
|
|
||||||
module T = Term
|
let theory : Solver.theory =
|
||||||
|
Sidekick_th_lra.theory
|
||||||
|
(module struct
|
||||||
module Z = Sidekick_zarith.Int
|
module Z = Sidekick_zarith.Int
|
||||||
module Q = Sidekick_zarith.Rational
|
module Q = Sidekick_zarith.Rational
|
||||||
|
|
||||||
type term = S.T.Term.t
|
let ty_real = LRA_term.real
|
||||||
type ty = S.T.Ty.t
|
let has_ty_real = LRA_term.has_ty_real
|
||||||
|
let view_as_lra = LRA_term.view
|
||||||
module LRA = Sidekick_arith_lra
|
let mk_lra = LRA_term.term_of_view
|
||||||
|
end : Sidekick_th_lra.ARG)
|
||||||
let mk_eq = Form.eq
|
|
||||||
|
|
||||||
let mk_lra store l =
|
|
||||||
match l with
|
|
||||||
| LRA.LRA_other x -> x
|
|
||||||
| LRA.LRA_pred (p, x, y) -> T.lra store (Pred (p, x, y))
|
|
||||||
| LRA.LRA_op (op, x, y) -> T.lra store (Op (op, x, y))
|
|
||||||
| LRA.LRA_const c -> T.lra store (Const c)
|
|
||||||
| LRA.LRA_mult (c, x) -> T.lra store (Mult (c, x))
|
|
||||||
|
|
||||||
let mk_bool = T.bool
|
|
||||||
|
|
||||||
let rec view_as_lra t =
|
|
||||||
match T.view t with
|
|
||||||
| T.LRA l ->
|
|
||||||
let module LRA = Sidekick_arith_lra in
|
|
||||||
(match l with
|
|
||||||
| Const c -> LRA.LRA_const c
|
|
||||||
| Pred (p, a, b) -> LRA.LRA_pred (p, a, b)
|
|
||||||
| Op (op, a, b) -> LRA.LRA_op (op, a, b)
|
|
||||||
| Mult (c, x) -> LRA.LRA_mult (c, x)
|
|
||||||
| To_real x -> view_as_lra x
|
|
||||||
| Var x -> LRA.LRA_other x)
|
|
||||||
| T.Eq (a, b) when Ty.equal (T.ty a) (Ty.real ()) -> LRA.LRA_pred (Eq, a, b)
|
|
||||||
| _ -> LRA.LRA_other t
|
|
||||||
|
|
||||||
let ty_lra _st = Ty.real ()
|
|
||||||
let has_ty_real t = Ty.equal (T.ty t) (Ty.real ())
|
|
||||||
let lemma_lra = Proof.lemma_lra
|
|
||||||
|
|
||||||
module Gensym = Gensym
|
|
||||||
end)
|
|
||||||
*)
|
|
||||||
|
|
|
||||||
|
|
@ -178,8 +178,7 @@ let main_smt ~config () : _ result =
|
||||||
Log.debugf 1 (fun k ->
|
Log.debugf 1 (fun k ->
|
||||||
k "(@[main.th-bool.pick@ %S@])"
|
k "(@[main.th-bool.pick@ %S@])"
|
||||||
(Sidekick_smt_solver.Theory.name th_bool));
|
(Sidekick_smt_solver.Theory.name th_bool));
|
||||||
Sidekick_smt_solver.Theory.
|
Sidekick_smt_solver.Theory.[ th_bool; Process.th_data; Process.th_lra ]
|
||||||
[ th_bool; Process.th_data (* FIXME Process.th_lra *) ]
|
|
||||||
in
|
in
|
||||||
Process.Solver.create_default ~proof ~theories tst
|
Process.Solver.create_default ~proof ~theories tst
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -338,14 +338,10 @@ let process_stmt ?gc ?restarts ?(pp_cnf = false) ?proof_file ?pp_model
|
||||||
|
|
||||||
module Th_data = Sidekick_base.Th_data
|
module Th_data = Sidekick_base.Th_data
|
||||||
module Th_bool = Sidekick_base.Th_bool
|
module Th_bool = Sidekick_base.Th_bool
|
||||||
(* FIXME
|
module Th_lra = Sidekick_base.Th_lra
|
||||||
module Th_lra = Sidekick_base.Th_lra
|
|
||||||
*)
|
|
||||||
|
|
||||||
let th_bool = Th_bool.theory
|
let th_bool = Th_bool.theory
|
||||||
let th_bool_dyn : Solver.theory = Th_bool.theory_dyn
|
let th_bool_dyn : Solver.theory = Th_bool.theory_dyn
|
||||||
let th_bool_static : Solver.theory = Th_bool.theory_static
|
let th_bool_static : Solver.theory = Th_bool.theory_static
|
||||||
let th_data : Solver.theory = Th_data.theory
|
let th_data : Solver.theory = Th_data.theory
|
||||||
(* FIXME
|
let th_lra : Solver.theory = Th_lra.theory
|
||||||
let th_lra : Solver.theory = Th_lra.theory
|
|
||||||
*)
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ val th_bool_dyn : Solver.theory
|
||||||
val th_bool_static : Solver.theory
|
val th_bool_static : Solver.theory
|
||||||
val th_bool : Config.t -> Solver.theory
|
val th_bool : Config.t -> Solver.theory
|
||||||
val th_data : Solver.theory
|
val th_data : Solver.theory
|
||||||
(* FIXME
|
val th_lra : Solver.theory
|
||||||
val th_lra : Solver.theory
|
|
||||||
*)
|
|
||||||
|
|
||||||
type 'a or_error = ('a, string) CCResult.t
|
type 'a or_error = ('a, string) CCResult.t
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,49 +113,62 @@ let string_as_q (s : string) : Q.t option =
|
||||||
Some x
|
Some x
|
||||||
with _ -> None
|
with _ -> None
|
||||||
|
|
||||||
(* TODO
|
let t_as_q t =
|
||||||
let t_as_q t =
|
match LRA_term.view t with
|
||||||
match Term.view t with
|
| LRA_term.View.LRA_const n -> Some n
|
||||||
| T.LRA (Const n) -> Some n
|
(*
|
||||||
| T.LIA (Const n) -> Some (Q.of_bigint n)
|
| T.LIA (Const n) -> Some (Q.of_bigint n)
|
||||||
|
*)
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
|
(* TODO
|
||||||
let t_as_z t =
|
let t_as_z t =
|
||||||
match Term.view t with
|
match Term.view t with
|
||||||
| T.LIA (Const n) -> Some n
|
| T.LIA (Const n) -> Some n
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
*)
|
||||||
|
|
||||||
let is_real = Ty.is_real
|
let is_real = Ty.is_real
|
||||||
|
|
||||||
(* convert [t] to a real term *)
|
(* convert [t] to a real term *)
|
||||||
let cast_to_real (ctx : Ctx.t) (t : T.t) : T.t =
|
let cast_to_real (ctx : Ctx.t) (t : T.t) : T.t =
|
||||||
let rec conv t =
|
let conv t =
|
||||||
match T.view t with
|
match T.view t with
|
||||||
| T.LRA _ -> t
|
| _ when Ty.is_real (T.ty t) -> t
|
||||||
| _ when Ty.equal (T.ty t) (Ty.real ()) -> t
|
(* FIXME
|
||||||
| T.LIA (Const n) -> T.lra ctx.tst (Const (Q.of_bigint n))
|
| T.LIA (Const n) -> T.lra ctx.tst (Const (Q.of_bigint n))
|
||||||
| T.LIA l ->
|
| T.LIA l ->
|
||||||
(* convert the whole structure to reals *)
|
(* convert the whole structure to reals *)
|
||||||
let l = LIA_view.to_lra conv l in
|
let l = LIA_view.to_lra conv l in
|
||||||
T.lra ctx.tst l
|
T.lra ctx.tst l
|
||||||
| T.Ite (a, b, c) -> T.ite ctx.tst a (conv b) (conv c)
|
| T.Ite (a, b, c) -> T.ite ctx.tst a (conv b) (conv c)
|
||||||
|
*)
|
||||||
| _ -> errorf_ctx ctx "cannot cast term to real@ :term %a" T.pp t
|
| _ -> errorf_ctx ctx "cannot cast term to real@ :term %a" T.pp t
|
||||||
in
|
in
|
||||||
conv t
|
conv t
|
||||||
|
|
||||||
let conv_arith_op (ctx : Ctx.t) t (op : PA.arith_op) (l : T.t list) : T.t =
|
let conv_arith_op (ctx : Ctx.t) (t : PA.term) (op : PA.arith_op) (l : T.t list)
|
||||||
|
: T.t =
|
||||||
let tst = ctx.Ctx.tst in
|
let tst = ctx.Ctx.tst in
|
||||||
|
|
||||||
let mk_pred p a b =
|
let mk_pred p a b =
|
||||||
|
LRA_term.pred tst p (cast_to_real ctx a) (cast_to_real ctx b)
|
||||||
|
(* TODO
|
||||||
if is_real a || is_real b then
|
if is_real a || is_real b then
|
||||||
T.lra tst (Pred (p, cast_to_real ctx a, cast_to_real ctx b))
|
LRA_term.pred tst p (cast_to_real ctx a) (cast_to_real ctx b)
|
||||||
else
|
else
|
||||||
|
Error.errorf "cannot handle LIA term %a" PA.pp_term t
|
||||||
T.lia tst (Pred (p, a, b))
|
T.lia tst (Pred (p, a, b))
|
||||||
|
*)
|
||||||
and mk_op o a b =
|
and mk_op o a b =
|
||||||
|
LRA_term.op tst o (cast_to_real ctx a) (cast_to_real ctx b)
|
||||||
|
(* TODO
|
||||||
if is_real a || is_real b then
|
if is_real a || is_real b then
|
||||||
T.lra tst (Op (o, cast_to_real ctx a, cast_to_real ctx b))
|
LRA_term.op tst o (cast_to_real ctx a) (cast_to_real ctx b)
|
||||||
else
|
else
|
||||||
|
Error.errorf "cannot handle LIA term %a" PA.pp_term t
|
||||||
T.lia tst (Op (o, a, b))
|
T.lia tst (Op (o, a, b))
|
||||||
|
*)
|
||||||
in
|
in
|
||||||
|
|
||||||
match op, l with
|
match op, l with
|
||||||
|
|
@ -166,6 +179,18 @@ let string_as_q (s : string) : Q.t option =
|
||||||
| PA.Add, [ a; b ] -> mk_op Plus a b
|
| PA.Add, [ a; b ] -> mk_op Plus a b
|
||||||
| PA.Add, a :: l -> List.fold_left (fun a b -> mk_op Plus a b) a l
|
| PA.Add, a :: l -> List.fold_left (fun a b -> mk_op Plus a b) a l
|
||||||
| PA.Minus, [ a ] ->
|
| PA.Minus, [ a ] ->
|
||||||
|
(match t_as_q a with
|
||||||
|
| Some q -> LRA_term.const tst (Q.neg q)
|
||||||
|
| None ->
|
||||||
|
let zero =
|
||||||
|
if is_real a then
|
||||||
|
LRA_term.const tst Q.zero
|
||||||
|
else
|
||||||
|
Error.errorf "cannot handle non-rat %a" PA.pp_term t
|
||||||
|
(* T.lia tst (Const Z.zero) *)
|
||||||
|
in
|
||||||
|
mk_op Minus zero a)
|
||||||
|
(*
|
||||||
(match t_as_q a, t_as_z a with
|
(match t_as_q a, t_as_z a with
|
||||||
| _, Some n -> T.lia tst (Const (Z.neg n))
|
| _, Some n -> T.lia tst (Const (Z.neg n))
|
||||||
| Some q, None -> T.lra tst (Const (Q.neg q))
|
| Some q, None -> T.lra tst (Const (Q.neg q))
|
||||||
|
|
@ -176,57 +201,52 @@ let string_as_q (s : string) : Q.t option =
|
||||||
else
|
else
|
||||||
T.lia tst (Const Z.zero)
|
T.lia tst (Const Z.zero)
|
||||||
in
|
in
|
||||||
|
|
||||||
mk_op Minus zero a)
|
mk_op Minus zero a)
|
||||||
|
*)
|
||||||
| PA.Minus, [ a; b ] -> mk_op Minus a b
|
| PA.Minus, [ a; b ] -> mk_op Minus a b
|
||||||
| PA.Minus, a :: l -> List.fold_left (fun a b -> mk_op Minus a b) a l
|
| PA.Minus, a :: l -> List.fold_left (fun a b -> mk_op Minus a b) a l
|
||||||
| PA.Mult, [ a; b ] when is_real a || is_real b ->
|
| PA.Mult, [ a; b ] ->
|
||||||
(match t_as_q a, t_as_q b with
|
(match t_as_q a, t_as_q b with
|
||||||
| Some a, Some b -> T.lra tst (Const (Q.mul a b))
|
| Some a, Some b -> LRA_term.const tst (Q.mul a b)
|
||||||
| Some a, _ -> T.lra tst (Mult (a, b))
|
| Some a, _ -> LRA_term.mult_by tst a b
|
||||||
| _, Some b -> T.lra tst (Mult (b, a))
|
| _, Some b -> LRA_term.mult_by tst b a
|
||||||
| None, None ->
|
| None, None ->
|
||||||
errorf_ctx ctx "cannot handle non-linear mult %a" PA.pp_term t)
|
errorf_ctx ctx "cannot handle non-linear mult %a" PA.pp_term t)
|
||||||
| PA.Mult, [ a; b ] ->
|
(* TODO
|
||||||
|
| PA.Mult, [ _a; _b ] ->
|
||||||
(match t_as_z a, t_as_z b with
|
(match t_as_z a, t_as_z b with
|
||||||
| Some a, Some b -> T.lia tst (Const (Z.mul a b))
|
| Some a, Some b -> T.lia tst (Const (Z.mul a b))
|
||||||
| Some a, _ -> T.lia tst (Mult (a, b))
|
| Some a, _ -> T.lia tst (Mult (a, b))
|
||||||
| _, Some b -> T.lia tst (Mult (b, a))
|
| _, Some b -> T.lia tst (Mult (b, a))
|
||||||
| None, None ->
|
| None, None ->
|
||||||
errorf_ctx ctx "cannot handle non-linear mult %a" PA.pp_term t)
|
errorf_ctx ctx "cannot handle non-linear mult %a" PA.pp_term t)
|
||||||
| PA.Div, [ a; b ] when is_real a || is_real b ->
|
errorf_ctx ctx "cannot handle non-linear mult %a" PA.pp_term t
|
||||||
(match t_as_q a, t_as_q b with
|
*)
|
||||||
| Some a, Some b -> T.lra tst (Const (Q.div a b))
|
|
||||||
| _, Some b -> T.lra tst (Mult (Q.inv b, a))
|
|
||||||
| _, None -> errorf_ctx ctx "cannot handle non-linear div %a" PA.pp_term t)
|
|
||||||
| PA.Div, [ a; b ] ->
|
| PA.Div, [ a; b ] ->
|
||||||
(* becomes a real *)
|
|
||||||
(match t_as_q a, t_as_q b with
|
(match t_as_q a, t_as_q b with
|
||||||
| Some a, Some b -> T.lra tst (Const (Q.div a b))
|
| Some a, Some b -> LRA_term.const tst (Q.div a b)
|
||||||
| _, Some b ->
|
| _, Some b ->
|
||||||
let a = cast_to_real ctx a in
|
let a = cast_to_real ctx a in
|
||||||
T.lra tst (Mult (Q.inv b, a))
|
LRA_term.mult_by tst (Q.inv b) a
|
||||||
| _, None -> errorf_ctx ctx "cannot handle non-linear div %a" PA.pp_term t)
|
| _, None -> errorf_ctx ctx "cannot handle non-linear div %a" PA.pp_term t)
|
||||||
| _ -> errorf_ctx ctx "cannot handle arith construct %a" PA.pp_term t
|
| _ -> errorf_ctx ctx "cannot handle arith construct %a" PA.pp_term t
|
||||||
*)
|
|
||||||
|
|
||||||
(* conversion of terms *)
|
(* conversion of terms *)
|
||||||
let rec conv_term (ctx : Ctx.t) (t : PA.term) : T.t =
|
let rec conv_term (ctx : Ctx.t) (t : PA.term) : T.t =
|
||||||
let tst = ctx.Ctx.tst in
|
let tst = ctx.Ctx.tst in
|
||||||
match t with
|
match t with
|
||||||
| PA.True -> T.true_ tst
|
| PA.True -> T.true_ tst
|
||||||
| PA.False ->
|
| PA.False -> T.false_ tst
|
||||||
T.false_ tst
|
|
||||||
(* FIXME
|
|
||||||
| PA.Const s when is_num s ->
|
| PA.Const s when is_num s ->
|
||||||
(match string_as_z s, ctx.default_num with
|
(match string_as_z s, ctx.default_num with
|
||||||
| Some n, `Int -> T.lia tst (Const n)
|
| Some n, `Real -> LRA_term.const tst (Q.of_bigint n)
|
||||||
| Some n, `Real -> T.lra tst (Const (Q.of_bigint n))
|
| Some n, `Int ->
|
||||||
|
Error.errorf "cannot handle integer constant %a yet" Z.pp_print n
|
||||||
|
(* TODO T.lia tst (Const n) *)
|
||||||
| None, _ ->
|
| None, _ ->
|
||||||
(match string_as_q s with
|
(match string_as_q s with
|
||||||
| Some n -> T.lra tst (Const n)
|
| Some n -> LRA_term.const tst n
|
||||||
| None -> errorf_ctx ctx "expected a number for %a" PA.pp_term t))
|
| None -> errorf_ctx ctx "expected a number for %a" PA.pp_term t))
|
||||||
*)
|
|
||||||
| PA.Const f | PA.App (f, []) ->
|
| PA.Const f | PA.App (f, []) ->
|
||||||
(* lookup in `let` table, then in type defs *)
|
(* lookup in `let` table, then in type defs *)
|
||||||
(match StrTbl.find ctx.Ctx.lets f with
|
(match StrTbl.find ctx.Ctx.lets f with
|
||||||
|
|
@ -276,11 +296,11 @@ let rec conv_term (ctx : Ctx.t) (t : PA.term) : T.t =
|
||||||
| PA.Eq (a, b) ->
|
| PA.Eq (a, b) ->
|
||||||
let a = conv_term ctx a in
|
let a = conv_term ctx a in
|
||||||
let b = conv_term ctx b in
|
let b = conv_term ctx b in
|
||||||
(* FIXME
|
|
||||||
if is_real a || is_real b then
|
if is_real a || is_real b then
|
||||||
Form.eq tst (cast_to_real ctx a) (cast_to_real ctx b)
|
(* Form.eq tst (cast_to_real ctx a) (cast_to_real ctx b) *)
|
||||||
|
LRA_term.pred tst LRA_term.Pred.Eq (cast_to_real ctx a)
|
||||||
|
(cast_to_real ctx b)
|
||||||
else
|
else
|
||||||
*)
|
|
||||||
Form.eq tst a b
|
Form.eq tst a b
|
||||||
| PA.Imply (a, b) ->
|
| PA.Imply (a, b) ->
|
||||||
let a = conv_term ctx a in
|
let a = conv_term ctx a in
|
||||||
|
|
@ -371,12 +391,9 @@ let rec conv_term (ctx : Ctx.t) (t : PA.term) : T.t =
|
||||||
in
|
in
|
||||||
A.match_ lhs cases
|
A.match_ lhs cases
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* FIXME
|
|
||||||
| PA.Arith (op, l) ->
|
| PA.Arith (op, l) ->
|
||||||
let l = List.map (conv_term ctx) l in
|
let l = List.map (conv_term ctx) l in
|
||||||
conv_arith_op ctx t op l
|
conv_arith_op ctx t op l
|
||||||
*)
|
|
||||||
| PA.Cast (t, ty_expect) ->
|
| PA.Cast (t, ty_expect) ->
|
||||||
let t = conv_term ctx t in
|
let t = conv_term ctx t in
|
||||||
let ty_expect = conv_ty ctx ty_expect in
|
let ty_expect = conv_ty ctx ty_expect in
|
||||||
|
|
|
||||||
|
|
@ -39,21 +39,9 @@ module type ARG = sig
|
||||||
val mk_lra : Term.store -> (Q.t, Term.t) lra_view -> Term.t
|
val mk_lra : Term.store -> (Q.t, Term.t) lra_view -> Term.t
|
||||||
(** Make a Term.t from the given theory view *)
|
(** Make a Term.t from the given theory view *)
|
||||||
|
|
||||||
val ty_lra : Term.store -> ty
|
val ty_real : Term.store -> ty
|
||||||
|
(** Build the type Q *)
|
||||||
|
|
||||||
val has_ty_real : Term.t -> bool
|
val has_ty_real : Term.t -> bool
|
||||||
(** Does this term have the type [Real] *)
|
(** Does this term have the type [Real] *)
|
||||||
|
|
||||||
val lemma_lra : Lit.t list -> Proof_term.t
|
|
||||||
|
|
||||||
module Gensym : sig
|
|
||||||
type t
|
|
||||||
|
|
||||||
val create : Term.store -> t
|
|
||||||
val tst : t -> Term.store
|
|
||||||
val copy : t -> t
|
|
||||||
|
|
||||||
val fresh_term : t -> pre:string -> ty -> term
|
|
||||||
(** Make a fresh term of the given type *)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
3
src/th-lra/proof_rules.ml
Normal file
3
src/th-lra/proof_rules.ml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
open Sidekick_core
|
||||||
|
|
||||||
|
let lemma_lra lits : Proof_term.t = Proof_term.apply_rule "lra.lemma" ~lits
|
||||||
5
src/th-lra/proof_rules.mli
Normal file
5
src/th-lra/proof_rules.mli
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
open Sidekick_core
|
||||||
|
|
||||||
|
val lemma_lra : Lit.t list -> Proof_term.t
|
||||||
|
(** List of literals [l1…ln] where [¬l1 /\ … /\ ¬ln] is LRA-unsat *)
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
type state = {
|
type state = {
|
||||||
tst: Term.store;
|
tst: Term.store;
|
||||||
proof: Proof_trace.t;
|
proof: Proof_trace.t;
|
||||||
gensym: A.Gensym.t;
|
gensym: Gensym.t;
|
||||||
in_model: unit Term.Tbl.t; (* terms to add to model *)
|
in_model: unit Term.Tbl.t; (* terms to add to model *)
|
||||||
encoded_eqs: unit Term.Tbl.t;
|
encoded_eqs: unit Term.Tbl.t;
|
||||||
(* [a=b] gets clause [a = b <=> (a >= b /\ a <= b)] *)
|
(* [a=b] gets clause [a = b <=> (a >= b /\ a <= b)] *)
|
||||||
|
|
@ -140,6 +140,8 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
mutable encoded_le: Term.t Comb_map.t; (* [le] -> var encoding [le] *)
|
mutable encoded_le: Term.t Comb_map.t; (* [le] -> var encoding [le] *)
|
||||||
simplex: SimpSolver.t;
|
simplex: SimpSolver.t;
|
||||||
mutable last_res: SimpSolver.result option;
|
mutable last_res: SimpSolver.result option;
|
||||||
|
n_propagate: int Stat.counter;
|
||||||
|
n_conflict: int Stat.counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
let create (si : SI.t) : state =
|
let create (si : SI.t) : state =
|
||||||
|
|
@ -151,7 +153,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
proof;
|
proof;
|
||||||
in_model = Term.Tbl.create 8;
|
in_model = Term.Tbl.create 8;
|
||||||
st_exprs = ST_exprs.create_and_setup (SI.cc si);
|
st_exprs = ST_exprs.create_and_setup (SI.cc si);
|
||||||
gensym = A.Gensym.create tst;
|
gensym = Gensym.create tst;
|
||||||
simp_preds = Term.Tbl.create 32;
|
simp_preds = Term.Tbl.create 32;
|
||||||
simp_defined = Term.Tbl.create 16;
|
simp_defined = Term.Tbl.create 16;
|
||||||
encoded_eqs = Term.Tbl.create 8;
|
encoded_eqs = Term.Tbl.create 8;
|
||||||
|
|
@ -159,6 +161,8 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
encoded_le = Comb_map.empty;
|
encoded_le = Comb_map.empty;
|
||||||
simplex = SimpSolver.create ~stat ();
|
simplex = SimpSolver.create ~stat ();
|
||||||
last_res = None;
|
last_res = None;
|
||||||
|
n_propagate = Stat.mk_int stat "th.lra.propagate";
|
||||||
|
n_conflict = Stat.mk_int stat "th.lra.conflicts";
|
||||||
}
|
}
|
||||||
|
|
||||||
let[@inline] reset_res_ (self : state) : unit = self.last_res <- None
|
let[@inline] reset_res_ (self : state) : unit = self.last_res <- None
|
||||||
|
|
@ -175,7 +179,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
SimpSolver.pop_levels self.simplex n;
|
SimpSolver.pop_levels self.simplex n;
|
||||||
()
|
()
|
||||||
|
|
||||||
let fresh_term self ~pre ty = A.Gensym.fresh_term self.gensym ~pre ty
|
let fresh_term self ~pre ty = Gensym.fresh_term self.gensym ~pre ty
|
||||||
|
|
||||||
let fresh_lit (self : state) ~mk_lit ~pre : Lit.t =
|
let fresh_lit (self : state) ~mk_lit ~pre : Lit.t =
|
||||||
let t = fresh_term ~pre self (Term.bool self.tst) in
|
let t = fresh_term ~pre self (Term.bool self.tst) in
|
||||||
|
|
@ -239,7 +243,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
| x -> x (* already encoded that *)
|
| x -> x (* already encoded that *)
|
||||||
| exception Not_found ->
|
| exception Not_found ->
|
||||||
(* new variable to represent [le_comb] *)
|
(* new variable to represent [le_comb] *)
|
||||||
let proxy = fresh_term self ~pre (A.ty_lra self.tst) in
|
let proxy = fresh_term self ~pre (A.ty_real self.tst) in
|
||||||
(* TODO: define proxy *)
|
(* TODO: define proxy *)
|
||||||
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
||||||
Log.debugf 50 (fun k ->
|
Log.debugf 50 (fun k ->
|
||||||
|
|
@ -251,7 +255,9 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
proxy)
|
proxy)
|
||||||
|
|
||||||
let add_clause_lra_ ?using (module PA : SI.PREPROCESS_ACTS) lits =
|
let add_clause_lra_ ?using (module PA : SI.PREPROCESS_ACTS) lits =
|
||||||
let pr = Proof_trace.add_step PA.proof @@ fun () -> A.lemma_lra lits in
|
let pr =
|
||||||
|
Proof_trace.add_step PA.proof @@ fun () -> Proof_rules.lemma_lra lits
|
||||||
|
in
|
||||||
let pr =
|
let pr =
|
||||||
match using with
|
match using with
|
||||||
| None -> pr
|
| None -> pr
|
||||||
|
|
@ -281,7 +287,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(match Comb_map.get le_comb self.encoded_le with
|
(match Comb_map.get le_comb self.encoded_le with
|
||||||
| Some x -> x, A.Q.one (* already encoded that *)
|
| Some x -> x, A.Q.one (* already encoded that *)
|
||||||
| None ->
|
| None ->
|
||||||
let proxy = fresh_term self ~pre:"_le_comb" (A.ty_lra self.tst) in
|
let proxy = fresh_term self ~pre:"_le_comb" (A.ty_real self.tst) in
|
||||||
|
|
||||||
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
self.encoded_le <- Comb_map.add le_comb proxy self.encoded_le;
|
||||||
LE_.Comb.iter (fun v _ -> SimpSolver.add_var self.simplex v) le_comb;
|
LE_.Comb.iter (fun v _ -> SimpSolver.add_var self.simplex v) le_comb;
|
||||||
|
|
@ -400,11 +406,11 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(Term.t * Proof_step.id Iter.t) option =
|
(Term.t * Proof_step.id Iter.t) option =
|
||||||
let proof_eq t u =
|
let proof_eq t u =
|
||||||
Proof_trace.add_step self.proof @@ fun () ->
|
Proof_trace.add_step self.proof @@ fun () ->
|
||||||
A.lemma_lra [ Lit.atom self.tst (Term.eq self.tst t u) ]
|
Proof_rules.lemma_lra [ Lit.atom self.tst (Term.eq self.tst t u) ]
|
||||||
in
|
in
|
||||||
let proof_bool t ~sign:b =
|
let proof_bool t ~sign:b =
|
||||||
let lit = Lit.atom ~sign:b self.tst t in
|
let lit = Lit.atom ~sign:b self.tst t in
|
||||||
Proof_trace.add_step self.proof @@ fun () -> A.lemma_lra [ lit ]
|
Proof_trace.add_step self.proof @@ fun () -> Proof_rules.lemma_lra [ lit ]
|
||||||
in
|
in
|
||||||
|
|
||||||
match A.view_as_lra t with
|
match A.view_as_lra t with
|
||||||
|
|
@ -462,7 +468,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
(* raise conflict from certificate *)
|
(* raise conflict from certificate *)
|
||||||
let fail_with_cert si acts cert : 'a =
|
let fail_with_cert (self : state) si acts cert : 'a =
|
||||||
Profile.with1 "lra.simplex.check-cert" SimpSolver._check_cert cert;
|
Profile.with1 "lra.simplex.check-cert" SimpSolver._check_cert cert;
|
||||||
let confl =
|
let confl =
|
||||||
SimpSolver.Unsat_cert.lits cert
|
SimpSolver.Unsat_cert.lits cert
|
||||||
|
|
@ -470,19 +476,22 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
|> List.rev_map Lit.neg
|
|> List.rev_map Lit.neg
|
||||||
in
|
in
|
||||||
let pr =
|
let pr =
|
||||||
Proof_trace.add_step (SI.proof si) @@ fun () -> A.lemma_lra confl
|
Proof_trace.add_step (SI.proof si) @@ fun () ->
|
||||||
|
Proof_rules.lemma_lra confl
|
||||||
in
|
in
|
||||||
|
Stat.incr self.n_conflict;
|
||||||
SI.raise_conflict si acts confl pr
|
SI.raise_conflict si acts confl pr
|
||||||
|
|
||||||
let on_propagate_ si acts lit ~reason =
|
let on_propagate_ self si acts lit ~reason =
|
||||||
match lit with
|
match lit with
|
||||||
| Tag.Lit lit ->
|
| Tag.Lit lit ->
|
||||||
(* TODO: more detailed proof certificate *)
|
(* TODO: more detailed proof certificate *)
|
||||||
|
Stat.incr self.n_propagate;
|
||||||
SI.propagate si acts lit ~reason:(fun () ->
|
SI.propagate si acts lit ~reason:(fun () ->
|
||||||
let lits = CCList.flat_map (Tag.to_lits si) reason in
|
let lits = CCList.flat_map (Tag.to_lits si) reason in
|
||||||
let pr =
|
let pr =
|
||||||
Proof_trace.add_step (SI.proof si) @@ fun () ->
|
Proof_trace.add_step (SI.proof si) @@ fun () ->
|
||||||
A.lemma_lra (lit :: lits)
|
Proof_rules.lemma_lra (lit :: lits)
|
||||||
in
|
in
|
||||||
CCList.flat_map (Tag.to_lits si) reason, pr)
|
CCList.flat_map (Tag.to_lits si) reason, pr)
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
|
|
@ -495,7 +504,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(SimpSolver.n_rows self.simplex));
|
(SimpSolver.n_rows self.simplex));
|
||||||
let res =
|
let res =
|
||||||
Profile.with_ "lra.simplex.solve" @@ fun () ->
|
Profile.with_ "lra.simplex.solve" @@ fun () ->
|
||||||
SimpSolver.check self.simplex ~on_propagate:(on_propagate_ si acts)
|
SimpSolver.check self.simplex ~on_propagate:(on_propagate_ self si acts)
|
||||||
in
|
in
|
||||||
Log.debug 5 "(lra.check-simplex.done)";
|
Log.debug 5 "(lra.check-simplex.done)";
|
||||||
self.last_res <- Some res;
|
self.last_res <- Some res;
|
||||||
|
|
@ -504,7 +513,7 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
| SimpSolver.Unsat cert ->
|
| SimpSolver.Unsat cert ->
|
||||||
Log.debugf 10 (fun k ->
|
Log.debugf 10 (fun k ->
|
||||||
k "(@[lra.check.unsat@ :cert %a@])" SimpSolver.Unsat_cert.pp cert);
|
k "(@[lra.check.unsat@ :cert %a@])" SimpSolver.Unsat_cert.pp cert);
|
||||||
fail_with_cert si acts cert
|
fail_with_cert self si acts cert
|
||||||
|
|
||||||
(* TODO: trivial propagations *)
|
(* TODO: trivial propagations *)
|
||||||
|
|
||||||
|
|
@ -528,7 +537,8 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(* [c=0] when [c] is not 0 *)
|
(* [c=0] when [c] is not 0 *)
|
||||||
let lit = Lit.atom ~sign:false self.tst @@ Term.eq self.tst t1 t2 in
|
let lit = Lit.atom ~sign:false self.tst @@ Term.eq self.tst t1 t2 in
|
||||||
let pr =
|
let pr =
|
||||||
Proof_trace.add_step self.proof @@ fun () -> A.lemma_lra [ lit ]
|
Proof_trace.add_step self.proof @@ fun () ->
|
||||||
|
Proof_rules.lemma_lra [ lit ]
|
||||||
in
|
in
|
||||||
SI.add_clause_permanent si acts [ lit ] pr
|
SI.add_clause_permanent si acts [ lit ] pr
|
||||||
)
|
)
|
||||||
|
|
@ -537,11 +547,11 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
try
|
try
|
||||||
let c1 = SimpSolver.Constraint.geq v le_const in
|
let c1 = SimpSolver.Constraint.geq v le_const in
|
||||||
SimpSolver.add_constraint self.simplex c1 tag
|
SimpSolver.add_constraint self.simplex c1 tag
|
||||||
~on_propagate:(on_propagate_ si acts);
|
~on_propagate:(on_propagate_ self si acts);
|
||||||
let c2 = SimpSolver.Constraint.leq v le_const in
|
let c2 = SimpSolver.Constraint.leq v le_const in
|
||||||
SimpSolver.add_constraint self.simplex c2 tag
|
SimpSolver.add_constraint self.simplex c2 tag
|
||||||
~on_propagate:(on_propagate_ si acts)
|
~on_propagate:(on_propagate_ self si acts)
|
||||||
with SimpSolver.E_unsat cert -> fail_with_cert si acts cert
|
with SimpSolver.E_unsat cert -> fail_with_cert self si acts cert
|
||||||
)
|
)
|
||||||
|
|
||||||
let add_local_eq (self : state) si acts n1 n2 : unit =
|
let add_local_eq (self : state) si acts n1 n2 : unit =
|
||||||
|
|
@ -627,12 +637,12 @@ module Make (A : ARG) = (* : S with module A = A *) struct
|
||||||
(try
|
(try
|
||||||
SimpSolver.add_var self.simplex v;
|
SimpSolver.add_var self.simplex v;
|
||||||
SimpSolver.add_constraint self.simplex constr (Tag.Lit lit)
|
SimpSolver.add_constraint self.simplex constr (Tag.Lit lit)
|
||||||
~on_propagate:(on_propagate_ si acts)
|
~on_propagate:(on_propagate_ self si acts)
|
||||||
with SimpSolver.E_unsat cert ->
|
with SimpSolver.E_unsat cert ->
|
||||||
Log.debugf 10 (fun k ->
|
Log.debugf 10 (fun k ->
|
||||||
k "(@[lra.partial-check.unsat@ :cert %a@])"
|
k "(@[lra.partial-check.unsat@ :cert %a@])"
|
||||||
SimpSolver.Unsat_cert.pp cert);
|
SimpSolver.Unsat_cert.pp cert);
|
||||||
fail_with_cert si acts cert)
|
fail_with_cert self si acts cert)
|
||||||
| None, LRA_pred (Eq, t1, t2) when sign ->
|
| None, LRA_pred (Eq, t1, t2) when sign ->
|
||||||
add_local_eq_t self si acts t1 t2 ~tag:(Tag.Lit lit)
|
add_local_eq_t self si acts t1 t2 ~tag:(Tag.Lit lit)
|
||||||
| None, LRA_pred (Neq, t1, t2) when not sign ->
|
| None, LRA_pred (Neq, t1, t2) when not sign ->
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,30 @@
|
||||||
(** Linear Rational Arithmetic *)
|
(** Linear Rational Arithmetic *)
|
||||||
|
|
||||||
|
open Sidekick_core
|
||||||
module Intf = Intf
|
module Intf = Intf
|
||||||
|
module Predicate = Intf.Predicate
|
||||||
|
module SMT = Sidekick_smt_solver
|
||||||
|
|
||||||
include module type of struct
|
module type INT = Intf.INT
|
||||||
include Intf
|
module type RATIONAL = Intf.RATIONAL
|
||||||
end
|
|
||||||
|
module S_op = Sidekick_simplex.Op
|
||||||
|
|
||||||
|
type term = Term.t
|
||||||
|
type ty = Term.t
|
||||||
|
type pred = Intf.pred = Leq | Geq | Lt | Gt | Eq | Neq
|
||||||
|
type op = Intf.op = Plus | Minus
|
||||||
|
|
||||||
|
type ('num, 'a) lra_view = ('num, 'a) Intf.lra_view =
|
||||||
|
| LRA_pred of pred * 'a * 'a
|
||||||
|
| LRA_op of op * 'a * 'a
|
||||||
|
| LRA_mult of 'num * 'a
|
||||||
|
| LRA_const of 'num
|
||||||
|
| LRA_other of 'a
|
||||||
|
|
||||||
|
val map_view : ('a -> 'b) -> ('c, 'a) lra_view -> ('c, 'b) lra_view
|
||||||
|
|
||||||
|
module type ARG = Intf.ARG
|
||||||
|
|
||||||
(* TODO
|
(* TODO
|
||||||
type state
|
type state
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue