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

FP to real and back conversions don't seem to be operational #14

Closed
LeventErkok opened this issue Mar 29, 2015 · 4 comments
Closed

FP to real and back conversions don't seem to be operational #14

LeventErkok opened this issue Mar 29, 2015 · 4 comments
Assignees

Comments

@LeventErkok
Copy link

This is on the unstable branch.

I'm experimenting with floating-point to real (fp.to_real) and back-conversions ((_ to_fp eb sb)). It appears Z3 is always producing unknown or going away forever for queries that involve these conversions. Is something wrong with the way I've constructed the benchmarks (logic-selection comes to mind), or is this just not quite working well yet?

Here's an example benchmark that causes Z3 to run forever. (Well, I just killed it after a while)

; Automatically generated by SBV. Do not edit.
(set-option :produce-models true)
(set-logic QF_FP)
; --- uninterpreted sorts ---
; --- literal constants ---
(define-fun s_2 () Bool false)
(define-fun s_1 () Bool true)
; --- skolem constants ---
(declare-fun s0 () Real)
(declare-fun s1 () RoundingMode)
; --- constant tables ---
; --- skolemized tables ---
; --- arrays ---
; --- uninterpreted constants ---
; --- user given axioms ---
; --- formula ---
(assert ; no quantifiers
   (let ((s2 ((_ to_fp 8 24) s1 s0)))
   (let ((s3 (fp.to_real s2)))
   (let ((s4 (distinct s0 s3)))
   s4))))
(check-sat)

And this one causes Z3 to issue unknown:

; Automatically generated by SBV. Do not edit.
(set-option :produce-models true)
(set-logic QF_FP)
; --- uninterpreted sorts ---
; --- literal constants ---
(define-fun s_2 () Bool false)
(define-fun s_1 () Bool true)
; --- skolem constants ---
(declare-fun s0 () Real)
(declare-fun s1 () RoundingMode)
(declare-fun s2 () RoundingMode)
; --- constant tables ---
; --- skolemized tables ---
; --- arrays ---
; --- uninterpreted constants ---
; --- user given axioms ---
; --- formula ---
(assert ; no quantifiers
   (let ((s3 ((_ to_fp 8 24) s1 s0)))
   (let ((s4 ((_ to_fp 8 24) s2 s0)))
   (let ((s5 (not (fp.eq s3 s4))))
   s5))))
(check-sat)
LeventErkok added a commit to LeventErkok/sbv that referenced this issue Mar 29, 2015
Implement sRealToSFloat, sRealToSDouble, and fpToSReal. Also add
symbolic rounding modes as convenient shortcuts.

Note that while the conversion seems to be working OK, Z3 is having
hard time actually producing results for queries involving these
conversions. Filed this issue: Z3Prover/z3#14
@wintersteiger wintersteiger self-assigned this Mar 29, 2015
wintersteiger pushed a commit that referenced this issue Mar 29, 2015
@wintersteiger
Copy link
Contributor

Floating-point constraints are usually translated first into bit-vectors and then into propositional SAT. Conversion terms from/to (non-numeral) reals translate into large non-linear constraints over the reals, which the (new, fast) purely propositional SAT solver can't handle, so it falls back to the (old, slow) SMT core that handles all theories, but is often slower. In the case of these non-linear constraints it's simply not strong enough and it either doesn't terminate or gives up early and returns unknown.

