Skip to content

Commit 2590d67

Browse files
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
1 parent 58474df commit 2590d67

File tree

4 files changed

+182
-50
lines changed

4 files changed

+182
-50
lines changed

src/ast/sls/bv_sls_eval.cpp

+106-40
Original file line numberDiff line numberDiff line change
@@ -1122,57 +1122,123 @@ namespace bv {
11221122
for (unsigned i = 0; i < e.nw; ++i)
11231123
m_tmp[i] = ~e.bits()[i];
11241124
a.clear_overflow_bits(m_tmp);
1125-
return a.set_repair(random_bool(), m_tmp);
1125+
return a.try_set(m_tmp);
11261126
}
11271127

1128-
bool sls_eval::try_repair_bneg(bvval const& e, bvval& a) {
1129-
1128+
bool sls_eval::try_repair_bneg(bvval const& e, bvval& a) {
11301129
e.set_sub(m_tmp, m_zero, e.bits());
1131-
return a.set_repair(random_bool(), m_tmp);
1132-
}
1133-
1134-
bool sls_eval::try_repair_ule(bool e, bvval& a, bvval const& b) {
1135-
return try_repair_ule(e, a, b.bits());
1130+
return a.try_set(m_tmp);
11361131
}
11371132

1138-
bool sls_eval::try_repair_uge(bool e, bvval& a, bvval const& b) {
1139-
return try_repair_uge(e, a, b.bits());
1140-
}
11411133

11421134
// a <=s b <-> a + p2 <=u b + p2
1143-
11441135
//
1145-
// to solve x for x <=s b:
1146-
// y := at most (b + p2) - p2
1147-
// x := random_at_most y
1148-
// or
1149-
// x := random_at_least y - p2 if y < p2
1150-
//
1136+
// NB: p2 = -p2
1137+
//
11511138
// to solve x for x >s b:
1152-
// infeasible if b + p2 = 0
1153-
// y := at least (b + 1 + p2) - p2
1154-
// TODO
1139+
// infeasible if b + 1 = p2
1140+
// solve for x >=s b + 1
11551141
//
11561142
bool sls_eval::try_repair_sle(bool e, bvval& a, bvval const& b) {
1157-
a.set(m_tmp, b.bits());
1158-
if (e) {
1159-
return a.set_repair(true, m_tmp);
1160-
}
1143+
auto& p2 = m_b;
1144+
b.set_zero(p2);
1145+
p2.set(b.bw - 1, true);
1146+
p2.set_bw(b.bw);
1147+
bool r = false;
1148+
if (e)
1149+
r = try_repair_sle(a, b.bits(), p2);
11611150
else {
1162-
a.set_add(m_tmp2, m_tmp, m_one);
1163-
return a.set_repair(false, m_tmp2);
1151+
auto& b1 = m_nexta;
1152+
a.set_add(b1, b.bits(), m_one);
1153+
if (p2 == b1)
1154+
r = false;
1155+
else
1156+
r = try_repair_sge(a, b1, p2);
11641157
}
1158+
p2.set_bw(0);
1159+
return r;
11651160
}
11661161

1162+
// to solve x for x <s b:
1163+
// infeasible if b = 0
1164+
// solve for x <=s b - 1
1165+
//
11671166
bool sls_eval::try_repair_sge(bool e, bvval& a, bvval const& b) {
1168-
a.set(m_tmp, b.bits());
1169-
if (e) {
1170-
return a.set_repair(false, m_tmp);
1167+
auto& p2 = m_b;
1168+
b.set_zero(p2);
1169+
p2.set(b.bw - 1, true);
1170+
p2.set_bw(b.bw);
1171+
bool r = false;
1172+
if (e)
1173+
r = try_repair_sge(a, b.bits(), p2);
1174+
else if (b.is_zero())
1175+
r = false;
1176+
else {
1177+
auto& b1 = m_nexta;
1178+
a.set_sub(b1, b.bits(), m_one);
1179+
b1.set_bw(b.bw);
1180+
r = try_repair_sle(a, b1, p2);
1181+
b1.set_bw(0);
11711182
}
1183+
p2.set_bw(0);
1184+
return r;
1185+
}
1186+
1187+
1188+
// to solve x for x <=s b:
1189+
// let c := b + p2
1190+
// solve for
1191+
// x + p2 <= c
1192+
//
1193+
// x := random x <= b or x >= p2 if c >= p2 (b < p2)
1194+
// or
1195+
// x := random p2 <= x <= b if c < p2 (b >= p2)
1196+
//
1197+
bool sls_eval::try_repair_sle(bvval& a, bvect const& b, bvect const& p2) {
1198+
bool r = false;
1199+
if (b < p2) {
1200+
bool coin = m_rand() % 2 == 0;
1201+
if (coin)
1202+
r = a.set_random_at_least(p2, m_tmp3, m_rand);
1203+
if (!r)
1204+
r = a.set_random_at_most(b, m_tmp3, m_rand);
1205+
if (!coin && !r)
1206+
r = a.set_random_at_least(p2, m_tmp3, m_rand);
1207+
}
1208+
else
1209+
r = a.set_random_in_range(p2, b, m_tmp3, m_rand);
1210+
return r;
1211+
}
1212+
1213+
// solve for x >=s b
1214+
//
1215+
// d := b + p2
1216+
//
1217+
// x := random b <= x < p2 if d >= p2 (b < p2)
1218+
// or
1219+
// x := random b <= x or x < p2 if d < p2
1220+
//
1221+
1222+
bool sls_eval::try_repair_sge(bvval& a, bvect const& b, bvect const& p2) {
1223+
auto& p2_1 = m_tmp4;
1224+
a.set_sub(p2_1, p2, m_one);
1225+
p2_1.set_bw(a.bw);
1226+
bool r = false;
1227+
if (b < p2)
1228+
// random b <= x < p2
1229+
r = a.set_random_in_range(b, p2_1, m_tmp3, m_rand);
11721230
else {
1173-
a.set_sub(m_tmp2, m_tmp, m_one);
1174-
return a.set_repair(true, m_tmp2);
1175-
}
1231+
// random b <= x or x < p2
1232+
bool coin = m_rand() % 2 == 0;
1233+
if (coin)
1234+
r = a.set_random_at_most(p2_1, m_tmp3, m_rand);
1235+
if (!r)
1236+
r = a.set_random_at_least(b, m_tmp3, m_rand);
1237+
if (!r && !coin)
1238+
r = a.set_random_at_most(p2_1, m_tmp3, m_rand);
1239+
}
1240+
p2_1.set_bw(0);
1241+
return r;
11761242
}
11771243

11781244
void sls_eval::add_p2_1(bvval const& a, bvect& t) const {
@@ -1182,30 +1248,30 @@ namespace bv {
11821248
a.clear_overflow_bits(t);
11831249
}
11841250

1185-
bool sls_eval::try_repair_ule(bool e, bvval& a, bvect const& t) {
1251+
bool sls_eval::try_repair_ule(bool e, bvval& a, bvval const& b) {
11861252
if (e) {
11871253
// a <= t
1188-
return a.set_random_at_most(t, m_tmp, m_rand);
1254+
return a.set_random_at_most(b.bits(), m_tmp, m_rand);
11891255
}
11901256
else {
11911257
// a > t
1192-
a.set_add(m_tmp, t, m_one);
1258+
a.set_add(m_tmp, b.bits(), m_one);
11931259
if (a.is_zero(m_tmp))
11941260
return false;
11951261
return a.set_random_at_least(m_tmp, m_tmp2, m_rand);
11961262
}
11971263
}
11981264

1199-
bool sls_eval::try_repair_uge(bool e, bvval& a, bvect const& t) {
1265+
bool sls_eval::try_repair_uge(bool e, bvval& a, bvval const& b) {
12001266
if (e) {
12011267
// a >= t
1202-
return a.set_random_at_least(t, m_tmp, m_rand);
1268+
return a.set_random_at_least(b.bits(), m_tmp, m_rand);
12031269
}
12041270
else {
12051271
// a < t
1206-
if (a.is_zero(t))
1272+
if (b.is_zero())
12071273
return false;
1208-
a.set_sub(m_tmp, t, m_one);
1274+
a.set_sub(m_tmp, b.bits(), m_one);
12091275
return a.set_random_at_most(m_tmp, m_tmp2, m_rand);
12101276
}
12111277
}

src/ast/sls/bv_sls_eval.h

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ namespace bv {
8989
bool try_repair_uge(bool e, bvval& a, bvval const& b);
9090
bool try_repair_sle(bool e, bvval& a, bvval const& b);
9191
bool try_repair_sge(bool e, bvval& a, bvval const& b);
92+
bool try_repair_sge(bvval& a, bvect const& b, bvect const& p2);
93+
bool try_repair_sle(bvval& a, bvect const& b, bvect const& p2);
9294
bool try_repair_shl(bvval const& e, bvval& a, bvval& b, unsigned i);
9395
bool try_repair_ashr(bvval const& e, bvval& a, bvval& b, unsigned i);
9496
bool try_repair_lshr(bvval const& e, bvval& a, bvval& b, unsigned i);

src/ast/sls/sls_valuation.cpp

+69-10
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,9 @@ namespace bv {
205205
if (is_zero(tmp) || (0 == r() % 2))
206206
return try_set(tmp);
207207

208-
208+
set_random_below(tmp, r);
209209
// random value below tmp
210-
auto msb_bit = msb(tmp);
211-
for (unsigned i = 0; i < nw; ++i)
212-
tmp[i] = (random_bits(r) & ~fixed[i]) | (fixed[i] & tmp[i]);
213-
for (unsigned i = msb_bit; i < bw; ++i)
214-
tmp.set(i, false);
210+
215211
if (m_lo == m_hi || is_zero(m_lo) || m_lo <= tmp)
216212
return try_set(tmp);
217213

@@ -226,17 +222,80 @@ namespace bv {
226222
return try_set(tmp);
227223

228224
// random value at least tmp
229-
auto msb_bit = msb(tmp);
230-
for (unsigned i = 0; i < nw; ++i)
231-
tmp[i] = (random_bits(r) & ~fixed[i]) | (fixed[i] & tmp[i]);
232-
tmp.set(msb_bit, true);
225+
set_random_above(tmp, r);
226+
233227
if (m_lo == m_hi || is_zero(m_hi) || m_hi > tmp)
234228
return try_set(tmp);
235229

236230
// for simplicity, bail out if we were not lucky
237231
return get_at_least(src, tmp) && try_set(tmp);
238232
}
239233

234+
bool sls_valuation::set_random_in_range(bvect const& lo, bvect const& hi, bvect& tmp, random_gen& r) {
235+
if (0 == r() % 2) {
236+
if (!get_at_least(lo, tmp))
237+
return false;
238+
SASSERT(in_range(tmp));
239+
if (hi < tmp)
240+
return false;
241+
242+
if (is_ones(tmp) || (0 == r() % 2))
243+
return try_set(tmp);
244+
set_random_above(tmp, r);
245+
round_down(tmp, [&](bvect const& t) { return hi >= t && in_range(t); });
246+
if (in_range(tmp) && lo <= tmp && hi >= tmp)
247+
return try_set(tmp);
248+
return get_at_least(lo, tmp) && hi >= tmp && try_set(tmp);
249+
}
250+
else {
251+
if (!get_at_most(hi, tmp))
252+
return false;
253+
SASSERT(in_range(tmp));
254+
if (lo > tmp)
255+
return false;
256+
if (is_zero(tmp) || (0 == r() % 2))
257+
return try_set(tmp);
258+
set_random_below(tmp, r);
259+
round_up(tmp, [&](bvect const& t) { return lo <= t && in_range(t); });
260+
if (in_range(tmp) && lo <= tmp && hi >= tmp)
261+
return try_set(tmp);
262+
return get_at_most(hi, tmp) && lo <= tmp && try_set(tmp);
263+
}
264+
}
265+
266+
void sls_valuation::round_down(bvect& dst, std::function<bool(bvect const&)> const& is_feasible) {
267+
for (unsigned i = bw; !is_feasible(dst) && i-- > 0; )
268+
if (!fixed.get(i) && dst.get(i))
269+
dst.set(i, false);
270+
}
271+
272+
void sls_valuation::round_up(bvect& dst, std::function<bool(bvect const&)> const& is_feasible) {
273+
for (unsigned i = 0; !is_feasible(dst) && i < bw; ++i)
274+
if (!fixed.get(i) && !dst.get(i))
275+
dst.set(i, true);
276+
}
277+
278+
void sls_valuation::set_random_above(bvect& dst, random_gen& r) {
279+
for (unsigned i = 0; i < nw; ++i)
280+
dst[i] = dst[i] | (random_bits(r) & ~fixed[i]);
281+
}
282+
283+
void sls_valuation::set_random_below(bvect& dst, random_gen& r) {
284+
if (is_zero(dst))
285+
return;
286+
unsigned n = 0, idx = UINT_MAX;
287+
for (unsigned i = 0; i < bw; ++i)
288+
if (dst.get(i) && !fixed.get(i) && (r() % ++n) == 0)
289+
idx = i;
290+
291+
if (idx == UINT_MAX)
292+
return;
293+
dst.set(idx, false);
294+
for (unsigned i = 0; i < idx; ++i)
295+
if (!fixed.get(i))
296+
dst.set(i, r() % 2 == 0);
297+
}
298+
240299
bool sls_valuation::set_repair(bool try_down, bvect& dst) {
241300
for (unsigned i = 0; i < nw; ++i)
242301
dst[i] = (~fixed[i] & dst[i]) | (fixed[i] & m_bits[i]);

src/ast/sls/sls_valuation.h

+5
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,13 @@ namespace bv {
188188

189189
bool set_random_at_most(bvect const& src, bvect& tmp, random_gen& r);
190190
bool set_random_at_least(bvect const& src, bvect& tmp, random_gen& r);
191+
bool set_random_in_range(bvect const& lo, bvect const& hi, bvect& tmp, random_gen& r);
191192

192193
bool set_repair(bool try_down, bvect& dst);
194+
void set_random_above(bvect& dst, random_gen& r);
195+
void set_random_below(bvect& dst, random_gen& r);
196+
void round_down(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
197+
void round_up(bvect& dst, std::function<bool(bvect const&)> const& is_feasible);
193198

194199

195200
static digit_t random_bits(random_gen& r);

0 commit comments

Comments
 (0)