Commit e4b2063
authored
Adding support for
This PR would add support for `Real` values. In more detail:
- It adds the type `real`, with the helper method `real_sort`
- It adds the method `con_to_real` for converting `Int` values to reals
- It adds the method `rdiv` which corresponds to division for reals
(i.e. `/`)
- It adds support for parsing real valued solutions (see below)
## On Parsing `Real` Solutions
As it turns out, parsing the satisfying assignment for solutions to real
values is not as straightforward. In many cases, the SMT solver will
represent a solution as a fraction, e.g. if it assigns the value `2.5`
to a variable, when asked for the solution, it will return it as the
expression `/ 5.0 2.0`.
For my project, I am fine with the loss of precision when evaluating
this expression to an `f32` or `f64`. The `get_f32` and `get_f64`
methods in this PR will evaluate this expression and return the result.
However, if this is not desired, the next section discusses possible
alternatives.
I have written a small test that should check all possible variations of
solutions that can be returned by the SMT solver:
```rust
#[test]
fn test_real_numbers() {
let mut ctx = ContextBuilder::new()
.solver("z3")
.solver_args(["-smt2", "-in"])
.build()
.unwrap();
let x = ctx.declare_const("x", ctx.real_sort()).unwrap();
// x == 2.0
ctx.assert(ctx.eq(x, ctx.decimal(2.0))).unwrap();
assert_eq!(ctx.check().unwrap(), Response::Sat);
let solution = ctx.get_value(vec![x]).unwrap();
let sol = ctx.get_f64(solution[0].1).unwrap();
// Z3 returns `2.0`
assert!(sol == 2.0, "Expected solution to be 2.5, got {}", sol);
let y = ctx.declare_const("y", ctx.real_sort()).unwrap();
// y == -2.0
ctx.assert(ctx.eq(y, ctx.decimal(-2.0))).unwrap();
assert_eq!(ctx.check().unwrap(), Response::Sat);
let solution = ctx.get_value(vec![y]).unwrap();
let sol = ctx.get_f64(solution[0].1).unwrap();
// Z3 returns `- 2.0`
assert!(sol == -2.0, "Expected solution to be 2.5, got {}", sol);
let z = ctx.declare_const("z", ctx.real_sort()).unwrap();
// z == 2.5 / 1.0
ctx.assert(ctx.eq(z, ctx.rdiv(ctx.decimal(2.5), ctx.decimal(1.0))))
.unwrap();
assert_eq!(ctx.check().unwrap(), Response::Sat);
let solution = ctx.get_value(vec![z]).unwrap();
let sol = ctx.get_f64(solution[0].1).unwrap();
// Z3 returns `(/ 5.0 2.0)`
assert!(sol == 2.5, "Expected solution to be 2.5, got {}", sol);
let a = ctx.declare_const("a", ctx.real_sort()).unwrap();
// a == 2.5 / -1.0
ctx.assert(ctx.eq(a, ctx.rdiv(ctx.decimal(2.5), ctx.decimal(-1.0))))
.unwrap();
assert_eq!(ctx.check().unwrap(), Response::Sat);
let solution = ctx.get_value(vec![a]).unwrap();
let sol = ctx.get_f64(solution[0].1).unwrap();
// Z3 returns `(- (/ 5.0 2.0))`
assert!(sol == -2.5, "Expected solution to be -2.5, got {}", sol);
}
```
### Possible Alternatives
If the loss of precision that occurs when parsing the solution is not
desired, I see two alternatives:
- Explicitly have functions like `get_numerator` and `get_denominator`
- Defining / importing a fractional type (possibly hidden behind a
feature flag)
Let me know your thoughts!Reals (#50)1 parent 3dd756e commit e4b2063
4 files changed
+177
-14
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
704 | 704 | | |
705 | 705 | | |
706 | 706 | | |
707 | | - | |
| 707 | + | |
708 | 708 | | |
709 | 709 | | |
710 | 710 | | |
| |||
716 | 716 | | |
717 | 717 | | |
718 | 718 | | |
719 | | - | |
| 719 | + | |
720 | 720 | | |
721 | 721 | | |
722 | 722 | | |
| |||
728 | 728 | | |
729 | 729 | | |
730 | 730 | | |
731 | | - | |
| 731 | + | |
732 | 732 | | |
733 | 733 | | |
734 | 734 | | |
| |||
740 | 740 | | |
741 | 741 | | |
742 | 742 | | |
743 | | - | |
| 743 | + | |
744 | 744 | | |
745 | 745 | | |
746 | 746 | | |
| |||
752 | 752 | | |
753 | 753 | | |
754 | 754 | | |
755 | | - | |
| 755 | + | |
756 | 756 | | |
757 | 757 | | |
758 | 758 | | |
| |||
764 | 764 | | |
765 | 765 | | |
766 | 766 | | |
767 | | - | |
| 767 | + | |
768 | 768 | | |
769 | 769 | | |
770 | 770 | | |
| |||
776 | 776 | | |
777 | 777 | | |
778 | 778 | | |
779 | | - | |
| 779 | + | |
780 | 780 | | |
781 | 781 | | |
782 | 782 | | |
| |||
788 | 788 | | |
789 | 789 | | |
790 | 790 | | |
791 | | - | |
| 791 | + | |
792 | 792 | | |
793 | 793 | | |
794 | 794 | | |
| |||
800 | 800 | | |
801 | 801 | | |
802 | 802 | | |
803 | | - | |
| 803 | + | |
804 | 804 | | |
805 | 805 | | |
806 | 806 | | |
| |||
812 | 812 | | |
813 | 813 | | |
814 | 814 | | |
815 | | - | |
| 815 | + | |
816 | 816 | | |
817 | 817 | | |
818 | 818 | | |
| |||
824 | 824 | | |
825 | 825 | | |
826 | 826 | | |
827 | | - | |
| 827 | + | |
828 | 828 | | |
829 | 829 | | |
830 | 830 | | |
| |||
836 | 836 | | |
837 | 837 | | |
838 | 838 | | |
839 | | - | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
840 | 863 | | |
841 | 864 | | |
842 | 865 | | |
| |||
997 | 1020 | | |
998 | 1021 | | |
999 | 1022 | | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
1000 | 1036 | | |
1001 | 1037 | | |
1002 | 1038 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
51 | 54 | | |
52 | 55 | | |
53 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
250 | 250 | | |
251 | 251 | | |
252 | 252 | | |
253 | | - | |
| 253 | + | |
254 | 254 | | |
255 | 255 | | |
256 | 256 | | |
| |||
278 | 278 | | |
279 | 279 | | |
280 | 280 | | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
281 | 333 | | |
282 | 334 | | |
283 | 335 | | |
| |||
310 | 362 | | |
311 | 363 | | |
312 | 364 | | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
313 | 389 | | |
314 | 390 | | |
315 | 391 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
0 commit comments