updates and cleanup

This commit is contained in:
Simon Cruanes 2022-02-14 10:46:08 -05:00
parent 73289d1ded
commit 98c30bf0cc
No known key found for this signature in database
GPG key ID: EBFFF6F283F3A2B4
6 changed files with 39 additions and 82 deletions

View file

@ -329,7 +329,7 @@ val b : Term.t = b
# Term.ty a;; # Term.ty a;;
- : Ty.t = Real - : Ty.t = Real
# let a_leq_b = Term.LRA.(leq tstore (var tstore a) (var tstore b));; # let a_leq_b = Term.LRA.(leq tstore a b);;
val a_leq_b : Term.t = (<= a b) val a_leq_b : Term.t = (<= a b)
``` ```
@ -367,7 +367,10 @@ val res : Solver.res =
This just showed that `a=1, b=1/2, a>=b` is unsatisfiable. This just showed that `a=1, b=1/2, a>=b` is unsatisfiable.
The junk assumption `p` was not used during the proof The junk assumption `p` was not used during the proof
and therefore doesn't appear in the unsat core we extract from `res`. and therefore doesn't appear in the unsat core we extract from `res`;
the assertion `a<=b` isn't in the core either because it was asserted
using `(assert …)` rather than passed as a local assumption,
so it's "background" knowledge.
## Functions and congruence closure ## Functions and congruence closure

View file

@ -679,7 +679,7 @@ module Make (A: CC_ARG)
if same_class a b then ( if same_class a b then (
let expl = Expl.mk_merge a b in let expl = Expl.mk_merge a b in
Log.debugf 5 Log.debugf 5
(fun k->k "(@[pending.eq@ %a@ :r1 %a@ :r2 %a@])" N.pp n N.pp a N.pp b); (fun k->k "(@[cc.pending.eq@ %a@ :r1 %a@ :r2 %a@])" N.pp n N.pp a N.pp b);
merge_classes cc n (n_true cc) expl merge_classes cc n (n_true cc) expl
) )
| Some (Not u) -> | Some (Not u) ->

View file

