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

Refactoring Enum_rel using domains on class representatives only #1078

Merged
merged 15 commits into from
Apr 4, 2024

Conversation

Halbaroth
Copy link
Collaborator

@Halbaroth Halbaroth commented Mar 26, 2024

This PR refactors the Enum relations in order to use a proper type
for the domains of enum semantic values.

Now, we only store domains for class representatives and I believe that the new
implementation is simpler to understand and to maintain.

I don't use the functor Domains_make of Rel_utils as domain's
propagations performed in Enum_rel are much simpler than the propagations in
the BV theory.

@Halbaroth Halbaroth force-pushed the enum-rel-domains branch 3 times, most recently from afebbd6 to 1944788 Compare April 2, 2024 16:00
@Halbaroth Halbaroth marked this pull request as ready for review April 2, 2024 16:01
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 3, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 3, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Copy link
Collaborator

@bclement-ocp bclement-ocp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the code in this PR is technically correct (the best kind of correct!) and without major flaws; as such, I'd be OK with merging it provided the remarks regarding comments/documentation are addressed.

However, I have concerns regarding regarding long-term maintainability (and some performance issues but those are probably minor) regarding the SimpleDomains_make functor, explained below.

To the best of my understanding, Alt-Ergo currently generates a Subst equality r → rr when r gets assigned to a new representative rr exactly two cases1:

  • r is a leaf (in the sense of X.is_a_leaf), or
  • r is a term representative, i.e. there is a term t in the problem such that r = X.make t = Uf.make uf t

This means that my assertion "if we see r1 = r2 as Other then we will see r1 = rr and r2 = rr as Subst equalities", reproduced here in a comment, is not entirely correct (sorry! I keep forgetting about this edge case) if either r1 or r2 is not a term representative. For the Enum theory it does not matter because all enum semantic values are necessarily term representatives2, but looking forward to #1087 we can have ADTs that are not class term representatives (see below for an example).