For numerals, we can get rid of those expressions altogether (and I've added another one of those in 59911f78), but for general constraints, there is no efficient method yet.

@wintersteiger
Copy link
Contributor

Closing this issue as all questions are answered. There is no simple solution to the performance problems, so will require more research. Feel free to re-open if new information becomes available.

@LeventErkok
Copy link
Author

Indeed, there isn't much point to keeping this ticket here.

I'll just note that most of the interesting floating-point verification work actually involves showing that certain operations will produce exact results. The typical approach is to take two floats, convert them to reals, do the operation with infinite precision, and turn the result back to a float using the rounding mode. Then, one shows that this result is precisely the same as just doing the corresponding operation directly on the floats without moving to reals and back. (This is the required behavior in the IEEE754 sense.)

I'd even say that this is the raison d'etre for why we want an automated floating-point logic in the first place.

Of course, none of this is criticism for Z3 or SMT. It's just that such problems are hard and more research is needed. But without proper real/float conversion support in solvers, the automation is inherently limited in its industrial use.

@wintersteiger
Copy link
Contributor

You're completely right of course and we are aware of those problems. We have plans to extend the floating point reasoning in that direction, but that will take some time.

NikolajBjorner referenced this issue in NikolajBjorner/z3 Jul 3, 2016
added bounds propagation in theory_lra
@evmaus evmaus mentioned this issue May 24, 2019
mtzguido added a commit to mtzguido/z3 that referenced this issue Jun 23, 2023
…junctions

After introducing the rewriter.sort_disjunctions option, I noticed a
segfault in a Z3 run that was working fine for me.

I traced the difference to a slight discrepancy between the first patch
I submitted and the one we ended up merging: my first version would skip
sorting the disjuncts in mk_nflat_core, but still return BR_DONE, while
the patch in master returns BR_FAILED instead.

This patch fixes the problem for me, and it makes slightly more sense
to me to return a BR_DONE since, if `s` is true, some disjunct (e.g. a
`false` or a repeat) might have been simplified away. However I don't
fully understand this code.

.. and I can't say I understand why the segfault happens. Perhaps that
is a separate issue?

This is the file to reproduce:
 https://gist.github.com/mtzguido/b7360c74d3d2e42d89f1bd9149ad26f6

Here's a stack trace of the failure, mk_nflat_or_core is not involved.
```
 (gdb) where
 #0  0x0000555555b98497 in smt::context::get_lit_assignment(unsigned int) const ()
 Z3Prover#1  0x0000555555b984cb in smt::context::get_assignment(sat::literal) const ()
 Z3Prover#2  0x0000555555b98504 in smt::context::get_assignment(unsigned int) const ()
 Z3Prover#3  0x0000555555ca83b8 in smt::context::get_assignment_core(expr*) const ()
 Z3Prover#4  0x0000555555c9af5a in smt::context::get_assignment(expr*) const ()
 Z3Prover#5  0x0000555555d7bd1d in (anonymous namespace)::has_child_assigned_to(smt::context&, app*, lbool, expr*&, unsigned int) ()
 Z3Prover#6  0x0000555555d7c413 in (anonymous namespace)::rel_case_split_queue::next_case_split_core(ptr_vector<expr>&, unsigned int&, unsigned int&, lbool&) ()
 Z3Prover#7  0x0000555555d7c589 in (anonymous namespace)::rel_case_split_queue::next_case_split(unsigned int&, lbool&) ()
 Z3Prover#8  0x0000555555c9c1b7 in smt::context::decide() ()
 Z3Prover#9  0x0000555555ca39fd in smt::context::bounded_search() ()
 Z3Prover#10 0x0000555555ca30c2 in smt::context::search() ()
 Z3Prover#11 0x0000555555ca273d in smt::context::check(unsigned int, expr* const*, bool) ()
 Z3Prover#12 0x0000555555cb166a in smt::kernel::check(unsigned int, expr* const*) ()
 Z3Prover#13 0x0000555555cb9695 in (anonymous namespace)::smt_solver::check_sat_core2(unsigned int, expr* const*) ()
 Z3Prover#14 0x00005555560dc0c6 in solver_na2as::check_sat_core(unsigned int, expr* const*) ()
 Z3Prover#15 0x00005555560d73f3 in combined_solver::check_sat_core(unsigned int, expr* const*) ()
 Z3Prover#16 0x00005555560d34e3 in solver::check_sat(unsigned int, expr* const*) ()
 Z3Prover#17 0x0000555556097b26 in cmd_context::check_sat(unsigned int, expr* const*) ()
 Z3Prover#18 0x0000555556082ff0 in smt2::parser::parse_check_sat() ()
 Z3Prover#19 0x0000555556084dc0 in smt2::parser::parse_cmd() ()
 Z3Prover#20 0x00005555560861b6 in smt2::parser::operator()() ()
 Z3Prover#21 0x00005555560757e6 in parse_smt2_commands(cmd_context&, std::basic_istream<char, std::char_traits<char> >&, bool, params_ref const&, char const*) ()
 Z3Prover#22 0x00005555555e8f68 in read_smtlib2_commands(char const*) ()
 Z3Prover#23 0x00005555555ee6f6 in main ()
 (gdb)
```
mtzguido added a commit to mtzguido/z3 that referenced this issue Jun 23, 2023
…junctions

After introducing the rewriter.sort_disjunctions option (Z3Prover#6774), I
noticed a segfault in a Z3 run that was working fine for me before the
PR.

I traced the difference to a slight discrepancy between the first patch
I submitted and the one we ended up merging: my first version would skip
sorting the disjuncts in mk_nflat_core, but still return BR_DONE, while
the patch in master returns BR_FAILED instead.

This patch fixes that problem, and it makes slightly more sense to me to
return a BR_DONE since, if `s` is true, some disjunct (e.g. a `false`
or a repeat) might have been simplified away. However I don't fully
understand this code.

... and I can't say I understand why the segfault happens. Perhaps that
is a separate issue?

This is the file to reproduce:
 https://gist.github.com/mtzguido/b7360c74d3d2e42d89f1bd9149ad26f6

Here's a stack trace of the failure, mk_nflat_or_core is not involved.
```
 (gdb) where
 #0  0x0000555555b98497 in smt::context::get_lit_assignment(unsigned int) const ()
 Z3Prover#1  0x0000555555b984cb in smt::context::get_assignment(sat::literal) const ()
 Z3Prover#2  0x0000555555b98504 in smt::context::get_assignment(unsigned int) const ()
 Z3Prover#3  0x0000555555ca83b8 in smt::context::get_assignment_core(expr*) const ()
 Z3Prover#4  0x0000555555c9af5a in smt::context::get_assignment(expr*) const ()
 Z3Prover#5  0x0000555555d7bd1d in (anonymous namespace)::has_child_assigned_to(smt::context&, app*, lbool, expr*&, unsigned int) ()
 Z3Prover#6  0x0000555555d7c413 in (anonymous namespace)::rel_case_split_queue::next_case_split_core(ptr_vector<expr>&, unsigned int&, unsigned int&, lbool&) ()
 Z3Prover#7  0x0000555555d7c589 in (anonymous namespace)::rel_case_split_queue::next_case_split(unsigned int&, lbool&) ()
 Z3Prover#8  0x0000555555c9c1b7 in smt::context::decide() ()
 Z3Prover#9  0x0000555555ca39fd in smt::context::bounded_search() ()
 Z3Prover#10 0x0000555555ca30c2 in smt::context::search() ()
 Z3Prover#11 0x0000555555ca273d in smt::context::check(unsigned int, expr* const*, bool) ()
 Z3Prover#12 0x0000555555cb166a in smt::kernel::check(unsigned int, expr* const*) ()
 Z3Prover#13 0x0000555555cb9695 in (anonymous namespace)::smt_solver::check_sat_core2(unsigned int, expr* const*) ()
 Z3Prover#14 0x00005555560dc0c6 in solver_na2as::check_sat_core(unsigned int, expr* const*) ()
 Z3Prover#15 0x00005555560d73f3 in combined_solver::check_sat_core(unsigned int, expr* const*) ()
 Z3Prover#16 0x00005555560d34e3 in solver::check_sat(unsigned int, expr* const*) ()
 Z3Prover#17 0x0000555556097b26 in cmd_context::check_sat(unsigned int, expr* const*) ()
 Z3Prover#18 0x0000555556082ff0 in smt2::parser::parse_check_sat() ()
 Z3Prover#19 0x0000555556084dc0 in smt2::parser::parse_cmd() ()
 Z3Prover#20 0x00005555560861b6 in smt2::parser::operator()() ()
 Z3Prover#21 0x00005555560757e6 in parse_smt2_commands(cmd_context&, std::basic_istream<char, std::char_traits<char> >&, bool, params_ref const&, char const*) ()
 Z3Prover#22 0x00005555555e8f68 in read_smtlib2_commands(char const*) ()
 Z3Prover#23 0x00005555555ee6f6 in main ()
 (gdb)
```
NikolajBjorner pushed a commit that referenced this issue Jun 23, 2023
…junctions (#6779)

After introducing the rewriter.sort_disjunctions option (#6774), I
noticed a segfault in a Z3 run that was working fine for me before the
PR.

I traced the difference to a slight discrepancy between the first patch
I submitted and the one we ended up merging: my first version would skip
sorting the disjuncts in mk_nflat_core, but still return BR_DONE, while
the patch in master returns BR_FAILED instead.

This patch fixes that problem, and it makes slightly more sense to me to
return a BR_DONE since, if `s` is true, some disjunct (e.g. a `false`
or a repeat) might have been simplified away. However I don't fully
understand this code.

... and I can't say I understand why the segfault happens. Perhaps that
is a separate issue?

This is the file to reproduce:
 https://gist.github.com/mtzguido/b7360c74d3d2e42d89f1bd9149ad26f6

Here's a stack trace of the failure, mk_nflat_or_core is not involved.
```
 (gdb) where
 #0  0x0000555555b98497 in smt::context::get_lit_assignment(unsigned int) const ()
 #1  0x0000555555b984cb in smt::context::get_assignment(sat::literal) const ()
 #2  0x0000555555b98504 in smt::context::get_assignment(unsigned int) const ()
 #3  0x0000555555ca83b8 in smt::context::get_assignment_core(expr*) const ()
 #4  0x0000555555c9af5a in smt::context::get_assignment(expr*) const ()
 #5  0x0000555555d7bd1d in (anonymous namespace)::has_child_assigned_to(smt::context&, app*, lbool, expr*&, unsigned int) ()
 #6  0x0000555555d7c413 in (anonymous namespace)::rel_case_split_queue::next_case_split_core(ptr_vector<expr>&, unsigned int&, unsigned int&, lbool&) ()
 #7  0x0000555555d7c589 in (anonymous namespace)::rel_case_split_queue::next_case_split(unsigned int&, lbool&) ()
 #8  0x0000555555c9c1b7 in smt::context::decide() ()
 #9  0x0000555555ca39fd in smt::context::bounded_search() ()
 #10 0x0000555555ca30c2 in smt::context::search() ()
 #11 0x0000555555ca273d in smt::context::check(unsigned int, expr* const*, bool) ()
 #12 0x0000555555cb166a in smt::kernel::check(unsigned int, expr* const*) ()
 #13 0x0000555555cb9695 in (anonymous namespace)::smt_solver::check_sat_core2(unsigned int, expr* const*) ()
 #14 0x00005555560dc0c6 in solver_na2as::check_sat_core(unsigned int, expr* const*) ()
 #15 0x00005555560d73f3 in combined_solver::check_sat_core(unsigned int, expr* const*) ()
 #16 0x00005555560d34e3 in solver::check_sat(unsigned int, expr* const*) ()
 #17 0x0000555556097b26 in cmd_context::check_sat(unsigned int, expr* const*) ()
 #18 0x0000555556082ff0 in smt2::parser::parse_check_sat() ()
 #19 0x0000555556084dc0 in smt2::parser::parse_cmd() ()
 #20 0x00005555560861b6 in smt2::parser::operator()() ()
 #21 0x00005555560757e6 in parse_smt2_commands(cmd_context&, std::basic_istream<char, std::char_traits<char> >&, bool, params_ref const&, char const*) ()
 #22 0x00005555555e8f68 in read_smtlib2_commands(char const*) ()
 #23 0x00005555555ee6f6 in main ()
 (gdb)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants