diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-07 03:59:58 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-07 03:59:58 +0800 |
| commit | 5ab3efd522cf0221481684b5bbc9c2ac6bfc9919 (patch) | |
| tree | 9c521dedd2bc49bdbac642a0640dd048b6d8e4a1 /tests | |
| parent | bf4f464cec8b6515d9e5131d43847ef9b2fd21d1 (diff) | |
| download | ratp-5ab3efd522cf0221481684b5bbc9c2ac6bfc9919.tar.gz ratp-5ab3efd522cf0221481684b5bbc9c2ac6bfc9919.tar.xz | |
refactor: rename struct members to follow trailing underscore naming convention across core, search, and frontend components
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_end_to_end.cc | 11 | ||||
| -rw-r--r-- | tests/test_proof_trace.cc | 126 | ||||
| -rw-r--r-- | tests/test_prover.cc | 131 | ||||
| -rw-r--r-- | tests/test_resolution.cc | 190 | ||||
| -rw-r--r-- | tests/test_simplify.cc | 102 | ||||
| -rw-r--r-- | tests/test_term_bank.cc | 262 | ||||
| -rw-r--r-- | tests/test_unification.cc | 228 |
7 files changed, 531 insertions, 519 deletions
diff --git a/tests/test_end_to_end.cc b/tests/test_end_to_end.cc index d45a101..ceb9991 100644 --- a/tests/test_end_to_end.cc +++ b/tests/test_end_to_end.cc @@ -28,14 +28,15 @@ #include <gtest/gtest.h> #include <string> +#include <utility> namespace atp { namespace { /// Helper: parse a TPTP string and run the prover, return the result. struct E2EResult { - ProverResult result; - std::string proof_output; + ProverResult result_; + std::string proof_output_; }; E2EResult runProver(const std::string& tptp_input) { @@ -48,7 +49,7 @@ E2EResult runProver(const std::string& tptp_input) { Prover prover(bank, store); prover.addClauses(std::move(clauses)); - ProverResult result = prover.prove(); + ProverResult const result = prover.prove(); std::string proof_output; if (result == ProverResult::kTheorem) { @@ -140,10 +141,10 @@ TEST(EndToEnd, ProofOutputContainsAllSteps) { // Must contain [resolution] for derived clauses EXPECT_NE(proof.find("[resolution]"), std::string::npos) << proof; // Must contain empty clause marker - std::string empty_marker = "□"; + std::string const empty_marker = "□"; EXPECT_NE(proof.find(empty_marker), std::string::npos) << proof; // Must contain [X, Y] provenance (sequential numbers) - EXPECT_NE(proof.find("["), std::string::npos) << proof; + EXPECT_NE(proof.find('['), std::string::npos) << proof; } // ═══════════════════════════════════════════════════════════════════════════ diff --git a/tests/test_proof_trace.cc b/tests/test_proof_trace.cc index 5e12060..f2c3c96 100644 --- a/tests/test_proof_trace.cc +++ b/tests/test_proof_trace.cc @@ -27,43 +27,45 @@ #include <gtest/gtest.h> #include <string> +#include <utility> +#include <vector> namespace atp { namespace { class ProofTraceTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; - ClauseStore store; + SymbolTable symbols_; + TermBank bank_{symbols_}; + ClauseStore store_; - SymbolId sym_a{}, sym_b{}; - SymbolId sym_P{}, sym_Q{}; - SymbolId sym_X{}; + SymbolId sym_a_{}, sym_b_{}; + SymbolId sym_p_{}, sym_q_{}; + SymbolId sym_x_{}; - TermId a_term{}, b_term{}, X_term{}; + TermId a_term_{}, b_term_{}, x_term_{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_P = symbols.intern("P", SymbolKind::kPredicate, 1); - sym_Q = symbols.intern("Q", SymbolKind::kPredicate, 1); - sym_X = symbols.intern("X", SymbolKind::kVariable); - - a_term = bank.makeTerm(sym_a, {}); - b_term = bank.makeTerm(sym_b, {}); - X_term = bank.makeVar(sym_X); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_p_ = symbols_.intern("P", SymbolKind::kPredicate, 1); + sym_q_ = symbols_.intern("Q", SymbolKind::kPredicate, 1); + sym_x_ = symbols_.intern("X", SymbolKind::kVariable); + + a_term_ = bank_.makeTerm(sym_a_, {}); + b_term_ = bank_.makeTerm(sym_b_, {}); + x_term_ = bank_.makeVar(sym_x_); } - TermId P(TermId arg) { return bank.makeTerm(sym_P, {{arg}}); } - TermId Q(TermId arg) { return bank.makeTerm(sym_Q, {{arg}}); } + TermId p(TermId arg) { return bank_.makeTerm(sym_p_, {{arg}}); } + TermId q(TermId arg) { return bank_.makeTerm(sym_q_, {{arg}}); } - Literal pos(TermId atom) { return {.atom = atom, .is_positive = true}; } - Literal neg(TermId atom) { return {.atom = atom, .is_positive = false}; } + static Literal pos(TermId atom) { return {.atom_ = atom, .is_positive_ = true}; } + static Literal neg(TermId atom) { return {.atom_ = atom, .is_positive_ = false}; } - Clause makeClause(std::vector<Literal> lits) { + static Clause makeClause(std::vector<Literal> lits) { Clause cl; - cl.literals = std::move(lits); + cl.literals_ = std::move(lits); return cl; } }; @@ -73,23 +75,23 @@ class ProofTraceTest : public ::testing::Test { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProofTraceTest, TermToStringConstant) { - EXPECT_EQ(termToString(a_term, bank), "a"); + EXPECT_EQ(termToString(a_term_, bank_), "a"); } TEST_F(ProofTraceTest, TermToStringVariable) { - EXPECT_EQ(termToString(X_term, bank), "X"); + EXPECT_EQ(termToString(x_term_, bank_), "X"); } TEST_F(ProofTraceTest, TermToStringCompound) { - TermId pa = P(a_term); - EXPECT_EQ(termToString(pa, bank), "P(a)"); + TermId const pa = p(a_term_); + EXPECT_EQ(termToString(pa, bank_), "P(a)"); } TEST_F(ProofTraceTest, TermToStringNested) { - SymbolId sym_f = symbols.intern("f", SymbolKind::kFunction, 1); - TermId fa = bank.makeTerm(sym_f, {{a_term}}); - TermId pfa = P(fa); - EXPECT_EQ(termToString(pfa, bank), "P(f(a))"); + SymbolId const sym_f = symbols_.intern("f", SymbolKind::kFunction, 1); + TermId const fa = bank_.makeTerm(sym_f, {{a_term_}}); + TermId const pfa = p(fa); + EXPECT_EQ(termToString(pfa, bank_), "P(f(a))"); } // ═══════════════════════════════════════════════════════════════════════════ @@ -97,23 +99,23 @@ TEST_F(ProofTraceTest, TermToStringNested) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProofTraceTest, ClauseToStringEmpty) { - Clause empty = makeClause({}); - EXPECT_EQ(clauseToString(empty, bank), "□"); + Clause const empty = makeClause({}); + EXPECT_EQ(clauseToString(empty, bank_), "□"); } TEST_F(ProofTraceTest, ClauseToStringSinglePositive) { - Clause c = makeClause({pos(P(a_term))}); - EXPECT_EQ(clauseToString(c, bank), "P(a)"); + Clause const c = makeClause({pos(p(a_term_))}); + EXPECT_EQ(clauseToString(c, bank_), "P(a)"); } TEST_F(ProofTraceTest, ClauseToStringSingleNegative) { - Clause c = makeClause({neg(P(a_term))}); - EXPECT_EQ(clauseToString(c, bank), "¬P(a)"); + Clause const c = makeClause({neg(p(a_term_))}); + EXPECT_EQ(clauseToString(c, bank_), "¬P(a)"); } TEST_F(ProofTraceTest, ClauseToStringMultipleLiterals) { - Clause c = makeClause({neg(P(X_term)), pos(Q(X_term))}); - std::string s = clauseToString(c, bank); + Clause const c = makeClause({neg(p(x_term_)), pos(q(x_term_))}); + std::string const s = clauseToString(c, bank_); EXPECT_EQ(s, "¬P(X) ∨ Q(X)"); } @@ -123,42 +125,42 @@ TEST_F(ProofTraceTest, ClauseToStringMultipleLiterals) { TEST_F(ProofTraceTest, ExtractProofTrivial) { // Run a trivial proof: {P(a)} + {¬P(a)} → □ - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a_term))}), makeClause({neg(P(a_term))})}); - ProverResult result = prover.prove(); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_term_))}), makeClause({neg(p(a_term_))})}); + ProverResult const result = prover.prove(); ASSERT_EQ(result, ProverResult::kTheorem); auto eid = prover.getEmptyClauseId(); ASSERT_TRUE(eid.has_value()); - auto proof = extractProof(store, *eid); - ASSERT_GE(proof.size(), 3u); // At least: 2 axioms + 1 empty clause + auto proof = extractProof(store_, *eid); + ASSERT_GE(proof.size(), 3U); // At least: 2 axioms + 1 empty clause // First steps should be axioms (kInput) - EXPECT_EQ(proof.front().rule, InferenceRule::kInput); + EXPECT_EQ(proof.front().rule_, InferenceRule::kInput); // Last step should be the empty clause - EXPECT_EQ(proof.back().clause_id, *eid); + EXPECT_EQ(proof.back().clause_id_, *eid); // Last step should be resolution - EXPECT_EQ(proof.back().rule, InferenceRule::kResolution); + EXPECT_EQ(proof.back().rule_, InferenceRule::kResolution); } TEST_F(ProofTraceTest, ExtractProofTwoStep) { // {P(a)}, {¬P(X), Q(X)}, {¬Q(a)} → □ in 2 resolution steps - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a_term))}), makeClause({neg(P(X_term)), pos(Q(X_term))}), - makeClause({neg(Q(a_term))})}); - ProverResult result = prover.prove(); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_term_))}), makeClause({neg(p(x_term_)), pos(q(x_term_))}), + makeClause({neg(q(a_term_))})}); + ProverResult const result = prover.prove(); ASSERT_EQ(result, ProverResult::kTheorem); auto eid = prover.getEmptyClauseId(); ASSERT_TRUE(eid.has_value()); - auto proof = extractProof(store, *eid); + auto proof = extractProof(store_, *eid); // Should have axioms + intermediate + empty clause - ASSERT_GE(proof.size(), 4u); // 3 axioms + at least 1 intermediate + empty + ASSERT_GE(proof.size(), 4U); // 3 axioms + at least 1 intermediate + empty // Last step is the empty clause - EXPECT_EQ(proof.back().clause_id, *eid); + EXPECT_EQ(proof.back().clause_id_, *eid); } // ═══════════════════════════════════════════════════════════════════════════ @@ -166,33 +168,33 @@ TEST_F(ProofTraceTest, ExtractProofTwoStep) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProofTraceTest, FormatProofContainsExpectedElements) { - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a_term))}), makeClause({neg(P(a_term))})}); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_term_))}), makeClause({neg(p(a_term_))})}); prover.prove(); auto eid = prover.getEmptyClauseId(); ASSERT_TRUE(eid.has_value()); - auto proof = extractProof(store, *eid); - std::string output = formatProof(proof, store, bank); + auto proof = extractProof(store_, *eid); + std::string const output = formatProof(proof, store_, bank_); // Should contain key elements EXPECT_NE(output.find("input"), std::string::npos) << output; EXPECT_NE(output.find("resolution"), std::string::npos) << output; EXPECT_NE(output.find("P(a)"), std::string::npos) << output; // Empty clause should appear - std::string empty_marker = "□"; + std::string const empty_marker = "□"; EXPECT_NE(output.find(empty_marker), std::string::npos) << output; } TEST_F(ProofTraceTest, FormatProofNoParentsForAxioms) { - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a_term))}), makeClause({neg(P(a_term))})}); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_term_))}), makeClause({neg(p(a_term_))})}); prover.prove(); auto eid = prover.getEmptyClauseId(); - auto proof = extractProof(store, *eid); - std::string output = formatProof(proof, store, bank); + auto proof = extractProof(store_, *eid); + std::string const output = formatProof(proof, store_, bank_); // The first line (an axiom) should NOT have "[from ...]" // Find the first newline diff --git a/tests/test_prover.cc b/tests/test_prover.cc index ada1af2..74d02ad 100644 --- a/tests/test_prover.cc +++ b/tests/test_prover.cc @@ -25,50 +25,53 @@ #include "atp/search/prover.h" #include <gtest/gtest.h> +#include <utility> +#include <vector> namespace atp { namespace { class ProverTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; - ClauseStore store; + SymbolTable symbols_; + TermBank bank_{symbols_}; + ClauseStore store_; - SymbolId sym_a{}, sym_b{}; - SymbolId sym_f{}; - SymbolId sym_P{}, sym_Q{}, sym_R{}; - SymbolId sym_X{}, sym_Y{}; + SymbolId sym_a_{}, sym_b_{}; + SymbolId sym_f_{}; + SymbolId sym_p_{}, sym_q_{}, sym_r_{}; + SymbolId sym_x_{}, sym_y_{}; + + TermId a_{}, b_{}, x_{}, y_{}; - TermId a{}, b{}, X{}, Y{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_f = symbols.intern("f", SymbolKind::kFunction, 1); - sym_P = symbols.intern("P", SymbolKind::kPredicate, 1); - sym_Q = symbols.intern("Q", SymbolKind::kPredicate, 1); - sym_R = symbols.intern("R", SymbolKind::kPredicate, 2); - sym_X = symbols.intern("X", SymbolKind::kVariable); - sym_Y = symbols.intern("Y", SymbolKind::kVariable); - - a = bank.makeTerm(sym_a, {}); - b = bank.makeTerm(sym_b, {}); - X = bank.makeVar(sym_X); - Y = bank.makeVar(sym_Y); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_f_ = symbols_.intern("f", SymbolKind::kFunction, 1); + sym_p_ = symbols_.intern("P", SymbolKind::kPredicate, 1); + sym_q_ = symbols_.intern("Q", SymbolKind::kPredicate, 1); + sym_r_ = symbols_.intern("R", SymbolKind::kPredicate, 2); + sym_x_ = symbols_.intern("X", SymbolKind::kVariable); + sym_y_ = symbols_.intern("Y", SymbolKind::kVariable); + + a_ = bank_.makeTerm(sym_a_, {}); + b_ = bank_.makeTerm(sym_b_, {}); + x_ = bank_.makeVar(sym_x_); + y_ = bank_.makeVar(sym_y_); } - TermId P(TermId arg) { return bank.makeTerm(sym_P, {{arg}}); } - TermId Q(TermId arg) { return bank.makeTerm(sym_Q, {{arg}}); } - TermId R(TermId a1, TermId a2) { return bank.makeTerm(sym_R, {{a1, a2}}); } - TermId f(TermId arg) { return bank.makeTerm(sym_f, {{arg}}); } + TermId p(TermId arg) { return bank_.makeTerm(sym_p_, {{arg}}); } + TermId q(TermId arg) { return bank_.makeTerm(sym_q_, {{arg}}); } + TermId r(TermId a1, TermId a2) { return bank_.makeTerm(sym_r_, {{a1, a2}}); } + TermId f(TermId arg) { return bank_.makeTerm(sym_f_, {{arg}}); } - Literal pos(TermId atom) { return {.atom = atom, .is_positive = true}; } - Literal neg(TermId atom) { return {.atom = atom, .is_positive = false}; } + static Literal pos(TermId atom) { return {.atom_ = atom, .is_positive_ = true}; } + static Literal neg(TermId atom) { return {.atom_ = atom, .is_positive_ = false}; } - Clause makeClause(std::vector<Literal> lits) { + static Clause makeClause(std::vector<Literal> lits) { Clause cl; - cl.literals = std::move(lits); + cl.literals_ = std::move(lits); return cl; } }; @@ -78,11 +81,11 @@ class ProverTest : public ::testing::Test { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, TrivialRefutation) { - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a))}), makeClause({neg(P(a))})}); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_))}), makeClause({neg(p(a_))})}); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTheorem); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTheorem); EXPECT_TRUE(prover.getEmptyClauseId().has_value()); } @@ -91,11 +94,11 @@ TEST_F(ProverTest, TrivialRefutation) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, RefutationWithUnification) { - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(X))}), makeClause({neg(P(a))})}); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(x_))}), makeClause({neg(p(a_))})}); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTheorem); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTheorem); } // ═══════════════════════════════════════════════════════════════════════════ @@ -105,12 +108,12 @@ TEST_F(ProverTest, RefutationWithUnification) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, TwoStepRefutation) { - Prover prover(bank, store); + Prover prover(bank_, store_); prover.addClauses( - {makeClause({pos(P(a))}), makeClause({neg(P(X)), pos(Q(X))}), makeClause({neg(Q(a))})}); + {makeClause({pos(p(a_))}), makeClause({neg(p(x_)), pos(q(x_))}), makeClause({neg(q(a_))})}); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTheorem); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTheorem); } // ═══════════════════════════════════════════════════════════════════════════ @@ -118,11 +121,11 @@ TEST_F(ProverTest, TwoStepRefutation) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, Saturation) { - Prover prover(bank, store); - prover.addClauses({makeClause({pos(P(a))}), makeClause({pos(Q(b))})}); + Prover prover(bank_, store_); + prover.addClauses({makeClause({pos(p(a_))}), makeClause({pos(q(b_))})}); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kSaturation); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kSaturation); } // ═══════════════════════════════════════════════════════════════════════════ @@ -131,15 +134,15 @@ TEST_F(ProverTest, Saturation) { TEST_F(ProverTest, Timeout) { ProverConfig config; - config.max_iterations = 1; + config.max_iterations_ = 1; // Need enough clauses to not saturate in 1 iteration - Prover prover(bank, store, config); - prover.addClauses({makeClause({pos(P(X)), pos(Q(X))}), makeClause({neg(P(a)), pos(Q(a))}), - makeClause({neg(Q(X)), pos(P(f(X)))}), makeClause({neg(P(X)), neg(Q(X))})}); + Prover prover(bank_, store_, config); + prover.addClauses({makeClause({pos(p(x_)), pos(q(x_))}), makeClause({neg(p(a_)), pos(q(a_))}), + makeClause({neg(q(x_)), pos(p(f(x_)))}), makeClause({neg(p(x_)), neg(q(x_))})}); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTimeout); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTimeout); } // ═══════════════════════════════════════════════════════════════════════════ @@ -147,19 +150,19 @@ TEST_F(ProverTest, Timeout) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, ThreeStepChain) { - SymbolId sym_S = symbols.intern("S", SymbolKind::kPredicate, 1); - auto S = [&](TermId arg) { return bank.makeTerm(sym_S, {{arg}}); }; + const SymbolId kSymS = symbols_.intern("S", SymbolKind::kPredicate, 1); + auto s = [&](TermId arg) { return bank_.makeTerm(kSymS, {{arg}}); }; - Prover prover(bank, store); + Prover prover(bank_, store_); prover.addClauses({ - makeClause({pos(P(a))}), // P(a) - makeClause({neg(P(X)), pos(Q(X))}), // ¬P(X) ∨ Q(X) - makeClause({neg(Q(X)), pos(S(X))}), // ¬Q(X) ∨ S(X) - makeClause({neg(S(a))}) // ¬S(a) + makeClause({pos(p(a_))}), // P(a) + makeClause({neg(p(x_)), pos(q(x_))}), // ¬P(X) ∨ Q(X) + makeClause({neg(q(x_)), pos(s(x_))}), // ¬Q(X) ∨ S(X) + makeClause({neg(s(a_))}) // ¬S(a) }); - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTheorem); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTheorem); } // ═══════════════════════════════════════════════════════════════════════════ @@ -167,13 +170,13 @@ TEST_F(ProverTest, ThreeStepChain) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ProverTest, EmptyClauseInInput) { - Prover prover(bank, store); + Prover prover(bank_, store_); prover.addClauses({makeClause({}), // empty clause directly - makeClause({pos(P(a))})}); + makeClause({pos(p(a_))})}); // Empty clause should be detected immediately when selected from queue - ProverResult result = prover.prove(); - EXPECT_EQ(result, ProverResult::kTheorem); + const ProverResult kResult = prover.prove(); + EXPECT_EQ(kResult, ProverResult::kTheorem); } } // namespace diff --git a/tests/test_resolution.cc b/tests/test_resolution.cc index 931635d..02250d9 100644 --- a/tests/test_resolution.cc +++ b/tests/test_resolution.cc @@ -22,62 +22,62 @@ #include "atp/core/term_bank.h" #include "atp/core/types.h" #include "atp/infer/resolution.h" -#include "atp/infer/substitution.h" -#include "atp/infer/unification.h" #include <gtest/gtest.h> +#include <utility> +#include <vector> namespace atp { namespace { class ResolutionTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; + SymbolTable symbols_; + TermBank bank_{symbols_}; - SymbolId sym_a{}, sym_b{}, sym_c{}; - SymbolId sym_f{}; - SymbolId sym_P{}, sym_Q{}, sym_R{}; - SymbolId sym_X{}, sym_Y{}, sym_Z{}; + SymbolId sym_a_{}, sym_b_{}, sym_c_{}; + SymbolId sym_f_{}; + SymbolId sym_p_{}, sym_q_{}, sym_r_{}; + SymbolId sym_x_{}, sym_y_{}, sym_z_{}; - TermId a{}, b{}, c{}; - TermId X{}, Y{}, Z{}; + TermId a_{}, b_{}, c_{}; + TermId x_{}, y_{}, z_{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_c = symbols.intern("c", SymbolKind::kConstant); - sym_f = symbols.intern("f", SymbolKind::kFunction, 1); - sym_P = symbols.intern("P", SymbolKind::kPredicate, 1); - sym_Q = symbols.intern("Q", SymbolKind::kPredicate, 1); - sym_R = symbols.intern("R", SymbolKind::kPredicate, 2); - sym_X = symbols.intern("X", SymbolKind::kVariable); - sym_Y = symbols.intern("Y", SymbolKind::kVariable); - sym_Z = symbols.intern("Z", SymbolKind::kVariable); - - a = bank.makeTerm(sym_a, {}); - b = bank.makeTerm(sym_b, {}); - c = bank.makeTerm(sym_c, {}); - X = bank.makeVar(sym_X); - Y = bank.makeVar(sym_Y); - Z = bank.makeVar(sym_Z); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_c_ = symbols_.intern("c", SymbolKind::kConstant); + sym_f_ = symbols_.intern("f", SymbolKind::kFunction, 1); + sym_p_ = symbols_.intern("P", SymbolKind::kPredicate, 1); + sym_q_ = symbols_.intern("Q", SymbolKind::kPredicate, 1); + sym_r_ = symbols_.intern("R", SymbolKind::kPredicate, 2); + sym_x_ = symbols_.intern("X", SymbolKind::kVariable); + sym_y_ = symbols_.intern("Y", SymbolKind::kVariable); + sym_z_ = symbols_.intern("Z", SymbolKind::kVariable); + + a_ = bank_.makeTerm(sym_a_, {}); + b_ = bank_.makeTerm(sym_b_, {}); + c_ = bank_.makeTerm(sym_c_, {}); + x_ = bank_.makeVar(sym_x_); + y_ = bank_.makeVar(sym_y_); + z_ = bank_.makeVar(sym_z_); } - TermId P(TermId arg) { return bank.makeTerm(sym_P, {{arg}}); } - TermId Q(TermId arg) { return bank.makeTerm(sym_Q, {{arg}}); } - TermId R(TermId a1, TermId a2) { return bank.makeTerm(sym_R, {{a1, a2}}); } - TermId f(TermId arg) { return bank.makeTerm(sym_f, {{arg}}); } + TermId p(TermId arg) { return bank_.makeTerm(sym_p_, {{arg}}); } + TermId q(TermId arg) { return bank_.makeTerm(sym_q_, {{arg}}); } + TermId r(TermId a1, TermId a2) { return bank_.makeTerm(sym_r_, {{a1, a2}}); } + TermId f(TermId arg) { return bank_.makeTerm(sym_f_, {{arg}}); } // Helper: make a clause from literals - Clause makeClause(std::vector<Literal> lits, ClauseId id = kInvalidId) { + static Clause makeClause(std::vector<Literal> lits, ClauseId id = kInvalidId) { Clause c; - c.id = id; - c.literals = std::move(lits); + c.id_ = id; + c.literals_ = std::move(lits); return c; } - Literal pos(TermId atom) { return {.atom = atom, .is_positive = true}; } - Literal neg(TermId atom) { return {.atom = atom, .is_positive = false}; } + static Literal pos(TermId atom) { return {.atom_ = atom, .is_positive_ = true}; } + static Literal neg(TermId atom) { return {.atom_ = atom, .is_positive_ = false}; } }; // ═══════════════════════════════════════════════════════════════════════════ @@ -86,86 +86,86 @@ class ResolutionTest : public ::testing::Test { TEST_F(ResolutionTest, SimpleGroundResolution) { // {P(a)} and {¬P(a), Q(b)} → {Q(b)} - Clause c1 = makeClause({pos(P(a))}, 0); - Clause c2 = makeClause({neg(P(a)), pos(Q(b))}, 1); + Clause const c1 = makeClause({pos(p(a_))}, 0); + Clause const c2 = makeClause({neg(p(a_)), pos(q(b_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->literals.size(), 1); - EXPECT_EQ(result->literals[0].atom, Q(b)); - EXPECT_TRUE(result->literals[0].is_positive); + EXPECT_EQ(result->literals_.size(), 1); + EXPECT_EQ(result->literals_[0].atom_, q(b_)); + EXPECT_TRUE(result->literals_[0].is_positive_); } TEST_F(ResolutionTest, ResolutionWithUnification) { // {P(X)} and {¬P(a)} → {} (empty clause!) - Clause c1 = makeClause({pos(P(X))}, 0); - Clause c2 = makeClause({neg(P(a))}, 1); + Clause const c1 = makeClause({pos(p(x_))}, 0); + Clause const c2 = makeClause({neg(p(a_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result->isEmpty()) << "Should derive empty clause (contradiction)"; } TEST_F(ResolutionTest, ResolutionFailsSamePolarity) { // {P(a)} and {P(b)} → no resolution (both positive) - Clause c1 = makeClause({pos(P(a))}, 0); - Clause c2 = makeClause({pos(P(b))}, 1); + Clause const c1 = makeClause({pos(p(a_))}, 0); + Clause const c2 = makeClause({pos(p(b_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); EXPECT_FALSE(result.has_value()); } TEST_F(ResolutionTest, ResolutionFailsNoUnifier) { // {P(a)} and {¬P(b)} → can't unify a with b - Clause c1 = makeClause({pos(P(a))}, 0); - Clause c2 = makeClause({neg(P(b))}, 1); + Clause const c1 = makeClause({pos(p(a_))}, 0); + Clause const c2 = makeClause({neg(p(b_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); EXPECT_FALSE(result.has_value()); } TEST_F(ResolutionTest, ResolutionAppliesSubstToRemainingLiterals) { // {P(X), Q(X)} and {¬P(a)} → {Q(a)} - Clause c1 = makeClause({pos(P(X)), pos(Q(X))}, 0); - Clause c2 = makeClause({neg(P(a))}, 1); + Clause const c1 = makeClause({pos(p(x_)), pos(q(x_))}, 0); + Clause const c2 = makeClause({neg(p(a_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->literals.size(), 1); - EXPECT_EQ(result->literals[0].atom, Q(a)); + EXPECT_EQ(result->literals_.size(), 1); + EXPECT_EQ(result->literals_[0].atom_, q(a_)); } TEST_F(ResolutionTest, ResolutionMultipleLiterals) { // {P(X), Q(b)} and {¬P(a), R(a, c)} → {Q(b), R(a, c)} - Clause c1 = makeClause({pos(P(X)), pos(Q(b))}, 0); - Clause c2 = makeClause({neg(P(a)), pos(R(a, c))}, 1); + Clause const c1 = makeClause({pos(p(x_)), pos(q(b_))}, 0); + Clause const c2 = makeClause({neg(p(a_)), pos(r(a_, c_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->literals.size(), 2); + EXPECT_EQ(result->literals_.size(), 2); } TEST_F(ResolutionTest, VariableRenamingWorks) { // Both clauses use variable X // {P(X)} and {¬P(X), Q(X)} → {Q(a)} only if X is renamed in c2 - Clause c1 = makeClause({pos(P(a))}, 0); - Clause c2 = makeClause({neg(P(X)), pos(Q(X))}, 1); + Clause const c1 = makeClause({pos(p(a_))}, 0); + Clause const c2 = makeClause({neg(p(x_)), pos(q(x_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->literals.size(), 1); + EXPECT_EQ(result->literals_.size(), 1); // Q(X) should become Q(a) after substitution {X→a} - EXPECT_EQ(result->literals[0].atom, Q(a)); + EXPECT_EQ(result->literals_[0].atom_, q(a_)); } TEST_F(ResolutionTest, VariableRenamingPreventsClash) { // {R(X, a)} and {¬R(b, X)} // Without renaming: X would clash between c1 and c2 // With renaming: c2's X → _R0, then unify R(X,a) with R(b,_R0) → {X→b, _R0→a} - Clause c1 = makeClause({pos(R(X, a))}, 0); - Clause c2 = makeClause({neg(R(b, X))}, 1); + Clause const c1 = makeClause({pos(r(x_, a_))}, 0); + Clause const c2 = makeClause({neg(r(b_, x_))}, 1); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result->isEmpty()); } @@ -177,19 +177,19 @@ TEST_F(ResolutionTest, VariableRenamingPreventsClash) { TEST_F(ResolutionTest, AllResolventsFindsAll) { // {P(a), Q(a)} and {¬P(a), ¬Q(a)} // Can resolve on P or Q → 2 resolvents - Clause c1 = makeClause({pos(P(a)), pos(Q(a))}, 0); - Clause c2 = makeClause({neg(P(a)), neg(Q(a))}, 1); + Clause const c1 = makeClause({pos(p(a_)), pos(q(a_))}, 0); + Clause const c2 = makeClause({neg(p(a_)), neg(q(a_))}, 1); - auto results = allResolvents(bank, c1, c2); + auto results = allResolvents(bank_, c1, c2); EXPECT_EQ(results.size(), 2); } TEST_F(ResolutionTest, AllResolventsEmpty) { // {P(a)} and {Q(b)} → no complementary pairs - Clause c1 = makeClause({pos(P(a))}, 0); - Clause c2 = makeClause({pos(Q(b))}, 1); + Clause const c1 = makeClause({pos(p(a_))}, 0); + Clause const c2 = makeClause({pos(q(b_))}, 1); - auto results = allResolvents(bank, c1, c2); + auto results = allResolvents(bank_, c1, c2); EXPECT_TRUE(results.empty()); } @@ -199,34 +199,34 @@ TEST_F(ResolutionTest, AllResolventsEmpty) { TEST_F(ResolutionTest, SimpleFactoring) { // {P(X), P(a), Q(X)} → factor P(X) with P(a): {P(a), Q(a)} - Clause c = makeClause({pos(P(X)), pos(P(a)), pos(Q(X))}, 0); + Clause const c = makeClause({pos(p(x_)), pos(p(a_)), pos(q(x_))}, 0); - auto results = factor(bank, c); + auto results = factor(bank_, c); ASSERT_EQ(results.size(), 1); - EXPECT_EQ(results[0].literals.size(), 2); + EXPECT_EQ(results[0].literals_.size(), 2); // After factoring: {P(a), Q(a)} - EXPECT_EQ(results[0].literals[0].atom, P(a)); - EXPECT_EQ(results[0].literals[1].atom, Q(a)); + EXPECT_EQ(results[0].literals_[0].atom_, p(a_)); + EXPECT_EQ(results[0].literals_[1].atom_, q(a_)); } TEST_F(ResolutionTest, NoFactoring) { // {P(a), Q(b)} → different predicates, can't factor - Clause c = makeClause({pos(P(a)), pos(Q(b))}, 0); - auto results = factor(bank, c); + Clause const c = makeClause({pos(p(a_)), pos(q(b_))}, 0); + auto results = factor(bank_, c); EXPECT_TRUE(results.empty()); } TEST_F(ResolutionTest, FactoringDifferentPolarity) { // {P(a), ¬P(a)} → different polarity, can't factor - Clause c = makeClause({pos(P(a)), neg(P(a))}, 0); - auto results = factor(bank, c); + Clause const c = makeClause({pos(p(a_)), neg(p(a_))}, 0); + auto results = factor(bank_, c); EXPECT_TRUE(results.empty()); } TEST_F(ResolutionTest, FactoringNonUnifiable) { // {P(a), P(b)} → can't unify a with b - Clause c = makeClause({pos(P(a)), pos(P(b))}, 0); - auto results = factor(bank, c); + Clause const c = makeClause({pos(p(a_)), pos(p(b_))}, 0); + auto results = factor(bank_, c); EXPECT_TRUE(results.empty()); } @@ -235,22 +235,22 @@ TEST_F(ResolutionTest, FactoringNonUnifiable) { // ═══════════════════════════════════════════════════════════════════════════ TEST_F(ResolutionTest, ResolventHasProvenance) { - Clause c1 = makeClause({pos(P(X))}, 5); - Clause c2 = makeClause({neg(P(a))}, 7); + Clause const c1 = makeClause({pos(p(x_))}, 5); + Clause const c2 = makeClause({neg(p(a_))}, 7); - auto result = resolve(bank, c1, 0, c2, 0); + auto result = resolve(bank_, c1, 0, c2, 0); ASSERT_TRUE(result.has_value()); - EXPECT_EQ(result->rule, InferenceRule::kResolution); - EXPECT_EQ(result->parent1, 5); - EXPECT_EQ(result->parent2, 7); + EXPECT_EQ(result->rule_, InferenceRule::kResolution); + EXPECT_EQ(result->parent1_, 5); + EXPECT_EQ(result->parent2_, 7); } TEST_F(ResolutionTest, FactoredHasProvenance) { - Clause c = makeClause({pos(P(X)), pos(P(a))}, 3); - auto results = factor(bank, c); + Clause const c = makeClause({pos(p(x_)), pos(p(a_))}, 3); + auto results = factor(bank_, c); ASSERT_FALSE(results.empty()); - EXPECT_EQ(results[0].rule, InferenceRule::kFactoring); - EXPECT_EQ(results[0].parent1, 3); + EXPECT_EQ(results[0].rule_, InferenceRule::kFactoring); + EXPECT_EQ(results[0].parent1_, 3); } } // namespace diff --git a/tests/test_simplify.cc b/tests/test_simplify.cc index 98b0db9..968ab3b 100644 --- a/tests/test_simplify.cc +++ b/tests/test_simplify.cc @@ -25,46 +25,48 @@ #include "atp/simplify/tautology.h" #include <gtest/gtest.h> +#include <utility> +#include <vector> namespace atp { namespace { class SimplifyTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; + SymbolTable symbols_; + TermBank bank_{symbols_}; - SymbolId sym_a{}, sym_b{}, sym_c{}; - SymbolId sym_P{}, sym_Q{}, sym_R{}; - SymbolId sym_X{}; + SymbolId sym_a_{}, sym_b_{}, sym_c_{}; + SymbolId sym_p_{}, sym_q_{}, sym_r_{}; + SymbolId sym_x_{}; - TermId a{}, b{}, c{}, X{}; + TermId a_{}, b_{}, c_{}, x_{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_c = symbols.intern("c", SymbolKind::kConstant); - sym_P = symbols.intern("P", SymbolKind::kPredicate, 1); - sym_Q = symbols.intern("Q", SymbolKind::kPredicate, 1); - sym_R = symbols.intern("R", SymbolKind::kPredicate, 2); - sym_X = symbols.intern("X", SymbolKind::kVariable); - - a = bank.makeTerm(sym_a, {}); - b = bank.makeTerm(sym_b, {}); - c = bank.makeTerm(sym_c, {}); - X = bank.makeVar(sym_X); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_c_ = symbols_.intern("c", SymbolKind::kConstant); + sym_p_ = symbols_.intern("P", SymbolKind::kPredicate, 1); + sym_q_ = symbols_.intern("Q", SymbolKind::kPredicate, 1); + sym_r_ = symbols_.intern("R", SymbolKind::kPredicate, 2); + sym_x_ = symbols_.intern("X", SymbolKind::kVariable); + + a_ = bank_.makeTerm(sym_a_, {}); + b_ = bank_.makeTerm(sym_b_, {}); + c_ = bank_.makeTerm(sym_c_, {}); + x_ = bank_.makeVar(sym_x_); } - TermId P(TermId arg) { return bank.makeTerm(sym_P, {{arg}}); } - TermId Q(TermId arg) { return bank.makeTerm(sym_Q, {{arg}}); } - TermId R(TermId a1, TermId a2) { return bank.makeTerm(sym_R, {{a1, a2}}); } + TermId p(TermId arg) { return bank_.makeTerm(sym_p_, {{arg}}); } + TermId q(TermId arg) { return bank_.makeTerm(sym_q_, {{arg}}); } + TermId r(TermId a1, TermId a2) { return bank_.makeTerm(sym_r_, {{a1, a2}}); } - Literal pos(TermId atom) { return {.atom = atom, .is_positive = true}; } - Literal neg(TermId atom) { return {.atom = atom, .is_positive = false}; } + static Literal pos(TermId atom) { return {.atom_ = atom, .is_positive_ = true}; } + static Literal neg(TermId atom) { return {.atom_ = atom, .is_positive_ = false}; } - Clause makeClause(std::vector<Literal> lits) { + static Clause makeClause(std::vector<Literal> lits) { Clause cl; - cl.literals = std::move(lits); + cl.literals_ = std::move(lits); return cl; } }; @@ -75,53 +77,53 @@ class SimplifyTest : public ::testing::Test { TEST_F(SimplifyTest, TautologyComplementaryLiterals) { // {P(a), ¬P(a)} → tautology - Clause cl = makeClause({pos(P(a)), neg(P(a))}); + Clause const cl = makeClause({pos(p(a_)), neg(p(a_))}); EXPECT_TRUE(isTautology(cl)); } TEST_F(SimplifyTest, TautologyWithExtraLiterals) { // {Q(b), P(a), ¬P(a)} → tautology - Clause cl = makeClause({pos(Q(b)), pos(P(a)), neg(P(a))}); + Clause const cl = makeClause({pos(q(b_)), pos(p(a_)), neg(p(a_))}); EXPECT_TRUE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologySamePolarity) { // {P(a), P(a)} → NOT tautology (same polarity) - Clause cl = makeClause({pos(P(a)), pos(P(a))}); + Clause const cl = makeClause({pos(p(a_)), pos(p(a_))}); EXPECT_FALSE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologyDifferentAtoms) { // {P(a), ¬P(b)} → NOT tautology (different atoms) - Clause cl = makeClause({pos(P(a)), neg(P(b))}); + Clause const cl = makeClause({pos(p(a_)), neg(p(b_))}); EXPECT_FALSE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologyDifferentPredicates) { // {P(a), ¬Q(a)} → NOT tautology (different predicates) - Clause cl = makeClause({pos(P(a)), neg(Q(a))}); + Clause const cl = makeClause({pos(p(a_)), neg(q(a_))}); EXPECT_FALSE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologyEmptyClause) { - Clause cl = makeClause({}); + Clause const cl = makeClause({}); EXPECT_FALSE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologySingleLiteral) { - Clause cl = makeClause({pos(P(a))}); + Clause const cl = makeClause({pos(p(a_))}); EXPECT_FALSE(isTautology(cl)); } TEST_F(SimplifyTest, TautologyVariableAtom) { // {P(X), ¬P(X)} → tautology (same variable term) - Clause cl = makeClause({pos(P(X)), neg(P(X))}); + Clause const cl = makeClause({pos(p(x_)), neg(p(x_))}); EXPECT_TRUE(isTautology(cl)); } TEST_F(SimplifyTest, NotTautologyVarVsConst) { // {P(X), ¬P(a)} → NOT tautology (syntactically different) - Clause cl = makeClause({pos(P(X)), neg(P(a))}); + Clause const cl = makeClause({pos(p(x_)), neg(p(a_))}); EXPECT_FALSE(isTautology(cl)); } @@ -131,57 +133,57 @@ TEST_F(SimplifyTest, NotTautologyVarVsConst) { TEST_F(SimplifyTest, SubsumesSubset) { // {P(a)} subsumes {P(a), Q(b)} - Clause gen = makeClause({pos(P(a))}); - Clause spec = makeClause({pos(P(a)), pos(Q(b))}); + Clause const gen = makeClause({pos(p(a_))}); + Clause const spec = makeClause({pos(p(a_)), pos(q(b_))}); EXPECT_TRUE(subsumes(gen, spec)); } TEST_F(SimplifyTest, SubsumesIdentical) { // {P(a), Q(b)} subsumes {P(a), Q(b)} - Clause c1 = makeClause({pos(P(a)), pos(Q(b))}); - Clause c2 = makeClause({pos(P(a)), pos(Q(b))}); + Clause const c1 = makeClause({pos(p(a_)), pos(q(b_))}); + Clause const c2 = makeClause({pos(p(a_)), pos(q(b_))}); EXPECT_TRUE(subsumes(c1, c2)); } TEST_F(SimplifyTest, SubsumesEmptyClause) { // {} subsumes everything - Clause empty = makeClause({}); - Clause cl = makeClause({pos(P(a)), neg(Q(b))}); + Clause const empty = makeClause({}); + Clause const cl = makeClause({pos(p(a_)), neg(q(b_))}); EXPECT_TRUE(subsumes(empty, cl)); } TEST_F(SimplifyTest, SubsumesNotLarger) { // {P(a), Q(b)} does NOT subsume {P(a)} - Clause gen = makeClause({pos(P(a)), pos(Q(b))}); - Clause spec = makeClause({pos(P(a))}); + Clause const gen = makeClause({pos(p(a_)), pos(q(b_))}); + Clause const spec = makeClause({pos(p(a_))}); EXPECT_FALSE(subsumes(gen, spec)); } TEST_F(SimplifyTest, SubsumesRequiresSamePolarity) { // {P(a)} does NOT subsume {¬P(a)} - Clause gen = makeClause({pos(P(a))}); - Clause spec = makeClause({neg(P(a))}); + Clause const gen = makeClause({pos(p(a_))}); + Clause const spec = makeClause({neg(p(a_))}); EXPECT_FALSE(subsumes(gen, spec)); } TEST_F(SimplifyTest, SubsumesRequiresSameAtom) { // {P(a)} does NOT subsume {P(b)} - Clause gen = makeClause({pos(P(a))}); - Clause spec = makeClause({pos(P(b))}); + Clause const gen = makeClause({pos(p(a_))}); + Clause const spec = makeClause({pos(p(b_))}); EXPECT_FALSE(subsumes(gen, spec)); } TEST_F(SimplifyTest, SubsumesNegativeLiterals) { // {¬P(a)} subsumes {¬P(a), Q(b)} - Clause gen = makeClause({neg(P(a))}); - Clause spec = makeClause({neg(P(a)), pos(Q(b))}); + Clause const gen = makeClause({neg(p(a_))}); + Clause const spec = makeClause({neg(p(a_)), pos(q(b_))}); EXPECT_TRUE(subsumes(gen, spec)); } TEST_F(SimplifyTest, SubsumesOrderIndependent) { // {Q(b), P(a)} subsumes {P(a), Q(b), R(a,b)} regardless of order - Clause gen = makeClause({pos(Q(b)), pos(P(a))}); - Clause spec = makeClause({pos(P(a)), pos(Q(b)), pos(R(a, b))}); + Clause const gen = makeClause({pos(q(b_)), pos(p(a_))}); + Clause const spec = makeClause({pos(p(a_)), pos(q(b_)), pos(r(a_, b_))}); EXPECT_TRUE(subsumes(gen, spec)); } diff --git a/tests/test_term_bank.cc b/tests/test_term_bank.cc index 3ea15ac..0d4fcc7 100644 --- a/tests/test_term_bank.cc +++ b/tests/test_term_bank.cc @@ -24,7 +24,11 @@ #include "atp/core/term_bank.h" #include "atp/core/types.h" +#include <cstddef> #include <gtest/gtest.h> +#include <span> +#include <stdexcept> +#include <utility> namespace atp { namespace { @@ -35,39 +39,39 @@ namespace { TEST(SymbolTableTest, InternReturnsConsistentId) { SymbolTable st; - SymbolId id1 = st.intern("foo", SymbolKind::kFunction, 2); - SymbolId id2 = st.intern("foo", SymbolKind::kFunction, 2); + SymbolId const id1 = st.intern("foo", SymbolKind::kFunction, 2); + SymbolId const id2 = st.intern("foo", SymbolKind::kFunction, 2); EXPECT_EQ(id1, id2); } TEST(SymbolTableTest, DifferentNamesGetDifferentIds) { SymbolTable st; - SymbolId a = st.intern("a", SymbolKind::kConstant); - SymbolId b = st.intern("b", SymbolKind::kConstant); + SymbolId const a = st.intern("a", SymbolKind::kConstant); + SymbolId const b = st.intern("b", SymbolKind::kConstant); EXPECT_NE(a, b); } TEST(SymbolTableTest, GetNameRoundTrips) { SymbolTable st; - SymbolId id = st.intern("hello", SymbolKind::kFunction, 1); + SymbolId const id = st.intern("hello", SymbolKind::kFunction, 1); EXPECT_EQ(st.getName(id), "hello"); } TEST(SymbolTableTest, GetInfoPreservesMetadata) { SymbolTable st; - SymbolId id = st.intern("P", SymbolKind::kPredicate, 3, 42); + SymbolId const id = st.intern("P", SymbolKind::kPredicate, 3, 42); const SymbolInfo& info = st.getInfo(id); - EXPECT_EQ(info.name, "P"); - EXPECT_EQ(info.kind, SymbolKind::kPredicate); - EXPECT_EQ(info.arity, 3); - EXPECT_EQ(info.sort, 42); + EXPECT_EQ(info.name_, "P"); + EXPECT_EQ(info.kind_, SymbolKind::kPredicate); + EXPECT_EQ(info.arity_, 3); + EXPECT_EQ(info.sort_, 42); } TEST(SymbolTableTest, IsVariableDetectsKind) { SymbolTable st; - SymbolId var = st.intern("X", SymbolKind::kVariable); - SymbolId con = st.intern("a", SymbolKind::kConstant); - SymbolId fun = st.intern("f", SymbolKind::kFunction, 1); + SymbolId const var = st.intern("X", SymbolKind::kVariable); + SymbolId const con = st.intern("a", SymbolKind::kConstant); + SymbolId const fun = st.intern("f", SymbolKind::kFunction, 1); EXPECT_TRUE(st.isVariable(var)); EXPECT_FALSE(st.isVariable(con)); EXPECT_FALSE(st.isVariable(fun)); @@ -102,123 +106,123 @@ TEST(SymbolTableTest, SizeTracksInternedSymbols) { class TermBankTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; + SymbolTable symbols_; + TermBank bank_{symbols_}; - SymbolId sym_a, sym_b, sym_f, sym_g, sym_X, sym_Y; + SymbolId sym_a_{}, sym_b_{}, sym_f_{}, sym_g_{}, sym_x_id_{}, sym_y_id_{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_f = symbols.intern("f", SymbolKind::kFunction, 1); - sym_g = symbols.intern("g", SymbolKind::kFunction, 2); - sym_X = symbols.intern("X", SymbolKind::kVariable); - sym_Y = symbols.intern("Y", SymbolKind::kVariable); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_f_ = symbols_.intern("f", SymbolKind::kFunction, 1); + sym_g_ = symbols_.intern("g", SymbolKind::kFunction, 2); + sym_x_id_ = symbols_.intern("X", SymbolKind::kVariable); + sym_y_id_ = symbols_.intern("Y", SymbolKind::kVariable); } }; TEST_F(TermBankTest, HashConsingReturnsSameId) { - TermId a1 = bank.makeTerm(sym_a, {}); - TermId a2 = bank.makeTerm(sym_a, {}); - EXPECT_EQ(a1, a2) << "Hash consing failed: same term got different IDs"; + const TermId kA1 = bank_.makeTerm(sym_a_, {}); + const TermId kA2 = bank_.makeTerm(sym_a_, {}); + EXPECT_EQ(kA1, kA2) << "Hash consing failed: same term got different IDs"; } TEST_F(TermBankTest, DifferentTermsGetDifferentIds) { - TermId a = bank.makeTerm(sym_a, {}); - TermId b = bank.makeTerm(sym_b, {}); - EXPECT_NE(a, b); + const TermId kA = bank_.makeTerm(sym_a_, {}); + const TermId kB = bank_.makeTerm(sym_b_, {}); + EXPECT_NE(kA, kB); } TEST_F(TermBankTest, CompoundTermHashConsing) { - TermId a = bank.makeTerm(sym_a, {}); - TermId b = bank.makeTerm(sym_b, {}); + const TermId kA = bank_.makeTerm(sym_a_, {}); + const TermId kB = bank_.makeTerm(sym_b_, {}); // f(a) - TermId fa1 = bank.makeTerm(sym_f, {{a}}); - TermId fa2 = bank.makeTerm(sym_f, {{a}}); - EXPECT_EQ(fa1, fa2); + const TermId kFA1 = bank_.makeTerm(sym_f_, {{kA}}); + const TermId kFA2 = bank_.makeTerm(sym_f_, {{kA}}); + EXPECT_EQ(kFA1, kFA2); // f(b) != f(a) - TermId fb = bank.makeTerm(sym_f, {{b}}); - EXPECT_NE(fa1, fb); + const TermId kFB = bank_.makeTerm(sym_f_, {{kB}}); + EXPECT_NE(kFA1, kFB); } TEST_F(TermBankTest, NestedTermHashConsing) { - TermId a = bank.makeTerm(sym_a, {}); - TermId fa = bank.makeTerm(sym_f, {{a}}); + const TermId kA = bank_.makeTerm(sym_a_, {}); + const TermId kFA = bank_.makeTerm(sym_f_, {{kA}}); // g(f(a), a) - TermId gfa_a_1 = bank.makeTerm(sym_g, {{fa, a}}); - TermId gfa_a_2 = bank.makeTerm(sym_g, {{fa, a}}); - EXPECT_EQ(gfa_a_1, gfa_a_2); + const TermId kGFAA1 = bank_.makeTerm(sym_g_, {{kFA, kA}}); + const TermId kGFAA2 = bank_.makeTerm(sym_g_, {{kFA, kA}}); + EXPECT_EQ(kGFAA1, kGFAA2); } TEST_F(TermBankTest, GetTermReturnsCorrectSymbol) { - TermId a = bank.makeTerm(sym_a, {}); - const Term& t = bank.getTerm(a); - EXPECT_EQ(t.symbol_id, sym_a); + const TermId kA = bank_.makeTerm(sym_a_, {}); + const Term& t = bank_.getTerm(kA); + EXPECT_EQ(t.symbol_id_, sym_a_); EXPECT_EQ(t.arity(), 0); } TEST_F(TermBankTest, GetTermReturnsCorrectArgs) { - TermId a = bank.makeTerm(sym_a, {}); - TermId b = bank.makeTerm(sym_b, {}); - TermId gab = bank.makeTerm(sym_g, {{a, b}}); + const TermId kA = bank_.makeTerm(sym_a_, {}); + const TermId kB = bank_.makeTerm(sym_b_, {}); + const TermId kGAB = bank_.makeTerm(sym_g_, {{kA, kB}}); - const Term& t = bank.getTerm(gab); - EXPECT_EQ(t.symbol_id, sym_g); + const Term& t = bank_.getTerm(kGAB); + EXPECT_EQ(t.symbol_id_, sym_g_); EXPECT_EQ(t.arity(), 2); - ASSERT_EQ(t.args.size(), 2); - EXPECT_EQ(t.args[0], a); - EXPECT_EQ(t.args[1], b); + ASSERT_EQ(t.args_.size(), 2); + EXPECT_EQ(t.args_[0], kA); + EXPECT_EQ(t.args_[1], kB); } TEST_F(TermBankTest, MakeVarCreatesZeroArityTerm) { - TermId x = bank.makeVar(sym_X); - const Term& t = bank.getTerm(x); - EXPECT_EQ(t.symbol_id, sym_X); + const TermId kX = bank_.makeVar(sym_x_id_); + const Term& t = bank_.getTerm(kX); + EXPECT_EQ(t.symbol_id_, sym_x_id_); EXPECT_EQ(t.arity(), 0); - EXPECT_TRUE(t.args.empty()); + EXPECT_TRUE(t.args_.empty()); } TEST_F(TermBankTest, IsVariableDistinguishesFromConstants) { - TermId x = bank.makeVar(sym_X); - TermId a = bank.makeTerm(sym_a, {}); + const TermId kX = bank_.makeVar(sym_x_id_); + const TermId kA = bank_.makeTerm(sym_a_, {}); - EXPECT_TRUE(bank.isVariable(x)) << "Variable should be detected as variable"; - EXPECT_FALSE(bank.isVariable(a)) << "Constant should NOT be detected as variable"; + EXPECT_TRUE(bank_.isVariable(kX)) << "Variable should be detected as variable"; + EXPECT_FALSE(bank_.isVariable(kA)) << "Constant should NOT be detected as variable"; } TEST_F(TermBankTest, VariableHashConsing) { - TermId x1 = bank.makeVar(sym_X); - TermId x2 = bank.makeVar(sym_X); - EXPECT_EQ(x1, x2); + const TermId kX1 = bank_.makeVar(sym_x_id_); + const TermId kX2 = bank_.makeVar(sym_x_id_); + EXPECT_EQ(kX1, kX2); - TermId y = bank.makeVar(sym_Y); - EXPECT_NE(x1, y); + const TermId kY = bank_.makeVar(sym_y_id_); + EXPECT_NE(kX1, kY); } TEST_F(TermBankTest, SizeTracksUniqueTerms) { - EXPECT_EQ(bank.size(), 0); - TermId a = bank.makeTerm(sym_a, {}); - EXPECT_EQ(bank.size(), 1); - bank.makeTerm(sym_a, {}); // duplicate - EXPECT_EQ(bank.size(), 1); - bank.makeTerm(sym_b, {}); - EXPECT_EQ(bank.size(), 2); - bank.makeTerm(sym_f, {{a}}); - EXPECT_EQ(bank.size(), 3); + EXPECT_EQ(bank_.size(), 0); + const TermId kA = bank_.makeTerm(sym_a_, {}); + EXPECT_EQ(bank_.size(), 1); + bank_.makeTerm(sym_a_, {}); // duplicate + EXPECT_EQ(bank_.size(), 1); + bank_.makeTerm(sym_b_, {}); + EXPECT_EQ(bank_.size(), 2); + bank_.makeTerm(sym_f_, {{kA}}); + EXPECT_EQ(bank_.size(), 3); } TEST_F(TermBankTest, CompoundTermWithVariableArgs) { // f(X) — a function applied to a variable - TermId x = bank.makeVar(sym_X); - TermId fx = bank.makeTerm(sym_f, {{x}}); + const TermId kX = bank_.makeVar(sym_x_id_); + const TermId kFX = bank_.makeTerm(sym_f_, {{kX}}); - const Term& t = bank.getTerm(fx); - EXPECT_EQ(t.symbol_id, sym_f); + const Term& t = bank_.getTerm(kFX); + EXPECT_EQ(t.symbol_id_, sym_f_); EXPECT_EQ(t.arity(), 1); - EXPECT_EQ(t.args[0], x); + EXPECT_EQ(t.args_[0], kX); - EXPECT_FALSE(bank.isVariable(fx)); - EXPECT_TRUE(bank.isVariable(x)); + EXPECT_FALSE(bank_.isVariable(kFX)); + EXPECT_TRUE(bank_.isVariable(kX)); } // ═══════════════════════════════════════════════════════════════════════════ @@ -228,48 +232,48 @@ TEST_F(TermBankTest, CompoundTermWithVariableArgs) { TEST(ClauseStoreTest, AddAndRetrieve) { ClauseStore store; Clause c; - c.literals.push_back(Literal{.atom = 0, .is_positive = true}); - c.literals.push_back(Literal{.atom = 1, .is_positive = false}); - - ClauseId id = store.addClause(std::move(c)); - EXPECT_EQ(id, 0); - - const Clause& retrieved = store.getClause(id); - EXPECT_EQ(retrieved.id, id); - EXPECT_EQ(retrieved.literals.size(), 2); - EXPECT_EQ(retrieved.literals[0].atom, 0); - EXPECT_TRUE(retrieved.literals[0].is_positive); - EXPECT_EQ(retrieved.literals[1].atom, 1); - EXPECT_FALSE(retrieved.literals[1].is_positive); + c.literals_.push_back(Literal{.atom_ = 0, .is_positive_ = true}); + c.literals_.push_back(Literal{.atom_ = 1, .is_positive_ = false}); + + const ClauseId kId = store.addClause(std::move(c)); + EXPECT_EQ(kId, 0); + + const Clause& retrieved = store.getClause(kId); + EXPECT_EQ(retrieved.id_, kId); + EXPECT_EQ(retrieved.literals_.size(), 2); + EXPECT_EQ(retrieved.literals_[0].atom_, 0); + EXPECT_TRUE(retrieved.literals_[0].is_positive_); + EXPECT_EQ(retrieved.literals_[1].atom_, 1); + EXPECT_FALSE(retrieved.literals_[1].is_positive_); } TEST(ClauseStoreTest, AssignsSequentialIds) { ClauseStore store; - ClauseId id0 = store.addClause(Clause{}); - ClauseId id1 = store.addClause(Clause{}); - ClauseId id2 = store.addClause(Clause{}); - EXPECT_EQ(id0, 0); - EXPECT_EQ(id1, 1); - EXPECT_EQ(id2, 2); + const ClauseId kId0 = store.addClause(Clause{}); + const ClauseId kId1 = store.addClause(Clause{}); + const ClauseId kId2 = store.addClause(Clause{}); + EXPECT_EQ(kId0, 0); + EXPECT_EQ(kId1, 1); + EXPECT_EQ(kId2, 2); EXPECT_EQ(store.size(), 3); } TEST(ClauseStoreTest, StampsClauseWithId) { ClauseStore store; Clause c; - c.id = kInvalidId; // unset - ClauseId id = store.addClause(std::move(c)); - EXPECT_EQ(store.getClause(id).id, id); + c.id_ = kInvalidId; // unset + const ClauseId kId = store.addClause(std::move(c)); + EXPECT_EQ(store.getClause(kId).id_, kId); } TEST(ClauseStoreTest, MutableAccess) { ClauseStore store; Clause c; - c.depth = 0; - ClauseId id = store.addClause(std::move(c)); + c.depth_ = 0; + const ClauseId kId = store.addClause(std::move(c)); - store.getMutableClause(id).depth = 42; - EXPECT_EQ(store.getClause(id).depth, 42); + store.getMutableClause(kId).depth_ = 42; + EXPECT_EQ(store.getClause(kId).depth_, 42); } TEST(ClauseStoreTest, ForEachVisitsAll) { @@ -286,7 +290,7 @@ TEST(ClauseStoreTest, ForEachVisitsAll) { TEST(ClauseStoreTest, EmptyClauseDetection) { Clause c; EXPECT_TRUE(c.isEmpty()); - c.literals.push_back(Literal{.atom = 0, .is_positive = true}); + c.literals_.push_back(Literal{.atom_ = 0, .is_positive_ = true}); EXPECT_FALSE(c.isEmpty()); EXPECT_EQ(c.size(), 1); } @@ -294,17 +298,17 @@ TEST(ClauseStoreTest, EmptyClauseDetection) { TEST(ClauseStoreTest, ProvenancePreserved) { ClauseStore store; Clause c; - c.rule = InferenceRule::kResolution; - c.parent1 = 3; - c.parent2 = 7; - c.depth = 5; + c.rule_ = InferenceRule::kResolution; + c.parent1_ = 3; + c.parent2_ = 7; + c.depth_ = 5; - ClauseId id = store.addClause(std::move(c)); + ClauseId const id = store.addClause(std::move(c)); const Clause& retrieved = store.getClause(id); - EXPECT_EQ(retrieved.rule, InferenceRule::kResolution); - EXPECT_EQ(retrieved.parent1, 3); - EXPECT_EQ(retrieved.parent2, 7); - EXPECT_EQ(retrieved.depth, 5); + EXPECT_EQ(retrieved.rule_, InferenceRule::kResolution); + EXPECT_EQ(retrieved.parent1_, 3); + EXPECT_EQ(retrieved.parent2_, 7); + EXPECT_EQ(retrieved.depth_, 5); } // ═══════════════════════════════════════════════════════════════════════════ @@ -312,23 +316,23 @@ TEST(ClauseStoreTest, ProvenancePreserved) { // ═══════════════════════════════════════════════════════════════════════════ TEST(LiteralTest, Complement) { - Literal pos{.atom = 42, .is_positive = true}; - Literal neg = pos.complement(); - EXPECT_EQ(neg.atom, 42); - EXPECT_FALSE(neg.is_positive); + const Literal kPos{.atom_ = 42, .is_positive_ = true}; + const Literal kNeg = kPos.complement(); + EXPECT_EQ(kNeg.atom_, 42); + EXPECT_FALSE(kNeg.is_positive_); - Literal back = neg.complement(); - EXPECT_EQ(back, pos); + const Literal kBack = kNeg.complement(); + EXPECT_EQ(kBack, kPos); } TEST(LiteralTest, Equality) { - Literal a{.atom = 1, .is_positive = true}; - Literal b{.atom = 1, .is_positive = true}; - Literal c{.atom = 1, .is_positive = false}; - Literal d{.atom = 2, .is_positive = true}; - EXPECT_EQ(a, b); - EXPECT_NE(a, c); - EXPECT_NE(a, d); + const Literal kA{.atom_ = 1, .is_positive_ = true}; + const Literal kB{.atom_ = 1, .is_positive_ = true}; + const Literal kC{.atom_ = 1, .is_positive_ = false}; + const Literal kD{.atom_ = 2, .is_positive_ = true}; + EXPECT_EQ(kA, kB); + EXPECT_NE(kA, kC); + EXPECT_NE(kA, kD); } } // namespace diff --git a/tests/test_unification.cc b/tests/test_unification.cc index 516058a..63ac9f0 100644 --- a/tests/test_unification.cc +++ b/tests/test_unification.cc @@ -33,47 +33,47 @@ namespace { class UnificationTest : public ::testing::Test { protected: - SymbolTable symbols; - TermBank bank{symbols}; + SymbolTable symbols_; + TermBank bank_{symbols_}; // Symbols - SymbolId sym_a{}, sym_b{}, sym_c{}; - SymbolId sym_f{}, sym_g{}, sym_h{}; - SymbolId sym_P{}; - SymbolId sym_X{}, sym_Y{}, sym_Z{}; + SymbolId sym_a_{}, sym_b_{}, sym_c_{}; + SymbolId sym_f_{}, sym_g_{}, sym_h_{}; + SymbolId sym_p_{}; + SymbolId sym_x_{}, sym_y_{}, sym_z_{}; // Terms (created in SetUp) - TermId a{}, b{}, c{}; - TermId X{}, Y{}, Z{}; + TermId a_{}, b_{}, c_{}; + TermId x_{}, y_{}, z_{}; void SetUp() override { - sym_a = symbols.intern("a", SymbolKind::kConstant); - sym_b = symbols.intern("b", SymbolKind::kConstant); - sym_c = symbols.intern("c", SymbolKind::kConstant); - sym_f = symbols.intern("f", SymbolKind::kFunction, 1); - sym_g = symbols.intern("g", SymbolKind::kFunction, 2); - sym_h = symbols.intern("h", SymbolKind::kFunction, 1); - sym_P = symbols.intern("P", SymbolKind::kPredicate, 2); - sym_X = symbols.intern("X", SymbolKind::kVariable); - sym_Y = symbols.intern("Y", SymbolKind::kVariable); - sym_Z = symbols.intern("Z", SymbolKind::kVariable); - - a = bank.makeTerm(sym_a, {}); - b = bank.makeTerm(sym_b, {}); - c = bank.makeTerm(sym_c, {}); - X = bank.makeVar(sym_X); - Y = bank.makeVar(sym_Y); - Z = bank.makeVar(sym_Z); + sym_a_ = symbols_.intern("a", SymbolKind::kConstant); + sym_b_ = symbols_.intern("b", SymbolKind::kConstant); + sym_c_ = symbols_.intern("c", SymbolKind::kConstant); + sym_f_ = symbols_.intern("f", SymbolKind::kFunction, 1); + sym_g_ = symbols_.intern("g", SymbolKind::kFunction, 2); + sym_h_ = symbols_.intern("h", SymbolKind::kFunction, 1); + sym_p_ = symbols_.intern("P", SymbolKind::kPredicate, 2); + sym_x_ = symbols_.intern("X", SymbolKind::kVariable); + sym_y_ = symbols_.intern("Y", SymbolKind::kVariable); + sym_z_ = symbols_.intern("Z", SymbolKind::kVariable); + + a_ = bank_.makeTerm(sym_a_, {}); + b_ = bank_.makeTerm(sym_b_, {}); + c_ = bank_.makeTerm(sym_c_, {}); + x_ = bank_.makeVar(sym_x_); + y_ = bank_.makeVar(sym_y_); + z_ = bank_.makeVar(sym_z_); } // Helper: make f(arg) - TermId f(TermId arg) { return bank.makeTerm(sym_f, {{arg}}); } + TermId f(TermId arg) { return bank_.makeTerm(sym_f_, {{arg}}); } // Helper: make g(arg1, arg2) - TermId g(TermId a1, TermId a2) { return bank.makeTerm(sym_g, {{a1, a2}}); } + TermId g(TermId a1, TermId a2) { return bank_.makeTerm(sym_g_, {{a1, a2}}); } // Helper: make h(arg) - TermId h(TermId arg) { return bank.makeTerm(sym_h, {{arg}}); } + TermId h(TermId arg) { return bank_.makeTerm(sym_h_, {{arg}}); } // Helper: make P(arg1, arg2) - TermId P(TermId a1, TermId a2) { return bank.makeTerm(sym_P, {{a1, a2}}); } + TermId p(TermId a1, TermId a2) { return bank_.makeTerm(sym_p_, {{a1, a2}}); } }; // ═══════════════════════════════════════════════════════════════════════════ @@ -82,90 +82,90 @@ class UnificationTest : public ::testing::Test { TEST_F(UnificationTest, SubstBindAndLookup) { Substitution subst; - EXPECT_TRUE(subst.bind(X, a)); - EXPECT_EQ(subst.lookup(X), a); - EXPECT_EQ(subst.lookup(Y), kInvalidId); // unbound + EXPECT_TRUE(subst.bind(x_, a_)); + EXPECT_EQ(subst.lookup(x_), a_); + EXPECT_EQ(subst.lookup(y_), kInvalidId); // unbound } TEST_F(UnificationTest, SubstBindSameTermSucceeds) { Substitution subst; - EXPECT_TRUE(subst.bind(X, a)); - EXPECT_TRUE(subst.bind(X, a)); // same binding → OK + EXPECT_TRUE(subst.bind(x_, a_)); + EXPECT_TRUE(subst.bind(x_, a_)); // same binding → OK } TEST_F(UnificationTest, SubstBindDifferentTermFails) { Substitution subst; - EXPECT_TRUE(subst.bind(X, a)); - EXPECT_FALSE(subst.bind(X, b)); // different binding → fail + EXPECT_TRUE(subst.bind(x_, a_)); + EXPECT_FALSE(subst.bind(x_, b_)); // different binding → fail } TEST_F(UnificationTest, SubstResolveChain) { // X → Y → a Substitution subst; - subst.bind(X, Y); - subst.bind(Y, a); - EXPECT_EQ(subst.resolve(X, bank), a); + subst.bind(x_, y_); + subst.bind(y_, a_); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, SubstResolveUnbound) { - Substitution subst; - EXPECT_EQ(subst.resolve(X, bank), X); // unbound → returns itself + Substitution const subst; + EXPECT_EQ(subst.resolve(x_, bank_), x_); // unbound → returns itself } TEST_F(UnificationTest, SubstResolveNonVariable) { - Substitution subst; - EXPECT_EQ(subst.resolve(a, bank), a); // constant → returns itself + Substitution const subst; + EXPECT_EQ(subst.resolve(a_, bank_), a_); // constant → returns itself } TEST_F(UnificationTest, SubstApplySimple) { // σ = {X → a} apply to f(X) → f(a) Substitution subst; - subst.bind(X, a); - TermId fx = f(X); - TermId result = subst.apply(fx, bank); - TermId expected = f(a); + subst.bind(x_, a_); + TermId const fx = f(x_); + TermId const result = subst.apply(fx, bank_); + TermId const expected = f(a_); EXPECT_EQ(result, expected); } TEST_F(UnificationTest, SubstApplyLeavesUnbound) { // σ = {X → a} apply to g(X, Y) → g(a, Y) Substitution subst; - subst.bind(X, a); - TermId gxy = g(X, Y); - TermId result = subst.apply(gxy, bank); - TermId expected = g(a, Y); + subst.bind(x_, a_); + TermId const gxy = g(x_, y_); + TermId const result = subst.apply(gxy, bank_); + TermId const expected = g(a_, y_); EXPECT_EQ(result, expected); } TEST_F(UnificationTest, SubstApplyNested) { // σ = {X → f(a)} apply to g(X, b) → g(f(a), b) Substitution subst; - subst.bind(X, f(a)); - TermId result = subst.apply(g(X, b), bank); - EXPECT_EQ(result, g(f(a), b)); + subst.bind(x_, f(a_)); + TermId const result = subst.apply(g(x_, b_), bank_); + EXPECT_EQ(result, g(f(a_), b_)); } TEST_F(UnificationTest, SubstOccursIn) { - Substitution subst; + Substitution const subst; // X occurs in f(X) - EXPECT_TRUE(subst.occursIn(X, f(X), bank)); + EXPECT_TRUE(subst.occursIn(x_, f(x_), bank_)); // X occurs in g(a, f(X)) - EXPECT_TRUE(subst.occursIn(X, g(a, f(X)), bank)); + EXPECT_TRUE(subst.occursIn(x_, g(a_, f(x_)), bank_)); // X does NOT occur in f(a) - EXPECT_FALSE(subst.occursIn(X, f(a), bank)); + EXPECT_FALSE(subst.occursIn(x_, f(a_), bank_)); // X does NOT occur in Y (different variable) - EXPECT_FALSE(subst.occursIn(X, Y, bank)); + EXPECT_FALSE(subst.occursIn(x_, y_, bank_)); } TEST_F(UnificationTest, SubstClearAndSize) { Substitution subst; EXPECT_TRUE(subst.empty()); - subst.bind(X, a); - subst.bind(Y, b); + subst.bind(x_, a_); + subst.bind(y_, b_); EXPECT_EQ(subst.size(), 2); subst.clear(); EXPECT_TRUE(subst.empty()); - EXPECT_EQ(subst.lookup(X), kInvalidId); + EXPECT_EQ(subst.lookup(x_), kInvalidId); } // ═══════════════════════════════════════════════════════════════════════════ @@ -174,104 +174,104 @@ TEST_F(UnificationTest, SubstClearAndSize) { TEST_F(UnificationTest, UnifyIdenticalConstants) { Substitution subst; - EXPECT_TRUE(unify(bank, a, a, subst)); + EXPECT_TRUE(unify(bank_, a_, a_, subst)); EXPECT_TRUE(subst.empty()); } TEST_F(UnificationTest, UnifyDifferentConstants) { Substitution subst; - EXPECT_FALSE(unify(bank, a, b, subst)); + EXPECT_FALSE(unify(bank_, a_, b_, subst)); } TEST_F(UnificationTest, UnifyVarWithConstant) { Substitution subst; - EXPECT_TRUE(unify(bank, X, a, subst)); - EXPECT_EQ(subst.resolve(X, bank), a); + EXPECT_TRUE(unify(bank_, x_, a_, subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, UnifyConstantWithVar) { // Symmetric: unify(a, X) should also work Substitution subst; - EXPECT_TRUE(unify(bank, a, X, subst)); - EXPECT_EQ(subst.resolve(X, bank), a); + EXPECT_TRUE(unify(bank_, a_, x_, subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, UnifyTwoVariables) { Substitution subst; - EXPECT_TRUE(unify(bank, X, Y, subst)); + EXPECT_TRUE(unify(bank_, x_, y_, subst)); // One should be bound to the other - TermId rx = subst.resolve(X, bank); - TermId ry = subst.resolve(Y, bank); + TermId const rx = subst.resolve(x_, bank_); + TermId const ry = subst.resolve(y_, bank_); EXPECT_EQ(rx, ry); } TEST_F(UnificationTest, UnifyCompoundTerms) { // f(X) =? f(a) → {X → a} Substitution subst; - EXPECT_TRUE(unify(bank, f(X), f(a), subst)); - EXPECT_EQ(subst.resolve(X, bank), a); + EXPECT_TRUE(unify(bank_, f(x_), f(a_), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, UnifyMultipleArgs) { // g(X, Y) =? g(a, b) → {X → a, Y → b} Substitution subst; - EXPECT_TRUE(unify(bank, g(X, Y), g(a, b), subst)); - EXPECT_EQ(subst.resolve(X, bank), a); - EXPECT_EQ(subst.resolve(Y, bank), b); + EXPECT_TRUE(unify(bank_, g(x_, y_), g(a_, b_), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); + EXPECT_EQ(subst.resolve(y_, bank_), b_); } TEST_F(UnificationTest, UnifyConflictingBindings) { // g(X, X) =? g(a, b) → fails (X can't be both a and b) Substitution subst; - EXPECT_FALSE(unify(bank, g(X, X), g(a, b), subst)); + EXPECT_FALSE(unify(bank_, g(x_, x_), g(a_, b_), subst)); } TEST_F(UnificationTest, UnifyConsistentRepeatedVar) { // g(X, X) =? g(a, a) → {X → a} Substitution subst; - EXPECT_TRUE(unify(bank, g(X, X), g(a, a), subst)); - EXPECT_EQ(subst.resolve(X, bank), a); + EXPECT_TRUE(unify(bank_, g(x_, x_), g(a_, a_), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, UnifyDifferentHeadSymbols) { // f(X) =? h(X) → fails Substitution subst; - EXPECT_FALSE(unify(bank, f(X), h(X), subst)); + EXPECT_FALSE(unify(bank_, f(x_), h(x_), subst)); } TEST_F(UnificationTest, UnifyDifferentArity) { // f(X) =? g(X, Y) → fails (arity 1 vs 2) Substitution subst; - EXPECT_FALSE(unify(bank, f(X), g(X, Y), subst)); + EXPECT_FALSE(unify(bank_, f(x_), g(x_, y_), subst)); } TEST_F(UnificationTest, UnifyNestedTerms) { // f(g(X, a)) =? f(Y) → {Y → g(X, a)} Substitution subst; - EXPECT_TRUE(unify(bank, f(g(X, a)), f(Y), subst)); - EXPECT_EQ(subst.resolve(Y, bank), g(X, a)); + EXPECT_TRUE(unify(bank_, f(g(x_, a_)), f(y_), subst)); + EXPECT_EQ(subst.resolve(y_, bank_), g(x_, a_)); } TEST_F(UnificationTest, UnifyVarWithCompound) { // X =? f(a) → {X → f(a)} Substitution subst; - EXPECT_TRUE(unify(bank, X, f(a), subst)); - EXPECT_EQ(subst.resolve(X, bank), f(a)); + EXPECT_TRUE(unify(bank_, x_, f(a_), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), f(a_)); } TEST_F(UnificationTest, UnifyDeepNesting) { // f(f(f(X))) =? f(f(f(a))) → {X → a} Substitution subst; - EXPECT_TRUE(unify(bank, f(f(f(X))), f(f(f(a))), subst)); - EXPECT_EQ(subst.resolve(X, bank), a); + EXPECT_TRUE(unify(bank_, f(f(f(x_))), f(f(f(a_))), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); } TEST_F(UnificationTest, UnifyChainedVariables) { // g(X, Y) =? g(Y, a) → {X → Y, Y → a} effectively X → a Substitution subst; - EXPECT_TRUE(unify(bank, g(X, Y), g(Y, a), subst)); - EXPECT_EQ(subst.resolve(X, bank), a); - EXPECT_EQ(subst.resolve(Y, bank), a); + EXPECT_TRUE(unify(bank_, g(x_, y_), g(y_, a_), subst)); + EXPECT_EQ(subst.resolve(x_, bank_), a_); + EXPECT_EQ(subst.resolve(y_, bank_), a_); } // ═══════════════════════════════════════════════════════════════════════════ @@ -281,22 +281,22 @@ TEST_F(UnificationTest, UnifyChainedVariables) { TEST_F(UnificationTest, OccursCheckBlocks) { // X =? f(X) with occurs check → fails Substitution subst; - UnificationConfig config{.enable_occurs_check = true}; - EXPECT_FALSE(unify(bank, X, f(X), subst, config)); + UnificationConfig const config{.enable_occurs_check_ = true}; + EXPECT_FALSE(unify(bank_, x_, f(x_), subst, config)); } TEST_F(UnificationTest, OccursCheckDisabledAllows) { // X =? f(X) without occurs check → succeeds (unsound but fast) Substitution subst; - UnificationConfig config{.enable_occurs_check = false}; - EXPECT_TRUE(unify(bank, X, f(X), subst, config)); + UnificationConfig const config{.enable_occurs_check_ = false}; + EXPECT_TRUE(unify(bank_, x_, f(x_), subst, config)); } TEST_F(UnificationTest, OccursCheckDeep) { // X =? f(g(X, a)) with occurs check → fails Substitution subst; - UnificationConfig config{.enable_occurs_check = true}; - EXPECT_FALSE(unify(bank, X, f(g(X, a)), subst, config)); + UnificationConfig const config{.enable_occurs_check_ = true}; + EXPECT_FALSE(unify(bank_, x_, f(g(x_, a_)), subst, config)); } // ═══════════════════════════════════════════════════════════════════════════ @@ -305,50 +305,50 @@ TEST_F(UnificationTest, OccursCheckDeep) { TEST_F(UnificationTest, ApplySubstitutionSimple) { Substitution subst; - subst.bind(X, a); - EXPECT_EQ(applySubstitution(subst, f(X), bank), f(a)); + subst.bind(x_, a_); + EXPECT_EQ(applySubstitution(subst, f(x_), bank_), f(a_)); } TEST_F(UnificationTest, ApplySubstitutionNested) { Substitution subst; - subst.bind(X, a); - subst.bind(Y, b); - EXPECT_EQ(applySubstitution(subst, g(f(X), Y), bank), g(f(a), b)); + subst.bind(x_, a_); + subst.bind(y_, b_); + EXPECT_EQ(applySubstitution(subst, g(f(x_), y_), bank_), g(f(a_), b_)); } TEST_F(UnificationTest, ApplySubstitutionPreservesUnbound) { Substitution subst; - subst.bind(X, a); + subst.bind(x_, a_); // Y is unbound → stays as Y - EXPECT_EQ(applySubstitution(subst, g(X, Y), bank), g(a, Y)); + EXPECT_EQ(applySubstitution(subst, g(x_, y_), bank_), g(a_, y_)); } TEST_F(UnificationTest, ApplySubstitutionToConstant) { Substitution subst; - subst.bind(X, a); + subst.bind(x_, a_); // Constant is unchanged - EXPECT_EQ(applySubstitution(subst, b, bank), b); + EXPECT_EQ(applySubstitution(subst, b_, bank_), b_); } TEST_F(UnificationTest, ApplySubstitutionChain) { // σ = {X → Y, Y → a} apply to f(X) → f(a) Substitution subst; - subst.bind(X, Y); - subst.bind(Y, a); - EXPECT_EQ(applySubstitution(subst, f(X), bank), f(a)); + subst.bind(x_, y_); + subst.bind(y_, a_); + EXPECT_EQ(applySubstitution(subst, f(x_), bank_), f(a_)); } TEST_F(UnificationTest, UnifyThenApply) { // Full round-trip: unify P(X, f(Y)) with P(a, f(b)), then apply Substitution subst; - TermId lhs = P(X, f(Y)); - TermId rhs = P(a, f(b)); - ASSERT_TRUE(unify(bank, lhs, rhs, subst)); + TermId const lhs = p(x_, f(y_)); + TermId const rhs = p(a_, f(b_)); + ASSERT_TRUE(unify(bank_, lhs, rhs, subst)); - EXPECT_EQ(applySubstitution(subst, lhs, bank), P(a, f(b))); - EXPECT_EQ(applySubstitution(subst, rhs, bank), P(a, f(b))); + EXPECT_EQ(applySubstitution(subst, lhs, bank_), p(a_, f(b_))); + EXPECT_EQ(applySubstitution(subst, rhs, bank_), p(a_, f(b_))); // Both sides should produce the same term after applying the MGU - EXPECT_EQ(applySubstitution(subst, lhs, bank), applySubstitution(subst, rhs, bank)); + EXPECT_EQ(applySubstitution(subst, lhs, bank_), applySubstitution(subst, rhs, bank_)); } } // namespace |
