summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOuyancheng <1024842937@qq.com>2021-04-28 16:10:51 -0700
committerGitHub <noreply@github.com>2021-04-28 23:10:51 +0000
commit9e5a4a3e6aca1b25cf1af4a6392003cb5ecb8866 (patch)
tree92ccc180c69150cd7276d5cedd41913e110fad2d /src
parent541e19463a0a5dc44dc97a494ca295aae296091e (diff)
Fix BV Optimization Boundary Condition when lower bound = upper bound + 1 (#6452)
If lb = ub + 1 then (lb+ub)/2 =pivot == lb since it's rounding to -infinity. and lb <= x < pivot will always be UNSAT. We need to handle this differently. And this only happens in minimization.
Diffstat (limited to 'src')
-rw-r--r--src/omt/bitvector_optimizer.cpp53
1 files changed, 22 insertions, 31 deletions
diff --git a/src/omt/bitvector_optimizer.cpp b/src/omt/bitvector_optimizer.cpp
index bfbf1cef3..ab5af03f7 100644
--- a/src/omt/bitvector_optimizer.cpp
+++ b/src/omt/bitvector_optimizer.cpp
@@ -35,18 +35,12 @@ BitVector OMTOptimizerBitVector::computeAverage(const BitVector& a,
// average = (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2)
uint32_t aMod2 = static_cast<uint32_t>(a.isBitSet(0));
uint32_t bMod2 = static_cast<uint32_t>(b.isBitSet(0));
- BitVector aMod2PlusbMod2(a.getSize(), (aMod2 + bMod2) / 2);
+ BitVector aMod2PlusbMod2Div2(a.getSize(), (aMod2 + bMod2) / 2);
BitVector bv1 = BitVector::mkOne(a.getSize());
- if (isSigned)
- {
- return (a.arithRightShift(bv1) + b.arithRightShift(bv1)
- + aMod2PlusbMod2.arithRightShift(bv1));
- }
- else
- {
- return (a.logicalRightShift(bv1) + b.logicalRightShift(bv1)
- + aMod2PlusbMod2.logicalRightShift(bv1));
- }
+ return (isSigned) ? ((a.arithRightShift(bv1) + b.arithRightShift(bv1)
+ + aMod2PlusbMod2Div2))
+ : ((a.logicalRightShift(bv1) + b.logicalRightShift(bv1)
+ + aMod2PlusbMod2Div2));
}
std::pair<OptResult, Node> OMTOptimizerBitVector::minimize(
@@ -92,23 +86,24 @@ std::pair<OptResult, Node> OMTOptimizerBitVector::minimize(
// pivot = (lowerBound + upperBound) / 2
// rounded towards -infinity
BitVector pivot;
- while (true)
+ while ((d_isSigned && lowerBound.signedLessThan(upperBound))
+ || (!d_isSigned && lowerBound.unsignedLessThan(upperBound)))
{
- if (d_isSigned)
+ pivot = computeAverage(lowerBound, upperBound, d_isSigned);
+ optChecker->push();
+ if (lowerBound == pivot)
{
- if (!lowerBound.signedLessThan(upperBound)) break;
+ optChecker->assertFormula(
+ nm->mkNode(kind::EQUAL, target, nm->mkConst(lowerBound)));
}
else
{
- if (!lowerBound.unsignedLessThan(upperBound)) break;
+ // lowerBound <= target < pivot
+ optChecker->assertFormula(
+ nm->mkNode(kind::AND,
+ nm->mkNode(GEOperator, target, nm->mkConst(lowerBound)),
+ nm->mkNode(LTOperator, target, nm->mkConst(pivot))));
}
- pivot = computeAverage(lowerBound, upperBound, d_isSigned);
- optChecker->push();
- // lowerBound <= target < pivot
- optChecker->assertFormula(
- nm->mkNode(kind::AND,
- nm->mkNode(GEOperator, target, nm->mkConst(lowerBound)),
- nm->mkNode(LTOperator, target, nm->mkConst(pivot))));
intermediateSatResult = optChecker->checkSat();
if (intermediateSatResult.isUnknown() || intermediateSatResult.isNull())
{
@@ -186,19 +181,15 @@ std::pair<OptResult, Node> OMTOptimizerBitVector::maximize(
// pivot = (lowerBound + upperBound) / 2
// rounded towards -infinity
BitVector pivot;
- while (true)
+ while ((d_isSigned && lowerBound.signedLessThan(upperBound))
+ || (!d_isSigned && lowerBound.unsignedLessThan(upperBound)))
{
- if (d_isSigned)
- {
- if (!lowerBound.signedLessThan(upperBound)) break;
- }
- else
- {
- if (!lowerBound.unsignedLessThan(upperBound)) break;
- }
pivot = computeAverage(lowerBound, upperBound, d_isSigned);
optChecker->push();
+ // notice that we don't have boundary condition here
+ // because lowerBound == pivot / lowerBound == upperBound + 1 is also
+ // covered
// pivot < target <= upperBound
optChecker->assertFormula(
nm->mkNode(kind::AND,
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback