-
Notifications
You must be signed in to change notification settings - Fork 33
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
Complete model #1019
Complete model #1019
Changes from 1 commit
b29a119
959bf7b
8a556a4
3e2d501
6e499aa
02208a1
e07bfa0
b073017
ad415e5
14e729d
c65d8f2
359ac56
98899b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
This PR fixes the issue #778. The suggested solution by this PR is as follows: - Collect user-declared symbols in `D_cnf`; - As the function `make` of the module `D_cnf` returns a list of commands, we add a new command `Decl` in `Frontend` to declare symbols; - The declared symbols are given to the SAT solver through a new function `declaration` in `sat_solver_sig`. - These symbols are collected in vectors and we keep indexes in another PR in order to manage properly the push/pop mechanism. - Finally the declared symbols are given to `Uf` and we create the empty model with them. Another annoying point comes from the current datastructure used in `ModelMap`. The type of `ModelMap` saves model values in the form of graphs. A graph is a finite set of constraints but there is no appropriate representation for the graph without constraints. Let's imagine we have the input: ```smt2 (set-option :produce-models true) (set-logic ALL) (declare-fun (Int) Int) (check-sat) (get-model) ``` We expect an output as follows: ```smt2 ( (define-fun f (_x Int) (@A as Int)) ) ``` But `Graph.empty` cannot hold the abstract value `@a`. A naive solution consists in using an ADT: ```ocaml type graph = | Empty of Id.typed | G of Graph.t ``` But we'll add an extra indirection. Probably the best solution would be to use a custom datastructure instead of a map to store the constraints. In this PR, we detect in `ModelMap.add` if the only constraint in the graph is of the form `something -> abstract value`. In this case we remove this constraint. This solution isn't perfect as explained in issue #1018. The biggest drawback of this solution is the fact we have to declare symbols in the SAT API, otherwise models returned by `get_model` could be incomplete.
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -53,6 +53,12 @@ module HT = Hashtbl.Make( | |||||||||||||||||||||||||||||||||||||||||||||||||
let hash = Fun.id | ||||||||||||||||||||||||||||||||||||||||||||||||||
end) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
module DeclSet = Set.Make | ||||||||||||||||||||||||||||||||||||||||||||||||||
(struct | ||||||||||||||||||||||||||||||||||||||||||||||||||
type t = Id.typed | ||||||||||||||||||||||||||||||||||||||||||||||||||
let compare = Id.compare_typed | ||||||||||||||||||||||||||||||||||||||||||||||||||
end) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
(** Helper function: returns the basename of a dolmen path, since in AE | ||||||||||||||||||||||||||||||||||||||||||||||||||
the problems are contained in one-file (for now at least), the path is | ||||||||||||||||||||||||||||||||||||||||||||||||||
irrelevant and only the basename matters *) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -701,8 +707,15 @@ let mk_term_decl ({ id_ty; path; tags; _ } as tcst: DE.term_cst) = | |||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||
Cache.store_sy tcst sy; | ||||||||||||||||||||||||||||||||||||||||||||||||||
Cache.store_ty_vars id_ty; | ||||||||||||||||||||||||||||||||||||||||||||||||||
(* Adding polymorphic types to the cache. *) | ||||||||||||||||||||||||||||||||||||||||||||||||||
Cache.store_ty_vars id_ty | ||||||||||||||||||||||||||||||||||||||||||||||||||
let arg_tys, ret_ty = | ||||||||||||||||||||||||||||||||||||||||||||||||||
match DT.view id_ty with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| `Arrow (arg_tys, ret_ty) -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
List.map dty_to_ty arg_tys, dty_to_ty ret_ty | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> [], dty_to_ty id_ty | ||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||
(Hstring.make name, arg_tys, ret_ty) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
(** Handles the definitions of a list of mutually recursive types. | ||||||||||||||||||||||||||||||||||||||||||||||||||
- If one of the types is an ADT, the ADTs that have only one case are | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -2087,14 +2100,24 @@ let make dloc_file acc stmt = | |||||||||||||||||||||||||||||||||||||||||||||||||
assert false | ||||||||||||||||||||||||||||||||||||||||||||||||||
) defs | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| {contents = `Decls [td]; _ } -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
begin match td with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| `Type_decl (td, _def) -> mk_ty_decl td | ||||||||||||||||||||||||||||||||||||||||||||||||||
| `Term_decl td -> mk_term_decl td | ||||||||||||||||||||||||||||||||||||||||||||||||||
end; | ||||||||||||||||||||||||||||||||||||||||||||||||||
acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {contents = `Decls [td]; loc; _ } -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
let decl = match td with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| `Type_decl (td, _def) -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
mk_ty_decl td; | ||||||||||||||||||||||||||||||||||||||||||||||||||
None | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| `Term_decl td -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
Some (mk_term_decl td) | ||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||
begin match decl with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Some d -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
let st_loc = dl_to_ael dloc_file loc in | ||||||||||||||||||||||||||||||||||||||||||||||||||
C.{ st_decl = Decl d; st_loc } :: acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
| None -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to build an
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| {contents = `Decls dcl; _ } -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {contents = `Decls dcl; loc; _ } -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
let rec aux acc tdl = | ||||||||||||||||||||||||||||||||||||||||||||||||||
(* for now, when acc has more than one element it is assumed that the | ||||||||||||||||||||||||||||||||||||||||||||||||||
types are mutually recursive. Which is not necessarily the case. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -2107,21 +2130,24 @@ let make dloc_file acc stmt = | |||||||||||||||||||||||||||||||||||||||||||||||||
| [otd] -> mk_ty_decl otd | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> mk_mr_ty_decls (List.rev acc) | ||||||||||||||||||||||||||||||||||||||||||||||||||
end; | ||||||||||||||||||||||||||||||||||||||||||||||||||
mk_term_decl td; | ||||||||||||||||||||||||||||||||||||||||||||||||||
aux [] tl | ||||||||||||||||||||||||||||||||||||||||||||||||||
let st_loc = dl_to_ael dloc_file loc in | ||||||||||||||||||||||||||||||||||||||||||||||||||
C.{ st_decl = Decl (mk_term_decl td); st_loc } :: aux [] tl | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| `Type_decl (td, _def) :: tl -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
aux (td :: acc) tl | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| [] -> | ||||||||||||||||||||||||||||||||||||||||||||||||||
begin match acc with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [] -> () | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [otd] -> mk_ty_decl otd | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> mk_mr_ty_decls (List.rev acc) | ||||||||||||||||||||||||||||||||||||||||||||||||||
begin | ||||||||||||||||||||||||||||||||||||||||||||||||||
let () = | ||||||||||||||||||||||||||||||||||||||||||||||||||
match acc with | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [] -> () | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [otd] -> mk_ty_decl otd | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> mk_mr_ty_decls (List.rev acc) | ||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||
[] | ||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||
aux [] dcl; | ||||||||||||||||||||||||||||||||||||||||||||||||||
acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
aux [] dcl @ acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| { contents = `Set_logic _ | `Set_info _ | `Get_info _ ; _ } -> acc | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -177,6 +177,8 @@ module Make (Th : Theory.S) = struct | |
unit_facts_cache : (E.gformula * Ex.t) ME.t ref; | ||
last_saved_model : Models.t Lazy.t option ref; | ||
unknown_reason : Sat_solver_sig.unknown_reason option; | ||
declare_ids : Id.typed Vec.t; | ||
declare_lim : int Vec.t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need to do this dance in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was my first implementation and it didn't work. A functional solution would be to use a list of lists: declare_stack: Id.typed list list We have to Honestly, I believe we should pull up all the imperative stuff of I also tried to implement the feature in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, right,
You did write too much C++ :) A list of lists (or a stack of lists, which is the same thing) is very probably not going to be an issue here because we never actually look at the lists until model generation (and also because this only impacts calls to
If we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree to use |
||
} | ||
|
||
let reset_refs () = | ||
|
@@ -1123,7 +1125,8 @@ module Make (Th : Theory.S) = struct | |
else begin | ||
try | ||
(* also performs case-split and pushes pending atoms to CS *) | ||
let model, _ = Th.compute_concrete_model env.tbox in | ||
let declared_ids = Vec.to_list env.declare_ids in | ||
let model, _ = Th.compute_concrete_model ~declared_ids env.tbox in | ||
env.last_saved_model := Some model; | ||
env | ||
with Ex.Inconsistent (expl, classes) -> | ||
|
@@ -1611,6 +1614,10 @@ module Make (Th : Theory.S) = struct | |
"solved with backward!"; | ||
raise e | ||
|
||
let declare env id = | ||
Vec.push env.declare_ids id; | ||
env | ||
|
||
let push env to_push = | ||
if Options.get_tableaux_cdcl () then | ||
Errors.run_error | ||
|
@@ -1626,6 +1633,7 @@ module Make (Th : Theory.S) = struct | |
let guards = ME.add new_guard | ||
(mk_gf new_guard "" true true,Ex.empty) | ||
acc.guards.guards in | ||
Vec.push env.declare_lim (Vec.size env.declare_ids); | ||
{acc with guards = | ||
{ acc.guards with | ||
current_guard = new_guard; | ||
|
@@ -1656,6 +1664,8 @@ module Make (Th : Theory.S) = struct | |
in | ||
acc.model_gen_phase := false; | ||
env.last_saved_model := None; | ||
let lim = Vec.size env.declare_ids - Vec.pop env.declare_lim in | ||
Vec.shrink env.declare_ids lim; | ||
{acc with inst; | ||
guards = | ||
{ acc.guards with | ||
|
@@ -1837,6 +1847,8 @@ module Make (Th : Theory.S) = struct | |
add_inst = selector; | ||
last_saved_model = ref None; | ||
unknown_reason = None; | ||
declare_ids = Vec.make 17 ~dummy:Id.dummy_typed; | ||
declare_lim = Vec.make 17 ~dummy:(-1); | ||
} | ||
in | ||
assume env gf_true Ex.empty | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,8 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct | |
mutable unknown_reason : Sat_solver_sig.unknown_reason option; | ||
(** The reason why satml raised [I_dont_know] if it does; [None] by | ||
default. *) | ||
declare_ids : Id.typed Vec.t; | ||
declare_lim : int Vec.t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be simpler to use a vector of lists here: mutable declare_ids : Id.typed list ;
declare_queue : Id.typed list Vec.t ; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uhm, I adopt this solution because it's the current style of SatML. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it's a stack (for some reasons they are called "queues" elsewhere in satML but we can use the proper teminology ;) ). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So why do we need an extra field declare_stack: Id.typed list Vec.t is sufficient. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if the algorithmic complexity is identical, the constant term is not the same; having a separate field here avoids having to check that the vector is not empty on all accesses. It probably does not matter here because we never look at the declarations except during model generation but for the other vectors in SatML which are accessed much more frequently it might matter. It's fine to use a non-empty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will use the current design with an extra field. |
||
} | ||
|
||
let empty_guards () = { | ||
|
@@ -97,6 +99,8 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct | |
last_saved_model = None; | ||
last_saved_objectives = None; | ||
unknown_reason = None; | ||
declare_ids = Vec.make 17 ~dummy:Id.dummy_typed; | ||
declare_lim = Vec.make 17 ~dummy:(-1); | ||
} | ||
|
||
exception Sat | ||
|
@@ -965,8 +969,9 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct | |
if compute then begin | ||
try | ||
(* also performs case-split and pushes pending atoms to CS *) | ||
let declared_ids = Vec.to_list env.declare_ids in | ||
let model, objectives = | ||
Th.compute_concrete_model (SAT.current_tbox env.satml) | ||
Th.compute_concrete_model ~declared_ids (SAT.current_tbox env.satml) | ||
in | ||
env.last_saved_model <- Some model; | ||
env.last_saved_objectives <- Some objectives; | ||
|
@@ -1204,14 +1209,17 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct | |
expr_guard, atom_guard | ||
| _ -> assert false | ||
|
||
let declare env id = Vec.push env.declare_ids id | ||
|
||
let push env to_push = | ||
Util.loop ~f:(fun _n () () -> | ||
try | ||
let expr_guard, atom_guard = create_guard env in | ||
SAT.push env.satml atom_guard; | ||
Stack.push expr_guard env.guards.stack_guard; | ||
Steps.push_steps (); | ||
env.guards.current_guard <- expr_guard | ||
env.guards.current_guard <- expr_guard; | ||
Vec.push env.declare_lim (Vec.size env.declare_ids) | ||
with | ||
| Util.Step_limit_reached _ -> | ||
(* This function should be called without step limit | ||
|
@@ -1234,7 +1242,9 @@ module Make (Th : Theory.S) : Sat_solver_sig.S = struct | |
env.last_saved_model <- None; | ||
env.last_saved_objectives <- None; | ||
env.inst <- inst; | ||
env.guards.current_guard <- b | ||
env.guards.current_guard <- b; | ||
let lim = Vec.size env.declare_ids - Vec.pop env.declare_lim in | ||
Vec.shrink env.declare_ids lim | ||
) | ||
~max:to_pop | ||
~elt:() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to use the type here? Can we have multiple declarations with the same name but different types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is because we need the type in
Uf
, this should be a map from identifiers to types rather than a set of typed identifiers.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this doesn't seem to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I forgot to remove it ;)