Quantcast
Channel: Active questions tagged ocaml - Stack Overflow
Viewing all articles
Browse latest Browse all 527

Obtain an interpretation of unbounded variables using Z3 in OCaml

$
0
0

Problem

I am trying to use the Z3 optimization capabilities to take into account some objectives when checking satisfiability. When I ask Z3 to minimize x + y with x > 0 and y > 0, the obtained interpretation with get_model assigns 1 to both x and y. I am, however, interested in obtaining interpretations that are "closer" to the optimal solution. I tried a workaround (which I explain below), but I'm wondering whether there exists some "built-in" feature in Z3 that allows to "better" interpret unbounded objectives.

What I tried

I tried to use get_lower and get_upper, which gives a symbolic value to x + y— that is 2 * epsilon. Then, I use substitute_one to substitute epsilon with some "very small" value of choice (for example: 0.001). I could inject the obtained value of x + y (which is the expression I am trying to minimize) into the solver. A get_model would then be enough.

This is the example I tried, to see the result of different Z3 functions:

open Z3open Z3.Expropen Z3.Booleanopen Z3.Arithmeticopen Z3.Arithmetic.Realopen Z3.Optimizeopen Z3.Solveropen Z3.Modelopen Printflet ctx = Z3.mk_context [] (* context object *)let opt = Optimize.mk_opt ctx (* optimization context *)let x = Real.mk_const_s ctx "x"let y = Real.mk_const_s ctx "y"let zero = Real.mk_numeral_i ctx 0let x_plus_y = Real.mk_const_s ctx "x_plus_y"let assertions =   Arithmetic.mk_gt ctx x zero (* x > 0 *)  :: Arithmetic.mk_gt ctx y zero (* y > 0 *)  :: Boolean.mk_eq ctx x_plus_y (Arithmetic.mk_add ctx [x; y]) (* x_plus_y = x + y *)  :: [](* assert constraints into the optimize solver *)let () = Optimize.add opt assertions(* ask the solver to minimize x_plus_y *)let handle = Optimize.minimize opt x_plus_y(* check sat *)let status = Optimize.check optlet () = Z3.Params.set_print_mode ctx PRINT_SMTLIB_FULLlet () = printf "- status: %s\n\n" @@ Solver.string_of_status status(* get a model when SAT *)let () = if status == SATISFIABLE then  match Optimize.get_model opt with  | None -> ()  | Some model ->     printf "- model:\n%s\n" @@ Model.to_string model;    printf "- objectives:";    List.iter       (fun expr -> printf " %s\n" @@ Expr.to_string expr)       @@ Optimize.get_objectives opt;    printf "- lower_bound: %s\n"       @@ Expr.to_string       @@ Optimize.get_lower handle;    printf "- upper_bound: %s\n\n"       @@ Expr.to_string       @@ Optimize.get_upper handle;    printf "- substitute epsilon with 0.001: %s\n\n"       @@ Expr.to_string      @@ Expr.substitute_one           (Optimize.get_lower handle)           (Real.mk_const_s ctx "epsilon")           (Real.mk_numeral_s ctx @@ string_of_float 0.001);

Which gives the following output:

- status: satisfiable- model:y -> 1.0x -> 1.0x_plus_y -> 2.0- objectives: x_plus_y- lower_bound: (* 2.0 epsilon)- upper_bound: (* 2.0 epsilon)- substitute epsilon with 0.001: (* 2.0 (/ 1.0 1000.0))

Questions

  • I am not sure of the use of get_lower and get_upper. In my example they return the exact same value. Is there any resource explaining what lower and upper bounds mean in this context ?
  • Is there any alternative to evaluate the objective (other than substituting epsilon, as I did) ?

Thanks.


Viewing all articles
Browse latest Browse all 527

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>