This is the reason why the Domains_make functor has a leaves_map field that it uses during substitution (see also discussion in #1040), so that we catch this edge case. SimpleDomains_make does not, and thus will miss domain updates in the presence of such synthetic representatives.

For the enum and ADT theories, this has zero impact on the correctness: the only way to generate synthetic representatives would be if they are argument of an ADT constructor (for instance, an ADT constructor with a bit-vector argument), but once we know the constructor, the unknown domain is the tightest possible! It does mean that the theory will go through different paths depending on whether a synthetic representative was substituted (we will not find it in the map, so we will return its unknown value) or no synthetic representative was substituted (we will find it in the map), which could easily cause subtle bugs in the future.

For these reasons, I think it would be preferrable to either use the more general Domains_make (adding back the propagate function; doing this will be more computationally expensive), or folding the SimpleDomains_make definition into the enum theory and inlining it for that theory specifically. Inlining it for that theory allows some optimisations because we can make use of the remark above (once we know the constructor we know the domain) to avoid looking in the map if we have a constructor (in both find and update). This has the disadvantage that the code needs to be copy-and-pasted from enum to adt, but if the plan is to merge both, that will be an acceptable temporary situation; since the SimpleDomains makes use of some specificity of these theories, it also makes sense for the implementation to be there rather than in the more generic Rel_utils module.

Footnotes

  1. I think there is also a variant of the 2nd case where r results from the AC-completion of term representatives, but it does not really matter here.

  2. Except if users define an AC symbol over enums, but I'd classify this as an AC(X) bug since it impacts many theories, see Preserve mapping between old and new representatives with AC symbols #823

Comment on lines 72 to 75
(* Only Enum values can have a domain. This case can happen since we
don't dispatch the literals processed in [assume] by their types in
the Relation module. *)
invalid_arg "unknown"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this case can happen, it must not raise an Invalid_argument exception as per the documentation of Invalid_argument:

As a general rule, this exception should not be caught, it denotes a programming error and the code should be modified not to trigger it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to update, but it looks like this case can no longer happen because we do check the types before calling Domains.add, so the code is correct but the comment no longer is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why do you use invalid_arg in the very same situation in Bitv_rel?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because in the Bitv_rel case it can't happen (there is a check for the type)! In fact, as noted in my 2nd comment, it is also the case here; the code is right but the comment that says "this case can happen" is wrong.

Comment on lines 95 to 97
let fold_leaves _f _rr _d _ = assert false

let map_leaves _f _rr _ = assert false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the following would be correct (e.g. would allow usage with Domains_make):

Suggested change
let fold_leaves _f _rr _d _ = assert false
let map_leaves _f _rr _ = assert false
let fold_leaves f r d acc = f r d acc
let map_leaves f r acc = f r acc

Comment on lines 218 to 219
(* Needed for models generation because fresh terms are not added with the
function add. *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the function needed for models generation is add_rec? This comment is on add.

src/lib/reasoners/enum_rel.ml Show resolved Hide resolved
returned domain is identical to the domain of [d], only the
justifications are changed. *)
val unknown : X.r -> t
(** [unknown r] returns a full domain for values of the semantic value [r]. *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes the documentation (and the function unknown) unclear: a "full domain" means that all values are possible, so it shouldn't depend on the semantic value.

What this does currently is that it returns a full domain in the Bitv theory, and either a full domain or a singleton domain for the Enum theory. It would be more foolproof to keep the unknown function as-is and to add a val create : X.r -> t (or val default) that returns a default domain for the representative r (it is a bit weird that unknown r is able to represent a precise singleton domain which is not "unknown" at all).

(Essentially this boils down to a difference in the way that the Domains_make and SimpleDomains_make functors want to use this function: Domains_make wants to call it on the leaves, then use map_leaves to build up a larger combined domain; SimpleDomains_make wants to call it on every value.)

Comment on lines 264 to 265
if Domain.cardinal d = 1 then
let c = Domain.choose d in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this (and assume_distinct above) might make the intent clearer if written:

match Domain.as_singleton d with
| Some c -> ...
| None -> eqs

Comment on lines 663 to 664
(** [update r d t] replaces the domain of [r] in [t] by [d]. The
representative [r] is marked [changed] after this call. *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not replace it, it intersects it, and r is only marked changed if this causes the domain to change. The documentation should also make it clear that the new domain must have had any explanations justifying that it applies to r already added.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, Domain.update is only used in assume_distinct where nd is always a subset of the old domain, so we don't need to perform an intersection here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the code and the doc disagree fixing either if fine by me :)

(Note that skipping the intersection here is a bit risky because we could end up widening a domain, which is a completeness bug, so this should be called out in the documentation)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a heavy assert to check we never update a domain with another one that isn't a subset.


let add env _ r _ = add_aux env r, []
let case_split_limit env n =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case_split_limit makes it sound like it will be true if the limit is reached (I understood this on first read and was confused). Maybe call it case_split_ok or can_split?

Comment on lines 702 to 706
match MX.find r t.domains with
| _ -> t
| exception Not_found ->
let nd = Domain.unknown r in
internal_update r nd t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the function add can be a no-op; there is no need to add unknown domains since that is the default value returned by get, and the unknown r domain should be stable by propagation (unless some constraint applies, in which case the constraint will trigger the propagation).

Copy link
Collaborator Author

@Halbaroth Halbaroth Apr 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add this function for sake of completeness. If you replace it by no-op, you got regressions. For instance the following problem from the test suite:

type t = A | B

logic f: t , int -> int

goal g8:
  forall x:t.
  forall y:int.
  f(x,y) = f(A,y) or f(x,y) = f(B,y)

is unsat with the current add operation but we got unknown with no-op.
The reason is simple. The map env.domains has two roles. It saves the domains of enum semantic values AND it saves the set of seen semantic values.

In the above test, x is never seen in a constraint before the first case-split round. If we don't add a domain for it in env.domains, the function Domains.fold won't see it while performing case-split and we lost the opportunity to discover the inconsistency here.

We can:

  • add a set in the environment of the theory to save seen semantic values and fold on it during the case splits;
  • keep the current implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it is also used for case splits, that makes sense, thanks for checking it out. I think it would be useful to note that this is useful for case splits in a comment here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it wasn't clear at all ;)

Comment on lines 718 to 719
let nd = Domain.intersect ~ex:Explanation.empty (Domain.unknown r) d in
internal_update r nd t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If nd is equal to Domain.unknown r then there is nothing to do, or at least Domain.unknown r should be used instead (I think this is important to make sure domains associated with constants always have an empty explanation).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that we can replace this implementation by the following one:

  let update r d t =
    let od = get r t in
    let nd = Domain.intersect ~ex:Explanation.empty od d in
    if Domain.equal od nd then
      t
    else
      internal_update r nd t

The update function is only used in assume_distinct.
Now, Domain.equal od nd is true if and only if both od and nd are the default domain for the type of r. If r isn't in the map t.domains, this implementation doesn't add it to the map but I think it's ok.

Actually, add_rec ensures that all the enum semantic values of the current context are in the map t.domains.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think this is important to make sure domains associated with constants always have an empty explanation).

To my understanding, the previous implementation of update could add unnecessary explanations. Technically, it's correct but if we want to use explanations to produce a proof for instance, we could got useless hypotheses in this proof, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, using get here should work and is simpler.

Unnecessary explanations translate to useless hypotheses in the proof, yes (depending on the way you see it, it is either useless hypotheses in the proof of the current branch, or unnecessary disjunctions in the proof of the user's statement, where we repeat the same sub-proof in both branches).

@bclement-ocp
Copy link
Collaborator

To clarify the type of cases I have in mind when writing the comment above, I believe that using the SimpleDomains_make functor for the ADT theory and this test case:

(set-logic ALL)
(declare-datatype Opt_BV ((None) (Some (val (_ BitVec 8)))))
(declare-const x (_ BitVec 8))
(declare-const y Opt_BV)
(assert (= y (Some x)))
(assert (= ((_ extract 0 0) x) #b0))
(assert (= ((_ extract 1 1) x) #b0))
(check-sat)

would result in a bogus entry in the table of the form Some(val : .kX[7] @ 0[1]) -> Some with a mapping .kX[7] -> .kY[6] @ 0[1] in the union-find.

@Halbaroth
Copy link
Collaborator Author

For these reasons, I think it would be preferable to either use the more general Domains_make (adding back the propagate function; doing this will be more computationally expensive), or folding the SimpleDomains_make definition into the enum theory and inlining it for that theory specifically. Inlining it for that theory allows some optimizations because we can make use of the remark above (once we know the constructor we know the domain) to avoid looking in the map if we have a constructor (in both find and update). This has the disadvantage that the code needs to be copy-and-pasted from enum to adt, but if the plan is to merge both, that will be an acceptable temporary situation; since the SimpleDomains makes use of some specificity of these theories, it also makes sense for the implementation to be there rather than in the more generic Rel_utils module.

I think that inlining the functor is the best choice here.

@Halbaroth
Copy link
Collaborator Author

Halbaroth commented Apr 4, 2024

Inlining it for that theory allows some optimisations because we can make use of the remark above (once we know the constructor we know the domain) to avoid looking in the map if we have a constructor (in both find and update).

I'm no sure it's correct to do this optimization. As we only store domains for the current class representatives, we cannot return the default domain when we see a constructor. Let's imagine we have a semantic value r with the default domain in our map and after some computation in CC(X), we discover that r has to be equal to the constructor c. In our map, we substitute the r key by c but the explanation of this semantic value shouldn't be empty! We have to explain why the domain of r represented by the c key is a singleton. So I believe we should keep this implementation:

  let add r t =
    match MX.find r t.domains with
    | _ -> t
    | exception Not_found ->
      let nd = Domain.default r in
      internal_update r nd t

  let get r t =
    try MX.find r t.domains
    with Not_found -> Domain.default r

@bclement-ocp
Copy link
Collaborator

I am no sure it's correct to do this optimization. As we only store domains for the current class representative, we cannot return the default domain when we see a constructor. Let's imagine we have a semantic value r with the default domain in our map and after some computation in CC(X), we discover that r has to be equal to the constructor c. In our map, we substitute the r key by c but the explanation of this semantic value shouldn't be empty!

The semantics of an entry x → d in the map is that the domain for x is d, and the explanation stored in d is a justification of that fact. After substitution, the key in the map for which we are storing a domain is c, no longer r. The domain of c being the singleton { c } is a tautology, so we don't need to keep any explanations from the domain of r. The justification for r being equal to c is stored in the union-find data structure.

@bclement-ocp
Copy link
Collaborator

More formally: an entry x → d in the map is valid iff the implication explanation(d) ⇒ x ∈ d is true at level 0. The formula c ∈ { c } is always true, so an entry c → { c } in the map is always valid without additional explanations.

This PR refactors the `Enum` relations in order to use a proper type
for the domains of enum semantic values.

Now, we only store domains for class representatives and I believe that the new
implementation is simpler to understand and to maintain.

I don't use the functor `Domains_make` of `Rel_utils` as domain's
propagations performed in `Enum_rel` are much simpler than the propagations in
the BV theory.
The previous implementation of `Domain.update` could replace a default
domain (with the empty explanation) by a default one with a non-empty
explanation. There is no reason to add these extra explanations.

This new implementation doesn't update the map `t.domains` if the
intersection is a default domain. It means `update` doesn't add a domain
if `d` is a default domain and `r` isn't in the map, which is ok as we
ensure that all seen semantic values are added to `t.domains` in `assume`.
The `unknown` function in `Enum_rel` doesn't return the full domain
for constructor semantic values but the tightest possible domain for it.
The `default` name is more appropriate for this behaviour.
As we inlined the function `SimpleDomains_make` in `Enum_rel`, we can
write more efficient code for this theory.

We don't need to look in the map `t.domains` for constructor semantic
values as we always produce the same default domain for them, that is
a singleton without any explanation.
We don't need to perform an intersection in `Domain.update` as we always
call it on domains that are subsets of the old ones.
Copy link
Collaborator

@bclement-ocp bclement-ocp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are still a couple places where constant entries into the map slip through the cracks but otherwise looks good 👍

Comment on lines 139 to 141
match MX.find r t.domains with
| _ -> t
| exception Not_found ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
match MX.find r t.domains with
| _ -> t
| exception Not_found ->
if MX.mem r t.domains then t else

Comment on lines 142 to 144
(* We have to add a default domain if the key `r` isn't in map in order to
be sure that the case-split mechanism will attempt to choose a value
for it. *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only true if r is not a constructor, no? We ignore Cons values in both case_split and get so I don't think entries for them are ever used.

| exception Not_found -> d
in
let t = remove r t in
internal_update nr nnd t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update should be used rather than internal_update to avoid adding unnecessary explanations (and also avoid storing domains for constants)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't store at all domains for the constructor, we should use get in subst as follows to get the appropriate
intersection:

  let subst ~ex r nr t =
    match MX.find r t.domains with
    | d ->
      let nd = Domain.intersect ~ex d (get nr t) in
      let t = remove r t in
      update nr nd t

    | exception Not_found -> t

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right! In fact this:

      let nnd =
        match MX.find nr t.domains with
        | nd -> Domain.intersect ~ex d nd
        | exception Not_found -> d
      in

was a soundness bug because update does not intersect and so we lose the explanation ex if nr is not in t.domains.

Copy link
Collaborator Author

@Halbaroth Halbaroth Apr 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also rename update into tighten. update isn't a meaningful name.

@Halbaroth Halbaroth enabled auto-merge (squash) April 4, 2024 14:50
@Halbaroth Halbaroth merged commit ef4119e into OCamlPro:next Apr 4, 2024
15 checks passed
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 4, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 5, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 5, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 5, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 5, 2024
The PR OCamlPro#1078 introduces a soundness bug in `assume_distinct`. We have
to propagate explanations of singleton domains, otherwise we may raise
Inconsistency with an empty explanation.

Add a test that caught the bug.
Halbaroth added a commit that referenced this pull request Apr 5, 2024
The PR #1078 introduces a soundness bug in `assume_distinct`. We have
to propagate explanations of singleton domains, otherwise we may raise
Inconsistency with an empty explanation.

Add a test that caught the bug.
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 8, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 8, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 13, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit to Halbaroth/alt-ergo that referenced this pull request Apr 15, 2024
This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR OCamlPro#1078
Halbaroth added a commit that referenced this pull request Apr 22, 2024
)

This PR refactors the `Adt` relations in order to use a proper type
for the domains of enum semantic values.
See PR #1078
@bclement-ocp bclement-ocp added this to the 2.6.0 milestone Jul 11, 2024
bclement-ocp added a commit to bclement-ocp/opam-repository that referenced this pull request Sep 24, 2024
CHANGES:

### Command-line interface

 - Enable FPA theory by default (OCamlPro/alt-ergo#1177)
 - Remove deprecated output channels (OCamlPro/alt-ergo#782)
 - Deprecate the --use-underscore since it produces models that are not SMT-LIB
   compliant (OCamlPro/alt-ergo#805)
 - Add --dump-models-on to dump models on a specific output channel (OCamlPro/alt-ergo#838)
 - Use consistent return codes (OCamlPro/alt-ergo#842)
 - Add --continue-on-error flag to set the SMT-LIB error behavior (OCamlPro/alt-ergo#853)
 - Make dolmen the default value for the --frontend option (OCamlPro/alt-ergo#857)
 - Restore functionality to broken `--profiling` option (OCamlPro/alt-ergo#947)
 - Add bare-bones support for interactive input in SMT-LIB format (OCamlPro/alt-ergo#949)
 - Less confusing behavior on timeout (OCamlPro/alt-ergo#982, OCamlPro/alt-ergo#984)
 - Add `--strict` option for SMT-LIB compliant mode (OCamlPro/alt-ergo#916, OCamlPro/alt-ergo#1133)
 - Deprecate `sum`, `typing` and `warnings` debug flags (OCamlPro/alt-ergo#1204)

### SMT-LIB support

 - Add support for the many new SMT-LIB commands (OCamlPro/alt-ergo#837, OCamlPro/alt-ergo#848, OCamlPro/alt-ergo#852, OCamlPro/alt-ergo#863, OCamlPro/alt-ergo#911,
   OCamlPro/alt-ergo#942, OCamlPro/alt-ergo#945, OCamlPro/alt-ergo#961, OCamlPro/alt-ergo#975, OCamlPro/alt-ergo#1069)
 - Expose the FPA rounding builtin in the SMT-LIB format (OCamlPro/alt-ergo#876, OCamlPro/alt-ergo#1135)
 - Allow changing the SAT solver using (set-option) (OCamlPro/alt-ergo#880)
 - Add support for the `:named` attribute (OCamlPro/alt-ergo#957)
 - Add support for quoted identifiers (OCamlPro/alt-ergo#909, OCamlPro/alt-ergo#972)
 - Add support for naming lemmas in SMT-LIB syntax (OCamlPro/alt-ergo#1141, OCamlPro/alt-ergo#1143)

### Model generation

 - Use post-solve SAT environment in model generation, fixing issues where
   incorrect models were generated (OCamlPro/alt-ergo#789)
 - Restore support for records in models (OCamlPro/alt-ergo#793)
 - Use abstract values instead of dummy values in models where the
   actual value does not matter (OCamlPro/alt-ergo#804, OCamlPro/alt-ergo#835)
 - Use fresh names for all abstract values to prevent accidental captures (OCamlPro/alt-ergo#811)
 - Add support for model generation with the default CDCL solver (OCamlPro/alt-ergo#829)
 - Support model generation for the BV theory (OCamlPro/alt-ergo#841, OCamlPro/alt-ergo#968)
 - Add support for optimization (MaxSMT / OptiSMT) with
   lexicographic Int and Real objectives (OCamlPro/alt-ergo#861, OCamlPro/alt-ergo#921)
 - Add a SMT-LIB printer for expressions (OCamlPro/alt-ergo#952, OCamlPro/alt-ergo#981, OCamlPro/alt-ergo#1082, OCamlPro/alt-ergo#931, OCamlPro/alt-ergo#932)
 - Ensure models have a value for all constants in the problem (OCamlPro/alt-ergo#1019)
 - Fix a rare soundness issue with integer constraints when model generation is
   enabled (OCamlPro/alt-ergo#1025)
 - Support model generation for the ADT theory (OCamlPro/alt-ergo#1093, OCamlPro/alt-ergo#1153)

### Theory reasoning

 - Add word-level propagators for the BV theory (OCamlPro/alt-ergo#944, OCamlPro/alt-ergo#1004, OCamlPro/alt-ergo#1007, OCamlPro/alt-ergo#1010,
   OCamlPro/alt-ergo#1011, OCamlPro/alt-ergo#1012, OCamlPro/alt-ergo#1040, OCamlPro/alt-ergo#1044, OCamlPro/alt-ergo#1054, OCamlPro/alt-ergo#1055, OCamlPro/alt-ergo#1056, OCamlPro/alt-ergo#1057, OCamlPro/alt-ergo#1065, OCamlPro/alt-ergo#1073, OCamlPro/alt-ergo#1144,
   OCamlPro/alt-ergo#1152)
 - Add interval domains and arithmetic propagators for the BV theory (OCamlPro/alt-ergo#1058,
   OCamlPro/alt-ergo#1083, OCamlPro/alt-ergo#1084, OCamlPro/alt-ergo#1085)
 - Native support for bv2nat of bit-vector normal forms (OCamlPro/alt-ergo#1154)
 - Fix incompleteness issues in the BV solver (OCamlPro/alt-ergo#978, OCamlPro/alt-ergo#979)
 - Abstract more arguments of AC symbols to avoid infinite loops when
   they contain other AC symbols (OCamlPro/alt-ergo#990)
 - Do not make irrelevant decisions in CDCL solver, improving
   performance slightly (OCamlPro/alt-ergo#1041)
 - Rewrite the ADT theory to use domains and integrate the enum theory into the
   ADT theory (OCamlPro/alt-ergo#1078, OCamlPro/alt-ergo#1086, OCamlPro/alt-ergo#1087, OCamlPro/alt-ergo#1091, OCamlPro/alt-ergo#1094, OCamlPro/alt-ergo#1138)
 - Rewrite the Intervals module entirely (OCamlPro/alt-ergo#1108)
 - Add maximize/minimize terms for matching (OCamlPro/alt-ergo#1166)
 - Internalize `sign_extend` and `repeat` (OCamlPro/alt-ergo#1192)
 - Run cross-propagators to completion (OCamlPro/alt-ergo#1221)
 - Support binary distinct on arbitrary bit-widths (OCamlPro/alt-ergo#1222)
 - Only perform optimization when building a model (OCamlPro/alt-ergo#1224)
 - Make sure domains do not overflow the default domain (OCamlPro/alt-ergo#1225)
 - Do not build unnormalized values in `zero_extend` (OCamlPro/alt-ergo#1226)

### Internal/library changes

 - Rewrite the Vec module (OCamlPro/alt-ergo#607)
 - Move printer definitions closer to type definitions (OCamlPro/alt-ergo#808)
 - Mark proxy names as reserved (OCamlPro/alt-ergo#836)
 - Use a Zarith-based representation for numbers and bit-vectors (OCamlPro/alt-ergo#850, OCamlPro/alt-ergo#943)
 - Add native support for (bvnot) in the BV solver (OCamlPro/alt-ergo#856)
 - Add constant propagators for partially interpreted functions (OCamlPro/alt-ergo#869)
 - Remove `Util.failwith` in favor of `Fmt.failwith` (OCamlPro/alt-ergo#872)
 - Add more `Expr` smart constructors (OCamlPro/alt-ergo#877, OCamlPro/alt-ergo#878)
 - Do not use existential variables for integer division (OCamlPro/alt-ergo#881)
 - Preserve `Subst` literals to prevent accidental incompleteness (OCamlPro/alt-ergo#886)
 - Properly start timers (OCamlPro/alt-ergo#924)
 - Compute a concrete representation of a model instead of performing (OCamlPro/alt-ergo#925)
 - Allow direct access to the SAT API in the Alt-Ergo library computations
   during printing (OCamlPro/alt-ergo#927)
 - Better handling for step limit (OCamlPro/alt-ergo#936)
 - Add a generic option manager to deal with the dolmen state (OCamlPro/alt-ergo#951)
 - Expose an imperative SAT API in the Alt-Ergo library (OCamlPro/alt-ergo#962)
 - Keep track of the SMT-LIB mode (OCamlPro/alt-ergo#971)
 - Add ability to decide on semantic literals (OCamlPro/alt-ergo#1027, OCamlPro/alt-ergo#1118)
 - Preserve trigger order when parsing quantifiers with multiple trigger
   (OCamlPro/alt-ergo#1046).
 - Store domains inside the union-find module (OCamlPro/alt-ergo#1119)
 - Remove some polymorphic hashtables (OCamlPro/alt-ergo#1219)

### Build and integration

 - Drop support for OCaml <4.08.1 (OCamlPro/alt-ergo#803)
 - Use dune-site for the inequalities plugins. External pluginsm ust now be
   registered through the dune-site plugin mechanism in the
   `(alt-ergo plugins)` site to be picked up by Alt-Ergo (OCamlPro/alt-ergo#1049).
 - Add a release workflow (OCamlPro/alt-ergo#827)
 - Add a Windows workflow (OCamlPro/alt-ergo#1203)
 - Mark the dune.inc file as linguist-generated to avoid huge diffs (OCamlPro/alt-ergo#830)
 - Use GitHub Actions badges in the README (OCamlPro/alt-ergo#882)
 - Use `dune build @check` to build the project (OCamlPro/alt-ergo#887)
 - Enable warnings as errors on the CI (OCamlPro/alt-ergo#888)
 - Uniformization of internal identifiers generation (OCamlPro/alt-ergo#905, OCamlPro/alt-ergo#918)
 - Use an efficient `String.starts_with` implementation (OCamlPro/alt-ergo#912)
 - Fix the Makefile (OCamlPro/alt-ergo#914)
 - Add `Logs` dependency (OCamlPro/alt-ergo#1206)
 - Use `dynamic_include` to include the generated file `dune.inc` (OCamlPro/alt-ergo#1199)
 - Support Windows (OCamlPro/alt-ergo#1184,OCamlPro/alt-ergo#1189,OCamlPro/alt-ergo#1195,OCamlPro/alt-ergo#1199,OCamlPro/alt-ergo#1200)
 - Wrap the library `Alt_ergo_prelude` (OCamlPro/alt-ergo#1223)

### Testing

 - Use --enable-assertions in tests (OCamlPro/alt-ergo#809)
 - Add a test for push/pop (OCamlPro/alt-ergo#843)
 - Use the CDCL solver when testing model generation (OCamlPro/alt-ergo#938)
 - Do not test .smt2 files with the legacy frontend (OCamlPro/alt-ergo#939)
 - Restore automatic creation of .expected files (OCamlPro/alt-ergo#941)

### Documentation

 - Add a new example for model generation (OCamlPro/alt-ergo#826)
 - Add a Pygments lexer for the Alt-Ergo native language (OCamlPro/alt-ergo#862)
 - Update the current authors (OCamlPro/alt-ergo#865)
 - Documentation of the `Enum` theory (OCamlPro/alt-ergo#871)
 - Document `Th_util.lit_origin` (OCamlPro/alt-ergo#915)
 - Document the CDCL-Tableaux solver (OCamlPro/alt-ergo#995)
 - Document Windows support (OCamlPro/alt-ergo#1216)
 - Remove instructions to install Alt-Ergo on Debian (OCamlPro/alt-ergo#1217)
 - Document optimization feature (OCamlPro/alt-ergo#1231)
tjammer pushed a commit to tjammer/opam-repository that referenced this pull request Sep 24, 2024
CHANGES:

### Command-line interface

 - Enable FPA theory by default (OCamlPro/alt-ergo#1177)
 - Remove deprecated output channels (OCamlPro/alt-ergo#782)
 - Deprecate the --use-underscore since it produces models that are not SMT-LIB
   compliant (OCamlPro/alt-ergo#805)
 - Add --dump-models-on to dump models on a specific output channel (OCamlPro/alt-ergo#838)
 - Use consistent return codes (OCamlPro/alt-ergo#842)
 - Add --continue-on-error flag to set the SMT-LIB error behavior (OCamlPro/alt-ergo#853)
 - Make dolmen the default value for the --frontend option (OCamlPro/alt-ergo#857)
 - Restore functionality to broken `--profiling` option (OCamlPro/alt-ergo#947)
 - Add bare-bones support for interactive input in SMT-LIB format (OCamlPro/alt-ergo#949)
 - Less confusing behavior on timeout (OCamlPro/alt-ergo#982, OCamlPro/alt-ergo#984)
 - Add `--strict` option for SMT-LIB compliant mode (OCamlPro/alt-ergo#916, OCamlPro/alt-ergo#1133)
 - Deprecate `sum`, `typing` and `warnings` debug flags (OCamlPro/alt-ergo#1204)

### SMT-LIB support

 - Add support for the many new SMT-LIB commands (OCamlPro/alt-ergo#837, OCamlPro/alt-ergo#848, OCamlPro/alt-ergo#852, OCamlPro/alt-ergo#863, OCamlPro/alt-ergo#911,
   OCamlPro/alt-ergo#942, OCamlPro/alt-ergo#945, OCamlPro/alt-ergo#961, OCamlPro/alt-ergo#975, OCamlPro/alt-ergo#1069)
 - Expose the FPA rounding builtin in the SMT-LIB format (OCamlPro/alt-ergo#876, OCamlPro/alt-ergo#1135)
 - Allow changing the SAT solver using (set-option) (OCamlPro/alt-ergo#880)
 - Add support for the `:named` attribute (OCamlPro/alt-ergo#957)
 - Add support for quoted identifiers (OCamlPro/alt-ergo#909, OCamlPro/alt-ergo#972)
 - Add support for naming lemmas in SMT-LIB syntax (OCamlPro/alt-ergo#1141, OCamlPro/alt-ergo#1143)

### Model generation

 - Use post-solve SAT environment in model generation, fixing issues where
   incorrect models were generated (OCamlPro/alt-ergo#789)
 - Restore support for records in models (OCamlPro/alt-ergo#793)
 - Use abstract values instead of dummy values in models where the
   actual value does not matter (OCamlPro/alt-ergo#804, OCamlPro/alt-ergo#835)
 - Use fresh names for all abstract values to prevent accidental captures (OCamlPro/alt-ergo#811)
 - Add support for model generation with the default CDCL solver (OCamlPro/alt-ergo#829)
 - Support model generation for the BV theory (OCamlPro/alt-ergo#841, OCamlPro/alt-ergo#968)
 - Add support for optimization (MaxSMT / OptiSMT) with
   lexicographic Int and Real objectives (OCamlPro/alt-ergo#861, OCamlPro/alt-ergo#921)
 - Add a SMT-LIB printer for expressions (OCamlPro/alt-ergo#952, OCamlPro/alt-ergo#981, OCamlPro/alt-ergo#1082, OCamlPro/alt-ergo#931, OCamlPro/alt-ergo#932)
 - Ensure models have a value for all constants in the problem (OCamlPro/alt-ergo#1019)
 - Fix a rare soundness issue with integer constraints when model generation is
   enabled (OCamlPro/alt-ergo#1025)
 - Support model generation for the ADT theory (OCamlPro/alt-ergo#1093, OCamlPro/alt-ergo#1153)

### Theory reasoning

 - Add word-level propagators for the BV theory (OCamlPro/alt-ergo#944, OCamlPro/alt-ergo#1004, OCamlPro/alt-ergo#1007, OCamlPro/alt-ergo#1010,
   OCamlPro/alt-ergo#1011, OCamlPro/alt-ergo#1012, OCamlPro/alt-ergo#1040, OCamlPro/alt-ergo#1044, OCamlPro/alt-ergo#1054, OCamlPro/alt-ergo#1055, OCamlPro/alt-ergo#1056, OCamlPro/alt-ergo#1057, OCamlPro/alt-ergo#1065, OCamlPro/alt-ergo#1073, OCamlPro/alt-ergo#1144,
   OCamlPro/alt-ergo#1152)
 - Add interval domains and arithmetic propagators for the BV theory (OCamlPro/alt-ergo#1058,
   OCamlPro/alt-ergo#1083, OCamlPro/alt-ergo#1084, OCamlPro/alt-ergo#1085)
 - Native support for bv2nat of bit-vector normal forms (OCamlPro/alt-ergo#1154)
 - Fix incompleteness issues in the BV solver (OCamlPro/alt-ergo#978, OCamlPro/alt-ergo#979)
 - Abstract more arguments of AC symbols to avoid infinite loops when
   they contain other AC symbols (OCamlPro/alt-ergo#990)
 - Do not make irrelevant decisions in CDCL solver, improving
   performance slightly (OCamlPro/alt-ergo#1041)
 - Rewrite the ADT theory to use domains and integrate the enum theory into the
   ADT theory (OCamlPro/alt-ergo#1078, OCamlPro/alt-ergo#1086, OCamlPro/alt-ergo#1087, OCamlPro/alt-ergo#1091, OCamlPro/alt-ergo#1094, OCamlPro/alt-ergo#1138)
 - Rewrite the Intervals module entirely (OCamlPro/alt-ergo#1108)
 - Add maximize/minimize terms for matching (OCamlPro/alt-ergo#1166)
 - Internalize `sign_extend` and `repeat` (OCamlPro/alt-ergo#1192)
 - Run cross-propagators to completion (OCamlPro/alt-ergo#1221)
 - Support binary distinct on arbitrary bit-widths (OCamlPro/alt-ergo#1222)
 - Only perform optimization when building a model (OCamlPro/alt-ergo#1224)
 - Make sure domains do not overflow the default domain (OCamlPro/alt-ergo#1225)
 - Do not build unnormalized values in `zero_extend` (OCamlPro/alt-ergo#1226)

### Internal/library changes

 - Rewrite the Vec module (OCamlPro/alt-ergo#607)
 - Move printer definitions closer to type definitions (OCamlPro/alt-ergo#808)
 - Mark proxy names as reserved (OCamlPro/alt-ergo#836)
 - Use a Zarith-based representation for numbers and bit-vectors (OCamlPro/alt-ergo#850, OCamlPro/alt-ergo#943)
 - Add native support for (bvnot) in the BV solver (OCamlPro/alt-ergo#856)
 - Add constant propagators for partially interpreted functions (OCamlPro/alt-ergo#869)
 - Remove `Util.failwith` in favor of `Fmt.failwith` (OCamlPro/alt-ergo#872)
 - Add more `Expr` smart constructors (OCamlPro/alt-ergo#877, OCamlPro/alt-ergo#878)
 - Do not use existential variables for integer division (OCamlPro/alt-ergo#881)
 - Preserve `Subst` literals to prevent accidental incompleteness (OCamlPro/alt-ergo#886)
 - Properly start timers (OCamlPro/alt-ergo#924)
 - Compute a concrete representation of a model instead of performing (OCamlPro/alt-ergo#925)
 - Allow direct access to the SAT API in the Alt-Ergo library computations
   during printing (OCamlPro/alt-ergo#927)
 - Better handling for step limit (OCamlPro/alt-ergo#936)
 - Add a generic option manager to deal with the dolmen state (OCamlPro/alt-ergo#951)
 - Expose an imperative SAT API in the Alt-Ergo library (OCamlPro/alt-ergo#962)
 - Keep track of the SMT-LIB mode (OCamlPro/alt-ergo#971)
 - Add ability to decide on semantic literals (OCamlPro/alt-ergo#1027, OCamlPro/alt-ergo#1118)
 - Preserve trigger order when parsing quantifiers with multiple trigger
   (OCamlPro/alt-ergo#1046).
 - Store domains inside the union-find module (OCamlPro/alt-ergo#1119)
 - Remove some polymorphic hashtables (OCamlPro/alt-ergo#1219)

### Build and integration

 - Drop support for OCaml <4.08.1 (OCamlPro/alt-ergo#803)
 - Use dune-site for the inequalities plugins. External pluginsm ust now be
   registered through the dune-site plugin mechanism in the
   `(alt-ergo plugins)` site to be picked up by Alt-Ergo (OCamlPro/alt-ergo#1049).
 - Add a release workflow (OCamlPro/alt-ergo#827)
 - Add a Windows workflow (OCamlPro/alt-ergo#1203)
 - Mark the dune.inc file as linguist-generated to avoid huge diffs (OCamlPro/alt-ergo#830)
 - Use GitHub Actions badges in the README (OCamlPro/alt-ergo#882)
 - Use `dune build @check` to build the project (OCamlPro/alt-ergo#887)
 - Enable warnings as errors on the CI (OCamlPro/alt-ergo#888)
 - Uniformization of internal identifiers generation (OCamlPro/alt-ergo#905, OCamlPro/alt-ergo#918)
 - Use an efficient `String.starts_with` implementation (OCamlPro/alt-ergo#912)
 - Fix the Makefile (OCamlPro/alt-ergo#914)
 - Add `Logs` dependency (OCamlPro/alt-ergo#1206)
 - Use `dynamic_include` to include the generated file `dune.inc` (OCamlPro/alt-ergo#1199)
 - Support Windows (OCamlPro/alt-ergo#1184,OCamlPro/alt-ergo#1189,OCamlPro/alt-ergo#1195,OCamlPro/alt-ergo#1199,OCamlPro/alt-ergo#1200)
 - Wrap the library `Alt_ergo_prelude` (OCamlPro/alt-ergo#1223)

### Testing

 - Use --enable-assertions in tests (OCamlPro/alt-ergo#809)
 - Add a test for push/pop (OCamlPro/alt-ergo#843)
 - Use the CDCL solver when testing model generation (OCamlPro/alt-ergo#938)
 - Do not test .smt2 files with the legacy frontend (OCamlPro/alt-ergo#939)
 - Restore automatic creation of .expected files (OCamlPro/alt-ergo#941)

### Documentation

 - Add a new example for model generation (OCamlPro/alt-ergo#826)
 - Add a Pygments lexer for the Alt-Ergo native language (OCamlPro/alt-ergo#862)
 - Update the current authors (OCamlPro/alt-ergo#865)
 - Documentation of the `Enum` theory (OCamlPro/alt-ergo#871)
 - Document `Th_util.lit_origin` (OCamlPro/alt-ergo#915)
 - Document the CDCL-Tableaux solver (OCamlPro/alt-ergo#995)
 - Document Windows support (OCamlPro/alt-ergo#1216)
 - Remove instructions to install Alt-Ergo on Debian (OCamlPro/alt-ergo#1217)
 - Document optimization feature (OCamlPro/alt-ergo#1231)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants