Skip to content

Commit

Permalink
Refactoring models representation (#925)
Browse files Browse the repository at this point in the history
* Refactoring model

* Creating a module for identifiers

As we need to use identifiers in both `Symbols` and `Value` of models, I
create a new module `Id.ml` which contains namespaces for internal
identifiers and abstract values.

* Clean-up printers

* Reset the cache at the start of generation model

The call to `Cache.reset` wasn't in the appropriate function and
reset the cache after computing each model value.

* Produce an abstract value for abstract type.

We cannot produce a concrete value for a symbol whose the type is an
abstract value. For instance, consider the input file:

```
(set-logic ALL)
(set-option :produce-models true)
(declare-sort s 0)
(declare-const a s)
(declare-const b s)
(assert (= a b))
(check-sat)
(get-model)
```

Alt-Ergo outputs `unknown`, which makes sense as we don't know anything
about the abstract type `s`. As `a` and `b` are user-defined, we have to
print something in the model about them but we cannot! Thus, we have to
print abstract values for them.

* Restoring record model generation

* Print the same abstract value of equal semantic values.

If we have the equation `a = b` for two terms `a` and `b` and we
produce an abstract value for `a`, we have to use the same abstract
value for `b` in the model.

* Prefix unused arguments of model values

Prefix unused arguments of model values by an underscore. In the current
codebase, the only situation in which such arguments can appear is while
printing constants.

* Restoring objectives in interpretation

* Restoring assertion mode for models and clean-up

* Use `Seq.is_empty` from `stdcompat`

* Cleanup and a bit of documentation

* Promote tests

* Linter

* Update src/lib/structures/modelMap.ml

Co-authored-by: Stevendeo <de.oliveira.steven@gmail.com>

* Update src/lib/util/util.mli

Co-authored-by: Stevendeo <de.oliveira.steven@gmail.com>

* Update src/lib/reasoners/uf.ml

Co-authored-by: Stevendeo <de.oliveira.steven@gmail.com>

* Update src/lib/reasoners/uf.ml

Co-authored-by: Stevendeo <de.oliveira.steven@gmail.com>

* Review changes

* Unused argument in the test

* Promote tests

* Models for functions returning records

The previous implementation of `compute_concrete_model` doesn't support
properly model generation for functions returning records. This is a
quick fix.

* Improve the type of `ModelMap.Value`

The previous type was not sufficient to represent all the possible model
values. In particular, we couldn't represent embedded records in other
record and we cannot use complex types for indices and values of functional
arrays.

* Change review

* rebase artefact

* Use `Expr.t` to store model values

Use `Expr.t` values instead of strings to store the value of the
first-order model.

Add a new function `to_term_const` in the signature of `Shostak`.
Basically this function is the inverse function of `X.make` on the
constant terms only. The function always returns a term `t` such that
`Expr.is_const_term t` is `true`.

Notice that we need this function during model generation. Indeed, even
if the class of a semantic value in UF contains terms whose the `make`
is constant according to `X.is_constant`, these terms aren't necessary
constant according to `Expr.is_const_term`. For instance, the term `0 +
1` will become the semantic value `1` and we expect that
`X.to_term_const` returns `Some 1`.

Modify the definition of `Expr.is_const_term` (formerly named
`const_term`). The previous definition considered that the application
of constructor of an ADT to constant terms isn't a constant term. The
same went for record definitions. Now, there are constant too.
We have to check that this modification is correct for the

Notice that we keep the old definion `const_term` in the module `Expr`
but we don't expose it anymore. Indeed, this function is used to detect
constants in the smart constructor of the let bindings because the
definition of the depth of formulae have been tweaked to prevent
regressions. Modifying this function could be dangereous.

* Poetry

* Hide the caches in the closure of `compute_concrete_model`

* Fix `to_const_term` in BV theory

* Documentation in UF and fix BV symbols

Currently, we produce casesplits for bitvectors in order to generate
models but we cannot reasoning with `BVand`, `BVxor` and `BVor`. It
means we cannot add these symbols as interpreted symbols of the theory
BV (see the function `Bitv.is_mine_symbol`) but these symbols can appear
in the union-find environment. We have to ignore them while computing
the model in UF.

* Documentation of the type sy

* documentation

* restoring the constraint printer

* Incorrect `is_internal` predicate

We have to consider every symbol names starting with a dot or a `at` as
an internal symbols. For instance the CDCL SAT solver produces internal
names prefixed by `.PROXY__`.

* Simpler `to_const_term` in BV theory

We don't need to consider the case where a constant semantic value would
be a concatenation of constant simple terms. Now the canonizer eliminate
this case completely.

* rename `terms_values` to `term_values`

* rebase artefact in models.ml

* Use Dolmen to quote identifiers

* Rename `is_const_term` to `is_model_term`

Variables aren't adequate model values. Now the predicate
`is_model_term` returns `false` on them.

* Remove brackets in `ArrayEx.select`

* Clarify `X.is_constant` implementation

* Simplify `model_repr_of_term`

We don't need to inspect the class of a term to retrieve a constant
expression in it. When we call `model_repr_of_term` during the model
generation, we are sure that the representant of the class is a constant
semantic value and `X.to_const_term` cannot fail. Otherwise, it's a bug!

* Rename `to_const_term` to `to_model_term`

As we rename `Expr.is_const_term` to `Expr.is_model_term`, I rename
this function for consistency purposes.

* Only use `Expr.t` to store model values

As arrays can occur into model values, we need to use `Expr.t` to
represent them.

We cannot produce the appropriate model term with `Arrays.to_model_term`
because we haven't semantic values for arrays. Instead we perform two
passes on a pre-model generating with `X.to_model_term`.
- The first pass collects all the values of arrays and generates a model
  term for each array. If the array was declared by the user, we add
  it to the model.
- The second pass substitutes all the array identifiers in the pre-model
  by model terms we have generated in the first pass.

* Remove warning message for models in presence of FPA symbols

* bvor, bvand and bvxor aren't suspicious anymore

* prefix model error

* Poetry

---------

Co-authored-by: Stevendeo <de.oliveira.steven@gmail.com>
  • Loading branch information
Halbaroth and Stevendeo authored Dec 21, 2023
1 parent 828f0ec commit f451ee0
Show file tree
Hide file tree
Showing 55 changed files with 908 additions and 870 deletions.
1 change: 1 addition & 0 deletions alt-ergo-lib.opam
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ depends: [
"fmt" {>= "0.9.0"}
"stdlib-shims"
"ppx_blob" {>= "0.7.2"}
"ppx_deriving"
"camlzip" {>= "1.07"}
"odoc" {with-doc}
"ppx_deriving"
Expand Down
1 change: 1 addition & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ See more details on http://alt-ergo.ocamlpro.com/"
(fmt (>= 0.9.0))
stdlib-shims
(ppx_blob (>= 0.7.2))
ppx_deriving
(camlzip (>= 1.07))
(odoc :with-doc)
ppx_deriving
Expand Down
9 changes: 6 additions & 3 deletions src/bin/common/solving_loop.ml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ let main () =
begin
let mdl = Model ((module SAT), partial_model) in
if Options.(get_interpretation () && get_dump_models ()) then begin
FE.print_model (Options.Output.get_fmt_models ()) partial_model
Fmt.pf (Options.Output.get_fmt_models ()) "%a@."
FE.print_model partial_model
end;
Sat mdl
end
Expand All @@ -193,7 +194,8 @@ let main () =
Printer.print_fmt (Options.Output.get_fmt_diagnostic ())
"@[<v 0>Returned unknown reason = %a@]"
Sat_solver_sig.pp_ae_unknown_reason_opt ur;
FE.print_model (Options.Output.get_fmt_models ()) partial_model
Fmt.pf (Options.Output.get_fmt_models ()) "%a@."
FE.print_model partial_model
end;
Unknown (Some mdl)
end
Expand Down Expand Up @@ -927,7 +929,8 @@ let main () =
let () = match State.get partial_model_key st with
| Some (Model ((module SAT), env)) ->
let module FE = Frontend.Make (SAT) in
FE.print_model (Options.Output.get_fmt_regular ()) env
Fmt.pf (Options.Output.get_fmt_regular ()) "%a@."
FE.print_model env
| None ->
(* TODO: add the location of the statement. *)
recoverable_error "No model produced."
Expand Down
2 changes: 1 addition & 1 deletion src/lib/dune
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
; structures
Commands Errors Explanation Fpa_rounding
Parsed Profiling Satml_types Symbols
Expr Var Ty Typed Xliteral ModelMap Objective
Expr Var Ty Typed Xliteral ModelMap Id Objective
; util
Emap Gc_debug Hconsing Hstring Heap Lists Loc
MyUnix Numbers
Expand Down
40 changes: 20 additions & 20 deletions src/lib/frontend/d_cnf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ module SM = Sy.Map

module DE = DStd.Expr
module DT = DE.Ty
module Id = DStd.Id
module B = DStd.Builtin

let unsupported msg =
Expand Down Expand Up @@ -194,7 +193,7 @@ let builtin_term t = Dl.Typer.T.builtin_term t
let builtin_ty t = Dl.Typer.T.builtin_ty t

let ty name ty =
Id.Map.add { name = DStd.Name.simple name; ns = Sort } @@
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Sort } @@
fun env s ->
builtin_ty @@
Dolmen_type.Base.app0 (module Dl.Typer.T) env s ty
Expand All @@ -214,10 +213,11 @@ let builtin_enum = function
let add_cstrs map =
List.fold_left (fun map ((c : DE.term_cst), _) ->
let name = get_basename c.path in
Id.Map.add { name = DStd.Name.simple name; ns = Term } (fun env _ ->
builtin_term @@
Dolmen_type.Base.term_app_cst
(module Dl.Typer.T) env c) map)
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Term }
(fun env _ ->
builtin_term @@
Dolmen_type.Base.term_app_cst
(module Dl.Typer.T) env c) map)
map cstrs
in
Cache.store_ty (DE.Ty.Const.hash ty_cst) ty_;
Expand All @@ -238,19 +238,19 @@ module Const = struct
let bv2nat =
with_cache (fun n ->
let name = "bv2nat" in
Id.mk ~name ~builtin:(BV2Nat n)
DE.Id.mk ~name ~builtin:(BV2Nat n)
(DStd.Path.global name) Ty.(arrow [bitv n] int))

let int2bv =
with_cache (fun n ->
let name = "int2bv" in
Id.mk ~name ~builtin:(Int2BV n)
DE.Id.mk ~name ~builtin:(Int2BV n)
(DStd.Path.global name) Ty.(arrow [int] (bitv n)))

let smt_round =
with_cache (fun (n, m) ->
let name = "ae.round" in
Id.mk
DE.Id.mk
~name
~builtin:(AERound (n, m))
(DStd.Path.global name)
Expand Down Expand Up @@ -299,7 +299,7 @@ let bv_builtins env s =
equivalent *)
let inject_ae_to_smt2 id =
match id with
| Id.{name = Simple n; _} ->
| DStd.Id.{name = Simple n; _} ->
begin
if String.equal n Fpa_rounding.fpa_rounding_mode_ae_type_name then
(* Injecting the type name as the SMT2 Type name. *)
Expand All @@ -322,15 +322,15 @@ let inject_ae_to_smt2 id =
let ae_fpa_builtins =
let (->.) args ret = (args, ret) in
let dterm name f =
Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
fun env s ->
builtin_term @@
Dolmen_type.Base.term_app1 (module Dl.Typer.T) env s f
in
let op ?(tyvars = []) name builtin (args, ret) =
let ty = DT.pi tyvars @@ DT.arrow args ret in
let cst = DE.Id.mk ~name ~builtin (DStd.Path.global name) ty in
Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
fun env _ ->
builtin_term @@
Dolmen_type.Base.term_app_cst
Expand Down Expand Up @@ -358,13 +358,13 @@ let ae_fpa_builtins =
let float64 = float (DE.Term.int "53") (DE.Term.int "1074") in
let float64d x = float64 (mode "NearestTiesToEven") x in
let partial1 name f =
Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
fun env s ->
builtin_term @@
Dolmen_type.Base.term_app1 (module Dl.Typer.T) env s f
in
let partial2 name f =
Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
DStd.Id.Map.add { name = DStd.Name.simple name; ns = Term } @@
fun env s ->
builtin_term @@
Dolmen_type.Base.term_app2 (module Dl.Typer.T) env s f
Expand All @@ -380,7 +380,7 @@ let ae_fpa_builtins =
in
let fpa_builtins =
let open DT in
Id.Map.empty
DStd.Id.Map.empty

|> add_rounding_modes

Expand Down Expand Up @@ -454,7 +454,7 @@ let ae_fpa_builtins =
fun env s ->
let search_id id =
try
Id.Map.find_exn id fpa_builtins env s
DStd.Id.Map.find_exn id fpa_builtins env s
with Not_found -> `Not_found
in
match s with
Expand All @@ -469,7 +469,7 @@ let smt_fpa_builtins =
Dolmen_type.Base.term_app2 (module Dl.Typer.T) env s f
in
let other_builtins =
Id.Map.empty
DStd.Id.Map.empty
|> add_rounding_modes
in
fun env s ->
Expand All @@ -487,7 +487,7 @@ let smt_fpa_builtins =
| exception Failure _ -> `Not_found
end
| Dl.Typer.T.Id id -> begin
match Id.Map.find_exn id other_builtins env s with
match DStd.Id.Map.find_exn id other_builtins env s with
| e -> e
| exception Not_found -> `Not_found
end
Expand Down Expand Up @@ -1876,7 +1876,7 @@ let make dloc_file acc stmt =
let ns = DStd.Namespace.Decl in
let name = Ty.fresh_hypothesis_name goal_sort in
let decl: _ Typer_Pipe.stmt = {
id = Id.mk ns name;
id = DStd.Id.mk ns name;
contents = `Hyp t; loc; attrs; implicit
}
in
Expand All @@ -1893,7 +1893,7 @@ let make dloc_file acc stmt =
assert false

(* Axiom definitions *)
| { id = Id.{name = Simple name; _}; contents = `Hyp t; loc; attrs;
| { id = DStd.Id.{name = Simple name; _}; contents = `Hyp t; loc; attrs;
implicit=_ } ->
let dloc = DStd.Loc.(loc dloc_file stmt.loc) in
let aloc = DStd.Loc.lexing_positions dloc in
Expand Down
2 changes: 1 addition & 1 deletion src/lib/frontend/frontend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -520,5 +520,5 @@ module Make(SAT : Sat_solver_sig.S) : S with type sat_env = SAT.t = struct
Sat_solver_sig.pp_ae_unknown_reason_opt ur;

| Some model ->
Models.output_concrete_model ppf model
Models.pp ppf model
end
Loading

0 comments on commit f451ee0

Please sign in to comment.