Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/smtml/feature_extraction.ml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ let string_of_naryop (naryop : Ty.Naryop.t) : string =
| Logor -> "Logor"
| Concat -> "Concat"
| Regexp_union -> "Regexp_union"
| Distinct -> "Distinct"

let string_of_expr_kind (e : Expr.expr) _ty : string =
match e with
Expand Down
1 change: 1 addition & 0 deletions src/smtml/mappings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ module Make (M_with_make : M_with_make) : S_with_fresh = struct
match op with
| Naryop.Logand -> M.logand l
| Logor -> M.logor l
| Distinct -> M.distinct l
| _ ->
Fmt.failwith {|Bool: Unsupported n-ary operator "%a"|} Naryop.pp op

Expand Down
8 changes: 6 additions & 2 deletions src/smtml/ty.ml
Original file line number Diff line number Diff line change
Expand Up @@ -627,28 +627,32 @@ module Naryop = struct
| Logor
| Concat
| Regexp_union
| Distinct
[@@deriving ord]

let hash = function
| Logand -> 0
| Logor -> 1
| Concat -> 2
| Regexp_union -> 3
| Distinct -> 4

let equal op1 op2 =
match (op1, op2) with
| Logand, Logand
| Logor, Logor
| Concat, Concat
| Regexp_union, Regexp_union ->
| Regexp_union, Regexp_union
| Distinct, Distinct ->
true
| (Logand | Logor | Concat | Regexp_union), _ -> false
| (Logand | Logor | Concat | Regexp_union | Distinct), _ -> false

let pp fmt = function
| Logand -> Fmt.string fmt "and"
| Logor -> Fmt.string fmt "or"
| Concat -> Fmt.string fmt "++"
| Regexp_union -> Fmt.string fmt "union"
| Distinct -> Fmt.string fmt "distinct"
end

module Smtlib = struct
Expand Down
1 change: 1 addition & 0 deletions src/smtml/ty.mli
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ module Naryop : sig
| Logor (** Logical OR. *)
| Concat (** Concatenation. *)
| Regexp_union (** Union of regular expressions. *)
| Distinct
[@@deriving ord]

val hash : t -> int
Expand Down
5 changes: 5 additions & 0 deletions src/smtml/typed.ml
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,11 @@ module Bool = struct

let[@inline] eq (a : 'a expr) (b : 'a expr) = Expr.relop Types.bool Eq a b

let[@inline] distinct (es : 'a expr list) =
(* Typically this encodes a symbolic constraint: (distinct x y z), so no
need to waste time trying to simplify. Just use `raw_naryop`. *)
Expr.raw_naryop Types.bool Distinct es

let[@inline] ite c (r1 : 'a expr) (r2 : 'a expr) : 'a expr =
Expr.triop Types.bool Ite c r1 r2

Expand Down
4 changes: 4 additions & 0 deletions src/smtml/typed.mli
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ module Bool : sig
(** [eq t1 t2] returns true if [t1] and [t2] are structurally equal. *)
val eq : 'a expr -> 'a expr -> t

(** [distinct es] returns true if all expressions in the list [es] are
pair-wise distinct. *)
val distinct : 'a expr list -> t

(** [ite cond then_ else_] constructs an if-then-else expression. Returns
[then_] if [cond] evaluates to true, and [else_] otherwise. *)
val ite : t -> 'a expr -> 'a expr -> 'a expr
Expand Down
22 changes: 22 additions & 0 deletions test/integration/test_solver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,27 @@ module Make (M : Mappings_intf.S_with_fresh) = struct
let val_x = Option.bind model (fun m -> Model.evaluate m symbol_x) in
assert (match val_x with Some v -> Value.equal v (Int 5) | None -> false)

let test_distinct solver_module =
let open Typed in
let module Solver = (val solver_module : Solver_intf.S) in
let solver = Solver.create ~logic:LIA () in
let x = symbol Types.int "x" in
let y = symbol Types.int "y" in
let z = symbol Types.int "z" in
Solver.add solver [ (Bool.distinct [ x; y; z ] :> Expr.t) ];
Solver.add solver [ (Bool.eq x (Int.v 1) :> Expr.t) ];
Solver.add solver [ (Bool.eq y (Int.v 1) :> Expr.t) ];
assert_unsat ~f:"test_distinct_unsat" (Solver.check solver []);
Solver.reset solver;
let x = symbol Types.int "x" in
let y = symbol Types.int "y" in
let z = symbol Types.int "z" in
Solver.add solver [ (Bool.distinct [ x; y; z ] :> Expr.t) ];
Solver.add solver [ (Bool.eq x (Int.v 1) :> Expr.t) ];
Solver.add solver [ (Bool.eq y (Int.v 2) :> Expr.t) ];
Solver.add solver [ (Bool.eq z (Int.v 3) :> Expr.t) ];
assert_sat ~f:"test_distinct_sat" (Solver.check solver [])

let test_lia_1 solver_module =
let open Infix in
let module Solver = (val solver_module : Solver_intf.S) in
Expand All @@ -123,6 +144,7 @@ module Make (M : Mappings_intf.S_with_fresh) = struct
"test_lia"
>::: [ "test_lia_0" >:: with_solver test_lia_0
; "test_lia_1" >:: with_solver test_lia_1
; "test_distinct" >:: with_solver test_distinct
]

let test_lra =
Expand Down