@@ -1326,6 +1326,7 @@ namespace smt {
1326
1326
1327
1327
void theory_str::instantiate_axiom_Indexof(enode * e) {
1328
1328
context & ctx = get_context();
1329
+ th_rewriter & rw = ctx.get_rewriter();
1329
1330
ast_manager & m = get_manager();
1330
1331
1331
1332
app * ex = e->get_owner();
@@ -1345,13 +1346,21 @@ namespace smt {
1345
1346
}
1346
1347
axiomatized_terms.insert(ex);
1347
1348
1349
+ expr * exHaystack = nullptr;
1350
+ expr * exNeedle = nullptr;
1351
+ expr * exIndex = nullptr;
1352
+ u.str.is_index(ex, exHaystack, exNeedle, exIndex);
1353
+
1348
1354
TRACE("str", tout << "instantiate str.indexof axiom for " << mk_pp(ex, m) << std::endl;);
1349
1355
1350
1356
expr_ref x1(mk_str_var("x1"), m);
1351
1357
expr_ref x2(mk_str_var("x2"), m);
1352
1358
expr_ref indexAst(mk_int_var("index"), m);
1353
1359
1354
- expr_ref condAst(mk_contains(ex->get_arg(0), ex->get_arg(1)), m);
1360
+ expr_ref condAst1(mk_contains(ex->get_arg(0), ex->get_arg(1)), m);
1361
+ expr_ref condAst2(m.mk_not(ctx.mk_eq_atom(exNeedle, mk_string(""))), m);
1362
+ expr_ref condAst(m.mk_and(condAst1, condAst2), m);
1363
+ //expr_ref condAst(mk_contains(ex->get_arg(0), ex->get_arg(1)), m);
1355
1364
SASSERT(condAst);
1356
1365
1357
1366
// -----------------------
@@ -1376,7 +1385,11 @@ namespace smt {
1376
1385
1377
1386
// -----------------------
1378
1387
// false branch
1379
- expr_ref elseBranch(ctx.mk_eq_atom(indexAst, mk_int(-1)), m);
1388
+ expr_ref elseBranch(m.mk_ite(
1389
+ ctx.mk_eq_atom(exNeedle, mk_string("")),
1390
+ ctx.mk_eq_atom(indexAst, mk_int(0)),
1391
+ ctx.mk_eq_atom(indexAst, mk_int(-1))
1392
+ ), m);
1380
1393
SASSERT(elseBranch);
1381
1394
1382
1395
expr_ref breakdownAssert(m.mk_ite(condAst, thenBranch, elseBranch), m);
@@ -1386,7 +1399,7 @@ namespace smt {
1386
1399
SASSERT(reduceToIndex);
1387
1400
1388
1401
expr_ref finalAxiom(m.mk_and(breakdownAssert, reduceToIndex), m);
1389
- SASSERT (finalAxiom);
1402
+ rw (finalAxiom);
1390
1403
assert_axiom(finalAxiom);
1391
1404
1392
1405
{
@@ -1408,6 +1421,7 @@ namespace smt {
1408
1421
1409
1422
void theory_str::instantiate_axiom_Indexof_extended(enode * _e) {
1410
1423
context & ctx = get_context();
1424
+ th_rewriter & rw = ctx.get_rewriter();
1411
1425
ast_manager & m = get_manager();
1412
1426
1413
1427
app * e = _e->get_owner();
@@ -1436,6 +1450,7 @@ namespace smt {
1436
1450
1437
1451
expr_ref minus_one(m_autil.mk_numeral(rational::minus_one(), true), m);
1438
1452
expr_ref zero(m_autil.mk_numeral(rational::zero(), true), m);
1453
+ expr_ref empty_string(mk_string(""), m);
1439
1454
1440
1455
// case split
1441
1456
@@ -1446,9 +1461,40 @@ namespace smt {
1446
1461
assert_implication(premise, conclusion);
1447
1462
}
1448
1463
1464
+ // case 1.1: N == "" and i out of range
1465
+ {
1466
+ expr_ref premiseNEmpty(ctx.mk_eq_atom(N, empty_string), m);
1467
+ // range check
1468
+ expr_ref premiseRangeLower(m_autil.mk_le(i, minus_one), m);
1469
+ expr_ref premiseRangeUpper(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero), m);
1470
+ expr_ref premiseRange(m.mk_or(premiseRangeLower, premiseRangeUpper), m);
1471
+ expr_ref premise(m.mk_and(premiseNEmpty, premiseRange), m);
1472
+ expr_ref conclusion(ctx.mk_eq_atom(e, minus_one), m);
1473
+ expr_ref finalAxiom(rewrite_implication(premise, conclusion), m);
1474
+ rw(finalAxiom);
1475
+ assert_axiom(finalAxiom);
1476
+ }
1477
+
1478
+ // case 1.2: N == "" and i within range
1479
+ {
1480
+ expr_ref premiseNEmpty(ctx.mk_eq_atom(N, empty_string), m);
1481
+ // range check
1482
+ expr_ref premiseRangeLower(m_autil.mk_le(i, minus_one), m);
1483
+ expr_ref premiseRangeUpper(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero), m);
1484
+ expr_ref premiseRange(m.mk_not(m.mk_or(premiseRangeLower, premiseRangeUpper)), m);
1485
+ expr_ref premise(m.mk_and(premiseNEmpty, premiseRange), m);
1486
+ expr_ref conclusion(ctx.mk_eq_atom(e, i), m);
1487
+ expr_ref finalAxiom(rewrite_implication(premise, conclusion), m);
1488
+ rw(finalAxiom);
1489
+ assert_axiom(finalAxiom);
1490
+ }
1491
+
1449
1492
// case 2: i = 0
1450
1493
{
1451
- expr_ref premise(ctx.mk_eq_atom(i, zero), m);
1494
+ expr_ref premise1(ctx.mk_eq_atom(i, zero), m);
1495
+ expr_ref premise2(m.mk_not(ctx.mk_eq_atom(N, empty_string)), m);
1496
+ expr_ref premise(m.mk_and(premise1, premise2), m);
1497
+ rw(premise);
1452
1498
// reduction to simpler case
1453
1499
expr_ref conclusion(ctx.mk_eq_atom(e, mk_indexof(H, N)), m);
1454
1500
assert_implication(premise, conclusion);
@@ -1459,7 +1505,10 @@ namespace smt {
1459
1505
//expr_ref premise(_premise);
1460
1506
//th_rewriter rw(m);
1461
1507
//rw(premise);
1462
- expr_ref premise(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero), m);
1508
+ expr_ref premise1(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero), m);
1509
+ expr_ref premise2(m.mk_not(ctx.mk_eq_atom(N, empty_string)), m);
1510
+ expr_ref premise(m.mk_and(premise1, premise2), m);
1511
+ rw(premise);
1463
1512
expr_ref conclusion(ctx.mk_eq_atom(e, minus_one), m);
1464
1513
assert_implication(premise, conclusion);
1465
1514
}
@@ -1469,15 +1518,21 @@ namespace smt {
1469
1518
expr_ref conclusion(ctx.mk_eq_atom(e, minus_one), m);
1470
1519
assert_implication(premise, conclusion);
1471
1520
}
1472
- // case 4: 0 < i < len(H) and H contains N
1521
+ // case 4: 0 < i < len(H), N non-empty, and H contains N
1473
1522
{
1474
1523
expr_ref premise1(m_autil.mk_gt(i, zero), m);
1475
1524
//expr_ref premise2(m_autil.mk_lt(i, mk_strlen(H)), m);
1476
1525
expr_ref premise2(m.mk_not(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero)), m);
1477
1526
expr_ref premise3(u.str.mk_contains(H, N), m);
1478
- expr_ref _premise(m.mk_and(premise1, premise2, premise3), m);
1527
+ expr_ref premise4(m.mk_not(ctx.mk_eq_atom(N, mk_string(""))), m);
1528
+
1529
+ expr_ref_vector premises(m);
1530
+ premises.push_back(premise1);
1531
+ premises.push_back(premise2);
1532
+ premises.push_back(premise3);
1533
+ premises.push_back(premise4);
1534
+ expr_ref _premise(mk_and(premises), m);
1479
1535
expr_ref premise(_premise);
1480
- th_rewriter rw(m);
1481
1536
rw(premise);
1482
1537
1483
1538
expr_ref hd(mk_str_var("hd"), m);
@@ -1500,9 +1555,8 @@ namespace smt {
1500
1555
expr_ref precondition1(m_autil.mk_gt(i, minus_one), m);
1501
1556
//expr_ref precondition2(m_autil.mk_lt(i, mk_strlen(H)), m);
1502
1557
expr_ref precondition2(m.mk_not(m_autil.mk_ge(m_autil.mk_add(i, m_autil.mk_mul(minus_one, mk_strlen(H))), zero)), m);
1503
- expr_ref _precondition(m.mk_and(precondition1, precondition2), m);
1504
- expr_ref precondition(_precondition);
1505
- th_rewriter rw(m);
1558
+ expr_ref precondition3(m.mk_not(ctx.mk_eq_atom(N, mk_string(""))), m);
1559
+ expr_ref precondition(m.mk_and(precondition1, precondition2, precondition3), m);
1506
1560
rw(precondition);
1507
1561
1508
1562
expr_ref premise(u.str.mk_contains(H, N), m);
0 commit comments