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

Clean up OptimAE #921

Merged
merged 24 commits into from
Dec 6, 2023
Merged

Clean up OptimAE #921

merged 24 commits into from
Dec 6, 2023

Conversation

Halbaroth
Copy link
Collaborator

@Halbaroth Halbaroth commented Oct 31, 2023

This PR refactors the way we manage optimization constraints in
Alt-Ergo.

  • Optimization constraints aren't tag on subformulas anymore. Instead
    we use the MaxSMT syntaxes.
  • We don't support optimization in Alt-Ergo native format. As this
    feature haven't been published, we don't need to deprecated it.
  • We support maximize, minimize and get-objectives. There is no
    support for assert-soft. I think it's out of the scope of this PR.
    Besides, it seems that get-objectives can take arguments in our current implementation of Solving_loop but I didn't find
    any examples using this syntax, thus I silently ignore these arguments.
  • The SAT solver API exposes two new functions: optimize and
    get_objectives which, respectively, register objective function and
    return the current objective model.

@Halbaroth Halbaroth added clean-up optimization This issue is related to optimization in models. labels Oct 31, 2023
@Halbaroth Halbaroth added this to the 2.6.0 milestone Oct 31, 2023
@Halbaroth Halbaroth force-pushed the clean-up-optimae branch 3 times, most recently from 72c682d to 5891fd2 Compare November 3, 2023 11:33
This was referenced Nov 7, 2023
@Halbaroth Halbaroth force-pushed the clean-up-optimae branch 3 times, most recently from 23f0bba to 4188d71 Compare November 16, 2023 20:10
@Halbaroth Halbaroth force-pushed the clean-up-optimae branch 2 times, most recently from 6e56cbb to cb6d88a Compare November 27, 2023 13:52
@Halbaroth Halbaroth force-pushed the clean-up-optimae branch 5 times, most recently from a357a75 to 28c6ba6 Compare November 28, 2023 08:32
@Halbaroth Halbaroth marked this pull request as ready for review November 28, 2023 08:33
@Halbaroth
Copy link
Collaborator Author

Uhm, I thought it was a good idea to hide completely the priority order in the objective model but in fact, users could feed AE with a file like this one:

(set-logic ALL)
(set-option :produce-models true)
(declare-const x Int)
(declare-const y Int)
(assert (<= x 10))
(assert (< y 5))
(maximize x)
(maximize y)
(maximize x)
(check-sat)
(get-model)
(get-objectives)

With the current implementation, the second maximize will be completely ignored and output:

unknown
(
  (define-fun x () Int 10)
  (define-fun y () Real 0.0)
)
(objectives 
  (x 10)
  (y (- 5.0 epsilon))
)

Another tricky example is if we use both maximize and minimize on the same expression. The second one is ignored. Should we print a warning?

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.

Uhm, I thought it was a good idea to hide completely the priority order in the objective model but in fact, users could feed AE with a file like this one:
[..]
Another tricky example is if we use both maximize and minimize on the same expression. The second one is ignored. Should we print a warning?

Yeah, I was going to make a remark on that. We shouldn't print a warning, we should print all the objectives requested by the user in the correct order!

(We might want to also print a warning when we perform optimization under an unbounded/strict objective, which should only occur during model generation if I understand correctly)

Not sure how that's tricky — wouldn't removing the test for an existing function in Objective.Model.add just do The Right Thing™?

@@ -429,6 +437,8 @@ module Make(SAT : Sat_solver_sig.S) : S with type sat_env = SAT.t = struct

let th_assume = wrap_f internal_th_assume