@ -460,70 +460,15 @@ module Make(A : ARG) : S with module A = A = struct
Log.debugf 50 (fun k->k "(@[lra.preproc@ :t %a@ :to-constr %a@])" Log.debugf 50 (fun k->k "(@[lra.preproc@ :t %a@ :to-constr %a@])"
T.pp t SimpSolver.Constraint.pp constr); T.pp t SimpSolver.Constraint.pp constr);
| LRA_op _ | LRA_mult _ -> () | LRA_op _ | LRA_mult _ ->
(* (* NOTE: we don't need to do anything for rational subterms, at least
NOTE: we don't need to do anything for rational subterms, at least
not at first. Only when theory combination mandates we compare not at first. Only when theory combination mandates we compare
two terms (by deciding [t1 = t2]) do they impact the simplex; and two terms (by deciding [t1 = t2]) do they impact the simplex; and
then they're moved into an equation, which means then they're moved into an equation, which means they are
preprocessed in the LRA_pred case above. *)
let le = as_linexp t in
(* [t] is [le_comb + le_const], where [le_comb] is a linear expression
without constant. *)
let le_comb, le_const = LE.comb le, LE.const le in
LE_.Comb.iter (fun v _ -> SimpSolver.add_var self.simplex v) le_comb;
if A.Q.(le_const = zero) then (
(* if there is no constant, define [t] as [t := le_comb] *)
declare_term_to_cc ~sub:false t;
SimpSolver.define self.simplex t (LE_.Comb.to_list le_comb);
) else (
(* a bit more complicated: we cannot just define [t := le_comb]
because of the coefficient, and the simplex doesn't like offsets.
Instead we assert [t := le_comb + proxy2] using a secondary
variable [proxy2], and assert [proxy2 = le_const] in
the simplex *)
let proxy2 = fresh_term self ~pre:"_le_diff" (T.ty t) in
SimpSolver.add_var self.simplex proxy2;
LE_.Comb.iter (fun v _ ->
declare_term_to_cc ~sub:true v;
SimpSolver.add_var self.simplex v;
) le_comb;
SimpSolver.define self.simplex t
((A.Q.one, proxy2) :: LE_.Comb.to_list le_comb);
Log.debugf 50
(fun k->k "(@[lra.encode-linexp.with-offset@ `@[%a@]`@ :var %a@ :const-var %a@])"
LE_.Comb.pp le_comb T.pp t T.pp proxy2);
declare_term_to_cc ~sub:false t;
declare_term_to_cc ~sub:true proxy2;
(* can only work at level 0 *)
assert (Backtrack_stack.n_levels self.local_eqs = 0);
SimpSolver.declare_bound self.simplex
(SimpSolver.Constraint.mk proxy2 Leq le_const) Tag.By_def;
SimpSolver.declare_bound self.simplex
(SimpSolver.Constraint.mk proxy2 Geq le_const) Tag.By_def;
() ()
)
*)
| LRA_const n -> | LRA_const _n -> ()
(* add to simplex, make sure it's always itself *)
SimpSolver.add_var self.simplex t;
assert (n_levels self=0); (* otherwise this will be backtracked but not re-done *)
SimpSolver.declare_bound self.simplex
(SimpSolver.Constraint.mk t Leq n) Tag.By_def;
SimpSolver.declare_bound self.simplex
(SimpSolver.Constraint.mk t Geq n) Tag.By_def;
| LRA_other t when A.has_ty_real t -> () | LRA_other t when A.has_ty_real t -> ()
| LRA_other _ -> | LRA_other _ ->
@ -683,6 +628,11 @@ module Make(A : ARG) : S with module A = A = struct
(Util.pp_iter @@ Fmt.within "`" "`" T.pp) (T.Tbl.keys self.needs_th_combination)); (Util.pp_iter @@ Fmt.within "`" "`" T.pp) (T.Tbl.keys self.needs_th_combination));
); );
let eval_in_subst_ subst t = match A.view_as_lra t with
| LRA_const n -> n
| _ -> Subst.eval subst t |> CCOpt.get_or ~default:A.Q.zero
in
let n = ref 0 in let n = ref 0 in
(* theory combination: for [t1,t2] terms in [self.needs_th_combination] (* theory combination: for [t1,t2] terms in [self.needs_th_combination]
that have same value, but are not provably equal, push that have same value, but are not provably equal, push
@ -690,7 +640,7 @@ module Make(A : ARG) : S with module A = A = struct
begin begin
let by_val: T.t list Q_map.t = let by_val: T.t list Q_map.t =
T.Tbl.keys self.needs_th_combination T.Tbl.keys self.needs_th_combination
|> Iter.map (fun t -> Subst.eval subst t, t) |> Iter.map (fun t -> eval_in_subst_ subst t, t)
|> Iter.fold |> Iter.fold
(fun m (q,t) -> (fun m (q,t) ->
let l = Q_map.get_or ~default:[] q m in let l = Q_map.get_or ~default:[] q m in
@ -816,7 +766,10 @@ module Make(A : ARG) : S with module A = A = struct
begin match self.last_res with begin match self.last_res with
| Some (SimpSolver.Sat m) -> | Some (SimpSolver.Sat m) ->
Log.debugf 50 (fun k->k "(@[lra.model-ask@ %a@])" T.pp t); Log.debugf 50 (fun k->k "(@[lra.model-ask@ %a@])" T.pp t);
SimpSolver.V_map.get t m |> CCOpt.map (t_const self) begin match A.view_as_lra t with
| LRA_const n -> Some n (* always eval constants to themselves *)
| _ -> SimpSolver.V_map.get t m
end |> CCOpt.map (t_const self)
| _ -> None | _ -> None
end end

View file

@ -73,7 +73,7 @@ module type S = sig
module Subst : sig module Subst : sig
type t = num V_map.t type t = num V_map.t
val eval : t -> V.t -> Q.t val eval : t -> V.t -> Q.t option
val pp : t Fmt.printer val pp : t Fmt.printer
val to_string : t -> string val to_string : t -> string
end end
@ -210,7 +210,7 @@ module Make(Arg: ARG)
module Subst = struct module Subst = struct
type t = num V_map.t type t = num V_map.t
let eval self t = try V_map.find t self with Not_found -> Q.zero let eval self t = V_map.get t self
let pp out (self:t) : unit = let pp out (self:t) : unit =
let pp_pair out (v,n) = let pp_pair out (v,n) =
Fmt.fprintf out "(@[%a := %a@])" V.pp v pp_q_dbg n in Fmt.fprintf out "(@[%a := %a@])" V.pp v pp_q_dbg n in
@ -1170,15 +1170,17 @@ module Make(Arg: ARG)
Matrix.iter_rows self.matrix Matrix.iter_rows self.matrix
(fun _i x_i -> (fun _i x_i ->
if x_i.is_int then ( if x_i.is_int then (
let n = Subst.eval m x_i.var in begin match Subst.eval m x_i.var with
if not (Q.is_int n) then ( | Some n when not (Q.is_int n) ->
(* found one! *) (* found one! *)
Log.debugf 10 Log.debugf 10
(fun k->k "(@[simplex.int-var-assigned-to-non-int@ %a := %a@])" (fun k->k "(@[simplex.int-var-assigned-to-non-int@ %a := %a@])"
Var_state.pp x_i Q.pp n); Var_state.pp x_i Q.pp n);
raise (Found (x_i, n)) raise (Found (x_i, n))
)
| _ -> ()
end
) )
); );
Ok() Ok()

View file

@ -787,8 +787,10 @@ module Make(A : ARG)
(c:lit IArray.t) (pr:proof_step) : lit IArray.t * proof_step = (c:lit IArray.t) (pr:proof_step) : lit IArray.t * proof_step =
Solver_internal.preprocess_clause_iarray_ self.si c pr Solver_internal.preprocess_clause_iarray_ self.si c pr
let[@inline] mk_lit_t (self:t) ?sign (t:term) : lit = let mk_lit_t (self:t) ?sign (t:term) : lit =
Lit.atom self.si.tst ?sign t let lit = Lit.atom self.si.tst ?sign t in
let lit, _ = Solver_internal.simplify_and_preproc_lit_ self.si lit in
lit
(** {2 Main} *) (** {2 Main} *)

View file

@ -127,10 +127,7 @@ let t_as_z t = match Term.view t with
| T.LIA (Const n) -> Some n | T.LIA (Const n) -> Some n
| _ -> None | _ -> None
let is_real t = let[@inline] is_real t = Ty.equal (T.ty t) (Ty.real())
match T.view t with
| T.LRA _ -> true
| _ -> Ty.equal (T.ty t) (Ty.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 =