|
2 | 2 | // released under BSD 3-Clause License |
3 | 3 | // author: Kevin Laeufer <laeufer@cornell.edu> |
4 | 4 |
|
5 | | -use baa::{BitVecMutOps, BitVecOps, BitVecValue, BitVecValueRef}; |
| 5 | +use baa::{BitVecOps, BitVecValue, BitVecValueRef}; |
6 | 6 | use patronus::expr::*; |
7 | 7 | use polysub::{Coef, Term, VarIndex}; |
8 | 8 | use rustc_hash::FxHashSet; |
@@ -55,7 +55,16 @@ pub fn verify_word_level_equality(ctx: &mut Context, p: ScaEqualityProblem) -> S |
55 | 55 | ScaVerifyResult::Equal |
56 | 56 | } else { |
57 | 57 | let witness = extract_witness(ctx, &result, inputs.iter().cloned()); |
58 | | - ScaVerifyResult::Unequal(witness) |
| 58 | + // check witness |
| 59 | + let is_equal = eval_bv_expr(ctx, witness.as_slice(), p.equality); |
| 60 | + if is_equal.is_true() { |
| 61 | + println!( |
| 62 | + "ERROR: the polynomial does not reduce to zero, but we were not able to find a witness to show inequality. Returning Unknown." |
| 63 | + ); |
| 64 | + ScaVerifyResult::Unknown |
| 65 | + } else { |
| 66 | + ScaVerifyResult::Unequal(witness) |
| 67 | + } |
59 | 68 | } |
60 | 69 | } |
61 | 70 |
|
@@ -533,7 +542,7 @@ impl<'a, 'b> Display for PrettyPoly<'a, 'b> { |
533 | 542 | mod tests { |
534 | 543 | use super::*; |
535 | 544 | use patronus::expr::{eval_bv_expr, find_symbols}; |
536 | | - use patronus::smt::{BITWUZLA, Logic, SmtCommand, Solver, SolverContext, read_command}; |
| 545 | + use patronus::smt::{SmtCommand, read_command}; |
537 | 546 | use rustc_hash::FxHashMap; |
538 | 547 | use std::io::BufReader; |
539 | 548 |
|
@@ -720,6 +729,35 @@ mod tests { |
720 | 729 | assert_eq!(result, ScaVerifyResult::Equal); |
721 | 730 | } |
722 | 731 |
|
| 732 | + #[test] |
| 733 | + fn test_incorrect_2bit_adder() { |
| 734 | + let mut ctx = Context::default(); |
| 735 | + let a = ctx.bv_symbol("a", 2); |
| 736 | + let b = ctx.bv_symbol("b", 2); |
| 737 | + let word_level = ctx.add(a, b); |
| 738 | + let a_0 = ctx.slice(a, 0, 0); |
| 739 | + let a_1 = ctx.slice(a, 1, 1); |
| 740 | + let b_0 = ctx.slice(b, 0, 0); |
| 741 | + let b_1 = ctx.slice(b, 1, 1); |
| 742 | + let gate_level_0 = ctx.xor(a_0, b_0); |
| 743 | + let carry_1 = ctx.and(a_0, b_0); |
| 744 | + let gate_level_1 = ctx.majority(a_1, b_1, carry_1); |
| 745 | + let gate_level = ctx.concat(gate_level_1, gate_level_0); |
| 746 | + let equality = ctx.equal(word_level, gate_level); |
| 747 | + |
| 748 | + let problem = find_sca_simplification_candidates(&ctx, equality)[0]; |
| 749 | + |
| 750 | + // manually check that our problem is actually incorrect |
| 751 | + assert!(!is_eq_exhaustive(&ctx, problem)); |
| 752 | + |
| 753 | + let result = verify_word_level_equality(&mut ctx, problem); |
| 754 | + if let ScaVerifyResult::Unequal(w) = result { |
| 755 | + println!("Witness: {w:?}"); |
| 756 | + } else { |
| 757 | + assert!(false, "{result:?}"); |
| 758 | + } |
| 759 | + } |
| 760 | + |
723 | 761 | #[test] |
724 | 762 | fn test_simplify_coward_three_add_2bit() { |
725 | 763 | check_eq_coward_smt("../inputs/coward/add_three.2_bit.smt2"); |
|
0 commit comments