let optimize = handle_sat_exn internal_optimize
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be wrap_f, not handle_sat_exn to avoid using an invalid satML environment (see #946 and related issues).

@@ -604,4 +575,3 @@ let output_concrete_model fmt m =
(* SmtlibCounterExample.output_arrays_counterexample fmt m.arrays; *)

Printer.print_fmt fmt "@]@,)";
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
Printer.print_fmt fmt "@]@,)";
Printer.print_fmt fmt "@]@,)"

src/lib/reasoners/fun_sat.ml Outdated Show resolved Hide resolved
| Unknown -> true
| _ -> false
);
let uf, _ = Uf.add uf e in
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 seem right; we don't return the uf so the added repr is lost.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Uhm, I don't think we need to keep the representative element here. The expression e here isn't a part of our problem but the expression we try to optimize modulo our constraints. Now, I remember why I add this line before

let repr, _ = Uf.find uf e in

The reason is because the function Uf.find fails if the expression have never been added to the union-find before. As the expression can be something completely new, this can happen. Consider for instance the input file:

(set-logic ALL)
(set-option :produce-models true)
(declare-const x Int)
(assert (<= x 10))
(maximize (+ x 5))
(check-sat)
(get-model)
(get-objectives)

The expression (+ x 5) is completely new and the union-find will raise Not_found exception here.

Now if the expression is already knew, we want to get both its representative in the union-find (in the code it's repr) and the semantic values returned by X.make for this expression (in the code it's r1).

Another solution would be add the expression e in the union-find when we call the function optimize of the SAT solver.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we want to get the representative if there is one or the result of X.make otherwise then the right code is probably along the lines of:

let repr, r1 =
  match Uf.find uf e with
  | repr, _ -> repr, Uf.make uf e
  | exception Not_found -> let r, _ = X.make e in r, r

That said, I didn't think about it, but you are right — we should add e in the call to optimize (this is what was done before when Optimize was a symbol). Note that this needs to use Theory.add_term to make sure that all sub-terms are properly added (Uf.add only adds the term itself but not the subterms).

The real reason to do this is that if we do (maximize (bv2nat x)) for instance, and the problem does not otherwise contain (bv2nat x), not adding bv2nat to the theory would lose some reasoning power (because it would not be seen by the relations, and knowledge about it would not be properly propagated).

@@ -2045,17 +2045,35 @@ let case_split env uf ~for_model =
end
| _ -> res

let optimizing_split env uf opt_split =
(* Helper function used in [optimizing_objective] to pick a value
for the polynomial [p] in its interval. We used this function in the case
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
for the polynomial [p] in its interval. We used this function in the case
for the polynomial [p] in its interval. We use this function in the case

Comment on lines 725 to 726
(* let objectives, reset_cs_env =
update_objectives t.objectives assumed gamma in *)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this no longer needed? What happens if an assertion renders an existing objective invalid?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The purpose of update_objectives function was to ensure we add new optimization discovered while exploring a term. At this time, we could have optimization everywhere in formulae. In particular, it means the theory module could ignore an optimization constraint before the underlying formula was involved in a formula of the current trail of the SAT solver. I didn't check, but I guess we could even forget an optimization constraint by backtracking.

If we discover a new constraint, we have to throw away all the case splits. A flag in update_objectives was used to remember that and we call reset_case_split_env if the flag is up.

Now, we feed the SAT solver with all the optimization constraints at once. I thought it was fine but in fact we perform case splits after each assume. Thus we have to reset casesplits after each optimize in Theory.

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 I did! I just forget to remove the dead code commented. :) Thanks for the remark. I will add a comment in optimize.

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, update_objectives is for adding new objectives — I mixed it up in my head with partial_objectives_reset which is used when an objective becomes invalid, thanks for the clarification!

I thought it was fine but in fact we perform case splits after each assume.

Yeah, either after each assume or before matching or after matching depending on the split policy. After each assume is the most aggressive version tho, so I think if we deal with that properly we are good.

I didn't check, but I guess we could even forget an optimization constraint by backtracking.
Now, we feed the SAT solver with all the optimization constraints at once. I thought it was fine but in fact we perform case splits after each assume. Thus we have to reset casesplits after each optimize in Theory.

