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

[models] Add support for printing arrays #659

Merged
merged 2 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 62 additions & 32 deletions src/lib/frontend/models.ml
Original file line number Diff line number Diff line change
Expand Up @@ -323,31 +323,34 @@ module SmtlibCounterExample = struct
with _ -> t
in

Printer.print_fmt ~flushed:false fmt
"(define-fun %a (%a) %a %s)@ "
Format.fprintf fmt
"@ (define-fun %a (%a) %a %s)"
Sy.print name
(Printer.pp_list_space (print_args)) args
Ty.print ty
defined_value

let output_constants_counterexample fmt records cprofs =
let output_constants_counterexample ?(ignored = Sy.Set.empty) fmt records =
ModelMap.iter
(fun (f, xs_ty, ty) st ->
assert (xs_ty == []);
match ModelMap.V.elements st with
| [[], rep] ->
let rep = Format.asprintf "%a" x_print rep in
let rep =
match ty with
| Ty.Trecord r ->
let constr = mk_records_constr records f r in
sprintf "(%s)" constr
| _ -> rep
in

print_fun_def fmt f [] ty rep
| _ -> assert false
) cprofs
begin match ty with
| Ty.Tfarray _ when Sy.Set.mem f ignored -> ()
| _ ->
match ModelMap.V.elements st with
| [[], rep] ->
let rep = Format.asprintf "%a" x_print rep in
let rep =
match ty with
| Ty.Trecord r ->
let constr = mk_records_constr records f r in
sprintf "(%s)" constr
| _ -> rep
in

print_fun_def fmt f [] ty rep
| _ -> assert false
end)

let output_functions_counterexample fmt records fprofs =
let records = ref records in
Expand Down Expand Up @@ -422,8 +425,28 @@ module SmtlibCounterExample = struct
) fprofs;
!records

let output_arrays_counterexample fmt _arrays =
Printer.print_fmt fmt "@ ; Arrays not yet supported@ "
let output_arrays_counterexample fmt arrays =
let pp_array ppf (symbol, dty, st) =
let abstract =
Format.dprintf "(as @@%a %t)" Sy.print symbol dty
in
ModelMap.V.fold (fun (keys, (_value_r, value_s)) rst ->
Format.dprintf "(@[<hv>store@ %t@ %a %s)@]"
rst
Fmt.(list ~sep:sp (using (fun (_, (_, s)) -> s) string)) keys
value_s
) st abstract ppf
in
let pp_array_ty ppf (args_ty, ret_ty) =
Format.fprintf ppf "(@[Array@ %a@ %a)@]"
Fmt.(list ~sep:sp Ty.print) args_ty
Ty.print ret_ty
in
ModelMap.iter
(fun (f, xs_ty, ty) st ->
let dty = Format.dprintf "%a" pp_array_ty (xs_ty, ty) in
Format.fprintf fmt "@ (@[define-fun %a () %t@ %a)@]"
Sy.print f dty pp_array (f, dty, st)) arrays

end
(* of module SmtlibCounterExample *)
Expand All @@ -432,41 +455,48 @@ module Why3CounterExample = struct

let output_constraints fmt prop_model =
let assertions = SE.fold (fun e acc ->
(asprintf "%s(assert %a)@ " acc SmtlibCounterExample.pp_term e)
) prop_model "" in
Printer.print_fmt ~flushed:false fmt "@ ; constants@ ";
(dprintf "%t(assert %a)@ " acc SmtlibCounterExample.pp_term e)
) prop_model (dprintf "") in
Format.fprintf fmt "@ ; constraints@ ";
MS.iter (fun _ (name,ty,args_ty) ->
match args_ty with
| [] ->
Printer.print_fmt ~flushed:false fmt "(declare-const %s %s)@ "
Format.fprintf fmt "(declare-const %s %s)@ "
name ty
| l ->
Printer.print_fmt ~flushed:false fmt "(declare-fun %s (%s) %s)@ "
Format.fprintf fmt "(declare-fun %s (%s) %s)@ "
name
(String.concat " " l)
ty
) !constraints;
Printer.print_fmt ~flushed:false fmt "@ ; assertions@ ";
Printer.print_fmt fmt ~flushed:false "%s" assertions
Format.fprintf fmt "@ ; assertions@ ";
Format.fprintf fmt "%t" assertions

end
(* of module Why3CounterExample *)

let output_concrete_model fmt props ~functions ~constants ~arrays =
Printer.print_fmt ~flushed:false fmt "@[<v 2>(@,";
Format.fprintf fmt "@[<v 2>(";
if Options.get_model_type_constraints () then
begin
Why3CounterExample.output_constraints fmt props
Why3CounterExample.output_constraints fmt props;
Format.fprintf fmt "@ ; values"
end;

Printer.print_fmt fmt "@ ; Functions@ ";
(* Functions *)
let records = SmtlibCounterExample.output_functions_counterexample
fmt MS.empty functions in

Printer.print_fmt fmt "@ ; Constants@ ";
let array_symbols =
ModelMap.fold (fun (f, _, _) _ -> Sy.Set.add f) arrays Sy.Set.empty
in

(* Constants *)
(* If the constant is present in the arrays map, it will be printed there. *)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure to understand this comment. If the constant is present in the arrays map, then it is present in arrays_symbols and ignored by the function output_constants_counterexample.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not sure to understand why some arrays will be printed as constant and other by output_arrays_counterexample.

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 I remember correctly, this is because arrays for which there has been no get/set are not added to the array_symbols.

I didn't think it was very important to keep this distinction, but it should not be too hard to iterate over the constant array symbols in output_arrays_counterexample instead.

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 have a version that does what I described above, but it's not very pretty because:

  • There are arrays that only appear in the constants portion. This is the case where an array is defined to be equal to another array.
  • There are also arrays that only appear in the arrays portion. This is the case of an array that is defined (i.e. has get/set on them) but does not appear in the original problem and was synthesized by the solver.

Here is a (slightly overcomplicated) example:

(set-logic ALL)
(declare-const x Int)
(declare-const y Int)
(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(declare-const a4 (Array Int Int))
(assert (= a4 a2))
(assert (= (select a1 x) x))
(assert (= (store a1 x y) a1))
(assert (= (store a1 y y) a1))
(assert (= (store a2 7 3) a2))
(assert (= (store a2 19 4) a2))

(declare-const a3 (Array Int Int))

(declare-fun f (Bool) (Array Int Int))
(assert (= (f true) a2))
(assert (= (store (f false) 7 3) (f false)))

(check-sat)
(get-model)

A model is:

unknown
(
  ; Functions
  (define-fun f ((arg_0 Bool)) (Array Int Int) (ite (= arg_0 true) a4 !k2))
  ; Constants
  (define-fun x () Int 0)
  (define-fun y () Int 0)
  ; Arrays
  (define-fun a1 () (Array Int Int) (store (as @a1 (Array Int Int)) 0 0))
  (define-fun a2 () (Array Int Int) a4)
  (define-fun a4 () (Array Int Int)
   (store (store (as @a4 (Array Int Int)) 7 3) 19 4))
  (define-fun !k2 () (Array Int Int) (store (as @!k2 (Array Int Int)) 7 3))
)

In this example, a1 and a4 are in both constants and arrays; a2 is only in constants; and !k2 is only in arrays.

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 will push the code but am waiting on the merge of #703 to include tests)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That said I am not convinced that keeping the separation while printing is worth the added code complexity.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree. All the values are functions. We should remove the difference. I suggest to keep the code as simple as possible and remove the pointless SMTLIB comments in the output model. We will produce a better code for the next release.

SmtlibCounterExample.output_constants_counterexample
fmt records constants;
~ignored:array_symbols fmt records constants;

(* Arrays *)
SmtlibCounterExample.output_arrays_counterexample fmt arrays;

Printer.print_fmt fmt "@]@ )";
Printer.print_fmt fmt "@]@,)";
1 change: 0 additions & 1 deletion src/lib/reasoners/uf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1085,4 +1085,3 @@ let save_cache () =

let reinit_cache () =
LX.reinit_cache ()

10 changes: 10 additions & 0 deletions tests/cram.t/model555.smt2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
; From https://github.com/OCamlPro/alt-ergo/issues/555
(set-logic ALL)
(declare-const x Int)
(declare-const y Int)
(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(assert (= (select a1 x) x))
(assert (= (store a1 x y) a1))
(check-sat)
(get-model)
13 changes: 13 additions & 0 deletions tests/cram.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,16 @@
alt-ergo: ; Fatal Error: [Dynlink] Loading the 'inequalities' reasoner (FM module) plugin in "does-not-exist" failed!
>> Failure message: error loading shared library: Dynlink.Error (Dynlink.Cannot_open_dll "Failure(\"$TESTCASE_ROOT/does-not-exist: cannot open shared object file: No such file or directory\")")
[125]

Now we will have some tests for the models. Note that it is okay if the format
changes slightly, you should be concerned with ensuring the semantic is
appropriate here.

$ alt-ergo --frontend dolmen --produce-models model555.smt2 --no-forced-flush-in-output 2>/dev/null

unknown
(
(define-fun x () Int 0)
(define-fun y () Int 0)
(define-fun a1 () (Array Int Int) (store (as @a1 (Array Int Int)) 0 0))
)
7 changes: 7 additions & 0 deletions tests/issues/555/models/555.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

unknown
(
(define-fun x () Int 0)
(define-fun y () Int 0)
(define-fun a1 () (Array Int Int) (store (as @a1 (Array Int Int)) 0 0))
)
10 changes: 10 additions & 0 deletions tests/issues/555/models/555.smt2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(set-logic ALL)
(set-option :produce-models true)
(declare-const x Int)
(declare-const y Int)
(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(assert (= (select a1 x) x))
(assert (= (store a1 x y) a1))
(check-sat)
(get-model)
11 changes: 1 addition & 10 deletions tests/models/arith/arith1.expected
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@

unknown
(

; Functions

; Constants

(define-fun x () Int 0)

; Arrays not yet supported


(define-fun x () Int 0)
)
14 changes: 2 additions & 12 deletions tests/models/arith/arith2.expected
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@

unknown
(

; Functions

; Constants

(define-fun x () Int 8)

(define-fun y () Int 42)

; Arrays not yet supported


(define-fun x () Int 8)
(define-fun y () Int 42)
)
25 changes: 3 additions & 22 deletions tests/models/bool/bool1.expected
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@

unknown
(

; Functions

; Constants

; Arrays not yet supported


)

unknown
(

; Functions

; Constants

(define-fun p () Bool true)

(define-fun q () Bool true)

(define-fun nq () Bool true)

; Arrays not yet supported


(define-fun p () Bool true)
(define-fun q () Bool true)
(define-fun nq () Bool true)
)
8 changes: 0 additions & 8 deletions tests/models/bool/bool2.expected
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@

unknown
(

; Functions

; Constants

; Arrays not yet supported


)
17 changes: 3 additions & 14 deletions tests/models/uf/uf1.expected
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@

unknown
(

; Functions

(define-fun f ((arg_0 Int)) Int 0)

; Constants

(define-fun a () Int 0)

(define-fun b () Int 0)

; Arrays not yet supported


(define-fun f ((arg_0 Int)) Int 0)
(define-fun a () Int 0)
(define-fun b () Int 0)
)
17 changes: 3 additions & 14 deletions tests/models/uf/uf2.expected
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@

unknown
(

; Functions

(define-fun f ((arg_0 Int)) Int (ite (= arg_0 a) 2 0))

; Constants

(define-fun a () Int 0)

(define-fun b () Int (- 2))

; Arrays not yet supported


(define-fun f ((arg_0 Int)) Int (ite (= arg_0 a) 2 0))
(define-fun a () Int 0)
(define-fun b () Int (- 2))
)