|
| 1 | +/* |
| 2 | + * Copyright (c) 2024, Martin Blicha <[email protected]> |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: MIT |
| 5 | + */ |
| 6 | + |
| 7 | +#include <gtest/gtest.h> |
| 8 | +#include <ArithLogic.h> |
| 9 | +#include <MainSolver.h> |
| 10 | +#include <SMTConfig.h> |
| 11 | + |
| 12 | +#include <memory> |
| 13 | + |
| 14 | +class UFUnsatCoreTest : public ::testing::Test { |
| 15 | +protected: |
| 16 | + UFUnsatCoreTest(): logic{opensmt::Logic_t::QF_UF} {} |
| 17 | + void SetUp() override { |
| 18 | + ufsort = logic.declareUninterpretedSort("U"); |
| 19 | + x = logic.mkVar(ufsort, "x"); |
| 20 | + y = logic.mkVar(ufsort, "y"); |
| 21 | + f = logic.declareFun("f", ufsort, {ufsort}); |
| 22 | + g = logic.declareFun("g", ufsort, {ufsort, ufsort}); |
| 23 | + p = logic.declareFun("p", logic.getSort_bool(), {ufsort}); |
| 24 | + b1 = logic.mkBoolVar("b1"); |
| 25 | + b2 = logic.mkBoolVar("b2"); |
| 26 | + b3 = logic.mkBoolVar("b3"); |
| 27 | + b4 = logic.mkBoolVar("b4"); |
| 28 | + b5 = logic.mkBoolVar("b5"); |
| 29 | + nb1 = logic.mkNot(b1); |
| 30 | + nb2 = logic.mkNot(b2); |
| 31 | + nb3 = logic.mkNot(b3); |
| 32 | + nb4 = logic.mkNot(b4); |
| 33 | + nb5 = logic.mkNot(b5); |
| 34 | + } |
| 35 | + Logic logic; |
| 36 | + SMTConfig config; |
| 37 | + SRef ufsort; |
| 38 | + PTRef x, y, b1, b2, b3, b4, b5; |
| 39 | + PTRef nb1, nb2, nb3, nb4, nb5; |
| 40 | + SymRef f, g, p; |
| 41 | + |
| 42 | + MainSolver makeSolver() { |
| 43 | + const char* msg = "ok"; |
| 44 | + config.setOption(SMTConfig::o_produce_unsat_cores, SMTOption(true), msg); |
| 45 | + return {logic, config, "unsat_core"}; |
| 46 | + } |
| 47 | +}; |
| 48 | + |
| 49 | +TEST_F(UFUnsatCoreTest, Bool_Simple) { |
| 50 | + MainSolver solver = makeSolver(); |
| 51 | + solver.insertFormula(b1); |
| 52 | + solver.insertFormula(b2); |
| 53 | + solver.insertFormula(nb1); |
| 54 | + auto res = solver.check(); |
| 55 | + ASSERT_EQ(res, s_False); |
| 56 | + auto core = solver.getUnsatCore(); |
| 57 | + ASSERT_EQ(core.size(), 2); |
| 58 | + EXPECT_TRUE(core[0] == b1 or core[1] == b1); |
| 59 | + EXPECT_TRUE(core[0] == nb1 or core[1] == nb1); |
| 60 | +} |
| 61 | + |
| 62 | +TEST_F(UFUnsatCoreTest, Bool_ReuseProofChain) { |
| 63 | + // We add three assertions |
| 64 | + // a1 := (b1 or b2) and (b1 or ~b2) |
| 65 | + // a2 := (~b1 or b3) and (~b1 or ~b3) |
| 66 | + // a3 := b4 |
| 67 | + // The first two assertions form the unsat core. |
| 68 | + MainSolver solver = makeSolver(); |
| 69 | + PTRef c1 = logic.mkOr(b1, b2); |
| 70 | + PTRef c2 = logic.mkOr(b1, nb2); |
| 71 | + PTRef c3 = logic.mkOr(nb1, b3); |
| 72 | + PTRef c4 = logic.mkOr(nb1, nb3); |
| 73 | + PTRef a1 = logic.mkAnd(c1,c2); |
| 74 | + PTRef a2 = logic.mkAnd(c3,c4); |
| 75 | + solver.insertFormula(a1); |
| 76 | + solver.insertFormula(a2); |
| 77 | + solver.insertFormula(b4); |
| 78 | + auto res = solver.check(); |
| 79 | + ASSERT_EQ(res, s_False); |
| 80 | + auto core = solver.getUnsatCore(); |
| 81 | + ASSERT_EQ(core.size(), 2); |
| 82 | + EXPECT_TRUE(core[0] == a1 or core[1] == a1); |
| 83 | + EXPECT_TRUE(core[0] == a2 or core[1] == a2); |
| 84 | +} |
0 commit comments