This remark makes me wonder: previously, we had optimizations in assertions, which are obviously stored in the assertion stack (and so would be normally affected by push and pop), but I am not sure that is still the case in this PR (I didn't see any mechanism that would take care of it, but also was not aware it could be an issue prior to your comment). Might be worth checking -- for instance the following should output 0, not 10.

(set-option :produce-models true)
(set-logic ALL)
(declare-const x Int)
(assert (<= 0 x 10))
(push 1)
(maximize x)
(pop 1)
(minimize x)
(check-sat)
(get-model)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Uhm I thought it was fine because I use the same semantic as the assert but I probably miss something in solving_loop. Thanks for the test.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah dang, I take it that means it does not work then :/ I think it is probably an issue in the Satml_frontend / Satml rather than solving_loop. The way push and pop work in the Satml solver is that we create guards, and assertions within a push/pop assertions are, well, guarded: if the guard is false, the assertion is just ignored.

So for instance the following:

(push 1)
(assert f1)
(check-sat)

is treated as if we had:

(declare-const guard Bool)
(assert (=> guard f1))
(assert guard) ; Generated for all assertions levels that were not popped on (check-sat)
(check-sat)

and the following:

(push 1)
(assert f1)
(pop 1)
(check-sat)

is treated as if we had:

(declare-const guard Bool)
(assert (=> guard f1))
(assert (not guard)) ; Generated on (pop 1)
(check-sat)

and so Th.assume (which is called during propagation) will never be called on f1. But I believe that with the current implementation (from my recollection of it, I did not check in detail) we will always call optimize without taking the guards into account.

In the previous implementation this "just worked" because optimization markers were expressions inside assertions that were not assumed when the guards are false, but now that optimization markers are declarations there is a little bit more work that needs to be duplicated. In fact there is probably a bit of overlap with #901, now that I think about it.

Given that optimization is still experimental (and that you've said you're sick of working on it for so long, which is understandable :) ), I think dropping support for optimization within push/pop in this PR is acceptable. We can then either deal with that as part of #901 (which I think is on track for inclusion in the next release, since postponing #904 freed up quite some time for me) or otherwise in a separate PR; your call.

Copy link
Collaborator Author

@Halbaroth Halbaroth Nov 29, 2023

Choose a reason for hiding this comment

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

I think I'll take it after we solve #901. I'll print a warning if we try to optimize with push and pop. An error isn't necessary here as we still got a correct model but we don't respect the optimization constraint.

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 open an issue #933 and add a warning when we process files involving both optimization constraints and pop and push.

in
aux env sem_facts (List.rev env.choices) new_choices
aux env sem_facts (List.rev env.choices)
(Objective.Model.functions env.objectives, 0) new_choices
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is starting at order 0 here really correct? What if some objectives have been optimized already?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm actually it looks like we are optimizing all objectives again at each case split, that looks wasteful (possibly incorrect, but I don't think so since we use equalities for the splits).

Copy link
Collaborator Author

@Halbaroth Halbaroth Nov 29, 2023

Choose a reason for hiding this comment

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

Let's clarify a bit the previous behaviour and the current one.

  • Before this PR, the function look_for_sat proceeds choices in this order when for_model = false:
    • First, it propagates new choices in the pending queue.
    • Then it try to optimize as much as it can objectives for which we didn't get a best value yet (in the current SAT branch of course). If it see an objective whose the previous value is a limit (+oo, -oo or a strict bound), it tries to optimize it again.
    • If we fail to optimize a bound, we stop in optimizing_objective.
    • Otherwise, it asks theories to generate new case splits and it goes back to the first point.

Now, if we're generating model (so for_model = true), the previous code ignore objectives whose the value is a limit and we keep optimize next objectives (with a lower priority).

This is not what we want. If we got a limit for some objective o, it doesn't make sense to try to optimize objectives with lower priority than o. But in model generation, we want to keep generating model, even if we can fulfill some objectives.

Let's pick an example:

(set-option :produce-models true)
(set-logic ALL)
(declare-const x Int)
(declare-const y Int)
(maximize x)
(minimize y)
(assert (>= y (- 10)))
(assert (>= x 0))
(check-sat)
(get-model)
(assert (<= x 10))
(check-sat)
(get-model)

If you run AE next on it with the command

dune exec -- alt-ergo test.smt2 --optimize --objctives-in-interpretation --frontend legacy --dump-models

AE outputs:

unknown
Returned unknown reason = Incomplete
(
  (define-fun x () Int +oo)
  (define-fun y () Int (- 10))
)

unknown
Returned unknown reason = Incomplete
(
  (define-fun x () Int 10)
  (define-fun y () Int (- 10))
)

We don't expect that AE keep optimizing objectives after x before the first check-sat, but we keep doing it...

Now, if we don't the same on this PR with the command

dune exec -- alt-ergo test2.smt2 --optimize --objectives-in-interpretation

AE outputs:

unknown
(
  (define-fun x () Int 1)
  (define-fun y () Int 0)
)

; File "test2.smt2", line 12, characters 1-12: I don't know (0.0009) (6 steps) (goal g_2)

unknown
(
  (define-fun x () Int 10)
  (define-fun y () Int (- 10))
)

The new code does the right thing... by chance! It's because during each case split phase, we do again all the optimizations, even if we got an infinity value before and we stop optimization if we got an infinity value in optimizing_objective. If the flag for_model is true, we stop also optimization but we keep generate new casesplits.

I add a new function next_unknown in Objective.Model whose the semantic is closed to the old next_optimization:

  exception Found of Function.t * int

  let next_unknown mdl =
    try
      M.iter (fun { f; order } v ->
        match (v : Value.t) with
        | Value _ -> ()
        | Pinfinity | Minfinity | Limit _ -> raise Exit
        | _ -> raise (Found (f, order))
      ) mdl;
      None
    with
    | Found (f, order) -> Some (f, order)
    | Exit -> None

Notice this function isn't very efficient because we keep visiting Value node in the map again and again. The behaviour of Objective.Model is basically a queue with some printers. I guess I will rewrite it with a functional queue but let's keep map now, early optimization is risky.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok, it's still incorrect for this test:

; This test checks if the optimization doesn't stop after trying to
; optimize a strict bound.
(set-option :produce-models true)
(set-logic ALL)
(declare-const x Real)
(declare-const y Real)
; If the SAT solver explores first the right branch of the following OR gate, it
; shouldn't conclude that x cannot be optimized.
(assert (or (<= x 4.0) (< x 1.5)))
(maximize x)
; The current implementation of SatML explores the right branch of OR gates
; first. We add the following line to be sure the optimization feature still
; works after changing the order of branches.
(assert (or (< y 1.5) (<= y 4.0)))
(maximize y)
(check-sat)
(get-model)
(get-objectives)

During the first assert we don't know that y will be bound and we get infinity here. Thus, we have to treat infinity value again after the second assert, otherwise we will print +oo for y. This was explained in a comment of the original OptimAE PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't expect that AE keeps optimize value after x after the first check-sat, but we keep doing it...

I disagree: in that case I fully expect alt-ergo to re-optimize the model because of the new get-sat and the new constraints added by assert since the last check-sat !

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok my example is ambiguous. I was talking of the first check-sat only. I totally agree we have to keep optimize if new constraints are involved.

we continue to produce a model if the flag [for_model] is up. *)
if for_model then
aux env sem_facts acc_choices []
aux env sem_facts acc_choices ([], 0) []
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 this is a behavior change — previously we would keep optimizing further objectives while doing model generation, but now we no longer does (this call to aux goes immediately to generate_choices). Is that intentional?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also as far as I can tell, this means that the case splits in the middle of intervals and the such that we create for infinite/limit cases are never used.

src/lib/reasoners/intervalCalculus.ml Show resolved Hide resolved
in the domain of the polynomial [p]. But we propagate the new
value [value] for this objective. Indeed, we want to be able
to print it while using the statement [get-objective]. *)
middle_value env ~to_max ty p None
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same remark as above; are standard model generation mechanisms failing somehow?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Before this PR, we use a wrapped case-split as input for this function and we have access to the last computed value for the first-order model through this wrapped case-split.

