Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Make sure model generation is complete for more operators (#1234) #1238

Merged
merged 1 commit into from
Sep 18, 2024
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
13 changes: 7 additions & 6 deletions docs/sphinx_docs/Model_generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,25 @@ following constructs:
- Algebraic data types (including records and enumerated types in the native
language)

- Integer and real primitives (addition, subtraction, multiplication,
division, modulo, exponentiation, and comparisons), but not conversion
operators between reals and integers
- The following integer and real primitives: addition, subtraction,
multiplication, division, modulo, comparisons, and exponentiations *with an
integer exponent*

- Bit-vector primitives (concatenation, extraction, `bvadd`, `bvand`, `bvule`,
etc.), including `bv2nat` and `int2bv`

Completeness for the following constructs is only guaranteed with certain
command-line flags:

- Conversions operators between integers and reals require the
`--enable-theories ria` flag
- Conversions operators from integers to reals `real_of_int` and `real_is_int`
require the `--enable-theories ria` flag

- Floating-point primitives (`ae.round`, `ae.float32` etc. in the SMT-LIB
language; `float`, `float32` and `float64` in the native language) require
the `--enable-theories fpa` flag

Model generation is known to be sometimes incomplete in the presence of arrays.
Model generation is known to be sometimes incomplete in the presence of arrays,
and is incomplete for the `integer_round` function.

## Examples

Expand Down
5 changes: 5 additions & 0 deletions src/lib/frontend/d_cnf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ type _ DStd.Builtin.t +=
| Sqrt_real_excess
| Ceiling_to_int of [ `Real ]
| Max_real
| Min_real
| Max_int
| Min_int
| Integer_log2
Expand Down Expand Up @@ -360,6 +361,9 @@ let ae_fpa_builtins =
(* maximum of two reals *)
|> op "max_real" Max_real ([real; real] ->. real)

(* minimum of two reals *)
|> op "min_real" Min_real ([real; real] ->. real)

(* maximum of two ints *)
|> op "max_int" Max_int ([int; int] ->. int)

Expand Down Expand Up @@ -1349,6 +1353,7 @@ let rec mk_expr
| B.Is_int `Real, _ -> op Real_is_int
| Ceiling_to_int `Real, _ -> op Int_ceil
| Max_real, _ -> op Max_real
| Min_real, _ -> op Min_real
| Max_int, _ -> op Max_int
| Min_int, _ -> op Min_int
| Integer_log2, _ -> op Integer_log2
Expand Down
3 changes: 3 additions & 0 deletions src/lib/frontend/typechecker.ml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ module Env = struct
(* maximum of two reals *)
|> op "max_real" Max_real ([real; real] ->. real)

(* minimum of two reals *)
|> op "min_real" Min_real ([real; real] ->. real)

(* maximum of two ints *)
|> op "max_int" Max_int ([int; int] ->. int)

Expand Down
40 changes: 40 additions & 0 deletions src/lib/reasoners/intervalCalculus.ml
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,51 @@ let delayed_pow uf _op = function
| [ a; b ] -> calc_pow a b (E.type_info a) uf
| _ -> assert false

let delayed_op1 ~ty fn uf _op = function
| [ x ] ->
let rx, exx = Uf.find uf x in
Option.bind (P.is_const (poly_of rx)) @@ fun cx ->
Some (alien_of (P.create [] (fn cx) ty), exx)
| _ -> assert false

let delayed_op2 ~ty fn uf _op = function
| [ x; y ] ->
let rx, exx = Uf.find uf x in
let ry, exy = Uf.find uf y in
Option.bind (P.is_const (poly_of rx)) @@ fun cx ->
Option.bind (P.is_const (poly_of ry)) @@ fun cy ->
Some (alien_of (P.create [] (fn cx cy) ty), Ex.union exx exy)
| _ -> assert false

let delayed_integer_log2 uf _op = function
| [ x ] -> (
let rx, exx = Uf.find uf x in
let px = poly_of rx in
match P.is_const px with
| None -> None
| Some cb ->
if Q.compare cb Q.zero <= 0 then None
else
let res =
alien_of @@
P.create [] (Q.from_int (Fpa_rounding.integer_log_2 cb)) Treal
in
Some (res, exx)
)
| _ -> assert false

(* These are the partially interpreted functions that we know how to compute.
They will be computed immediately if possible, or as soon as we learn the
value of their arguments. *)
let dispatch = function
| Symbols.Pow -> Some delayed_pow
| Symbols.Integer_log2 -> Some delayed_integer_log2
| Symbols.Int_floor -> Some (delayed_op1 ~ty:Tint Numbers.Q.floor)
| Symbols.Int_ceil -> Some (delayed_op1 ~ty:Tint Numbers.Q.ceiling)
| Symbols.Min_int -> Some (delayed_op2 ~ty:Tint Q.min)
| Symbols.Max_int -> Some (delayed_op2 ~ty:Tint Q.max)
| Symbols.Min_real -> Some (delayed_op2 ~ty:Treal Q.min)
| Symbols.Max_real -> Some (delayed_op2 ~ty:Treal Q.max)
| _ -> None

let empty uf = {
Expand Down
1 change: 0 additions & 1 deletion src/lib/structures/expr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2958,7 +2958,6 @@ let int_view t =
| _ ->
Fmt.failwith "The given term %a is not an integer" print t


let rounding_mode_view t =
match const_view t with
| RoundingMode m -> m
Expand Down
Loading