An alternative implementation would be to give this value as an argument of optimizing_objective.

Notice that my middle_value gives a value in the last interval (for the to_max = true case) of the domain of the polynomial p. You told me other solvers try to give a bigger value when we maximize strict bound.

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 this is for that! Makes sense. What I was thinking for that case (and what other solvers do I believe) is add an inequality constraint rather than an equality in case that specific value end up not being feasible. For instance, with a nonlinear objective x * x with x in 1 .. 2range, the range forx * xis1 .. 4(AFAIK Alt-Ergo know this) but if we pick2or3as a value there is no model whereas if we just constrain< 3or> 2` it is.

(I think in this specific case we might go into an infinite loop in the current PR if we actually used this split in look_for_sat, not sure)

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 I suggest to keep the code as it's now. We could make better change later.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure I am fine with keeping that code as is for now, but the code in look_for_sat needs to be fixed to actually use the split during model generation!

@@ -1,8 +1,11 @@
(set-logic ALL)
(set-option :produce-models true)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should happen before (set-logic ...)

)
(objectives
Copy link
Collaborator

Choose a reason for hiding this comment

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

As y cannot be optimized, I believe we should warn the user when he invokes (get-objectives)

This PR refactors the way we manage optimization constraints in
Alt-Ergo.

- Optimization constraints aren't tag on subformulas anymore. Instead
  we use the MaxSMT syntaxes.
- We don't support optimization in Alt-Ergo native format. As this
  feature haven't been published, we don't need to deprecated it.
- We support `maximize`, `minimize` and `get-objectives`. There is no
  support for `assert-soft`. I think it's out of the scope of this PR.
- The SAT solver API exposes two new functions: `optimize` and
  `get_objectives` which, respectively, register objective function and
  return the current objective model.
- The objective values are expressions.
The optimization constraint is wrong if we use it in incremental
mode but it's safe if we use `maximize` and `minimize` at the top level
only.
The value produced by `middle_value` in `intervalCalculus` wasn't
propagate to the CC(X) module in `look_for_sat`. We propagate it now.

I also modify the test `arith7.optimize.smt2` as we cannot use both
incremental mode and optimization constraints.
We don't support yet impure terms or formulae in `maximize` and
`minimize` statements. Let's print a warning message and ignoring
invalid objective functions.
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 we are good with a couple minor omissions noted inline; please fix these before merging!

@@ -350,6 +350,10 @@ let main () =
State.create_key ~pipe:"" "named_terms"
in

let has_incremental : int State.key =
Copy link
Collaborator

Choose a reason for hiding this comment

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

If it's an int, it should not be called has_incremental. I guess two of my comments in the previous round somewhat contradicted each other. Maybe incremental_depth?

(State.get solver_ctx_key st).ctx stmt
in
(* Using both optimization and incremental mode may be wrong if
some optimization constraints aren't at the toplevel. *)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should have a link back to #993

src/lib/reasoners/intervalCalculus.ml Outdated Show resolved Hide resolved
src/lib/reasoners/theory.ml Outdated Show resolved Hide resolved
src/bin/common/solving_loop.ml Outdated Show resolved Hide resolved
Halbaroth and others added 4 commits December 6, 2023 11:38
Co-authored-by: Basile Clément <129742207+bclement-ocp@users.noreply.github.com>
Co-authored-by: Basile Clément <129742207+bclement-ocp@users.noreply.github.com>
Co-authored-by: Basile Clément <129742207+bclement-ocp@users.noreply.github.com>
@Halbaroth Halbaroth enabled auto-merge (squash) December 6, 2023 10:44
@Halbaroth Halbaroth merged commit c1ccd0e into OCamlPro:next Dec 6, 2023
12 checks passed
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
clean-up optimization This issue is related to optimization in models.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Supporting the MaxSMT extension of Dolmen Add support for get-objectives
4 participants