From df8a2cf317c2a6e63ad42b9ab036df98dc418047 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 19 Sep 2024 20:36:12 +0200 Subject: [PATCH 01/64] Merge some entries in ConstraintIndex; add reversed ordering constraint to result of superpositions; modify KBOComparator to a similar structure as LPOComparator --- Indexing/CodeTree.cpp | 90 +-- Indexing/CodeTree.hpp | 17 +- Inferences/ForwardDemodulation.cpp | 13 + Inferences/Superposition.cpp | 11 +- Kernel/KBOComparator.cpp | 750 ++++++++++++++++++------- Kernel/KBOComparator.hpp | 202 ++++--- Kernel/Ordering.hpp | 1 + Saturation/Splitter.cpp | 15 +- Saturation/Splitter.hpp | 1 + Shell/ConditionalRedundancyHandler.cpp | 203 ++++++- Shell/ConditionalRedundancyHandler.hpp | 11 +- 11 files changed, 956 insertions(+), 358 deletions(-) diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index 31ab8f8da..362a21671 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -655,11 +655,11 @@ void CodeTree::visitAllOps(Visitor visitor) const std::ostream& operator<<(std::ostream& out, const CodeTree& ct) { - ct.visitAllOps([&out](const CodeTree::CodeOp* op, unsigned depth) { + ct.visitAllOps([&out,&ct](const CodeTree::CodeOp* op, unsigned depth) { for (unsigned i = 0; i < depth; i++) { out << " "; } - out << *op << std::endl; + out << *op << (op->isSuccess()?" "+ct.leafToString(op):"") << std::endl; }); return out; } @@ -672,6 +672,7 @@ void CodeTree::CompileContext::init() varMap.reset(); nextGlobalVarNum=0; globalVarMap.reset(); + eqCons.reset(); } void CodeTree::CompileContext::nextLit() @@ -694,9 +695,11 @@ void CodeTree::CompileContext::deinit(CodeTree* tree, bool discarded) } } - +template void CodeTree::compileTerm(const Term* trm, CodeStack& code, CompileContext& cctx, bool addLitEnd) { + ASS(!linearize || !addLitEnd); + static Stack globalCounterparts; globalCounterparts.reset(); @@ -707,44 +710,50 @@ void CodeTree::compileTerm(const Term* trm, CodeStack& code, CompileContext& cct if(trm->isLiteral()) { auto lit=static_cast(trm); code.push(CodeOp::getTermOp(CHECK_FUN, lit->header())); - } - else { + } else { code.push(CodeOp::getTermOp(CHECK_FUN, trm->functor())); } SubtermIterator sti(trm); while(sti.hasNext()) { TermList s=sti.next(); - if(s.isVar()) { - unsigned var=s.var(); - unsigned* varNumPtr; - if(cctx.varMap.getValuePtr(var,varNumPtr)) { - *varNumPtr=cctx.nextVarNum++; - code.push(CodeOp::getTermOp(ASSIGN_VAR, *varNumPtr)); - - if(addLitEnd) { - unsigned* globalVarNumPtr; - if(cctx.globalVarMap.getValuePtr(var,globalVarNumPtr)) { - *globalVarNumPtr=cctx.nextGlobalVarNum++; - } - globalCounterparts.push(*globalVarNumPtr); - } - } - else { - code.push(CodeOp::getTermOp(CHECK_VAR, *varNumPtr)); - } - } - else { - ASS(s.isTerm()); - Term* t=s.term(); + if (s.isVar()) { + unsigned var=s.var(); + unsigned* varNumPtr; + if constexpr (linearize) { + if (cctx.varMap.getValuePtr(var,varNumPtr)) { + *varNumPtr = cctx.nextVarNum; + } else { + cctx.eqCons.push(make_pair(*varNumPtr, cctx.nextVarNum)); + } + code.push(CodeOp::getTermOp(ASSIGN_VAR, cctx.nextVarNum)); + cctx.nextVarNum++; + } else { + if (cctx.varMap.getValuePtr(var,varNumPtr)) { + *varNumPtr=cctx.nextVarNum++; + code.push(CodeOp::getTermOp(ASSIGN_VAR, *varNumPtr)); + + if (addLitEnd) { + unsigned* globalVarNumPtr; + if (cctx.globalVarMap.getValuePtr(var,globalVarNumPtr)) { + *globalVarNumPtr=cctx.nextGlobalVarNum++; + } + globalCounterparts.push(*globalVarNumPtr); + } + } else { + code.push(CodeOp::getTermOp(CHECK_VAR, *varNumPtr)); + } + } + } else { + ASS(s.isTerm()); + Term* t=s.term(); - if(GROUND_TERM_CHECK && t->ground()) { - code.push(CodeOp::getGroundTermCheck(t)); - sti.right(); - } - else { - code.push(CodeOp::getTermOp(CHECK_FUN, t->functor())); - } + if (GROUND_TERM_CHECK && t->ground()) { + code.push(CodeOp::getGroundTermCheck(t)); + sti.right(); + } else { + code.push(CodeOp::getTermOp(CHECK_FUN, t->functor())); + } } } } @@ -756,9 +765,11 @@ void CodeTree::compileTerm(const Term* trm, CodeStack& code, CompileContext& cct ILStruct* ils=new ILStruct(static_cast(trm), varCnt, globalCounterparts); code.push(CodeOp::getLitEnd(ils)); } - } +template void CodeTree::compileTerm(const Term*, CodeStack&, CompileContext&, bool); +template void CodeTree::compileTerm(const Term*, CodeStack&, CompileContext&, bool); + /** * Build CodeBlock object from the last @b cnt instructions on the * @b code stack. @@ -1355,7 +1366,7 @@ bool CodeTree::Matcher::execute() bool shouldBacktrack=false; for(;;) { if(op->alternative()) { - btStack.push(BTPoint(tp, op->alternative())); + btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); } switch(op->_instruction()) { case SUCCESS_OR_FAIL: @@ -1429,6 +1440,8 @@ bool CodeTree::Matcher::backtrack() BTPoint bp=btStack.pop(); tp=bp.tp; op=bp.op; + substIsRenaming=bp.substIsRenaming; + substVRange=bp.substVRange; return true; } @@ -1475,6 +1488,10 @@ inline void CodeTree::Matcher::doAssignVar() if(fte->_tag()==FlatTerm::VAR) { bindings[var]=TermList(fte->_number(),false); tp++; + if (fte->_number() > 64 || (substVRange & (1UL << fte->_number()))) { + substIsRenaming = false; + } + substVRange |= (1UL << fte->_number()); } else { ASS(fte->isFun()); @@ -1485,6 +1502,7 @@ inline void CodeTree::Matcher::doAssignVar() fte++; ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); tp+=fte->_number(); + substIsRenaming = false; } } diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 160021f94..ff97a188d 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -60,8 +60,8 @@ class CodeTree public: CodeTree(); - ~CodeTree(); - + virtual ~CodeTree(); + struct LitInfo { LitInfo() {} @@ -204,7 +204,7 @@ class CodeTree return _data(); } - template inline T* getSuccessResult() { ASS(isSuccess()); return _data(); } + template inline T* getSuccessResult() const { ASS(isSuccess()); return _data(); } inline ILStruct* getILS() { @@ -338,6 +338,7 @@ class CodeTree * a call to the @b prepareLiteral function). */ CodeOp* op; + bool substIsRenaming; protected: bool doCheckGroundTerm(); @@ -357,6 +358,7 @@ class CodeTree */ FlatTerm* ft; + uint64_t substVRange; }; //////// auxiliary methods ////////// @@ -386,6 +388,7 @@ class CodeTree unsigned nextGlobalVarNum; VarMap varMap; VarMap globalVarMap; + Stack> eqCons; }; static CodeBlock* buildBlock(CodeStack& code, size_t cnt, ILStruct* prev); @@ -394,6 +397,7 @@ class CodeTree template void compressCheckOps(CodeOp* chainStart); + template static void compileTerm(const Term* trm, CodeStack& code, CompileContext& cctx, bool addLitEnd); //////////// removal ////////////// @@ -460,12 +464,15 @@ class CodeTree struct BTPoint { BTPoint() {} - BTPoint(size_t tp, CodeOp* op) : tp(tp), op(op) {} + BTPoint(size_t tp, CodeOp* op, bool substIsRenaming, size_t substVRange) + : tp(tp), op(op), substIsRenaming(substIsRenaming), substVRange(substVRange) {} /** Position in the flat term */ size_t tp; /** Pointer to the next operation */ CodeOp* op; + bool substIsRenaming; + uint64_t substVRange; }; typedef Stack BTStack; @@ -544,6 +551,8 @@ class CodeTree void incTimeStamp(); + virtual std::string leafToString(const CodeOp* success) const { return ""; } + //////// member variables ////////// diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index ae9af4c39..6580860fe 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -44,6 +44,8 @@ #include "DemodulationHelper.hpp" +#include "Shell/ConditionalRedundancyHandler.hpp" + #include "ForwardDemodulation.hpp" namespace Inferences { @@ -174,8 +176,18 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if (_precompiledComparison) { if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { + if (ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { + std::cout << qr.data->term << " " << qr.data->rhs << std::endl; + std::cout << qr.data->comparator->toString() << std::endl; + INVALID_OPERATION("greater"); + } continue; } + if (!ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { + std::cout << qr.data->term << " " << qr.data->rhs << std::endl; + std::cout << qr.data->comparator->toString() << std::endl; + INVALID_OPERATION("not greater"); + } } else { if (!preordered && (_preorderedOnly || !ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true)))) { continue; @@ -224,6 +236,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* premises = pvi( getSingletonIterator(qr.data->clause)); replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, qr.data->clause)); + ConditionalRedundancyHandler::transfer(cl, replacement); return true; } } diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index b5a03a23f..6ffc66577 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -386,8 +386,11 @@ Clause* Superposition::performSuperposition( } if (!unifier->usesUwa()) { - condRedHandler.insertSuperposition( - eqClause, rwClause, rwTermS, tgtTermS, eqLHS, rwLitS, eqLit, comp, eqIsResult, subst.ptr()); + if (!condRedHandler.insertSuperposition( + eqClause, rwClause, rwTermS, tgtTermS, eqLHS, rwLitS, eqLit, comp, eqIsResult, subst.ptr())) + { + return 0; + } } Literal* tgtLitS = EqHelper::replace(rwLitS,rwTermS,tgtTermS); @@ -556,5 +559,9 @@ Clause* Superposition::performSuperposition( env.proofExtra->insert(clause,extra); } + if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { + condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); + } + return clause; } diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index f9879142b..e108bfa81 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,71 +21,404 @@ using namespace Lib; using namespace Shell; KBOComparator::KBOComparator(TermList lhs, TermList rhs, const KBO& kbo) - : OrderingComparator(lhs, rhs, kbo) + : OrderingComparator(lhs, rhs, kbo), _root(lhs, rhs) { } -void KBOComparator::makeReady() +// void KBOComparator::makeReady() +// { +// ASS(!_ready); + +// const auto& kbo = static_cast(_ord); + +// // stack of subcomparisons in lexicographic order (w.r.t. tl1 and tl2) +// Stack> todo; +// todo.push(make_pair(_lhs,_rhs)); + +// while (todo.isNonEmpty()) { +// auto kv = todo.pop(); +// auto lhs = kv.first; +// auto rhs = kv.second; + +// auto comp = kbo.compare(lhs,rhs); +// switch (comp) { +// case Ordering::LESS: { +// // at this point the execution will fail, no further instructions +// return; +// } +// case Ordering::GREATER: { +// // at this point the execution will succeed, push SUCCESS +// _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); +// return; +// } +// default: +// break; +// } +// // this essentially means the EQUAL case +// if (comp != Ordering::INCOMPARABLE) { +// continue; +// } +// // if either term is a variable, we cannot preprocess them further +// if (lhs.isVar() || rhs.isVar()) { +// if (lhs.isVar() && rhs.isVar()) { +// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VV,lhs.var(),rhs.var())); +// } else if (lhs.isVar()) { +// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VT,lhs.var())); +// _instructions.push(Instruction::term(rhs.term())); +// } else if (rhs.isVar()) { +// // note that lhs is the second argument in this case +// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_TV,rhs.var())); +// _instructions.push(Instruction::term(lhs.term())); +// } + +// // Prepare further cases if this is equal. +// // Note that lhs and rhs are incomparable, +// // so we don't need an occurs check. +// Substitution subst; +// if (lhs.isVar()) { +// subst.bind(lhs.var(),rhs); +// } else { +// subst.bind(rhs.var(),lhs); +// } +// for (auto& kv : todo) { +// kv.first = SubstHelper::apply(kv.first,subst); +// kv.second = SubstHelper::apply(kv.second,subst); +// } +// continue; +// } + +// // if both are proper terms, we calculate +// // weight and variable balances first + +// // we only care about the non-zero weights and counts +// bool varInbalance = false; +// auto state = kbo._state; +// #if VDEBUG +// // we make sure kbo._state is not used while we're using it +// kbo._state = nullptr; +// #endif +// auto w = state->_weightDiff; +// decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); +// Stack> nonzeros; +// while (vit.hasNext()) { +// unsigned v; +// int cnt; +// vit.next(v,cnt); +// if (cnt!=0) { +// nonzeros.push(make_pair(v,cnt)); +// w-=cnt; // we have to remove the variable weights from w +// } +// if (cnt<0) { +// varInbalance = true; +// } +// } +// #if VDEBUG +// kbo._state = state; +// state = nullptr; +// #endif + +// // if the condition below does not hold, the weight/var balances are satisfied +// if (w < 0 || varInbalance) { +// // reinterpret weight here to unsigned because the compiler might not do it +// unsigned wu = reinterpret_cast(w); + +// _instructions.push(Instruction::uintUint(InstructionTag::WEIGHT, (unsigned)nonzeros.size(), wu)); +// // sort the [var,count] pairs by count descending so that +// // we can exit early during execution if needed +// sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { +// return e1.second>e2.second; +// }); +// for (const auto& [v,cnt] : nonzeros) { +// // see same with weight above +// unsigned cntu = reinterpret_cast(cnt); + +// _instructions.push(Instruction::uintUint(InstructionTag::DATA, v, cntu)); +// } +// } + +// auto lhst = lhs.term(); +// auto rhst = rhs.term(); + +// Ordering::Result prec = lhst->isSort() +// ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) +// : kbo.compareFunctionPrecedences(lhst->functor(),rhst->functor()); +// switch (prec) +// { +// case Ordering::LESS: { +// // again, this means the execution failed +// return; +// } +// case Ordering::GREATER: { +// // and this means the execution succeeded +// _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); +// return; +// } +// case Ordering::EQUAL: { +// // push the arguments in reverse order to maintain +// // left-to-right lexicographic order in todo +// for (unsigned i = 0; i < lhst->arity(); i++) { +// auto lhsArg = *lhst->nthArgument(lhst->arity()-i-1); +// auto rhsArg = *rhst->nthArgument(lhst->arity()-i-1); +// todo.push(make_pair(lhsArg,rhsArg)); +// } +// break; +// } +// default: { +// ASSERTION_VIOLATION; +// } +// } +// } +// } + +// bool KBOComparator::check(const SubstApplicator* applicator) +// { +// if (!_ready) { +// makeReady(); +// _ready = true; +// } + +// const auto& kbo = static_cast(_ord); + +// for (unsigned i = 0; i < _instructions.size();) { +// switch (static_cast(_instructions[i]._tag())) { +// case InstructionTag::WEIGHT: { + +// // check weight and var balance +// auto arity = _instructions[i]._firstUint(); +// auto weight = _instructions[i]._coeff(); +// ZIArray varDiffs; +// for (unsigned j = i+1; j < i+1+arity; j++) { +// ASS(_instructions[j]._tag()==InstructionTag::DATA); + +// auto var = _instructions[j]._firstUint(); +// auto coeff = _instructions[j]._coeff(); +// AppliedTerm tt(TermList::var(var), applicator, true); + +// VariableIterator vit(tt.term); +// while (vit.hasNext()) { +// auto v = vit.next(); +// varDiffs[v.var()] += coeff; +// // since the counts are sorted in descending order, +// // this can only mean we will fail +// if (varDiffs[v.var()]<0) { +// return false; +// } +// } +// auto w = kbo.computeWeight(tt); +// weight += coeff*w; +// // due to descending order of counts, +// // this also means failure +// if (coeff<0 && weight<0) { +// return false; +// } +// } + +// if (weight > 0) { +// return true; +// } else if (weight < 0) { +// return false; +// } +// // jump over the [var,count] pairs +// i += 1+arity; +// break; +// } +// case InstructionTag::COMPARE_VV: { +// auto res = kbo.isGreaterOrEq( +// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), +// AppliedTerm(TermList::var(_instructions[i]._secondUint()), applicator, true)); +// if (res==Ordering::EQUAL) { +// i++; +// break; +// } +// return res==Ordering::GREATER; +// } +// case InstructionTag::COMPARE_VT: { +// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); +// auto res = kbo.isGreaterOrEq( +// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), +// AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true)); +// if (res==Ordering::EQUAL) { +// i += 2; +// break; +// } +// return res==Ordering::GREATER; +// } +// case InstructionTag::COMPARE_TV: { +// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); +// // note that in this case the term is the second argument +// auto res = kbo.isGreaterOrEq( +// AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true), +// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true)); +// if (res==Ordering::EQUAL) { +// i += 2; +// break; +// } +// return res==Ordering::GREATER; +// } +// case InstructionTag::SUCCESS: { +// return true; +// } +// default: +// ASSERTION_VIOLATION; +// } +// } +// return false; +// } + +ostream& operator<<(ostream& out, const KBOComparator::BranchTag& t) +{ + switch (t) { + case KBOComparator::BranchTag::T_NOT_GREATER: + out << "!>"; + break; + case KBOComparator::BranchTag::T_GREATER: + out << ">"; + break; + case KBOComparator::BranchTag::T_COMPARISON: + out << "$"; + break; + case KBOComparator::BranchTag::T_WEIGHT: + out << "w"; + break; + case KBOComparator::BranchTag::T_UNKNOWN: + out << "?"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& str, const KBOComparator::Branch& branch) { - ASS(!_ready); + str << branch.tag << " "; + if (branch.n) { + if (branch.tag==KBOComparator::BranchTag::T_WEIGHT) { + auto n = static_cast(branch.n.ptr()); + str << n->w << " "; + for (const auto& [var, coeff] : n->varCoeffPairs) { + str << "X" << var << " " << coeff << " "; + } + } else { + auto n = static_cast(branch.n.ptr()); + str << n->lhs << " " << n->rhs; + } + } else { + str << "null"; + } + return str; +} - const auto& kbo = static_cast(_ord); +ostream& operator<<(ostream& str, const KBOComparator& comp) +{ + str << "comparator for " << comp._lhs << " > " << comp._rhs << endl; + // return str; - // stack of subcomparisons in lexicographic order (w.r.t. tl1 and tl2) - Stack> todo; - todo.push(make_pair(_lhs,_rhs)); + Stack> todo; + todo.push(make_pair(&comp._root,0)); + unsigned cnt = 1; while (todo.isNonEmpty()) { auto kv = todo.pop(); - auto lhs = kv.first; - auto rhs = kv.second; + str << cnt++ << " "; + for (unsigned i = 0; i < kv.second; i++) { + str << " "; + } + str << *kv.first << endl; + if (kv.first->n) { + todo.push(make_pair(&kv.first->n->incBranch,kv.second+1)); + todo.push(make_pair(&kv.first->n->gtBranch,kv.second+1)); + todo.push(make_pair(&kv.first->n->eqBranch,kv.second+1)); + } + } + return str; +} - auto comp = kbo.compare(lhs,rhs); - switch (comp) { - case Ordering::LESS: { - // at this point the execution will fail, no further instructions - return; +std::string KBOComparator::toString() const +{ + std::stringstream str; + str << *this << endl; + return str.str(); +} + +bool KBOComparator::check(const SubstApplicator* applicator) +{ + const auto& kbo = static_cast(_ord); + auto curr = &_root; + + while (curr->n) { + expand(*curr, kbo); + if (!curr->n) { + break; + } + ASS(curr->n); + Ordering::Result comp = Ordering::INCOMPARABLE; + if (curr->tag==BranchTag::T_COMPARISON) { + auto node = static_cast(curr->n.ptr()); + comp = kbo.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); + } else { + ASS(curr->tag==BranchTag::T_WEIGHT); + auto node = static_cast(curr->n.ptr()); + auto weight = node->w; + ZIArray varDiffs; + for (const auto& [var, coeff] : node->varCoeffPairs) { + AppliedTerm tt(TermList::var(var), applicator, true); + + VariableIterator vit(tt.term); + while (vit.hasNext()) { + auto v = vit.next(); + varDiffs[v.var()] += coeff; + // since the counts are sorted in descending order, + // this can only mean we will fail + if (varDiffs[v.var()]<0) { + goto loop_end; + } + } + auto w = kbo.computeWeight(tt); + weight += coeff*w; + // due to descending order of counts, + // this also means failure + if (coeff<0 && weight<0) { + goto loop_end; + } } - case Ordering::GREATER: { - // at this point the execution will succeed, push SUCCESS - _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); - return; + + if (weight > 0) { + comp = Ordering::GREATER; + } else if (weight == 0) { + comp = Ordering::EQUAL; } - default: - break; } - // this essentially means the EQUAL case - if (comp != Ordering::INCOMPARABLE) { - continue; - } - // if either term is a variable, we cannot preprocess them further - if (lhs.isVar() || rhs.isVar()) { - if (lhs.isVar() && rhs.isVar()) { - _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VV,lhs.var(),rhs.var())); - } else if (lhs.isVar()) { - _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VT,lhs.var())); - _instructions.push(Instruction::term(rhs.term())); - } else if (rhs.isVar()) { - // note that lhs is the second argument in this case - _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_TV,rhs.var())); - _instructions.push(Instruction::term(lhs.term())); - } +loop_end: + curr = &curr->n->getBranch(comp); + } + return curr->tag == BranchTag::T_GREATER; +} + +void KBOComparator::expand(Branch& branch, const KBO& kbo) +{ + while (branch.tag == BranchTag::T_UNKNOWN) + { + // take temporary ownership of node + Branch nodeHolder = branch; + auto node = static_cast(nodeHolder.n.ptr()); - // Prepare further cases if this is equal. - // Note that lhs and rhs are incomparable, - // so we don't need an occurs check. - Substitution subst; - if (lhs.isVar()) { - subst.bind(lhs.var(),rhs); + // Use compare here to filter out as many + // precomputable comparisons as possible. + auto comp = kbo.compare(node->lhs,node->rhs); + if (comp != Ordering::INCOMPARABLE) { + if (comp == Ordering::LESS) { + branch = node->incBranch; + } else if (comp == Ordering::GREATER) { + branch = node->gtBranch; } else { - subst.bind(rhs.var(),lhs); - } - for (auto& kv : todo) { - kv.first = SubstHelper::apply(kv.first,subst); - kv.second = SubstHelper::apply(kv.second,subst); + branch = node->eqBranch; } continue; } + // If we have a variable, we cannot preprocess further. + if (node->lhs.isVar() || node->rhs.isVar()) { + branch.tag = BranchTag::T_COMPARISON; + continue; + } // if both are proper terms, we calculate // weight and variable balances first @@ -117,27 +450,21 @@ void KBOComparator::makeReady() state = nullptr; #endif + auto curr = &branch; + // if the condition below does not hold, the weight/var balances are satisfied if (w < 0 || varInbalance) { - // reinterpret weight here to unsigned because the compiler might not do it - unsigned wu = reinterpret_cast(w); - - _instructions.push(Instruction::uintUint(InstructionTag::WEIGHT, (unsigned)nonzeros.size(), wu)); - // sort the [var,count] pairs by count descending so that - // we can exit early during execution if needed sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { return e1.second>e2.second; }); - for (const auto& [v,cnt] : nonzeros) { - // see same with weight above - unsigned cntu = reinterpret_cast(cnt); - - _instructions.push(Instruction::uintUint(InstructionTag::DATA, v, cntu)); - } + *curr = Branch(w, std::move(nonzeros)); + curr->n->gtBranch = node->gtBranch; + curr->n->incBranch = node->incBranch; + curr = &branch.n->eqBranch; } - auto lhst = lhs.term(); - auto rhst = rhs.term(); + auto lhst = node->lhs.term(); + auto rhst = node->rhs.term(); Ordering::Result prec = lhst->isSort() ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) @@ -145,22 +472,23 @@ void KBOComparator::makeReady() switch (prec) { case Ordering::LESS: { - // again, this means the execution failed - return; + *curr = node->incBranch; + break; } case Ordering::GREATER: { - // and this means the execution succeeded - _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); - return; + *curr = node->gtBranch; + break; } case Ordering::EQUAL: { // push the arguments in reverse order to maintain // left-to-right lexicographic order in todo for (unsigned i = 0; i < lhst->arity(); i++) { - auto lhsArg = *lhst->nthArgument(lhst->arity()-i-1); - auto rhsArg = *rhst->nthArgument(lhst->arity()-i-1); - todo.push(make_pair(lhsArg,rhsArg)); + auto lhsArg = *lhst->nthArgument(i); + auto rhsArg = *rhst->nthArgument(i); + *curr = Branch(lhsArg,rhsArg); + curr = &curr->n->eqBranch; } + *curr = node->eqBranch; break; } default: { @@ -170,159 +498,145 @@ void KBOComparator::makeReady() } } -bool KBOComparator::check(const SubstApplicator* applicator) -{ - if (!_ready) { - makeReady(); - _ready = true; - } - - const auto& kbo = static_cast(_ord); - - for (unsigned i = 0; i < _instructions.size();) { - switch (static_cast(_instructions[i]._tag())) { - case InstructionTag::WEIGHT: { - - // check weight and var balance - auto arity = _instructions[i]._firstUint(); - auto weight = _instructions[i]._coeff(); - ZIArray varDiffs; - for (unsigned j = i+1; j < i+1+arity; j++) { - ASS(_instructions[j]._tag()==InstructionTag::DATA); - - auto var = _instructions[j]._firstUint(); - auto coeff = _instructions[j]._coeff(); - AppliedTerm tt(TermList::var(var), applicator, true); - - VariableIterator vit(tt.term); - while (vit.hasNext()) { - auto v = vit.next(); - varDiffs[v.var()] += coeff; - // since the counts are sorted in descending order, - // this can only mean we will fail - if (varDiffs[v.var()]<0) { - return false; - } - } - auto w = kbo.computeWeight(tt); - weight += coeff*w; - // due to descending order of counts, - // this also means failure - if (coeff<0 && weight<0) { - return false; - } - } - - if (weight > 0) { - return true; - } else if (weight < 0) { - return false; - } - // jump over the [var,count] pairs - i += 1+arity; - break; - } - case InstructionTag::COMPARE_VV: { - auto res = kbo.isGreaterOrEq( - AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), - AppliedTerm(TermList::var(_instructions[i]._secondUint()), applicator, true)); - if (res==Ordering::EQUAL) { - i++; - break; - } - return res==Ordering::GREATER; - } - case InstructionTag::COMPARE_VT: { - ASS(_instructions[i+1]._tag()==InstructionTag::DATA); - auto res = kbo.isGreaterOrEq( - AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), - AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true)); - if (res==Ordering::EQUAL) { - i += 2; - break; - } - return res==Ordering::GREATER; - } - case InstructionTag::COMPARE_TV: { - ASS(_instructions[i+1]._tag()==InstructionTag::DATA); - // note that in this case the term is the second argument - auto res = kbo.isGreaterOrEq( - AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true), - AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true)); - if (res==Ordering::EQUAL) { - i += 2; - break; - } - return res==Ordering::GREATER; - } - case InstructionTag::SUCCESS: { - return true; - } - default: - ASSERTION_VIOLATION; - } - } - return false; -} +// std::string KBOComparator::toString() const +// { +// std::stringstream str; -std::string KBOComparator::toString() const -{ - std::stringstream str; +// unsigned cnt = 1; +// for (unsigned i = 0; i < _instructions.size();) { +// switch (static_cast(_instructions[i]._tag())) { +// case InstructionTag::SUCCESS: { +// str << Int::toString(cnt++) << " success, "; +// i += 1; +// break; +// } +// case InstructionTag::WEIGHT: { +// auto arity = _instructions[i]._firstUint(); +// auto w = _instructions[i]._coeff(); +// str << Int::toString(cnt++) << " weight " << Int::toString(w); - unsigned cnt = 1; - for (unsigned i = 0; i < _instructions.size();) { - switch (static_cast(_instructions[i]._tag())) { - case InstructionTag::SUCCESS: { - str << Int::toString(cnt++) << " success" << endl; - i += 1; - break; - } - case InstructionTag::WEIGHT: { - auto arity = _instructions[i]._firstUint(); - auto w = _instructions[i]._coeff(); - str << Int::toString(cnt++) << " weight " << Int::toString(w); +// for (unsigned j = i+1; j < i+1+arity; j++) { +// ASS(_instructions[j]._tag()==InstructionTag::DATA); +// auto var = _instructions[j]._firstUint(); +// auto coeff = _instructions[j]._coeff(); - for (unsigned j = i+1; j < i+1+arity; j++) { - ASS(_instructions[j]._tag()==InstructionTag::DATA); - auto var = _instructions[j]._firstUint(); - auto coeff = _instructions[j]._coeff(); +// str << " w(X" << Int::toString(var) << ")*" << Int::toString(coeff); +// } +// str << ", "; +// i += 1+arity; +// break; +// } +// case InstructionTag::COMPARE_VV: { +// auto v1 = _instructions[i]._firstUint(); +// auto v2 = _instructions[i]._secondUint(); +// str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " X" << Int::toString(v2) << ", "; +// i++; +// break; +// } +// case InstructionTag::COMPARE_VT: { +// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); +// auto v1 = _instructions[i]._firstUint(); +// auto t2 = _instructions[i+1]._term(); +// str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " " << *t2 << ", "; +// i += 2; +// break; +// } +// case InstructionTag::COMPARE_TV: { +// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); +// auto t1 = _instructions[i+1]._term(); +// auto v2 = _instructions[i]._firstUint(); +// str << Int::toString(cnt++) << " compare " << *t1 << " X" << Int::toString(v2) << ", "; +// i += 2; +// break; +// } +// default: +// ASSERTION_VIOLATION; +// } +// } +// return str.str(); +// } - str << " w(X" << Int::toString(var) << ")*" << Int::toString(coeff); - } - str << endl; - i += 1+arity; - break; - } - case InstructionTag::COMPARE_VV: { - auto v1 = _instructions[i]._firstUint(); - auto v2 = _instructions[i]._secondUint(); - str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " X" << Int::toString(v2) << endl; - i++; - break; - } - case InstructionTag::COMPARE_VT: { - ASS(_instructions[i+1]._tag()==InstructionTag::DATA); - auto v1 = _instructions[i]._firstUint(); - auto t2 = _instructions[i+1]._term(); - str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " " << *t2 << endl; - i += 2; - break; - } - case InstructionTag::COMPARE_TV: { - ASS(_instructions[i+1]._tag()==InstructionTag::DATA); - auto t1 = _instructions[i+1]._term(); - auto v2 = _instructions[i]._firstUint(); - str << Int::toString(cnt++) << " compare " << *t1 << " X" << Int::toString(v2) << endl; - i += 2; - break; - } - default: - ASSERTION_VIOLATION; - } - } - str << endl; - return str.str(); -} +// bool KBOComparator::subsumes(OrderingComparator& other) +// { +// if (!_ready) { +// makeReady(); +// _ready = true; +// } +// auto& otherKBO = static_cast(other); +// if (!otherKBO._ready) { +// otherKBO.makeReady(); +// otherKBO._ready = true; +// } +// if (_instructions.size()(_instructions[i]._tag())) { +// case InstructionTag::WEIGHT: { +// // check weight and var balance +// auto arity = _instructions[i]._firstUint(); +// auto weight = _instructions[i]._coeff(); +// auto arityOther = otherKBO._instructions[i]._firstUint(); +// auto weightOther = otherKBO._instructions[i]._coeff(); +// if (arity != arityOther || weight != weightOther) { +// return false; +// } +// for (unsigned j = i+1; j < i+1+arity; j++) { +// ASS(_instructions[j]._tag()==InstructionTag::DATA); +// auto var = _instructions[j]._firstUint(); +// auto coeff = _instructions[j]._coeff(); +// auto varOther = otherKBO._instructions[j]._firstUint(); +// auto coeffOther = otherKBO._instructions[j]._coeff(); +// // if ((*renaming)(var) != TermList::var(varOther) || coeff != coeffOther) { +// // return false; +// // } +// if (var != varOther || coeff != coeffOther) { +// return false; +// } +// } +// // jump over the [var,count] pairs +// i += 1+arity; +// break; +// } +// case InstructionTag::COMPARE_VV: { +// auto var1 = _instructions[i]._firstUint(); +// auto var2 = _instructions[i]._secondUint(); +// auto var1Other = otherKBO._instructions[i]._firstUint(); +// auto var2Other = otherKBO._instructions[i]._secondUint(); +// // if ((*renaming)(var1) != TermList::var(var1Other) || (*renaming)(var2) != TermList::var(var2Other)) { +// // return false; +// // } +// if (var1 != var1Other || var2 != var2Other) { +// return false; +// } +// i++; +// break; +// } +// case InstructionTag::COMPARE_VT: +// case InstructionTag::COMPARE_TV: { +// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); +// auto var = _instructions[i]._firstUint(); +// auto term = _instructions[i+1]._term(); +// auto varOther = otherKBO._instructions[i]._firstUint(); +// auto termOther = otherKBO._instructions[i+1]._term(); +// // if ((*renaming)(var) != TermList::var(varOther) || SubstHelper::apply(TermList(term),*renaming) != TermList(termOther)) { +// // return false; +// // } +// if (var != varOther || term != termOther) { +// return false; +// } +// i += 2; +// break; +// } +// default: +// return true; +// } +// } +// return true; +// } } diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 15adc4578..ed65288e9 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -38,81 +38,151 @@ class KBOComparator /** Executes the runtime specialized instructions with concrete substitution. */ bool check(const SubstApplicator* applicator) override; std::string toString() const override; + // bool subsumes(OrderingComparator& other) override; -private: +// private: void makeReady(); - enum InstructionTag { - DATA = 0u, - WEIGHT = 1u, - COMPARE_VV = 2u, - COMPARE_VT = 3u, - COMPARE_TV = 4u, - SUCCESS = 5u, + // enum InstructionTag { + // DATA = 0u, + // WEIGHT = 1u, + // COMPARE_VV = 2u, + // COMPARE_VT = 3u, + // COMPARE_TV = 4u, + // SUCCESS = 5u, + // }; + + // /** + // * Stores atomic instructions for KBO. + // * We have 64 bits per instruction, and the following combinations (where ?> denotes checking >): + // * - success + // * - weight check: w + |var_i o \theta|_v * nvar_i ?> 0 + // * - compare var with var: (var1 o \theta) ?> (var2 o \theta) + // * - compare var with term: (var o \theta) ?> (term o \theta) + // * - compare term with var: (term o \theta) ?> (var o \theta) + // * + // * and the following layout of instructions: + // * | first instruction | second instruction | ... + // * | 3 bits | 29 bits | 32 bits | 3 bits | 29 bits | 32 bits | + // * | SUCCESS | + // * | WEIGHT | arity | w | DATA | var_i | nvar_i | ... (this block `arity` times) + // * | COMPARE_VV | var1 | var2 | + // * | COMPARE_VT | var | | term | + // * | COMPARE_TV | var | | term | + // */ + // struct Instruction { + // static Instruction term(Term* t) { + // Instruction ins; + // ins._setTag(InstructionTag::DATA); + // ins._setTerm(t); + // return ins; + // } + // static Instruction uintUint(InstructionTag t, unsigned v1 = 0, unsigned v2 = 0) { + // Instruction ins; + // ins._content = 0; // to silence a gcc warning (we set all bits below anyway) + // ins._setTag(t); + // ins._setFirstUint(v1); + // ins._setSecondUint(v2); + // return ins; + // } + + // static constexpr unsigned + // TAG_BITS_START = 0, + // TAG_BITS_END = TAG_BITS_START + 3, + // FIRST_UINT_BITS_START = TAG_BITS_END, + // FIRST_UINT_BITS_END = FIRST_UINT_BITS_START + 29, + // SECOND_UINT_BITS_START = FIRST_UINT_BITS_END, + // SECOND_UINT_BITS_END = SECOND_UINT_BITS_START + 32, + // COEFF_BITS_START = FIRST_UINT_BITS_END, + // COEFF_BITS_END = COEFF_BITS_START + 32, + // TERM_BITS_START = 0, + // TERM_BITS_END = CHAR_BIT * sizeof(Term *); + + // static_assert(TAG_BITS_START == 0, "tag must be the least significant bits"); + // static_assert(TERM_BITS_START == 0, "term must be the least significant bits"); + // static_assert(sizeof(void *) <= sizeof(uint64_t), "must be able to fit a pointer into a 64-bit integer"); + // static_assert(InstructionTag::SUCCESS < 8, "must be able to squash tags into 3 bits"); + + // BITFIELD64_GET_AND_SET(unsigned, tag, Tag, TAG) + // BITFIELD64_GET_AND_SET(unsigned, firstUint, FirstUint, FIRST_UINT) + // BITFIELD64_GET_AND_SET(unsigned, secondUint, SecondUint, SECOND_UINT) + // BITFIELD64_GET_AND_SET(int, coeff, Coeff, COEFF) + // BITFIELD64_GET_AND_SET_PTR(Term*, term, Term, TERM) + + // private: + // uint64_t _content; + // }; + + enum class BranchTag : uint8_t { + T_GREATER, + T_NOT_GREATER, + T_COMPARISON, + T_WEIGHT, + T_UNKNOWN, }; - /** - * Stores atomic instructions for KBO. - * We have 64 bits per instruction, and the following combinations (where ?> denotes checking >): - * - success - * - weight check: w + |var_i o \theta|_v * nvar_i ?> 0 - * - compare var with var: (var1 o \theta) ?> (var2 o \theta) - * - compare var with term: (var o \theta) ?> (term o \theta) - * - compare term with var: (term o \theta) ?> (var o \theta) - * - * and the following layout of instructions: - * | first instruction | second instruction | ... - * | 3 bits | 29 bits | 32 bits | 3 bits | 29 bits | 32 bits | - * | SUCCESS | - * | WEIGHT | arity | w | DATA | var_i | nvar_i | ... (this block `arity` times) - * | COMPARE_VV | var1 | var2 | - * | COMPARE_VT | var | | term | - * | COMPARE_TV | var | | term | - */ - struct Instruction { - static Instruction term(Term* t) { - Instruction ins; - ins._setTag(InstructionTag::DATA); - ins._setTerm(t); - return ins; - } - static Instruction uintUint(InstructionTag t, unsigned v1 = 0, unsigned v2 = 0) { - Instruction ins; - ins._content = 0; // to silence a gcc warning (we set all bits below anyway) - ins._setTag(t); - ins._setFirstUint(v1); - ins._setSecondUint(v2); - return ins; + struct Node; + + struct Branch { + BranchTag tag; + SmartPtr n; + + explicit Branch(BranchTag t) : tag(t) { ASS(t==BranchTag::T_GREATER || t==BranchTag::T_NOT_GREATER); } + explicit Branch(TermList lhs, TermList rhs) + : tag(BranchTag::T_UNKNOWN), n(new ComparisonNode(lhs, rhs)) {} + explicit Branch(int w, Stack>&& varCoeffPairs) + : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))) {} + }; + + struct Node { + Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER) {} + + auto& getBranch(Ordering::Result r) { + switch (r) { + case Ordering::EQUAL: + return eqBranch; + case Ordering::GREATER: + return gtBranch; + case Ordering::INCOMPARABLE: + return incBranch; + default: + ASSERTION_VIOLATION; + } } - static constexpr unsigned - TAG_BITS_START = 0, - TAG_BITS_END = TAG_BITS_START + 3, - FIRST_UINT_BITS_START = TAG_BITS_END, - FIRST_UINT_BITS_END = FIRST_UINT_BITS_START + 29, - SECOND_UINT_BITS_START = FIRST_UINT_BITS_END, - SECOND_UINT_BITS_END = SECOND_UINT_BITS_START + 32, - COEFF_BITS_START = FIRST_UINT_BITS_END, - COEFF_BITS_END = COEFF_BITS_START + 32, - TERM_BITS_START = 0, - TERM_BITS_END = CHAR_BIT * sizeof(Term *); - - static_assert(TAG_BITS_START == 0, "tag must be the least significant bits"); - static_assert(TERM_BITS_START == 0, "term must be the least significant bits"); - static_assert(sizeof(void *) <= sizeof(uint64_t), "must be able to fit a pointer into a 64-bit integer"); - static_assert(InstructionTag::SUCCESS < 8, "must be able to squash tags into 3 bits"); - - BITFIELD64_GET_AND_SET(unsigned, tag, Tag, TAG) - BITFIELD64_GET_AND_SET(unsigned, firstUint, FirstUint, FIRST_UINT) - BITFIELD64_GET_AND_SET(unsigned, secondUint, SecondUint, SECOND_UINT) - BITFIELD64_GET_AND_SET(int, coeff, Coeff, COEFF) - BITFIELD64_GET_AND_SET_PTR(Term*, term, Term, TERM) - - private: - uint64_t _content; + Branch eqBranch; + Branch gtBranch; + Branch incBranch; }; + + class ComparisonNode : public Node { + ComparisonNode(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs) {} + + // only allow calling ctor from Branch + friend struct Branch; + + public: + TermList lhs; + TermList rhs; + }; + + class WeightNode : public Node { + WeightNode(unsigned w, Stack>&& varCoeffPairs) + : w(w), varCoeffPairs(varCoeffPairs) {} + + // only allow calling ctor from Branch + friend struct Branch; + + public: + int w; + Stack> varCoeffPairs; + }; + + static void expand(Branch& branch, const KBO& kbo); + bool _ready = false; - Stack _instructions; + // Stack _instructions; + Branch _root; }; } diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index 9a573740c..ea5ca8793 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -45,6 +45,7 @@ struct OrderingComparator virtual ~OrderingComparator() = default; virtual std::string toString() const { return _lhs.toString()+" > "+_rhs.toString(); } virtual bool check(const SubstApplicator* applicator); + virtual bool subsumes(OrderingComparator& other) { return false; } TermList _lhs; TermList _rhs; diff --git a/Saturation/Splitter.cpp b/Saturation/Splitter.cpp index 933dfc042..8f96ff159 100644 --- a/Saturation/Splitter.cpp +++ b/Saturation/Splitter.cpp @@ -835,7 +835,7 @@ void Splitter::onAllProcessed() // but would need to maintain them even when _deleteDeactivated == Options::SplittingDeleteDeactivated::ON if (allSplitLevelsActive(rcl->splits())) { RSTAT_CTR_INC("fast_clauses_restored"); - _sa->addNewClause(rcl); + addNewClause(rcl); } else { RSTAT_CTR_INC("fast_clauses_not_restored"); } @@ -1520,12 +1520,17 @@ bool Splitter::allSplitLevelsActive(SplitSet* s) return true; } -void Splitter::onNewClause(Clause* cl) +void Splitter::addNewClause(Clause* cl) { // when using AVATAR, we could have performed // generating inferences on the clause previously, // so we need to reset the data. ConditionalRedundancyHandler::destroyClauseData(cl); + _sa->addNewClause(cl); +} + +void Splitter::onNewClause(Clause* cl) +{ if (cl->inference().rule() == InferenceRule::AVATAR_ASSERTION_REINTRODUCTION) { // Do not assign splits from premises if cl originated by re-introducing AVATAR assertions (avoids looping) @@ -1675,7 +1680,7 @@ void Splitter::addComponents(const SplitLevelStack& toAdd) //we need to put the component clause among children, //so that it is backtracked when we remove the component sr->children.push(sr->component); - _sa->addNewClause(sr->component); + addNewClause(sr->component); } else { // children were kept, so we just put them back RCClauseStack::Iterator chit(sr->children); @@ -1683,7 +1688,7 @@ void Splitter::addComponents(const SplitLevelStack& toAdd) Clause* cl = chit.next(); cl->incNumActiveSplits(); if (cl->getNumActiveSplits() == (int)cl->splits()->size()) { - _sa->addNewClause(cl); + addNewClause(cl); //check that restored clause does not depend on inactive splits ASS(allSplitLevelsActive(cl->splits())); } @@ -1757,7 +1762,7 @@ void Splitter::removeComponents(const SplitLevelStack& toRemove) ASS_EQ(rcl->store(), Clause::NONE); rcl->invalidateMyReductionRecords(); // to make sure we don't unfreeze this clause a second time - _sa->addNewClause(rcl); + addNewClause(rcl); // TODO: keep statistics in release ? // RSTAT_MCTR_INC("unfrozen clauses",rcl->getFreezeCount()); diff --git a/Saturation/Splitter.hpp b/Saturation/Splitter.hpp index 309bc98c0..379e82677 100644 --- a/Saturation/Splitter.hpp +++ b/Saturation/Splitter.hpp @@ -186,6 +186,7 @@ class Splitter { void onClauseReduction(Clause* cl, ClauseIterator premises, Clause* replacement); void addConditionalRedundancyEntry(SplitSet* splits, ConditionalRedundancyEntry* e); + void addNewClause(Clause* cl); void onNewClause(Clause* cl); void onAllProcessed(); bool handleEmptyClause(Clause* cl); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index b1fc4b6b1..1e9f0f686 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -49,6 +49,25 @@ bool checkVars(const TermStack& ts, T s) return true; } +std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) +{ + if (!e.active) { + str << "not active"; + } else { + str << *e.splits << "; " << *e.lits << "; "; + iterTraits(e.ordCons.iter()).forEach([&str](const OrderingConstraint& con) { + str << (con.comp ? con.comp->toString() : (con.lhs.toString()+" > "+con.rhs.toString())); + }); + } + return str; +} + +void ensureComparator(const Ordering* ord, OrderingConstraint& cons) { + if (!cons.comp) { + cons.comp = ord->createComparator(cons.lhs, cons.rhs); + } +} + class ConditionalRedundancyHandler::ConstraintIndex : public CodeTree { @@ -74,11 +93,11 @@ class ConditionalRedundancyHandler::ConstraintIndex return !check(ts, ord, lits, splits); } - void insert(ResultSubstitution* subst, bool result, Splitter* splitter, + bool insert(const Ordering* ord, ResultSubstitution* subst, bool result, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) { auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - insert(ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } bool checkAndInsert(const Ordering* ord, ResultSubstitution* subst, bool result, bool doInsert, Splitter* splitter, @@ -94,7 +113,7 @@ class ConditionalRedundancyHandler::ConstraintIndex return false; } if (doInsert) { - insert(ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } return true; } @@ -104,34 +123,98 @@ class ConditionalRedundancyHandler::ConstraintIndex Clause* _cl; #endif - void insert(const TermStack& ts, void* ptr) + bool insert(const Ordering* ord, Entries* entries, ConditionalRedundancyEntry* ptr) { + ASS(ptr->active); + + auto numCons = ptr->lits->size() + ptr->splits->size() + ptr->ordCons.size() + ptr->eqCons.size(); + if (ptr->ordCons.size()==1) { + for (unsigned i = 0; i < entries->size();) { + const auto& e = (*entries)[i]; + if (e->active && e->lits->isEmpty() && e->splits->isEmpty() && e->ordCons.size()==1) { + ensureComparator(ord, e->ordCons[0]); + ensureComparator(ord, ptr->ordCons[0]); + if (e->ordCons[0].comp->subsumes(*ptr->ordCons[0].comp)) { + env.statistics->skippedInferencesDueToOrderingConstraints++; + return false; + } + if (ptr->ordCons[0].comp->subsumes(*e->ordCons[0].comp)) { + std::swap((*entries)[i],entries->top()); + entries->pop(); + continue; + } + } + i++; + } + } + entries->push(ptr); + return true; + } + + bool insert(const Ordering* ord, const TermStack& ts, ConditionalRedundancyEntry* ptr) + { + if (lastRenamingEntry) { + // there is an entry up to renaming already, insert it here + if (insert(ord, lastRenamingEntry, ptr)) { + // cout << "insert2 " << *_cl << endl; + // cout << varSortsToString(_varSorts) << endl; + // cout << *this << endl << endl; + return true; + } + // cout << "no insert " << *_cl << endl; + // cout << varSortsToString(_varSorts) << endl; + return false; + } + static CodeStack code; code.reset(); +#define LINEARIZE 0 + static CompileContext cctx; cctx.init(); for (const auto& t : ts) { if (t.isVar()) { unsigned var=t.var(); unsigned* varNumPtr; +#if LINEARIZE + if (cctx.varMap.getValuePtr(var,varNumPtr)) { + *varNumPtr = cctx.nextVarNum; + } else { + cctx.eqCons.push(make_pair(*varNumPtr, cctx.nextVarNum)); + } + code.push(CodeOp::getTermOp(ASSIGN_VAR, cctx.nextVarNum)); + cctx.nextVarNum++; +#else if (cctx.varMap.getValuePtr(var,varNumPtr)) { *varNumPtr=cctx.nextVarNum++; code.push(CodeOp::getTermOp(ASSIGN_VAR, *varNumPtr)); } else { code.push(CodeOp::getTermOp(CHECK_VAR, *varNumPtr)); } +#endif } else { ASS(t.isTerm()); - compileTerm(t.term(), code, cctx, false); +#if LINEARIZE + compileTerm(t.term(), code, cctx, false); +#else + compileTerm(t.term(), code, cctx, false); +#endif } } + ptr->eqCons = cctx.eqCons; cctx.deinit(this); // just put anything non-null in there to get a valid success - code.push(CodeOp::getSuccess(ptr)); + auto es = new Entries(); + es->push(ptr); + code.push(CodeOp::getSuccess(es)); incorporate(code); + // cout << "insert " << *_cl << endl; + // cout << varSortsToString(_varSorts) << endl; + // cout << *this << endl << endl; + return true; } bool check(const TermStack& ts, const Ordering* ord, const LiteralSet* lits, const SplitSet* splits) @@ -145,14 +228,30 @@ class ConditionalRedundancyHandler::ConstraintIndex TermList operator()(unsigned v) const override { return matcher.bindings[v]; } } applicator; + lastRenamingEntry = nullptr; matcher.init(this, ts); - ConditionalRedundancyEntry* e; - while ((e = matcher.next())) + Entries* es; + while ((es = matcher.next())) { + if (matcher.substIsRenaming) { + lastRenamingEntry = es; + } + + // TODO indent + for (const auto& e : *es) { + if (!e->active) { continue; } + // auto eqs_ok = iterTraits(e->eqCons.iter()).all([&applicator](const auto& kv) { + // return applicator(kv.first) == applicator(kv.second); + // }); + // if (!eqs_ok) { + // env.statistics->structInduction++; + // continue; + // } + // check AVATAR constraints if (!e->splits->isSubsetOf(splits)) { continue; @@ -168,9 +267,7 @@ class ConditionalRedundancyHandler::ConstraintIndex // check ordering constraints auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - if (!ordCon.comp) { - ordCon.comp = ord->createComparator(ordCon.lhs, ordCon.rhs); - } + ensureComparator(ord, ordCon); return ordCon.comp->check(&applicator); }); if (!ordCons_ok) { @@ -188,6 +285,7 @@ class ConditionalRedundancyHandler::ConstraintIndex env.statistics->skippedInferencesDueToAvatarConstraints++; } return true; + } } matcher.reset(); @@ -261,6 +359,8 @@ class ConditionalRedundancyHandler::ConstraintIndex op=entry; tp=0; + substIsRenaming=true; + substVRange=0; } void reset() @@ -268,7 +368,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ft->destroy(); } - ConditionalRedundancyEntry* next() + Entries* next() { if (finished()) { //all possible matches are exhausted @@ -281,15 +381,27 @@ class ConditionalRedundancyHandler::ConstraintIndex } ASS(op->isSuccess()); - return op->getSuccessResult(); + return op->getSuccessResult(); } }; static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { - op->getSuccessResult()->release(); + iterTraits(op->getSuccessResult()->iter()) + .forEach([](ConditionalRedundancyEntry* e) { e->release(); }); } } + + std::string leafToString(const CodeOp* success) const override { + std::stringstream str; + iterTraits(success->getSuccessResult()->iter()) + .forEach([&str](ConditionalRedundancyEntry* e) { + str << *e << ";; "; + }); + return str.str(); + } + + Entries* lastRenamingEntry; }; // ConditionalRedundancyHandler @@ -348,7 +460,7 @@ void ConditionalRedundancyHandler::checkEquations(Clause* cl) const } auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + (*clDataPtr)->insert(nullptr, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); }); } @@ -365,6 +477,16 @@ ConditionalRedundancyHandler::ConstraintIndex** ConditionalRedundancyHandler::ge return ptr; } +void ConditionalRedundancyHandler::transfer(Clause* from, Clause* to) +{ + ConstraintIndex* ptr = nullptr; + clauseData.pop(from, ptr); + if (!ptr) { + return; + } + ALWAYS(clauseData.insert(to, ptr)); +} + DHMap ConditionalRedundancyHandler::clauseData; // ConditionalRedundancyHandlerImpl @@ -422,12 +544,12 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp } template -void ConditionalRedundancyHandlerImpl::insertSuperposition( +bool ConditionalRedundancyHandlerImpl::insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const { if constexpr (!enabled) { - return; + return true; } struct Applicator : SubstApplicator { @@ -451,19 +573,19 @@ void ConditionalRedundancyHandlerImpl::insertSuper // TODO we cannot handle them together yet if (eqComp != Ordering::LESS) { if (!premiseRedundant || !rwTermS.containsAllVariablesOf(tgtTermS)) { - return; + return true; } ordCons.push(OrderingConstraint(rwTermS, tgtTermS)); } else if (!premiseRedundant) { TermList other = EqHelper::getOtherEqualitySide(rwLitS, rwTermS); if (otherComp != Ordering::INCOMPARABLE || !other.containsAllVariablesOf(tgtTermS)) { - return; + return true; } ordCons.push(OrderingConstraint(other, tgtTermS)); } } else { if (eqComp != Ordering::LESS || !premiseRedundant) { - return; + return true; } } @@ -471,7 +593,7 @@ void ConditionalRedundancyHandlerImpl::insertSuper auto lits = LiteralSet::getEmpty(); if constexpr (litC) { if (eqClause->numSelected()!=1) { - return; + return true; } lits = LiteralSet::getFromIterator(eqClause->iterLits().filter([eqLit,eqLHS](Literal* lit) { return lit != eqLit && eqLHS.containsAllVariablesOf(TermList(lit)); @@ -479,11 +601,11 @@ void ConditionalRedundancyHandlerImpl::insertSuper return subs->applyTo(lit,eqIsResult); })); if (eqClause->size()>lits->size()+1) { - return; + return true; } } else { if (eqClause->length()!=1) { - return; + return true; } } @@ -493,12 +615,16 @@ void ConditionalRedundancyHandlerImpl::insertSuper splits = eqClause->splits()->subtract(rwClause->splits()); } else { if (!eqClause->noSplits()) { - return; + return true; } } auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/true); - (*rwClDataPtr)->insert(subs, !eqIsResult, _splitter, std::move(ordCons), lits, splits); + if (!(*rwClDataPtr)->insert(_ord, subs, !eqIsResult, _splitter, std::move(ordCons), lits, splits)) { + env.statistics->skippedSuperposition++; + return false; + } + return true; } template @@ -617,6 +743,8 @@ bool ConditionalRedundancyHandlerImpl::isSuperposi Clause* rwCl, Literal* rwLit, TermList rwTerm, TermList tgtTerm, Clause* eqCl, TermList eqLHS, const SubstApplicator* eqApplicator, Ordering::Result& tord) const { + ASS(enabled); + // if check is turned off, we always report redundant if (!_redundancyCheck) { return true; @@ -647,4 +775,29 @@ bool ConditionalRedundancyHandlerImpl::isSuperposi // TODO perform ordering check for rest of rwCl } +template +void ConditionalRedundancyHandlerImpl::initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const +{ + if (!enabled) { + return; + } + + if (!ordC) { + return; + } + + OrderingConstraints ordCons; + ordCons.push(OrderingConstraint(tgtTerm, rwTerm)); + auto lits = LiteralSet::getEmpty(); + auto splits = SplitSet::getEmpty(); + + struct RenamingSubstitution : public ResultSubstitution { + TermList applyTo(TermList t, unsigned index) override { return t; } + void output(std::ostream&) const override {} + } subst; + + auto clDataPtr = getDataPtr(resClause, /*doAllocate=*/true); + (*clDataPtr)->insert(_ord, &subst, true, _splitter, std::move(ordCons), lits, splits); +} + } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 3e9b06a4a..804b67f49 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -68,6 +68,7 @@ struct OrderingConstraint { using OrderingConstraints = Stack; struct ConditionalRedundancyEntry { + Stack> eqCons; OrderingConstraints ordCons; const LiteralSet* lits; SplitSet* splits; @@ -92,6 +93,8 @@ struct ConditionalRedundancyEntry { } }; +using Entries = Stack; + class ConditionalRedundancyHandler { public: @@ -103,7 +106,7 @@ class ConditionalRedundancyHandler virtual bool checkSuperposition( Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const = 0; - virtual void insertSuperposition( + virtual bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const = 0; @@ -112,6 +115,8 @@ class ConditionalRedundancyHandler virtual bool handleReductiveUnaryInference(Clause* premise, RobSubstitution* subs) const = 0; + virtual void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const = 0; + void checkEquations(Clause* cl) const; protected: @@ -137,7 +142,7 @@ class ConditionalRedundancyHandlerImpl bool checkSuperposition( Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const override; - void insertSuperposition( + bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const override; @@ -152,6 +157,8 @@ class ConditionalRedundancyHandlerImpl Clause* rwCl, Literal* rwLit, TermList rwTerm, TermList tgtTerm, Clause* eqCl, TermList eqLHS, const SubstApplicator* eqApplicator, Ordering::Result& tord) const; + void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const override; + private: bool _redundancyCheck; bool _encompassing; From 500917647d1f324ed9665dee838da65a9773490a Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 21 Sep 2024 10:46:55 +0200 Subject: [PATCH 02/64] Implement merging ordering comparators -- needs lot of work, but not completely inefficient --- Indexing/TermCodeTree.hpp | 8 ++- Kernel/KBOComparator.cpp | 91 ++++++++++++++++++++++++-- Kernel/KBOComparator.hpp | 16 +++-- Kernel/Ordering.hpp | 1 + Shell/ConditionalRedundancyHandler.cpp | 5 ++ 5 files changed, 111 insertions(+), 10 deletions(-) diff --git a/Indexing/TermCodeTree.hpp b/Indexing/TermCodeTree.hpp index 62e7ccf32..d332ac88e 100644 --- a/Indexing/TermCodeTree.hpp +++ b/Indexing/TermCodeTree.hpp @@ -43,7 +43,13 @@ class TermCodeTree : public CodeTree { protected: static void onCodeOpDestroying(CodeOp* op); - + + std::string leafToString(const CodeOp* success) const override { + std::stringstream str; + str << *success->getSuccessResult(); + return str.str(); + } + public: TermCodeTree(); diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index e108bfa81..956cd7682 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -339,23 +339,82 @@ std::string KBOComparator::toString() const return str.str(); } +void KBOComparator::merge(OrderingComparator&& other) +{ + auto otherKBO = static_cast(other); + + static unsigned ts = 0; + ts++; + + Stack> todo; + todo.push(make_pair(&_root, std::move(otherKBO._root))); + while (todo.isNonEmpty()) { + auto [currB, otherB] = todo.pop(); + // if this branch is successful, or other + // branch is unsuccessful, we do nothing + if (currB->tag == BranchTag::T_GREATER + || otherB.tag == BranchTag::T_NOT_GREATER) + { + continue; + } + // if this branch is unsuccessful, or other branch + // is successful, we just replace current with other + if (currB->tag == BranchTag::T_NOT_GREATER + || otherB.tag == BranchTag::T_GREATER) + { + *currB = otherB; + continue; + } + ASS(currB->n); + ASS(otherB.n); + // if we already checked this branch, continue + if (currB->n->getTs()==ts) { + continue; + } + currB->n->setTs(ts); + // TODO no node from other should be T_COMPARISON here + if (currB->tag != otherB.tag || currB->tag != BranchTag::T_COMPARISON) { + todo.push(make_pair(&currB->n->eqBranch, otherB)); + todo.push(make_pair(&currB->n->gtBranch, otherB)); + todo.push(make_pair(&currB->n->incBranch, otherB)); + continue; + } + auto n = static_cast(currB->n.ptr()); + auto o = static_cast(otherB.n.ptr()); + if (n->lhs == o->lhs && n->rhs == o->rhs) { + todo.push(make_pair(&currB->n->eqBranch, otherB.n->eqBranch)); + todo.push(make_pair(&currB->n->gtBranch, otherB.n->gtBranch)); + todo.push(make_pair(&currB->n->incBranch, otherB.n->incBranch)); + continue; + } + todo.push(make_pair(&currB->n->eqBranch, otherB)); + todo.push(make_pair(&currB->n->gtBranch, otherB)); + todo.push(make_pair(&currB->n->incBranch, otherB)); + } +} + bool KBOComparator::check(const SubstApplicator* applicator) { + static Stack cache; + cache.reset(); const auto& kbo = static_cast(_ord); auto curr = &_root; while (curr->n) { - expand(*curr, kbo); + expand(*curr, kbo, cache); if (!curr->n) { break; } ASS(curr->n); Ordering::Result comp = Ordering::INCOMPARABLE; - if (curr->tag==BranchTag::T_COMPARISON) { + if (curr->tag == BranchTag::T_COMPARISON) { + auto node = static_cast(curr->n.ptr()); comp = kbo.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); + cache.push({ node->lhs, node->rhs, comp }); + } else { - ASS(curr->tag==BranchTag::T_WEIGHT); + ASS(curr->tag == BranchTag::T_WEIGHT); auto node = static_cast(curr->n.ptr()); auto weight = node->w; ZIArray varDiffs; @@ -393,7 +452,7 @@ bool KBOComparator::check(const SubstApplicator* applicator) return curr->tag == BranchTag::T_GREATER; } -void KBOComparator::expand(Branch& branch, const KBO& kbo) +void KBOComparator::expand(Branch& branch, const KBO& kbo, const Stack>& cache) { while (branch.tag == BranchTag::T_UNKNOWN) { @@ -416,6 +475,28 @@ void KBOComparator::expand(Branch& branch, const KBO& kbo) } // If we have a variable, we cannot preprocess further. if (node->lhs.isVar() || node->rhs.isVar()) { + // try cache + bool found = false; + for (const auto& [s,t,r] : cache) { + if (s != node->lhs || t != node->rhs) { + continue; + } + if (r == Ordering::GREATER) { + branch = node->gtBranch; + } else if (r == Ordering::EQUAL) { + branch = node->eqBranch; + } else { + ASS_NEQ(r, Ordering::LESS); + branch = node->incBranch; + } + found = true; + break; + } + if (found) { + continue; + } + // TODO we should replace the node here with a fresh one + // TODO check node's refcount? branch.tag = BranchTag::T_COMPARISON; continue; } @@ -432,7 +513,7 @@ void KBOComparator::expand(Branch& branch, const KBO& kbo) #endif auto w = state->_weightDiff; decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); - Stack> nonzeros; + Stack nonzeros; while (vit.hasNext()) { unsigned v; int cnt; diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index ed65288e9..c8d99aea6 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -39,6 +39,7 @@ class KBOComparator bool check(const SubstApplicator* applicator) override; std::string toString() const override; // bool subsumes(OrderingComparator& other) override; + void merge(OrderingComparator&& other) override; // private: void makeReady(); @@ -135,7 +136,7 @@ class KBOComparator }; struct Node { - Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER) {} + Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER), ts(0) {} auto& getBranch(Ordering::Result r) { switch (r) { @@ -150,9 +151,13 @@ class KBOComparator } } + void setTs(unsigned val) { ts = val; } + unsigned getTs() const { return ts; } + Branch eqBranch; Branch gtBranch; Branch incBranch; + unsigned ts; }; class ComparisonNode : public Node { @@ -166,8 +171,10 @@ class KBOComparator TermList rhs; }; + using VarCoeffPair = std::pair; + class WeightNode : public Node { - WeightNode(unsigned w, Stack>&& varCoeffPairs) + WeightNode(int w, Stack&& varCoeffPairs) : w(w), varCoeffPairs(varCoeffPairs) {} // only allow calling ctor from Branch @@ -175,10 +182,11 @@ class KBOComparator public: int w; - Stack> varCoeffPairs; + Stack varCoeffPairs; }; - static void expand(Branch& branch, const KBO& kbo); + using TermPairRes = std::tuple; + static void expand(Branch& branch, const KBO& kbo, const Stack& cache); bool _ready = false; // Stack _instructions; diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index ea5ca8793..aa685507b 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -46,6 +46,7 @@ struct OrderingComparator virtual std::string toString() const { return _lhs.toString()+" > "+_rhs.toString(); } virtual bool check(const SubstApplicator* applicator); virtual bool subsumes(OrderingComparator& other) { return false; } + virtual void merge(OrderingComparator&& other) {} TermList _lhs; TermList _rhs; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 6e5cb3a74..f6b0d79d1 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -134,6 +134,11 @@ class ConditionalRedundancyHandler::ConstraintIndex if (e->active && e->lits->isEmpty() && e->splits->isEmpty() && e->ordCons.size()==1) { ensureComparator(ord, e->ordCons[0]); ensureComparator(ord, ptr->ordCons[0]); + + e->ordCons[0].comp->merge(std::move(*ptr->ordCons[0].comp.get())); + return true; + /// UNREACHABLE + if (e->ordCons[0].comp->subsumes(*ptr->ordCons[0].comp)) { env.statistics->skippedInferencesDueToOrderingConstraints++; return false; From c7f16475d5dbbcb9fe89df6a12cabfeb57582a1c Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 21 Sep 2024 12:45:17 +0200 Subject: [PATCH 03/64] Try unifying matcher and removingmatcher --- Indexing/ClauseCodeTree.cpp | 11 +- Indexing/ClauseCodeTree.hpp | 4 +- Indexing/CodeTree.cpp | 632 ++++++++++--------------- Indexing/CodeTree.hpp | 240 ++++------ Indexing/TermCodeTree.cpp | 4 +- Indexing/TermCodeTree.hpp | 4 +- Shell/ConditionalRedundancyHandler.cpp | 8 +- 7 files changed, 359 insertions(+), 544 deletions(-) diff --git a/Indexing/ClauseCodeTree.cpp b/Indexing/ClauseCodeTree.cpp index 4b45346f2..6ed3bc2a6 100644 --- a/Indexing/ClauseCodeTree.cpp +++ b/Indexing/ClauseCodeTree.cpp @@ -250,7 +250,7 @@ void ClauseCodeTree::remove(Clause* cl) } iteration_restart: - if(!rlm->next()) { + if(!rlm->execute()) { if(depth==0) { ASSERTION_VIOLATION; INVALID_OPERATION("clause to be removed was not found"); @@ -291,7 +291,7 @@ void ClauseCodeTree::remove(Clause* cl) void ClauseCodeTree::RemovingLiteralMatcher::init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, ClauseCodeTree* tree_, Stack* firstsInBlocks_) { - RemovingMatcher::init(entry_, linfos_, linfoCnt_, tree_, firstsInBlocks_); + Matcher::init(tree_, entry_, linfos_, linfoCnt_, firstsInBlocks_); ALWAYS(prepareLiteral()); } @@ -331,10 +331,7 @@ void ClauseCodeTree::LiteralMatcher::init(CodeTree* tree_, CodeOp* entry_, { ASS_G(linfoCnt_,0); - Matcher::init(tree_,entry_); - - linfos=linfos_; - linfoCnt=linfoCnt_; + Matcher::init(tree_,entry_,linfos_,linfoCnt_); _eagerlyMatched=false; eagerResults.reset(); @@ -346,7 +343,7 @@ void ClauseCodeTree::LiteralMatcher::init(CodeTree* tree_, CodeOp* entry_, //(and those must be at the entry point or its alternatives) _eagerlyMatched=true; - _fresh=false; + fresh=false; CodeOp* sop=entry; while(sop) { if(sop->isSuccess()) { diff --git a/Indexing/ClauseCodeTree.hpp b/Indexing/ClauseCodeTree.hpp index c9c2de4aa..d540cfed4 100644 --- a/Indexing/ClauseCodeTree.hpp +++ b/Indexing/ClauseCodeTree.hpp @@ -58,7 +58,7 @@ class ClauseCodeTree : public CodeTree bool removeOneOfAlternatives(CodeOp* op, Clause* cl, Stack* firstsInBlocks); struct RemovingLiteralMatcher - : public RemovingMatcher + : public Matcher { void init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, ClauseCodeTree* tree_, Stack* firstsInBlocks_); @@ -72,7 +72,7 @@ class ClauseCodeTree : public CodeTree * * Here the actual execution of the code of the tree takes place */ struct LiteralMatcher - : public Matcher + : public Matcher { void init(CodeTree* tree, CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, bool seekOnlySuccess=false); bool next(); diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index 1453b377e..ef7eee0c2 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -517,7 +517,242 @@ CodeTree::CodeOp*& CodeTree::SearchStructImpl::targetOp(const T& val) return targets[left]; } -inline bool CodeTree::BaseMatcher::doCheckGroundTerm() +//////////////// Matcher //////////////////// + +template +bool CodeTree::Matcher::execute() +{ + if(fresh) { + fresh=false; + } + else { + //we backtrack from what we found in the previous run + if(!backtrack()) { + return false; + } + } + + bool shouldBacktrack=false; + for(;;) { + if(op->alternative()) { + if constexpr (removing) { + btStack.push(BTPointRemoving(tp, op->alternative(), firstsInBlocks->size())); + } else { + btStack.push(BTPoint(tp, op->alternative())); + } + } + switch(op->_instruction()) { + case SUCCESS_OR_FAIL: + if(op->isFail()) { + shouldBacktrack=true; + break; + } + if constexpr (removing) { + if (matchingClauses) { + //we can succeed only in certain depth and that will be handled separately + shouldBacktrack=true; + } + else { + //we are matching terms in a TermCodeTree + return true; + } + } else { + //yield successes only in the first round (we don't want to yield the + //same thing for each query literal) + if(curLInfo==0) { + return true; + } + shouldBacktrack=true; + } + break; + case LIT_END: + ASS(matchingClauses); + return true; + case CHECK_GROUND_TERM: + shouldBacktrack=!doCheckGroundTerm(); + break; + case CHECK_FUN: + shouldBacktrack=!doCheckFun(); + break; + case ASSIGN_VAR: + if constexpr (variant) { + shouldBacktrack=!doAssignVar(); + } else { + doAssignVar(); + } + break; + case CHECK_VAR: + shouldBacktrack=!doCheckVar(); + break; + case SEARCH_STRUCT: { + if(doSearchStruct()) { + //a new value of @b op is assigned, so restart the loop + continue; + } + shouldBacktrack=true; + break; + } + } + if(shouldBacktrack) { + if(!backtrack()) { + return false; + } + shouldBacktrack=false; + } + else { + //the SEARCH_STRUCT operation does not appear in CodeBlocks + ASS(!op->isSearchStruct()); + //In each CodeBlock there is always either operation LIT_END or FAIL. + //As we haven't encountered one yet, we may safely increase the + //operation pointer + op++; + } + } +} + +template +void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, Stack* firstsInBlocks_) +{ + tree=tree_; + entry=entry_; + + linfos=linfos_; + linfoCnt=linfoCnt_; + + if constexpr (removing) { + firstsInBlocks=firstsInBlocks_; + initFIBDepth=firstsInBlocks->size(); + } + + fresh=true; + _matched=false; + curLInfo=0; + + bindings.ensure(tree->_maxVarCnt); + btStack.reset(); + + matchingClauses=tree->_clauseCodeTree; +} + +/** + * Is called when we need to retrieve a new result. + * It does not only backtrack to the next alternative to try, + * but if there are no more alternatives, it goes back to the + * entry point and starts evaluating new literal info (if there + * is some left). + */ +template +bool CodeTree::Matcher::backtrack() +{ + if(btStack.isEmpty()) { + curLInfo++; + return prepareLiteral(); + } + auto bp=btStack.pop(); + tp=bp.tp; + op=bp.op; + if constexpr (removing) { + firstsInBlocks->truncate(bp.fibDepth); + firstsInBlocks->push(op); + } + return true; +} + +template +bool CodeTree::Matcher::prepareLiteral() +{ + if constexpr (removing) { + firstsInBlocks->truncate(initFIBDepth); + } + if(curLInfo>=linfoCnt) { + return false; + } + ft=linfos[curLInfo].ft; + tp=0; + op=entry; + return true; +} + +template +inline bool CodeTree::Matcher::doAssignVar() +{ + ASS_EQ(op->_instruction(), ASSIGN_VAR); + + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if (fte->isVar()) { + // TODO I think here we need to check the var range as well + // in the variant==true case + bindings[var]=TermList::var(fte->_number()); + tp++; + } + else { + // in the variant==true case we are looking for variants + // and they match only other variables into variables + if constexpr (variant) { + return false; + } + ASS(fte->isFun()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); + ASS(fte->_term()); + bindings[var]=TermList(fte->_term()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); + tp+=fte->_number(); + } + return true; +} + +template +inline bool CodeTree::Matcher::doCheckVar() +{ + ASS_EQ(op->_instruction(), CHECK_VAR); + + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if (fte->isVar()) { + if(bindings[var]!=TermList::var(fte->_number())) { + return false; + } + tp++; + } + else { + // in the variant==true case we are looking for variants + // and they match only other variables into variables + if constexpr (removing) { + return false; + } + ASS(fte->isFun()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); + if(bindings[var]!=TermList(fte->_term())) { + return false; + } + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); + tp+=fte->_number(); + } + return true; +} + +template +inline bool CodeTree::Matcher::doCheckFun() +{ + ASS_EQ(op->_instruction(), CHECK_FUN); + + unsigned functor=op->_arg(); + FlatTerm::Entry& fte=(*ft)[tp]; + if(!fte.isFun(functor)) { + return false; + } + fte.expand(); + tp+=FlatTerm::FUNCTION_ENTRY_COUNT; + return true; +} + +template +inline bool CodeTree::Matcher::doCheckGroundTerm() { ASS_EQ(op->_instruction(), CHECK_GROUND_TERM); @@ -540,6 +775,27 @@ inline bool CodeTree::BaseMatcher::doCheckGroundTerm() return true; } +template +inline bool CodeTree::Matcher::doSearchStruct() +{ + ASS_EQ(op->_instruction(), SEARCH_STRUCT); + + const FlatTerm::Entry* fte=&(*ft)[tp]; + CodeOp* target=op->getSearchStruct()->getTargetOp(fte); + if(!target) { + return false; + } + op=target; + // TODO look at this if something crashes + if constexpr (removing) { + firstsInBlocks->push(op); + } + return true; +} + +template struct CodeTree::Matcher; +template struct CodeTree::Matcher; + //////////////// auxiliary //////////////////// CodeTree::CodeTree() @@ -1158,186 +1414,6 @@ void CodeTree::optimizeMemoryAfterRemoval(Stack* firstsInBlocks, CodeOp } } -void CodeTree::RemovingMatcher::init(CodeOp* entry_, LitInfo* linfos_, - size_t linfoCnt_, CodeTree* tree_, Stack* firstsInBlocks_) -{ - fresh=true; - entry=entry_; - linfos=linfos_; - linfoCnt=linfoCnt_; - tree=tree_; - firstsInBlocks=firstsInBlocks_; - - initFIBDepth=firstsInBlocks->size(); - - matchingClauses=tree->_clauseCodeTree; - bindings.ensure(tree->_maxVarCnt); - btStack.reset(); - - curLInfo=0; -} - -bool CodeTree::RemovingMatcher::next() -{ - if(fresh) { - fresh=false; - } - else { - //we backtrack from what we found in the previous run - if(!backtrack()) { - return false; - } - } - - - bool shouldBacktrack=false; - for(;;) { - if(op->alternative()) { - btStack.push(BTPoint(tp, op->alternative(), firstsInBlocks->size())); - } - switch(op->_instruction()) { - case SUCCESS_OR_FAIL: - if(op->isFail()) { - shouldBacktrack=true; - break; - } - if(matchingClauses) { - //we can succeed only in certain depth and that will be handled separately - shouldBacktrack=true; - } - else { - //we are matching terms in a TermCodeTree - return true; - } - break; - case LIT_END: - ASS(matchingClauses); - return true; - case CHECK_GROUND_TERM: - shouldBacktrack=!doCheckGroundTerm(); - break; - case CHECK_FUN: - shouldBacktrack=!doCheckFun(); - break; - case ASSIGN_VAR: - shouldBacktrack=!doAssignVar(); - break; - case CHECK_VAR: - shouldBacktrack=!doCheckVar(); - break; - case SEARCH_STRUCT: - if(doSearchStruct()) { - //a new value of @b op is assigned, so restart the loop - continue; - } - else { - shouldBacktrack=true; - } - break; - } - if(shouldBacktrack) { - if(!backtrack()) { - return false; - } - // dead store, left here in case it should have been a static? - // shouldBacktrack = false; - } - else { - //the SEARCH_STRUCT operation does not appear in CodeBlocks - ASS(!op->isSearchStruct()); - //In each CodeBlock there is always either operation LIT_END or FAIL. - //As we haven't encountered one yet, we may safely increase the - //operation pointer - op++; - } - } -} - -bool CodeTree::RemovingMatcher::backtrack() -{ - if(btStack.isEmpty()) { - curLInfo++; - return prepareLiteral(); - } - BTPoint bp=btStack.pop(); - tp=bp.tp; - op=bp.op; - firstsInBlocks->truncate(bp.fibDepth); - firstsInBlocks->push(op); - return true; -} - -bool CodeTree::RemovingMatcher::prepareLiteral() -{ - firstsInBlocks->truncate(initFIBDepth); - if(curLInfo>=linfoCnt) { - return false; - } - ft=linfos[curLInfo].ft; - tp=0; - op=entry; - return true; -} - -inline bool CodeTree::RemovingMatcher::doSearchStruct() -{ - ASS_EQ(op->_instruction(), SEARCH_STRUCT); - - const FlatTerm::Entry* fte=&(*ft)[tp]; - CodeOp* target=op->getSearchStruct()->getTargetOp(fte); - if(!target) { - return false; - } - op=target; - firstsInBlocks->push(op); - return true; -} - -inline bool CodeTree::RemovingMatcher::doCheckFun() -{ - ASS_EQ(op->_instruction(), CHECK_FUN); - - unsigned functor=op->_arg(); - FlatTerm::Entry& fte=(*ft)[tp]; - if(!fte.isFun(functor)) { - return false; - } - fte.expand(); - tp+=FlatTerm::FUNCTION_ENTRY_COUNT; - return true; -} - -inline bool CodeTree::RemovingMatcher::doAssignVar() -{ - ASS_EQ(op->_instruction(), ASSIGN_VAR); - - //we are looking for variants and they match only other variables into variables - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if(fte->_tag()!=FlatTerm::VAR) { - return false; - } - bindings[var]=fte->_number(); - tp++; - return true; -} - -inline bool CodeTree::RemovingMatcher::doCheckVar() -{ - ASS_EQ(op->_instruction(), CHECK_VAR); - - //we are looking for variants and they match only other variables into variables - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if(fte->_tag()!=FlatTerm::VAR || bindings[var]!=fte->_number()) { - return false; - } - tp++; - return true; -} - - - //////////////// retrieval //////////////////// void CodeTree::incTimeStamp() @@ -1349,198 +1425,4 @@ void CodeTree::incTimeStamp() } } -void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_) -{ - tree=tree_; - entry=entry_; - - _fresh=true; - _matched=false; - curLInfo=0; - btStack.reset(); - bindings.ensure(tree->_maxVarCnt); -} - -bool CodeTree::Matcher::execute() -{ - if(_fresh) { - _fresh=false; - } - else { - //we backtrack from what we found in the previous run - if(!backtrack()) { - return false; - } - } - - - bool shouldBacktrack=false; - for(;;) { - if(op->alternative()) { - btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); - } - switch(op->_instruction()) { - case SUCCESS_OR_FAIL: - if(op->isFail()) { - shouldBacktrack=true; - break; - } - //yield successes only in the first round (we don't want to yield the - //same thing for each query literal) - if(curLInfo==0) { - return true; - } - else { - shouldBacktrack=true; - } - break; - case LIT_END: - return true; - case CHECK_GROUND_TERM: - shouldBacktrack=!doCheckGroundTerm(); - break; - case CHECK_FUN: - shouldBacktrack=!doCheckFun(); - break; - case ASSIGN_VAR: - doAssignVar(); - break; - case CHECK_VAR: - shouldBacktrack=!doCheckVar(); - break; - case SEARCH_STRUCT: - if(doSearchStruct()) { - //a new value of @b op is assigned, so restart the loop - continue; - } - else { - shouldBacktrack=true; - } - break; - } - if(shouldBacktrack) { - if(!backtrack()) { - return false; - } - shouldBacktrack=false; - } - else { - //the SEARCH_STRUCT operation does not appear in CodeBlocks - ASS(!op->isSearchStruct()); - //In each CodeBlock there is always either operation LIT_END or FAIL. - //As we haven't encountered one yet, we may safely increase the - //operation pointer - op++; - } - } -} - -/** - * Is called when we need to retrieve a new result. - * It does not only backtrack to the next alternative to try, - * but if there are no more alternatives, it goes back to the - * entry point and starts evaluating new literal info (if there - * is some left). - */ -bool CodeTree::Matcher::backtrack() -{ - if(btStack.isEmpty()) { - curLInfo++; - return prepareLiteral(); - } - BTPoint bp=btStack.pop(); - tp=bp.tp; - op=bp.op; - substIsRenaming=bp.substIsRenaming; - substVRange=bp.substVRange; - return true; -} - -bool CodeTree::Matcher::prepareLiteral() -{ - if(curLInfo>=linfoCnt) { - return false; - } - tp=0; - op=entry; - ft=linfos[curLInfo].ft; - return true; -} - -inline bool CodeTree::Matcher::doSearchStruct() -{ - ASS_EQ(op->_instruction(), SEARCH_STRUCT); - - const FlatTerm::Entry* fte=&(*ft)[tp]; - op=op->getSearchStruct()->getTargetOp(fte); - return op; -} - -inline bool CodeTree::Matcher::doCheckFun() -{ - ASS_EQ(op->_instruction(), CHECK_FUN); - - unsigned functor=op->_arg(); - FlatTerm::Entry& fte=(*ft)[tp]; - if(!fte.isFun(functor)) { - return false; - } - fte.expand(); - tp+=FlatTerm::FUNCTION_ENTRY_COUNT; - return true; -} - -inline void CodeTree::Matcher::doAssignVar() -{ - ASS_EQ(op->_instruction(), ASSIGN_VAR); - - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if(fte->_tag()==FlatTerm::VAR) { - bindings[var]=TermList(fte->_number(),false); - tp++; - if (fte->_number() > 64 || (substVRange & (1UL << fte->_number()))) { - substIsRenaming = false; - } - substVRange |= (1UL << fte->_number()); - } - else { - ASS(fte->isFun()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); - ASS(fte->_term()); - bindings[var]=TermList(fte->_term()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); - tp+=fte->_number(); - substIsRenaming = false; - } -} - -inline bool CodeTree::Matcher::doCheckVar() -{ - ASS_EQ(op->_instruction(), CHECK_VAR); - - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if(fte->_tag()==FlatTerm::VAR) { - if(bindings[var]!=TermList(fte->_number(),false)) { - return false; - } - tp++; - } - else { - ASS(fte->isFun()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); - if(bindings[var]!=TermList(fte->_term())) { - return false; - } - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); - tp+=fte->_number(); - } - return true; -} - } diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 8ba570539..1d8f1fb30 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -321,10 +321,51 @@ class CodeTree typedef Vector CodeBlock; typedef Stack CodeStack; + typedef DArray BindingArray; - struct BaseMatcher + /** + * Context for finding matches of literals + * + * Here the actual execution of the code of the tree takes place. + * + * The object is not initialized not only by constructor, but also by + * a call to the @b init function (inheritors should implement their + * own @b init function (possibly with other arguments) that will call + * this one. After use, the @b deinit function should be called (if + * present). This allows for reuse of a single object. + */ + template + struct Matcher { - public: + /** + * Backtracking point for the interpretation of the code tree. + */ + struct BTPoint + { + BTPoint(size_t tp, CodeOp* op) : tp(tp), op(op) {} + + /** Position in the flat term */ + size_t tp; + /** Pointer to the next operation */ + CodeOp* op; + }; + + struct BTPointRemoving + { + BTPointRemoving(size_t tp, CodeOp* op, size_t fibDepth) + : tp(tp), op(op), fibDepth(fibDepth) {} + + size_t tp; + CodeOp* op; + size_t fibDepth; + }; + + inline bool finished() const { return !fresh && !_matched; } + inline bool matched() const { return _matched && op->isLitEnd(); } + inline bool success() const { return _matched && op->isSuccess(); } + + bool execute(); + /** * Pointer to the current operation * @@ -332,10 +373,25 @@ class CodeTree * a call to the @b prepareLiteral function). */ CodeOp* op; - bool substIsRenaming; + + BindingArray bindings; + + bool keepRecycled() const + { return bindings.keepRecycled() + || btStack.keepRecycled() + || (firstsInBlocks && firstsInBlocks->keepRecycled()); } + protected: + void init(CodeTree* tree_, CodeOp* entry_, LitInfo* linfos_ = 0, + size_t linfoCnt_ = 0, Stack* firstsInBlocks_ = 0); + bool backtrack(); + bool prepareLiteral(); + bool doAssignVar(); + bool doCheckVar(); + bool doCheckFun(); bool doCheckGroundTerm(); + bool doSearchStruct(); /** * Position in the flat term @@ -352,7 +408,38 @@ class CodeTree */ FlatTerm* ft; - uint64_t substVRange; + /** the matcher object is initialized but no execution of code was done yet */ + bool fresh; + bool _matched; + + CodeOp* entry; + CodeTree* tree; + + /** + * Currently matched LitInfo object in case LitInfo objects + * are used (they are not in TermCodeTree::TermMatcher). + */ + size_t curLInfo; + /** + * Array of alternative LitInfo objects + * + * Must be initialized by inheritor. + */ + LitInfo* linfos; + /** + * Length of the @b linfos array + * + * Must be initialized by inheritor. + */ + size_t linfoCnt; + + /** Stack containing backtracking points */ + Stack> btStack; + + Stack* firstsInBlocks; + size_t initFIBDepth; + + bool matchingClauses; }; //////// auxiliary methods ////////// @@ -404,151 +491,6 @@ class CodeTree void optimizeMemoryAfterRemoval(Stack* firstsInBlocks, CodeOp* removedOp); - struct RemovingMatcher - : public BaseMatcher - { - public: - bool next(); - - bool keepRecycled() const - { return bindings.keepRecycled() - || btStack.keepRecycled() - || (firstsInBlocks && firstsInBlocks->keepRecycled()); } - - protected: - void init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, - CodeTree* tree_, Stack* firstsInBlocks_); - - - bool prepareLiteral(); - bool backtrack(); - bool doSearchStruct(); - bool doCheckFun(); - bool doAssignVar(); - bool doCheckVar(); - - - struct BTPoint - { - BTPoint(size_t tp, CodeOp* op, size_t fibDepth) - : tp(tp), op(op), fibDepth(fibDepth) {} - - size_t tp; - CodeOp* op; - size_t fibDepth; - }; - - /** Variable bindings */ - DArray bindings; - - Stack btStack; - Stack* firstsInBlocks; - bool fresh; - size_t curLInfo; - - CodeOp* entry; - size_t initFIBDepth; - - LitInfo* linfos; - size_t linfoCnt; - - bool matchingClauses; - CodeTree* tree; - }; - - //////// retrieval ////////// - - /** - * Backtracking point for the interpretation of the code tree. - */ - struct BTPoint - { - BTPoint() {} - BTPoint(size_t tp, CodeOp* op, bool substIsRenaming, size_t substVRange) - : tp(tp), op(op), substIsRenaming(substIsRenaming), substVRange(substVRange) {} - - /** Position in the flat term */ - size_t tp; - /** Pointer to the next operation */ - CodeOp* op; - bool substIsRenaming; - uint64_t substVRange; - }; - - typedef Stack BTStack; - typedef DArray BindingArray; - - /** - * Context for finding matches of literals - * - * Here the actual execution of the code of the tree takes place. - * - * The object is not initialized not only by constructor, but also by - * a call to the @b init function (inheritors should implement their - * own @b init function (possibly with other arguments) that will call - * this one. After use, the @b deinit function should be called (if - * present). This allows for reuse of a single object. - */ - struct Matcher - : public BaseMatcher - { - void init(CodeTree* tree, CodeOp* entry_); - - inline bool finished() const { return !_fresh && !_matched; } - inline bool matched() const { return _matched && op->isLitEnd(); } - inline bool success() const { return _matched && op->isSuccess(); } - - - - private: - bool backtrack(); - bool doSearchStruct(); - bool doCheckFun(); - void doAssignVar(); - bool doCheckVar(); - - protected: - bool execute(); - bool prepareLiteral(); - - public: - /** Variable bindings */ - BindingArray bindings; - bool keepRecycled() const { return bindings.keepRecycled(); } - - protected: - /** the matcher object is initialized but no execution of code was done yet */ - bool _fresh; - bool _matched; - - /** Stack containing backtracking points */ - BTStack btStack; - - CodeOp* entry; - - CodeTree* tree; - /** - * Array of alternative LitInfo objects - * - * Must be initialized by inheritor. - */ - LitInfo* linfos; - /** - * Length of the @b linfos array - * - * Must be initialized by inheritor. - */ - size_t linfoCnt; - - /** - * Currently matched LitInfo object in case LitInfo objects - * are used (they are not in TermCodeTree::TermMatcher). - */ - size_t curLInfo; - - }; - - void incTimeStamp(); virtual std::string leafToString(const CodeOp* success) const { return ""; } diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index dea8ad9c8..10eaa68bb 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -85,7 +85,7 @@ void TermCodeTree::remove(const Data& data) Data* dptr = nullptr; for(;;) { - if (!rtm.next()) { + if (!rtm.execute()) { ASSERTION_VIOLATION; INVALID_OPERATION("term being removed was not found"); } @@ -129,7 +129,7 @@ template void TermCodeTree::RemovingTermMatcher::init(FlatTerm* ft_, TermCodeTree* tree_, Stack* firstsInBlocks_) { - RemovingMatcher::init(tree_->getEntryPoint(), 0, 0, tree_, firstsInBlocks_); + Matcher::init(tree_, tree_->getEntryPoint(), 0, 0, firstsInBlocks_); firstsInBlocks->push(entry); diff --git a/Indexing/TermCodeTree.hpp b/Indexing/TermCodeTree.hpp index d332ac88e..6b7983742 100644 --- a/Indexing/TermCodeTree.hpp +++ b/Indexing/TermCodeTree.hpp @@ -58,7 +58,7 @@ class TermCodeTree : public CodeTree private: struct RemovingTermMatcher - : public RemovingMatcher + : public Matcher { public: void init(FlatTerm* ft_, TermCodeTree* tree_, Stack* firstsInBlocks_); @@ -67,7 +67,7 @@ class TermCodeTree : public CodeTree public: struct TermMatcher - : public Matcher + : public Matcher { TermMatcher(); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index f6b0d79d1..a96285854 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -216,10 +216,6 @@ class ConditionalRedundancyHandler::ConstraintIndex Entries* es; while ((es = matcher.next())) { - if (matcher.substIsRenaming) { - lastRenamingEntry = es; - } - // TODO indent for (const auto& e : *es) { @@ -332,7 +328,7 @@ class ConditionalRedundancyHandler::ConstraintIndex } struct SubstMatcher - : public Matcher + : public Matcher { void init(CodeTree* tree, const TermStack& ts) { @@ -342,8 +338,6 @@ class ConditionalRedundancyHandler::ConstraintIndex op=entry; tp=0; - substIsRenaming=true; - substVRange=0; } void reset() From 5ead1011f1758d386214e88425eb826c4edca205 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 21 Sep 2024 17:32:10 +0200 Subject: [PATCH 04/64] Revert "Try unifying matcher and removingmatcher" This reverts commit c7f16475d5dbbcb9fe89df6a12cabfeb57582a1c. --- Indexing/ClauseCodeTree.cpp | 11 +- Indexing/ClauseCodeTree.hpp | 4 +- Indexing/CodeTree.cpp | 632 +++++++++++++++---------- Indexing/CodeTree.hpp | 240 ++++++---- Indexing/TermCodeTree.cpp | 4 +- Indexing/TermCodeTree.hpp | 4 +- Shell/ConditionalRedundancyHandler.cpp | 8 +- 7 files changed, 544 insertions(+), 359 deletions(-) diff --git a/Indexing/ClauseCodeTree.cpp b/Indexing/ClauseCodeTree.cpp index 6ed3bc2a6..4b45346f2 100644 --- a/Indexing/ClauseCodeTree.cpp +++ b/Indexing/ClauseCodeTree.cpp @@ -250,7 +250,7 @@ void ClauseCodeTree::remove(Clause* cl) } iteration_restart: - if(!rlm->execute()) { + if(!rlm->next()) { if(depth==0) { ASSERTION_VIOLATION; INVALID_OPERATION("clause to be removed was not found"); @@ -291,7 +291,7 @@ void ClauseCodeTree::remove(Clause* cl) void ClauseCodeTree::RemovingLiteralMatcher::init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, ClauseCodeTree* tree_, Stack* firstsInBlocks_) { - Matcher::init(tree_, entry_, linfos_, linfoCnt_, firstsInBlocks_); + RemovingMatcher::init(entry_, linfos_, linfoCnt_, tree_, firstsInBlocks_); ALWAYS(prepareLiteral()); } @@ -331,7 +331,10 @@ void ClauseCodeTree::LiteralMatcher::init(CodeTree* tree_, CodeOp* entry_, { ASS_G(linfoCnt_,0); - Matcher::init(tree_,entry_,linfos_,linfoCnt_); + Matcher::init(tree_,entry_); + + linfos=linfos_; + linfoCnt=linfoCnt_; _eagerlyMatched=false; eagerResults.reset(); @@ -343,7 +346,7 @@ void ClauseCodeTree::LiteralMatcher::init(CodeTree* tree_, CodeOp* entry_, //(and those must be at the entry point or its alternatives) _eagerlyMatched=true; - fresh=false; + _fresh=false; CodeOp* sop=entry; while(sop) { if(sop->isSuccess()) { diff --git a/Indexing/ClauseCodeTree.hpp b/Indexing/ClauseCodeTree.hpp index d540cfed4..c9c2de4aa 100644 --- a/Indexing/ClauseCodeTree.hpp +++ b/Indexing/ClauseCodeTree.hpp @@ -58,7 +58,7 @@ class ClauseCodeTree : public CodeTree bool removeOneOfAlternatives(CodeOp* op, Clause* cl, Stack* firstsInBlocks); struct RemovingLiteralMatcher - : public Matcher + : public RemovingMatcher { void init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, ClauseCodeTree* tree_, Stack* firstsInBlocks_); @@ -72,7 +72,7 @@ class ClauseCodeTree : public CodeTree * * Here the actual execution of the code of the tree takes place */ struct LiteralMatcher - : public Matcher + : public Matcher { void init(CodeTree* tree, CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, bool seekOnlySuccess=false); bool next(); diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index ef7eee0c2..1453b377e 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -517,242 +517,7 @@ CodeTree::CodeOp*& CodeTree::SearchStructImpl::targetOp(const T& val) return targets[left]; } -//////////////// Matcher //////////////////// - -template -bool CodeTree::Matcher::execute() -{ - if(fresh) { - fresh=false; - } - else { - //we backtrack from what we found in the previous run - if(!backtrack()) { - return false; - } - } - - bool shouldBacktrack=false; - for(;;) { - if(op->alternative()) { - if constexpr (removing) { - btStack.push(BTPointRemoving(tp, op->alternative(), firstsInBlocks->size())); - } else { - btStack.push(BTPoint(tp, op->alternative())); - } - } - switch(op->_instruction()) { - case SUCCESS_OR_FAIL: - if(op->isFail()) { - shouldBacktrack=true; - break; - } - if constexpr (removing) { - if (matchingClauses) { - //we can succeed only in certain depth and that will be handled separately - shouldBacktrack=true; - } - else { - //we are matching terms in a TermCodeTree - return true; - } - } else { - //yield successes only in the first round (we don't want to yield the - //same thing for each query literal) - if(curLInfo==0) { - return true; - } - shouldBacktrack=true; - } - break; - case LIT_END: - ASS(matchingClauses); - return true; - case CHECK_GROUND_TERM: - shouldBacktrack=!doCheckGroundTerm(); - break; - case CHECK_FUN: - shouldBacktrack=!doCheckFun(); - break; - case ASSIGN_VAR: - if constexpr (variant) { - shouldBacktrack=!doAssignVar(); - } else { - doAssignVar(); - } - break; - case CHECK_VAR: - shouldBacktrack=!doCheckVar(); - break; - case SEARCH_STRUCT: { - if(doSearchStruct()) { - //a new value of @b op is assigned, so restart the loop - continue; - } - shouldBacktrack=true; - break; - } - } - if(shouldBacktrack) { - if(!backtrack()) { - return false; - } - shouldBacktrack=false; - } - else { - //the SEARCH_STRUCT operation does not appear in CodeBlocks - ASS(!op->isSearchStruct()); - //In each CodeBlock there is always either operation LIT_END or FAIL. - //As we haven't encountered one yet, we may safely increase the - //operation pointer - op++; - } - } -} - -template -void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, Stack* firstsInBlocks_) -{ - tree=tree_; - entry=entry_; - - linfos=linfos_; - linfoCnt=linfoCnt_; - - if constexpr (removing) { - firstsInBlocks=firstsInBlocks_; - initFIBDepth=firstsInBlocks->size(); - } - - fresh=true; - _matched=false; - curLInfo=0; - - bindings.ensure(tree->_maxVarCnt); - btStack.reset(); - - matchingClauses=tree->_clauseCodeTree; -} - -/** - * Is called when we need to retrieve a new result. - * It does not only backtrack to the next alternative to try, - * but if there are no more alternatives, it goes back to the - * entry point and starts evaluating new literal info (if there - * is some left). - */ -template -bool CodeTree::Matcher::backtrack() -{ - if(btStack.isEmpty()) { - curLInfo++; - return prepareLiteral(); - } - auto bp=btStack.pop(); - tp=bp.tp; - op=bp.op; - if constexpr (removing) { - firstsInBlocks->truncate(bp.fibDepth); - firstsInBlocks->push(op); - } - return true; -} - -template -bool CodeTree::Matcher::prepareLiteral() -{ - if constexpr (removing) { - firstsInBlocks->truncate(initFIBDepth); - } - if(curLInfo>=linfoCnt) { - return false; - } - ft=linfos[curLInfo].ft; - tp=0; - op=entry; - return true; -} - -template -inline bool CodeTree::Matcher::doAssignVar() -{ - ASS_EQ(op->_instruction(), ASSIGN_VAR); - - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if (fte->isVar()) { - // TODO I think here we need to check the var range as well - // in the variant==true case - bindings[var]=TermList::var(fte->_number()); - tp++; - } - else { - // in the variant==true case we are looking for variants - // and they match only other variables into variables - if constexpr (variant) { - return false; - } - ASS(fte->isFun()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); - ASS(fte->_term()); - bindings[var]=TermList(fte->_term()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); - tp+=fte->_number(); - } - return true; -} - -template -inline bool CodeTree::Matcher::doCheckVar() -{ - ASS_EQ(op->_instruction(), CHECK_VAR); - - unsigned var=op->_arg(); - const FlatTerm::Entry* fte=&(*ft)[tp]; - if (fte->isVar()) { - if(bindings[var]!=TermList::var(fte->_number())) { - return false; - } - tp++; - } - else { - // in the variant==true case we are looking for variants - // and they match only other variables into variables - if constexpr (removing) { - return false; - } - ASS(fte->isFun()); - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); - if(bindings[var]!=TermList(fte->_term())) { - return false; - } - fte++; - ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); - tp+=fte->_number(); - } - return true; -} - -template -inline bool CodeTree::Matcher::doCheckFun() -{ - ASS_EQ(op->_instruction(), CHECK_FUN); - - unsigned functor=op->_arg(); - FlatTerm::Entry& fte=(*ft)[tp]; - if(!fte.isFun(functor)) { - return false; - } - fte.expand(); - tp+=FlatTerm::FUNCTION_ENTRY_COUNT; - return true; -} - -template -inline bool CodeTree::Matcher::doCheckGroundTerm() +inline bool CodeTree::BaseMatcher::doCheckGroundTerm() { ASS_EQ(op->_instruction(), CHECK_GROUND_TERM); @@ -775,27 +540,6 @@ inline bool CodeTree::Matcher::doCheckGroundTerm() return true; } -template -inline bool CodeTree::Matcher::doSearchStruct() -{ - ASS_EQ(op->_instruction(), SEARCH_STRUCT); - - const FlatTerm::Entry* fte=&(*ft)[tp]; - CodeOp* target=op->getSearchStruct()->getTargetOp(fte); - if(!target) { - return false; - } - op=target; - // TODO look at this if something crashes - if constexpr (removing) { - firstsInBlocks->push(op); - } - return true; -} - -template struct CodeTree::Matcher; -template struct CodeTree::Matcher; - //////////////// auxiliary //////////////////// CodeTree::CodeTree() @@ -1414,6 +1158,186 @@ void CodeTree::optimizeMemoryAfterRemoval(Stack* firstsInBlocks, CodeOp } } +void CodeTree::RemovingMatcher::init(CodeOp* entry_, LitInfo* linfos_, + size_t linfoCnt_, CodeTree* tree_, Stack* firstsInBlocks_) +{ + fresh=true; + entry=entry_; + linfos=linfos_; + linfoCnt=linfoCnt_; + tree=tree_; + firstsInBlocks=firstsInBlocks_; + + initFIBDepth=firstsInBlocks->size(); + + matchingClauses=tree->_clauseCodeTree; + bindings.ensure(tree->_maxVarCnt); + btStack.reset(); + + curLInfo=0; +} + +bool CodeTree::RemovingMatcher::next() +{ + if(fresh) { + fresh=false; + } + else { + //we backtrack from what we found in the previous run + if(!backtrack()) { + return false; + } + } + + + bool shouldBacktrack=false; + for(;;) { + if(op->alternative()) { + btStack.push(BTPoint(tp, op->alternative(), firstsInBlocks->size())); + } + switch(op->_instruction()) { + case SUCCESS_OR_FAIL: + if(op->isFail()) { + shouldBacktrack=true; + break; + } + if(matchingClauses) { + //we can succeed only in certain depth and that will be handled separately + shouldBacktrack=true; + } + else { + //we are matching terms in a TermCodeTree + return true; + } + break; + case LIT_END: + ASS(matchingClauses); + return true; + case CHECK_GROUND_TERM: + shouldBacktrack=!doCheckGroundTerm(); + break; + case CHECK_FUN: + shouldBacktrack=!doCheckFun(); + break; + case ASSIGN_VAR: + shouldBacktrack=!doAssignVar(); + break; + case CHECK_VAR: + shouldBacktrack=!doCheckVar(); + break; + case SEARCH_STRUCT: + if(doSearchStruct()) { + //a new value of @b op is assigned, so restart the loop + continue; + } + else { + shouldBacktrack=true; + } + break; + } + if(shouldBacktrack) { + if(!backtrack()) { + return false; + } + // dead store, left here in case it should have been a static? + // shouldBacktrack = false; + } + else { + //the SEARCH_STRUCT operation does not appear in CodeBlocks + ASS(!op->isSearchStruct()); + //In each CodeBlock there is always either operation LIT_END or FAIL. + //As we haven't encountered one yet, we may safely increase the + //operation pointer + op++; + } + } +} + +bool CodeTree::RemovingMatcher::backtrack() +{ + if(btStack.isEmpty()) { + curLInfo++; + return prepareLiteral(); + } + BTPoint bp=btStack.pop(); + tp=bp.tp; + op=bp.op; + firstsInBlocks->truncate(bp.fibDepth); + firstsInBlocks->push(op); + return true; +} + +bool CodeTree::RemovingMatcher::prepareLiteral() +{ + firstsInBlocks->truncate(initFIBDepth); + if(curLInfo>=linfoCnt) { + return false; + } + ft=linfos[curLInfo].ft; + tp=0; + op=entry; + return true; +} + +inline bool CodeTree::RemovingMatcher::doSearchStruct() +{ + ASS_EQ(op->_instruction(), SEARCH_STRUCT); + + const FlatTerm::Entry* fte=&(*ft)[tp]; + CodeOp* target=op->getSearchStruct()->getTargetOp(fte); + if(!target) { + return false; + } + op=target; + firstsInBlocks->push(op); + return true; +} + +inline bool CodeTree::RemovingMatcher::doCheckFun() +{ + ASS_EQ(op->_instruction(), CHECK_FUN); + + unsigned functor=op->_arg(); + FlatTerm::Entry& fte=(*ft)[tp]; + if(!fte.isFun(functor)) { + return false; + } + fte.expand(); + tp+=FlatTerm::FUNCTION_ENTRY_COUNT; + return true; +} + +inline bool CodeTree::RemovingMatcher::doAssignVar() +{ + ASS_EQ(op->_instruction(), ASSIGN_VAR); + + //we are looking for variants and they match only other variables into variables + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if(fte->_tag()!=FlatTerm::VAR) { + return false; + } + bindings[var]=fte->_number(); + tp++; + return true; +} + +inline bool CodeTree::RemovingMatcher::doCheckVar() +{ + ASS_EQ(op->_instruction(), CHECK_VAR); + + //we are looking for variants and they match only other variables into variables + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if(fte->_tag()!=FlatTerm::VAR || bindings[var]!=fte->_number()) { + return false; + } + tp++; + return true; +} + + + //////////////// retrieval //////////////////// void CodeTree::incTimeStamp() @@ -1425,4 +1349,198 @@ void CodeTree::incTimeStamp() } } +void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_) +{ + tree=tree_; + entry=entry_; + + _fresh=true; + _matched=false; + curLInfo=0; + btStack.reset(); + bindings.ensure(tree->_maxVarCnt); +} + +bool CodeTree::Matcher::execute() +{ + if(_fresh) { + _fresh=false; + } + else { + //we backtrack from what we found in the previous run + if(!backtrack()) { + return false; + } + } + + + bool shouldBacktrack=false; + for(;;) { + if(op->alternative()) { + btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); + } + switch(op->_instruction()) { + case SUCCESS_OR_FAIL: + if(op->isFail()) { + shouldBacktrack=true; + break; + } + //yield successes only in the first round (we don't want to yield the + //same thing for each query literal) + if(curLInfo==0) { + return true; + } + else { + shouldBacktrack=true; + } + break; + case LIT_END: + return true; + case CHECK_GROUND_TERM: + shouldBacktrack=!doCheckGroundTerm(); + break; + case CHECK_FUN: + shouldBacktrack=!doCheckFun(); + break; + case ASSIGN_VAR: + doAssignVar(); + break; + case CHECK_VAR: + shouldBacktrack=!doCheckVar(); + break; + case SEARCH_STRUCT: + if(doSearchStruct()) { + //a new value of @b op is assigned, so restart the loop + continue; + } + else { + shouldBacktrack=true; + } + break; + } + if(shouldBacktrack) { + if(!backtrack()) { + return false; + } + shouldBacktrack=false; + } + else { + //the SEARCH_STRUCT operation does not appear in CodeBlocks + ASS(!op->isSearchStruct()); + //In each CodeBlock there is always either operation LIT_END or FAIL. + //As we haven't encountered one yet, we may safely increase the + //operation pointer + op++; + } + } +} + +/** + * Is called when we need to retrieve a new result. + * It does not only backtrack to the next alternative to try, + * but if there are no more alternatives, it goes back to the + * entry point and starts evaluating new literal info (if there + * is some left). + */ +bool CodeTree::Matcher::backtrack() +{ + if(btStack.isEmpty()) { + curLInfo++; + return prepareLiteral(); + } + BTPoint bp=btStack.pop(); + tp=bp.tp; + op=bp.op; + substIsRenaming=bp.substIsRenaming; + substVRange=bp.substVRange; + return true; +} + +bool CodeTree::Matcher::prepareLiteral() +{ + if(curLInfo>=linfoCnt) { + return false; + } + tp=0; + op=entry; + ft=linfos[curLInfo].ft; + return true; +} + +inline bool CodeTree::Matcher::doSearchStruct() +{ + ASS_EQ(op->_instruction(), SEARCH_STRUCT); + + const FlatTerm::Entry* fte=&(*ft)[tp]; + op=op->getSearchStruct()->getTargetOp(fte); + return op; +} + +inline bool CodeTree::Matcher::doCheckFun() +{ + ASS_EQ(op->_instruction(), CHECK_FUN); + + unsigned functor=op->_arg(); + FlatTerm::Entry& fte=(*ft)[tp]; + if(!fte.isFun(functor)) { + return false; + } + fte.expand(); + tp+=FlatTerm::FUNCTION_ENTRY_COUNT; + return true; +} + +inline void CodeTree::Matcher::doAssignVar() +{ + ASS_EQ(op->_instruction(), ASSIGN_VAR); + + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if(fte->_tag()==FlatTerm::VAR) { + bindings[var]=TermList(fte->_number(),false); + tp++; + if (fte->_number() > 64 || (substVRange & (1UL << fte->_number()))) { + substIsRenaming = false; + } + substVRange |= (1UL << fte->_number()); + } + else { + ASS(fte->isFun()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); + ASS(fte->_term()); + bindings[var]=TermList(fte->_term()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); + tp+=fte->_number(); + substIsRenaming = false; + } +} + +inline bool CodeTree::Matcher::doCheckVar() +{ + ASS_EQ(op->_instruction(), CHECK_VAR); + + unsigned var=op->_arg(); + const FlatTerm::Entry* fte=&(*ft)[tp]; + if(fte->_tag()==FlatTerm::VAR) { + if(bindings[var]!=TermList(fte->_number(),false)) { + return false; + } + tp++; + } + else { + ASS(fte->isFun()); + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_TERM_PTR); + if(bindings[var]!=TermList(fte->_term())) { + return false; + } + fte++; + ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); + tp+=fte->_number(); + } + return true; +} + } diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 1d8f1fb30..8ba570539 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -321,51 +321,10 @@ class CodeTree typedef Vector CodeBlock; typedef Stack CodeStack; - typedef DArray BindingArray; - /** - * Context for finding matches of literals - * - * Here the actual execution of the code of the tree takes place. - * - * The object is not initialized not only by constructor, but also by - * a call to the @b init function (inheritors should implement their - * own @b init function (possibly with other arguments) that will call - * this one. After use, the @b deinit function should be called (if - * present). This allows for reuse of a single object. - */ - template - struct Matcher + struct BaseMatcher { - /** - * Backtracking point for the interpretation of the code tree. - */ - struct BTPoint - { - BTPoint(size_t tp, CodeOp* op) : tp(tp), op(op) {} - - /** Position in the flat term */ - size_t tp; - /** Pointer to the next operation */ - CodeOp* op; - }; - - struct BTPointRemoving - { - BTPointRemoving(size_t tp, CodeOp* op, size_t fibDepth) - : tp(tp), op(op), fibDepth(fibDepth) {} - - size_t tp; - CodeOp* op; - size_t fibDepth; - }; - - inline bool finished() const { return !fresh && !_matched; } - inline bool matched() const { return _matched && op->isLitEnd(); } - inline bool success() const { return _matched && op->isSuccess(); } - - bool execute(); - + public: /** * Pointer to the current operation * @@ -373,25 +332,10 @@ class CodeTree * a call to the @b prepareLiteral function). */ CodeOp* op; - - BindingArray bindings; - - bool keepRecycled() const - { return bindings.keepRecycled() - || btStack.keepRecycled() - || (firstsInBlocks && firstsInBlocks->keepRecycled()); } - + bool substIsRenaming; protected: - void init(CodeTree* tree_, CodeOp* entry_, LitInfo* linfos_ = 0, - size_t linfoCnt_ = 0, Stack* firstsInBlocks_ = 0); - bool backtrack(); - bool prepareLiteral(); - bool doAssignVar(); - bool doCheckVar(); - bool doCheckFun(); bool doCheckGroundTerm(); - bool doSearchStruct(); /** * Position in the flat term @@ -408,38 +352,7 @@ class CodeTree */ FlatTerm* ft; - /** the matcher object is initialized but no execution of code was done yet */ - bool fresh; - bool _matched; - - CodeOp* entry; - CodeTree* tree; - - /** - * Currently matched LitInfo object in case LitInfo objects - * are used (they are not in TermCodeTree::TermMatcher). - */ - size_t curLInfo; - /** - * Array of alternative LitInfo objects - * - * Must be initialized by inheritor. - */ - LitInfo* linfos; - /** - * Length of the @b linfos array - * - * Must be initialized by inheritor. - */ - size_t linfoCnt; - - /** Stack containing backtracking points */ - Stack> btStack; - - Stack* firstsInBlocks; - size_t initFIBDepth; - - bool matchingClauses; + uint64_t substVRange; }; //////// auxiliary methods ////////// @@ -491,6 +404,151 @@ class CodeTree void optimizeMemoryAfterRemoval(Stack* firstsInBlocks, CodeOp* removedOp); + struct RemovingMatcher + : public BaseMatcher + { + public: + bool next(); + + bool keepRecycled() const + { return bindings.keepRecycled() + || btStack.keepRecycled() + || (firstsInBlocks && firstsInBlocks->keepRecycled()); } + + protected: + void init(CodeOp* entry_, LitInfo* linfos_, size_t linfoCnt_, + CodeTree* tree_, Stack* firstsInBlocks_); + + + bool prepareLiteral(); + bool backtrack(); + bool doSearchStruct(); + bool doCheckFun(); + bool doAssignVar(); + bool doCheckVar(); + + + struct BTPoint + { + BTPoint(size_t tp, CodeOp* op, size_t fibDepth) + : tp(tp), op(op), fibDepth(fibDepth) {} + + size_t tp; + CodeOp* op; + size_t fibDepth; + }; + + /** Variable bindings */ + DArray bindings; + + Stack btStack; + Stack* firstsInBlocks; + bool fresh; + size_t curLInfo; + + CodeOp* entry; + size_t initFIBDepth; + + LitInfo* linfos; + size_t linfoCnt; + + bool matchingClauses; + CodeTree* tree; + }; + + //////// retrieval ////////// + + /** + * Backtracking point for the interpretation of the code tree. + */ + struct BTPoint + { + BTPoint() {} + BTPoint(size_t tp, CodeOp* op, bool substIsRenaming, size_t substVRange) + : tp(tp), op(op), substIsRenaming(substIsRenaming), substVRange(substVRange) {} + + /** Position in the flat term */ + size_t tp; + /** Pointer to the next operation */ + CodeOp* op; + bool substIsRenaming; + uint64_t substVRange; + }; + + typedef Stack BTStack; + typedef DArray BindingArray; + + /** + * Context for finding matches of literals + * + * Here the actual execution of the code of the tree takes place. + * + * The object is not initialized not only by constructor, but also by + * a call to the @b init function (inheritors should implement their + * own @b init function (possibly with other arguments) that will call + * this one. After use, the @b deinit function should be called (if + * present). This allows for reuse of a single object. + */ + struct Matcher + : public BaseMatcher + { + void init(CodeTree* tree, CodeOp* entry_); + + inline bool finished() const { return !_fresh && !_matched; } + inline bool matched() const { return _matched && op->isLitEnd(); } + inline bool success() const { return _matched && op->isSuccess(); } + + + + private: + bool backtrack(); + bool doSearchStruct(); + bool doCheckFun(); + void doAssignVar(); + bool doCheckVar(); + + protected: + bool execute(); + bool prepareLiteral(); + + public: + /** Variable bindings */ + BindingArray bindings; + bool keepRecycled() const { return bindings.keepRecycled(); } + + protected: + /** the matcher object is initialized but no execution of code was done yet */ + bool _fresh; + bool _matched; + + /** Stack containing backtracking points */ + BTStack btStack; + + CodeOp* entry; + + CodeTree* tree; + /** + * Array of alternative LitInfo objects + * + * Must be initialized by inheritor. + */ + LitInfo* linfos; + /** + * Length of the @b linfos array + * + * Must be initialized by inheritor. + */ + size_t linfoCnt; + + /** + * Currently matched LitInfo object in case LitInfo objects + * are used (they are not in TermCodeTree::TermMatcher). + */ + size_t curLInfo; + + }; + + void incTimeStamp(); virtual std::string leafToString(const CodeOp* success) const { return ""; } diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index 10eaa68bb..dea8ad9c8 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -85,7 +85,7 @@ void TermCodeTree::remove(const Data& data) Data* dptr = nullptr; for(;;) { - if (!rtm.execute()) { + if (!rtm.next()) { ASSERTION_VIOLATION; INVALID_OPERATION("term being removed was not found"); } @@ -129,7 +129,7 @@ template void TermCodeTree::RemovingTermMatcher::init(FlatTerm* ft_, TermCodeTree* tree_, Stack* firstsInBlocks_) { - Matcher::init(tree_, tree_->getEntryPoint(), 0, 0, firstsInBlocks_); + RemovingMatcher::init(tree_->getEntryPoint(), 0, 0, tree_, firstsInBlocks_); firstsInBlocks->push(entry); diff --git a/Indexing/TermCodeTree.hpp b/Indexing/TermCodeTree.hpp index 6b7983742..d332ac88e 100644 --- a/Indexing/TermCodeTree.hpp +++ b/Indexing/TermCodeTree.hpp @@ -58,7 +58,7 @@ class TermCodeTree : public CodeTree private: struct RemovingTermMatcher - : public Matcher + : public RemovingMatcher { public: void init(FlatTerm* ft_, TermCodeTree* tree_, Stack* firstsInBlocks_); @@ -67,7 +67,7 @@ class TermCodeTree : public CodeTree public: struct TermMatcher - : public Matcher + : public Matcher { TermMatcher(); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index a96285854..f6b0d79d1 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -216,6 +216,10 @@ class ConditionalRedundancyHandler::ConstraintIndex Entries* es; while ((es = matcher.next())) { + if (matcher.substIsRenaming) { + lastRenamingEntry = es; + } + // TODO indent for (const auto& e : *es) { @@ -328,7 +332,7 @@ class ConditionalRedundancyHandler::ConstraintIndex } struct SubstMatcher - : public Matcher + : public Matcher { void init(CodeTree* tree, const TermStack& ts) { @@ -338,6 +342,8 @@ class ConditionalRedundancyHandler::ConstraintIndex op=entry; tp=0; + substIsRenaming=true; + substVRange=0; } void reset() From 1684599355c85effe118d14d6035adc31c8d64fc Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 21 Sep 2024 20:08:15 +0200 Subject: [PATCH 05/64] Unify the OrderingComparator implementations to some degree --- CMakeLists.txt | 2 + Indexing/Index.hpp | 11 +- Inferences/ForwardDemodulation.cpp | 4 +- Kernel/KBO.cpp | 2 +- Kernel/KBOComparator.cpp | 520 +------------------------ Kernel/KBOComparator.hpp | 159 +------- Kernel/LPO.cpp | 2 +- Kernel/LPOComparator.cpp | 105 ++--- Kernel/LPOComparator.hpp | 59 +-- Kernel/Ordering.cpp | 13 +- Kernel/Ordering.hpp | 23 +- Kernel/OrderingComparator.cpp | 141 +++++++ Kernel/OrderingComparator.hpp | 116 ++++++ Shell/ConditionalRedundancyHandler.cpp | 17 +- 14 files changed, 330 insertions(+), 844 deletions(-) create mode 100644 Kernel/OrderingComparator.cpp create mode 100644 Kernel/OrderingComparator.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 66d5173c5..4008af0e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/MLMatcherSD.cpp Kernel/MLVariant.cpp Kernel/Ordering.cpp + Kernel/OrderingComparator.cpp Kernel/Ordering_Equality.cpp Kernel/Problem.cpp Kernel/Renaming.cpp @@ -272,6 +273,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/MLMatcher.hpp Kernel/MLVariant.hpp Kernel/Ordering.hpp + Kernel/OrderingComparator.hpp Kernel/Problem.hpp Kernel/RCClauseStack.hpp Kernel/Renaming.hpp diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index c28b0ea0e..bc324ad78 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -18,15 +18,18 @@ #include "Forwards.hpp" #include "Debug/Output.hpp" +#include "Lib/Allocator.hpp" #include "Lib/Event.hpp" -#include "Kernel/Clause.hpp" -#include "Kernel/Term.hpp" #include "Lib/Exception.hpp" #include "Lib/VirtualIterator.hpp" + +#include "Kernel/Clause.hpp" +#include "Kernel/OrderingComparator.hpp" +#include "Kernel/Term.hpp" +#include "Kernel/UnificationWithAbstraction.hpp" + #include "Saturation/ClauseContainer.hpp" #include "ResultSubstitution.hpp" -#include "Kernel/UnificationWithAbstraction.hpp" -#include "Lib/Allocator.hpp" /** * Indices are parametrized by a LeafData, i.e. the bit of data you want to store in the index. diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 6580860fe..9669ebf0e 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -178,14 +178,14 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { if (ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; - std::cout << qr.data->comparator->toString() << std::endl; + std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("greater"); } continue; } if (!ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; - std::cout << qr.data->comparator->toString() << std::endl; + std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("not greater"); } } else { diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index 3bf5c8ff5..6396fc580 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -881,7 +881,7 @@ bool KBO::isGreater(AppliedTerm lhs, AppliedTerm rhs) const OrderingComparatorUP KBO::createComparator(TermList lhs, TermList rhs) const { - return make_unique(lhs, rhs, *this); + return make_unique(*this, lhs, rhs); } int KBO::symbolWeight(const Term* t) const diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 956cd7682..8e4ba63b0 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -8,6 +8,7 @@ * and in the source directory */ +#include "KBO.hpp" #include "SubstHelper.hpp" #include "Term.hpp" #include "TermIterators.hpp" @@ -20,379 +21,6 @@ using namespace std; using namespace Lib; using namespace Shell; -KBOComparator::KBOComparator(TermList lhs, TermList rhs, const KBO& kbo) - : OrderingComparator(lhs, rhs, kbo), _root(lhs, rhs) -{ -} - -// void KBOComparator::makeReady() -// { -// ASS(!_ready); - -// const auto& kbo = static_cast(_ord); - -// // stack of subcomparisons in lexicographic order (w.r.t. tl1 and tl2) -// Stack> todo; -// todo.push(make_pair(_lhs,_rhs)); - -// while (todo.isNonEmpty()) { -// auto kv = todo.pop(); -// auto lhs = kv.first; -// auto rhs = kv.second; - -// auto comp = kbo.compare(lhs,rhs); -// switch (comp) { -// case Ordering::LESS: { -// // at this point the execution will fail, no further instructions -// return; -// } -// case Ordering::GREATER: { -// // at this point the execution will succeed, push SUCCESS -// _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); -// return; -// } -// default: -// break; -// } -// // this essentially means the EQUAL case -// if (comp != Ordering::INCOMPARABLE) { -// continue; -// } -// // if either term is a variable, we cannot preprocess them further -// if (lhs.isVar() || rhs.isVar()) { -// if (lhs.isVar() && rhs.isVar()) { -// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VV,lhs.var(),rhs.var())); -// } else if (lhs.isVar()) { -// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_VT,lhs.var())); -// _instructions.push(Instruction::term(rhs.term())); -// } else if (rhs.isVar()) { -// // note that lhs is the second argument in this case -// _instructions.push(Instruction::uintUint(InstructionTag::COMPARE_TV,rhs.var())); -// _instructions.push(Instruction::term(lhs.term())); -// } - -// // Prepare further cases if this is equal. -// // Note that lhs and rhs are incomparable, -// // so we don't need an occurs check. -// Substitution subst; -// if (lhs.isVar()) { -// subst.bind(lhs.var(),rhs); -// } else { -// subst.bind(rhs.var(),lhs); -// } -// for (auto& kv : todo) { -// kv.first = SubstHelper::apply(kv.first,subst); -// kv.second = SubstHelper::apply(kv.second,subst); -// } -// continue; -// } - -// // if both are proper terms, we calculate -// // weight and variable balances first - -// // we only care about the non-zero weights and counts -// bool varInbalance = false; -// auto state = kbo._state; -// #if VDEBUG -// // we make sure kbo._state is not used while we're using it -// kbo._state = nullptr; -// #endif -// auto w = state->_weightDiff; -// decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); -// Stack> nonzeros; -// while (vit.hasNext()) { -// unsigned v; -// int cnt; -// vit.next(v,cnt); -// if (cnt!=0) { -// nonzeros.push(make_pair(v,cnt)); -// w-=cnt; // we have to remove the variable weights from w -// } -// if (cnt<0) { -// varInbalance = true; -// } -// } -// #if VDEBUG -// kbo._state = state; -// state = nullptr; -// #endif - -// // if the condition below does not hold, the weight/var balances are satisfied -// if (w < 0 || varInbalance) { -// // reinterpret weight here to unsigned because the compiler might not do it -// unsigned wu = reinterpret_cast(w); - -// _instructions.push(Instruction::uintUint(InstructionTag::WEIGHT, (unsigned)nonzeros.size(), wu)); -// // sort the [var,count] pairs by count descending so that -// // we can exit early during execution if needed -// sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { -// return e1.second>e2.second; -// }); -// for (const auto& [v,cnt] : nonzeros) { -// // see same with weight above -// unsigned cntu = reinterpret_cast(cnt); - -// _instructions.push(Instruction::uintUint(InstructionTag::DATA, v, cntu)); -// } -// } - -// auto lhst = lhs.term(); -// auto rhst = rhs.term(); - -// Ordering::Result prec = lhst->isSort() -// ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) -// : kbo.compareFunctionPrecedences(lhst->functor(),rhst->functor()); -// switch (prec) -// { -// case Ordering::LESS: { -// // again, this means the execution failed -// return; -// } -// case Ordering::GREATER: { -// // and this means the execution succeeded -// _instructions.push(Instruction::uintUint(InstructionTag::SUCCESS)); -// return; -// } -// case Ordering::EQUAL: { -// // push the arguments in reverse order to maintain -// // left-to-right lexicographic order in todo -// for (unsigned i = 0; i < lhst->arity(); i++) { -// auto lhsArg = *lhst->nthArgument(lhst->arity()-i-1); -// auto rhsArg = *rhst->nthArgument(lhst->arity()-i-1); -// todo.push(make_pair(lhsArg,rhsArg)); -// } -// break; -// } -// default: { -// ASSERTION_VIOLATION; -// } -// } -// } -// } - -// bool KBOComparator::check(const SubstApplicator* applicator) -// { -// if (!_ready) { -// makeReady(); -// _ready = true; -// } - -// const auto& kbo = static_cast(_ord); - -// for (unsigned i = 0; i < _instructions.size();) { -// switch (static_cast(_instructions[i]._tag())) { -// case InstructionTag::WEIGHT: { - -// // check weight and var balance -// auto arity = _instructions[i]._firstUint(); -// auto weight = _instructions[i]._coeff(); -// ZIArray varDiffs; -// for (unsigned j = i+1; j < i+1+arity; j++) { -// ASS(_instructions[j]._tag()==InstructionTag::DATA); - -// auto var = _instructions[j]._firstUint(); -// auto coeff = _instructions[j]._coeff(); -// AppliedTerm tt(TermList::var(var), applicator, true); - -// VariableIterator vit(tt.term); -// while (vit.hasNext()) { -// auto v = vit.next(); -// varDiffs[v.var()] += coeff; -// // since the counts are sorted in descending order, -// // this can only mean we will fail -// if (varDiffs[v.var()]<0) { -// return false; -// } -// } -// auto w = kbo.computeWeight(tt); -// weight += coeff*w; -// // due to descending order of counts, -// // this also means failure -// if (coeff<0 && weight<0) { -// return false; -// } -// } - -// if (weight > 0) { -// return true; -// } else if (weight < 0) { -// return false; -// } -// // jump over the [var,count] pairs -// i += 1+arity; -// break; -// } -// case InstructionTag::COMPARE_VV: { -// auto res = kbo.isGreaterOrEq( -// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), -// AppliedTerm(TermList::var(_instructions[i]._secondUint()), applicator, true)); -// if (res==Ordering::EQUAL) { -// i++; -// break; -// } -// return res==Ordering::GREATER; -// } -// case InstructionTag::COMPARE_VT: { -// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); -// auto res = kbo.isGreaterOrEq( -// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true), -// AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true)); -// if (res==Ordering::EQUAL) { -// i += 2; -// break; -// } -// return res==Ordering::GREATER; -// } -// case InstructionTag::COMPARE_TV: { -// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); -// // note that in this case the term is the second argument -// auto res = kbo.isGreaterOrEq( -// AppliedTerm(TermList(_instructions[i+1]._term()), applicator, true), -// AppliedTerm(TermList::var(_instructions[i]._firstUint()), applicator, true)); -// if (res==Ordering::EQUAL) { -// i += 2; -// break; -// } -// return res==Ordering::GREATER; -// } -// case InstructionTag::SUCCESS: { -// return true; -// } -// default: -// ASSERTION_VIOLATION; -// } -// } -// return false; -// } - -ostream& operator<<(ostream& out, const KBOComparator::BranchTag& t) -{ - switch (t) { - case KBOComparator::BranchTag::T_NOT_GREATER: - out << "!>"; - break; - case KBOComparator::BranchTag::T_GREATER: - out << ">"; - break; - case KBOComparator::BranchTag::T_COMPARISON: - out << "$"; - break; - case KBOComparator::BranchTag::T_WEIGHT: - out << "w"; - break; - case KBOComparator::BranchTag::T_UNKNOWN: - out << "?"; - break; - } - return out; -} - -std::ostream& operator<<(std::ostream& str, const KBOComparator::Branch& branch) -{ - str << branch.tag << " "; - if (branch.n) { - if (branch.tag==KBOComparator::BranchTag::T_WEIGHT) { - auto n = static_cast(branch.n.ptr()); - str << n->w << " "; - for (const auto& [var, coeff] : n->varCoeffPairs) { - str << "X" << var << " " << coeff << " "; - } - } else { - auto n = static_cast(branch.n.ptr()); - str << n->lhs << " " << n->rhs; - } - } else { - str << "null"; - } - return str; -} - -ostream& operator<<(ostream& str, const KBOComparator& comp) -{ - str << "comparator for " << comp._lhs << " > " << comp._rhs << endl; - // return str; - - Stack> todo; - todo.push(make_pair(&comp._root,0)); - unsigned cnt = 1; - - while (todo.isNonEmpty()) { - auto kv = todo.pop(); - str << cnt++ << " "; - for (unsigned i = 0; i < kv.second; i++) { - str << " "; - } - str << *kv.first << endl; - if (kv.first->n) { - todo.push(make_pair(&kv.first->n->incBranch,kv.second+1)); - todo.push(make_pair(&kv.first->n->gtBranch,kv.second+1)); - todo.push(make_pair(&kv.first->n->eqBranch,kv.second+1)); - } - } - return str; -} - -std::string KBOComparator::toString() const -{ - std::stringstream str; - str << *this << endl; - return str.str(); -} - -void KBOComparator::merge(OrderingComparator&& other) -{ - auto otherKBO = static_cast(other); - - static unsigned ts = 0; - ts++; - - Stack> todo; - todo.push(make_pair(&_root, std::move(otherKBO._root))); - while (todo.isNonEmpty()) { - auto [currB, otherB] = todo.pop(); - // if this branch is successful, or other - // branch is unsuccessful, we do nothing - if (currB->tag == BranchTag::T_GREATER - || otherB.tag == BranchTag::T_NOT_GREATER) - { - continue; - } - // if this branch is unsuccessful, or other branch - // is successful, we just replace current with other - if (currB->tag == BranchTag::T_NOT_GREATER - || otherB.tag == BranchTag::T_GREATER) - { - *currB = otherB; - continue; - } - ASS(currB->n); - ASS(otherB.n); - // if we already checked this branch, continue - if (currB->n->getTs()==ts) { - continue; - } - currB->n->setTs(ts); - // TODO no node from other should be T_COMPARISON here - if (currB->tag != otherB.tag || currB->tag != BranchTag::T_COMPARISON) { - todo.push(make_pair(&currB->n->eqBranch, otherB)); - todo.push(make_pair(&currB->n->gtBranch, otherB)); - todo.push(make_pair(&currB->n->incBranch, otherB)); - continue; - } - auto n = static_cast(currB->n.ptr()); - auto o = static_cast(otherB.n.ptr()); - if (n->lhs == o->lhs && n->rhs == o->rhs) { - todo.push(make_pair(&currB->n->eqBranch, otherB.n->eqBranch)); - todo.push(make_pair(&currB->n->gtBranch, otherB.n->gtBranch)); - todo.push(make_pair(&currB->n->incBranch, otherB.n->incBranch)); - continue; - } - todo.push(make_pair(&currB->n->eqBranch, otherB)); - todo.push(make_pair(&currB->n->gtBranch, otherB)); - todo.push(make_pair(&currB->n->incBranch, otherB)); - } -} - bool KBOComparator::check(const SubstApplicator* applicator) { static Stack cache; @@ -401,7 +29,7 @@ bool KBOComparator::check(const SubstApplicator* applicator) auto curr = &_root; while (curr->n) { - expand(*curr, kbo, cache); + expand(_ord, *curr, cache); if (!curr->n) { break; } @@ -452,8 +80,9 @@ bool KBOComparator::check(const SubstApplicator* applicator) return curr->tag == BranchTag::T_GREATER; } -void KBOComparator::expand(Branch& branch, const KBO& kbo, const Stack>& cache) +void KBOComparator::expand(const Ordering& ord, Branch& branch, const Stack& cache) { + const auto& kbo = static_cast(ord); while (branch.tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node @@ -579,145 +208,4 @@ void KBOComparator::expand(Branch& branch, const KBO& kbo, const Stack(_instructions[i]._tag())) { -// case InstructionTag::SUCCESS: { -// str << Int::toString(cnt++) << " success, "; -// i += 1; -// break; -// } -// case InstructionTag::WEIGHT: { -// auto arity = _instructions[i]._firstUint(); -// auto w = _instructions[i]._coeff(); -// str << Int::toString(cnt++) << " weight " << Int::toString(w); - -// for (unsigned j = i+1; j < i+1+arity; j++) { -// ASS(_instructions[j]._tag()==InstructionTag::DATA); -// auto var = _instructions[j]._firstUint(); -// auto coeff = _instructions[j]._coeff(); - -// str << " w(X" << Int::toString(var) << ")*" << Int::toString(coeff); -// } -// str << ", "; -// i += 1+arity; -// break; -// } -// case InstructionTag::COMPARE_VV: { -// auto v1 = _instructions[i]._firstUint(); -// auto v2 = _instructions[i]._secondUint(); -// str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " X" << Int::toString(v2) << ", "; -// i++; -// break; -// } -// case InstructionTag::COMPARE_VT: { -// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); -// auto v1 = _instructions[i]._firstUint(); -// auto t2 = _instructions[i+1]._term(); -// str << Int::toString(cnt++) << " compare X" << Int::toString(v1) << " " << *t2 << ", "; -// i += 2; -// break; -// } -// case InstructionTag::COMPARE_TV: { -// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); -// auto t1 = _instructions[i+1]._term(); -// auto v2 = _instructions[i]._firstUint(); -// str << Int::toString(cnt++) << " compare " << *t1 << " X" << Int::toString(v2) << ", "; -// i += 2; -// break; -// } -// default: -// ASSERTION_VIOLATION; -// } -// } -// return str.str(); -// } - -// bool KBOComparator::subsumes(OrderingComparator& other) -// { -// if (!_ready) { -// makeReady(); -// _ready = true; -// } -// auto& otherKBO = static_cast(other); -// if (!otherKBO._ready) { -// otherKBO.makeReady(); -// otherKBO._ready = true; -// } -// if (_instructions.size()(_instructions[i]._tag())) { -// case InstructionTag::WEIGHT: { -// // check weight and var balance -// auto arity = _instructions[i]._firstUint(); -// auto weight = _instructions[i]._coeff(); -// auto arityOther = otherKBO._instructions[i]._firstUint(); -// auto weightOther = otherKBO._instructions[i]._coeff(); -// if (arity != arityOther || weight != weightOther) { -// return false; -// } -// for (unsigned j = i+1; j < i+1+arity; j++) { -// ASS(_instructions[j]._tag()==InstructionTag::DATA); - -// auto var = _instructions[j]._firstUint(); -// auto coeff = _instructions[j]._coeff(); -// auto varOther = otherKBO._instructions[j]._firstUint(); -// auto coeffOther = otherKBO._instructions[j]._coeff(); -// // if ((*renaming)(var) != TermList::var(varOther) || coeff != coeffOther) { -// // return false; -// // } -// if (var != varOther || coeff != coeffOther) { -// return false; -// } -// } -// // jump over the [var,count] pairs -// i += 1+arity; -// break; -// } -// case InstructionTag::COMPARE_VV: { -// auto var1 = _instructions[i]._firstUint(); -// auto var2 = _instructions[i]._secondUint(); -// auto var1Other = otherKBO._instructions[i]._firstUint(); -// auto var2Other = otherKBO._instructions[i]._secondUint(); -// // if ((*renaming)(var1) != TermList::var(var1Other) || (*renaming)(var2) != TermList::var(var2Other)) { -// // return false; -// // } -// if (var1 != var1Other || var2 != var2Other) { -// return false; -// } -// i++; -// break; -// } -// case InstructionTag::COMPARE_VT: -// case InstructionTag::COMPARE_TV: { -// ASS(_instructions[i+1]._tag()==InstructionTag::DATA); -// auto var = _instructions[i]._firstUint(); -// auto term = _instructions[i+1]._term(); -// auto varOther = otherKBO._instructions[i]._firstUint(); -// auto termOther = otherKBO._instructions[i+1]._term(); -// // if ((*renaming)(var) != TermList::var(varOther) || SubstHelper::apply(TermList(term),*renaming) != TermList(termOther)) { -// // return false; -// // } -// if (var != varOther || term != termOther) { -// return false; -// } -// i += 2; -// break; -// } -// default: -// return true; -// } -// } -// return true; -// } - } diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index c8d99aea6..4e6395463 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -19,7 +19,7 @@ #include "Lib/Stack.hpp" -#include "KBO.hpp" +#include "OrderingComparator.hpp" namespace Kernel { @@ -33,164 +33,13 @@ class KBOComparator : public OrderingComparator { public: - KBOComparator(TermList lhs, TermList rhs, const KBO& kbo); + KBOComparator(const Ordering& ord, TermList lhs, TermList rhs) + : OrderingComparator(ord, lhs, rhs) {} /** Executes the runtime specialized instructions with concrete substitution. */ bool check(const SubstApplicator* applicator) override; - std::string toString() const override; - // bool subsumes(OrderingComparator& other) override; - void merge(OrderingComparator&& other) override; -// private: - void makeReady(); - - // enum InstructionTag { - // DATA = 0u, - // WEIGHT = 1u, - // COMPARE_VV = 2u, - // COMPARE_VT = 3u, - // COMPARE_TV = 4u, - // SUCCESS = 5u, - // }; - - // /** - // * Stores atomic instructions for KBO. - // * We have 64 bits per instruction, and the following combinations (where ?> denotes checking >): - // * - success - // * - weight check: w + |var_i o \theta|_v * nvar_i ?> 0 - // * - compare var with var: (var1 o \theta) ?> (var2 o \theta) - // * - compare var with term: (var o \theta) ?> (term o \theta) - // * - compare term with var: (term o \theta) ?> (var o \theta) - // * - // * and the following layout of instructions: - // * | first instruction | second instruction | ... - // * | 3 bits | 29 bits | 32 bits | 3 bits | 29 bits | 32 bits | - // * | SUCCESS | - // * | WEIGHT | arity | w | DATA | var_i | nvar_i | ... (this block `arity` times) - // * | COMPARE_VV | var1 | var2 | - // * | COMPARE_VT | var | | term | - // * | COMPARE_TV | var | | term | - // */ - // struct Instruction { - // static Instruction term(Term* t) { - // Instruction ins; - // ins._setTag(InstructionTag::DATA); - // ins._setTerm(t); - // return ins; - // } - // static Instruction uintUint(InstructionTag t, unsigned v1 = 0, unsigned v2 = 0) { - // Instruction ins; - // ins._content = 0; // to silence a gcc warning (we set all bits below anyway) - // ins._setTag(t); - // ins._setFirstUint(v1); - // ins._setSecondUint(v2); - // return ins; - // } - - // static constexpr unsigned - // TAG_BITS_START = 0, - // TAG_BITS_END = TAG_BITS_START + 3, - // FIRST_UINT_BITS_START = TAG_BITS_END, - // FIRST_UINT_BITS_END = FIRST_UINT_BITS_START + 29, - // SECOND_UINT_BITS_START = FIRST_UINT_BITS_END, - // SECOND_UINT_BITS_END = SECOND_UINT_BITS_START + 32, - // COEFF_BITS_START = FIRST_UINT_BITS_END, - // COEFF_BITS_END = COEFF_BITS_START + 32, - // TERM_BITS_START = 0, - // TERM_BITS_END = CHAR_BIT * sizeof(Term *); - - // static_assert(TAG_BITS_START == 0, "tag must be the least significant bits"); - // static_assert(TERM_BITS_START == 0, "term must be the least significant bits"); - // static_assert(sizeof(void *) <= sizeof(uint64_t), "must be able to fit a pointer into a 64-bit integer"); - // static_assert(InstructionTag::SUCCESS < 8, "must be able to squash tags into 3 bits"); - - // BITFIELD64_GET_AND_SET(unsigned, tag, Tag, TAG) - // BITFIELD64_GET_AND_SET(unsigned, firstUint, FirstUint, FIRST_UINT) - // BITFIELD64_GET_AND_SET(unsigned, secondUint, SecondUint, SECOND_UINT) - // BITFIELD64_GET_AND_SET(int, coeff, Coeff, COEFF) - // BITFIELD64_GET_AND_SET_PTR(Term*, term, Term, TERM) - - // private: - // uint64_t _content; - // }; - - enum class BranchTag : uint8_t { - T_GREATER, - T_NOT_GREATER, - T_COMPARISON, - T_WEIGHT, - T_UNKNOWN, - }; - - struct Node; - - struct Branch { - BranchTag tag; - SmartPtr n; - - explicit Branch(BranchTag t) : tag(t) { ASS(t==BranchTag::T_GREATER || t==BranchTag::T_NOT_GREATER); } - explicit Branch(TermList lhs, TermList rhs) - : tag(BranchTag::T_UNKNOWN), n(new ComparisonNode(lhs, rhs)) {} - explicit Branch(int w, Stack>&& varCoeffPairs) - : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))) {} - }; - - struct Node { - Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER), ts(0) {} - - auto& getBranch(Ordering::Result r) { - switch (r) { - case Ordering::EQUAL: - return eqBranch; - case Ordering::GREATER: - return gtBranch; - case Ordering::INCOMPARABLE: - return incBranch; - default: - ASSERTION_VIOLATION; - } - } - - void setTs(unsigned val) { ts = val; } - unsigned getTs() const { return ts; } - - Branch eqBranch; - Branch gtBranch; - Branch incBranch; - unsigned ts; - }; - - class ComparisonNode : public Node { - ComparisonNode(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - TermList lhs; - TermList rhs; - }; - - using VarCoeffPair = std::pair; - - class WeightNode : public Node { - WeightNode(int w, Stack&& varCoeffPairs) - : w(w), varCoeffPairs(varCoeffPairs) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - int w; - Stack varCoeffPairs; - }; - - using TermPairRes = std::tuple; - static void expand(Branch& branch, const KBO& kbo, const Stack& cache); - - bool _ready = false; - // Stack _instructions; - Branch _root; + static void expand(const Ordering& ord, Branch& branch, const Stack& cache); }; } diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index ccf3b56ab..970b9e88c 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -249,7 +249,7 @@ Ordering::Result LPO::majo(AppliedTerm s, AppliedTerm t, const TermList* tl, uns OrderingComparatorUP LPO::createComparator(TermList lhs, TermList rhs) const { - return make_unique(lhs, rhs, *this); + return make_unique(*this, lhs, rhs); } void LPO::showConcrete(ostream&) const diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index ec8ec443c..b73691dd3 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -8,6 +8,8 @@ * and in the source directory */ +#include "LPO.hpp" + #include "LPOComparator.hpp" #include "RobSubstitution.hpp" @@ -48,71 +50,6 @@ bool unify(TermList tl1, TermList tl2, TermList& orig1, TermList& orig2) return true; } -LPOComparator::LPOComparator(TermList lhs, TermList rhs, const LPO& lpo) - : OrderingComparator(lhs, rhs, lpo), _root(lhs, rhs) -{ -} - -ostream& operator<<(ostream& out, const LPOComparator::BranchTag& t) -{ - switch (t) { - case LPOComparator::BranchTag::T_NOT_GREATER: - out << "!>"; - break; - case LPOComparator::BranchTag::T_GREATER: - out << ">"; - break; - case LPOComparator::BranchTag::T_COMPARISON: - out << "$"; - break; - case LPOComparator::BranchTag::T_UNKNOWN: - out << "?"; - break; - } - return out; -} - -std::ostream& operator<<(std::ostream& str, const LPOComparator::Branch& branch) -{ - str << branch.tag << " "; - if (branch.n) { - str << branch.n->lhs << " " << branch.n->rhs; - } else { - str << "null"; - } - return str; -} - -ostream& operator<<(ostream& str, const LPOComparator& comp) -{ - str << "comparator for " << comp._lhs << " > " << comp._rhs << endl; - Stack> todo; - todo.push(make_pair(&comp._root,0)); - unsigned cnt = 1; - - while (todo.isNonEmpty()) { - auto kv = todo.pop(); - str << cnt++ << " "; - for (unsigned i = 0; i < kv.second; i++) { - str << " "; - } - str << *kv.first << endl; - if (kv.first->n) { - todo.push(make_pair(&kv.first->n->incBranch,kv.second+1)); - todo.push(make_pair(&kv.first->n->gtBranch,kv.second+1)); - todo.push(make_pair(&kv.first->n->eqBranch,kv.second+1)); - } - } - return str; -} - -std::string LPOComparator::toString() const -{ - std::stringstream str; - str << *this << endl; - return str.str(); -} - /** * Implements an @b LPO::majo call via instructions. */ @@ -143,13 +80,15 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = fail; } -void LPOComparator::expand(Branch& branch, const LPO& lpo) +void LPOComparator::expand(const Ordering& ord, Branch& branch, const Stack& cache) { + const auto& lpo = static_cast(ord); while (branch.tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node Branch nodeHolder = branch; - auto node = nodeHolder.n.ptr(); + auto node = static_cast(nodeHolder.n.ptr()); + ASS(node); // Use compare here to filter out as many // precomputable comparisons as possible. @@ -166,6 +105,28 @@ void LPOComparator::expand(Branch& branch, const LPO& lpo) } // If we have a variable, we cannot preprocess further. if (node->lhs.isVar() || node->rhs.isVar()) { + // try cache + bool found = false; + for (const auto& [s,t,r] : cache) { + if (s != node->lhs || t != node->rhs) { + continue; + } + if (r == Ordering::GREATER) { + branch = node->gtBranch; + } else if (r == Ordering::EQUAL) { + branch = node->eqBranch; + } else { + ASS_NEQ(r, Ordering::LESS); + branch = node->incBranch; + } + found = true; + break; + } + if (found) { + continue; + } + // TODO we should replace the node here with a fresh one + // TODO check node's refcount? branch.tag = BranchTag::T_COMPARISON; continue; } @@ -224,16 +185,22 @@ void LPOComparator::expand(Branch& branch, const LPO& lpo) bool LPOComparator::check(const SubstApplicator* applicator) { + static Stack cache; + cache.reset(); const auto& lpo = static_cast(_ord); auto curr = &_root; while (curr->n) { - expand(*curr, lpo); + expand(_ord, *curr, cache); if (!curr->n) { break; } + ASS(curr->tag==BranchTag::T_COMPARISON); ASS(curr->n); - auto comp = lpo.lpo(AppliedTerm(curr->n->lhs,applicator,true),AppliedTerm(curr->n->rhs,applicator,true)); + auto node = static_cast(curr->n.ptr()); + + auto comp = lpo.lpo(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); + cache.push({ node->lhs, node->rhs, comp }); curr = &curr->n->getBranch(comp); } return curr->tag == BranchTag::T_GREATER; diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index d867ba6d6..316a01dd9 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -13,7 +13,7 @@ #include "Forwards.hpp" -#include "LPO.hpp" +#include "OrderingComparator.hpp" namespace Kernel { @@ -24,67 +24,16 @@ class LPOComparator : public OrderingComparator { public: - LPOComparator(TermList lhs, TermList rhs, const LPO& lpo); + LPOComparator(const Ordering& ord, TermList lhs, TermList rhs) + : OrderingComparator(ord, lhs, rhs) {} /** Executes the runtime specialized instructions with concrete substitution. */ bool check(const SubstApplicator* applicator) override; - std::string toString() const override; - - /* A branch initially has a T_UNKNOWN tag, and after first processing becomes either - * a specific result T_GREATER/T_NOT_GREATER or a pointer to a comparison node. */ - enum class BranchTag : uint8_t { - T_GREATER, - T_NOT_GREATER, - T_COMPARISON, - T_UNKNOWN, - }; - - class Node; - - struct Branch { - BranchTag tag; - SmartPtr n; - - explicit Branch(BranchTag t) : tag(t) { ASS(t==BranchTag::T_GREATER || t==BranchTag::T_NOT_GREATER); } - explicit Branch(TermList lhs, TermList rhs) : tag(BranchTag::T_UNKNOWN), n(new Node(lhs, rhs)) {} - }; - - class Node { - Node(TermList lhs, TermList rhs) - : lhs(lhs), rhs(rhs), eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - auto& getBranch(Ordering::Result r) { - switch (r) { - case Ordering::EQUAL: - return eqBranch; - case Ordering::GREATER: - return gtBranch; - case Ordering::INCOMPARABLE: - return incBranch; - default: - ASSERTION_VIOLATION; - } - } - - TermList lhs; - TermList rhs; - Branch eqBranch; - Branch gtBranch; - Branch incBranch; - }; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); static void alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2, Branch success, Branch fail); - static void expand(Branch& branch, const LPO& lpo); - - friend ostream& operator<<(ostream& str, const LPOComparator& comp); - - Branch _root; + static void expand(const Ordering& ord, Branch& branch, const Stack& cache); }; } diff --git a/Kernel/Ordering.cpp b/Kernel/Ordering.cpp index bdfadf731..d3873d763 100644 --- a/Kernel/Ordering.cpp +++ b/Kernel/Ordering.cpp @@ -34,6 +34,7 @@ #include "LPO.hpp" #include "KBO.hpp" #include "SKIKBO.hpp" +#include "OrderingComparator.hpp" #include "Problem.hpp" #include "Signature.hpp" #include "NumTraits.hpp" @@ -49,13 +50,6 @@ using namespace std; using namespace Lib; using namespace Kernel; -bool OrderingComparator::check(const SubstApplicator* applicator) -{ - return _ord.isGreater( - AppliedTerm(_lhs, applicator, /*aboveVar*/true), - AppliedTerm(_rhs, applicator, /*aboveVar*/true)); -} - OrderingSP Ordering::s_globalOrdering; /** @@ -216,6 +210,11 @@ Ordering::Result Ordering::getEqualityArgumentOrder(Literal* eq) const return res; } +OrderingComparatorUP Ordering::createComparator(TermList lhs, TermList rhs) const +{ + return std::make_unique(*this, lhs, rhs); +} + ////////////////////////////////////////////////// // PrecedenceOrdering class ////////////////////////////////////////////////// diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index aa685507b..225a7f3fd 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -33,26 +33,6 @@ namespace Kernel { using namespace Shell; -/** - * Class implementing runtime specialized ordering check between two terms. - * The comparator is created and called from inside the respective ordering - * object, but owned by the caller, so the destructor is exposed as virtual. - * See @b KBOComparator and @b LPOComparator for implementation details. - */ -struct OrderingComparator -{ - OrderingComparator(TermList lhs, TermList rhs, const Ordering& ord) : _lhs(lhs), _rhs(rhs), _ord(ord) {} - virtual ~OrderingComparator() = default; - virtual std::string toString() const { return _lhs.toString()+" > "+_rhs.toString(); } - virtual bool check(const SubstApplicator* applicator); - virtual bool subsumes(OrderingComparator& other) { return false; } - virtual void merge(OrderingComparator&& other) {} - - TermList _lhs; - TermList _rhs; - const Ordering& _ord; -}; - /** * An abstract class for simplification orderings * @since 30/04/2008 flight Brussels-Tel Aviv @@ -94,8 +74,7 @@ class Ordering /** Creates optimised object to check that @b lhs is greater than @b rhs. * @see OrderingComparator. */ - virtual OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const - { return std::make_unique(lhs, rhs, *this); } + virtual OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const; virtual void show(std::ostream& out) const = 0; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp new file mode 100644 index 000000000..24e4b7375 --- /dev/null +++ b/Kernel/OrderingComparator.cpp @@ -0,0 +1,141 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file OrderingComparator.cpp + * Implements class OrderingComparator. + */ + +#include "Lib/Stack.hpp" + +#include "SubstHelper.hpp" + +#include "OrderingComparator.hpp" + +namespace Kernel { + +std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) +{ + switch (t) { + case OrderingComparator::BranchTag::T_NOT_GREATER: + out << "!>"; + break; + case OrderingComparator::BranchTag::T_GREATER: + out << ">"; + break; + case OrderingComparator::BranchTag::T_COMPARISON: + out << "$"; + break; + case OrderingComparator::BranchTag::T_WEIGHT: + out << "w"; + break; + case OrderingComparator::BranchTag::T_UNKNOWN: + out << "?"; + break; + } + return out; +} + +std::ostream& operator<<(std::ostream& str, const OrderingComparator::Branch& branch) +{ + str << branch.tag << " "; + if (branch.n) { + if (branch.tag==OrderingComparator::BranchTag::T_WEIGHT) { + auto n = static_cast(branch.n.ptr()); + str << n->w << " "; + for (const auto& [var, coeff] : n->varCoeffPairs) { + str << "X" << var << " " << coeff << " "; + } + } else { + auto n = static_cast(branch.n.ptr()); + str << n->lhs << " " << n->rhs; + } + } else { + str << "null"; + } + return str; +} + +std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) +{ + Stack> todo; + todo.push(std::make_pair(&comp._root,0)); + unsigned cnt = 1; + + while (todo.isNonEmpty()) { + auto kv = todo.pop(); + str << cnt++ << " "; + for (unsigned i = 0; i < kv.second; i++) { + str << " "; + } + str << *kv.first << std::endl; + if (kv.first->n) { + todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + } + } + return str; +} + +OrderingComparator::~OrderingComparator() = default; + +void OrderingComparator::merge(const OrderingComparator& other) +{ + static unsigned ts = 0; + ts++; + + Stack> todo; + todo.push(std::make_pair(&_root, other._root)); + while (todo.isNonEmpty()) { + auto [currB, otherB] = todo.pop(); + // if this branch is successful, or other + // branch is unsuccessful, we do nothing + if (currB->tag == BranchTag::T_GREATER + || otherB.tag == BranchTag::T_NOT_GREATER) + { + continue; + } + // if this branch is unsuccessful, or other branch + // is successful, we just replace current with other + if (currB->tag == BranchTag::T_NOT_GREATER + || otherB.tag == BranchTag::T_GREATER) + { + *currB = otherB; + continue; + } + ASS(currB->n); + ASS(otherB.n); + // if we already checked this branch, continue + if (currB->n->getTs()==ts) { + continue; + } + currB->n->setTs(ts); + // TODO no node from other should be T_COMPARISON here + if (currB->tag != otherB.tag || currB->tag != BranchTag::T_COMPARISON) { + todo.push(std::make_pair(&currB->n->eqBranch, otherB)); + todo.push(std::make_pair(&currB->n->gtBranch, otherB)); + todo.push(std::make_pair(&currB->n->incBranch, otherB)); + continue; + } + auto n = static_cast(currB->n.ptr()); + auto o = static_cast(otherB.n.ptr()); + if (n->lhs == o->lhs && n->rhs == o->rhs) { + todo.push(std::make_pair(&currB->n->eqBranch, otherB.n->eqBranch)); + todo.push(std::make_pair(&currB->n->gtBranch, otherB.n->gtBranch)); + todo.push(std::make_pair(&currB->n->incBranch, otherB.n->incBranch)); + continue; + } + todo.push(std::make_pair(&currB->n->eqBranch, otherB)); + todo.push(std::make_pair(&currB->n->gtBranch, otherB)); + todo.push(std::make_pair(&currB->n->incBranch, otherB)); + } +} + +} \ No newline at end of file diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp new file mode 100644 index 000000000..9633cb116 --- /dev/null +++ b/Kernel/OrderingComparator.hpp @@ -0,0 +1,116 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file OrderingComparator.hpp + */ + +#ifndef __OrderingComparator__ +#define __OrderingComparator__ + +#include "Forwards.hpp" + +#include "Ordering.hpp" + +namespace Kernel { + +/** + * Class implementing runtime specialized ordering check between two terms. + * The comparator is created and called from inside the respective ordering + * object, but owned by the caller, so the destructor is exposed as virtual. + * See @b KBOComparator and @b LPOComparator for implementation details. + */ +struct OrderingComparator +{ + OrderingComparator(const Ordering& ord, TermList lhs, TermList rhs) : _ord(ord), _root(lhs, rhs) {} + virtual ~OrderingComparator(); + virtual bool check(const SubstApplicator* applicator) { return false; } + virtual void merge(const OrderingComparator& other); + + friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); + + enum class BranchTag : uint8_t { + T_GREATER, + T_NOT_GREATER, + T_COMPARISON, + T_WEIGHT, + T_UNKNOWN, + }; + + struct Node; + + struct Branch { + BranchTag tag; + SmartPtr n; + + explicit Branch(BranchTag t) : tag(t) { ASS(t==BranchTag::T_GREATER || t==BranchTag::T_NOT_GREATER); } + explicit Branch(TermList lhs, TermList rhs) + : tag(BranchTag::T_UNKNOWN), n(new ComparisonNode(lhs, rhs)) {} + explicit Branch(int w, Stack>&& varCoeffPairs) + : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))) {} + }; + + struct Node { + Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER), ts(0) {} + + auto& getBranch(Ordering::Result r) { + switch (r) { + case Ordering::EQUAL: + return eqBranch; + case Ordering::GREATER: + return gtBranch; + case Ordering::INCOMPARABLE: + return incBranch; + default: + ASSERTION_VIOLATION; + } + } + + void setTs(unsigned val) { ts = val; } + unsigned getTs() const { return ts; } + + Branch eqBranch; + Branch gtBranch; + Branch incBranch; + unsigned ts; + }; + + class ComparisonNode : public Node { + ComparisonNode(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs) {} + + // only allow calling ctor from Branch + friend struct Branch; + + public: + TermList lhs; + TermList rhs; + }; + + using VarCoeffPair = std::pair; + using TermPairRes = std::tuple; + + class WeightNode : public Node { + WeightNode(int w, Stack&& varCoeffPairs) + : w(w), varCoeffPairs(varCoeffPairs) {} + + // only allow calling ctor from Branch + friend struct Branch; + + public: + int w; + Stack varCoeffPairs; + }; + + const Ordering& _ord; + Branch _root; +}; + +} // namespace Kernel + +#endif \ No newline at end of file diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index f6b0d79d1..f76a33ec7 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -56,7 +56,11 @@ std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) } else { str << *e.splits << "; " << *e.lits << "; "; iterTraits(e.ordCons.iter()).forEach([&str](const OrderingConstraint& con) { - str << (con.comp ? con.comp->toString() : (con.lhs.toString()+" > "+con.rhs.toString())); + if (con.comp) { + str << *con.comp; + } else { + str << con.lhs.toString() << " > " << con.rhs.toString(); + } }); } return str; @@ -137,17 +141,6 @@ class ConditionalRedundancyHandler::ConstraintIndex e->ordCons[0].comp->merge(std::move(*ptr->ordCons[0].comp.get())); return true; - /// UNREACHABLE - - if (e->ordCons[0].comp->subsumes(*ptr->ordCons[0].comp)) { - env.statistics->skippedInferencesDueToOrderingConstraints++; - return false; - } - if (ptr->ordCons[0].comp->subsumes(*e->ordCons[0].comp)) { - std::swap((*entries)[i],entries->top()); - entries->pop(); - continue; - } } i++; } From 6d044da09cbf54928e7ad628b561a200971128f1 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 21 Sep 2024 21:47:28 +0200 Subject: [PATCH 06/64] Fix KBOComparator expansion --- Kernel/KBOComparator.cpp | 7 +++++++ Kernel/LPOComparator.cpp | 5 +++++ Kernel/OrderingComparator.hpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 8e4ba63b0..c188015f1 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -124,9 +124,14 @@ void KBOComparator::expand(const Ordering& ord, Branch& branch, const Stacklhs, node->rhs); // TODO we should replace the node here with a fresh one // TODO check node's refcount? branch.tag = BranchTag::T_COMPARISON; + branch.n->eqBranch = node->eqBranch; + branch.n->gtBranch = node->gtBranch; + branch.n->incBranch = node->incBranch; continue; } @@ -196,6 +201,8 @@ void KBOComparator::expand(const Ordering& ord, Branch& branch, const StacknthArgument(i); auto rhsArg = *rhst->nthArgument(i); *curr = Branch(lhsArg,rhsArg); + curr->n->gtBranch = node->gtBranch; + curr->n->incBranch = node->incBranch; curr = &curr->n->eqBranch; } *curr = node->eqBranch; diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index b73691dd3..1c55097c8 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -125,9 +125,14 @@ void LPOComparator::expand(const Ordering& ord, Branch& branch, const Stacklhs, node->rhs); // TODO we should replace the node here with a fresh one // TODO check node's refcount? branch.tag = BranchTag::T_COMPARISON; + branch.n->eqBranch = node->eqBranch; + branch.n->gtBranch = node->gtBranch; + branch.n->incBranch = node->incBranch; continue; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 9633cb116..d173a3778 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -56,6 +56,8 @@ struct OrderingComparator : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))) {} }; + friend std::ostream& operator<<(std::ostream& out, const Branch& branch); + struct Node { Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER), ts(0) {} From 34c92d76df7f4de91b5ec579e95f33c63da61da1 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 23 Sep 2024 11:11:16 +0200 Subject: [PATCH 07/64] Move check to OrderingComparator; expand is now the only virtual method of OrderingComparator --- Indexing/Index.hpp | 2 +- Inferences/BackwardDemodulation.cpp | 2 +- Inferences/ForwardDemodulation.cpp | 6 +- Kernel/KBO.cpp | 5 -- Kernel/KBO.hpp | 4 +- Kernel/KBOComparator.cpp | 61 +------------ Kernel/KBOComparator.hpp | 5 +- Kernel/LPO.cpp | 4 +- Kernel/LPO.hpp | 3 +- Kernel/LPOComparator.cpp | 27 +----- Kernel/LPOComparator.hpp | 4 +- Kernel/Ordering.hpp | 4 +- Kernel/OrderingComparator.cpp | 132 +++++++++++++++++++++------- Kernel/OrderingComparator.hpp | 10 ++- 14 files changed, 123 insertions(+), 146 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index bc324ad78..284080614 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -146,7 +146,7 @@ struct DemodulatorData IMPL_COMPARISONS_FROM_TUPLE(DemodulatorData) friend std::ostream& operator<<(std::ostream& out, DemodulatorData const& self) - { return out << "(" << self.term << " = " << self.rhs << outputPtr(self.clause) << ")"; } + { return out << "(" << self.term << " = " << self.rhs << ", cl " << outputPtr(self.clause) << ")"; } }; template diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index bc06298bd..6dfcae249 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -143,7 +143,7 @@ struct BackwardDemodulation::ResultFn TermList lhsS=qr.data->term; - if (!_ordering.isGreater(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))) { + if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { return BwSimplificationRecord(0); } diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 9669ebf0e..1f7e4d3ce 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -176,20 +176,20 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if (_precompiledComparison) { if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { - if (ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { + if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("greater"); } continue; } - if (!ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true))) { + if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("not greater"); } } else { - if (!preordered && (_preorderedOnly || !ordering.isGreater(AppliedTerm(trm),AppliedTerm(rhs,appl,true)))) { + if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true)))!=Ordering::GREATER) { continue; } } diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index 6396fc580..eeda27268 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -874,11 +874,6 @@ Ordering::Result KBO::isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const return res; } -bool KBO::isGreater(AppliedTerm lhs, AppliedTerm rhs) const -{ - return isGreaterOrEq(lhs,rhs)==GREATER; -} - OrderingComparatorUP KBO::createComparator(TermList lhs, TermList rhs) const { return make_unique(*this, lhs, rhs); diff --git a/Kernel/KBO.hpp b/Kernel/KBO.hpp index 92257e6c1..134120a66 100644 --- a/Kernel/KBO.hpp +++ b/Kernel/KBO.hpp @@ -157,15 +157,15 @@ class KBO Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm t1, AppliedTerm t2) const override; - bool isGreater(AppliedTerm t1, AppliedTerm t2) const override; + Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const override; OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const override; protected: - Result isGreaterOrEq(AppliedTerm tt1, AppliedTerm tt2) const; unsigned computeWeight(AppliedTerm tt) const; Result comparePredicates(Literal* l1, Literal* l2) const override; + friend struct OrderingComparator; friend class KBOComparator; // int functionSymbolWeight(unsigned fun) const; diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index c188015f1..be96da21a 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,68 +21,9 @@ using namespace std; using namespace Lib; using namespace Shell; -bool KBOComparator::check(const SubstApplicator* applicator) +void KBOComparator::expand(Branch& branch, const Stack& cache) { - static Stack cache; - cache.reset(); const auto& kbo = static_cast(_ord); - auto curr = &_root; - - while (curr->n) { - expand(_ord, *curr, cache); - if (!curr->n) { - break; - } - ASS(curr->n); - Ordering::Result comp = Ordering::INCOMPARABLE; - if (curr->tag == BranchTag::T_COMPARISON) { - - auto node = static_cast(curr->n.ptr()); - comp = kbo.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); - cache.push({ node->lhs, node->rhs, comp }); - - } else { - ASS(curr->tag == BranchTag::T_WEIGHT); - auto node = static_cast(curr->n.ptr()); - auto weight = node->w; - ZIArray varDiffs; - for (const auto& [var, coeff] : node->varCoeffPairs) { - AppliedTerm tt(TermList::var(var), applicator, true); - - VariableIterator vit(tt.term); - while (vit.hasNext()) { - auto v = vit.next(); - varDiffs[v.var()] += coeff; - // since the counts are sorted in descending order, - // this can only mean we will fail - if (varDiffs[v.var()]<0) { - goto loop_end; - } - } - auto w = kbo.computeWeight(tt); - weight += coeff*w; - // due to descending order of counts, - // this also means failure - if (coeff<0 && weight<0) { - goto loop_end; - } - } - - if (weight > 0) { - comp = Ordering::GREATER; - } else if (weight == 0) { - comp = Ordering::EQUAL; - } - } -loop_end: - curr = &curr->n->getBranch(comp); - } - return curr->tag == BranchTag::T_GREATER; -} - -void KBOComparator::expand(const Ordering& ord, Branch& branch, const Stack& cache) -{ - const auto& kbo = static_cast(ord); while (branch.tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 4e6395463..49a6c1601 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -36,10 +36,7 @@ class KBOComparator KBOComparator(const Ordering& ord, TermList lhs, TermList rhs) : OrderingComparator(ord, lhs, rhs) {} - /** Executes the runtime specialized instructions with concrete substitution. */ - bool check(const SubstApplicator* applicator) override; - - static void expand(const Ordering& ord, Branch& branch, const Stack& cache); + void expand(Branch& branch, const Stack& cache) override; }; } diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index 970b9e88c..60fd98038 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -96,9 +96,9 @@ Ordering::Result LPO::compare(AppliedTerm tl1, AppliedTerm tl2) const return clpo(tl1, tl2); } -bool LPO::isGreater(AppliedTerm lhs, AppliedTerm rhs) const +Ordering::Result LPO::isGreaterOrEq(AppliedTerm lhs, AppliedTerm rhs) const { - return lpo(lhs,rhs)==GREATER; + return lpo(lhs,rhs); } Ordering::Result LPO::clpo(AppliedTerm tl1, AppliedTerm tl2) const diff --git a/Kernel/LPO.hpp b/Kernel/LPO.hpp index 01d083ff6..bb919923c 100644 --- a/Kernel/LPO.hpp +++ b/Kernel/LPO.hpp @@ -47,7 +47,7 @@ class LPO using PrecedenceOrdering::compare; Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm tl1, AppliedTerm tl2) const override; - bool isGreater(AppliedTerm tl1, AppliedTerm tl2) const override; + Result isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const override; OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const override; void showConcrete(std::ostream&) const override; @@ -66,7 +66,6 @@ class LPO Result majo(AppliedTerm s, AppliedTerm t, const TermList* tl, unsigned arity) const; friend class LPOComparator; - friend class LPOComparator2; }; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 1c55097c8..539ff0ed3 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -80,9 +80,9 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = fail; } -void LPOComparator::expand(const Ordering& ord, Branch& branch, const Stack& cache) +void LPOComparator::expand(Branch& branch, const Stack& cache) { - const auto& lpo = static_cast(ord); + const auto& lpo = static_cast(_ord); while (branch.tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node @@ -188,27 +188,4 @@ void LPOComparator::expand(const Ordering& ord, Branch& branch, const Stack cache; - cache.reset(); - const auto& lpo = static_cast(_ord); - auto curr = &_root; - - while (curr->n) { - expand(_ord, *curr, cache); - if (!curr->n) { - break; - } - ASS(curr->tag==BranchTag::T_COMPARISON); - ASS(curr->n); - auto node = static_cast(curr->n.ptr()); - - auto comp = lpo.lpo(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); - cache.push({ node->lhs, node->rhs, comp }); - curr = &curr->n->getBranch(comp); - } - return curr->tag == BranchTag::T_GREATER; -} - } diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index 316a01dd9..26fae948d 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -27,13 +27,11 @@ class LPOComparator LPOComparator(const Ordering& ord, TermList lhs, TermList rhs) : OrderingComparator(ord, lhs, rhs) {} - /** Executes the runtime specialized instructions with concrete substitution. */ - bool check(const SubstApplicator* applicator) override; + void expand(Branch& branch, const Stack& cache) override; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); static void alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2, Branch success, Branch fail); - static void expand(const Ordering& ord, Branch& branch, const Stack& cache); }; } diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index 225a7f3fd..a49b34bb0 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -69,8 +69,8 @@ class Ordering /** Optimised function used for checking that @b t1 is greater than @b t2, * under some substitutions captured by @b AppliedTerm. */ - virtual bool isGreater(AppliedTerm t1, AppliedTerm t2) const - { return compare(t1, t2) == Result::GREATER; } + virtual Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const + { return compare(t1, t2); } /** Creates optimised object to check that @b lhs is greater than @b rhs. * @see OrderingComparator. */ diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 24e4b7375..4f9608f99 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -13,6 +13,7 @@ */ #include "Lib/Stack.hpp" +#include "KBO.hpp" #include "SubstHelper.hpp" @@ -86,30 +87,92 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) OrderingComparator::~OrderingComparator() = default; +bool OrderingComparator::check(const SubstApplicator* applicator) +{ + static Stack cache; + cache.reset(); + auto curr = &_root; + + while (curr->n) { + expand(*curr, cache); + if (!curr->n) { + break; + } + ASS(curr->n); + Ordering::Result comp = Ordering::INCOMPARABLE; + if (curr->tag == BranchTag::T_COMPARISON) { + + auto node = static_cast(curr->n.ptr()); + comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); + cache.push({ node->lhs, node->rhs, comp }); + + } else { + ASS(curr->tag == BranchTag::T_WEIGHT); + + const auto& kbo = static_cast(_ord); + auto node = static_cast(curr->n.ptr()); + auto weight = node->w; + ZIArray varDiffs; + for (const auto& [var, coeff] : node->varCoeffPairs) { + AppliedTerm tt(TermList::var(var), applicator, true); + + VariableIterator vit(tt.term); + while (vit.hasNext()) { + auto v = vit.next(); + varDiffs[v.var()] += coeff; + // since the counts are sorted in descending order, + // this can only mean we will fail + if (varDiffs[v.var()]<0) { + goto loop_end; + } + } + auto w = kbo.computeWeight(tt); + weight += coeff*w; + // due to descending order of counts, + // this also means failure + if (coeff<0 && weight<0) { + goto loop_end; + } + } + + if (weight > 0) { + comp = Ordering::GREATER; + } else if (weight == 0) { + comp = Ordering::EQUAL; + } + } +loop_end: + curr = &curr->n->getBranch(comp); + } + return curr->tag == BranchTag::T_GREATER; +} + void OrderingComparator::merge(const OrderingComparator& other) { + ASS(other._root.tag == BranchTag::T_UNKNOWN); + static unsigned ts = 0; ts++; Stack> todo; - todo.push(std::make_pair(&_root, other._root)); - while (todo.isNonEmpty()) { - auto [currB, otherB] = todo.pop(); - // if this branch is successful, or other - // branch is unsuccessful, we do nothing - if (currB->tag == BranchTag::T_GREATER - || otherB.tag == BranchTag::T_NOT_GREATER) - { - continue; + + auto pushBranches = [&todo](Branch* b, const Branch& other) { + // if other branch is unsuccessful, do nothing + if (b->tag == BranchTag::T_GREATER || other.tag == BranchTag::T_NOT_GREATER) { + return; } - // if this branch is unsuccessful, or other branch - // is successful, we just replace current with other - if (currB->tag == BranchTag::T_NOT_GREATER - || otherB.tag == BranchTag::T_GREATER) - { - *currB = otherB; - continue; + // if this branch is unsuccessful, replace this with other + if (b->tag == BranchTag::T_NOT_GREATER || other.tag == BranchTag::T_GREATER) { + *b = other; + return; } + todo.push(std::make_pair(b,other)); + }; + + pushBranches(&_root, other._root); + + while (todo.isNonEmpty()) { + auto [currB, otherB] = todo.pop(); ASS(currB->n); ASS(otherB.n); // if we already checked this branch, continue @@ -117,24 +180,27 @@ void OrderingComparator::merge(const OrderingComparator& other) continue; } currB->n->setTs(ts); - // TODO no node from other should be T_COMPARISON here - if (currB->tag != otherB.tag || currB->tag != BranchTag::T_COMPARISON) { - todo.push(std::make_pair(&currB->n->eqBranch, otherB)); - todo.push(std::make_pair(&currB->n->gtBranch, otherB)); - todo.push(std::make_pair(&currB->n->incBranch, otherB)); - continue; - } - auto n = static_cast(currB->n.ptr()); - auto o = static_cast(otherB.n.ptr()); - if (n->lhs == o->lhs && n->rhs == o->rhs) { - todo.push(std::make_pair(&currB->n->eqBranch, otherB.n->eqBranch)); - todo.push(std::make_pair(&currB->n->gtBranch, otherB.n->gtBranch)); - todo.push(std::make_pair(&currB->n->incBranch, otherB.n->incBranch)); - continue; + if (currB->tag == BranchTag::T_UNKNOWN && currB->tag != BranchTag::T_COMPARISON) { + // both must be comparison nodes + auto n = static_cast(currB->n.ptr()); + auto o = static_cast(otherB.n.ptr()); + if (n->lhs == o->lhs && n->rhs == o->rhs) { + pushBranches(&currB->n->eqBranch, otherB.n->eqBranch); + pushBranches(&currB->n->gtBranch, otherB.n->gtBranch); + pushBranches(&currB->n->incBranch, otherB.n->incBranch); + continue; + } } - todo.push(std::make_pair(&currB->n->eqBranch, otherB)); - todo.push(std::make_pair(&currB->n->gtBranch, otherB)); - todo.push(std::make_pair(&currB->n->incBranch, otherB)); + pushBranches(&currB->n->eqBranch, otherB); + pushBranches(&currB->n->gtBranch, otherB); + pushBranches(&currB->n->incBranch, otherB); + } +} + +void OrderingComparator::expand(Branch& branch, const Stack& cache) +{ + if (branch.tag == BranchTag::T_UNKNOWN) { + branch.tag = BranchTag::T_COMPARISON; } } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index d173a3778..8a3a692c5 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -30,8 +30,13 @@ struct OrderingComparator { OrderingComparator(const Ordering& ord, TermList lhs, TermList rhs) : _ord(ord), _root(lhs, rhs) {} virtual ~OrderingComparator(); - virtual bool check(const SubstApplicator* applicator) { return false; } - virtual void merge(const OrderingComparator& other); + bool check(const SubstApplicator* applicator); + void merge(const OrderingComparator& other); + + struct Branch; + using TermPairRes = std::tuple; + + virtual void expand(Branch& branch, const Stack& cache); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); @@ -95,7 +100,6 @@ struct OrderingComparator }; using VarCoeffPair = std::pair; - using TermPairRes = std::tuple; class WeightNode : public Node { WeightNode(int w, Stack&& varCoeffPairs) From a40cd71ae767f5c14b8daf43368bdbbe041896d6 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 23 Sep 2024 11:59:15 +0200 Subject: [PATCH 08/64] Remove unification from LPOComparator; improve and factor out cache usage --- Kernel/KBOComparator.cpp | 30 +------ Kernel/LPOComparator.cpp | 148 +++++++++------------------------- Kernel/OrderingComparator.cpp | 42 ++++++++++ Kernel/OrderingComparator.hpp | 2 + 4 files changed, 85 insertions(+), 137 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index be96da21a..a0a26da44 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -44,35 +44,7 @@ void KBOComparator::expand(Branch& branch, const Stack& cache) continue; } // If we have a variable, we cannot preprocess further. - if (node->lhs.isVar() || node->rhs.isVar()) { - // try cache - bool found = false; - for (const auto& [s,t,r] : cache) { - if (s != node->lhs || t != node->rhs) { - continue; - } - if (r == Ordering::GREATER) { - branch = node->gtBranch; - } else if (r == Ordering::EQUAL) { - branch = node->eqBranch; - } else { - ASS_NEQ(r, Ordering::LESS); - branch = node->incBranch; - } - found = true; - break; - } - if (found) { - continue; - } - // make a fresh copy - branch = Branch(node->lhs, node->rhs); - // TODO we should replace the node here with a fresh one - // TODO check node's refcount? - branch.tag = BranchTag::T_COMPARISON; - branch.n->eqBranch = node->eqBranch; - branch.n->gtBranch = node->gtBranch; - branch.n->incBranch = node->incBranch; + if (tryVarVarCase(branch, cache, node)) { continue; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 539ff0ed3..9326e3c29 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -12,44 +12,12 @@ #include "LPOComparator.hpp" -#include "RobSubstitution.hpp" - namespace Kernel { using namespace std; using namespace Lib; using namespace Shell; -bool unify(TermList tl1, TermList tl2, TermList& orig1, TermList& orig2) -{ - RobSubstitution rsubst; - if (!rsubst.unify(tl1, 0, tl2, 0)) { - return false; - } - Substitution temp; - VariableIterator vit1(orig1); - while (vit1.hasNext()) { - auto v = vit1.next(); - auto vS = rsubst.apply(v,0); - TermList t; - if (vS.isVar() && !temp.findBinding(vS.var(), t)) { - temp.bind(vS.var(), v); - } - } - VariableIterator vit2(orig2); - while (vit2.hasNext()) { - auto v = vit2.next(); - auto vS = rsubst.apply(v,0); - TermList t; - if (vS.isVar() && !temp.findBinding(vS.var(), t)) { - temp.bind(vS.var(), v); - } - } - orig1 = SubstHelper::apply(rsubst.apply(orig1,0), temp); - orig2 = SubstHelper::apply(rsubst.apply(orig2,0), temp); - return true; -} - /** * Implements an @b LPO::majo call via instructions. */ @@ -104,87 +72,51 @@ void LPOComparator::expand(Branch& branch, const Stack& cache) continue; } // If we have a variable, we cannot preprocess further. - if (node->lhs.isVar() || node->rhs.isVar()) { - // try cache - bool found = false; - for (const auto& [s,t,r] : cache) { - if (s != node->lhs || t != node->rhs) { - continue; - } - if (r == Ordering::GREATER) { - branch = node->gtBranch; - } else if (r == Ordering::EQUAL) { - branch = node->eqBranch; - } else { - ASS_NEQ(r, Ordering::LESS); - branch = node->incBranch; - } - found = true; - break; - } - if (found) { - continue; - } - // make a fresh copy - branch = Branch(node->lhs, node->rhs); - // TODO we should replace the node here with a fresh one - // TODO check node's refcount? - branch.tag = BranchTag::T_COMPARISON; - branch.n->eqBranch = node->eqBranch; - branch.n->gtBranch = node->gtBranch; - branch.n->incBranch = node->incBranch; + if (tryVarVarCase(branch, cache, node)) { continue; } - { - auto s = node->lhs.term(); - auto t = node->rhs.term(); - - switch (lpo.comparePrecedences(s, t)) { - case Ordering::EQUAL: { - ASS(s->arity()); // constants cannot be incomparable - - // copies for unification - auto lhs = node->lhs; - auto rhs = node->rhs; - - auto curr = &branch; - - // lexicographic comparisons - for (unsigned i = 0; i < s->arity(); i++) - { - auto s_arg = *lhs.term()->nthArgument(i); - auto t_arg = *rhs.term()->nthArgument(i); - *curr = Branch(s_arg,t_arg); - // greater branch is a majo chain - majoChain(&curr->n->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); - // incomparable branch is an alpha chain - alphaChain(&curr->n->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); - curr = &curr->n->eqBranch; - if (!unify(s_arg,t_arg,lhs,rhs)) { - *curr = node->incBranch; - goto loop_end; - } - } - *curr = node->eqBranch; - break; - } - case Ordering::GREATER: { - ASS(t->arity()); - majoChain(&branch, node->lhs, t, 0, node->gtBranch, node->incBranch); - break; - } - case Ordering::LESS: { - ASS(s->arity()); - alphaChain(&branch, s, 0, node->rhs, node->gtBranch, node->incBranch); - break; - } - default: - ASSERTION_VIOLATION; + auto s = node->lhs.term(); + auto t = node->rhs.term(); + + switch (lpo.comparePrecedences(s, t)) { + case Ordering::EQUAL: { + ASS(s->arity()); // constants cannot be incomparable + + // copies for unification + auto lhs = node->lhs; + auto rhs = node->rhs; + + auto curr = &branch; + + // lexicographic comparisons + for (unsigned i = 0; i < s->arity(); i++) + { + auto s_arg = *lhs.term()->nthArgument(i); + auto t_arg = *rhs.term()->nthArgument(i); + *curr = Branch(s_arg,t_arg); + // greater branch is a majo chain + majoChain(&curr->n->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); + // incomparable branch is an alpha chain + alphaChain(&curr->n->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); + curr = &curr->n->eqBranch; } + *curr = node->eqBranch; + break; + } + case Ordering::GREATER: { + ASS(t->arity()); + majoChain(&branch, node->lhs, t, 0, node->gtBranch, node->incBranch); + break; + } + case Ordering::LESS: { + ASS(s->arity()); + alphaChain(&branch, s, 0, node->rhs, node->gtBranch, node->incBranch); + break; + } + default: + ASSERTION_VIOLATION; } -loop_end: - continue; } } diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 4f9608f99..db63fccda 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -204,4 +204,46 @@ void OrderingComparator::expand(Branch& branch, const Stack& cache) } } +bool OrderingComparator::tryVarVarCase(Branch& branch, const Stack& cache, ComparisonNode* node) +{ + // If we have a variable, we cannot preprocess further. + if (!node->lhs.isVar() && !node->rhs.isVar()) { + return false; + } + // try cache + for (const auto& [s,t,r] : cache) { + if (s == node->lhs && t == node->rhs) { + if (r == Ordering::GREATER) { + branch = node->gtBranch; + } else if (r == Ordering::EQUAL) { + branch = node->eqBranch; + } else { + ASS_EQ(r, Ordering::INCOMPARABLE); + branch = node->incBranch; + } + return true; + } + + if (s == node->rhs && t == node->lhs && r != Ordering::INCOMPARABLE) { + if (r == Ordering::GREATER) { + branch = node->incBranch; + } else { + ASS_EQ(r, Ordering::EQUAL); + branch = node->eqBranch; + } + // Note: since we use isGreater which results + // in INCOMPARABLE when compare would be LESS, + // the INCOMPARABLE result we cannot use here + return true; + } + } + // make a fresh copy + branch = Branch(node->lhs, node->rhs); + branch.tag = BranchTag::T_COMPARISON; + branch.n->eqBranch = node->eqBranch; + branch.n->gtBranch = node->gtBranch; + branch.n->incBranch = node->incBranch; + return true; +} + } \ No newline at end of file diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 8a3a692c5..f04e89302 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -33,10 +33,12 @@ struct OrderingComparator bool check(const SubstApplicator* applicator); void merge(const OrderingComparator& other); + class ComparisonNode; struct Branch; using TermPairRes = std::tuple; virtual void expand(Branch& branch, const Stack& cache); + bool tryVarVarCase(Branch& branch, const Stack& cache, ComparisonNode* origNode); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); From e228d2a144a1f887a255d0968c2580e89316093c Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 24 Sep 2024 09:53:13 +0200 Subject: [PATCH 09/64] Some relatively stable version of ordering comparators/trees that can store result nodes --- Indexing/Index.hpp | 9 +- Inferences/ForwardDemodulation.cpp | 8 +- Inferences/Superposition.cpp | 6 +- Kernel/KBO.cpp | 4 +- Kernel/KBO.hpp | 2 +- Kernel/KBOComparator.cpp | 18 +-- Kernel/KBOComparator.hpp | 6 +- Kernel/LPO.cpp | 4 +- Kernel/LPO.hpp | 2 +- Kernel/LPOComparator.cpp | 20 +-- Kernel/LPOComparator.hpp | 6 +- Kernel/Ordering.cpp | 4 +- Kernel/Ordering.hpp | 4 +- Kernel/OrderingComparator.cpp | 155 ++++++++++-------- Kernel/OrderingComparator.hpp | 41 +++-- Shell/ConditionalRedundancyHandler.cpp | 213 ++++++++++++++----------- Shell/ConditionalRedundancyHandler.hpp | 21 ++- UnitTests/tKBO.cpp | 8 +- 18 files changed, 305 insertions(+), 226 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 284080614..58d33bc5f 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -116,11 +116,16 @@ struct TermLiteralClause /** Custom leaf data for forward demodulation to store the demodulator * left- and right-hand side normalized and cache preorderedness. */ -struct DemodulatorData +struct DemodulatorData : public OrderingComparator::ResultNode { DemodulatorData(TypedTermList term, TermList rhs, Clause* clause, bool preordered, const Ordering& ord) - : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator(ord.createComparator(term, rhs)) + : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator() { + if (!preordered) { + OrderingComparator::Branch root(term, rhs); + root.n->gtBranch = OrderingComparator::Branch(new OrderingComparator::ResultNode()); + comparator = ord.createComparator(&root); + } #if VDEBUG ASS(term.containsAllVariablesOf(rhs)); ASS(!preordered || ord.compare(term,rhs)==Ordering::GREATER); diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 1f7e4d3ce..ccd296a86 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -176,20 +176,24 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if (_precompiledComparison) { if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { +#if DEFINE_ORDERING if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("greater"); } +#endif continue; } +#if DEFINE_ORDERING if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER) { std::cout << qr.data->term << " " << qr.data->rhs << std::endl; std::cout << *qr.data->comparator << std::endl; INVALID_OPERATION("not greater"); } +#endif } else { - if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true)))!=Ordering::GREATER) { + if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER)) { continue; } } @@ -236,7 +240,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* premises = pvi( getSingletonIterator(qr.data->clause)); replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, qr.data->clause)); - ConditionalRedundancyHandler::transfer(cl, replacement); + // ConditionalRedundancyHandler::transfer(cl, replacement); return true; } } diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index 6ffc66577..1f2042cfe 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -559,9 +559,9 @@ Clause* Superposition::performSuperposition( env.proofExtra->insert(clause,extra); } - if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { - condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); - } + // if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { + // condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); + // } return clause; } diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index eeda27268..4908d6390 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -874,9 +874,9 @@ Ordering::Result KBO::isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const return res; } -OrderingComparatorUP KBO::createComparator(TermList lhs, TermList rhs) const +OrderingComparatorUP KBO::createComparator(void* root) const { - return make_unique(*this, lhs, rhs); + return make_unique(*this, root); } int KBO::symbolWeight(const Term* t) const diff --git a/Kernel/KBO.hpp b/Kernel/KBO.hpp index 134120a66..b5d03c12b 100644 --- a/Kernel/KBO.hpp +++ b/Kernel/KBO.hpp @@ -158,7 +158,7 @@ class KBO Result compare(AppliedTerm t1, AppliedTerm t2) const override; Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const override; - OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const override; + OrderingComparatorUP createComparator(void* root) const override; protected: unsigned computeWeight(AppliedTerm tt) const; diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index a0a26da44..7e29efb93 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,13 +21,13 @@ using namespace std; using namespace Lib; using namespace Shell; -void KBOComparator::expand(Branch& branch, const Stack& cache) +void KBOComparator::expand() { const auto& kbo = static_cast(_ord); - while (branch.tag == BranchTag::T_UNKNOWN) + while (_curr->tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node - Branch nodeHolder = branch; + Branch nodeHolder = *_curr; auto node = static_cast(nodeHolder.n.ptr()); // Use compare here to filter out as many @@ -35,16 +35,16 @@ void KBOComparator::expand(Branch& branch, const Stack& cache) auto comp = kbo.compare(node->lhs,node->rhs); if (comp != Ordering::INCOMPARABLE) { if (comp == Ordering::LESS) { - branch = node->incBranch; + *_curr = node->incBranch; } else if (comp == Ordering::GREATER) { - branch = node->gtBranch; + *_curr = node->gtBranch; } else { - branch = node->eqBranch; + *_curr = node->eqBranch; } continue; } // If we have a variable, we cannot preprocess further. - if (tryVarVarCase(branch, cache, node)) { + if (tryExpandVarCase(node)) { continue; } @@ -78,7 +78,7 @@ void KBOComparator::expand(Branch& branch, const Stack& cache) state = nullptr; #endif - auto curr = &branch; + auto curr = _curr; // if the condition below does not hold, the weight/var balances are satisfied if (w < 0 || varInbalance) { @@ -88,7 +88,7 @@ void KBOComparator::expand(Branch& branch, const Stack& cache) *curr = Branch(w, std::move(nonzeros)); curr->n->gtBranch = node->gtBranch; curr->n->incBranch = node->incBranch; - curr = &branch.n->eqBranch; + curr = &curr->n->eqBranch; } auto lhst = node->lhs.term(); diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 49a6c1601..bd6942f7c 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -33,10 +33,10 @@ class KBOComparator : public OrderingComparator { public: - KBOComparator(const Ordering& ord, TermList lhs, TermList rhs) - : OrderingComparator(ord, lhs, rhs) {} + KBOComparator(const Ordering& ord, void* root) + : OrderingComparator(ord, root) {} - void expand(Branch& branch, const Stack& cache) override; + void expand() override; }; } diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index 60fd98038..87043fb95 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -247,9 +247,9 @@ Ordering::Result LPO::majo(AppliedTerm s, AppliedTerm t, const TermList* tl, uns return GREATER; } -OrderingComparatorUP LPO::createComparator(TermList lhs, TermList rhs) const +OrderingComparatorUP LPO::createComparator(void* root) const { - return make_unique(*this, lhs, rhs); + return make_unique(*this, root); } void LPO::showConcrete(ostream&) const diff --git a/Kernel/LPO.hpp b/Kernel/LPO.hpp index bb919923c..03224e9b9 100644 --- a/Kernel/LPO.hpp +++ b/Kernel/LPO.hpp @@ -48,7 +48,7 @@ class LPO Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm tl1, AppliedTerm tl2) const override; Result isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const override; - OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const override; + OrderingComparatorUP createComparator(void* root) const override; void showConcrete(std::ostream&) const override; diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 9326e3c29..0fd14f76d 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -48,13 +48,13 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = fail; } -void LPOComparator::expand(Branch& branch, const Stack& cache) +void LPOComparator::expand() { const auto& lpo = static_cast(_ord); - while (branch.tag == BranchTag::T_UNKNOWN) + while (_curr->tag == BranchTag::T_UNKNOWN) { // take temporary ownership of node - Branch nodeHolder = branch; + Branch nodeHolder = *_curr; auto node = static_cast(nodeHolder.n.ptr()); ASS(node); @@ -63,16 +63,16 @@ void LPOComparator::expand(Branch& branch, const Stack& cache) auto comp = lpo.compare(node->lhs,node->rhs); if (comp != Ordering::INCOMPARABLE) { if (comp == Ordering::LESS) { - branch = node->incBranch; + *_curr = node->incBranch; } else if (comp == Ordering::GREATER) { - branch = node->gtBranch; + *_curr = node->gtBranch; } else { - branch = node->eqBranch; + *_curr = node->eqBranch; } continue; } // If we have a variable, we cannot preprocess further. - if (tryVarVarCase(branch, cache, node)) { + if (tryExpandVarCase(node)) { continue; } @@ -87,7 +87,7 @@ void LPOComparator::expand(Branch& branch, const Stack& cache) auto lhs = node->lhs; auto rhs = node->rhs; - auto curr = &branch; + auto curr = _curr; // lexicographic comparisons for (unsigned i = 0; i < s->arity(); i++) @@ -106,12 +106,12 @@ void LPOComparator::expand(Branch& branch, const Stack& cache) } case Ordering::GREATER: { ASS(t->arity()); - majoChain(&branch, node->lhs, t, 0, node->gtBranch, node->incBranch); + majoChain(_curr, node->lhs, t, 0, node->gtBranch, node->incBranch); break; } case Ordering::LESS: { ASS(s->arity()); - alphaChain(&branch, s, 0, node->rhs, node->gtBranch, node->incBranch); + alphaChain(_curr, s, 0, node->rhs, node->gtBranch, node->incBranch); break; } default: diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index 26fae948d..bcd1ad4f7 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -24,10 +24,10 @@ class LPOComparator : public OrderingComparator { public: - LPOComparator(const Ordering& ord, TermList lhs, TermList rhs) - : OrderingComparator(ord, lhs, rhs) {} + LPOComparator(const Ordering& ord, void* root) + : OrderingComparator(ord, root) {} - void expand(Branch& branch, const Stack& cache) override; + void expand() override; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); diff --git a/Kernel/Ordering.cpp b/Kernel/Ordering.cpp index d3873d763..43fecdb7c 100644 --- a/Kernel/Ordering.cpp +++ b/Kernel/Ordering.cpp @@ -210,9 +210,9 @@ Ordering::Result Ordering::getEqualityArgumentOrder(Literal* eq) const return res; } -OrderingComparatorUP Ordering::createComparator(TermList lhs, TermList rhs) const +OrderingComparatorUP Ordering::createComparator(void* root) const { - return std::make_unique(*this, lhs, rhs); + return std::make_unique(*this, root); } ////////////////////////////////////////////////// diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index a49b34bb0..d48c6cda6 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -29,6 +29,8 @@ #include "Lib/Portability.hpp" #include "Kernel/SubstHelper.hpp" +#define DEBUG_ORDERING 0 + namespace Kernel { using namespace Shell; @@ -74,7 +76,7 @@ class Ordering /** Creates optimised object to check that @b lhs is greater than @b rhs. * @see OrderingComparator. */ - virtual OrderingComparatorUP createComparator(TermList lhs, TermList rhs) const; + virtual OrderingComparatorUP createComparator(void* root) const; virtual void show(std::ostream& out) const = 0; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index db63fccda..64c98b622 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -24,11 +24,8 @@ namespace Kernel { std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) { switch (t) { - case OrderingComparator::BranchTag::T_NOT_GREATER: - out << "!>"; - break; - case OrderingComparator::BranchTag::T_GREATER: - out << ">"; + case OrderingComparator::BranchTag::T_RESULT: + out << "r"; break; case OrderingComparator::BranchTag::T_COMPARISON: out << "$"; @@ -43,24 +40,30 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& return out; } -std::ostream& operator<<(std::ostream& str, const OrderingComparator::Branch& branch) +std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& branch) { - str << branch.tag << " "; - if (branch.n) { - if (branch.tag==OrderingComparator::BranchTag::T_WEIGHT) { + out << branch.tag << " "; + switch (branch.tag) { + case OrderingComparator::BranchTag::T_RESULT: { + out << branch.n.ptr(); + break; + } + case OrderingComparator::BranchTag::T_WEIGHT: { auto n = static_cast(branch.n.ptr()); - str << n->w << " "; + out << n->w << " "; for (const auto& [var, coeff] : n->varCoeffPairs) { - str << "X" << var << " " << coeff << " "; + out << "X" << var << " " << coeff << " "; } - } else { + break; + } + case OrderingComparator::BranchTag::T_COMPARISON: + case OrderingComparator::BranchTag::T_UNKNOWN: { auto n = static_cast(branch.n.ptr()); - str << n->lhs << " " << n->rhs; + out << n->lhs << " " << n->rhs; + break; } - } else { - str << "null"; } - return str; + return out; } std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) @@ -77,9 +80,14 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } str << *kv.first << std::endl; if (kv.first->n) { - todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + if (kv.first->tag == OrderingComparator::BranchTag::T_RESULT) { + auto n = static_cast(kv.first->n.ptr()); + todo.push(std::make_pair(&n->alternative,kv.second+1)); + } else { + todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + } } } return str; @@ -87,30 +95,32 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) OrderingComparator::~OrderingComparator() = default; -bool OrderingComparator::check(const SubstApplicator* applicator) +OrderingComparator::ResultNode* OrderingComparator::next(const SubstApplicator* applicator) { - static Stack cache; - cache.reset(); - auto curr = &_root; - - while (curr->n) { - expand(*curr, cache); - if (!curr->n) { - break; + ASS(_curr); + while (_curr->n) { + expand(); + if (_curr->tag == BranchTag::T_RESULT) { + if (_curr) { + auto node = static_cast(_curr->n.ptr()); + _curr = &node->alternative; + return node; + } + return nullptr; } - ASS(curr->n); + Ordering::Result comp = Ordering::INCOMPARABLE; - if (curr->tag == BranchTag::T_COMPARISON) { + if (_curr->tag == BranchTag::T_COMPARISON) { - auto node = static_cast(curr->n.ptr()); + auto node = static_cast(_curr->n.ptr()); comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); - cache.push({ node->lhs, node->rhs, comp }); + _cache.push({ node->lhs, node->rhs, comp }); } else { - ASS(curr->tag == BranchTag::T_WEIGHT); + ASS(_curr->tag == BranchTag::T_WEIGHT); const auto& kbo = static_cast(_ord); - auto node = static_cast(curr->n.ptr()); + auto node = static_cast(_curr->n.ptr()); auto weight = node->w; ZIArray varDiffs; for (const auto& [var, coeff] : node->varCoeffPairs) { @@ -142,34 +152,35 @@ bool OrderingComparator::check(const SubstApplicator* applicator) } } loop_end: - curr = &curr->n->getBranch(comp); + _curr = &_curr->n->getBranch(comp); } - return curr->tag == BranchTag::T_GREATER; + return nullptr; } -void OrderingComparator::merge(const OrderingComparator& other) +void OrderingComparator::addAlternative(const Branch& branch) { - ASS(other._root.tag == BranchTag::T_UNKNOWN); + ASS(branch.tag == BranchTag::T_UNKNOWN); // branch should be unexpanded static unsigned ts = 0; ts++; - Stack> todo; + static Stack> todo; + todo.reset(); - auto pushBranches = [&todo](Branch* b, const Branch& other) { + auto pushBranches = [](Branch* b, const Branch& other) { // if other branch is unsuccessful, do nothing - if (b->tag == BranchTag::T_GREATER || other.tag == BranchTag::T_NOT_GREATER) { + if (other.tag == BranchTag::T_RESULT && !other.n) { return; } // if this branch is unsuccessful, replace this with other - if (b->tag == BranchTag::T_NOT_GREATER || other.tag == BranchTag::T_GREATER) { + if (b->tag == BranchTag::T_RESULT && !b->n) { *b = other; return; } todo.push(std::make_pair(b,other)); }; - pushBranches(&_root, other._root); + pushBranches(&_root, branch); while (todo.isNonEmpty()) { auto [currB, otherB] = todo.pop(); @@ -180,56 +191,64 @@ void OrderingComparator::merge(const OrderingComparator& other) continue; } currB->n->setTs(ts); - if (currB->tag == BranchTag::T_UNKNOWN && currB->tag != BranchTag::T_COMPARISON) { - // both must be comparison nodes - auto n = static_cast(currB->n.ptr()); - auto o = static_cast(otherB.n.ptr()); - if (n->lhs == o->lhs && n->rhs == o->rhs) { - pushBranches(&currB->n->eqBranch, otherB.n->eqBranch); - pushBranches(&currB->n->gtBranch, otherB.n->gtBranch); - pushBranches(&currB->n->incBranch, otherB.n->incBranch); - continue; - } + if (currB->tag == BranchTag::T_RESULT) { + auto n = static_cast(currB->n.ptr()); + pushBranches(&n->alternative, otherB); + continue; } + // TODO: results should be only pushed down + // in this case onto successful branches + // + // if (currB->tag == BranchTag::T_UNKNOWN && currB->tag != BranchTag::T_COMPARISON) { + // // both must be comparison nodes + // auto n = static_cast(currB->n.ptr()); + // auto o = static_cast(otherB.n.ptr()); + // if (n->lhs == o->lhs && n->rhs == o->rhs) { + // pushBranches(&currB->n->eqBranch, otherB.n->eqBranch); + // pushBranches(&currB->n->gtBranch, otherB.n->gtBranch); + // pushBranches(&currB->n->incBranch, otherB.n->incBranch); + // continue; + // } + // } pushBranches(&currB->n->eqBranch, otherB); pushBranches(&currB->n->gtBranch, otherB); pushBranches(&currB->n->incBranch, otherB); } } -void OrderingComparator::expand(Branch& branch, const Stack& cache) +void OrderingComparator::expand() { - if (branch.tag == BranchTag::T_UNKNOWN) { - branch.tag = BranchTag::T_COMPARISON; + if (_curr->tag == BranchTag::T_UNKNOWN) { + _curr->tag = BranchTag::T_COMPARISON; } } -bool OrderingComparator::tryVarVarCase(Branch& branch, const Stack& cache, ComparisonNode* node) +bool OrderingComparator::tryExpandVarCase(ComparisonNode* node) { // If we have a variable, we cannot preprocess further. if (!node->lhs.isVar() && !node->rhs.isVar()) { return false; } // try cache - for (const auto& [s,t,r] : cache) { + for (const auto& [s,t,r] : _cache) { if (s == node->lhs && t == node->rhs) { if (r == Ordering::GREATER) { - branch = node->gtBranch; + *_curr = node->gtBranch; } else if (r == Ordering::EQUAL) { - branch = node->eqBranch; + *_curr = node->eqBranch; } else { ASS_EQ(r, Ordering::INCOMPARABLE); - branch = node->incBranch; + *_curr = node->incBranch; } return true; } if (s == node->rhs && t == node->lhs && r != Ordering::INCOMPARABLE) { if (r == Ordering::GREATER) { - branch = node->incBranch; + *_curr = node->incBranch; } else { ASS_EQ(r, Ordering::EQUAL); - branch = node->eqBranch; + *_curr = node->eqBranch; } // Note: since we use isGreater which results // in INCOMPARABLE when compare would be LESS, @@ -238,11 +257,11 @@ bool OrderingComparator::tryVarVarCase(Branch& branch, const Stack& } } // make a fresh copy - branch = Branch(node->lhs, node->rhs); - branch.tag = BranchTag::T_COMPARISON; - branch.n->eqBranch = node->eqBranch; - branch.n->gtBranch = node->gtBranch; - branch.n->incBranch = node->incBranch; + *_curr = Branch(node->lhs, node->rhs); + _curr->tag = BranchTag::T_COMPARISON; + _curr->n->eqBranch = node->eqBranch; + _curr->n->gtBranch = node->gtBranch; + _curr->n->incBranch = node->incBranch; return true; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index f04e89302..eee6ca7ab 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -28,35 +28,44 @@ namespace Kernel { */ struct OrderingComparator { - OrderingComparator(const Ordering& ord, TermList lhs, TermList rhs) : _ord(ord), _root(lhs, rhs) {} + struct Branch; + struct Node; + struct ResultNode; + class ComparisonNode; + + OrderingComparator(const Ordering& ord, void* root) : _ord(ord), + _root(*static_cast(root)), _curr(&_root), _cache() {} virtual ~OrderingComparator(); - bool check(const SubstApplicator* applicator); - void merge(const OrderingComparator& other); - class ComparisonNode; - struct Branch; + void reset() { _curr = &_root; _cache.reset(); } + bool check(const SubstApplicator* applicator) { + reset(); + return next(applicator)!=nullptr; + } + + ResultNode* next(const SubstApplicator* applicator); + void addAlternative(const Branch& branch); + using TermPairRes = std::tuple; - virtual void expand(Branch& branch, const Stack& cache); - bool tryVarVarCase(Branch& branch, const Stack& cache, ComparisonNode* origNode); + virtual void expand(); + bool tryExpandVarCase(ComparisonNode* origNode); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); enum class BranchTag : uint8_t { - T_GREATER, - T_NOT_GREATER, + T_RESULT, T_COMPARISON, T_WEIGHT, T_UNKNOWN, }; - struct Node; - struct Branch { BranchTag tag; SmartPtr n; - explicit Branch(BranchTag t) : tag(t) { ASS(t==BranchTag::T_GREATER || t==BranchTag::T_NOT_GREATER); } + Branch() : tag(BranchTag::T_RESULT) {} + explicit Branch(ResultNode* r) : tag(BranchTag::T_RESULT), n(r) {} explicit Branch(TermList lhs, TermList rhs) : tag(BranchTag::T_UNKNOWN), n(new ComparisonNode(lhs, rhs)) {} explicit Branch(int w, Stack>&& varCoeffPairs) @@ -66,7 +75,7 @@ struct OrderingComparator friend std::ostream& operator<<(std::ostream& out, const Branch& branch); struct Node { - Node() : eqBranch(BranchTag::T_NOT_GREATER), gtBranch(BranchTag::T_GREATER), incBranch(BranchTag::T_NOT_GREATER), ts(0) {} + virtual ~Node() = default; auto& getBranch(Ordering::Result r) { switch (r) { @@ -90,6 +99,10 @@ struct OrderingComparator unsigned ts; }; + struct ResultNode : public Node { + Branch alternative; + }; + class ComparisonNode : public Node { ComparisonNode(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs) {} @@ -117,6 +130,8 @@ struct OrderingComparator const Ordering& _ord; Branch _root; + Branch* _curr; + Stack _cache; }; } // namespace Kernel diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index f76a33ec7..afbd0344e 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -49,29 +49,26 @@ bool checkVars(const TermStack& ts, T s) return true; } +std::ostream& operator<<(std::ostream& out, const OrderingConstraint& con) +{ + return out << con.lhs << " " << con.rhs; +} + std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) { if (!e.active) { str << "not active"; } else { str << *e.splits << "; " << *e.lits << "; "; +#if DEBUG_ORDERING iterTraits(e.ordCons.iter()).forEach([&str](const OrderingConstraint& con) { - if (con.comp) { - str << *con.comp; - } else { - str << con.lhs.toString() << " > " << con.rhs.toString(); - } + str << con; }); +#endif } return str; } -void ensureComparator(const Ordering* ord, OrderingConstraint& cons) { - if (!cons.comp) { - cons.comp = ord->createComparator(cons.lhs, cons.rhs); - } -} - class ConditionalRedundancyHandler::ConstraintIndex : public CodeTree { @@ -101,7 +98,8 @@ class ConditionalRedundancyHandler::ConstraintIndex OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) { auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + auto e = createEntry(ts, splitter, std::move(ordCons), lits, splits); + return insert(ord, ts, e.first, e.second); } bool checkAndInsert(const Ordering* ord, ResultSubstitution* subst, bool result, bool doInsert, Splitter* splitter, @@ -117,7 +115,8 @@ class ConditionalRedundancyHandler::ConstraintIndex return false; } if (doInsert) { - return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + auto e = createEntry(ts, splitter, std::move(ordCons), lits, splits); + return insert(ord, ts, e.first, e.second); } return true; } @@ -127,41 +126,24 @@ class ConditionalRedundancyHandler::ConstraintIndex Clause* _cl; #endif - bool insert(const Ordering* ord, Entries* entries, ConditionalRedundancyEntry* ptr) + bool insert(Entries* entries, const OrderingComparator::Branch& root, ConditionalRedundancyEntry* ptr) { ASS(ptr->active); - auto numCons = ptr->lits->size() + ptr->splits->size() + ptr->ordCons.size() + ptr->eqCons.size(); - if (ptr->ordCons.size()==1) { - for (unsigned i = 0; i < entries->size();) { - const auto& e = (*entries)[i]; - if (e->active && e->lits->isEmpty() && e->splits->isEmpty() && e->ordCons.size()==1) { - ensureComparator(ord, e->ordCons[0]); - ensureComparator(ord, ptr->ordCons[0]); + ASS(entries->comparator); - e->ordCons[0].comp->merge(std::move(*ptr->ordCons[0].comp.get())); - return true; - } - i++; - } - } - entries->push(ptr); +#if DEBUG_ORDERING + entries->entries.push(ptr); +#endif + entries->comparator->addAlternative(root); return true; } - bool insert(const Ordering* ord, const TermStack& ts, ConditionalRedundancyEntry* ptr) + bool insert(const Ordering* ord, const TermStack& ts, const OrderingComparator::Branch& root, ConditionalRedundancyEntry* ptr) { if (lastRenamingEntry) { // there is an entry up to renaming already, insert it here - if (insert(ord, lastRenamingEntry, ptr)) { - // cout << "insert2 " << *_cl << endl; - // cout << varSortsToString(_varSorts) << endl; - // cout << *this << endl << endl; - return true; - } - // cout << "no insert " << *_cl << endl; - // cout << varSortsToString(_varSorts) << endl; - return false; + return insert(lastRenamingEntry, root, ptr); } CodeStack code; @@ -182,14 +164,13 @@ class ConditionalRedundancyHandler::ConstraintIndex ptr->eqCons = compiler.eqCons; compiler.updateCodeTree(this); - // just put anything non-null in there to get a valid success auto es = new Entries(); - es->push(ptr); +#if DEBUG_ORDERING + es->entries.push(ptr); +#endif + es->comparator = ord->createComparator(const_cast(&root)); code.push(CodeOp::getSuccess(es)); incorporate(code); - // cout << "insert " << *_cl << endl; - // cout << varSortsToString(_varSorts) << endl; - // cout << *this << endl << endl; return true; } @@ -213,55 +194,85 @@ class ConditionalRedundancyHandler::ConstraintIndex lastRenamingEntry = es; } - // TODO indent - for (const auto& e : *es) { + ASS(es->comparator); + es->comparator->reset(); + ConditionalRedundancyEntry* e = nullptr; + while ((e = static_cast(es->comparator->next(&applicator)))) { - if (!e->active) { - continue; - } + if (!e->active) { + continue; + } - // auto eqs_ok = iterTraits(e->eqCons.iter()).all([&applicator](const auto& kv) { - // return applicator(kv.first) == applicator(kv.second); - // }); - // if (!eqs_ok) { - // env.statistics->structInduction++; - // continue; - // } + // check AVATAR constraints + if (!e->splits->isSubsetOf(splits)) { + continue; + } - // check AVATAR constraints - if (!e->splits->isSubsetOf(splits)) { - continue; - } + // check literal conditions + auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { + return lits->member(SubstHelper::apply(lit,applicator)); + }); + if (!subsetof) { + continue; + } - // check literal conditions - auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { - return lits->member(SubstHelper::apply(lit,applicator)); - }); - if (!subsetof) { - continue; - } +#if DEBUG_ORDERING + auto ordCons_crosscheck = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { + return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==Ordering::GREATER; + }); + if (!ordCons_crosscheck) { + cout << e << endl; + cout << *e << endl; + cout << *es->comparator << endl; + INVALID_OPERATION("nope"); + } +#endif - // check ordering constraints - auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - ensureComparator(ord, ordCon); - return ordCon.comp->check(&applicator); - }); - if (!ordCons_ok) { - continue; + // collect statistics + // TODO fix ordering constraint stats +#if DEBUG_ORDERING + if (e->ordCons.isNonEmpty()) { + env.statistics->skippedInferencesDueToOrderingConstraints++; + } +#endif + if (!e->lits->isEmpty()) { + env.statistics->skippedInferencesDueToLiteralConstraints++; + } + if (!e->splits->isEmpty()) { + env.statistics->skippedInferencesDueToAvatarConstraints++; + } + return true; } +#if DEBUG_ORDERING + for (const auto& e : es->entries) { + if (!e->active) { + continue; + } - // collect statistics - if (e->ordCons.isNonEmpty()) { - env.statistics->skippedInferencesDueToOrderingConstraints++; - } - if (!e->lits->isEmpty()) { - env.statistics->skippedInferencesDueToLiteralConstraints++; - } - if (!e->splits->isEmpty()) { - env.statistics->skippedInferencesDueToAvatarConstraints++; - } - return true; + // check AVATAR constraints + if (!e->splits->isSubsetOf(splits)) { + continue; + } + + // check literal conditions + auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { + return lits->member(SubstHelper::apply(lit,applicator)); + }); + if (!subsetof) { + continue; + } + + // check ordering constraints + auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { + return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==Ordering::GREATER; + }); + if (!ordCons_ok) { + continue; + } + + INVALID_OPERATION("nope"); } +#endif } matcher.reset(); @@ -282,7 +293,7 @@ class ConditionalRedundancyHandler::ConstraintIndex DHMap _varSorts; - ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const + std::pair createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const { auto e = new ConditionalRedundancyEntry(); Renaming r; @@ -302,14 +313,29 @@ class ConditionalRedundancyHandler::ConstraintIndex ordCon.lhs = r.apply(ordCon.lhs); ordCon.rhs = r.apply(ordCon.rhs); } + + OrderingComparator::Branch root; + auto curr = &root; + if (ordCons.isNonEmpty()) { + *curr = OrderingComparator::Branch(ordCons[0].lhs, ordCons[0].rhs); + curr = &curr->n->gtBranch; + for (unsigned i = 1; i < ordCons.size(); i++) { + auto& ordCon = ordCons[i]; + *curr = OrderingComparator::Branch(ordCon.lhs, ordCon.rhs); + curr = &curr->n->gtBranch; + } + } + *curr = OrderingComparator::Branch(e); +#if DEBUG_ORDERING e->ordCons = std::move(ordCons); +#endif #if VDEBUG lits->iter().forEach([&ts](Literal* lit) { ASS(checkVars(ts,lit)); }); #endif - + e->lits = LiteralSet::getFromIterator(lits->iter().map([&r](Literal* lit) { return r.apply(lit); })); @@ -321,7 +347,7 @@ class ConditionalRedundancyHandler::ConstraintIndex splitter->addConditionalRedundancyEntry(splits, e); } - return e; + return { root, e }; } struct SubstMatcher @@ -363,17 +389,13 @@ class ConditionalRedundancyHandler::ConstraintIndex static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { - iterTraits(op->getSuccessResult()->iter()) - .forEach([](ConditionalRedundancyEntry* e) { e->release(); }); + delete op->getSuccessResult(); } } std::string leafToString(const CodeOp* success) const override { std::stringstream str; - iterTraits(success->getSuccessResult()->iter()) - .forEach([&str](ConditionalRedundancyEntry* e) { - str << *e << ";; "; - }); + // TODO return str.str(); } @@ -424,7 +446,8 @@ void ConditionalRedundancyHandler::destroyClauseData(Clause* cl) void ConditionalRedundancyHandler::checkEquations(Clause* cl) const { - cl->iterLits().forEach([cl](Literal* lit){ + // TODO return if not enabled + cl->iterLits().forEach([cl,this](Literal* lit){ if (!lit->isEquality() || lit->isNegative()) { return; } @@ -436,7 +459,7 @@ void ConditionalRedundancyHandler::checkEquations(Clause* cl) const } auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(nullptr, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); }); } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 2086baaae..86ab6aa08 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -67,9 +67,12 @@ struct OrderingConstraint { using OrderingConstraints = Stack; -struct ConditionalRedundancyEntry { +struct ConditionalRedundancyEntry : OrderingComparator::ResultNode +{ Stack> eqCons; +#if DEBUG_ORDERING OrderingConstraints ordCons; +#endif const LiteralSet* lits; SplitSet* splits; bool active = true; @@ -93,7 +96,12 @@ struct ConditionalRedundancyEntry { } }; -using Entries = Stack; +struct Entries { +#if DEBUG_ORDERING + Stack entries; +#endif + OrderingComparatorUP comparator; +}; class ConditionalRedundancyHandler { @@ -101,6 +109,7 @@ class ConditionalRedundancyHandler static ConditionalRedundancyHandler* create(const Options& opts, const Ordering* ord, Splitter* splitter); static void destroyClauseData(Clause* cl); + ConditionalRedundancyHandler(const Ordering* ord) : _ord(ord) {} virtual ~ConditionalRedundancyHandler() = default; virtual bool checkSuperposition( @@ -128,6 +137,8 @@ class ConditionalRedundancyHandler // this contains the redundancy information associated with each clause static DHMap clauseData; + + const Ordering* _ord; }; template @@ -136,9 +147,10 @@ class ConditionalRedundancyHandlerImpl { public: ConditionalRedundancyHandlerImpl(const Options& opts, const Ordering* ord, Splitter* splitter) - : _redundancyCheck(opts.demodulationRedundancyCheck() != Options::DemodulationRedundancyCheck::OFF), + : ConditionalRedundancyHandler(ord), + _redundancyCheck(opts.demodulationRedundancyCheck() != Options::DemodulationRedundancyCheck::OFF), _encompassing(opts.demodulationRedundancyCheck() == Options::DemodulationRedundancyCheck::ENCOMPASS), - _ord(ord), _splitter(splitter) {} + _splitter(splitter) {} /** Returns false if superposition should be skipped. */ bool checkSuperposition( @@ -164,7 +176,6 @@ class ConditionalRedundancyHandlerImpl private: bool _redundancyCheck; bool _encompassing; - const Ordering* _ord; Splitter* _splitter; }; diff --git a/UnitTests/tKBO.cpp b/UnitTests/tKBO.cpp index 77ae85eae..353c6b0fc 100644 --- a/UnitTests/tKBO.cpp +++ b/UnitTests/tKBO.cpp @@ -382,8 +382,8 @@ TEST_FUN(kbo_test23) { // isGreater tests bool isGreaterSymmetric(const KBO& ord, TermList t1, TermList t2) { - return ord.isGreater(AppliedTerm(t1),AppliedTerm(t2)) - && !ord.isGreater(AppliedTerm(t2),AppliedTerm(t1)); + return ord.isGreaterOrEq(AppliedTerm(t1),AppliedTerm(t2))==Ordering::GREATER + && ord.isGreaterOrEq(AppliedTerm(t2),AppliedTerm(t1))!=Ordering::GREATER; } TEST_FUN(kbo_isGreater_test01) { @@ -430,8 +430,8 @@ TEST_FUN(kbo_isGreater_test04) { auto ord = kbo(weights(make_pair(f, 10u)), weights()); - ASS(!ord.isGreater(AppliedTerm(f(x)), AppliedTerm(g(g(g(g(g(y)))))))); - ASS(!ord.isGreater(AppliedTerm(g(g(g(g(g(y)))))), AppliedTerm(f(x)))); + ASS(ord.isGreaterOrEq(AppliedTerm(f(x)), AppliedTerm(g(g(g(g(g(y)))))))!=Ordering::GREATER); + ASS(ord.isGreaterOrEq(AppliedTerm(g(g(g(g(g(y)))))), AppliedTerm(f(x)))!=Ordering::GREATER); } TEST_FUN(kbo_isGreater_test05) { From fca0d229488d0fa4a880bf8fa3ce5d0e872bfa99 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 24 Sep 2024 16:00:33 +0200 Subject: [PATCH 10/64] Use ordering tree in demodulation, refactor interface --- Indexing/CodeTreeInterfaces.cpp | 2 +- Indexing/Index.hpp | 68 ++++++++++-- Indexing/IndexManager.cpp | 2 +- Indexing/TermCodeTree.cpp | 49 +++++---- Indexing/TermIndex.cpp | 3 +- Indexing/TermIndex.hpp | 4 +- Inferences/ForwardDemodulation.cpp | 145 ++++++++++++++----------- Kernel/KBO.cpp | 4 +- Kernel/KBO.hpp | 2 +- Kernel/KBOComparator.cpp | 10 +- Kernel/KBOComparator.hpp | 4 +- Kernel/LPO.cpp | 4 +- Kernel/LPO.hpp | 2 +- Kernel/LPOComparator.cpp | 10 +- Kernel/LPOComparator.hpp | 4 +- Kernel/Ordering.cpp | 4 +- Kernel/Ordering.hpp | 11 +- Kernel/OrderingComparator.cpp | 79 +++++++++----- Kernel/OrderingComparator.hpp | 39 ++++--- Shell/ConditionalRedundancyHandler.cpp | 70 ++++-------- Shell/ConditionalRedundancyHandler.hpp | 15 +-- 21 files changed, 316 insertions(+), 215 deletions(-) diff --git a/Indexing/CodeTreeInterfaces.cpp b/Indexing/CodeTreeInterfaces.cpp index 77c3a0ae5..04e357d72 100644 --- a/Indexing/CodeTreeInterfaces.cpp +++ b/Indexing/CodeTreeInterfaces.cpp @@ -180,7 +180,7 @@ bool CodeTreeTIS::generalizationExists(TermList t) } template class CodeTreeTIS; -template class CodeTreeTIS; +template class CodeTreeTIS; ///////////////// CodeTreeSubsumptionIndex ////////////////////// diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 58d33bc5f..b426e9672 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -106,6 +106,12 @@ struct TermLiteralClause IMPL_COMPARISONS_FROM_TUPLE(TermLiteralClause) + bool insert(const TermLiteralClause& other) { return false; } + + bool remove(const TermLiteralClause& other) { return *this==other; } + + bool canBeDeleted() const { return true; } + friend std::ostream& operator<<(std::ostream& out, TermLiteralClause const& self) { return out << "(" << self.term << ", " @@ -116,16 +122,11 @@ struct TermLiteralClause /** Custom leaf data for forward demodulation to store the demodulator * left- and right-hand side normalized and cache preorderedness. */ -struct DemodulatorData : public OrderingComparator::ResultNode +struct DemodulatorData { DemodulatorData(TypedTermList term, TermList rhs, Clause* clause, bool preordered, const Ordering& ord) - : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator() + : term(term), rhs(rhs), clause(clause), preordered(preordered) { - if (!preordered) { - OrderingComparator::Branch root(term, rhs); - root.n->gtBranch = OrderingComparator::Branch(new OrderingComparator::ResultNode()); - comparator = ord.createComparator(&root); - } #if VDEBUG ASS(term.containsAllVariablesOf(rhs)); ASS(!preordered || ord.compare(term,rhs)==Ordering::GREATER); @@ -141,7 +142,6 @@ struct DemodulatorData : public OrderingComparator::ResultNode TermList rhs; Clause* clause; bool preordered; // whether term > rhs - OrderingComparatorUP comparator; // owned comparator for whether term > rhs TypedTermList const& key() const { return term; } @@ -154,12 +154,62 @@ struct DemodulatorData : public OrderingComparator::ResultNode { return out << "(" << self.term << " = " << self.rhs << ", cl " << outputPtr(self.clause) << ")"; } }; +struct DemodulatorDataContainer { + TypedTermList term; + Stack dds; + OrderingComparatorUP comparator; + + DemodulatorDataContainer(DemodulatorData&& dd, const Ordering& ord) : term(dd.term) { + Stack ordCons; + if (!dd.preordered) { + ordCons.push({ dd.term, dd.rhs, Ordering::GREATER }); + } + auto ptr = new DemodulatorData(std::move(dd)); + dds.push(ptr); + comparator = ord.createComparator(ordCons, ptr); + } + + bool insert(const DemodulatorDataContainer& other) { + if (term!=other.term) { + return false; + } + dds.loadFromIterator(other.dds.iter()); + comparator->addAlternative(*other.comparator.get()); + return true; + } + + bool remove(const DemodulatorDataContainer& other) { + if (term!=other.term) { + return false; + } + iterTraits(other.dds.iter()).forEach([this](DemodulatorData* toRemove){ + decltype(dds)::DelIterator it(dds); + while (it.hasNext()) { + auto curr = it.next(); + if (*curr==*toRemove) { + // TODO this is not good until we can + // actually remove the node from the tree + // + // delete curr; + it.del(); + } + } + }); + return true; + } + + bool canBeDeleted() const { return dds.isEmpty(); } + + friend std::ostream& operator<<(std::ostream& out, DemodulatorDataContainer const& self) + { return out << "TODO"; } +}; + template struct is_indexed_data_normalized { static constexpr bool value = false; }; template<> -struct is_indexed_data_normalized +struct is_indexed_data_normalized { static constexpr bool value = true; }; /** diff --git a/Indexing/IndexManager.cpp b/Indexing/IndexManager.cpp index fea6be8e7..aa4dd8f48 100644 --- a/Indexing/IndexManager.cpp +++ b/Indexing/IndexManager.cpp @@ -186,7 +186,7 @@ Index* IndexManager::create(IndexType t) break; } case DEMODULATION_LHS_CODE_TREE: - res = new DemodulationLHSIndex(new CodeTreeTIS(), _alg->getOrdering(), _alg->getOptions()); + res = new DemodulationLHSIndex(new CodeTreeTIS(), _alg->getOrdering(), _alg->getOptions()); isGenerating = false; break; diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index dea8ad9c8..4244f17c4 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -50,6 +50,27 @@ TermCodeTree::TermCodeTree() template void TermCodeTree::insert(Data* data) { + if (!isEmpty()) { + static RemovingTermMatcher rtm; + static Stack firstsInBlocks; + firstsInBlocks.reset(); + + FlatTerm* ft=FlatTerm::create(data->term); + rtm.init(ft, this, &firstsInBlocks); + + Data* dptr = nullptr; + for(;;) { + if (!rtm.next()) { + break; + } + ASS(rtm.op->isSuccess()); + dptr=rtm.op->template getSuccessResult(); + if (dptr->insert(*data)) { + return; + } + } + } + static CodeStack code; code.reset(); @@ -91,11 +112,14 @@ void TermCodeTree::remove(const Data& data) } ASS(rtm.op->isSuccess()); dptr=rtm.op->template getSuccessResult(); - if (*dptr==data) { + if (dptr->remove(data)) { break; } } - + + if (!dptr->canBeDeleted()) { + return; + } rtm.op->makeFail(); ASS(dptr); @@ -103,26 +127,7 @@ void TermCodeTree::remove(const Data& data) ft->destroy(); optimizeMemoryAfterRemoval(&firstsInBlocks, rtm.op); - /* - - static TermMatcher tm; - - tm.init(this, ti.t); - - for(;;) { - TermInfo* found=tm.next(); - if (!found) { - INVALID_OPERATION("term being removed was not found"); - } - if (*found==ti) { - tm.op->makeFail(); - delete found; - break; - } - } - tm.deinit(); - */ } // TermCodeTree::remove template @@ -190,6 +195,6 @@ Data* TermCodeTree::TermMatcher::next() } template class TermCodeTree; -template class TermCodeTree; +template class TermCodeTree; }; diff --git a/Indexing/TermIndex.cpp b/Indexing/TermIndex.cpp index 1cef26e0e..8b0311770 100644 --- a/Indexing/TermIndex.cpp +++ b/Indexing/TermIndex.cpp @@ -141,7 +141,8 @@ void DemodulationLHSIndex::handleClause(Clause* c, bool adding) r.apply(EqHelper::getOtherEqualitySide(lit, lhs)), c, preordered, _ord ); - _is->handle(std::move(dd), adding); + DemodulatorDataContainer dc(std::move(dd), _ord); + _is->handle(std::move(dc), adding); } } diff --git a/Indexing/TermIndex.hpp b/Indexing/TermIndex.hpp index 6d65e0cc5..c51fb31af 100644 --- a/Indexing/TermIndex.hpp +++ b/Indexing/TermIndex.hpp @@ -109,10 +109,10 @@ class DemodulationSubtermIndexImpl * Term index for forward demodulation */ class DemodulationLHSIndex -: public TermIndex +: public TermIndex { public: - DemodulationLHSIndex(TermIndexingStructure* is, Ordering& ord, const Options& opt) + DemodulationLHSIndex(TermIndexingStructure* is, Ordering& ord, const Options& opt) : TermIndex(is), _ord(ord), _opt(opt) {}; protected: void handleClause(Clause* c, bool adding); diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index ccd296a86..d4a904b51 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -139,13 +139,10 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* auto git = _index->getGeneralizations(trm.term(), /* retrieveSubstitutions */ true); while(git.hasNext()) { auto qr=git.next(); - ASS_EQ(qr.data->clause->length(),1); - - if(!ColorHelper::compatible(cl->color(), qr.data->clause->color())) { - continue; - } auto lhs = qr.data->term; + auto subs = qr.unifier; + ASS(subs->isIdentityOnQueryWhenResultBound()); // TODO: // to deal with polymorphic matching @@ -158,90 +155,112 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if(lhs.isVar()){ eqSortSubs.reset(); TermList querySort = trm.sort(); - TermList eqSort = qr.data->term.sort(); + TermList eqSort = lhs.sort(); if(!eqSortSubs.match(eqSort, 0, querySort, 1)){ continue; } } - TermList rhs = qr.data->rhs; - bool preordered = qr.data->preordered; - - auto subs = qr.unifier; - ASS(subs->isIdentityOnQueryWhenResultBound()); - ApplicatorWithEqSort applWithEqSort(subs.ptr(), eqSortSubs); Applicator applWithoutEqSort(subs.ptr()); auto appl = lhs.isVar() ? (SubstApplicator*)&applWithEqSort : (SubstApplicator*)&applWithoutEqSort; - if (_precompiledComparison) { - if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { -#if DEFINE_ORDERING - if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { - std::cout << qr.data->term << " " << qr.data->rhs << std::endl; - std::cout << *qr.data->comparator << std::endl; - INVALID_OPERATION("greater"); - } -#endif + DemodulatorData* dd = nullptr; + qr.data->comparator->reset(); + while ((dd = static_cast(qr.data->comparator->next(appl)))) { + + ASS_EQ(dd->clause->length(),1); + if (dd->clause->store() == Clause::NONE) { + env.statistics->inductionApplication++; continue; } -#if DEFINE_ORDERING - if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER) { - std::cout << qr.data->term << " " << qr.data->rhs << std::endl; - std::cout << *qr.data->comparator << std::endl; - INVALID_OPERATION("not greater"); + + if(!ColorHelper::compatible(cl->color(), dd->clause->color())) { + continue; } -#endif - } else { - if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER)) { + + AppliedTerm rhsApplied(dd->rhs,appl,true); + #if DEBUG_ORDERING + if (ordering.isGreaterOrEq(AppliedTerm(trm),rhsApplied)!=Ordering::GREATER) { + INVALID_OPERATION("forward demodulation wrong"); + } + #endif + + // encompassing demodulation is fine when rewriting the smaller guy + if (redundancyCheck && _encompassing) { + // this will only run at most once; + // could have been factored out of the getGeneralizations loop, + // but then it would run exactly once there + Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); + if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || + (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { + redundancyCheck = false; + } + } + + TermList rhsS = rhsApplied.apply(); + if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsS, lhs, appl)) { continue; } - } - // encompassing demodulation is fine when rewriting the smaller guy - if (redundancyCheck && _encompassing) { - // this will only run at most once; - // could have been factored out of the getGeneralizations loop, - // but then it would run exactly once there - Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); - if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || - (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { - redundancyCheck = false; + Literal* resLit = EqHelper::replace(lit,trm,rhsS); + if(EqHelper::isEqTautology(resLit)) { + env.statistics->forwardDemodulationsToEqTaut++; + premises = pvi( getSingletonIterator(dd->clause)); + return true; } - } - TermList rhsS = subs->applyToBoundResult(rhs); - if (lhs.isVar()) { - rhsS = eqSortSubs.apply(rhsS, 0); - } + RStack resLits; + resLits->push(resLit); - if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsS, lhs, appl)) { - continue; - } + for(unsigned i=0;ipush(curr); + } + } + + env.statistics->forwardDemodulations++; - Literal* resLit = EqHelper::replace(lit,trm,rhsS); - if(EqHelper::isEqTautology(resLit)) { - env.statistics->forwardDemodulationsToEqTaut++; - premises = pvi( getSingletonIterator(qr.data->clause)); + premises = pvi( getSingletonIterator(dd->clause)); + replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, dd->clause)); + // ConditionalRedundancyHandler::transfer(cl, replacement); return true; } - RStack resLits; - resLits->push(resLit); +#if DEBUG_ORDERING + for (const auto& dd : qr.data->dds) { + ASS_EQ(dd->clause->length(),1); - for(unsigned i=0;ipush(curr); + if(!ColorHelper::compatible(cl->color(), dd->clause->color())) { + continue; } - } - env.statistics->forwardDemodulations++; + AppliedTerm rhsApplied(dd->rhs,appl,true); + bool preordered = dd->preordered; - premises = pvi( getSingletonIterator(qr.data->clause)); - replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, qr.data->clause)); - // ConditionalRedundancyHandler::transfer(cl, replacement); - return true; + if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),rhsApplied)!=Ordering::GREATER)) { + continue; + } + + // encompassing demodulation is fine when rewriting the smaller guy + if (redundancyCheck && _encompassing) { + // this will only run at most once; + // could have been factored out of the getGeneralizations loop, + // but then it would run exactly once there + Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); + if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || + (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { + redundancyCheck = false; + } + } + + if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsApplied.apply(), lhs, appl)) { + continue; + } + INVALID_OPERATION("forward demodulation missed"); + } +#endif } } } diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index 4908d6390..1b637701d 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -874,9 +874,9 @@ Ordering::Result KBO::isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const return res; } -OrderingComparatorUP KBO::createComparator(void* root) const +OrderingComparatorUP KBO::createComparator(const Stack& cons, void* result) const { - return make_unique(*this, root); + return make_unique(*this, cons, result); } int KBO::symbolWeight(const Term* t) const diff --git a/Kernel/KBO.hpp b/Kernel/KBO.hpp index b5d03c12b..9d01c6686 100644 --- a/Kernel/KBO.hpp +++ b/Kernel/KBO.hpp @@ -158,7 +158,7 @@ class KBO Result compare(AppliedTerm t1, AppliedTerm t2) const override; Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const override; - OrderingComparatorUP createComparator(void* root) const override; + OrderingComparatorUP createComparator(const Stack& cons, void* result) const override; protected: unsigned computeWeight(AppliedTerm tt) const; diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 7e29efb93..76d4f3319 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -24,10 +24,18 @@ using namespace Shell; void KBOComparator::expand() { const auto& kbo = static_cast(_ord); - while (_curr->tag == BranchTag::T_UNKNOWN) + while (!_curr->ready) { // take temporary ownership of node Branch nodeHolder = *_curr; + + if (_curr->tag == BranchTag::T_RESULT) { + auto node = static_cast(nodeHolder.n.ptr()); + *_curr = Branch(node->data); + static_cast(_curr->n.ptr())->alternative = node->alternative; + _curr->ready = true; + return; + } auto node = static_cast(nodeHolder.n.ptr()); // Use compare here to filter out as many diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index bd6942f7c..290535f2f 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -33,8 +33,8 @@ class KBOComparator : public OrderingComparator { public: - KBOComparator(const Ordering& ord, void* root) - : OrderingComparator(ord, root) {} + KBOComparator(const Ordering& ord, const Stack& comps, void* result) + : OrderingComparator(ord, comps, result) {} void expand() override; }; diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index 87043fb95..e1ad1ab80 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -247,9 +247,9 @@ Ordering::Result LPO::majo(AppliedTerm s, AppliedTerm t, const TermList* tl, uns return GREATER; } -OrderingComparatorUP LPO::createComparator(void* root) const +OrderingComparatorUP LPO::createComparator(const Stack& cons, void* result) const { - return make_unique(*this, root); + return make_unique(*this, cons, result); } void LPO::showConcrete(ostream&) const diff --git a/Kernel/LPO.hpp b/Kernel/LPO.hpp index 03224e9b9..19acafa9c 100644 --- a/Kernel/LPO.hpp +++ b/Kernel/LPO.hpp @@ -48,7 +48,7 @@ class LPO Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm tl1, AppliedTerm tl2) const override; Result isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const override; - OrderingComparatorUP createComparator(void* root) const override; + OrderingComparatorUP createComparator(const Stack& cons, void* result) const override; void showConcrete(std::ostream&) const override; diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 0fd14f76d..a4c7e6ef7 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -51,10 +51,18 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 void LPOComparator::expand() { const auto& lpo = static_cast(_ord); - while (_curr->tag == BranchTag::T_UNKNOWN) + while (!_curr->ready) { // take temporary ownership of node Branch nodeHolder = *_curr; + + if (_curr->tag == BranchTag::T_RESULT) { + auto node = static_cast(nodeHolder.n.ptr()); + *_curr = Branch(node->data); + static_cast(_curr->n.ptr())->alternative = node->alternative; + _curr->ready = true; + return; + } auto node = static_cast(nodeHolder.n.ptr()); ASS(node); diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index bcd1ad4f7..5e52c247e 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -24,8 +24,8 @@ class LPOComparator : public OrderingComparator { public: - LPOComparator(const Ordering& ord, void* root) - : OrderingComparator(ord, root) {} + LPOComparator(const Ordering& ord, const Stack& comps, void* result) + : OrderingComparator(ord, comps, result) {} void expand() override; diff --git a/Kernel/Ordering.cpp b/Kernel/Ordering.cpp index 43fecdb7c..40ceb8104 100644 --- a/Kernel/Ordering.cpp +++ b/Kernel/Ordering.cpp @@ -210,9 +210,9 @@ Ordering::Result Ordering::getEqualityArgumentOrder(Literal* eq) const return res; } -OrderingComparatorUP Ordering::createComparator(void* root) const +OrderingComparatorUP Ordering::createComparator(const Stack& cons, void* result) const { - return std::make_unique(*this, root); + return std::make_unique(*this, cons, result); } ////////////////////////////////////////////////// diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index d48c6cda6..f64f3757e 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -56,6 +56,15 @@ class Ordering INCOMPARABLE=4 }; + struct Constraint { + TermList lhs; + TermList rhs; + Result rel; + + friend std::ostream& operator<<(std::ostream& out, const Constraint& self) + { return out << self.lhs << " " << self.rhs << " " << resultToString(self.rel); } + }; + virtual ~Ordering() = default; /** Return the result of comparing @b l1 and @b l2 */ @@ -76,7 +85,7 @@ class Ordering /** Creates optimised object to check that @b lhs is greater than @b rhs. * @see OrderingComparator. */ - virtual OrderingComparatorUP createComparator(void* root) const; + virtual OrderingComparatorUP createComparator(const Stack& cons, void* result) const; virtual void show(std::ostream& out) const = 0; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 64c98b622..63340ab80 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -28,24 +28,26 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& out << "r"; break; case OrderingComparator::BranchTag::T_COMPARISON: - out << "$"; + out << "c"; break; case OrderingComparator::BranchTag::T_WEIGHT: out << "w"; break; - case OrderingComparator::BranchTag::T_UNKNOWN: - out << "?"; - break; } return out; } std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& branch) { - out << branch.tag << " "; + out << branch.tag << (branch.ready?" ":"? "); switch (branch.tag) { case OrderingComparator::BranchTag::T_RESULT: { - out << branch.n.ptr(); + auto n = static_cast(branch.n.ptr()); + if (n) { + out << n->data << " "; + } else { + out << "0x0 "; + } break; } case OrderingComparator::BranchTag::T_WEIGHT: { @@ -56,8 +58,7 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& br } break; } - case OrderingComparator::BranchTag::T_COMPARISON: - case OrderingComparator::BranchTag::T_UNKNOWN: { + case OrderingComparator::BranchTag::T_COMPARISON: { auto n = static_cast(branch.n.ptr()); out << n->lhs << " " << n->rhs; break; @@ -70,41 +71,64 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) { Stack> todo; todo.push(std::make_pair(&comp._root,0)); - unsigned cnt = 1; + // Note: using this set we get a more compact representation + DHSet seen; while (todo.isNonEmpty()) { auto kv = todo.pop(); - str << cnt++ << " "; for (unsigned i = 0; i < kv.second; i++) { - str << " "; + if (i+1 == kv.second) { + str << " |--"; + } else { + str << " | "; + } } str << *kv.first << std::endl; - if (kv.first->n) { - if (kv.first->tag == OrderingComparator::BranchTag::T_RESULT) { - auto n = static_cast(kv.first->n.ptr()); - todo.push(std::make_pair(&n->alternative,kv.second+1)); - } else { - todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + if (kv.first->n/* && seen.insert(kv.first->n.ptr()) */) { + switch (kv.first->tag) { + case OrderingComparator::BranchTag::T_RESULT: { + auto n = static_cast(kv.first->n.ptr()); + todo.push(std::make_pair(&n->alternative,kv.second+1)); + break; + } + default: { + todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + break; + } } } } return str; } +OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) +: _ord(ord), _root(), _curr(&_root) +{ + ASS(result); + auto curr = &_root; + for (const auto& [lhs,rhs,rel] : comps) { + *curr = OrderingComparator::Branch(lhs, rhs); + curr = &curr->n->getBranch(rel); + } + *curr = Branch(result); +} + OrderingComparator::~OrderingComparator() = default; -OrderingComparator::ResultNode* OrderingComparator::next(const SubstApplicator* applicator) +void* OrderingComparator::next(const SubstApplicator* applicator) { ASS(_curr); while (_curr->n) { expand(); + ASS(_curr->ready); + if (_curr->tag == BranchTag::T_RESULT) { - if (_curr) { + if (_curr && _curr->n) { auto node = static_cast(_curr->n.ptr()); _curr = &node->alternative; - return node; + return node->data; } return nullptr; } @@ -157,9 +181,10 @@ OrderingComparator::ResultNode* OrderingComparator::next(const SubstApplicator* return nullptr; } -void OrderingComparator::addAlternative(const Branch& branch) +void OrderingComparator::addAlternative(const OrderingComparator& other) { - ASS(branch.tag == BranchTag::T_UNKNOWN); // branch should be unexpanded + auto& branch = other._root; + ASS(!branch.ready); // branch should be unexpanded static unsigned ts = 0; ts++; @@ -218,8 +243,8 @@ void OrderingComparator::addAlternative(const Branch& branch) void OrderingComparator::expand() { - if (_curr->tag == BranchTag::T_UNKNOWN) { - _curr->tag = BranchTag::T_COMPARISON; + if (!_curr->ready) { + _curr->ready = true; } } @@ -258,10 +283,10 @@ bool OrderingComparator::tryExpandVarCase(ComparisonNode* node) } // make a fresh copy *_curr = Branch(node->lhs, node->rhs); - _curr->tag = BranchTag::T_COMPARISON; _curr->n->eqBranch = node->eqBranch; _curr->n->gtBranch = node->gtBranch; _curr->n->incBranch = node->incBranch; + _curr->ready = true; return true; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index eee6ca7ab..5e12c0cbf 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -28,13 +28,14 @@ namespace Kernel { */ struct OrderingComparator { +protected: struct Branch; struct Node; - struct ResultNode; + class ResultNode; class ComparisonNode; - OrderingComparator(const Ordering& ord, void* root) : _ord(ord), - _root(*static_cast(root)), _curr(&_root), _cache() {} +public: + OrderingComparator(const Ordering& ord, const Stack& comps, void* result); virtual ~OrderingComparator(); void reset() { _curr = &_root; _cache.reset(); } @@ -42,37 +43,38 @@ struct OrderingComparator reset(); return next(applicator)!=nullptr; } + const Stack& cache() const { return _cache; } - ResultNode* next(const SubstApplicator* applicator); - void addAlternative(const Branch& branch); + void* next(const SubstApplicator* applicator); + void addAlternative(const OrderingComparator& other); - using TermPairRes = std::tuple; + friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); +protected: virtual void expand(); bool tryExpandVarCase(ComparisonNode* origNode); - friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); - enum class BranchTag : uint8_t { T_RESULT, T_COMPARISON, T_WEIGHT, - T_UNKNOWN, }; struct Branch { BranchTag tag; SmartPtr n; + bool ready = false; - Branch() : tag(BranchTag::T_RESULT) {} - explicit Branch(ResultNode* r) : tag(BranchTag::T_RESULT), n(r) {} + Branch() : tag(BranchTag::T_RESULT), ready(true) {} + explicit Branch(void* data) : tag(BranchTag::T_RESULT), n(new ResultNode(data)) {} explicit Branch(TermList lhs, TermList rhs) - : tag(BranchTag::T_UNKNOWN), n(new ComparisonNode(lhs, rhs)) {} + : tag(BranchTag::T_COMPARISON), n(new ComparisonNode(lhs, rhs)) {} explicit Branch(int w, Stack>&& varCoeffPairs) - : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))) {} + : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))), ready(true) {} }; friend std::ostream& operator<<(std::ostream& out, const Branch& branch); + friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); struct Node { virtual ~Node() = default; @@ -99,7 +101,14 @@ struct OrderingComparator unsigned ts; }; - struct ResultNode : public Node { + class ResultNode : public Node { + ResultNode(void* data) : data(data) {} + + // only allow calling ctor from Branch + friend struct Branch; + + public: + void* data; Branch alternative; }; @@ -131,7 +140,7 @@ struct OrderingComparator const Ordering& _ord; Branch _root; Branch* _curr; - Stack _cache; + Stack _cache; }; } // namespace Kernel diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index afbd0344e..e394e76d4 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -49,11 +49,6 @@ bool checkVars(const TermStack& ts, T s) return true; } -std::ostream& operator<<(std::ostream& out, const OrderingConstraint& con) -{ - return out << con.lhs << " " << con.rhs; -} - std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) { if (!e.active) { @@ -61,7 +56,7 @@ std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) } else { str << *e.splits << "; " << *e.lits << "; "; #if DEBUG_ORDERING - iterTraits(e.ordCons.iter()).forEach([&str](const OrderingConstraint& con) { + iterTraits(e.ordCons.iter()).forEach([&str](const Ordering::Constraint& con) { str << con; }); #endif @@ -95,15 +90,14 @@ class ConditionalRedundancyHandler::ConstraintIndex } bool insert(const Ordering* ord, ResultSubstitution* subst, bool result, Splitter* splitter, - OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) + Stack&& ordCons, const LiteralSet* lits, SplitSet* splits) { auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - auto e = createEntry(ts, splitter, std::move(ordCons), lits, splits); - return insert(ord, ts, e.first, e.second); + return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } bool checkAndInsert(const Ordering* ord, ResultSubstitution* subst, bool result, bool doInsert, Splitter* splitter, - OrderingConstraints&& ordCons, const LiteralSet* lits, const SplitSet* splits) + Stack&& ordCons, const LiteralSet* lits, const SplitSet* splits) { ASS(lits); // TODO if this correct if we allow non-unit simplifications? @@ -115,8 +109,7 @@ class ConditionalRedundancyHandler::ConstraintIndex return false; } if (doInsert) { - auto e = createEntry(ts, splitter, std::move(ordCons), lits, splits); - return insert(ord, ts, e.first, e.second); + return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } return true; } @@ -126,7 +119,7 @@ class ConditionalRedundancyHandler::ConstraintIndex Clause* _cl; #endif - bool insert(Entries* entries, const OrderingComparator::Branch& root, ConditionalRedundancyEntry* ptr) + bool insert(const Ordering* ord, Entries* entries, ConditionalRedundancyEntry* ptr) { ASS(ptr->active); @@ -135,15 +128,16 @@ class ConditionalRedundancyHandler::ConstraintIndex #if DEBUG_ORDERING entries->entries.push(ptr); #endif - entries->comparator->addAlternative(root); + auto comp = ord->createComparator(ptr->ordCons, ptr); + entries->comparator->addAlternative(*comp.get()); return true; } - bool insert(const Ordering* ord, const TermStack& ts, const OrderingComparator::Branch& root, ConditionalRedundancyEntry* ptr) + bool insert(const Ordering* ord, const TermStack& ts, ConditionalRedundancyEntry* ptr) { if (lastRenamingEntry) { // there is an entry up to renaming already, insert it here - return insert(lastRenamingEntry, root, ptr); + return insert(ord, lastRenamingEntry, ptr); } CodeStack code; @@ -168,7 +162,7 @@ class ConditionalRedundancyHandler::ConstraintIndex #if DEBUG_ORDERING es->entries.push(ptr); #endif - es->comparator = ord->createComparator(const_cast(&root)); + es->comparator = ord->createComparator(ptr->ordCons, ptr); code.push(CodeOp::getSuccess(es)); incorporate(code); return true; @@ -224,7 +218,7 @@ class ConditionalRedundancyHandler::ConstraintIndex cout << e << endl; cout << *e << endl; cout << *es->comparator << endl; - INVALID_OPERATION("nope"); + INVALID_OPERATION("conditional redundancy ordering check failed"); } #endif @@ -270,7 +264,7 @@ class ConditionalRedundancyHandler::ConstraintIndex continue; } - INVALID_OPERATION("nope"); + INVALID_OPERATION("conditional redundancy entry missed"); } #endif } @@ -293,7 +287,7 @@ class ConditionalRedundancyHandler::ConstraintIndex DHMap _varSorts; - std::pair createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const + ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, Stack&& ordCons, const LiteralSet* lits, SplitSet* splits) const { auto e = new ConditionalRedundancyEntry(); Renaming r; @@ -306,29 +300,13 @@ class ConditionalRedundancyHandler::ConstraintIndex } for (auto& ordCon : ordCons) { - ASS(!ordCon.comp); ASS(checkVars(ts,ordCon.lhs)); ASS(checkVars(ts,ordCon.rhs)); ASS(ordCon.lhs.containsAllVariablesOf(ordCon.rhs)); ordCon.lhs = r.apply(ordCon.lhs); ordCon.rhs = r.apply(ordCon.rhs); } - - OrderingComparator::Branch root; - auto curr = &root; - if (ordCons.isNonEmpty()) { - *curr = OrderingComparator::Branch(ordCons[0].lhs, ordCons[0].rhs); - curr = &curr->n->gtBranch; - for (unsigned i = 1; i < ordCons.size(); i++) { - auto& ordCon = ordCons[i]; - *curr = OrderingComparator::Branch(ordCon.lhs, ordCon.rhs); - curr = &curr->n->gtBranch; - } - } - *curr = OrderingComparator::Branch(e); -#if DEBUG_ORDERING e->ordCons = std::move(ordCons); -#endif #if VDEBUG lits->iter().forEach([&ts](Literal* lit) { @@ -347,7 +325,7 @@ class ConditionalRedundancyHandler::ConstraintIndex splitter->addConditionalRedundancyEntry(splits, e); } - return { root, e }; + return e; } struct SubstMatcher @@ -459,7 +437,7 @@ void ConditionalRedundancyHandler::checkEquations(Clause* cl) const } auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, Stack(), LiteralSet::getEmpty(), SplitSet::getEmpty()); }); } @@ -567,20 +545,20 @@ bool ConditionalRedundancyHandlerImpl::insertSuper rwClause, rwLitS, rwTermS, tgtTermS, eqClause, eqLHS, &appl, otherComp); // create ordering constraints - OrderingConstraints ordCons; + Stack ordCons; if constexpr (ordC) { // TODO we cannot handle them together yet if (eqComp != Ordering::LESS) { if (!premiseRedundant || !rwTermS.containsAllVariablesOf(tgtTermS)) { return true; } - ordCons.push(OrderingConstraint(rwTermS, tgtTermS)); + ordCons.push({ rwTermS, tgtTermS, Ordering::GREATER }); } else if (!premiseRedundant) { TermList other = EqHelper::getOtherEqualitySide(rwLitS, rwTermS); if (otherComp != Ordering::INCOMPARABLE || !other.containsAllVariablesOf(tgtTermS)) { return true; } - ordCons.push(OrderingConstraint(other, tgtTermS)); + ordCons.push({ other, tgtTermS, Ordering::GREATER }); } } else { if (eqComp != Ordering::LESS || !premiseRedundant) { @@ -667,7 +645,7 @@ bool ConditionalRedundancyHandlerImpl::handleResol auto dataPtr = getDataPtr(queryCl, /*doAllocate=*/doInsert); if (dataPtr && !(*dataPtr)->checkAndInsert( - _ord, subs, /*result*/false, doInsert, _splitter, OrderingConstraints(), lits, splits)) + _ord, subs, /*result*/false, doInsert, _splitter, Stack(), lits, splits)) { env.statistics->skippedResolution++; return false; @@ -705,7 +683,7 @@ bool ConditionalRedundancyHandlerImpl::handleResol auto dataPtr = getDataPtr(resultCl, /*doAllocate=*/doInsert); if (dataPtr && !(*dataPtr)->checkAndInsert( - _ord, subs, /*result*/true, doInsert, _splitter, OrderingConstraints(), lits, splits)) + _ord, subs, /*result*/true, doInsert, _splitter, Stack(), lits, splits)) { env.statistics->skippedResolution++; return false; @@ -726,7 +704,7 @@ bool ConditionalRedundancyHandlerImpl::handleReduc auto lits = LiteralSet::getEmpty(); auto splits = SplitSet::getEmpty(); if (!(*dataPtr)->checkAndInsert( - _ord, subst.ptr(), /*result*/false, /*doInsert=*/true, _splitter, OrderingConstraints(), lits, splits)) + _ord, subst.ptr(), /*result*/false, /*doInsert=*/true, _splitter, Stack(), lits, splits)) { return false; } @@ -785,8 +763,8 @@ void ConditionalRedundancyHandlerImpl::initWithEqu return; } - OrderingConstraints ordCons; - ordCons.push(OrderingConstraint(tgtTerm, rwTerm)); + Stack ordCons; + ordCons.push({ tgtTerm, rwTerm, Ordering::GREATER }); auto lits = LiteralSet::getEmpty(); auto splits = SplitSet::getEmpty(); diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 86ab6aa08..044fbed00 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -58,21 +58,10 @@ using namespace Indexing; using LiteralSet = SharedSet; -struct OrderingConstraint { - OrderingConstraint(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs), comp() {} - TermList lhs; - TermList rhs; - OrderingComparatorUP comp; -}; - -using OrderingConstraints = Stack; - -struct ConditionalRedundancyEntry : OrderingComparator::ResultNode +struct ConditionalRedundancyEntry { Stack> eqCons; -#if DEBUG_ORDERING - OrderingConstraints ordCons; -#endif + Stack ordCons; const LiteralSet* lits; SplitSet* splits; bool active = true; From e6d77a5a094c7963cd408134052a5449a83b3c50 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 25 Sep 2024 11:49:13 +0200 Subject: [PATCH 11/64] Factor out common parts of expand --- Kernel/KBOComparator.cpp | 162 ++++++++++++++-------------------- Kernel/KBOComparator.hpp | 2 +- Kernel/LPOComparator.cpp | 107 ++++++++-------------- Kernel/LPOComparator.hpp | 2 +- Kernel/OrderingComparator.cpp | 46 +++++++++- Kernel/OrderingComparator.hpp | 4 +- 6 files changed, 149 insertions(+), 174 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 76d4f3319..2f637c634 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,117 +21,85 @@ using namespace std; using namespace Lib; using namespace Shell; -void KBOComparator::expand() +void KBOComparator::expandTermCase(ComparisonNode* node) { + ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& kbo = static_cast(_ord); - while (!_curr->ready) - { - // take temporary ownership of node - Branch nodeHolder = *_curr; - - if (_curr->tag == BranchTag::T_RESULT) { - auto node = static_cast(nodeHolder.n.ptr()); - *_curr = Branch(node->data); - static_cast(_curr->n.ptr())->alternative = node->alternative; - _curr->ready = true; - return; - } - auto node = static_cast(nodeHolder.n.ptr()); - - // Use compare here to filter out as many - // precomputable comparisons as possible. - auto comp = kbo.compare(node->lhs,node->rhs); - if (comp != Ordering::INCOMPARABLE) { - if (comp == Ordering::LESS) { - *_curr = node->incBranch; - } else if (comp == Ordering::GREATER) { - *_curr = node->gtBranch; - } else { - *_curr = node->eqBranch; - } - continue; - } - // If we have a variable, we cannot preprocess further. - if (tryExpandVarCase(node)) { - continue; - } - // if both are proper terms, we calculate - // weight and variable balances first + // weight and variable balances first - // we only care about the non-zero weights and counts - bool varInbalance = false; - auto state = kbo._state; + // we only care about the non-zero weights and counts + bool varInbalance = false; + auto state = kbo._state; #if VDEBUG - // we make sure kbo._state is not used while we're using it - kbo._state = nullptr; + // we make sure kbo._state is not used while we're using it + kbo._state = nullptr; #endif - auto w = state->_weightDiff; - decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); - Stack nonzeros; - while (vit.hasNext()) { - unsigned v; - int cnt; - vit.next(v,cnt); - if (cnt!=0) { - nonzeros.push(make_pair(v,cnt)); - w-=cnt; // we have to remove the variable weights from w - } - if (cnt<0) { - varInbalance = true; - } + auto w = state->_weightDiff; + decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); + Stack nonzeros; + while (vit.hasNext()) { + unsigned v; + int cnt; + vit.next(v,cnt); + if (cnt!=0) { + nonzeros.push(make_pair(v,cnt)); + w-=cnt; // we have to remove the variable weights from w + } + if (cnt<0) { + varInbalance = true; } + } #if VDEBUG - kbo._state = state; - state = nullptr; + kbo._state = state; + state = nullptr; #endif - auto curr = _curr; + auto curr = _curr; - // if the condition below does not hold, the weight/var balances are satisfied - if (w < 0 || varInbalance) { - sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { - return e1.second>e2.second; - }); - *curr = Branch(w, std::move(nonzeros)); - curr->n->gtBranch = node->gtBranch; - curr->n->incBranch = node->incBranch; - curr = &curr->n->eqBranch; - } + // if the condition below does not hold, the weight/var balances are satisfied + if (w < 0 || varInbalance) { + sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { + return e1.second>e2.second; + }); + *curr = Branch(w, std::move(nonzeros)); + curr->n->gtBranch = node->gtBranch; + curr->n->incBranch = node->incBranch; + curr = &curr->n->eqBranch; + } - auto lhst = node->lhs.term(); - auto rhst = node->rhs.term(); + auto lhst = node->lhs.term(); + auto rhst = node->rhs.term(); - Ordering::Result prec = lhst->isSort() - ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) - : kbo.compareFunctionPrecedences(lhst->functor(),rhst->functor()); - switch (prec) - { - case Ordering::LESS: { - *curr = node->incBranch; - break; - } - case Ordering::GREATER: { - *curr = node->gtBranch; - break; - } - case Ordering::EQUAL: { - // push the arguments in reverse order to maintain - // left-to-right lexicographic order in todo - for (unsigned i = 0; i < lhst->arity(); i++) { - auto lhsArg = *lhst->nthArgument(i); - auto rhsArg = *rhst->nthArgument(i); - *curr = Branch(lhsArg,rhsArg); - curr->n->gtBranch = node->gtBranch; - curr->n->incBranch = node->incBranch; - curr = &curr->n->eqBranch; - } - *curr = node->eqBranch; - break; - } - default: { - ASSERTION_VIOLATION; + Ordering::Result prec = lhst->isSort() + ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) + : kbo.compareFunctionPrecedences(lhst->functor(),rhst->functor()); + switch (prec) + { + case Ordering::LESS: { + *curr = node->incBranch; + break; + } + case Ordering::GREATER: { + *curr = node->gtBranch; + break; + } + case Ordering::EQUAL: { + // push the arguments in reverse order to maintain + // left-to-right lexicographic order in todo + for (unsigned i = 0; i < lhst->arity(); i++) { + auto lhsArg = *lhst->nthArgument(i); + auto rhsArg = *rhst->nthArgument(i); + *curr = Branch(lhsArg,rhsArg); + curr->n->gtBranch = node->gtBranch; + curr->n->incBranch = node->incBranch; + curr = &curr->n->eqBranch; } + *curr = node->eqBranch; + break; + } + default: { + ASSERTION_VIOLATION; } } } diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 290535f2f..6559c34dc 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -36,7 +36,7 @@ class KBOComparator KBOComparator(const Ordering& ord, const Stack& comps, void* result) : OrderingComparator(ord, comps, result) {} - void expand() override; + void expandTermCase(ComparisonNode* node) override; }; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index a4c7e6ef7..827e8b954 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -48,83 +48,50 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = fail; } -void LPOComparator::expand() +void LPOComparator::expandTermCase(ComparisonNode* node) { + ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& lpo = static_cast(_ord); - while (!_curr->ready) - { - // take temporary ownership of node - Branch nodeHolder = *_curr; + auto s = node->lhs.term(); + auto t = node->rhs.term(); - if (_curr->tag == BranchTag::T_RESULT) { - auto node = static_cast(nodeHolder.n.ptr()); - *_curr = Branch(node->data); - static_cast(_curr->n.ptr())->alternative = node->alternative; - _curr->ready = true; - return; - } - auto node = static_cast(nodeHolder.n.ptr()); - ASS(node); - - // Use compare here to filter out as many - // precomputable comparisons as possible. - auto comp = lpo.compare(node->lhs,node->rhs); - if (comp != Ordering::INCOMPARABLE) { - if (comp == Ordering::LESS) { - *_curr = node->incBranch; - } else if (comp == Ordering::GREATER) { - *_curr = node->gtBranch; - } else { - *_curr = node->eqBranch; - } - continue; - } - // If we have a variable, we cannot preprocess further. - if (tryExpandVarCase(node)) { - continue; - } - - auto s = node->lhs.term(); - auto t = node->rhs.term(); - - switch (lpo.comparePrecedences(s, t)) { - case Ordering::EQUAL: { - ASS(s->arity()); // constants cannot be incomparable + switch (lpo.comparePrecedences(s, t)) { + case Ordering::EQUAL: { + ASS(s->arity()); // constants cannot be incomparable - // copies for unification - auto lhs = node->lhs; - auto rhs = node->rhs; + // copies for unification + auto lhs = node->lhs; + auto rhs = node->rhs; - auto curr = _curr; + auto curr = _curr; - // lexicographic comparisons - for (unsigned i = 0; i < s->arity(); i++) - { - auto s_arg = *lhs.term()->nthArgument(i); - auto t_arg = *rhs.term()->nthArgument(i); - *curr = Branch(s_arg,t_arg); - // greater branch is a majo chain - majoChain(&curr->n->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); - // incomparable branch is an alpha chain - alphaChain(&curr->n->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); - curr = &curr->n->eqBranch; - } - *curr = node->eqBranch; - break; - } - case Ordering::GREATER: { - ASS(t->arity()); - majoChain(_curr, node->lhs, t, 0, node->gtBranch, node->incBranch); - break; - } - case Ordering::LESS: { - ASS(s->arity()); - alphaChain(_curr, s, 0, node->rhs, node->gtBranch, node->incBranch); - break; - } - default: - ASSERTION_VIOLATION; + // lexicographic comparisons + for (unsigned i = 0; i < s->arity(); i++) + { + auto s_arg = *lhs.term()->nthArgument(i); + auto t_arg = *rhs.term()->nthArgument(i); + *curr = Branch(s_arg,t_arg); + // greater branch is a majo chain + majoChain(&curr->n->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); + // incomparable branch is an alpha chain + alphaChain(&curr->n->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); + curr = &curr->n->eqBranch; } + *curr = node->eqBranch; + break; + } + case Ordering::GREATER: { + ASS(t->arity()); + majoChain(_curr, node->lhs, t, 0, node->gtBranch, node->incBranch); + break; + } + case Ordering::LESS: { + ASS(s->arity()); + alphaChain(_curr, s, 0, node->rhs, node->gtBranch, node->incBranch); + break; + } + default: + ASSERTION_VIOLATION; } } diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index 5e52c247e..b41c335e8 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -27,7 +27,7 @@ class LPOComparator LPOComparator(const Ordering& ord, const Stack& comps, void* result) : OrderingComparator(ord, comps, result) {} - void expand() override; + void expandTermCase(ComparisonNode* node) override; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 63340ab80..f25f344aa 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -243,11 +243,51 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) void OrderingComparator::expand() { - if (!_curr->ready) { - _curr->ready = true; + while (!_curr->ready) + { + // take temporary ownership of node + Branch nodeHolder = *_curr; + + if (_curr->tag == BranchTag::T_RESULT) { + auto node = static_cast(nodeHolder.n.ptr()); + *_curr = Branch(node->data); + static_cast(_curr->n.ptr())->alternative = node->alternative; + _curr->ready = true; + return; + } + ASS(_curr->tag != BranchTag::T_WEIGHT); + auto node = static_cast(nodeHolder.n.ptr()); + + // Use compare here to filter out as many + // precomputable comparisons as possible. + auto comp = _ord.compare(node->lhs,node->rhs); + if (comp != Ordering::INCOMPARABLE) { + if (comp == Ordering::LESS) { + *_curr = node->incBranch; + } else if (comp == Ordering::GREATER) { + *_curr = node->gtBranch; + } else { + *_curr = node->eqBranch; + } + continue; + } + // If we have a variable, we cannot preprocess further. + if (tryExpandVarCase(node)) { + continue; + } + + ASS_EQ(_curr->n.ptr(), node); + expandTermCase(node); + ASS_NEQ(_curr->n.ptr(), node); } } +void OrderingComparator::expandTermCase(ComparisonNode* node) +{ + ASS(!_curr->ready); + _curr->ready = true; +} + bool OrderingComparator::tryExpandVarCase(ComparisonNode* node) { // If we have a variable, we cannot preprocess further. @@ -267,7 +307,7 @@ bool OrderingComparator::tryExpandVarCase(ComparisonNode* node) } return true; } - + if (s == node->rhs && t == node->lhs && r != Ordering::INCOMPARABLE) { if (r == Ordering::GREATER) { *_curr = node->incBranch; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 5e12c0cbf..c7069f1a0 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -43,7 +43,6 @@ struct OrderingComparator reset(); return next(applicator)!=nullptr; } - const Stack& cache() const { return _cache; } void* next(const SubstApplicator* applicator); void addAlternative(const OrderingComparator& other); @@ -51,7 +50,8 @@ struct OrderingComparator friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); protected: - virtual void expand(); + void expand(); + virtual void expandTermCase(ComparisonNode* node); bool tryExpandVarCase(ComparisonNode* origNode); enum class BranchTag : uint8_t { From d42787beb501954c40c67680949c0f690efbcedd Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 25 Sep 2024 15:50:17 +0200 Subject: [PATCH 12/64] Some small fixes --- Kernel/KBOComparator.cpp | 6 +++- Kernel/KBOComparator.hpp | 2 +- Kernel/LPOComparator.cpp | 6 +++- Kernel/LPOComparator.hpp | 2 +- Kernel/OrderingComparator.cpp | 19 +++++++----- Kernel/OrderingComparator.hpp | 8 ++--- Makefile | 1 + Shell/ConditionalRedundancyHandler.cpp | 43 ++++++++++++++------------ Shell/ConditionalRedundancyHandler.hpp | 13 ++++---- 9 files changed, 57 insertions(+), 43 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 2f637c634..23ba2a74c 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,8 +21,12 @@ using namespace std; using namespace Lib; using namespace Shell; -void KBOComparator::expandTermCase(ComparisonNode* node) +void KBOComparator::expandTermCase() { + // take temporary ownership of node + Branch nodeHolder = *_curr; + auto node = static_cast(nodeHolder.n.ptr()); + ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& kbo = static_cast(_ord); diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 6559c34dc..7c3f2a98c 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -36,7 +36,7 @@ class KBOComparator KBOComparator(const Ordering& ord, const Stack& comps, void* result) : OrderingComparator(ord, comps, result) {} - void expandTermCase(ComparisonNode* node) override; + void expandTermCase() override; }; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 827e8b954..d6c9f924e 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -48,8 +48,12 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = fail; } -void LPOComparator::expandTermCase(ComparisonNode* node) +void LPOComparator::expandTermCase() { + // take temporary ownership of node + Branch nodeHolder = *_curr; + auto node = static_cast(nodeHolder.n.ptr()); + ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& lpo = static_cast(_ord); auto s = node->lhs.term(); diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index b41c335e8..bf090181a 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -27,7 +27,7 @@ class LPOComparator LPOComparator(const Ordering& ord, const Stack& comps, void* result) : OrderingComparator(ord, comps, result) {} - void expandTermCase(ComparisonNode* node) override; + void expandTermCase() override; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index f25f344aa..b53b6cad8 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -13,12 +13,15 @@ */ #include "Lib/Stack.hpp" -#include "KBO.hpp" +#include "Lib/Environment.hpp" +#include "KBO.hpp" #include "SubstHelper.hpp" #include "OrderingComparator.hpp" +using namespace std; + namespace Kernel { std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) @@ -272,24 +275,26 @@ void OrderingComparator::expand() continue; } // If we have a variable, we cannot preprocess further. - if (tryExpandVarCase(node)) { + if (tryExpandVarCase()) { continue; } - ASS_EQ(_curr->n.ptr(), node); - expandTermCase(node); - ASS_NEQ(_curr->n.ptr(), node); + expandTermCase(); } } -void OrderingComparator::expandTermCase(ComparisonNode* node) +void OrderingComparator::expandTermCase() { ASS(!_curr->ready); _curr->ready = true; } -bool OrderingComparator::tryExpandVarCase(ComparisonNode* node) +bool OrderingComparator::tryExpandVarCase() { + // take temporary ownership of node + Branch nodeHolder = *_curr; + auto node = static_cast(nodeHolder.n.ptr()); + // If we have a variable, we cannot preprocess further. if (!node->lhs.isVar() && !node->rhs.isVar()) { return false; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index c7069f1a0..35c86f4d9 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -39,10 +39,6 @@ struct OrderingComparator virtual ~OrderingComparator(); void reset() { _curr = &_root; _cache.reset(); } - bool check(const SubstApplicator* applicator) { - reset(); - return next(applicator)!=nullptr; - } void* next(const SubstApplicator* applicator); void addAlternative(const OrderingComparator& other); @@ -51,8 +47,8 @@ struct OrderingComparator protected: void expand(); - virtual void expandTermCase(ComparisonNode* node); - bool tryExpandVarCase(ComparisonNode* origNode); + virtual void expandTermCase(); + bool tryExpandVarCase(); enum class BranchTag : uint8_t { T_RESULT, diff --git a/Makefile b/Makefile index 60c699044..dc33812a7 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,7 @@ VK_OBJ= Kernel/Clause.o\ Kernel/MLVariant.o\ Kernel/Ordering.o\ Kernel/Ordering_Equality.o\ + Kernel/OrderingComparator.o\ Kernel/Problem.o\ Kernel/Renaming.o\ Kernel/RobSubstitution.o\ diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index e394e76d4..e3dde1e48 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -422,25 +422,6 @@ void ConditionalRedundancyHandler::destroyClauseData(Clause* cl) delete ptr; } -void ConditionalRedundancyHandler::checkEquations(Clause* cl) const -{ - // TODO return if not enabled - cl->iterLits().forEach([cl,this](Literal* lit){ - if (!lit->isEquality() || lit->isNegative()) { - return; - } - auto t0 = lit->termArg(0); - auto t1 = lit->termArg(1); - RobSubstitution subs; - if (!subs.unify(t0,0,t1,0)) { - return; - } - auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); - auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, Stack(), LiteralSet::getEmpty(), SplitSet::getEmpty()); - }); -} - ConditionalRedundancyHandler::ConstraintIndex** ConditionalRedundancyHandler::getDataPtr(Clause* cl, bool doAllocate) { if (!doAllocate) { @@ -777,4 +758,28 @@ void ConditionalRedundancyHandlerImpl::initWithEqu (*clDataPtr)->insert(_ord, &subst, true, _splitter, std::move(ordCons), lits, splits); } +template +void ConditionalRedundancyHandlerImpl::checkEquations(Clause* cl) const +{ + if (!enabled) { + return; + } + + // TODO return if not enabled + cl->iterLits().forEach([cl,this](Literal* lit){ + if (!lit->isEquality() || lit->isNegative()) { + return; + } + auto t0 = lit->termArg(0); + auto t1 = lit->termArg(1); + RobSubstitution subs; + if (!subs.unify(t0,0,t1,0)) { + return; + } + auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); + auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); + (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, Stack(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + }); +} + } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 044fbed00..5b7d1dd75 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -98,7 +98,6 @@ class ConditionalRedundancyHandler static ConditionalRedundancyHandler* create(const Options& opts, const Ordering* ord, Splitter* splitter); static void destroyClauseData(Clause* cl); - ConditionalRedundancyHandler(const Ordering* ord) : _ord(ord) {} virtual ~ConditionalRedundancyHandler() = default; virtual bool checkSuperposition( @@ -115,7 +114,7 @@ class ConditionalRedundancyHandler virtual void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const = 0; - void checkEquations(Clause* cl) const; + virtual void checkEquations(Clause* cl) const = 0; static void transfer(Clause* from, Clause* to); @@ -126,8 +125,6 @@ class ConditionalRedundancyHandler // this contains the redundancy information associated with each clause static DHMap clauseData; - - const Ordering* _ord; }; template @@ -136,10 +133,9 @@ class ConditionalRedundancyHandlerImpl { public: ConditionalRedundancyHandlerImpl(const Options& opts, const Ordering* ord, Splitter* splitter) - : ConditionalRedundancyHandler(ord), - _redundancyCheck(opts.demodulationRedundancyCheck() != Options::DemodulationRedundancyCheck::OFF), + : _redundancyCheck(opts.demodulationRedundancyCheck() != Options::DemodulationRedundancyCheck::OFF), _encompassing(opts.demodulationRedundancyCheck() == Options::DemodulationRedundancyCheck::ENCOMPASS), - _splitter(splitter) {} + _splitter(splitter), _ord(ord) {} /** Returns false if superposition should be skipped. */ bool checkSuperposition( @@ -162,10 +158,13 @@ class ConditionalRedundancyHandlerImpl void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const override; + void checkEquations(Clause* cl) const override; + private: bool _redundancyCheck; bool _encompassing; Splitter* _splitter; + const Ordering* _ord; }; }; From f2802438f935af2e298518deee04c9aa674aba96 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 26 Sep 2024 09:47:06 +0200 Subject: [PATCH 13/64] Fix crashes from TPTP run --- Indexing/Index.hpp | 15 +++++++++++---- Inferences/ForwardDemodulation.cpp | 1 + Shell/ConditionalRedundancyHandler.cpp | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index b426e9672..6c5b85807 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -170,7 +170,10 @@ struct DemodulatorDataContainer { } bool insert(const DemodulatorDataContainer& other) { - if (term!=other.term) { + ASS_EQ(other.dds.size(),1); + // only allow insertion if term sorts are identical to + // avoid putting variables of different sorts together + if (term!=other.term || term.sort()!=other.term.sort()) { return false; } dds.loadFromIterator(other.dds.iter()); @@ -179,11 +182,13 @@ struct DemodulatorDataContainer { } bool remove(const DemodulatorDataContainer& other) { - if (term!=other.term) { + ASS_EQ(other.dds.size(),1); + if (term!=other.term || term.sort()!=other.term.sort()) { return false; } - iterTraits(other.dds.iter()).forEach([this](DemodulatorData* toRemove){ + ALWAYS(iterTraits(other.dds.iter()).all([this](DemodulatorData* toRemove){ decltype(dds)::DelIterator it(dds); + unsigned removedCnt = 0; while (it.hasNext()) { auto curr = it.next(); if (*curr==*toRemove) { @@ -192,9 +197,11 @@ struct DemodulatorDataContainer { // // delete curr; it.del(); + removedCnt++; } } - }); + return removedCnt==1; + })); return true; } diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index d4a904b51..03ee8b40f 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -170,6 +170,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* while ((dd = static_cast(qr.data->comparator->next(appl)))) { ASS_EQ(dd->clause->length(),1); + ASS_EQ(lhs.sort(),dd->term.sort()); if (dd->clause->store() == Clause::NONE) { env.statistics->inductionApplication++; continue; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index e3dde1e48..9c685c85c 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -68,7 +68,7 @@ class ConditionalRedundancyHandler::ConstraintIndex : public CodeTree { public: - ConstraintIndex(Clause* cl) : _varSorts() + ConstraintIndex(Clause* cl) : _varSorts(), lastRenamingEntry(nullptr) { _clauseCodeTree=false; _onCodeOpDestroying = onCodeOpDestroying; From c2452a6a6a26af666fd1a762bc93de7971332866 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 26 Sep 2024 13:14:50 +0200 Subject: [PATCH 14/64] Add optimization for code tree execution without expanding stack --- Indexing/CodeTree.cpp | 11 +++++++++-- Indexing/CodeTree.hpp | 1 + Lib/Stack.hpp | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index 1453b377e..6d090361f 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -543,7 +543,7 @@ inline bool CodeTree::BaseMatcher::doCheckGroundTerm() //////////////// auxiliary //////////////////// CodeTree::CodeTree() -: _onCodeOpDestroying(0), _curTimeStamp(0), _maxVarCnt(1), _entryPoint(0) +: _onCodeOpDestroying(0), _curTimeStamp(0), _maxVarCnt(1), _maxTreeDepth(0), _entryPoint(0) { } @@ -816,6 +816,10 @@ void CodeTree::incorporate(CodeStack& code) { ASS(code.top().isSuccess()); + if (code.size() > _maxTreeDepth) { + _maxTreeDepth = code.size(); + } + if(isEmpty()) { _entryPoint=buildBlock(code, code.length(), 0); code.reset(); @@ -1172,6 +1176,7 @@ void CodeTree::RemovingMatcher::init(CodeOp* entry_, LitInfo* linfos_, matchingClauses=tree->_clauseCodeTree; bindings.ensure(tree->_maxVarCnt); + btStack.reserve(tree->_maxTreeDepth); btStack.reset(); curLInfo=0; @@ -1359,6 +1364,7 @@ void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_) curLInfo=0; btStack.reset(); bindings.ensure(tree->_maxVarCnt); + btStack.reserve(tree->_maxTreeDepth); } bool CodeTree::Matcher::execute() @@ -1377,7 +1383,8 @@ bool CodeTree::Matcher::execute() bool shouldBacktrack=false; for(;;) { if(op->alternative()) { - btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); + btStack.pushUnsafe(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); + // btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); } switch(op->_instruction()) { case SUCCESS_OR_FAIL: diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 8ba570539..9de9c25b2 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -561,6 +561,7 @@ class CodeTree /** maximal number of local variables in a stored term/literal (always at least 1) */ unsigned _maxVarCnt; + unsigned _maxTreeDepth; CodeBlock* _entryPoint; diff --git a/Lib/Stack.hpp b/Lib/Stack.hpp index cecb76d82..6b47d95c7 100644 --- a/Lib/Stack.hpp +++ b/Lib/Stack.hpp @@ -330,6 +330,14 @@ class Stack _cursor++; } // Stack::push() + inline + void pushUnsafe(C elem) + { + ASS(_cursor < _end); + ::new(_cursor) C(std::move(elem)); + _cursor++; + } // Stack::push() + /** * Pop the stack and return the popped element. * @since 11/03/2006 Bellevue From cee055a55a025a78a77e4476a64af188b9e5f284 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 27 Sep 2024 16:58:04 +0200 Subject: [PATCH 15/64] Merge nodes into one uniform class --- Kernel/KBOComparator.cpp | 30 +++---- Kernel/LPOComparator.cpp | 26 +++--- Kernel/OrderingComparator.cpp | 124 ++++++++++++++------------- Kernel/OrderingComparator.hpp | 152 ++++++++++++++++++++++------------ 4 files changed, 194 insertions(+), 138 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 23ba2a74c..3a921f7cb 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -23,11 +23,6 @@ using namespace Shell; void KBOComparator::expandTermCase() { - // take temporary ownership of node - Branch nodeHolder = *_curr; - auto node = static_cast(nodeHolder.n.ptr()); - - ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& kbo = static_cast(_ord); // weight and variable balances first @@ -41,13 +36,13 @@ void KBOComparator::expandTermCase() #endif auto w = state->_weightDiff; decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); - Stack nonzeros; + ScopedPtr nonzeros(new Stack()); while (vit.hasNext()) { unsigned v; int cnt; vit.next(v,cnt); if (cnt!=0) { - nonzeros.push(make_pair(v,cnt)); + nonzeros->push(make_pair(v,cnt)); w-=cnt; // we have to remove the variable weights from w } if (cnt<0) { @@ -59,19 +54,24 @@ void KBOComparator::expandTermCase() state = nullptr; #endif + // take temporary ownership of node + Branch nodeHolder = *_curr; + auto node = nodeHolder._node(); + auto curr = _curr; // if the condition below does not hold, the weight/var balances are satisfied if (w < 0 || varInbalance) { - sort(nonzeros.begin(),nonzeros.end(),[](const auto& e1, const auto& e2) { + sort(nonzeros->begin(),nonzeros->end(),[](const auto& e1, const auto& e2) { return e1.second>e2.second; }); - *curr = Branch(w, std::move(nonzeros)); - curr->n->gtBranch = node->gtBranch; - curr->n->incBranch = node->incBranch; - curr = &curr->n->eqBranch; + *curr = Branch(w, nonzeros.release()); + curr->_node()->gtBranch = node->gtBranch; + curr->_node()->incBranch = node->incBranch; + curr = &curr->_node()->eqBranch; } + ASS(node->lhs.isTerm() && node->rhs.isTerm()); auto lhst = node->lhs.term(); auto rhst = node->rhs.term(); @@ -95,9 +95,9 @@ void KBOComparator::expandTermCase() auto lhsArg = *lhst->nthArgument(i); auto rhsArg = *rhst->nthArgument(i); *curr = Branch(lhsArg,rhsArg); - curr->n->gtBranch = node->gtBranch; - curr->n->incBranch = node->incBranch; - curr = &curr->n->eqBranch; + curr->_node()->gtBranch = node->gtBranch; + curr->_node()->incBranch = node->incBranch; + curr = &curr->_node()->eqBranch; } *curr = node->eqBranch; break; diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index d6c9f924e..462d97dcd 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -26,11 +26,11 @@ void LPOComparator::majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, ASS(branch); for (unsigned j = i; j < t->arity(); j++) { *branch = Branch(tl1,*t->nthArgument(j)); - branch->n->eqBranch = fail; - branch->n->incBranch = fail; - branch = &branch->n->gtBranch; + branch->_node()->eqBranch = fail; + branch->_node()->incBranch = fail; + branch = &branch->_node()->gtBranch; } - *branch = success; + *branch = std::move(success); } /** @@ -41,18 +41,18 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 ASS(branch); for (unsigned j = i; j < s->arity(); j++) { *branch = Branch(*s->nthArgument(j),tl2); - branch->n->eqBranch = success; - branch->n->gtBranch = success; - branch = &branch->n->incBranch; + branch->_node()->eqBranch = success; + branch->_node()->gtBranch = success; + branch = &branch->_node()->incBranch; } - *branch = fail; + *branch = std::move(fail); } void LPOComparator::expandTermCase() { // take temporary ownership of node - Branch nodeHolder = *_curr; - auto node = static_cast(nodeHolder.n.ptr()); + Branch nodeHolder = std::move(*_curr); + auto node = nodeHolder._node(); ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& lpo = static_cast(_ord); @@ -76,10 +76,10 @@ void LPOComparator::expandTermCase() auto t_arg = *rhs.term()->nthArgument(i); *curr = Branch(s_arg,t_arg); // greater branch is a majo chain - majoChain(&curr->n->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); + majoChain(&curr->_node()->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); // incomparable branch is an alpha chain - alphaChain(&curr->n->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); - curr = &curr->n->eqBranch; + alphaChain(&curr->_node()->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); + curr = &curr->_node()->eqBranch; } *curr = node->eqBranch; break; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index b53b6cad8..3cec65c38 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -42,10 +42,10 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& branch) { - out << branch.tag << (branch.ready?" ":"? "); - switch (branch.tag) { + out << branch._tag() << (branch._ready()?" ":"? "); + switch (branch._tag()) { case OrderingComparator::BranchTag::T_RESULT: { - auto n = static_cast(branch.n.ptr()); + auto n = branch._node(); if (n) { out << n->data << " "; } else { @@ -54,15 +54,15 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& br break; } case OrderingComparator::BranchTag::T_WEIGHT: { - auto n = static_cast(branch.n.ptr()); + auto n = branch._node(); out << n->w << " "; - for (const auto& [var, coeff] : n->varCoeffPairs) { + for (const auto& [var, coeff] : *n->varCoeffPairs) { out << "X" << var << " " << coeff << " "; } break; } case OrderingComparator::BranchTag::T_COMPARISON: { - auto n = static_cast(branch.n.ptr()); + auto n = branch._node(); out << n->lhs << " " << n->rhs; break; } @@ -75,7 +75,7 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) Stack> todo; todo.push(std::make_pair(&comp._root,0)); // Note: using this set we get a more compact representation - DHSet seen; + // DHSet seen; while (todo.isNonEmpty()) { auto kv = todo.pop(); @@ -87,17 +87,16 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } } str << *kv.first << std::endl; - if (kv.first->n/* && seen.insert(kv.first->n.ptr()) */) { - switch (kv.first->tag) { + if (kv.first->_node()/* && seen.insert(kv.first->n.ptr()) */) { + switch (kv.first->_tag()) { case OrderingComparator::BranchTag::T_RESULT: { - auto n = static_cast(kv.first->n.ptr()); - todo.push(std::make_pair(&n->alternative,kv.second+1)); + todo.push(std::make_pair(&kv.first->_node()->alternative,kv.second+1)); break; } default: { - todo.push(std::make_pair(&kv.first->n->incBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->n->eqBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->_node()->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->_node()->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->_node()->eqBranch,kv.second+1)); break; } } @@ -113,9 +112,9 @@ OrderingComparator::OrderingComparator(const Ordering& ord, const Stackn->getBranch(rel); + curr = &curr->_node()->getBranch(rel); } - *curr = Branch(result); + *curr = Branch(result, Branch()); } OrderingComparator::~OrderingComparator() = default; @@ -123,13 +122,13 @@ OrderingComparator::~OrderingComparator() = default; void* OrderingComparator::next(const SubstApplicator* applicator) { ASS(_curr); - while (_curr->n) { + while (_curr->_node()) { expand(); - ASS(_curr->ready); + ASS(_curr->_ready()); + auto node = _curr->_node(); - if (_curr->tag == BranchTag::T_RESULT) { - if (_curr && _curr->n) { - auto node = static_cast(_curr->n.ptr()); + if (_curr->_tag() == BranchTag::T_RESULT) { + if (node) { _curr = &node->alternative; return node->data; } @@ -137,20 +136,18 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } Ordering::Result comp = Ordering::INCOMPARABLE; - if (_curr->tag == BranchTag::T_COMPARISON) { + if (_curr->_tag() == BranchTag::T_COMPARISON) { - auto node = static_cast(_curr->n.ptr()); comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); _cache.push({ node->lhs, node->rhs, comp }); } else { - ASS(_curr->tag == BranchTag::T_WEIGHT); + ASS(_curr->_tag() == BranchTag::T_WEIGHT); const auto& kbo = static_cast(_ord); - auto node = static_cast(_curr->n.ptr()); auto weight = node->w; ZIArray varDiffs; - for (const auto& [var, coeff] : node->varCoeffPairs) { + for (const auto& [var, coeff] : *node->varCoeffPairs) { AppliedTerm tt(TermList::var(var), applicator, true); VariableIterator vit(tt.term); @@ -163,7 +160,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) goto loop_end; } } - auto w = kbo.computeWeight(tt); + int64_t w = kbo.computeWeight(tt); weight += coeff*w; // due to descending order of counts, // this also means failure @@ -179,7 +176,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } } loop_end: - _curr = &_curr->n->getBranch(comp); + _curr = &_curr->_node()->getBranch(comp); } return nullptr; } @@ -187,7 +184,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) void OrderingComparator::addAlternative(const OrderingComparator& other) { auto& branch = other._root; - ASS(!branch.ready); // branch should be unexpanded + ASS(!branch._ready()); // branch should be unexpanded static unsigned ts = 0; ts++; @@ -197,11 +194,11 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) auto pushBranches = [](Branch* b, const Branch& other) { // if other branch is unsuccessful, do nothing - if (other.tag == BranchTag::T_RESULT && !other.n) { + if (other._tag() == BranchTag::T_RESULT && !other._node()) { return; } // if this branch is unsuccessful, replace this with other - if (b->tag == BranchTag::T_RESULT && !b->n) { + if (b->_tag() == BranchTag::T_RESULT && !b->_node()) { *b = other; return; } @@ -211,17 +208,18 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) pushBranches(&_root, branch); while (todo.isNonEmpty()) { - auto [currB, otherB] = todo.pop(); - ASS(currB->n); - ASS(otherB.n); + auto kv = todo.pop(); + auto currB = kv.first; + auto otherB = kv.second; + ASS(currB->_node()); + ASS(otherB._node()); // if we already checked this branch, continue - if (currB->n->getTs()==ts) { + if (currB->_node()->ts == ts) { continue; } - currB->n->setTs(ts); - if (currB->tag == BranchTag::T_RESULT) { - auto n = static_cast(currB->n.ptr()); - pushBranches(&n->alternative, otherB); + currB->_node()->ts = ts; + if (currB->_tag() == BranchTag::T_RESULT) { + pushBranches(&currB->_node()->alternative, otherB); continue; } // TODO: results should be only pushed down @@ -238,28 +236,26 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) // continue; // } // } - pushBranches(&currB->n->eqBranch, otherB); - pushBranches(&currB->n->gtBranch, otherB); - pushBranches(&currB->n->incBranch, otherB); + pushBranches(&currB->_node()->eqBranch, otherB); + pushBranches(&currB->_node()->gtBranch, otherB); + pushBranches(&currB->_node()->incBranch, otherB); } } void OrderingComparator::expand() { - while (!_curr->ready) + while (!_curr->_ready()) { // take temporary ownership of node Branch nodeHolder = *_curr; + auto node = nodeHolder._node(); - if (_curr->tag == BranchTag::T_RESULT) { - auto node = static_cast(nodeHolder.n.ptr()); - *_curr = Branch(node->data); - static_cast(_curr->n.ptr())->alternative = node->alternative; - _curr->ready = true; + if (_curr->_tag() == BranchTag::T_RESULT) { + *_curr = Branch(node->data, node->alternative); + _curr->_setReady(true); return; } - ASS(_curr->tag != BranchTag::T_WEIGHT); - auto node = static_cast(nodeHolder.n.ptr()); + ASS(_curr->_tag() != BranchTag::T_WEIGHT); // Use compare here to filter out as many // precomputable comparisons as possible. @@ -285,15 +281,15 @@ void OrderingComparator::expand() void OrderingComparator::expandTermCase() { - ASS(!_curr->ready); - _curr->ready = true; + ASS(!_curr->_ready()); + _curr->_setReady(true); } bool OrderingComparator::tryExpandVarCase() { // take temporary ownership of node Branch nodeHolder = *_curr; - auto node = static_cast(nodeHolder.n.ptr()); + auto node = nodeHolder._node(); // If we have a variable, we cannot preprocess further. if (!node->lhs.isVar() && !node->rhs.isVar()) { @@ -328,11 +324,25 @@ bool OrderingComparator::tryExpandVarCase() } // make a fresh copy *_curr = Branch(node->lhs, node->rhs); - _curr->n->eqBranch = node->eqBranch; - _curr->n->gtBranch = node->gtBranch; - _curr->n->incBranch = node->incBranch; - _curr->ready = true; + _curr->_node()->eqBranch = node->eqBranch; + _curr->_node()->gtBranch = node->gtBranch; + _curr->_node()->incBranch = node->incBranch; + _curr->_setReady(true); return true; } +void OrderingComparator::Node::incRefCnt() +{ + refcnt++; +} + +void OrderingComparator::Node::decRefCnt() +{ + ASS(refcnt); + refcnt--; + if (!refcnt) { + delete this; + } +} + } \ No newline at end of file diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 35c86f4d9..d07425cc1 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -50,30 +50,93 @@ struct OrderingComparator virtual void expandTermCase(); bool tryExpandVarCase(); - enum class BranchTag : uint8_t { - T_RESULT, - T_COMPARISON, - T_WEIGHT, + enum BranchTag { + T_RESULT = 0u, + T_COMPARISON = 1u, + T_WEIGHT = 2u, }; struct Branch { - BranchTag tag; - SmartPtr n; - bool ready = false; - - Branch() : tag(BranchTag::T_RESULT), ready(true) {} - explicit Branch(void* data) : tag(BranchTag::T_RESULT), n(new ResultNode(data)) {} - explicit Branch(TermList lhs, TermList rhs) - : tag(BranchTag::T_COMPARISON), n(new ComparisonNode(lhs, rhs)) {} - explicit Branch(int w, Stack>&& varCoeffPairs) - : tag(BranchTag::T_WEIGHT), n(new WeightNode(w, std::move(varCoeffPairs))), ready(true) {} + static_assert(alignof(Node*)>T_WEIGHT); + static constexpr unsigned + READY_BITS_START = 0, + READY_BITS_END = READY_BITS_START + 1, + TAG_BITS_START = READY_BITS_END, + TAG_BITS_END = TAG_BITS_START + 2, + NODE_BITS_START = TAG_BITS_END, + NODE_BITS_END = CHAR_BIT * sizeof(Node*); + + BITFIELD64_GET_AND_SET(bool, ready, Ready, READY) + BITFIELD64_GET_AND_SET(unsigned, tag, Tag, TAG) + // BITFIELD64_GET_AND_SET_PTR(Node*, node, Node, NODE) + Node* _node() const { return reinterpret_cast(BitUtils::getBits(_content)); } + void _setNode(Node* node) { + auto prev = _node(); + if (prev) { + prev->decRefCnt(); + } + if (node) { + node->incRefCnt(); + } + BitUtils::setBits(_content, reinterpret_cast(node)); + } + + Branch() { _setTag(T_RESULT); _setReady(true); _setNode(nullptr); } + explicit Branch(void* data, Branch alternative) { + _setTag(T_RESULT); + _setNode(new Node(data, alternative)); + } + explicit Branch(TermList lhs, TermList rhs) { + _setTag(T_COMPARISON); + _setNode(new Node(lhs, rhs)); + } + explicit Branch(int64_t w, Stack>* varCoeffPairs) { + _setTag(T_WEIGHT); + _setNode(new Node(w, varCoeffPairs)); + _setReady(true); + } + // Branch(const Branch& other) = delete; + // Branch& operator=(const Branch& other) = delete; + Branch(const Branch& other) { + _setTag(other._tag()); + _setReady(other._ready()); + _setNode(other._node()); + } + Branch& operator=(const Branch& other) { + if (&other==this) { + return *this; + } + _setTag(other._tag()); + _setReady(other._ready()); + _setNode(other._node()); + return *this; + } + Branch(Branch&& other) : _content(other._content) { + other._content = 0; + } + Branch& operator=(Branch&& other) { + if (&other==this) { + return *this; + } + _content = other._content; + other._content = 0; + return *this; + } + + private: + uint64_t _content = 0; }; friend std::ostream& operator<<(std::ostream& out, const Branch& branch); friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); + using VarCoeffPair = std::pair; + struct Node { - virtual ~Node() = default; + static_assert(sizeof(uint64_t) == sizeof(Branch)); + static_assert(sizeof(uint64_t) == sizeof(TermList)); + static_assert(sizeof(uint64_t) == sizeof(void*)); + static_assert(sizeof(uint64_t) == sizeof(int64_t)); auto& getBranch(Ordering::Result r) { switch (r) { @@ -88,49 +151,32 @@ struct OrderingComparator } } - void setTs(unsigned val) { ts = val; } - unsigned getTs() const { return ts; } + explicit Node(void* data, Branch alternative) + : data(data), alternative(alternative) {} + explicit Node(TermList lhs, TermList rhs) + : lhs(lhs), rhs(rhs) {} + explicit Node(uint64_t w, Stack* varCoeffPairs) + : w(w), varCoeffPairs(varCoeffPairs) {} + + void incRefCnt(); + void decRefCnt(); + + union { + void* data = nullptr; + TermList lhs; + int64_t w; + }; + union { + Branch alternative; + TermList rhs; + Stack* varCoeffPairs; + }; Branch eqBranch; Branch gtBranch; Branch incBranch; unsigned ts; - }; - - class ResultNode : public Node { - ResultNode(void* data) : data(data) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - void* data; - Branch alternative; - }; - - class ComparisonNode : public Node { - ComparisonNode(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - TermList lhs; - TermList rhs; - }; - - using VarCoeffPair = std::pair; - - class WeightNode : public Node { - WeightNode(int w, Stack&& varCoeffPairs) - : w(w), varCoeffPairs(varCoeffPairs) {} - - // only allow calling ctor from Branch - friend struct Branch; - - public: - int w; - Stack varCoeffPairs; + unsigned refcnt; }; const Ordering& _ord; From a49093892e47aa0a7e1105bfab01df927eebf3cf Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sun, 29 Sep 2024 10:01:40 +0200 Subject: [PATCH 16/64] Refactor OrderingComparator class a bit --- Indexing/Index.hpp | 6 +- Kernel/KBOComparator.cpp | 14 +- Kernel/LPOComparator.cpp | 20 +-- Kernel/OrderingComparator.cpp | 179 ++++++++++++++++--------- Kernel/OrderingComparator.hpp | 91 ++++--------- Shell/ConditionalRedundancyHandler.cpp | 3 +- 6 files changed, 167 insertions(+), 146 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 6c5b85807..ab9c1c32b 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -177,7 +177,11 @@ struct DemodulatorDataContainer { return false; } dds.loadFromIterator(other.dds.iter()); - comparator->addAlternative(*other.comparator.get()); + Stack ordCons; + if (!other.dds[0]->preordered) { + ordCons.push({ other.dds[0]->term, other.dds[0]->rhs, Ordering::GREATER }); + } + comparator->insert(ordCons, other.dds[0]); return true; } diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 3a921f7cb..efef966ab 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -56,7 +56,7 @@ void KBOComparator::expandTermCase() // take temporary ownership of node Branch nodeHolder = *_curr; - auto node = nodeHolder._node(); + auto node = nodeHolder.node(); auto curr = _curr; @@ -66,9 +66,9 @@ void KBOComparator::expandTermCase() return e1.second>e2.second; }); *curr = Branch(w, nonzeros.release()); - curr->_node()->gtBranch = node->gtBranch; - curr->_node()->incBranch = node->incBranch; - curr = &curr->_node()->eqBranch; + curr->node()->gtBranch = node->gtBranch; + curr->node()->incBranch = node->incBranch; + curr = &curr->node()->eqBranch; } ASS(node->lhs.isTerm() && node->rhs.isTerm()); @@ -95,9 +95,9 @@ void KBOComparator::expandTermCase() auto lhsArg = *lhst->nthArgument(i); auto rhsArg = *rhst->nthArgument(i); *curr = Branch(lhsArg,rhsArg); - curr->_node()->gtBranch = node->gtBranch; - curr->_node()->incBranch = node->incBranch; - curr = &curr->_node()->eqBranch; + curr->node()->gtBranch = node->gtBranch; + curr->node()->incBranch = node->incBranch; + curr = &curr->node()->eqBranch; } *curr = node->eqBranch; break; diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 462d97dcd..c3fcd9fa4 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -26,9 +26,9 @@ void LPOComparator::majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, ASS(branch); for (unsigned j = i; j < t->arity(); j++) { *branch = Branch(tl1,*t->nthArgument(j)); - branch->_node()->eqBranch = fail; - branch->_node()->incBranch = fail; - branch = &branch->_node()->gtBranch; + branch->node()->eqBranch = fail; + branch->node()->incBranch = fail; + branch = &branch->node()->gtBranch; } *branch = std::move(success); } @@ -41,9 +41,9 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 ASS(branch); for (unsigned j = i; j < s->arity(); j++) { *branch = Branch(*s->nthArgument(j),tl2); - branch->_node()->eqBranch = success; - branch->_node()->gtBranch = success; - branch = &branch->_node()->incBranch; + branch->node()->eqBranch = success; + branch->node()->gtBranch = success; + branch = &branch->node()->incBranch; } *branch = std::move(fail); } @@ -52,7 +52,7 @@ void LPOComparator::expandTermCase() { // take temporary ownership of node Branch nodeHolder = std::move(*_curr); - auto node = nodeHolder._node(); + auto node = nodeHolder.node(); ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& lpo = static_cast(_ord); @@ -76,10 +76,10 @@ void LPOComparator::expandTermCase() auto t_arg = *rhs.term()->nthArgument(i); *curr = Branch(s_arg,t_arg); // greater branch is a majo chain - majoChain(&curr->_node()->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); + majoChain(&curr->node()->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); // incomparable branch is an alpha chain - alphaChain(&curr->_node()->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); - curr = &curr->_node()->eqBranch; + alphaChain(&curr->node()->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); + curr = &curr->node()->eqBranch; } *curr = node->eqBranch; break; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 3cec65c38..cd0d228d0 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -40,30 +40,23 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& return out; } -std::ostream& operator<<(std::ostream& out, const OrderingComparator::Branch& branch) +std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node) { - out << branch._tag() << (branch._ready()?" ":"? "); - switch (branch._tag()) { + out << (OrderingComparator::BranchTag)node.tag << (node.ready?" ":"? "); + switch (node.tag) { case OrderingComparator::BranchTag::T_RESULT: { - auto n = branch._node(); - if (n) { - out << n->data << " "; - } else { - out << "0x0 "; - } + out << node.data; break; } case OrderingComparator::BranchTag::T_WEIGHT: { - auto n = branch._node(); - out << n->w << " "; - for (const auto& [var, coeff] : *n->varCoeffPairs) { + out << node.w << " "; + for (const auto& [var, coeff] : *node.varCoeffPairs) { out << "X" << var << " " << coeff << " "; } break; } case OrderingComparator::BranchTag::T_COMPARISON: { - auto n = branch._node(); - out << n->lhs << " " << n->rhs; + out << node.lhs << " " << node.rhs; break; } } @@ -75,7 +68,7 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) Stack> todo; todo.push(std::make_pair(&comp._root,0)); // Note: using this set we get a more compact representation - // DHSet seen; + DHSet seen; while (todo.isNonEmpty()) { auto kv = todo.pop(); @@ -86,17 +79,18 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) str << " | "; } } - str << *kv.first << std::endl; - if (kv.first->_node()/* && seen.insert(kv.first->n.ptr()) */) { - switch (kv.first->_tag()) { + if (!kv.first->node()) { + str << "c 0x0" << std::endl; + } else if (seen.insert(kv.first->node())) { + switch (kv.first->node()->tag) { case OrderingComparator::BranchTag::T_RESULT: { - todo.push(std::make_pair(&kv.first->_node()->alternative,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); break; } default: { - todo.push(std::make_pair(&kv.first->_node()->incBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->_node()->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->_node()->eqBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); break; } } @@ -112,7 +106,7 @@ OrderingComparator::OrderingComparator(const Ordering& ord, const Stack_node()->getBranch(rel); + curr = &curr->node()->getBranch(rel); } *curr = Branch(result, Branch()); } @@ -122,27 +116,27 @@ OrderingComparator::~OrderingComparator() = default; void* OrderingComparator::next(const SubstApplicator* applicator) { ASS(_curr); - while (_curr->_node()) { + while (_curr->node()) { expand(); - ASS(_curr->_ready()); - auto node = _curr->_node(); - - if (_curr->_tag() == BranchTag::T_RESULT) { - if (node) { - _curr = &node->alternative; - return node->data; - } + auto node = _curr->node(); + if (!node) { return nullptr; } + ASS(node->ready); + + if (node->tag == BranchTag::T_RESULT) { + _curr = &node->alternative; + return node->data; + } Ordering::Result comp = Ordering::INCOMPARABLE; - if (_curr->_tag() == BranchTag::T_COMPARISON) { + if (node->tag == BranchTag::T_COMPARISON) { comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); _cache.push({ node->lhs, node->rhs, comp }); } else { - ASS(_curr->_tag() == BranchTag::T_WEIGHT); + ASS(node->tag == BranchTag::T_WEIGHT); const auto& kbo = static_cast(_ord); auto weight = node->w; @@ -176,15 +170,21 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } } loop_end: - _curr = &_curr->_node()->getBranch(comp); + _curr = &_curr->node()->getBranch(comp); } return nullptr; } -void OrderingComparator::addAlternative(const OrderingComparator& other) +void OrderingComparator::insert(const Stack& comps, void* result) { - auto& branch = other._root; - ASS(!branch._ready()); // branch should be unexpanded + ASS(result); + Branch addedRoot; + auto curr = &addedRoot; + for (const auto& [lhs,rhs,rel] : comps) { + *curr = OrderingComparator::Branch(lhs, rhs); + curr = &curr->node()->getBranch(rel); + } + *curr = Branch(result, Branch()); static unsigned ts = 0; ts++; @@ -194,32 +194,32 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) auto pushBranches = [](Branch* b, const Branch& other) { // if other branch is unsuccessful, do nothing - if (other._tag() == BranchTag::T_RESULT && !other._node()) { + if (!other.node()) { return; } // if this branch is unsuccessful, replace this with other - if (b->_tag() == BranchTag::T_RESULT && !b->_node()) { + if (!b->node()) { *b = other; return; } todo.push(std::make_pair(b,other)); }; - pushBranches(&_root, branch); + pushBranches(&_root, addedRoot); while (todo.isNonEmpty()) { auto kv = todo.pop(); auto currB = kv.first; auto otherB = kv.second; - ASS(currB->_node()); - ASS(otherB._node()); + ASS(currB->node()); + ASS(otherB.node()); // if we already checked this branch, continue - if (currB->_node()->ts == ts) { + if (currB->node()->ts == ts) { continue; } - currB->_node()->ts = ts; - if (currB->_tag() == BranchTag::T_RESULT) { - pushBranches(&currB->_node()->alternative, otherB); + currB->node()->ts = ts; + if (currB->node()->tag == BranchTag::T_RESULT) { + pushBranches(&currB->node()->alternative, otherB); continue; } // TODO: results should be only pushed down @@ -236,26 +236,27 @@ void OrderingComparator::addAlternative(const OrderingComparator& other) // continue; // } // } - pushBranches(&currB->_node()->eqBranch, otherB); - pushBranches(&currB->_node()->gtBranch, otherB); - pushBranches(&currB->_node()->incBranch, otherB); + pushBranches(&currB->node()->eqBranch, otherB); + pushBranches(&currB->node()->gtBranch, otherB); + pushBranches(&currB->node()->incBranch, otherB); } } void OrderingComparator::expand() { - while (!_curr->_ready()) + ASS(_curr->node()); + while (_curr->node() && !_curr->node()->ready) { // take temporary ownership of node Branch nodeHolder = *_curr; - auto node = nodeHolder._node(); + auto node = nodeHolder.node(); - if (_curr->_tag() == BranchTag::T_RESULT) { + if (node->tag == BranchTag::T_RESULT) { *_curr = Branch(node->data, node->alternative); - _curr->_setReady(true); + _curr->node()->ready = true; return; } - ASS(_curr->_tag() != BranchTag::T_WEIGHT); + ASS(node->tag != BranchTag::T_WEIGHT); // Use compare here to filter out as many // precomputable comparisons as possible. @@ -281,15 +282,15 @@ void OrderingComparator::expand() void OrderingComparator::expandTermCase() { - ASS(!_curr->_ready()); - _curr->_setReady(true); + ASS(_curr->node() && !_curr->node()->ready); + _curr->node()->ready = true; } bool OrderingComparator::tryExpandVarCase() { // take temporary ownership of node Branch nodeHolder = *_curr; - auto node = nodeHolder._node(); + auto node = nodeHolder.node(); // If we have a variable, we cannot preprocess further. if (!node->lhs.isVar() && !node->rhs.isVar()) { @@ -324,13 +325,67 @@ bool OrderingComparator::tryExpandVarCase() } // make a fresh copy *_curr = Branch(node->lhs, node->rhs); - _curr->_node()->eqBranch = node->eqBranch; - _curr->_node()->gtBranch = node->gtBranch; - _curr->_node()->incBranch = node->incBranch; - _curr->_setReady(true); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->incBranch = node->incBranch; + _curr->node()->ready = true; return true; } +OrderingComparator::Branch::Branch() +{ + setNode(nullptr); +} + +OrderingComparator::Branch::~Branch() +{ + // _setNode(nullptr); +} + +OrderingComparator::Branch::Branch(const Branch& other) +{ + setNode(other.node()); +} + +OrderingComparator::Branch& OrderingComparator::Branch::operator=(const Branch& other) +{ + if (&other==this) { + return *this; + } + setNode(other.node()); + return *this; +} + +OrderingComparator::Branch::Branch(Branch&& other) + : _node(other._node) +{ + other._node = nullptr; +} + +OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other) +{ + if (&other==this) { + return *this; + } + _node = other._node; + other._node = nullptr; + return *this; +} + +OrderingComparator::Node::~Node() +{ + switch(tag) { + case T_RESULT: + // alternative.~Branch(); + break; + case T_COMPARISON: + break; + case T_WEIGHT: + delete varCoeffPairs; + break; + } +} + void OrderingComparator::Node::incRefCnt() { refcnt++; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index d07425cc1..dac5a3b4c 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -41,7 +41,7 @@ struct OrderingComparator void reset() { _curr = &_root; _cache.reset(); } void* next(const SubstApplicator* applicator); - void addAlternative(const OrderingComparator& other); + void insert(const Stack& comps, void* result); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); @@ -57,77 +57,35 @@ struct OrderingComparator }; struct Branch { - static_assert(alignof(Node*)>T_WEIGHT); - static constexpr unsigned - READY_BITS_START = 0, - READY_BITS_END = READY_BITS_START + 1, - TAG_BITS_START = READY_BITS_END, - TAG_BITS_END = TAG_BITS_START + 2, - NODE_BITS_START = TAG_BITS_END, - NODE_BITS_END = CHAR_BIT * sizeof(Node*); - - BITFIELD64_GET_AND_SET(bool, ready, Ready, READY) - BITFIELD64_GET_AND_SET(unsigned, tag, Tag, TAG) - // BITFIELD64_GET_AND_SET_PTR(Node*, node, Node, NODE) - Node* _node() const { return reinterpret_cast(BitUtils::getBits(_content)); } - void _setNode(Node* node) { - auto prev = _node(); - if (prev) { - prev->decRefCnt(); + Node* node() const { return _node; } + void setNode(Node* node) { + if (_node) { + _node->decRefCnt(); } - if (node) { - node->incRefCnt(); + _node = node; + if (_node) { + _node->incRefCnt(); } - BitUtils::setBits(_content, reinterpret_cast(node)); } - Branch() { _setTag(T_RESULT); _setReady(true); _setNode(nullptr); } - explicit Branch(void* data, Branch alternative) { - _setTag(T_RESULT); - _setNode(new Node(data, alternative)); - } - explicit Branch(TermList lhs, TermList rhs) { - _setTag(T_COMPARISON); - _setNode(new Node(lhs, rhs)); - } - explicit Branch(int64_t w, Stack>* varCoeffPairs) { - _setTag(T_WEIGHT); - _setNode(new Node(w, varCoeffPairs)); - _setReady(true); + Branch(); + template Branch(S&& s, T&& t) { + setNode(new Node(std::forward(s), std::forward(t))); } + ~Branch(); // Branch(const Branch& other) = delete; // Branch& operator=(const Branch& other) = delete; - Branch(const Branch& other) { - _setTag(other._tag()); - _setReady(other._ready()); - _setNode(other._node()); - } - Branch& operator=(const Branch& other) { - if (&other==this) { - return *this; - } - _setTag(other._tag()); - _setReady(other._ready()); - _setNode(other._node()); - return *this; - } - Branch(Branch&& other) : _content(other._content) { - other._content = 0; - } - Branch& operator=(Branch&& other) { - if (&other==this) { - return *this; - } - _content = other._content; - other._content = 0; - return *this; - } + Branch(const Branch& other); + Branch& operator=(const Branch& other); + Branch(Branch&& other); + Branch& operator=(Branch&& other); private: - uint64_t _content = 0; + Node* _node = nullptr; }; - friend std::ostream& operator<<(std::ostream& out, const Branch& branch); + friend std::ostream& operator<<(std::ostream& out, const Node& node); + // friend std::ostream& operator<<(std::ostream& out, const Branch& branch); friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); using VarCoeffPair = std::pair; @@ -152,15 +110,20 @@ struct OrderingComparator } explicit Node(void* data, Branch alternative) - : data(data), alternative(alternative) {} + : tag(T_RESULT), ready(false), data(data), alternative(alternative) {} explicit Node(TermList lhs, TermList rhs) - : lhs(lhs), rhs(rhs) {} + : tag(T_COMPARISON), ready(false), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) - : w(w), varCoeffPairs(varCoeffPairs) {} + : tag(T_WEIGHT), ready(true), w(w), varCoeffPairs(varCoeffPairs) {} + + ~Node(); void incRefCnt(); void decRefCnt(); + BranchTag tag; + bool ready; + union { void* data = nullptr; TermList lhs; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 9c685c85c..d5b6bd858 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -128,8 +128,7 @@ class ConditionalRedundancyHandler::ConstraintIndex #if DEBUG_ORDERING entries->entries.push(ptr); #endif - auto comp = ord->createComparator(ptr->ordCons, ptr); - entries->comparator->addAlternative(*comp.get()); + entries->comparator->insert(ptr->ordCons, ptr); return true; } From db1bdd4d43ed7eb06cf3c92781f07c4ad24ce2ef Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sun, 29 Sep 2024 12:26:51 +0200 Subject: [PATCH 17/64] Properly destruct branches and nodes; add fail node to make it easier to insert --- Indexing/Index.hpp | 2 +- Kernel/OrderingComparator.cpp | 143 ++++++++++++++-------------------- Kernel/OrderingComparator.hpp | 4 +- 3 files changed, 61 insertions(+), 88 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index ab9c1c32b..2cee4410f 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -212,7 +212,7 @@ struct DemodulatorDataContainer { bool canBeDeleted() const { return dds.isEmpty(); } friend std::ostream& operator<<(std::ostream& out, DemodulatorDataContainer const& self) - { return out << "TODO"; } + { return out << *self.comparator; } }; template diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index cd0d228d0..d3545567c 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -79,20 +79,16 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) str << " | "; } } - if (!kv.first->node()) { - str << "c 0x0" << std::endl; - } else if (seen.insert(kv.first->node())) { - switch (kv.first->node()->tag) { - case OrderingComparator::BranchTag::T_RESULT: { + str << *kv.first->node() << std::endl; + if (seen.insert(kv.first->node())) { + if (kv.first->node()->tag==OrderingComparator::BranchTag::T_RESULT) { + if (kv.first->node()->data) { todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); - break; - } - default: { - todo.push(std::make_pair(&kv.first->node()->incBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); - break; } + } else { + todo.push(std::make_pair(&kv.first->node()->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); } } } @@ -100,15 +96,22 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) -: _ord(ord), _root(), _curr(&_root) +: _ord(ord), _root(), _fail(nullptr, Branch()), _curr(&_root) { ASS(result); + static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; auto curr = &_root; for (const auto& [lhs,rhs,rel] : comps) { *curr = OrderingComparator::Branch(lhs, rhs); + for (unsigned i = 0; i < 3; i++) { + if (ordVals[i] != comps[0].rel) { + curr->node()->getBranch(ordVals[i]) = _fail; + } + } curr = &curr->node()->getBranch(rel); } - *curr = Branch(result, Branch()); + *curr = Branch(result, _fail); + _fail.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; @@ -116,15 +119,15 @@ OrderingComparator::~OrderingComparator() = default; void* OrderingComparator::next(const SubstApplicator* applicator) { ASS(_curr); - while (_curr->node()) { + for (;;) { expand(); auto node = _curr->node(); - if (!node) { - return nullptr; - } ASS(node->ready); if (node->tag == BranchTag::T_RESULT) { + if (!node->data) { + return nullptr; + } _curr = &node->alternative; return node->data; } @@ -170,7 +173,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } } loop_end: - _curr = &_curr->node()->getBranch(comp); + _curr = &node->getBranch(comp); } return nullptr; } @@ -178,68 +181,43 @@ void* OrderingComparator::next(const SubstApplicator* applicator) void OrderingComparator::insert(const Stack& comps, void* result) { ASS(result); - Branch addedRoot; - auto curr = &addedRoot; - for (const auto& [lhs,rhs,rel] : comps) { - *curr = OrderingComparator::Branch(lhs, rhs); - curr = &curr->node()->getBranch(rel); - } - *curr = Branch(result, Branch()); - - static unsigned ts = 0; - ts++; - - static Stack> todo; - todo.reset(); - - auto pushBranches = [](Branch* b, const Branch& other) { - // if other branch is unsuccessful, do nothing - if (!other.node()) { - return; - } - // if this branch is unsuccessful, replace this with other - if (!b->node()) { - *b = other; - return; - } - todo.push(std::make_pair(b,other)); - }; - - pushBranches(&_root, addedRoot); - - while (todo.isNonEmpty()) { - auto kv = todo.pop(); - auto currB = kv.first; - auto otherB = kv.second; - ASS(currB->node()); - ASS(otherB.node()); - // if we already checked this branch, continue - if (currB->node()->ts == ts) { - continue; + static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; + // we mutate current fail node and add a new one + auto curr = &_fail; + Branch newFail(nullptr, Branch()); + newFail.node()->ready = true; + + curr->node()->~Node(); + curr->node()->ready = false; + + if (comps.isNonEmpty()) { + curr->node()->tag = T_COMPARISON; + curr->node()->rhs = comps[0].rhs; + curr->node()->lhs = comps[0].lhs; + for (unsigned i = 0; i < 3; i++) { + if (ordVals[i] != comps[0].rel) { + curr->node()->getBranch(ordVals[i]) = newFail; + } } - currB->node()->ts = ts; - if (currB->node()->tag == BranchTag::T_RESULT) { - pushBranches(&currB->node()->alternative, otherB); - continue; + curr = &curr->node()->getBranch(comps[0].rel); + for (unsigned i = 1; i < comps.size(); i++) { + auto [lhs,rhs,rel] = comps[i]; + *curr = OrderingComparator::Branch(lhs, rhs); + for (unsigned i = 0; i < 3; i++) { + if (ordVals[i] != rel) { + curr->node()->getBranch(ordVals[i]) = newFail; + } + } + curr = &curr->node()->getBranch(rel); } - // TODO: results should be only pushed down - // in this case onto successful branches - // - // if (currB->tag == BranchTag::T_UNKNOWN && currB->tag != BranchTag::T_COMPARISON) { - // // both must be comparison nodes - // auto n = static_cast(currB->n.ptr()); - // auto o = static_cast(otherB.n.ptr()); - // if (n->lhs == o->lhs && n->rhs == o->rhs) { - // pushBranches(&currB->n->eqBranch, otherB.n->eqBranch); - // pushBranches(&currB->n->gtBranch, otherB.n->gtBranch); - // pushBranches(&currB->n->incBranch, otherB.n->incBranch); - // continue; - // } - // } - pushBranches(&currB->node()->eqBranch, otherB); - pushBranches(&currB->node()->gtBranch, otherB); - pushBranches(&currB->node()->incBranch, otherB); + *curr = Branch(result, newFail); + } else { + curr->node()->tag = T_RESULT; + curr->node()->data = result; + curr->node()->alternative = newFail; } + + _fail = newFail; } void OrderingComparator::expand() @@ -332,14 +310,9 @@ bool OrderingComparator::tryExpandVarCase() return true; } -OrderingComparator::Branch::Branch() -{ - setNode(nullptr); -} - OrderingComparator::Branch::~Branch() { - // _setNode(nullptr); + setNode(nullptr); } OrderingComparator::Branch::Branch(const Branch& other) @@ -376,7 +349,7 @@ OrderingComparator::Node::~Node() { switch(tag) { case T_RESULT: - // alternative.~Branch(); + alternative.~Branch(); break; case T_COMPARISON: break; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index dac5a3b4c..f8e3e0e71 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -68,7 +68,7 @@ struct OrderingComparator } } - Branch(); + Branch() = default; template Branch(S&& s, T&& t) { setNode(new Node(std::forward(s), std::forward(t))); } @@ -138,12 +138,12 @@ struct OrderingComparator Branch eqBranch; Branch gtBranch; Branch incBranch; - unsigned ts; unsigned refcnt; }; const Ordering& _ord; Branch _root; + Branch _fail; Branch* _curr; Stack _cache; }; From eee26b07a83d4be174036ad9b75c91614ef2bbd9 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 30 Sep 2024 12:06:54 +0200 Subject: [PATCH 18/64] Propagate traces in nodes instead of calculating it during execution; it leaks currently --- Kernel/KBOComparator.cpp | 2 + Kernel/OrderingComparator.cpp | 123 ++++++++++++++++++++++++++-------- Kernel/OrderingComparator.hpp | 26 ++++--- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index efef966ab..ff5989092 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -68,6 +68,8 @@ void KBOComparator::expandTermCase() *curr = Branch(w, nonzeros.release()); curr->node()->gtBranch = node->gtBranch; curr->node()->incBranch = node->incBranch; + curr->node()->trace = getCurrentTrace(); + curr->node()->ready = true; curr = &curr->node()->eqBranch; } diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index d3545567c..cbeb9a662 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -96,7 +96,7 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) -: _ord(ord), _root(), _fail(nullptr, Branch()), _curr(&_root) +: _ord(ord), _root(), _fail(nullptr, Branch()), _curr(&_root), _prev(nullptr) { ASS(result); static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; @@ -128,6 +128,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) if (!node->data) { return nullptr; } + _prev = _curr; _curr = &node->alternative; return node->data; } @@ -136,7 +137,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) if (node->tag == BranchTag::T_COMPARISON) { comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); - _cache.push({ node->lhs, node->rhs, comp }); + // _trace.set({ node->lhs, node->rhs, comp }); } else { ASS(node->tag == BranchTag::T_WEIGHT); @@ -173,6 +174,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } } loop_end: + _prev = _curr; _curr = &node->getBranch(comp); } return nullptr; @@ -192,8 +194,8 @@ void OrderingComparator::insert(const Stack& comps, void* if (comps.isNonEmpty()) { curr->node()->tag = T_COMPARISON; - curr->node()->rhs = comps[0].rhs; curr->node()->lhs = comps[0].lhs; + curr->node()->rhs = comps[0].rhs; for (unsigned i = 0; i < 3; i++) { if (ordVals[i] != comps[0].rel) { curr->node()->getBranch(ordVals[i]) = newFail; @@ -231,6 +233,7 @@ void OrderingComparator::expand() if (node->tag == BranchTag::T_RESULT) { *_curr = Branch(node->data, node->alternative); + _curr->node()->trace = getCurrentTrace(); _curr->node()->ready = true; return; } @@ -274,32 +277,17 @@ bool OrderingComparator::tryExpandVarCase() if (!node->lhs.isVar() && !node->rhs.isVar()) { return false; } - // try cache - for (const auto& [s,t,r] : _cache) { - if (s == node->lhs && t == node->rhs) { - if (r == Ordering::GREATER) { - *_curr = node->gtBranch; - } else if (r == Ordering::EQUAL) { - *_curr = node->eqBranch; - } else { - ASS_EQ(r, Ordering::INCOMPARABLE); - *_curr = node->incBranch; - } - return true; - } - - if (s == node->rhs && t == node->lhs && r != Ordering::INCOMPARABLE) { - if (r == Ordering::GREATER) { - *_curr = node->incBranch; - } else { - ASS_EQ(r, Ordering::EQUAL); - *_curr = node->eqBranch; - } - // Note: since we use isGreater which results - // in INCOMPARABLE when compare would be LESS, - // the INCOMPARABLE result we cannot use here - return true; + auto trace = getCurrentTrace(); + Ordering::Result val; + if (trace->get(node->lhs, node->rhs, val)) { + if (val == Ordering::GREATER) { + *_curr = node->gtBranch; + } else if (val == Ordering::EQUAL) { + *_curr = node->eqBranch; + } else { + *_curr = node->incBranch; } + return true; } // make a fresh copy *_curr = Branch(node->lhs, node->rhs); @@ -307,9 +295,88 @@ bool OrderingComparator::tryExpandVarCase() _curr->node()->gtBranch = node->gtBranch; _curr->node()->incBranch = node->incBranch; _curr->node()->ready = true; + _curr->node()->trace = trace; return true; } +bool OrderingComparator::Trace::get(TermList lhs, TermList rhs, Ordering::Result& res) const +{ + for (const auto& [s,t,r] : st) { + if (s == lhs && t == rhs) { + ASS_NEQ(r,Ordering::LESS); + res = r; + return true; + } + + // Note: since we use isGreater which results + // in INCOMPARABLE when compare would be LESS, + // the INCOMPARABLE result we cannot use here + if (s == rhs && t == lhs && r != Ordering::INCOMPARABLE) { + res = Ordering::reverse(r); + return true; + } + } + return false; +} + +bool OrderingComparator::Trace::set(Ordering::Constraint con) +{ + st.push(con); + return true; +} + +OrderingComparator::Trace* OrderingComparator::getCurrentTrace() +{ + ASS(!_curr->node()->ready); + + if (!_prev) { + return new Trace(); + } + + ASS(_prev->node()->ready); + ASS(_prev->node()->trace); + + switch (_prev->node()->tag) { + case BranchTag::T_COMPARISON: { + auto trace = new Trace(*_prev->node()->trace); + auto lhs = _prev->node()->lhs; + auto rhs = _prev->node()->rhs; + Ordering::Result res; + if (_curr == &_prev->node()->eqBranch) { + res = Ordering::EQUAL; + } else if (_curr == &_prev->node()->gtBranch) { + res = Ordering::GREATER; + } else { + res = Ordering::INCOMPARABLE; + } + ALWAYS(trace->set({ lhs, rhs, res })); + ASS(lhs.isVar() || rhs.isVar()); + if (res == Ordering::INCOMPARABLE) { + if (lhs.isTerm()) { + SubtermIterator stit(lhs.term()); + while (stit.hasNext()) { + trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE }); + } + } + } else { + if (rhs.isTerm()) { + SubtermIterator stit(rhs.term()); + while (stit.hasNext()) { + trace->set({ lhs, stit.next(), Ordering::GREATER }); + } + } + } + return trace; + } + case BranchTag::T_RESULT: { + return _prev->node()->trace; + } + case BranchTag::T_WEIGHT: { + return new Trace(*_prev->node()->trace); + } + } +} + OrderingComparator::Branch::~Branch() { setNode(nullptr); diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index f8e3e0e71..49efa8aa4 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -28,17 +28,11 @@ namespace Kernel { */ struct OrderingComparator { -protected: - struct Branch; - struct Node; - class ResultNode; - class ComparisonNode; - public: OrderingComparator(const Ordering& ord, const Stack& comps, void* result); virtual ~OrderingComparator(); - void reset() { _curr = &_root; _cache.reset(); } + void reset() { _curr = &_root; _prev = nullptr; /* _trace.reset(); */ } void* next(const SubstApplicator* applicator); void insert(const Stack& comps, void* result); @@ -56,6 +50,8 @@ struct OrderingComparator T_WEIGHT = 2u, }; + struct Node; + struct Branch { Node* node() const { return _node; } void setNode(Node* node) { @@ -90,6 +86,16 @@ struct OrderingComparator using VarCoeffPair = std::pair; + struct Trace { + bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; + bool set(Ordering::Constraint con); + void reset() { st.reset(); } + + Stack st; + }; + + Trace* getCurrentTrace(); + struct Node { static_assert(sizeof(uint64_t) == sizeof(Branch)); static_assert(sizeof(uint64_t) == sizeof(TermList)); @@ -114,7 +120,7 @@ struct OrderingComparator explicit Node(TermList lhs, TermList rhs) : tag(T_COMPARISON), ready(false), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) - : tag(T_WEIGHT), ready(true), w(w), varCoeffPairs(varCoeffPairs) {} + : tag(T_WEIGHT), ready(false), w(w), varCoeffPairs(varCoeffPairs) {} ~Node(); @@ -139,13 +145,15 @@ struct OrderingComparator Branch gtBranch; Branch incBranch; unsigned refcnt; + Trace* trace = nullptr; }; const Ordering& _ord; Branch _root; Branch _fail; Branch* _curr; - Stack _cache; + Branch* _prev; + // Trace _trace; }; } // namespace Kernel From 4dcb6cd3bec9f9acf5dde9e0cb038d6f4ae82f60 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 1 Oct 2024 10:21:44 +0200 Subject: [PATCH 19/64] Implement node-mutating version which tries to reuse the nodes as much as possible --- Kernel/KBOComparator.cpp | 52 +++++++++++++++++++---------------- Kernel/LPOComparator.cpp | 49 ++++++++++++++++++++++----------- Kernel/OrderingComparator.cpp | 13 +++++++-- Kernel/OrderingComparator.hpp | 9 ++---- 4 files changed, 75 insertions(+), 48 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index ff5989092..02956a667 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -54,9 +54,12 @@ void KBOComparator::expandTermCase() state = nullptr; #endif - // take temporary ownership of node - Branch nodeHolder = *_curr; - auto node = nodeHolder.node(); + ASS(_curr->node()->lhs.isTerm() && _curr->node()->rhs.isTerm()); + auto lhs = _curr->node()->lhs.term(); + auto rhs = _curr->node()->rhs.term(); + auto eqBranch = _curr->node()->eqBranch; + auto gtBranch = _curr->node()->gtBranch; + auto incBranch = _curr->node()->incBranch; auto curr = _curr; @@ -65,43 +68,44 @@ void KBOComparator::expandTermCase() sort(nonzeros->begin(),nonzeros->end(),[](const auto& e1, const auto& e2) { return e1.second>e2.second; }); - *curr = Branch(w, nonzeros.release()); - curr->node()->gtBranch = node->gtBranch; - curr->node()->incBranch = node->incBranch; - curr->node()->trace = getCurrentTrace(); - curr->node()->ready = true; + curr->node()->tag = T_WEIGHT; + curr->node()->w = w; + curr->node()->varCoeffPairs = nonzeros.release(); + curr->node()->gtBranch = gtBranch; + curr->node()->incBranch = incBranch; curr = &curr->node()->eqBranch; } - ASS(node->lhs.isTerm() && node->rhs.isTerm()); - auto lhst = node->lhs.term(); - auto rhst = node->rhs.term(); - - Ordering::Result prec = lhst->isSort() - ? kbo.compareTypeConPrecedences(lhst->functor(),rhst->functor()) - : kbo.compareFunctionPrecedences(lhst->functor(),rhst->functor()); + Ordering::Result prec = lhs->isSort() + ? kbo.compareTypeConPrecedences(lhs->functor(),rhs->functor()) + : kbo.compareFunctionPrecedences(lhs->functor(),rhs->functor()); switch (prec) { case Ordering::LESS: { - *curr = node->incBranch; + *curr = incBranch; break; } case Ordering::GREATER: { - *curr = node->gtBranch; + *curr = gtBranch; break; } case Ordering::EQUAL: { // push the arguments in reverse order to maintain // left-to-right lexicographic order in todo - for (unsigned i = 0; i < lhst->arity(); i++) { - auto lhsArg = *lhst->nthArgument(i); - auto rhsArg = *rhst->nthArgument(i); - *curr = Branch(lhsArg,rhsArg); - curr->node()->gtBranch = node->gtBranch; - curr->node()->incBranch = node->incBranch; + for (unsigned i = 0; i < lhs->arity(); i++) { + auto lhsArg = *lhs->nthArgument(i); + auto rhsArg = *rhs->nthArgument(i); + if (!(w < 0 || varInbalance) && i==0) { + curr->node()->lhs = lhsArg; + curr->node()->rhs = rhsArg; + } else { + *curr = Branch(lhsArg,rhsArg); + curr->node()->gtBranch = gtBranch; + curr->node()->incBranch = incBranch; + } curr = &curr->node()->eqBranch; } - *curr = node->eqBranch; + *curr = eqBranch; break; } default: { diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index c3fcd9fa4..724001955 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -51,22 +51,24 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 void LPOComparator::expandTermCase() { // take temporary ownership of node - Branch nodeHolder = std::move(*_curr); - auto node = nodeHolder.node(); + auto node = _curr->node(); + auto lhs = node->lhs; + auto rhs = node->rhs; + auto eqBranch = node->eqBranch; + auto gtBranch = node->gtBranch; + auto incBranch = node->incBranch; + + ASS_EQ(node->tag, T_COMPARISON); + ASS(!node->ready); + ASS(lhs.isTerm() && rhs.isTerm()); - ASS(node->lhs.isTerm() && node->rhs.isTerm()); const auto& lpo = static_cast(_ord); - auto s = node->lhs.term(); - auto t = node->rhs.term(); + auto s = lhs.term(); + auto t = rhs.term(); switch (lpo.comparePrecedences(s, t)) { case Ordering::EQUAL: { ASS(s->arity()); // constants cannot be incomparable - - // copies for unification - auto lhs = node->lhs; - auto rhs = node->rhs; - auto curr = _curr; // lexicographic comparisons @@ -74,24 +76,39 @@ void LPOComparator::expandTermCase() { auto s_arg = *lhs.term()->nthArgument(i); auto t_arg = *rhs.term()->nthArgument(i); - *curr = Branch(s_arg,t_arg); + if (i == 0) { + ASS_EQ(curr->node()->tag, T_COMPARISON); + curr->node()->lhs = s_arg; + curr->node()->rhs = t_arg; + } else { + *curr = Branch(s_arg,t_arg); + } // greater branch is a majo chain - majoChain(&curr->node()->gtBranch, lhs, rhs.term(), i+1, node->gtBranch, node->incBranch); + majoChain(&curr->node()->gtBranch, lhs, rhs.term(), i+1, gtBranch, incBranch); // incomparable branch is an alpha chain - alphaChain(&curr->node()->incBranch, lhs.term(), i+1, rhs, node->gtBranch, node->incBranch); + alphaChain(&curr->node()->incBranch, lhs.term(), i+1, rhs, gtBranch, incBranch); curr = &curr->node()->eqBranch; } - *curr = node->eqBranch; + *curr = eqBranch; break; } case Ordering::GREATER: { ASS(t->arity()); - majoChain(_curr, node->lhs, t, 0, node->gtBranch, node->incBranch); + _curr->node()->lhs = lhs; + _curr->node()->rhs = *t->nthArgument(0); + _curr->node()->eqBranch = incBranch; + _curr->node()->incBranch = incBranch; + majoChain(&_curr->node()->gtBranch, lhs, t, 1, gtBranch, incBranch); break; } case Ordering::LESS: { ASS(s->arity()); - alphaChain(_curr, s, 0, node->rhs, node->gtBranch, node->incBranch); + _curr->node()->lhs = *s->nthArgument(0); + _curr->node()->rhs = rhs; + _curr->node()->eqBranch = gtBranch; + _curr->node()->gtBranch = gtBranch; + alphaChain(&_curr->node()->incBranch, s, 1, rhs, gtBranch, incBranch); + ASS(_curr->node()); break; } default: diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index cbeb9a662..bf8d50a60 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -225,7 +225,7 @@ void OrderingComparator::insert(const Stack& comps, void* void OrderingComparator::expand() { ASS(_curr->node()); - while (_curr->node() && !_curr->node()->ready) + while (!_curr->node()->ready) { // take temporary ownership of node Branch nodeHolder = *_curr; @@ -237,7 +237,16 @@ void OrderingComparator::expand() _curr->node()->ready = true; return; } - ASS(node->tag != BranchTag::T_WEIGHT); + if (node->tag == BranchTag::T_WEIGHT) { + auto varCoeffPairs = new Stack(*node->varCoeffPairs); + *_curr = Branch(node->w, varCoeffPairs); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->incBranch = node->incBranch; + _curr->node()->trace = getCurrentTrace(); + _curr->node()->ready = true; + return; + } // Use compare here to filter out as many // precomputable comparisons as possible. diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 49efa8aa4..cc5e1c800 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -55,13 +55,13 @@ struct OrderingComparator struct Branch { Node* node() const { return _node; } void setNode(Node* node) { + if (node) { + node->incRefCnt(); + } if (_node) { _node->decRefCnt(); } _node = node; - if (_node) { - _node->incRefCnt(); - } } Branch() = default; @@ -69,8 +69,6 @@ struct OrderingComparator setNode(new Node(std::forward(s), std::forward(t))); } ~Branch(); - // Branch(const Branch& other) = delete; - // Branch& operator=(const Branch& other) = delete; Branch(const Branch& other); Branch& operator=(const Branch& other); Branch(Branch&& other); @@ -81,7 +79,6 @@ struct OrderingComparator }; friend std::ostream& operator<<(std::ostream& out, const Node& node); - // friend std::ostream& operator<<(std::ostream& out, const Branch& branch); friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); using VarCoeffPair = std::pair; From 85aebe597ecef9de788a8d181a4c658e40135216 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 3 Oct 2024 14:41:30 +0200 Subject: [PATCH 20/64] Try to get rid of memory leaks --- Indexing/TermCodeTree.cpp | 1 + Kernel/OrderingComparator.cpp | 9 ++++----- Kernel/OrderingComparator.hpp | 4 +++- Saturation/SaturationAlgorithm.cpp | 2 ++ Shell/ConditionalRedundancyHandler.cpp | 9 +++++++++ Shell/ConditionalRedundancyHandler.hpp | 1 + 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index 4244f17c4..740c836b3 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -66,6 +66,7 @@ void TermCodeTree::insert(Data* data) ASS(rtm.op->isSuccess()); dptr=rtm.op->template getSuccessResult(); if (dptr->insert(*data)) { + delete data; return; } } diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index bf8d50a60..154586462 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -393,7 +393,7 @@ OrderingComparator::Branch::~Branch() OrderingComparator::Branch::Branch(const Branch& other) { - setNode(other.node()); + setNode(other._node); } OrderingComparator::Branch& OrderingComparator::Branch::operator=(const Branch& other) @@ -416,8 +416,7 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other if (&other==this) { return *this; } - _node = other._node; - other._node = nullptr; + swap(_node,other._node); return *this; } @@ -442,9 +441,9 @@ void OrderingComparator::Node::incRefCnt() void OrderingComparator::Node::decRefCnt() { - ASS(refcnt); + ASS(refcnt>=0); refcnt--; - if (!refcnt) { + if (refcnt==0) { delete this; } } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index cc5e1c800..a3930de25 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -118,6 +118,8 @@ struct OrderingComparator : tag(T_COMPARISON), ready(false), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) : tag(T_WEIGHT), ready(false), w(w), varCoeffPairs(varCoeffPairs) {} + Node(const Node&) = delete; + Node& operator=(const Node&) = delete; ~Node(); @@ -141,7 +143,7 @@ struct OrderingComparator Branch eqBranch; Branch gtBranch; Branch incBranch; - unsigned refcnt; + int refcnt; Trace* trace = nullptr; }; diff --git a/Saturation/SaturationAlgorithm.cpp b/Saturation/SaturationAlgorithm.cpp index 0bb42f4e5..2fa5e1fee 100644 --- a/Saturation/SaturationAlgorithm.cpp +++ b/Saturation/SaturationAlgorithm.cpp @@ -266,6 +266,8 @@ SaturationAlgorithm::~SaturationAlgorithm() { ASS_EQ(s_instance,this); + ConditionalRedundancyHandler::destroyAllClauseData(); + s_instance = 0; if (_splitter) { diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index d5b6bd858..205353398 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -421,6 +421,15 @@ void ConditionalRedundancyHandler::destroyClauseData(Clause* cl) delete ptr; } +void ConditionalRedundancyHandler::destroyAllClauseData() +{ + decltype(clauseData)::Iterator it(clauseData); + while (it.hasNext()) { + auto data = it.next(); + delete data; + } +} + ConditionalRedundancyHandler::ConstraintIndex** ConditionalRedundancyHandler::getDataPtr(Clause* cl, bool doAllocate) { if (!doAllocate) { diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 5b7d1dd75..9f42027ef 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -97,6 +97,7 @@ class ConditionalRedundancyHandler public: static ConditionalRedundancyHandler* create(const Options& opts, const Ordering* ord, Splitter* splitter); static void destroyClauseData(Clause* cl); + static void destroyAllClauseData(); virtual ~ConditionalRedundancyHandler() = default; From 26d391e619a773cb8f557d6e72a57e5dc0cd3e15 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 3 Oct 2024 20:05:54 +0200 Subject: [PATCH 21/64] Fix some memory leaks --- Indexing/Index.hpp | 23 ++++++++++++++++------- Indexing/TermCodeTree.cpp | 14 +++++++------- Kernel/OrderingComparator.cpp | 7 ++++++- Kernel/OrderingComparator.hpp | 10 +++++----- Shell/ConditionalRedundancyHandler.cpp | 9 ++++----- Shell/ConditionalRedundancyHandler.hpp | 2 -- 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 2cee4410f..d3f3ebde1 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -106,7 +106,7 @@ struct TermLiteralClause IMPL_COMPARISONS_FROM_TUPLE(TermLiteralClause) - bool insert(const TermLiteralClause& other) { return false; } + bool insert(TermLiteralClause& other) { return false; } bool remove(const TermLiteralClause& other) { return *this==other; } @@ -157,6 +157,7 @@ struct DemodulatorData struct DemodulatorDataContainer { TypedTermList term; Stack dds; + unsigned removedCnt = 0; OrderingComparatorUP comparator; DemodulatorDataContainer(DemodulatorData&& dd, const Ordering& ord) : term(dd.term) { @@ -169,7 +170,13 @@ struct DemodulatorDataContainer { comparator = ord.createComparator(ordCons, ptr); } - bool insert(const DemodulatorDataContainer& other) { + ~DemodulatorDataContainer() { + iterTraits(dds.iter()).forEach([](DemodulatorData* dd){ delete dd; }); + } + + DemodulatorDataContainer(DemodulatorDataContainer&&) = default; + + bool insert(DemodulatorDataContainer& other) { ASS_EQ(other.dds.size(),1); // only allow insertion if term sorts are identical to // avoid putting variables of different sorts together @@ -182,6 +189,7 @@ struct DemodulatorDataContainer { ordCons.push({ other.dds[0]->term, other.dds[0]->rhs, Ordering::GREATER }); } comparator->insert(ordCons, other.dds[0]); + other.dds.reset(); // takes ownership return true; } @@ -191,8 +199,8 @@ struct DemodulatorDataContainer { return false; } ALWAYS(iterTraits(other.dds.iter()).all([this](DemodulatorData* toRemove){ - decltype(dds)::DelIterator it(dds); - unsigned removedCnt = 0; + decltype(dds)::Iterator it(dds); + unsigned removedOccs = 0; while (it.hasNext()) { auto curr = it.next(); if (*curr==*toRemove) { @@ -200,16 +208,17 @@ struct DemodulatorDataContainer { // actually remove the node from the tree // // delete curr; - it.del(); + // it.del(); removedCnt++; + removedOccs++; } } - return removedCnt==1; + return removedOccs==1; })); return true; } - bool canBeDeleted() const { return dds.isEmpty(); } + bool canBeDeleted() const { return removedCnt==dds.size(); } friend std::ostream& operator<<(std::ostream& out, DemodulatorDataContainer const& self) { return out << *self.comparator; } diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index 740c836b3..76548d354 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -67,9 +67,11 @@ void TermCodeTree::insert(Data* data) dptr=rtm.op->template getSuccessResult(); if (dptr->insert(*data)) { delete data; + ft->destroy(); return; } } + ft->destroy(); } static CodeStack code; @@ -118,16 +120,14 @@ void TermCodeTree::remove(const Data& data) } } - if (!dptr->canBeDeleted()) { - return; + if (dptr->canBeDeleted()) { + rtm.op->makeFail(); + ASS(dptr); + delete dptr; + optimizeMemoryAfterRemoval(&firstsInBlocks, rtm.op); } - rtm.op->makeFail(); - ASS(dptr); - delete dptr; ft->destroy(); - - optimizeMemoryAfterRemoval(&firstsInBlocks, rtm.op); } // TermCodeTree::remove diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 154586462..a1e3b4fe4 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -296,6 +296,7 @@ bool OrderingComparator::tryExpandVarCase() } else { *_curr = node->incBranch; } + delete trace; return true; } // make a fresh copy @@ -378,12 +379,13 @@ OrderingComparator::Trace* OrderingComparator::getCurrentTrace() return trace; } case BranchTag::T_RESULT: { - return _prev->node()->trace; + return new Trace(*_prev->node()->trace); } case BranchTag::T_WEIGHT: { return new Trace(*_prev->node()->trace); } } + ASSERTION_VIOLATION; } OrderingComparator::Branch::~Branch() @@ -432,6 +434,9 @@ OrderingComparator::Node::~Node() delete varCoeffPairs; break; } + ready = false; + delete trace; + trace = nullptr; } void OrderingComparator::Node::incRefCnt() diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index a3930de25..8a33baa1c 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -113,11 +113,11 @@ struct OrderingComparator } explicit Node(void* data, Branch alternative) - : tag(T_RESULT), ready(false), data(data), alternative(alternative) {} + : tag(T_RESULT), data(data), alternative(alternative) {} explicit Node(TermList lhs, TermList rhs) - : tag(T_COMPARISON), ready(false), lhs(lhs), rhs(rhs) {} + : tag(T_COMPARISON), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) - : tag(T_WEIGHT), ready(false), w(w), varCoeffPairs(varCoeffPairs) {} + : tag(T_WEIGHT), w(w), varCoeffPairs(varCoeffPairs) {} Node(const Node&) = delete; Node& operator=(const Node&) = delete; @@ -127,7 +127,7 @@ struct OrderingComparator void decRefCnt(); BranchTag tag; - bool ready; + bool ready = false; union { void* data = nullptr; @@ -143,7 +143,7 @@ struct OrderingComparator Branch eqBranch; Branch gtBranch; Branch incBranch; - int refcnt; + int refcnt = 0; Trace* trace = nullptr; }; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 205353398..9e7532717 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -125,9 +125,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(entries->comparator); -#if DEBUG_ORDERING entries->entries.push(ptr); -#endif entries->comparator->insert(ptr->ordCons, ptr); return true; } @@ -158,9 +156,7 @@ class ConditionalRedundancyHandler::ConstraintIndex compiler.updateCodeTree(this); auto es = new Entries(); -#if DEBUG_ORDERING es->entries.push(ptr); -#endif es->comparator = ord->createComparator(ptr->ordCons, ptr); code.push(CodeOp::getSuccess(es)); incorporate(code); @@ -234,6 +230,7 @@ class ConditionalRedundancyHandler::ConstraintIndex if (!e->splits->isEmpty()) { env.statistics->skippedInferencesDueToAvatarConstraints++; } + matcher.reset(); return true; } #if DEBUG_ORDERING @@ -366,7 +363,9 @@ class ConditionalRedundancyHandler::ConstraintIndex static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { - delete op->getSuccessResult(); + auto es = op->getSuccessResult(); + iterTraits(decltype(es->entries)::Iterator(es->entries)).forEach([](ConditionalRedundancyEntry* e) { delete e; }); + delete es; } } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 9f42027ef..87e6bc37e 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -86,9 +86,7 @@ struct ConditionalRedundancyEntry }; struct Entries { -#if DEBUG_ORDERING Stack entries; -#endif OrderingComparatorUP comparator; }; From 0366ff081589030fd9f12cd10cbe9317bc125ce5 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 4 Oct 2024 15:31:37 +0200 Subject: [PATCH 22/64] Try to reuse nodes with refcount==1 --- Kernel/KBOComparator.cpp | 25 ++++++++++---------- Kernel/LPOComparator.cpp | 8 ++++--- Kernel/OrderingComparator.cpp | 44 +++++++++++++++++++++-------------- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 02956a667..dcad4c288 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -54,20 +54,22 @@ void KBOComparator::expandTermCase() state = nullptr; #endif - ASS(_curr->node()->lhs.isTerm() && _curr->node()->rhs.isTerm()); - auto lhs = _curr->node()->lhs.term(); - auto rhs = _curr->node()->rhs.term(); - auto eqBranch = _curr->node()->eqBranch; - auto gtBranch = _curr->node()->gtBranch; - auto incBranch = _curr->node()->incBranch; + auto node = _curr->node(); + ASS(node->lhs.isTerm() && node->rhs.isTerm()); + auto lhs = node->lhs.term(); + auto rhs = node->rhs.term(); - auto curr = _curr; + auto eqBranch = node->eqBranch; + auto gtBranch = node->gtBranch; + auto incBranch = node->incBranch; - // if the condition below does not hold, the weight/var balances are satisfied - if (w < 0 || varInbalance) { + auto curr = _curr; + bool weightAdded = (w < 0 || varInbalance); + if (weightAdded) { sort(nonzeros->begin(),nonzeros->end(),[](const auto& e1, const auto& e2) { return e1.second>e2.second; }); + // we mutate the original node curr->node()->tag = T_WEIGHT; curr->node()->w = w; curr->node()->varCoeffPairs = nonzeros.release(); @@ -90,12 +92,11 @@ void KBOComparator::expandTermCase() break; } case Ordering::EQUAL: { - // push the arguments in reverse order to maintain - // left-to-right lexicographic order in todo for (unsigned i = 0; i < lhs->arity(); i++) { auto lhsArg = *lhs->nthArgument(i); auto rhsArg = *rhs->nthArgument(i); - if (!(w < 0 || varInbalance) && i==0) { + // we mutate the original node in the first iteration + if (!weightAdded && i==0) { curr->node()->lhs = lhsArg; curr->node()->rhs = rhsArg; } else { diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 724001955..b9c1ec2d1 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -60,12 +60,12 @@ void LPOComparator::expandTermCase() ASS_EQ(node->tag, T_COMPARISON); ASS(!node->ready); - ASS(lhs.isTerm() && rhs.isTerm()); - const auto& lpo = static_cast(_ord); + ASS(lhs.isTerm() && rhs.isTerm()); auto s = lhs.term(); auto t = rhs.term(); + const auto& lpo = static_cast(_ord); switch (lpo.comparePrecedences(s, t)) { case Ordering::EQUAL: { ASS(s->arity()); // constants cannot be incomparable @@ -77,6 +77,7 @@ void LPOComparator::expandTermCase() auto s_arg = *lhs.term()->nthArgument(i); auto t_arg = *rhs.term()->nthArgument(i); if (i == 0) { + // we mutate the original node in the first iteration ASS_EQ(curr->node()->tag, T_COMPARISON); curr->node()->lhs = s_arg; curr->node()->rhs = t_arg; @@ -94,6 +95,7 @@ void LPOComparator::expandTermCase() } case Ordering::GREATER: { ASS(t->arity()); + // we mutate the original node in the first iteration _curr->node()->lhs = lhs; _curr->node()->rhs = *t->nthArgument(0); _curr->node()->eqBranch = incBranch; @@ -103,12 +105,12 @@ void LPOComparator::expandTermCase() } case Ordering::LESS: { ASS(s->arity()); + // we mutate the original node in the first iteration _curr->node()->lhs = *s->nthArgument(0); _curr->node()->rhs = rhs; _curr->node()->eqBranch = gtBranch; _curr->node()->gtBranch = gtBranch; alphaChain(&_curr->node()->incBranch, s, 1, rhs, gtBranch, incBranch); - ASS(_curr->node()); break; } default: diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index a1e3b4fe4..91fa8265e 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -227,22 +227,29 @@ void OrderingComparator::expand() ASS(_curr->node()); while (!_curr->node()->ready) { - // take temporary ownership of node - Branch nodeHolder = *_curr; - auto node = nodeHolder.node(); + auto node = _curr->node(); if (node->tag == BranchTag::T_RESULT) { - *_curr = Branch(node->data, node->alternative); + ASS(node->data); // no fail nodes here + // if refcnt > 1 we copy the node and + // we can also safely use the original + if (node->refcnt > 1) { + *_curr = Branch(node->data, node->alternative); + } _curr->node()->trace = getCurrentTrace(); _curr->node()->ready = true; return; } if (node->tag == BranchTag::T_WEIGHT) { - auto varCoeffPairs = new Stack(*node->varCoeffPairs); - *_curr = Branch(node->w, varCoeffPairs); - _curr->node()->eqBranch = node->eqBranch; - _curr->node()->gtBranch = node->gtBranch; - _curr->node()->incBranch = node->incBranch; + // if refcnt > 1 we copy the node and + // we can also safely use the original + if (node->refcnt > 1) { + auto varCoeffPairs = new Stack(*node->varCoeffPairs); + *_curr = Branch(node->w, varCoeffPairs); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->incBranch = node->incBranch; + } _curr->node()->trace = getCurrentTrace(); _curr->node()->ready = true; return; @@ -278,9 +285,7 @@ void OrderingComparator::expandTermCase() bool OrderingComparator::tryExpandVarCase() { - // take temporary ownership of node - Branch nodeHolder = *_curr; - auto node = nodeHolder.node(); + auto node = _curr->node(); // If we have a variable, we cannot preprocess further. if (!node->lhs.isVar() && !node->rhs.isVar()) { @@ -299,11 +304,14 @@ bool OrderingComparator::tryExpandVarCase() delete trace; return true; } - // make a fresh copy - *_curr = Branch(node->lhs, node->rhs); - _curr->node()->eqBranch = node->eqBranch; - _curr->node()->gtBranch = node->gtBranch; - _curr->node()->incBranch = node->incBranch; + // if refcnt > 1 we copy the node and + // we can also safely use the original + if (node->refcnt > 1) { + *_curr = Branch(node->lhs, node->rhs); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->incBranch = node->incBranch; + } _curr->node()->ready = true; _curr->node()->trace = trace; return true; @@ -453,4 +461,4 @@ void OrderingComparator::Node::decRefCnt() } } -} \ No newline at end of file +} From de0b387b60f22a6e55442363738b613d20cbff56 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 8 Oct 2024 17:06:18 +0200 Subject: [PATCH 23/64] Add PartialOrdering current implementation; add some optimisations; add ordering comparator check to backward demodulation --- CMakeLists.txt | 2 + Inferences/BackwardDemodulation.cpp | 29 +- Kernel/OrderingComparator.cpp | 42 +- Kernel/OrderingComparator.hpp | 6 +- Kernel/PartialOrdering.cpp | 617 ++++++++++++++++++++++++++++ Kernel/PartialOrdering.hpp | 78 ++++ 6 files changed, 762 insertions(+), 12 deletions(-) create mode 100644 Kernel/PartialOrdering.cpp create mode 100644 Kernel/PartialOrdering.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6256f0d6a..7aa8760c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/Ordering.cpp Kernel/OrderingComparator.cpp Kernel/Ordering_Equality.cpp + Kernel/PartialOrdering.cpp Kernel/Problem.cpp Kernel/Renaming.cpp Kernel/RobSubstitution.cpp @@ -274,6 +275,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/MLVariant.hpp Kernel/Ordering.hpp Kernel/OrderingComparator.hpp + Kernel/PartialOrdering.hpp Kernel/Problem.hpp Kernel/RCClauseStack.hpp Kernel/Renaming.hpp diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index 6dfcae249..e47576f43 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -102,10 +102,20 @@ struct BackwardDemodulation::ResultFn typedef DHMultiset ClauseSet; ResultFn(Clause* cl, BackwardDemodulation& parent, const DemodulationHelper& helper) - : _cl(cl), _helper(helper), _ordering(parent._salg->getOrdering()) + : _cl(cl), _helper(helper), _ordering(parent._salg->getOrdering()), _comps() { ASS_EQ(_cl->length(),1); _eqLit=(*_cl)[0]; + { + Stack leftCons; + leftCons.push({ *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER }); + _comps.first = _ordering.createComparator(leftCons, (void*)0x1); + } + { + Stack rightCons; + rightCons.push({ *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER }); + _comps.second = _ordering.createComparator(rightCons, (void*)0x1); + } _removed=SmartPtr(new ClauseSet()); } @@ -143,9 +153,22 @@ struct BackwardDemodulation::ResultFn TermList lhsS=qr.data->term; - if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { + auto& comp = lhs==*_eqLit->nthArgument(0) ? _comps.first : _comps.second; + comp->reset(); + if (!comp->next(&appl)) { +#if DEBUG_ORDERING + if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))==Ordering::GREATER) { + INVALID_OPERATION("backward check should be greater"); + } +#endif return BwSimplificationRecord(0); } +#if DEBUG_ORDERING + if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { + INVALID_OPERATION("backward check not greater"); + // return BwSimplificationRecord(0); + } +#endif TermList rhsS=subs->applyToBoundQuery(rhs); @@ -189,6 +212,8 @@ struct BackwardDemodulation::ResultFn const DemodulationHelper& _helper; Ordering& _ordering; + + std::pair _comps; }; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 91fa8265e..23f7cbad8 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -236,7 +236,7 @@ void OrderingComparator::expand() if (node->refcnt > 1) { *_curr = Branch(node->data, node->alternative); } - _curr->node()->trace = getCurrentTrace(); + _curr->node()->trace = getCurrentTrace().release(); _curr->node()->ready = true; return; } @@ -250,7 +250,7 @@ void OrderingComparator::expand() _curr->node()->gtBranch = node->gtBranch; _curr->node()->incBranch = node->incBranch; } - _curr->node()->trace = getCurrentTrace(); + _curr->node()->trace = getCurrentTrace().release(); _curr->node()->ready = true; return; } @@ -301,9 +301,24 @@ bool OrderingComparator::tryExpandVarCase() } else { *_curr = node->incBranch; } - delete trace; return true; } + // TODO eventually incorporate this into the Trace + if (node->lhs.isVar() && node->rhs.isTerm()) { + SubtermIterator sti(node->rhs.term()); + while (sti.hasNext()) { + auto st = sti.next(); + if (trace->get(node->lhs, st, val)) { + if (val == Ordering::INCOMPARABLE) { + *_curr = node->incBranch; + return true; + } else if (val == Ordering::LESS) { + *_curr = node->incBranch; + return true; + } + } + } + } // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { @@ -313,7 +328,7 @@ bool OrderingComparator::tryExpandVarCase() _curr->node()->incBranch = node->incBranch; } _curr->node()->ready = true; - _curr->node()->trace = trace; + _curr->node()->trace = trace.release(); return true; } @@ -343,12 +358,21 @@ bool OrderingComparator::Trace::set(Ordering::Constraint con) return true; } -OrderingComparator::Trace* OrderingComparator::getCurrentTrace() +std::string OrderingComparator::Trace::to_string() const +{ + std::stringstream str; + for (const auto& con : st) { + str << con << endl; + } + return str.str(); +} + +ScopedPtr OrderingComparator::getCurrentTrace() { ASS(!_curr->node()->ready); if (!_prev) { - return new Trace(); + return ScopedPtr(new Trace()); } ASS(_prev->node()->ready); @@ -384,13 +408,13 @@ OrderingComparator::Trace* OrderingComparator::getCurrentTrace() } } } - return trace; + return ScopedPtr(trace); } case BranchTag::T_RESULT: { - return new Trace(*_prev->node()->trace); + return ScopedPtr(new Trace(*_prev->node()->trace)); } case BranchTag::T_WEIGHT: { - return new Trace(*_prev->node()->trace); + return ScopedPtr(new Trace(*_prev->node()->trace)); } } ASSERTION_VIOLATION; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 8a33baa1c..b235f67f3 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -16,6 +16,8 @@ #include "Forwards.hpp" +#include "PartialOrdering.hpp" + #include "Ordering.hpp" namespace Kernel { @@ -87,11 +89,13 @@ struct OrderingComparator bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; bool set(Ordering::Constraint con); void reset() { st.reset(); } + std::string to_string() const; Stack st; }; + // using Trace = PartialOrdering; - Trace* getCurrentTrace(); + ScopedPtr getCurrentTrace(); struct Node { static_assert(sizeof(uint64_t) == sizeof(Branch)); diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp new file mode 100644 index 000000000..466ecd029 --- /dev/null +++ b/Kernel/PartialOrdering.cpp @@ -0,0 +1,617 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file PartialOrdering.cpp + * Implements class PartialOrdering. + */ + +#include + +#include "PartialOrdering.hpp" +#include "Lib/Stack.hpp" +#include "Lib/Metaiterators.hpp" + +namespace Kernel { + +using namespace std; + +uint8_t reverseSafe(uint8_t v) { + if (!v) { + return v; + } + ASS_LE(v,Ordering::INCOMPARABLE); + return Ordering::reverse(Result(v)); +} + +Result poCompToResult(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + ASSERTION_VIOLATION; + case PoComp::GREATER: + return Result::GREATER; + case PoComp::EQUAL: + return Result::EQUAL; + case PoComp::LESS: + return Result::LESS; + case PoComp::LTR_INCOMPARABLE: + case PoComp::RTL_INCOMPARABLE: + case PoComp::INCOMPARABLE: + return Result::INCOMPARABLE; + } +} + +PoComp resultToPoComp(Result r, bool reversed) { + switch (r) { + case Result::GREATER: + return reversed ? PoComp::LESS : PoComp::GREATER; + case Result::EQUAL: + return PoComp::EQUAL; + case Result::LESS: + return reversed ? PoComp::GREATER : PoComp::LESS; + case Result::INCOMPARABLE: + return reversed ? PoComp::RTL_INCOMPARABLE : PoComp::LTR_INCOMPARABLE; + } +} + +string idx_to_string(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + return "UNKNOWN"; + case PoComp::GREATER: + return "GREATER"; + case PoComp::EQUAL: + return "EQUAL"; + case PoComp::LESS: + return "LESS"; + case PoComp::LTR_INCOMPARABLE: + return "LTR_INCOMPARABLE"; + case PoComp::RTL_INCOMPARABLE: + return "RTL_INCOMPARABLE"; + case PoComp::INCOMPARABLE: + return "INCOMPARABLE"; + } +} + +PartialOrdering::PartialOrdering() + : _nodes(), _inverse(), _size(0), _array(nullptr) {} + +PartialOrdering::PartialOrdering(const PartialOrdering& other) + : _nodes(other._nodes), _inverse(other._inverse), _size(_nodes.size()), _array(nullptr) +{ + size_t arrSize = ((_size - 1) * _size / 2); + if (arrSize) { + void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); + _array = array_new(mem, arrSize); + memcpy(_array,other._array,arrSize*sizeof(PoComp)); + } +} + +// PartialOrdering& PartialOrdering::operator=(const PartialOrdering& other) +// { +// auto prevSize = ((_size - 1) * _size / 2); +// if (prevSize) { +// array_delete(_array, prevSize); +// DEALLOC_KNOWN(_array, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); +// } +// _nodes = other._nodes; +// _nodes.reset(); +// _nodes.loadFromMap(other._nodes); +// _inverse.reset(); +// _inverse.loadFromMap(other._inverse); +// _size = other._size; +// size_t arrSize = ((_size - 1) * _size / 2); +// if (arrSize) { +// void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); +// _array = array_new(mem, arrSize); +// memcpy(_array,other._array,arrSize*sizeof(PoComp)); +// } +// return *this; +// } + +PartialOrdering::~PartialOrdering() +{ + size_t arrSize = ((_size - 1) * _size / 2); + if (arrSize) { + array_delete(_array, arrSize); + DEALLOC_KNOWN(_array, arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); + } +} + +void PartialOrdering::reset() +{ + std::memset(_array, 0, ((_size - 1) * _size / 2)*sizeof(PoComp)); +} + +bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const +{ + if (lhs == rhs) { + res = Result::EQUAL; + return true; + } + if (!_nodes.find(lhs) || !_nodes.find(rhs)) { + return false; + } + size_t idx_x = idx_of_elem(lhs); + size_t idx_y = idx_of_elem(rhs); + bool reversed = idx_x > idx_y; + if (reversed) { + swap(idx_x,idx_y); + } + PoComp val = idx_of(idx_x,idx_y); + if (val == PoComp::UNKNOWN) { + return false; + } + // if we only have INCOMPARABLE in the "other direction" + // as we use isGreater which never gives LESS, we cannot + // distinguish between the two LESS and INCOMPARABLE + if (reversed) { + if (val == PoComp::LTR_INCOMPARABLE) { + return false; + } + res = Ordering::reverse(poCompToResult(val)); + return true; + } else { + if (val == PoComp::RTL_INCOMPARABLE) { + return false; + } + res = poCompToResult(val); + return true; + } +} + +bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) +{ + if (old == PoComp::UNKNOWN) { + res = curr; + return true; + } + switch (curr) { + case PoComp::GREATER: + res = PoComp::GREATER; + return old == PoComp::GREATER || old == PoComp::RTL_INCOMPARABLE; + case PoComp::EQUAL: + res = PoComp::EQUAL; + return old == PoComp::EQUAL; + case PoComp::LESS: + res = PoComp::LESS; + return old == PoComp::LESS || old == PoComp::LTR_INCOMPARABLE; + case PoComp::INCOMPARABLE: + res = PoComp::INCOMPARABLE; + return old == PoComp::INCOMPARABLE || old == PoComp::LTR_INCOMPARABLE || old == PoComp::RTL_INCOMPARABLE; + case PoComp::LTR_INCOMPARABLE: + switch (old) { + case PoComp::LESS: + case PoComp::INCOMPARABLE: + case PoComp::LTR_INCOMPARABLE: + res = old; + return true; + case PoComp::RTL_INCOMPARABLE: + res = PoComp::INCOMPARABLE; + return true; + default: + return false; + } + break; + case PoComp::RTL_INCOMPARABLE: + switch (old) { + case PoComp::GREATER: + case PoComp::INCOMPARABLE: + case PoComp::RTL_INCOMPARABLE: + res = old; + return true; + case PoComp::LTR_INCOMPARABLE: + res = PoComp::INCOMPARABLE; + return true; + default: + return false; + } + break; + default: + ASSERTION_VIOLATION; + } + ASSERTION_VIOLATION; +} + +bool PartialOrdering::set(Ordering::Constraint con) +{ + ASS_EQ(_size,_nodes.size()); + if (con.lhs == con.rhs) { + return true; // TODO should we check anything here? + } + size_t idx_x = idx_of_elem_ext(con.lhs); + size_t idx_y = idx_of_elem_ext(con.rhs); + + bool reversed = idx_x > idx_y; + if (reversed) { + swap(idx_x,idx_y); + } + PoComp curr = resultToPoComp(con.rel, reversed); + PoComp old = idx_of(idx_x,idx_y); + PoComp res; + // cout << idx_to_string(old) << " " << idx_to_string(curr); + if (checkCompatibility(old, curr, res)) { + // cout << " " << idx_to_string(res) << endl; + set_idx_of(idx_x,idx_y,res); + if ((curr == PoComp::UNKNOWN || curr == PoComp::INCOMPARABLE) && + (res == PoComp::GREATER || res == PoComp::EQUAL || res == PoComp::LESS)) + { + // set_inferred(idx_x,idx_y,poCompToResult(res)); + } + return true; + } + // cout << " incompatible" << endl; + return false; +} + +// TermList PartialOrdering::get_rep(TermList t) const +// { +// const size_t* ptr = _nodes.findPtr(e); +// if (!ptr) { +// return e; +// } +// size_t idx_e = *ptr; +// for (size_t idx_o = 0; idx_o < idx_e; idx_o++) { +// if (idx_of(idx_o,idx_e) == Result::EQUAL) { +// return _inverse.get(idx_o); +// } +// } +// return e; +// } + +size_t PartialOrdering::idx_of_elem(TermList t) const +{ + ASS(_nodes.find(t)); + return _nodes.get(t); +} + +size_t PartialOrdering::idx_of_elem_ext(TermList t) +{ + size_t *ptr; + // cout << "size " << _size << endl; + if (_nodes.getValuePtr(t, ptr, _size)) { + ALWAYS(_inverse.insert(_size, t)); + // cout << "extend" << endl; + // extend array + size_t prevSize = ((_size - 1) * _size / 2); + auto prevArray = _array; + _size++; + static unsigned maxSize = 0; + if (_size > maxSize) { + maxSize = _size; + cout << "max size of partial ordering " << maxSize << endl; + } + if (_size>1) { + size_t newSize = prevSize + _size; + void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); + _array = array_new(mem, newSize); + std::memset(_array, 0, newSize*sizeof(PoComp)); + if (prevArray) { + memcpy(_array,prevArray,prevSize*sizeof(PoComp)); + } + } + // remove previous array + if (prevSize) { + array_delete(prevArray, prevSize); + DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); + } + } + // cout << "return " << *ptr << endl; + return *ptr; +} + +void PartialOrdering::set_idx_of(size_t idx_x, size_t idx_y, PoComp v) +{ + size_t idx = idx_y*(idx_y-1)/2 + idx_x; + ASS_L(idx,((_size - 1) * _size / 2)); + _array[idx] = v; +} + +void PartialOrdering::set_idx_of_safe(size_t idx_x, size_t idx_y, Result v) +{ + if (idx_x < idx_y) { + set_idx_of(idx_x,idx_y,resultToPoComp(v,false)); + } else { + set_idx_of(idx_y,idx_x,resultToPoComp(v,true)); + } +} + +PoComp PartialOrdering::idx_of(size_t idx_x, size_t idx_y) const +{ + size_t idx = idx_y*(idx_y-1)/2 + idx_x; + ASS_L(idx,((_size - 1) * _size / 2)); + return _array[idx]; +} + +void PartialOrdering::set_inferred_loop(size_t idx_x, size_t idx_y, Result gt, Result lt) +{ + ASS_NEQ(idx_x,idx_y); + + Stack above; + Stack below; + bool sort = idx_x < idx_y; + size_t idx_1 = sort ? idx_x : idx_y; + size_t idx_2 = sort ? idx_y : idx_x; + + // z> above; + Stack> below; + + bool sort = idx_x < idx_y; + size_t idx_1 = sort ? idx_x : idx_y; + size_t idx_2 = sort ? idx_y : idx_x; + + // z y: then ∀z. y ≥ z, also x > z, + and ∀z. z ≥ x, also z > y */ + case Result::GREATER: + set_inferred_loop(idx_x, idx_y, Result::GREATER, Result::LESS); + break; + /* x < y: then ∀z. y ≤ z, also x < z, + and ∀z. z ≤ x, also z < y */ + case Result::LESS: + set_inferred_loop(idx_x, idx_y, Result::LESS, Result::GREATER); + break; + /* x = y: then ∀z. z = x, also z = y + and ∀z. z = y, also z = x + and ∀z. z > x, also z > y + and ∀z. z > y, also z > x + and ∀z. z < x, also z < y + and ∀z. z < y, also z < x */ + case Result::EQUAL: + set_inferred_loop_eq(idx_x, idx_y); + break; + /* if INC then nothing can be inferred */ + case Result::INCOMPARABLE: + break; + } +} + +string PartialOrdering::to_string() const +{ + if (_nodes.size()<2) { + return "{}"; + } + stringstream str; + typename DHMap::Iterator vit1(_nodes); + while (vit1.hasNext()) { + TermList t1; + size_t v1; + vit1.next(t1,v1); + typename DHMap::Iterator vit2(_nodes); + while (vit2.hasNext()) { + TermList t2; + size_t v2; + vit2.next(t2,v2); + if (v1 < v2) { + auto c = idx_of(v1,v2); + if (c == PoComp::UNKNOWN) { + continue; + } + str << " { " << t1 << " " << t2 << " " << idx_to_string(c) << " }, " << endl; + } + } + } + return str.str(); +} + +// string PartialOrdering::to_string_raw() const +// { +// stringstream str; +// typename DHMap::Iterator vit(_nodes); +// while (vit.hasNext()) { +// TermList t; +// size_t v; +// vit.next(t,v); +// str << t << " " << v << ", "; +// } +// str << "; "; +// size_t arrSize = ((_size - 1) * _size / 2); +// // for (size_t i = 0; i < arrSize; i++) { +// // str << Ordering::resultToStringInfix(_array[i]) << " "; +// // } +// return str.str(); +// } + +} diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp new file mode 100644 index 000000000..e8b54fb02 --- /dev/null +++ b/Kernel/PartialOrdering.hpp @@ -0,0 +1,78 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file PartialOrdering.hpp + * Defines class PartialOrdering. + */ + +#ifndef __PartialOrdering__ +#define __PartialOrdering__ + +#include "Forwards.hpp" + +#include "Lib/DHMap.hpp" +#include "Lib/VirtualIterator.hpp" + +#include "Ordering.hpp" + +namespace Kernel { + +using namespace Lib; + +using Result = Ordering::Result; + +enum class PoComp : uint8_t { + UNKNOWN, + GREATER, + EQUAL, + LESS, + LTR_INCOMPARABLE, + RTL_INCOMPARABLE, + INCOMPARABLE, +}; + +class PartialOrdering +{ +public: + PartialOrdering(); + PartialOrdering(const PartialOrdering& other); + ~PartialOrdering(); + + void reset(); + + // PartialOrdering& operator=(const PartialOrdering& other); + + bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; + bool set(Ordering::Constraint con); + // const TermList& get_rep(const T& e) const; + + std::string to_string() const; + std::string to_string_raw() const; + +private: + size_t idx_of_elem(TermList t) const; + size_t idx_of_elem_ext(TermList t); + PoComp idx_of(size_t idx_x, size_t idx_y) const; + void set_idx_of(size_t idx_x, size_t idx_y, PoComp v); + void set_idx_of_safe(size_t idx_x, size_t idx_y, Result v); + + void set_inferred(size_t idx_x, size_t idx_y, Ordering::Result result); + void set_inferred_loop(size_t idx_x, size_t idx_y, Ordering::Result gt, Ordering::Result lt); + void set_inferred_loop_eq(size_t idx_x, size_t idx_y); + + DHMap _nodes; + DHMap _inverse; + size_t _size; + PoComp* _array; +}; + +}; + +#endif /* __PartialOrdering__ */ \ No newline at end of file From c7600131d6938979a7bb2a2dccae9809518e4b49 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 9 Oct 2024 12:22:27 +0200 Subject: [PATCH 24/64] Clean up PartialOrdering a bit --- Kernel/PartialOrdering.cpp | 417 ++++++++++++++++--------------------- Kernel/PartialOrdering.hpp | 15 +- 2 files changed, 189 insertions(+), 243 deletions(-) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 466ecd029..8341f88b5 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -22,12 +22,23 @@ namespace Kernel { using namespace std; -uint8_t reverseSafe(uint8_t v) { - if (!v) { - return v; +constexpr PoComp reverse(PoComp v) { + switch (v) { + case PoComp::UNKNOWN: + return PoComp::UNKNOWN; + case PoComp::GREATER: + return PoComp::LESS; + case PoComp::EQUAL: + return PoComp::EQUAL; + case PoComp::LESS: + return PoComp::GREATER; + case PoComp::LTR_INCOMPARABLE: + return PoComp::RTL_INCOMPARABLE; + case PoComp::RTL_INCOMPARABLE: + return PoComp::LTR_INCOMPARABLE; + case PoComp::INCOMPARABLE: + return PoComp::INCOMPARABLE; } - ASS_LE(v,Ordering::INCOMPARABLE); - return Ordering::reverse(Result(v)); } Result poCompToResult(PoComp c) { @@ -93,28 +104,6 @@ PartialOrdering::PartialOrdering(const PartialOrdering& other) } } -// PartialOrdering& PartialOrdering::operator=(const PartialOrdering& other) -// { -// auto prevSize = ((_size - 1) * _size / 2); -// if (prevSize) { -// array_delete(_array, prevSize); -// DEALLOC_KNOWN(_array, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); -// } -// _nodes = other._nodes; -// _nodes.reset(); -// _nodes.loadFromMap(other._nodes); -// _inverse.reset(); -// _inverse.loadFromMap(other._inverse); -// _size = other._size; -// size_t arrSize = ((_size - 1) * _size / 2); -// if (arrSize) { -// void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); -// _array = array_new(mem, arrSize); -// memcpy(_array,other._array,arrSize*sizeof(PoComp)); -// } -// return *this; -// } - PartialOrdering::~PartialOrdering() { size_t arrSize = ((_size - 1) * _size / 2); @@ -138,13 +127,13 @@ bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const if (!_nodes.find(lhs) || !_nodes.find(rhs)) { return false; } - size_t idx_x = idx_of_elem(lhs); - size_t idx_y = idx_of_elem(rhs); - bool reversed = idx_x > idx_y; + size_t x = idx_of_elem(lhs); + size_t y = idx_of_elem(rhs); + bool reversed = x > y; if (reversed) { - swap(idx_x,idx_y); + swap(x,y); } - PoComp val = idx_of(idx_x,idx_y); + PoComp val = idx_of(x,y); if (val == PoComp::UNKNOWN) { return false; } @@ -225,46 +214,27 @@ bool PartialOrdering::set(Ordering::Constraint con) if (con.lhs == con.rhs) { return true; // TODO should we check anything here? } - size_t idx_x = idx_of_elem_ext(con.lhs); - size_t idx_y = idx_of_elem_ext(con.rhs); + size_t x = idx_of_elem_ext(con.lhs); + size_t y = idx_of_elem_ext(con.rhs); - bool reversed = idx_x > idx_y; + bool reversed = x > y; if (reversed) { - swap(idx_x,idx_y); + swap(x,y); } PoComp curr = resultToPoComp(con.rel, reversed); - PoComp old = idx_of(idx_x,idx_y); + PoComp old = idx_of(x,y); PoComp res; - // cout << idx_to_string(old) << " " << idx_to_string(curr); if (checkCompatibility(old, curr, res)) { - // cout << " " << idx_to_string(res) << endl; - set_idx_of(idx_x,idx_y,res); - if ((curr == PoComp::UNKNOWN || curr == PoComp::INCOMPARABLE) && - (res == PoComp::GREATER || res == PoComp::EQUAL || res == PoComp::LESS)) - { - // set_inferred(idx_x,idx_y,poCompToResult(res)); + set_idx_of(x,y,res); + // if something's changed, we calculate the transitive closure + if (curr != res) { + set_inferred(x,y,res); } return true; } - // cout << " incompatible" << endl; return false; } -// TermList PartialOrdering::get_rep(TermList t) const -// { -// const size_t* ptr = _nodes.findPtr(e); -// if (!ptr) { -// return e; -// } -// size_t idx_e = *ptr; -// for (size_t idx_o = 0; idx_o < idx_e; idx_o++) { -// if (idx_of(idx_o,idx_e) == Result::EQUAL) { -// return _inverse.get(idx_o); -// } -// } -// return e; -// } - size_t PartialOrdering::idx_of_elem(TermList t) const { ASS(_nodes.find(t)); @@ -274,19 +244,12 @@ size_t PartialOrdering::idx_of_elem(TermList t) const size_t PartialOrdering::idx_of_elem_ext(TermList t) { size_t *ptr; - // cout << "size " << _size << endl; if (_nodes.getValuePtr(t, ptr, _size)) { ALWAYS(_inverse.insert(_size, t)); - // cout << "extend" << endl; // extend array size_t prevSize = ((_size - 1) * _size / 2); auto prevArray = _array; _size++; - static unsigned maxSize = 0; - if (_size > maxSize) { - maxSize = _size; - cout << "max size of partial ordering " << maxSize << endl; - } if (_size>1) { size_t newSize = prevSize + _size; void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); @@ -302,256 +265,260 @@ size_t PartialOrdering::idx_of_elem_ext(TermList t) DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); } } - // cout << "return " << *ptr << endl; return *ptr; } -void PartialOrdering::set_idx_of(size_t idx_x, size_t idx_y, PoComp v) +void PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) { - size_t idx = idx_y*(idx_y-1)/2 + idx_x; + size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); _array[idx] = v; } -void PartialOrdering::set_idx_of_safe(size_t idx_x, size_t idx_y, Result v) +void PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v) { - if (idx_x < idx_y) { - set_idx_of(idx_x,idx_y,resultToPoComp(v,false)); + if (x < y) { + set_idx_of(x,y,v); } else { - set_idx_of(idx_y,idx_x,resultToPoComp(v,true)); + set_idx_of(y,x,v); } } -PoComp PartialOrdering::idx_of(size_t idx_x, size_t idx_y) const +PoComp PartialOrdering::idx_of(size_t x, size_t y) const { - size_t idx = idx_y*(idx_y-1)/2 + idx_x; + size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); return _array[idx]; } -void PartialOrdering::set_inferred_loop(size_t idx_x, size_t idx_y, Result gt, Result lt) +void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) { - ASS_NEQ(idx_x,idx_y); + ASS_NEQ(x,y); Stack above; Stack below; - bool sort = idx_x < idx_y; - size_t idx_1 = sort ? idx_x : idx_y; - size_t idx_2 = sort ? idx_y : idx_x; + bool sort = x < y; + size_t min = sort ? x : y; + size_t max = sort ? y : x; + auto inv = reverse(rel); // inverse of rel // z z rel y + // z = x /\ x rel y -> z rel y + if (r == rel || r == PoComp::EQUAL) { + set_idx_of(z, y, rel); + above.push(z); + continue; + } + r = idx_of(z, y); + // x rel y /\ y rel z -> x rel z + // x rel y /\ y = z -> x rel z + if (r == inv || r == PoComp::EQUAL) { + set_idx_of(z, x, inv); + below.push(z); } } if (sort) { // x z rel y + // z = x /\ x rel y -> z rel y + if (r == inv || r == PoComp::EQUAL) { + set_idx_of(z, y, rel); + above.push(z); + continue; + } + r = idx_of(z, y); + // x rel y /\ y rel z -> x rel z + // x rel y /\ y = z -> x rel z + if (r == inv || r == PoComp::EQUAL) { + set_idx_of(x, z, rel); + below.push(z); } } } else { // y z rel y + // z = x /\ x rel y -> z rel y + if (r == rel || r == PoComp::EQUAL) { + set_idx_of(y, z, inv); + above.push(z); + continue; + } + r = idx_of(y, z); + // x rel y /\ y rel z -> x rel z + // x rel y /\ y = z -> x rel z + if (r == rel || r == PoComp::EQUAL) { + set_idx_of(z, x, inv); + below.push(z); } } } // x z rel y + // z = x /\ x rel y -> z rel y + if (r == inv || r == PoComp::EQUAL) { + set_idx_of(y, z, inv); + above.push(z); + continue; + } + r = idx_of(y, z); + // x rel y /\ y rel z -> x rel z + // x rel y /\ y = z -> x rel z + if (r == rel || r == PoComp::EQUAL) { + set_idx_of(x, z, rel); + below.push(z); } } - // cout << "after loop " << to_string() << endl; - + // connect all pairs that have been derived for (const auto& x : above) { for (const auto& y : below) { - set_idx_of_safe(x,y,gt); + set_idx_of_safe(x,y,rel); } } } -void PartialOrdering::set_inferred_loop_eq(size_t idx_x, size_t idx_y) +void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) { - ASS_NEQ(idx_x,idx_y); + ASS_NEQ(x,y); - Stack> above; - Stack> below; + Stack> above; + Stack> below; - bool sort = idx_x < idx_y; - size_t idx_1 = sort ? idx_x : idx_y; - size_t idx_2 = sort ? idx_y : idx_x; + bool sort = x < y; + size_t min = sort ? x : y; + size_t max = sort ? y : x; // z y: then ∀z. y ≥ z, also x > z, and ∀z. z ≥ x, also z > y */ - case Result::GREATER: - set_inferred_loop(idx_x, idx_y, Result::GREATER, Result::LESS); + case PoComp::GREATER: + set_inferred_loop(x, y, PoComp::GREATER); break; /* x < y: then ∀z. y ≤ z, also x < z, and ∀z. z ≤ x, also z < y */ - case Result::LESS: - set_inferred_loop(idx_x, idx_y, Result::LESS, Result::GREATER); + case PoComp::LESS: + set_inferred_loop(x, y, PoComp::LESS); break; /* x = y: then ∀z. z = x, also z = y and ∀z. z = y, also z = x @@ -559,11 +526,11 @@ void PartialOrdering::set_inferred(size_t idx_x, size_t idx_y, Result result) and ∀z. z > y, also z > x and ∀z. z < x, also z < y and ∀z. z < y, also z < x */ - case Result::EQUAL: - set_inferred_loop_eq(idx_x, idx_y); + case PoComp::EQUAL: + set_inferred_loop_eq(x, y); break; /* if INC then nothing can be inferred */ - case Result::INCOMPARABLE: + default: break; } } @@ -596,22 +563,4 @@ string PartialOrdering::to_string() const return str.str(); } -// string PartialOrdering::to_string_raw() const -// { -// stringstream str; -// typename DHMap::Iterator vit(_nodes); -// while (vit.hasNext()) { -// TermList t; -// size_t v; -// vit.next(t,v); -// str << t << " " << v << ", "; -// } -// str << "; "; -// size_t arrSize = ((_size - 1) * _size / 2); -// // for (size_t i = 0; i < arrSize; i++) { -// // str << Ordering::resultToStringInfix(_array[i]) << " "; -// // } -// return str.str(); -// } - } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index e8b54fb02..54488e1a7 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -47,11 +47,8 @@ class PartialOrdering void reset(); - // PartialOrdering& operator=(const PartialOrdering& other); - bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; bool set(Ordering::Constraint con); - // const TermList& get_rep(const T& e) const; std::string to_string() const; std::string to_string_raw() const; @@ -59,13 +56,13 @@ class PartialOrdering private: size_t idx_of_elem(TermList t) const; size_t idx_of_elem_ext(TermList t); - PoComp idx_of(size_t idx_x, size_t idx_y) const; - void set_idx_of(size_t idx_x, size_t idx_y, PoComp v); - void set_idx_of_safe(size_t idx_x, size_t idx_y, Result v); + PoComp idx_of(size_t x, size_t y) const; + void set_idx_of(size_t x, size_t y, PoComp v); + void set_idx_of_safe(size_t x, size_t y, PoComp v); - void set_inferred(size_t idx_x, size_t idx_y, Ordering::Result result); - void set_inferred_loop(size_t idx_x, size_t idx_y, Ordering::Result gt, Ordering::Result lt); - void set_inferred_loop_eq(size_t idx_x, size_t idx_y); + void set_inferred(size_t x, size_t y, PoComp result); + void set_inferred_loop(size_t x, size_t y, PoComp rel); + void set_inferred_loop_eq(size_t x, size_t y); DHMap _nodes; DHMap _inverse; From ac24723f64607e6abb80efb505d7b3a9f6c4f664 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 10 Oct 2024 08:51:28 +0200 Subject: [PATCH 25/64] Refactor PartialOrdering a bit more; debug check that values are set in a compatible way; fix Map copy ctor --- Kernel/PartialOrdering.cpp | 198 ++++++++++++++++++++----------------- Kernel/PartialOrdering.hpp | 11 +-- Lib/Map.hpp | 4 +- 3 files changed, 113 insertions(+), 100 deletions(-) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 8341f88b5..aa2fcc895 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -32,15 +32,26 @@ constexpr PoComp reverse(PoComp v) { return PoComp::EQUAL; case PoComp::LESS: return PoComp::GREATER; - case PoComp::LTR_INCOMPARABLE: - return PoComp::RTL_INCOMPARABLE; - case PoComp::RTL_INCOMPARABLE: - return PoComp::LTR_INCOMPARABLE; + case PoComp::NGEQ: + return PoComp::NLEQ; + case PoComp::NLEQ: + return PoComp::NGEQ; case PoComp::INCOMPARABLE: return PoComp::INCOMPARABLE; } } +constexpr PoComp weaken(PoComp v) { + switch (v) { + case PoComp::GREATER: + return PoComp::NLEQ; + case PoComp::LESS: + return PoComp::NGEQ; + default: + ASSERTION_VIOLATION; + } +} + Result poCompToResult(PoComp c) { switch (c) { case PoComp::UNKNOWN: @@ -51,8 +62,8 @@ Result poCompToResult(PoComp c) { return Result::EQUAL; case PoComp::LESS: return Result::LESS; - case PoComp::LTR_INCOMPARABLE: - case PoComp::RTL_INCOMPARABLE: + case PoComp::NGEQ: + case PoComp::NLEQ: case PoComp::INCOMPARABLE: return Result::INCOMPARABLE; } @@ -67,7 +78,7 @@ PoComp resultToPoComp(Result r, bool reversed) { case Result::LESS: return reversed ? PoComp::GREATER : PoComp::LESS; case Result::INCOMPARABLE: - return reversed ? PoComp::RTL_INCOMPARABLE : PoComp::LTR_INCOMPARABLE; + return reversed ? PoComp::NLEQ : PoComp::NGEQ; } } @@ -81,20 +92,20 @@ string idx_to_string(PoComp c) { return "EQUAL"; case PoComp::LESS: return "LESS"; - case PoComp::LTR_INCOMPARABLE: - return "LTR_INCOMPARABLE"; - case PoComp::RTL_INCOMPARABLE: - return "RTL_INCOMPARABLE"; + case PoComp::NGEQ: + return "NGEQ"; + case PoComp::NLEQ: + return "NLEQ"; case PoComp::INCOMPARABLE: return "INCOMPARABLE"; } } PartialOrdering::PartialOrdering() - : _nodes(), _inverse(), _size(0), _array(nullptr) {} + : _nodes(), _size(0), _array(nullptr) {} PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _nodes(other._nodes), _inverse(other._inverse), _size(_nodes.size()), _array(nullptr) + : _nodes(other._nodes), _size(_nodes.size()), _array(nullptr) { size_t arrSize = ((_size - 1) * _size / 2); if (arrSize) { @@ -141,13 +152,13 @@ bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const // as we use isGreater which never gives LESS, we cannot // distinguish between the two LESS and INCOMPARABLE if (reversed) { - if (val == PoComp::LTR_INCOMPARABLE) { + if (val == PoComp::NGEQ) { return false; } res = Ordering::reverse(poCompToResult(val)); return true; } else { - if (val == PoComp::RTL_INCOMPARABLE) { + if (val == PoComp::NLEQ) { return false; } res = poCompToResult(val); @@ -164,38 +175,38 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) switch (curr) { case PoComp::GREATER: res = PoComp::GREATER; - return old == PoComp::GREATER || old == PoComp::RTL_INCOMPARABLE; + return old == PoComp::GREATER || old == PoComp::NLEQ; case PoComp::EQUAL: res = PoComp::EQUAL; return old == PoComp::EQUAL; case PoComp::LESS: res = PoComp::LESS; - return old == PoComp::LESS || old == PoComp::LTR_INCOMPARABLE; + return old == PoComp::LESS || old == PoComp::NGEQ; case PoComp::INCOMPARABLE: res = PoComp::INCOMPARABLE; - return old == PoComp::INCOMPARABLE || old == PoComp::LTR_INCOMPARABLE || old == PoComp::RTL_INCOMPARABLE; - case PoComp::LTR_INCOMPARABLE: + return old == PoComp::INCOMPARABLE || old == PoComp::NGEQ || old == PoComp::NLEQ; + case PoComp::NGEQ: switch (old) { case PoComp::LESS: case PoComp::INCOMPARABLE: - case PoComp::LTR_INCOMPARABLE: + case PoComp::NGEQ: res = old; return true; - case PoComp::RTL_INCOMPARABLE: + case PoComp::NLEQ: res = PoComp::INCOMPARABLE; return true; default: return false; } break; - case PoComp::RTL_INCOMPARABLE: + case PoComp::NLEQ: switch (old) { case PoComp::GREATER: case PoComp::INCOMPARABLE: - case PoComp::RTL_INCOMPARABLE: + case PoComp::NLEQ: res = old; return true; - case PoComp::LTR_INCOMPARABLE: + case PoComp::NGEQ: res = PoComp::INCOMPARABLE; return true; default: @@ -221,14 +232,12 @@ bool PartialOrdering::set(Ordering::Constraint con) if (reversed) { swap(x,y); } - PoComp curr = resultToPoComp(con.rel, reversed); - PoComp old = idx_of(x,y); - PoComp res; - if (checkCompatibility(old, curr, res)) { - set_idx_of(x,y,res); + PoComp old_val = idx_of(x, y); + PoComp new_val = resultToPoComp(con.rel, reversed); + if (set_idx_of(x, y, new_val)) { // if something's changed, we calculate the transitive closure - if (curr != res) { - set_inferred(x,y,res); + if (new_val != old_val) { + set_inferred(x, y, new_val); } return true; } @@ -245,7 +254,6 @@ size_t PartialOrdering::idx_of_elem_ext(TermList t) { size_t *ptr; if (_nodes.getValuePtr(t, ptr, _size)) { - ALWAYS(_inverse.insert(_size, t)); // extend array size_t prevSize = ((_size - 1) * _size / 2); auto prevArray = _array; @@ -268,19 +276,24 @@ size_t PartialOrdering::idx_of_elem_ext(TermList t) return *ptr; } -void PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) +bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) { size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); - _array[idx] = v; + PoComp new_v; + if (!checkCompatibility(_array[idx], v, new_v)) { + return false; + } + _array[idx] = new_v; + return true; } -void PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v) +bool PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v) { if (x < y) { - set_idx_of(x,y,v); + return set_idx_of(x,y,v); } else { - set_idx_of(y,x,v); + return set_idx_of(y,x,reverse(v)); } } @@ -305,18 +318,18 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // z z rel y - // z = x /\ x rel y -> z rel y + // z rel x ∧ x rel y → z rel y + // z = x ∧ x rel y → z rel y if (r == rel || r == PoComp::EQUAL) { - set_idx_of(z, y, rel); + ALWAYS(set_idx_of(z, y, rel)); above.push(z); continue; } r = idx_of(z, y); - // x rel y /\ y rel z -> x rel z - // x rel y /\ y = z -> x rel z + // x rel y ∧ y rel z → x rel z + // x rel y ∧ y = z → x rel z if (r == inv || r == PoComp::EQUAL) { - set_idx_of(z, x, inv); + ALWAYS(set_idx_of(z, x, inv)); below.push(z); } } @@ -325,18 +338,18 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // x z rel y - // z = x /\ x rel y -> z rel y + // z rel x ∧ x rel y → z rel y + // z = x ∧ x rel y → z rel y if (r == inv || r == PoComp::EQUAL) { - set_idx_of(z, y, rel); + ALWAYS(set_idx_of(z, y, rel)); above.push(z); continue; } r = idx_of(z, y); - // x rel y /\ y rel z -> x rel z - // x rel y /\ y = z -> x rel z + // x rel y ∧ y rel z → x rel z + // x rel y ∧ y = z → x rel z if (r == inv || r == PoComp::EQUAL) { - set_idx_of(x, z, rel); + ALWAYS(set_idx_of(x, z, rel)); below.push(z); } } @@ -344,18 +357,18 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // y z rel y - // z = x /\ x rel y -> z rel y + // z rel x ∧ x rel y → z rel y + // z = x ∧ x rel y → z rel y if (r == rel || r == PoComp::EQUAL) { - set_idx_of(y, z, inv); + ALWAYS(set_idx_of(y, z, inv)); above.push(z); continue; } r = idx_of(y, z); - // x rel y /\ y rel z -> x rel z - // x rel y /\ y = z -> x rel z + // x rel y ∧ y rel z → x rel z + // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { - set_idx_of(z, x, inv); + ALWAYS(set_idx_of(z, x, inv)); below.push(z); } } @@ -364,18 +377,18 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // x z rel y - // z = x /\ x rel y -> z rel y + // z rel x ∧ x rel y → z rel y + // z = x ∧ x rel y → z rel y if (r == inv || r == PoComp::EQUAL) { - set_idx_of(y, z, inv); + ALWAYS(set_idx_of(y, z, inv)); above.push(z); continue; } r = idx_of(y, z); - // x rel y /\ y rel z -> x rel z - // x rel y /\ y = z -> x rel z + // x rel y ∧ y rel z → x rel z + // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { - set_idx_of(x, z, rel); + ALWAYS(set_idx_of(x, z, rel)); below.push(z); } } @@ -383,7 +396,7 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // connect all pairs that have been derived for (const auto& x : above) { for (const auto& y : below) { - set_idx_of_safe(x,y,rel); + ALWAYS(set_idx_of_safe(x,y,rel)); } } } @@ -402,14 +415,14 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z::Iterator vit1(_nodes); + typename Map::Iterator vit1(_nodes); while (vit1.hasNext()) { - TermList t1; - size_t v1; - vit1.next(t1,v1); - typename DHMap::Iterator vit2(_nodes); + const auto& e1 = vit1.next(); + typename Map::Iterator vit2(_nodes); while (vit2.hasNext()) { - TermList t2; - size_t v2; - vit2.next(t2,v2); - if (v1 < v2) { - auto c = idx_of(v1,v2); + const auto& e2 = vit2.next(); + if (e1.value() < e2.value()) { + auto c = idx_of(e1.value(),e2.value()); if (c == PoComp::UNKNOWN) { continue; } - str << " { " << t1 << " " << t2 << " " << idx_to_string(c) << " }, " << endl; + str << " { " << e1.key() << " " << e2.key() << " " << idx_to_string(c) << " }, " << endl; } } } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 54488e1a7..3b8ea9c2d 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -33,8 +33,8 @@ enum class PoComp : uint8_t { GREATER, EQUAL, LESS, - LTR_INCOMPARABLE, - RTL_INCOMPARABLE, + NGEQ, + NLEQ, INCOMPARABLE, }; @@ -57,15 +57,14 @@ class PartialOrdering size_t idx_of_elem(TermList t) const; size_t idx_of_elem_ext(TermList t); PoComp idx_of(size_t x, size_t y) const; - void set_idx_of(size_t x, size_t y, PoComp v); - void set_idx_of_safe(size_t x, size_t y, PoComp v); + bool set_idx_of(size_t x, size_t y, PoComp v); + bool set_idx_of_safe(size_t x, size_t y, PoComp v); void set_inferred(size_t x, size_t y, PoComp result); void set_inferred_loop(size_t x, size_t y, PoComp rel); void set_inferred_loop_eq(size_t x, size_t y); - DHMap _nodes; - DHMap _inverse; + Map _nodes; size_t _size; PoComp* _array; }; diff --git a/Lib/Map.hpp b/Lib/Map.hpp index 0082bf400..fbb413efb 100644 --- a/Lib/Map.hpp +++ b/Lib/Map.hpp @@ -72,7 +72,7 @@ class Map private: /** Create a new entry */ explicit Entry(Entry const& other) - : code(other.code) + : code(0) { if (other.occupied()) { init(Key(other.key()), Val(other.value()), other.code); @@ -619,7 +619,7 @@ class Map DECL_ELEMENT_TYPE(Entry&); /** Create a new iterator */ - inline Iterator(Map& map) + inline Iterator(const Map& map) : _next(map._entries), _last(map._afterLast) { } // Map::Iterator From f768c29610f365ab82ddfe53699138a3b4e8f80f Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 10 Oct 2024 14:25:46 +0200 Subject: [PATCH 26/64] Add more cases to the transitive closure; output PartialOrdering in triangular matrix form --- Inferences/ForwardDemodulation.cpp | 4 + Kernel/OrderingComparator.cpp | 35 --- Kernel/OrderingComparator.hpp | 10 +- Kernel/PartialOrdering.cpp | 344 ++++++++++++++++++++++------- Kernel/PartialOrdering.hpp | 1 - 5 files changed, 267 insertions(+), 127 deletions(-) diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 03ee8b40f..c0eb5aa06 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -233,6 +233,10 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* for (const auto& dd : qr.data->dds) { ASS_EQ(dd->clause->length(),1); + if (dd->clause->store() == Clause::NONE) { + continue; + } + if(!ColorHelper::compatible(cl->color(), dd->clause->color())) { continue; } diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 23f7cbad8..527db723a 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -332,41 +332,6 @@ bool OrderingComparator::tryExpandVarCase() return true; } -bool OrderingComparator::Trace::get(TermList lhs, TermList rhs, Ordering::Result& res) const -{ - for (const auto& [s,t,r] : st) { - if (s == lhs && t == rhs) { - ASS_NEQ(r,Ordering::LESS); - res = r; - return true; - } - - // Note: since we use isGreater which results - // in INCOMPARABLE when compare would be LESS, - // the INCOMPARABLE result we cannot use here - if (s == rhs && t == lhs && r != Ordering::INCOMPARABLE) { - res = Ordering::reverse(r); - return true; - } - } - return false; -} - -bool OrderingComparator::Trace::set(Ordering::Constraint con) -{ - st.push(con); - return true; -} - -std::string OrderingComparator::Trace::to_string() const -{ - std::stringstream str; - for (const auto& con : st) { - str << con << endl; - } - return str.str(); -} - ScopedPtr OrderingComparator::getCurrentTrace() { ASS(!_curr->node()->ready); diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index b235f67f3..a345850ed 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -85,15 +85,7 @@ struct OrderingComparator using VarCoeffPair = std::pair; - struct Trace { - bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; - bool set(Ordering::Constraint con); - void reset() { st.reset(); } - std::string to_string() const; - - Stack st; - }; - // using Trace = PartialOrdering; + using Trace = PartialOrdering; ScopedPtr getCurrentTrace(); diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index aa2fcc895..99de67af8 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -13,6 +13,7 @@ */ #include +#include #include "PartialOrdering.hpp" #include "Lib/Stack.hpp" @@ -82,25 +83,6 @@ PoComp resultToPoComp(Result r, bool reversed) { } } -string idx_to_string(PoComp c) { - switch (c) { - case PoComp::UNKNOWN: - return "UNKNOWN"; - case PoComp::GREATER: - return "GREATER"; - case PoComp::EQUAL: - return "EQUAL"; - case PoComp::LESS: - return "LESS"; - case PoComp::NGEQ: - return "NGEQ"; - case PoComp::NLEQ: - return "NLEQ"; - case PoComp::INCOMPARABLE: - return "INCOMPARABLE"; - } -} - PartialOrdering::PartialOrdering() : _nodes(), _size(0), _array(nullptr) {} @@ -314,6 +296,8 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) size_t min = sort ? x : y; size_t max = sort ? y : x; auto inv = reverse(rel); // inverse of rel + auto wkn = weaken(rel); // weakened variant of rel + auto iwkn = reverse(wkn); // inverse of wkn // z> above; - Stack> below; + // pairs (z, rel) s.t. z rel x + Stack> x_rel; + // pairs (z, rel) s.t. y rel z + Stack> y_rel; bool sort = x < y; size_t min = sort ? x : y; @@ -417,13 +455,13 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) auto r = idx_of(z, x); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(z, y, r)); - above.push(make_pair(z,r)); + x_rel.push({ z, r }); continue; } r = idx_of(z, y); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(z, x, r)); - below.push(make_pair(z,r)); + y_rel.push({ z, reverse(r) }); } } @@ -433,13 +471,13 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) auto r = idx_of(x, z); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(z, y, reverse(r))); - above.push(make_pair(z,reverse(r))); + x_rel.push({ z, reverse(r) }); continue; } r = idx_of(z, y); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(x, z, reverse(r))); - below.push(make_pair(z,r)); + y_rel.push({ z, reverse(r) }); } } } else { @@ -448,13 +486,13 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) auto r = idx_of(z, x); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(y, z, reverse(r))); - above.push(make_pair(z,r)); + x_rel.push({ z, r }); continue; } r = idx_of(y, z); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(z, x, reverse(r))); - below.push(make_pair(z,reverse(r))); + y_rel.push({ z, r }); } } } @@ -464,63 +502,154 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) auto r = idx_of(x, z); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(y, z, r)); - above.push(make_pair(z,reverse(r))); + x_rel.push({ z, reverse(r) }); continue; } r = idx_of(y, z); if (r != PoComp::UNKNOWN) { ALWAYS(set_idx_of(x, z, r)); - below.push(make_pair(z,reverse(r))); + y_rel.push({ z, r }); } } - if (below.isNonEmpty()) { - for (const auto& [x,rx] : above) { - switch (rx) { - case PoComp::EQUAL: { - for (const auto& [y,ry] : below) { - ALWAYS(set_idx_of_safe(y, x, ry)); + if (y_rel.isEmpty()) { + return; + } + + // we assume x = y + for (const auto& [z,rz] : x_rel) { + switch (rz) { + case PoComp::EQUAL: { + for (const auto& [u,ru] : y_rel) { + // z = x ∧ x ru u → z ru u + ALWAYS(set_idx_of_safe(z, u, ru)); + } + break; + } + case PoComp::GREATER: { + for (const auto& [u,ru] : y_rel) { + switch (ru) { + // z > x ∧ x ≥ u → z > u + case PoComp::EQUAL: + case PoComp::GREATER: + ALWAYS(set_idx_of_safe(z, u, PoComp::GREATER)); + break; + // z > x ∧ x ≰ u → z ≰ u + case PoComp::NLEQ: + case PoComp::INCOMPARABLE: + ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + break; + // z > x ∧ x < u implies nothing + case PoComp::LESS: + // z > x ∧ x ≱ u implies nothing + case PoComp::NGEQ: + break; + default: + ASSERTION_VIOLATION; } - break; } - case PoComp::GREATER: { - for (const auto& [y,ry] : below) { - switch (ry) { - case PoComp::GREATER: - break; - case PoComp::EQUAL: - case PoComp::LESS: - ALWAYS(set_idx_of_safe(x, y, PoComp::GREATER)); - break; - default: - ASSERTION_VIOLATION; - } + break; + } + case PoComp::LESS: { + for (const auto& [u,ru] : y_rel) { + switch (ru) { + // z < x ∧ x ≤ u → z < u + case PoComp::EQUAL: + case PoComp::LESS: + ALWAYS(set_idx_of_safe(z, u, PoComp::LESS)); + break; + // z < x ∧ x ≱ u → z ≱ u + case PoComp::NGEQ: + case PoComp::INCOMPARABLE: + ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + break; + // z < x ∧ x > u implies nothing + case PoComp::GREATER: + // z < x ∧ x ≰ u implies nothing + case PoComp::NLEQ: + break; + default: + ASSERTION_VIOLATION; } - break; } - case PoComp::LESS: { - for (const auto& [y,ry] : below) { - switch (ry) { - case PoComp::LESS: - break; - case PoComp::EQUAL: - case PoComp::GREATER: - ALWAYS(set_idx_of_safe(x, y, PoComp::LESS)); - break; - default: - ASSERTION_VIOLATION; - } + break; + } + case PoComp::INCOMPARABLE: { + for (const auto& [u,ru] : y_rel) { + switch (ru) { + // z ≰ x ∧ x > u → z ≰ u + case PoComp::GREATER: + ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + break; + // z ⋈ x ∧ x = u → z ⋈ u + case PoComp::EQUAL: + ALWAYS(set_idx_of_safe(z, u, PoComp::INCOMPARABLE)); + break; + // z ≱ x ∧ x < u → z ≱ u + case PoComp::LESS: + ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + break; + // z ⋈ x ∧ x ≱ u implies nothing + case PoComp::NGEQ: + // z ⋈ x ∧ x ≰ u implies nothing + case PoComp::NLEQ: + // z ⋈ x ∧ x ⋈ u implies nothing + case PoComp::INCOMPARABLE: + break; + default: + ASSERTION_VIOLATION; } - break; } - case PoComp::INCOMPARABLE: - case PoComp::NGEQ: - case PoComp::NLEQ: - //TODO - break; - default: - ASSERTION_VIOLATION; + break; + } + case PoComp::NGEQ: { + for (const auto& [u,ru] : y_rel) { + switch (ru) { + // z ≱ x ∧ x ≤ u → z ≱ u + case PoComp::EQUAL: + case PoComp::LESS: + ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + break; + // z ≱ x ∧ x > u implies nothing + case PoComp::GREATER: + // z ≱ x ∧ x ≱ u implies nothing + case PoComp::NGEQ: + // z ≱ x ∧ x ≰ u implies nothing + case PoComp::NLEQ: + // z ≱ x ∧ x ⋈ u implies nothing + case PoComp::INCOMPARABLE: + break; + default: + ASSERTION_VIOLATION; + } + } + break; } + case PoComp::NLEQ: { + for (const auto& [u,ru] : y_rel) { + switch (ru) { + // z ≰ x ∧ x ≥ u → z ≰ u + case PoComp::GREATER: + case PoComp::EQUAL: + ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + break; + // z ≰ x ∧ x < u implies nothing + case PoComp::LESS: + // z ≰ x ∧ x ≱ u implies nothing + case PoComp::NGEQ: + // z ≰ x ∧ x ≰ u implies nothing + case PoComp::NLEQ: + // z ≰ x ∧ x ⋈ u implies nothing + case PoComp::INCOMPARABLE: + break; + default: + ASSERTION_VIOLATION; + } + } + break; + } + default: + ASSERTION_VIOLATION; } } } @@ -553,26 +682,77 @@ void PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) } } +string idx_to_string(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + return "UNKNOWN"; + case PoComp::GREATER: + return "GREATER"; + case PoComp::EQUAL: + return "EQUAL"; + case PoComp::LESS: + return "LESS"; + case PoComp::NGEQ: + return "NGEQ"; + case PoComp::NLEQ: + return "NLEQ"; + case PoComp::INCOMPARABLE: + return "INCOMPARABLE"; + } +} + +string idx_to_infix(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + return "?"; + case PoComp::GREATER: + return ">"; + case PoComp::EQUAL: + return "="; + case PoComp::LESS: + return "<"; + case PoComp::NGEQ: + return "≱"; + case PoComp::NLEQ: + return "≰"; + case PoComp::INCOMPARABLE: + return "⋈"; + } +} + string PartialOrdering::to_string() const { if (_nodes.size()<2) { - return "{}"; + return " {} "; } stringstream str; - typename Map::Iterator vit1(_nodes); - while (vit1.hasNext()) { - const auto& e1 = vit1.next(); - typename Map::Iterator vit2(_nodes); - while (vit2.hasNext()) { - const auto& e2 = vit2.next(); - if (e1.value() < e2.value()) { - auto c = idx_of(e1.value(),e2.value()); - if (c == PoComp::UNKNOWN) { - continue; - } - str << " { " << e1.key() << " " << e2.key() << " " << idx_to_string(c) << " }, " << endl; + typename Map::Iterator it(_nodes); + while (it.hasNext()) { + const auto& e = it.next(); + str << e.value() << ": " << e.key() << ", "; + } + str << endl; + + size_t s = _size-1; + size_t w = 0; + while (s) { s /= 10; w++; } + + for (size_t i = 0; i < _size; i++) { + str << std::setw(w) << i << " "; + for (size_t j = 0; j < i; j++) { + if (w>1) { + str << std::setw(w-1) << " "; } + str << idx_to_infix(idx_of(j,i)) << " "; } + if (w>1) { + str << std::setw(w-1) << " "; + } + str << idx_to_infix(PoComp::EQUAL) << " " << endl; + } + str << std::setw(w) << " " << " "; + for (size_t i = 0; i < _size; i++) { + str << std::setw(w) << i << " "; } return str.str(); } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 3b8ea9c2d..ac0735725 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -51,7 +51,6 @@ class PartialOrdering bool set(Ordering::Constraint con); std::string to_string() const; - std::string to_string_raw() const; private: size_t idx_of_elem(TermList t) const; From 16885b892d60123676283cbc9298911315d74cfc Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 10 Oct 2024 16:12:05 +0200 Subject: [PATCH 27/64] Add set_inferred_loop for incomparable variants --- Kernel/PartialOrdering.cpp | 211 ++++++++++++++++++++++++++++++------- Kernel/PartialOrdering.hpp | 1 + 2 files changed, 171 insertions(+), 41 deletions(-) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 99de67af8..fe99d154b 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -53,6 +53,17 @@ constexpr PoComp weaken(PoComp v) { } } +constexpr PoComp strengthen(PoComp v) { + switch (v) { + case PoComp::NLEQ: + return PoComp::GREATER; + case PoComp::NGEQ: + return PoComp::LESS; + default: + ASSERTION_VIOLATION; + } +} + Result poCompToResult(PoComp c) { switch (c) { case PoComp::UNKNOWN: @@ -291,42 +302,46 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) ASS_NEQ(x,y); Stack above; + Stack above_w; Stack below; + Stack below_w; bool sort = x < y; size_t min = sort ? x : y; size_t max = sort ? y : x; - auto inv = reverse(rel); // inverse of rel + auto rev = reverse(rel); // reverse of rel auto wkn = weaken(rel); // weakened variant of rel - auto iwkn = reverse(wkn); // inverse of wkn + auto rwkn = reverse(wkn); // reverse of wkn // z above; + Stack below; + bool sort = x < y; + size_t min = sort ? x : y; + size_t max = sort ? y : x; + auto rel = strengthen(wkn); // stronger variant of wkn + auto rev = reverse(rel); // reverse of rel + auto rwkn = reverse(wkn); // reverse of wkn + + // z y: then ∀z. y ≥ z, also x > z, and ∀z. z ≥ x, also z > y */ case PoComp::GREATER: - set_inferred_loop(x, y, PoComp::GREATER); - break; /* x < y: then ∀z. y ≤ z, also x < z, and ∀z. z ≤ x, also z < y */ case PoComp::LESS: - set_inferred_loop(x, y, PoComp::LESS); + set_inferred_loop(x, y, result); break; /* x = y: then ∀z. z = x, also z = y and ∀z. z = y, also z = x @@ -676,7 +798,14 @@ void PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) case PoComp::EQUAL: set_inferred_loop_eq(x, y); break; - /* if INC then nothing can be inferred */ + case PoComp::NGEQ: + case PoComp::NLEQ: + set_inferred_loop_inc(x, y, result); + break; + case PoComp::INCOMPARABLE: + set_inferred_loop_inc(x, y, PoComp::NGEQ); + set_inferred_loop_inc(x, y, PoComp::NLEQ); + break; default: break; } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index ac0735725..0fc7d45e0 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -61,6 +61,7 @@ class PartialOrdering void set_inferred(size_t x, size_t y, PoComp result); void set_inferred_loop(size_t x, size_t y, PoComp rel); + void set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); void set_inferred_loop_eq(size_t x, size_t y); Map _nodes; From cdf3d93b96b49ae7bcd9fdb7ca6779842b31a58a Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 31 Oct 2024 15:20:37 +0100 Subject: [PATCH 28/64] Sync naming conventions with current paper state --- Kernel/KBOComparator.cpp | 10 ++--- Kernel/LPOComparator.cpp | 22 +++++------ Kernel/OrderingComparator.cpp | 73 ++++++++++++++++++----------------- Kernel/OrderingComparator.hpp | 22 +++++------ Kernel/PartialOrdering.cpp | 4 +- 5 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index dcad4c288..6a1504a34 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -61,7 +61,7 @@ void KBOComparator::expandTermCase() auto eqBranch = node->eqBranch; auto gtBranch = node->gtBranch; - auto incBranch = node->incBranch; + auto ngeBranch = node->ngeBranch; auto curr = _curr; bool weightAdded = (w < 0 || varInbalance); @@ -70,11 +70,11 @@ void KBOComparator::expandTermCase() return e1.second>e2.second; }); // we mutate the original node - curr->node()->tag = T_WEIGHT; + curr->node()->tag = T_POLY; curr->node()->w = w; curr->node()->varCoeffPairs = nonzeros.release(); curr->node()->gtBranch = gtBranch; - curr->node()->incBranch = incBranch; + curr->node()->ngeBranch = ngeBranch; curr = &curr->node()->eqBranch; } @@ -84,7 +84,7 @@ void KBOComparator::expandTermCase() switch (prec) { case Ordering::LESS: { - *curr = incBranch; + *curr = ngeBranch; break; } case Ordering::GREATER: { @@ -102,7 +102,7 @@ void KBOComparator::expandTermCase() } else { *curr = Branch(lhsArg,rhsArg); curr->node()->gtBranch = gtBranch; - curr->node()->incBranch = incBranch; + curr->node()->ngeBranch = ngeBranch; } curr = &curr->node()->eqBranch; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index b9c1ec2d1..21aad1f79 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -27,7 +27,7 @@ void LPOComparator::majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, for (unsigned j = i; j < t->arity(); j++) { *branch = Branch(tl1,*t->nthArgument(j)); branch->node()->eqBranch = fail; - branch->node()->incBranch = fail; + branch->node()->ngeBranch = fail; branch = &branch->node()->gtBranch; } *branch = std::move(success); @@ -43,7 +43,7 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = Branch(*s->nthArgument(j),tl2); branch->node()->eqBranch = success; branch->node()->gtBranch = success; - branch = &branch->node()->incBranch; + branch = &branch->node()->ngeBranch; } *branch = std::move(fail); } @@ -56,9 +56,9 @@ void LPOComparator::expandTermCase() auto rhs = node->rhs; auto eqBranch = node->eqBranch; auto gtBranch = node->gtBranch; - auto incBranch = node->incBranch; + auto ngeBranch = node->ngeBranch; - ASS_EQ(node->tag, T_COMPARISON); + ASS_EQ(node->tag, T_TERM); ASS(!node->ready); ASS(lhs.isTerm() && rhs.isTerm()); @@ -78,16 +78,16 @@ void LPOComparator::expandTermCase() auto t_arg = *rhs.term()->nthArgument(i); if (i == 0) { // we mutate the original node in the first iteration - ASS_EQ(curr->node()->tag, T_COMPARISON); + ASS_EQ(curr->node()->tag, T_TERM); curr->node()->lhs = s_arg; curr->node()->rhs = t_arg; } else { *curr = Branch(s_arg,t_arg); } // greater branch is a majo chain - majoChain(&curr->node()->gtBranch, lhs, rhs.term(), i+1, gtBranch, incBranch); + majoChain(&curr->node()->gtBranch, lhs, rhs.term(), i+1, gtBranch, ngeBranch); // incomparable branch is an alpha chain - alphaChain(&curr->node()->incBranch, lhs.term(), i+1, rhs, gtBranch, incBranch); + alphaChain(&curr->node()->ngeBranch, lhs.term(), i+1, rhs, gtBranch, ngeBranch); curr = &curr->node()->eqBranch; } *curr = eqBranch; @@ -98,9 +98,9 @@ void LPOComparator::expandTermCase() // we mutate the original node in the first iteration _curr->node()->lhs = lhs; _curr->node()->rhs = *t->nthArgument(0); - _curr->node()->eqBranch = incBranch; - _curr->node()->incBranch = incBranch; - majoChain(&_curr->node()->gtBranch, lhs, t, 1, gtBranch, incBranch); + _curr->node()->eqBranch = ngeBranch; + _curr->node()->ngeBranch = ngeBranch; + majoChain(&_curr->node()->gtBranch, lhs, t, 1, gtBranch, ngeBranch); break; } case Ordering::LESS: { @@ -110,7 +110,7 @@ void LPOComparator::expandTermCase() _curr->node()->rhs = rhs; _curr->node()->eqBranch = gtBranch; _curr->node()->gtBranch = gtBranch; - alphaChain(&_curr->node()->incBranch, s, 1, rhs, gtBranch, incBranch); + alphaChain(&_curr->node()->ngeBranch, s, 1, rhs, gtBranch, ngeBranch); break; } default: diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 527db723a..a013dee25 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -27,13 +27,13 @@ namespace Kernel { std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) { switch (t) { - case OrderingComparator::BranchTag::T_RESULT: + case OrderingComparator::BranchTag::T_DATA: out << "r"; break; - case OrderingComparator::BranchTag::T_COMPARISON: + case OrderingComparator::BranchTag::T_TERM: out << "c"; break; - case OrderingComparator::BranchTag::T_WEIGHT: + case OrderingComparator::BranchTag::T_POLY: out << "w"; break; } @@ -44,18 +44,18 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node { out << (OrderingComparator::BranchTag)node.tag << (node.ready?" ":"? "); switch (node.tag) { - case OrderingComparator::BranchTag::T_RESULT: { + case OrderingComparator::BranchTag::T_DATA: { out << node.data; break; } - case OrderingComparator::BranchTag::T_WEIGHT: { + case OrderingComparator::BranchTag::T_POLY: { out << node.w << " "; for (const auto& [var, coeff] : *node.varCoeffPairs) { out << "X" << var << " " << coeff << " "; } break; } - case OrderingComparator::BranchTag::T_COMPARISON: { + case OrderingComparator::BranchTag::T_TERM: { out << node.lhs << " " << node.rhs; break; } @@ -66,7 +66,7 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) { Stack> todo; - todo.push(std::make_pair(&comp._root,0)); + todo.push(std::make_pair(&comp._source,0)); // Note: using this set we get a more compact representation DHSet seen; @@ -81,12 +81,12 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } str << *kv.first->node() << std::endl; if (seen.insert(kv.first->node())) { - if (kv.first->node()->tag==OrderingComparator::BranchTag::T_RESULT) { + if (kv.first->node()->tag==OrderingComparator::BranchTag::T_DATA) { if (kv.first->node()->data) { todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); } } else { - todo.push(std::make_pair(&kv.first->node()->incBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->ngeBranch,kv.second+1)); todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); } @@ -96,22 +96,22 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) -: _ord(ord), _root(), _fail(nullptr, Branch()), _curr(&_root), _prev(nullptr) +: _ord(ord), _source(), _sink(nullptr, Branch()), _curr(&_source), _prev(nullptr) { ASS(result); static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; - auto curr = &_root; + auto curr = &_source; for (const auto& [lhs,rhs,rel] : comps) { *curr = OrderingComparator::Branch(lhs, rhs); for (unsigned i = 0; i < 3; i++) { if (ordVals[i] != comps[0].rel) { - curr->node()->getBranch(ordVals[i]) = _fail; + curr->node()->getBranch(ordVals[i]) = _sink; } } curr = &curr->node()->getBranch(rel); } - *curr = Branch(result, _fail); - _fail.node()->ready = true; + *curr = Branch(result, _sink); + _sink.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; @@ -124,7 +124,7 @@ void* OrderingComparator::next(const SubstApplicator* applicator) auto node = _curr->node(); ASS(node->ready); - if (node->tag == BranchTag::T_RESULT) { + if (node->tag == BranchTag::T_DATA) { if (!node->data) { return nullptr; } @@ -134,13 +134,13 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } Ordering::Result comp = Ordering::INCOMPARABLE; - if (node->tag == BranchTag::T_COMPARISON) { + if (node->tag == BranchTag::T_TERM) { comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); // _trace.set({ node->lhs, node->rhs, comp }); } else { - ASS(node->tag == BranchTag::T_WEIGHT); + ASS(node->tag == BranchTag::T_POLY); const auto& kbo = static_cast(_ord); auto weight = node->w; @@ -185,7 +185,7 @@ void OrderingComparator::insert(const Stack& comps, void* ASS(result); static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; // we mutate current fail node and add a new one - auto curr = &_fail; + auto curr = &_sink; Branch newFail(nullptr, Branch()); newFail.node()->ready = true; @@ -193,7 +193,7 @@ void OrderingComparator::insert(const Stack& comps, void* curr->node()->ready = false; if (comps.isNonEmpty()) { - curr->node()->tag = T_COMPARISON; + curr->node()->tag = T_TERM; curr->node()->lhs = comps[0].lhs; curr->node()->rhs = comps[0].rhs; for (unsigned i = 0; i < 3; i++) { @@ -214,12 +214,12 @@ void OrderingComparator::insert(const Stack& comps, void* } *curr = Branch(result, newFail); } else { - curr->node()->tag = T_RESULT; + curr->node()->tag = T_DATA; curr->node()->data = result; curr->node()->alternative = newFail; } - _fail = newFail; + _sink = newFail; } void OrderingComparator::expand() @@ -229,7 +229,7 @@ void OrderingComparator::expand() { auto node = _curr->node(); - if (node->tag == BranchTag::T_RESULT) { + if (node->tag == BranchTag::T_DATA) { ASS(node->data); // no fail nodes here // if refcnt > 1 we copy the node and // we can also safely use the original @@ -240,7 +240,8 @@ void OrderingComparator::expand() _curr->node()->ready = true; return; } - if (node->tag == BranchTag::T_WEIGHT) { + if (node->tag == BranchTag::T_POLY) { + auto trace = getCurrentTrace(); // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { @@ -248,9 +249,9 @@ void OrderingComparator::expand() *_curr = Branch(node->w, varCoeffPairs); _curr->node()->eqBranch = node->eqBranch; _curr->node()->gtBranch = node->gtBranch; - _curr->node()->incBranch = node->incBranch; + _curr->node()->ngeBranch = node->ngeBranch; } - _curr->node()->trace = getCurrentTrace().release(); + _curr->node()->trace = trace.release(); _curr->node()->ready = true; return; } @@ -260,7 +261,7 @@ void OrderingComparator::expand() auto comp = _ord.compare(node->lhs,node->rhs); if (comp != Ordering::INCOMPARABLE) { if (comp == Ordering::LESS) { - *_curr = node->incBranch; + *_curr = node->ngeBranch; } else if (comp == Ordering::GREATER) { *_curr = node->gtBranch; } else { @@ -299,7 +300,7 @@ bool OrderingComparator::tryExpandVarCase() } else if (val == Ordering::EQUAL) { *_curr = node->eqBranch; } else { - *_curr = node->incBranch; + *_curr = node->ngeBranch; } return true; } @@ -310,10 +311,10 @@ bool OrderingComparator::tryExpandVarCase() auto st = sti.next(); if (trace->get(node->lhs, st, val)) { if (val == Ordering::INCOMPARABLE) { - *_curr = node->incBranch; + *_curr = node->ngeBranch; return true; } else if (val == Ordering::LESS) { - *_curr = node->incBranch; + *_curr = node->ngeBranch; return true; } } @@ -325,7 +326,7 @@ bool OrderingComparator::tryExpandVarCase() *_curr = Branch(node->lhs, node->rhs); _curr->node()->eqBranch = node->eqBranch; _curr->node()->gtBranch = node->gtBranch; - _curr->node()->incBranch = node->incBranch; + _curr->node()->ngeBranch = node->ngeBranch; } _curr->node()->ready = true; _curr->node()->trace = trace.release(); @@ -344,7 +345,7 @@ ScopedPtr OrderingComparator::getCurrentTrace() ASS(_prev->node()->trace); switch (_prev->node()->tag) { - case BranchTag::T_COMPARISON: { + case BranchTag::T_TERM: { auto trace = new Trace(*_prev->node()->trace); auto lhs = _prev->node()->lhs; auto rhs = _prev->node()->rhs; @@ -375,10 +376,10 @@ ScopedPtr OrderingComparator::getCurrentTrace() } return ScopedPtr(trace); } - case BranchTag::T_RESULT: { + case BranchTag::T_DATA: { return ScopedPtr(new Trace(*_prev->node()->trace)); } - case BranchTag::T_WEIGHT: { + case BranchTag::T_POLY: { return ScopedPtr(new Trace(*_prev->node()->trace)); } } @@ -422,12 +423,12 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other OrderingComparator::Node::~Node() { switch(tag) { - case T_RESULT: + case T_DATA: alternative.~Branch(); break; - case T_COMPARISON: + case T_TERM: break; - case T_WEIGHT: + case T_POLY: delete varCoeffPairs; break; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index a345850ed..be3dbd5be 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -34,7 +34,7 @@ struct OrderingComparator OrderingComparator(const Ordering& ord, const Stack& comps, void* result); virtual ~OrderingComparator(); - void reset() { _curr = &_root; _prev = nullptr; /* _trace.reset(); */ } + void reset() { _curr = &_source; _prev = nullptr; /* _trace.reset(); */ } void* next(const SubstApplicator* applicator); void insert(const Stack& comps, void* result); @@ -47,9 +47,9 @@ struct OrderingComparator bool tryExpandVarCase(); enum BranchTag { - T_RESULT = 0u, - T_COMPARISON = 1u, - T_WEIGHT = 2u, + T_DATA = 0u, + T_TERM = 1u, + T_POLY = 2u, }; struct Node; @@ -102,18 +102,18 @@ struct OrderingComparator case Ordering::GREATER: return gtBranch; case Ordering::INCOMPARABLE: - return incBranch; + return ngeBranch; default: ASSERTION_VIOLATION; } } explicit Node(void* data, Branch alternative) - : tag(T_RESULT), data(data), alternative(alternative) {} + : tag(T_DATA), data(data), alternative(alternative) {} explicit Node(TermList lhs, TermList rhs) - : tag(T_COMPARISON), lhs(lhs), rhs(rhs) {} + : tag(T_TERM), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) - : tag(T_WEIGHT), w(w), varCoeffPairs(varCoeffPairs) {} + : tag(T_POLY), w(w), varCoeffPairs(varCoeffPairs) {} Node(const Node&) = delete; Node& operator=(const Node&) = delete; @@ -138,14 +138,14 @@ struct OrderingComparator Branch eqBranch; Branch gtBranch; - Branch incBranch; + Branch ngeBranch; int refcnt = 0; Trace* trace = nullptr; }; const Ordering& _ord; - Branch _root; - Branch _fail; + Branch _source; + Branch _sink; Branch* _curr; Branch* _prev; // Trace _trace; diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index fe99d154b..0cacedb8c 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -66,8 +66,6 @@ constexpr PoComp strengthen(PoComp v) { Result poCompToResult(PoComp c) { switch (c) { - case PoComp::UNKNOWN: - ASSERTION_VIOLATION; case PoComp::GREATER: return Result::GREATER; case PoComp::EQUAL: @@ -78,7 +76,9 @@ Result poCompToResult(PoComp c) { case PoComp::NLEQ: case PoComp::INCOMPARABLE: return Result::INCOMPARABLE; + default: } + ASSERTION_VIOLATION; } PoComp resultToPoComp(Result r, bool reversed) { From cf499e97f41324a51aa2a08478389fb876bb5e3d Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 5 Nov 2024 11:38:26 +0100 Subject: [PATCH 29/64] GCC complains about empty case in switch --- Kernel/PartialOrdering.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 0cacedb8c..b040e3881 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -77,6 +77,7 @@ Result poCompToResult(PoComp c) { case PoComp::INCOMPARABLE: return Result::INCOMPARABLE; default: + break; } ASSERTION_VIOLATION; } From 9a1c30a86cc6899c0e6eeaf1b945ae6cc8ca682d Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 5 Nov 2024 14:50:01 +0100 Subject: [PATCH 30/64] Add ability to output ordering diagrams as dot DAGs --- Kernel/OrderingComparator.cpp | 135 ++++++++++++++++++++++++++++++++++ Kernel/OrderingComparator.hpp | 1 + Kernel/PartialOrdering.hpp | 1 + 3 files changed, 137 insertions(+) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index a013dee25..629f2cfd9 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -95,6 +95,141 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) return str; } +std::string to_tikz_term(TermList t) +{ + if (t.isVar()) { + switch (t.var()) { + case 0: + return "x"; + case 1: + return "y"; + case 2: + return "z"; + default: + return "x_"+Int::toString(t.var()); + } + } + auto tt = t.term(); + auto res = tt->functionName() + "("; + for (unsigned i = 0; i < tt->arity(); i++) { + res += to_tikz_term(*tt->nthArgument(i)) + ","; + } + res += ")"; + return res; +} + +std::string OrderingComparator::to_dot() const +{ + std::deque todo; + todo.push_back(_source.node()); + // Note: using this set we get a more compact representation + DHMap seen; + + seen.insert(_source.node(), 0); + unsigned cnt = 1; + + auto getId = [&todo,&seen,&cnt](auto n) { + unsigned* ptr; + if (seen.getValuePtr(n,ptr)) { + todo.push_back(n); + *ptr = cnt++; + } + return *ptr; + }; + + enum class EdgeTag { + GT, + EQ, + INC, + ALT, + }; + auto getBranch = [&getId](unsigned from, auto to_node, EdgeTag tag) -> std::string + { + auto res = "n" + Int::toString(from) + " -> n" + Int::toString(getId(to_node)); + switch (tag) { + case EdgeTag::GT: + res += " [style = gtedge]"; + break; + case EdgeTag::EQ: + res += " [style = eqedge]"; + break; + case EdgeTag::INC: + res += " [style = ngeedge]"; + break; + case EdgeTag::ALT: + res += " [style = trueedge]"; + break; + } + return res + ";\n"; + }; + + std::string nodes = "source [style = invisible, label = \"\"];\n"; + std::string edges = "source -> n0 [style = trueedge];\n"; + + while (!todo.empty()) { + auto n = todo.front(); + todo.pop_front(); + auto id = seen.get(n); + + std::string style = ""; + std::string label = ""; + if (n->ready) { + style += "processed,"; + } + switch (n->tag) { + case BranchTag::T_DATA: { + auto alt = n->alternative.node(); + if (!alt) { + // do not output anything for the fail node + style += "sinknode,"; + label += ""; + break; + } + style += "datanode,"; + label += Int::toString((unsigned long)n->data); + edges += getBranch(id, alt, EdgeTag::ALT); + break; + } + case BranchTag::T_TERM: { + // nodes += "termnode] (n" + Int::toString(id) + ") at (" + Int::toString(x) + "," + Int::toString(y) + ") {$" + // + to_tikz_term(n->lhs) + " \\comp " + to_tikz_term(n->rhs) + "$};\n"; + style += "termnode,"; + label += "$" + to_tikz_term(n->lhs) + " \\comp " + to_tikz_term(n->rhs) + "$"; + edges += getBranch(id, n->gtBranch.node(), EdgeTag::GT); + edges += getBranch(id, n->eqBranch.node(), EdgeTag::EQ); + edges += getBranch(id, n->ngeBranch.node(), EdgeTag::INC); + break; + } + case BranchTag::T_POLY: { + style += "polynode,"; + bool first = true; + label += "$"; + for (const auto& [var, coeff] : *n->varCoeffPairs) { + label += coeff<0 ? "-" : (first ? "" : "+"); + first = false; + auto a = std::abs(coeff); + if (a==1) { + label += to_tikz_term(TermList::var(var)); + } else { + label += Int::toString(a) + "\\cdot " + to_tikz_term(TermList::var(var)); + } + } + if (n->w) { + label += n->w<0 ? "-" : (first ? "" : "+"); + label += Int::toString((int)std::abs(n->w)); + } + label += "$"; + edges += getBranch(id, n->gtBranch.node(), EdgeTag::GT); + edges += getBranch(id, n->eqBranch.node(), EdgeTag::EQ); + edges += getBranch(id, n->ngeBranch.node(), EdgeTag::INC); + break; + } + } + nodes += "n" + Int::toString(id) + " [\n style = \"" + style + "\"\n label = \"" + label + "\"\n];\n"; + } + return "digraph {\nnodesep = 0;\nsep = 0;\nranksep = 0;\nesep = 0;\n" + nodes + "\n" + edges + "}\n"; +} + OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) : _ord(ord), _source(), _sink(nullptr, Branch()), _curr(&_source), _prev(nullptr) { diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index be3dbd5be..9965acac6 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -40,6 +40,7 @@ struct OrderingComparator void insert(const Stack& comps, void* result); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); + std::string to_dot() const; protected: void expand(); diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 0fc7d45e0..9cfd86b0f 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -56,6 +56,7 @@ class PartialOrdering size_t idx_of_elem(TermList t) const; size_t idx_of_elem_ext(TermList t); PoComp idx_of(size_t x, size_t y) const; + PoComp idx_of_safe(size_t x, size_t y) const; bool set_idx_of(size_t x, size_t y, PoComp v); bool set_idx_of_safe(size_t x, size_t y, PoComp v); From f9cbe224121ae88da41e49a2f89a114ab5d8575f Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sun, 10 Nov 2024 11:55:07 +0100 Subject: [PATCH 31/64] Some improvements to PartialOrdering --- Kernel/OrderingComparator.cpp | 22 ++- Kernel/PartialOrdering.cpp | 273 ++++------------------------------ 2 files changed, 49 insertions(+), 246 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 629f2cfd9..76861adc9 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -440,16 +440,26 @@ bool OrderingComparator::tryExpandVarCase() return true; } // TODO eventually incorporate this into the Trace - if (node->lhs.isVar() && node->rhs.isTerm()) { + if (node->rhs.isTerm()) { SubtermIterator sti(node->rhs.term()); while (sti.hasNext()) { auto st = sti.next(); if (trace->get(node->lhs, st, val)) { - if (val == Ordering::INCOMPARABLE) { + if (val == Ordering::INCOMPARABLE || val == Ordering::LESS) { *_curr = node->ngeBranch; return true; - } else if (val == Ordering::LESS) { - *_curr = node->ngeBranch; + } + } + } + } + if (node->lhs.isTerm()) { + SubtermIterator sti(node->lhs.term()); + while (sti.hasNext()) { + auto st = sti.next(); + if (trace->get(st, node->rhs, val)) { + // node->lhs > st ≥ node->rhs → node->lhs > node->rhs + if (val == Ordering::GREATER || val == Ordering::EQUAL) { + *_curr = node->gtBranch; return true; } } @@ -498,14 +508,14 @@ ScopedPtr OrderingComparator::getCurrentTrace() if (lhs.isTerm()) { SubtermIterator stit(lhs.term()); while (stit.hasNext()) { - trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE }); + ALWAYS(trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })); } } } else { if (rhs.isTerm()) { SubtermIterator stit(rhs.term()); while (stit.hasNext()) { - trace->set({ lhs, stit.next(), Ordering::GREATER }); + ALWAYS(trace->set({ lhs, stit.next(), Ordering::GREATER })); } } } diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index b040e3881..67fe4daa6 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -298,6 +298,15 @@ PoComp PartialOrdering::idx_of(size_t x, size_t y) const return _array[idx]; } +PoComp PartialOrdering::idx_of_safe(size_t x, size_t y) const +{ + if (x < y) { + return idx_of(x,y); + } else { + return reverse(idx_of(y,x)); + } +} + void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) { ASS_NEQ(x,y); @@ -306,146 +315,38 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) Stack above_w; Stack below; Stack below_w; - bool sort = x < y; - size_t min = sort ? x : y; - size_t max = sort ? y : x; - auto rev = reverse(rel); // reverse of rel auto wkn = weaken(rel); // weakened variant of rel - auto rwkn = reverse(wkn); // reverse of wkn - - // z above; Stack below; - bool sort = x < y; - size_t min = sort ? x : y; - size_t max = sort ? y : x; auto rel = strengthen(wkn); // stronger variant of wkn - auto rev = reverse(rel); // reverse of rel - auto rwkn = reverse(wkn); // reverse of wkn - // z> y_rel; - bool sort = x < y; - size_t min = sort ? x : y; - size_t max = sort ? y : x; - - // z Date: Wed, 13 Nov 2024 09:40:35 +0100 Subject: [PATCH 32/64] Add check to initWithEquation to avoid unbound variable crash --- Shell/ConditionalRedundancyHandler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 9e7532717..72bf1413f 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -751,6 +751,9 @@ void ConditionalRedundancyHandlerImpl::initWithEqu return; } + if (!tgtTerm.containsAllVariablesOf(rwTerm)) { + return; + } Stack ordCons; ordCons.push({ tgtTerm, rwTerm, Ordering::GREATER }); auto lits = LiteralSet::getEmpty(); From e79d2d2cc2dcaf51287da751501ab5b668ebca4f Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 13 Nov 2024 12:59:34 +0100 Subject: [PATCH 33/64] Simplify polynomials and do some simplifications on the code --- Kernel/OrderingComparator.cpp | 79 ++++++++++++++++++++------ Kernel/OrderingComparator.hpp | 3 +- Shell/ConditionalRedundancyHandler.cpp | 18 +++--- Shell/ConditionalRedundancyHandler.hpp | 3 +- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 76861adc9..761497d28 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -376,7 +376,6 @@ void OrderingComparator::expand() return; } if (node->tag == BranchTag::T_POLY) { - auto trace = getCurrentTrace(); // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { @@ -386,9 +385,9 @@ void OrderingComparator::expand() _curr->node()->gtBranch = node->gtBranch; _curr->node()->ngeBranch = node->ngeBranch; } - _curr->node()->trace = trace.release(); - _curr->node()->ready = true; - return; + + processPolyCase(); + continue; } // Use compare here to filter out as many @@ -404,8 +403,9 @@ void OrderingComparator::expand() } continue; } - // If we have a variable, we cannot preprocess further. - if (tryExpandVarCase()) { + // If we have a variable, we cannot expand further. + if (node->lhs.isVar() || node->rhs.isVar()) { + processVarCase(); continue; } @@ -419,14 +419,62 @@ void OrderingComparator::expandTermCase() _curr->node()->ready = true; } -bool OrderingComparator::tryExpandVarCase() +void OrderingComparator::processPolyCase() { auto node = _curr->node(); + auto varCoeffPairs = node->varCoeffPairs; + + auto trace = getCurrentTrace(); + + unsigned pos = 0; + unsigned neg = 0; + for (unsigned i = 0; i < varCoeffPairs->size();) { + auto& [var, coeff] = (*varCoeffPairs)[i]; + for (unsigned j = i+1; j < varCoeffPairs->size();) { + auto& [var2, coeff2] = (*varCoeffPairs)[j]; + Ordering::Result res; + if (trace->get(TermList::var(var), TermList::var(var2), res) && res == Ordering::EQUAL) { + coeff += coeff2; + swap((*varCoeffPairs)[j],varCoeffPairs->top()); + varCoeffPairs->pop(); + continue; + } + j++; + } + if (coeff == 0) { + swap((*varCoeffPairs)[i],varCoeffPairs->top()); + varCoeffPairs->pop(); + continue; + } else if (coeff > 0) { + pos++; + } else { + neg++; + } + i++; + } - // If we have a variable, we cannot preprocess further. - if (!node->lhs.isVar() && !node->rhs.isVar()) { - return false; + if (node->w == 0 && pos == 0 && neg == 0) { + *_curr = node->eqBranch; + return; } + if (node->w >= 0 && neg == 0) { + *_curr = node->gtBranch; + return; + } + if (node->w <= 0 && pos == 0) { + *_curr = node->ngeBranch; + return; + } + sort(varCoeffPairs->begin(),varCoeffPairs->end(),[](const auto& e1, const auto& e2) { + return e1.second>e2.second; + }); + _curr->node()->ready = true; + _curr->node()->trace = trace.release(); +} + +void OrderingComparator::processVarCase() +{ + auto node = _curr->node(); auto trace = getCurrentTrace(); Ordering::Result val; if (trace->get(node->lhs, node->rhs, val)) { @@ -437,7 +485,7 @@ bool OrderingComparator::tryExpandVarCase() } else { *_curr = node->ngeBranch; } - return true; + return; } // TODO eventually incorporate this into the Trace if (node->rhs.isTerm()) { @@ -447,7 +495,7 @@ bool OrderingComparator::tryExpandVarCase() if (trace->get(node->lhs, st, val)) { if (val == Ordering::INCOMPARABLE || val == Ordering::LESS) { *_curr = node->ngeBranch; - return true; + return; } } } @@ -460,7 +508,7 @@ bool OrderingComparator::tryExpandVarCase() // node->lhs > st ≥ node->rhs → node->lhs > node->rhs if (val == Ordering::GREATER || val == Ordering::EQUAL) { *_curr = node->gtBranch; - return true; + return; } } } @@ -475,7 +523,6 @@ bool OrderingComparator::tryExpandVarCase() } _curr->node()->ready = true; _curr->node()->trace = trace.release(); - return true; } ScopedPtr OrderingComparator::getCurrentTrace() @@ -491,7 +538,7 @@ ScopedPtr OrderingComparator::getCurrentTrace() switch (_prev->node()->tag) { case BranchTag::T_TERM: { - auto trace = new Trace(*_prev->node()->trace); + auto trace = ScopedPtr(new Trace(*_prev->node()->trace)); auto lhs = _prev->node()->lhs; auto rhs = _prev->node()->rhs; Ordering::Result res; @@ -519,7 +566,7 @@ ScopedPtr OrderingComparator::getCurrentTrace() } } } - return ScopedPtr(trace); + return ScopedPtr(trace.release()); } case BranchTag::T_DATA: { return ScopedPtr(new Trace(*_prev->node()->trace)); diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 9965acac6..86d909324 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -45,7 +45,8 @@ struct OrderingComparator protected: void expand(); virtual void expandTermCase(); - bool tryExpandVarCase(); + void processVarCase(); + void processPolyCase(); enum BranchTag { T_DATA = 0u, diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 72bf1413f..61eebd84a 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -90,14 +90,14 @@ class ConditionalRedundancyHandler::ConstraintIndex } bool insert(const Ordering* ord, ResultSubstitution* subst, bool result, Splitter* splitter, - Stack&& ordCons, const LiteralSet* lits, SplitSet* splits) + OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) { auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } bool checkAndInsert(const Ordering* ord, ResultSubstitution* subst, bool result, bool doInsert, Splitter* splitter, - Stack&& ordCons, const LiteralSet* lits, const SplitSet* splits) + OrderingConstraints&& ordCons, const LiteralSet* lits, const SplitSet* splits) { ASS(lits); // TODO if this correct if we allow non-unit simplifications? @@ -283,7 +283,7 @@ class ConditionalRedundancyHandler::ConstraintIndex DHMap _varSorts; - ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, Stack&& ordCons, const LiteralSet* lits, SplitSet* splits) const + ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const { auto e = new ConditionalRedundancyEntry(); Renaming r; @@ -533,7 +533,7 @@ bool ConditionalRedundancyHandlerImpl::insertSuper rwClause, rwLitS, rwTermS, tgtTermS, eqClause, eqLHS, &appl, otherComp); // create ordering constraints - Stack ordCons; + OrderingConstraints ordCons; if constexpr (ordC) { // TODO we cannot handle them together yet if (eqComp != Ordering::LESS) { @@ -633,7 +633,7 @@ bool ConditionalRedundancyHandlerImpl::handleResol auto dataPtr = getDataPtr(queryCl, /*doAllocate=*/doInsert); if (dataPtr && !(*dataPtr)->checkAndInsert( - _ord, subs, /*result*/false, doInsert, _splitter, Stack(), lits, splits)) + _ord, subs, /*result*/false, doInsert, _splitter, OrderingConstraints(), lits, splits)) { env.statistics->skippedResolution++; return false; @@ -671,7 +671,7 @@ bool ConditionalRedundancyHandlerImpl::handleResol auto dataPtr = getDataPtr(resultCl, /*doAllocate=*/doInsert); if (dataPtr && !(*dataPtr)->checkAndInsert( - _ord, subs, /*result*/true, doInsert, _splitter, Stack(), lits, splits)) + _ord, subs, /*result*/true, doInsert, _splitter, OrderingConstraints(), lits, splits)) { env.statistics->skippedResolution++; return false; @@ -692,7 +692,7 @@ bool ConditionalRedundancyHandlerImpl::handleReduc auto lits = LiteralSet::getEmpty(); auto splits = SplitSet::getEmpty(); if (!(*dataPtr)->checkAndInsert( - _ord, subst.ptr(), /*result*/false, /*doInsert=*/true, _splitter, Stack(), lits, splits)) + _ord, subst.ptr(), /*result*/false, /*doInsert=*/true, _splitter, OrderingConstraints(), lits, splits)) { return false; } @@ -754,7 +754,7 @@ void ConditionalRedundancyHandlerImpl::initWithEqu if (!tgtTerm.containsAllVariablesOf(rwTerm)) { return; } - Stack ordCons; + OrderingConstraints ordCons; ordCons.push({ tgtTerm, rwTerm, Ordering::GREATER }); auto lits = LiteralSet::getEmpty(); auto splits = SplitSet::getEmpty(); @@ -788,7 +788,7 @@ void ConditionalRedundancyHandlerImpl::checkEquati } auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, Stack(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); }); } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 87e6bc37e..5d3dda75d 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -56,12 +56,13 @@ namespace Shell { using namespace Lib; using namespace Indexing; +using OrderingConstraints = Stack; using LiteralSet = SharedSet; struct ConditionalRedundancyEntry { Stack> eqCons; - Stack ordCons; + OrderingConstraints ordCons; const LiteralSet* lits; SplitSet* splits; bool active = true; From 5c4c5a699c5e76152440ec4be5009646ab4c53db Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 14 Nov 2024 09:37:50 +0100 Subject: [PATCH 34/64] Remove duplicate code for insertion in OrderingComparator ctor - only allow through insert --- Indexing/Index.hpp | 3 ++- Inferences/BackwardDemodulation.cpp | 14 ++++---------- Kernel/KBO.cpp | 4 ++-- Kernel/KBO.hpp | 2 +- Kernel/KBOComparator.hpp | 5 +---- Kernel/LPO.cpp | 4 ++-- Kernel/LPO.hpp | 2 +- Kernel/LPOComparator.hpp | 3 +-- Kernel/Ordering.cpp | 4 ++-- Kernel/OrderingComparator.cpp | 17 ++--------------- Kernel/OrderingComparator.hpp | 2 +- Shell/ConditionalRedundancyHandler.cpp | 3 ++- 12 files changed, 21 insertions(+), 42 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index d3f3ebde1..7cbaf9752 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -167,7 +167,8 @@ struct DemodulatorDataContainer { } auto ptr = new DemodulatorData(std::move(dd)); dds.push(ptr); - comparator = ord.createComparator(ordCons, ptr); + comparator = ord.createComparator(); + comparator->insert(ordCons, ptr); } ~DemodulatorDataContainer() { diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index 6ab1123aa..23fb96434 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -106,16 +106,10 @@ struct BackwardDemodulation::ResultFn { ASS_EQ(_cl->length(),1); _eqLit=(*_cl)[0]; - { - Stack leftCons; - leftCons.push({ *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER }); - _comps.first = _ordering.createComparator(leftCons, (void*)0x1); - } - { - Stack rightCons; - rightCons.push({ *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER }); - _comps.second = _ordering.createComparator(rightCons, (void*)0x1); - } + _comps.first = _ordering.createComparator(); + _comps.first->insert({ { *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER } }, (void*)0x1); + _comps.second = _ordering.createComparator(); + _comps.second->insert({ { *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER } }, (void*)0x1); _removed=SmartPtr(new ClauseSet()); } diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index 1b637701d..7499762c3 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -874,9 +874,9 @@ Ordering::Result KBO::isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const return res; } -OrderingComparatorUP KBO::createComparator(const Stack& cons, void* result) const +OrderingComparatorUP KBO::createComparator() const { - return make_unique(*this, cons, result); + return make_unique(*this); } int KBO::symbolWeight(const Term* t) const diff --git a/Kernel/KBO.hpp b/Kernel/KBO.hpp index 9d01c6686..df5a6632e 100644 --- a/Kernel/KBO.hpp +++ b/Kernel/KBO.hpp @@ -158,7 +158,7 @@ class KBO Result compare(AppliedTerm t1, AppliedTerm t2) const override; Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const override; - OrderingComparatorUP createComparator(const Stack& cons, void* result) const override; + OrderingComparatorUP createComparator() const override; protected: unsigned computeWeight(AppliedTerm tt) const; diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 7c3f2a98c..359b49f34 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -17,8 +17,6 @@ #include "Forwards.hpp" -#include "Lib/Stack.hpp" - #include "OrderingComparator.hpp" namespace Kernel { @@ -33,8 +31,7 @@ class KBOComparator : public OrderingComparator { public: - KBOComparator(const Ordering& ord, const Stack& comps, void* result) - : OrderingComparator(ord, comps, result) {} + KBOComparator(const Ordering& ord) : OrderingComparator(ord) {} void expandTermCase() override; }; diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index e1ad1ab80..53b11a820 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -247,9 +247,9 @@ Ordering::Result LPO::majo(AppliedTerm s, AppliedTerm t, const TermList* tl, uns return GREATER; } -OrderingComparatorUP LPO::createComparator(const Stack& cons, void* result) const +OrderingComparatorUP LPO::createComparator() const { - return make_unique(*this, cons, result); + return make_unique(*this); } void LPO::showConcrete(ostream&) const diff --git a/Kernel/LPO.hpp b/Kernel/LPO.hpp index 19acafa9c..32cda5f38 100644 --- a/Kernel/LPO.hpp +++ b/Kernel/LPO.hpp @@ -48,7 +48,7 @@ class LPO Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm tl1, AppliedTerm tl2) const override; Result isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const override; - OrderingComparatorUP createComparator(const Stack& cons, void* result) const override; + OrderingComparatorUP createComparator() const override; void showConcrete(std::ostream&) const override; diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index bf090181a..152194af0 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -24,8 +24,7 @@ class LPOComparator : public OrderingComparator { public: - LPOComparator(const Ordering& ord, const Stack& comps, void* result) - : OrderingComparator(ord, comps, result) {} + LPOComparator(const Ordering& ord) : OrderingComparator(ord) {} void expandTermCase() override; diff --git a/Kernel/Ordering.cpp b/Kernel/Ordering.cpp index 40ceb8104..e30ebcebf 100644 --- a/Kernel/Ordering.cpp +++ b/Kernel/Ordering.cpp @@ -210,9 +210,9 @@ Ordering::Result Ordering::getEqualityArgumentOrder(Literal* eq) const return res; } -OrderingComparatorUP Ordering::createComparator(const Stack& cons, void* result) const +OrderingComparatorUP Ordering::createComparator() const { - return std::make_unique(*this, cons, result); + return std::make_unique(*this); } ////////////////////////////////////////////////// diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 761497d28..f303618e0 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -230,22 +230,9 @@ std::string OrderingComparator::to_dot() const return "digraph {\nnodesep = 0;\nsep = 0;\nranksep = 0;\nesep = 0;\n" + nodes + "\n" + edges + "}\n"; } -OrderingComparator::OrderingComparator(const Ordering& ord, const Stack& comps, void* result) -: _ord(ord), _source(), _sink(nullptr, Branch()), _curr(&_source), _prev(nullptr) +OrderingComparator::OrderingComparator(const Ordering& ord) +: _ord(ord), _source(nullptr, Branch()), _sink(_source), _curr(&_source), _prev(nullptr) { - ASS(result); - static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; - auto curr = &_source; - for (const auto& [lhs,rhs,rel] : comps) { - *curr = OrderingComparator::Branch(lhs, rhs); - for (unsigned i = 0; i < 3; i++) { - if (ordVals[i] != comps[0].rel) { - curr->node()->getBranch(ordVals[i]) = _sink; - } - } - curr = &curr->node()->getBranch(rel); - } - *curr = Branch(result, _sink); _sink.node()->ready = true; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 86d909324..c0c3a818f 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -31,7 +31,7 @@ namespace Kernel { struct OrderingComparator { public: - OrderingComparator(const Ordering& ord, const Stack& comps, void* result); + OrderingComparator(const Ordering& ord); virtual ~OrderingComparator(); void reset() { _curr = &_source; _prev = nullptr; /* _trace.reset(); */ } diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 61eebd84a..a642493d5 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -157,7 +157,8 @@ class ConditionalRedundancyHandler::ConstraintIndex auto es = new Entries(); es->entries.push(ptr); - es->comparator = ord->createComparator(ptr->ordCons, ptr); + es->comparator = ord->createComparator(); + es->comparator->insert(ptr->ordCons, ptr); code.push(CodeOp::getSuccess(es)); incorporate(code); return true; From 6212670f61c95aacaeb66c1b3ac0564ef299d28a Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 14 Nov 2024 16:29:48 +0100 Subject: [PATCH 35/64] Some small cosmetic changes --- Kernel/Ordering.hpp | 5 ++--- Kernel/PartialOrdering.cpp | 5 ----- Kernel/PartialOrdering.hpp | 2 -- Shell/ConditionalRedundancyHandler.cpp | 26 +++++++++++++++----------- Shell/ConditionalRedundancyHandler.hpp | 1 - 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index f64f3757e..97193ad16 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -83,9 +83,8 @@ class Ordering virtual Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const { return compare(t1, t2); } - /** Creates optimised object to check that @b lhs is greater than @b rhs. - * @see OrderingComparator. */ - virtual OrderingComparatorUP createComparator(const Stack& cons, void* result) const; + /** Creates optimised object for ordering checks. @see OrderingComparator. */ + virtual OrderingComparatorUP createComparator() const; virtual void show(std::ostream& out) const = 0; diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 67fe4daa6..46102ba7a 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -118,11 +118,6 @@ PartialOrdering::~PartialOrdering() } } -void PartialOrdering::reset() -{ - std::memset(_array, 0, ((_size - 1) * _size / 2)*sizeof(PoComp)); -} - bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const { if (lhs == rhs) { diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 9cfd86b0f..0e02dccbe 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -45,8 +45,6 @@ class PartialOrdering PartialOrdering(const PartialOrdering& other); ~PartialOrdering(); - void reset(); - bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; bool set(Ordering::Constraint con); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index a642493d5..e01b1d883 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -80,13 +80,13 @@ class ConditionalRedundancyHandler::ConstraintIndex } } - bool check(const Ordering* ord, ResultSubstitution* subst, bool result, const LiteralSet* lits, const SplitSet* splits) + bool check(const Ordering* ord, ResultSubstitution* subst, bool result, const OrderingConstraints& ordCons, const LiteralSet* lits, const SplitSet* splits) { if (_varSorts.isEmpty()) { return true; } auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - return !check(ts, ord, lits, splits); + return !check(ts, ord, ordCons, lits, splits); } bool insert(const Ordering* ord, ResultSubstitution* subst, bool result, Splitter* splitter, @@ -105,7 +105,7 @@ class ConditionalRedundancyHandler::ConstraintIndex return true; } auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - if (check(ts, ord, lits, splits)) { + if (check(ts, ord, ordCons, lits, splits)) { return false; } if (doInsert) { @@ -152,7 +152,9 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(t.isTerm()); compiler.handleTerm(t.term()); } - ptr->eqCons = compiler.eqCons; + for (const auto& [x,y] : compiler.eqCons) { + ptr->ordCons.push({ TermList::var(x), TermList::var(y), Ordering::EQUAL }); + } compiler.updateCodeTree(this); auto es = new Entries(); @@ -164,7 +166,7 @@ class ConditionalRedundancyHandler::ConstraintIndex return true; } - bool check(const TermStack& ts, const Ordering* ord, const LiteralSet* lits, const SplitSet* splits) + bool check(const TermStack& ts, const Ordering* ord, const OrderingConstraints& ordCons, const LiteralSet* lits, const SplitSet* splits) { if (isEmpty()) { return false; @@ -208,7 +210,7 @@ class ConditionalRedundancyHandler::ConstraintIndex #if DEBUG_ORDERING auto ordCons_crosscheck = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==Ordering::GREATER; + return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; }); if (!ordCons_crosscheck) { cout << e << endl; @@ -255,7 +257,7 @@ class ConditionalRedundancyHandler::ConstraintIndex // check ordering constraints auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==Ordering::GREATER; + return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; }); if (!ordCons_ok) { continue; @@ -370,9 +372,11 @@ class ConditionalRedundancyHandler::ConstraintIndex } } - std::string leafToString(const CodeOp* success) const override { + std::string leafToString(const CodeOp* op) const override { std::stringstream str; - // TODO + ASS(op->isSuccess()); + auto es = op->getSuccessResult(); + str << *es->comparator; return str.str(); } @@ -481,7 +485,7 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp } auto eqClDataPtr = getDataPtr(eqClause, /*doAllocate=*/false); - if (eqClDataPtr && !(*eqClDataPtr)->check(_ord, subs, eqIsResult, rwLits, rwSplits)) { + if (eqClDataPtr && !(*eqClDataPtr)->check(_ord, subs, eqIsResult, OrderingConstraints(), rwLits, rwSplits)) { env.statistics->skippedSuperposition++; return false; } @@ -501,7 +505,7 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp } auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); - if (rwClDataPtr && !(*rwClDataPtr)->check(_ord, subs, !eqIsResult, eqLits, eqSplits)) { + if (rwClDataPtr && !(*rwClDataPtr)->check(_ord, subs, !eqIsResult, OrderingConstraints(), eqLits, eqSplits)) { env.statistics->skippedSuperposition++; return false; } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 5d3dda75d..0033e378e 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -61,7 +61,6 @@ using LiteralSet = SharedSet; struct ConditionalRedundancyEntry { - Stack> eqCons; OrderingConstraints ordCons; const LiteralSet* lits; SplitSet* splits; From 9d4df6a5e445eba8fddb430065a59a6b5492e648 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 14 Nov 2024 19:55:05 +0100 Subject: [PATCH 36/64] Enable linearization and secondary redundancy check --- Shell/ConditionalRedundancyHandler.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index e01b1d883..549656124 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -138,7 +138,7 @@ class ConditionalRedundancyHandler::ConstraintIndex } CodeStack code; -#define LINEARIZE 0 +#define LINEARIZE 1 #if LINEARIZE Compiler compiler(code); #else @@ -542,11 +542,12 @@ bool ConditionalRedundancyHandlerImpl::insertSuper if constexpr (ordC) { // TODO we cannot handle them together yet if (eqComp != Ordering::LESS) { - if (!premiseRedundant || !rwTermS.containsAllVariablesOf(tgtTermS)) { + if (!rwTermS.containsAllVariablesOf(tgtTermS)) { return true; } ordCons.push({ rwTermS, tgtTermS, Ordering::GREATER }); - } else if (!premiseRedundant) { + } + if (!premiseRedundant) { TermList other = EqHelper::getOtherEqualitySide(rwLitS, rwTermS); if (otherComp != Ordering::INCOMPARABLE || !other.containsAllVariablesOf(tgtTermS)) { return true; From 88d3c0a2c611bc0c371704bc7b13657a089bb7ce Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 15 Nov 2024 11:17:41 +0100 Subject: [PATCH 37/64] Change inserting into same conditional redundancy entry; original was buggy, new only works with linearization --- Indexing/CodeTree.cpp | 10 +----- Indexing/CodeTree.hpp | 9 ++--- Inferences/Superposition.cpp | 6 ++-- Shell/ConditionalRedundancyHandler.cpp | 47 ++++++++++++++++++-------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index 6d090361f..59e6dc238 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -1383,8 +1383,7 @@ bool CodeTree::Matcher::execute() bool shouldBacktrack=false; for(;;) { if(op->alternative()) { - btStack.pushUnsafe(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); - // btStack.push(BTPoint(tp, op->alternative(), substIsRenaming, substVRange)); + btStack.pushUnsafe(BTPoint(tp, op->alternative())); } switch(op->_instruction()) { case SUCCESS_OR_FAIL: @@ -1458,8 +1457,6 @@ bool CodeTree::Matcher::backtrack() BTPoint bp=btStack.pop(); tp=bp.tp; op=bp.op; - substIsRenaming=bp.substIsRenaming; - substVRange=bp.substVRange; return true; } @@ -1506,10 +1503,6 @@ inline void CodeTree::Matcher::doAssignVar() if(fte->_tag()==FlatTerm::VAR) { bindings[var]=TermList(fte->_number(),false); tp++; - if (fte->_number() > 64 || (substVRange & (1UL << fte->_number()))) { - substIsRenaming = false; - } - substVRange |= (1UL << fte->_number()); } else { ASS(fte->isFun()); @@ -1520,7 +1513,6 @@ inline void CodeTree::Matcher::doAssignVar() fte++; ASS_EQ(fte->_tag(), FlatTerm::FUN_RIGHT_OFS); tp+=fte->_number(); - substIsRenaming = false; } } diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 9de9c25b2..d943bd2bf 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -332,7 +332,6 @@ class CodeTree * a call to the @b prepareLiteral function). */ CodeOp* op; - bool substIsRenaming; protected: bool doCheckGroundTerm(); @@ -351,8 +350,6 @@ class CodeTree * a call to the @b prepareLiteral function). */ FlatTerm* ft; - - uint64_t substVRange; }; //////// auxiliary methods ////////// @@ -464,15 +461,13 @@ class CodeTree struct BTPoint { BTPoint() {} - BTPoint(size_t tp, CodeOp* op, bool substIsRenaming, size_t substVRange) - : tp(tp), op(op), substIsRenaming(substIsRenaming), substVRange(substVRange) {} + BTPoint(size_t tp, CodeOp* op) + : tp(tp), op(op) {} /** Position in the flat term */ size_t tp; /** Pointer to the next operation */ CodeOp* op; - bool substIsRenaming; - uint64_t substVRange; }; typedef Stack BTStack; diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index 3e5824ca8..5bf148158 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -534,9 +534,9 @@ Clause* Superposition::performSuperposition( rwTerm )); - // if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { - // condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); - // } + if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { + condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); + } return clause; } diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 549656124..258c54a2b 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -68,7 +68,7 @@ class ConditionalRedundancyHandler::ConstraintIndex : public CodeTree { public: - ConstraintIndex(Clause* cl) : _varSorts(), lastRenamingEntry(nullptr) + ConstraintIndex(Clause* cl) : _varSorts() { _clauseCodeTree=false; _onCodeOpDestroying = onCodeOpDestroying; @@ -132,11 +132,6 @@ class ConditionalRedundancyHandler::ConstraintIndex bool insert(const Ordering* ord, const TermStack& ts, ConditionalRedundancyEntry* ptr) { - if (lastRenamingEntry) { - // there is an entry up to renaming already, insert it here - return insert(ord, lastRenamingEntry, ptr); - } - CodeStack code; #define LINEARIZE 1 #if LINEARIZE @@ -162,6 +157,25 @@ class ConditionalRedundancyHandler::ConstraintIndex es->comparator = ord->createComparator(); es->comparator->insert(ptr->ordCons, ptr); code.push(CodeOp::getSuccess(es)); + +#if LINEARIZE + if (!isEmpty()) { + VariantMatcher vm; + Stack firstsInBlocks; + + FlatTerm* ft = FlatTerm::create(ts); + vm.init(ft, this, &firstsInBlocks); + + if (vm.next()) { + ASS(vm.op->isSuccess()); + auto es = vm.op->template getSuccessResult(); + ft->destroy(); + return insert(ord, es, ptr); + } + ft->destroy(); + } +#endif + incorporate(code); return true; } @@ -177,15 +191,10 @@ class ConditionalRedundancyHandler::ConstraintIndex TermList operator()(unsigned v) const override { return matcher.bindings[v]; } } applicator; - lastRenamingEntry = nullptr; matcher.init(this, ts); Entries* es; while ((es = matcher.next())) { - if (matcher.substIsRenaming) { - lastRenamingEntry = es; - } - ASS(es->comparator); es->comparator->reset(); ConditionalRedundancyEntry* e = nullptr; @@ -338,8 +347,6 @@ class ConditionalRedundancyHandler::ConstraintIndex op=entry; tp=0; - substIsRenaming=true; - substVRange=0; } void reset() @@ -364,6 +371,18 @@ class ConditionalRedundancyHandler::ConstraintIndex } }; + struct VariantMatcher + : public RemovingMatcher + { + public: + void init(FlatTerm* ft_, CodeTree* tree_, Stack* firstsInBlocks_) { + RemovingMatcher::init(tree_->getEntryPoint(), 0, 0, tree_, firstsInBlocks_); + ft=ft_; + tp=0; + op=entry; + } + }; + static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { auto es = op->getSuccessResult(); @@ -379,8 +398,6 @@ class ConditionalRedundancyHandler::ConstraintIndex str << *es->comparator; return str.str(); } - - Entries* lastRenamingEntry; }; // ConditionalRedundancyHandler From 84a137abbdac2ffa746fd6eab644cf49980c9ebb Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 15 Nov 2024 13:35:35 +0100 Subject: [PATCH 38/64] Remove data from ordering comparators for now for simplicity --- Indexing/CodeTreeInterfaces.cpp | 2 +- Indexing/Index.hpp | 99 ++-------------- Indexing/IndexManager.cpp | 2 +- Indexing/TermCodeTree.cpp | 62 +++++----- Indexing/TermIndex.cpp | 3 +- Indexing/TermIndex.hpp | 4 +- Inferences/BackwardDemodulation.cpp | 7 +- Inferences/ForwardDemodulation.cpp | 153 ++++++++++--------------- Kernel/OrderingComparator.cpp | 104 +++++++---------- Kernel/OrderingComparator.hpp | 26 ++--- Shell/ConditionalRedundancyHandler.cpp | 85 +++----------- 11 files changed, 175 insertions(+), 372 deletions(-) diff --git a/Indexing/CodeTreeInterfaces.cpp b/Indexing/CodeTreeInterfaces.cpp index 04e357d72..77c3a0ae5 100644 --- a/Indexing/CodeTreeInterfaces.cpp +++ b/Indexing/CodeTreeInterfaces.cpp @@ -180,7 +180,7 @@ bool CodeTreeTIS::generalizationExists(TermList t) } template class CodeTreeTIS; -template class CodeTreeTIS; +template class CodeTreeTIS; ///////////////// CodeTreeSubsumptionIndex ////////////////////// diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 7cbaf9752..75ef7a45e 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -18,18 +18,16 @@ #include "Forwards.hpp" #include "Debug/Output.hpp" -#include "Lib/Allocator.hpp" #include "Lib/Event.hpp" -#include "Lib/Exception.hpp" -#include "Lib/VirtualIterator.hpp" - #include "Kernel/Clause.hpp" -#include "Kernel/OrderingComparator.hpp" #include "Kernel/Term.hpp" -#include "Kernel/UnificationWithAbstraction.hpp" - +#include "Lib/Exception.hpp" +#include "Lib/VirtualIterator.hpp" #include "Saturation/ClauseContainer.hpp" #include "ResultSubstitution.hpp" +#include "Kernel/UnificationWithAbstraction.hpp" +#include "Lib/Allocator.hpp" +#include "Kernel/OrderingComparator.hpp" /** * Indices are parametrized by a LeafData, i.e. the bit of data you want to store in the index. @@ -106,12 +104,6 @@ struct TermLiteralClause IMPL_COMPARISONS_FROM_TUPLE(TermLiteralClause) - bool insert(TermLiteralClause& other) { return false; } - - bool remove(const TermLiteralClause& other) { return *this==other; } - - bool canBeDeleted() const { return true; } - friend std::ostream& operator<<(std::ostream& out, TermLiteralClause const& self) { return out << "(" << self.term << ", " @@ -125,8 +117,9 @@ struct TermLiteralClause struct DemodulatorData { DemodulatorData(TypedTermList term, TermList rhs, Clause* clause, bool preordered, const Ordering& ord) - : term(term), rhs(rhs), clause(clause), preordered(preordered) + : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator(ord.createComparator()) { + comparator->insert({ { term, rhs, Ordering::GREATER } }); #if VDEBUG ASS(term.containsAllVariablesOf(rhs)); ASS(!preordered || ord.compare(term,rhs)==Ordering::GREATER); @@ -142,6 +135,7 @@ struct DemodulatorData TermList rhs; Clause* clause; bool preordered; // whether term > rhs + OrderingComparatorUP comparator; // owned comparator for whether term > rhs TypedTermList const& key() const { return term; } @@ -151,78 +145,7 @@ struct DemodulatorData IMPL_COMPARISONS_FROM_TUPLE(DemodulatorData) friend std::ostream& operator<<(std::ostream& out, DemodulatorData const& self) - { return out << "(" << self.term << " = " << self.rhs << ", cl " << outputPtr(self.clause) << ")"; } -}; - -struct DemodulatorDataContainer { - TypedTermList term; - Stack dds; - unsigned removedCnt = 0; - OrderingComparatorUP comparator; - - DemodulatorDataContainer(DemodulatorData&& dd, const Ordering& ord) : term(dd.term) { - Stack ordCons; - if (!dd.preordered) { - ordCons.push({ dd.term, dd.rhs, Ordering::GREATER }); - } - auto ptr = new DemodulatorData(std::move(dd)); - dds.push(ptr); - comparator = ord.createComparator(); - comparator->insert(ordCons, ptr); - } - - ~DemodulatorDataContainer() { - iterTraits(dds.iter()).forEach([](DemodulatorData* dd){ delete dd; }); - } - - DemodulatorDataContainer(DemodulatorDataContainer&&) = default; - - bool insert(DemodulatorDataContainer& other) { - ASS_EQ(other.dds.size(),1); - // only allow insertion if term sorts are identical to - // avoid putting variables of different sorts together - if (term!=other.term || term.sort()!=other.term.sort()) { - return false; - } - dds.loadFromIterator(other.dds.iter()); - Stack ordCons; - if (!other.dds[0]->preordered) { - ordCons.push({ other.dds[0]->term, other.dds[0]->rhs, Ordering::GREATER }); - } - comparator->insert(ordCons, other.dds[0]); - other.dds.reset(); // takes ownership - return true; - } - - bool remove(const DemodulatorDataContainer& other) { - ASS_EQ(other.dds.size(),1); - if (term!=other.term || term.sort()!=other.term.sort()) { - return false; - } - ALWAYS(iterTraits(other.dds.iter()).all([this](DemodulatorData* toRemove){ - decltype(dds)::Iterator it(dds); - unsigned removedOccs = 0; - while (it.hasNext()) { - auto curr = it.next(); - if (*curr==*toRemove) { - // TODO this is not good until we can - // actually remove the node from the tree - // - // delete curr; - // it.del(); - removedCnt++; - removedOccs++; - } - } - return removedOccs==1; - })); - return true; - } - - bool canBeDeleted() const { return removedCnt==dds.size(); } - - friend std::ostream& operator<<(std::ostream& out, DemodulatorDataContainer const& self) - { return out << *self.comparator; } + { return out << "(" << self.term << " = " << self.rhs << outputPtr(self.clause) << ")"; } }; template @@ -230,7 +153,7 @@ struct is_indexed_data_normalized { static constexpr bool value = false; }; template<> -struct is_indexed_data_normalized +struct is_indexed_data_normalized { static constexpr bool value = true; }; /** @@ -284,4 +207,4 @@ class Index }; }; -#endif /*__Indexing_Index__*/ +#endif /*__Indexing_Index__*/ \ No newline at end of file diff --git a/Indexing/IndexManager.cpp b/Indexing/IndexManager.cpp index aa4dd8f48..fea6be8e7 100644 --- a/Indexing/IndexManager.cpp +++ b/Indexing/IndexManager.cpp @@ -186,7 +186,7 @@ Index* IndexManager::create(IndexType t) break; } case DEMODULATION_LHS_CODE_TREE: - res = new DemodulationLHSIndex(new CodeTreeTIS(), _alg->getOrdering(), _alg->getOptions()); + res = new DemodulationLHSIndex(new CodeTreeTIS(), _alg->getOrdering(), _alg->getOptions()); isGenerating = false; break; diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index 76548d354..c8b5c5168 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -50,30 +50,6 @@ TermCodeTree::TermCodeTree() template void TermCodeTree::insert(Data* data) { - if (!isEmpty()) { - static RemovingTermMatcher rtm; - static Stack firstsInBlocks; - firstsInBlocks.reset(); - - FlatTerm* ft=FlatTerm::create(data->term); - rtm.init(ft, this, &firstsInBlocks); - - Data* dptr = nullptr; - for(;;) { - if (!rtm.next()) { - break; - } - ASS(rtm.op->isSuccess()); - dptr=rtm.op->template getSuccessResult(); - if (dptr->insert(*data)) { - delete data; - ft->destroy(); - return; - } - } - ft->destroy(); - } - static CodeStack code; code.reset(); @@ -115,20 +91,38 @@ void TermCodeTree::remove(const Data& data) } ASS(rtm.op->isSuccess()); dptr=rtm.op->template getSuccessResult(); - if (dptr->remove(data)) { + if (*dptr==data) { break; } } + + rtm.op->makeFail(); - if (dptr->canBeDeleted()) { - rtm.op->makeFail(); - ASS(dptr); - delete dptr; - optimizeMemoryAfterRemoval(&firstsInBlocks, rtm.op); - } - + ASS(dptr); + delete dptr; ft->destroy(); + + optimizeMemoryAfterRemoval(&firstsInBlocks, rtm.op); + /* + + static TermMatcher tm; + + tm.init(this, ti.t); + + for(;;) { + TermInfo* found=tm.next(); + if (!found) { + INVALID_OPERATION("term being removed was not found"); + } + if (*found==ti) { + tm.op->makeFail(); + delete found; + break; + } + } + tm.deinit(); + */ } // TermCodeTree::remove template @@ -196,6 +190,6 @@ Data* TermCodeTree::TermMatcher::next() } template class TermCodeTree; -template class TermCodeTree; +template class TermCodeTree; -}; +}; \ No newline at end of file diff --git a/Indexing/TermIndex.cpp b/Indexing/TermIndex.cpp index 8b0311770..1cef26e0e 100644 --- a/Indexing/TermIndex.cpp +++ b/Indexing/TermIndex.cpp @@ -141,8 +141,7 @@ void DemodulationLHSIndex::handleClause(Clause* c, bool adding) r.apply(EqHelper::getOtherEqualitySide(lit, lhs)), c, preordered, _ord ); - DemodulatorDataContainer dc(std::move(dd), _ord); - _is->handle(std::move(dc), adding); + _is->handle(std::move(dd), adding); } } diff --git a/Indexing/TermIndex.hpp b/Indexing/TermIndex.hpp index c51fb31af..6d65e0cc5 100644 --- a/Indexing/TermIndex.hpp +++ b/Indexing/TermIndex.hpp @@ -109,10 +109,10 @@ class DemodulationSubtermIndexImpl * Term index for forward demodulation */ class DemodulationLHSIndex -: public TermIndex +: public TermIndex { public: - DemodulationLHSIndex(TermIndexingStructure* is, Ordering& ord, const Options& opt) + DemodulationLHSIndex(TermIndexingStructure* is, Ordering& ord, const Options& opt) : TermIndex(is), _ord(ord), _opt(opt) {}; protected: void handleClause(Clause* c, bool adding); diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index 23fb96434..e56974b5f 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -107,9 +107,9 @@ struct BackwardDemodulation::ResultFn ASS_EQ(_cl->length(),1); _eqLit=(*_cl)[0]; _comps.first = _ordering.createComparator(); - _comps.first->insert({ { *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER } }, (void*)0x1); + _comps.first->insert({ { *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER } }); _comps.second = _ordering.createComparator(); - _comps.second->insert({ { *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER } }, (void*)0x1); + _comps.second->insert({ { *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER } }); _removed=SmartPtr(new ClauseSet()); } @@ -148,8 +148,7 @@ struct BackwardDemodulation::ResultFn TermList lhsS=qr.data->term; auto& comp = lhs==*_eqLit->nthArgument(0) ? _comps.first : _comps.second; - comp->reset(); - if (!comp->next(&appl)) { + if (!comp->check(&appl)) { #if DEBUG_ORDERING if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))==Ordering::GREATER) { INVALID_OPERATION("backward check should be greater"); diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index f7e7e6b2c..550037451 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -44,8 +44,6 @@ #include "DemodulationHelper.hpp" -#include "Shell/ConditionalRedundancyHandler.hpp" - #include "ForwardDemodulation.hpp" namespace Inferences { @@ -139,10 +137,13 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* auto git = _index->getGeneralizations(trm.term(), /* retrieveSubstitutions */ true); while(git.hasNext()) { auto qr=git.next(); + ASS_EQ(qr.data->clause->length(),1); + + if(!ColorHelper::compatible(cl->color(), qr.data->clause->color())) { + continue; + } auto lhs = qr.data->term; - auto subs = qr.unifier; - ASS(subs->isIdentityOnQueryWhenResultBound()); // TODO: // to deal with polymorphic matching @@ -155,119 +156,87 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if(lhs.isVar()){ eqSortSubs.reset(); TermList querySort = trm.sort(); - TermList eqSort = lhs.sort(); + TermList eqSort = qr.data->term.sort(); if(!eqSortSubs.match(eqSort, 0, querySort, 1)){ continue; } } + TermList rhs = qr.data->rhs; + bool preordered = qr.data->preordered; + + auto subs = qr.unifier; + ASS(subs->isIdentityOnQueryWhenResultBound()); + ApplicatorWithEqSort applWithEqSort(subs.ptr(), eqSortSubs); Applicator applWithoutEqSort(subs.ptr()); auto appl = lhs.isVar() ? (SubstApplicator*)&applWithEqSort : (SubstApplicator*)&applWithoutEqSort; - DemodulatorData* dd = nullptr; - qr.data->comparator->reset(); - while ((dd = static_cast(qr.data->comparator->next(appl)))) { - - ASS_EQ(dd->clause->length(),1); - ASS_EQ(lhs.sort(),dd->term.sort()); - if (dd->clause->store() == Clause::NONE) { - env.statistics->inductionApplication++; - continue; - } - - if(!ColorHelper::compatible(cl->color(), dd->clause->color())) { + if (_precompiledComparison) { + if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { +#if DEBUG_ORDERING + if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { + INVALID_OPERATION("greater"); + } +#endif continue; } - - AppliedTerm rhsApplied(dd->rhs,appl,true); - #if DEBUG_ORDERING - if (ordering.isGreaterOrEq(AppliedTerm(trm),rhsApplied)!=Ordering::GREATER) { - INVALID_OPERATION("forward demodulation wrong"); - } - #endif - - // encompassing demodulation is fine when rewriting the smaller guy - if (redundancyCheck && _encompassing) { - // this will only run at most once; - // could have been factored out of the getGeneralizations loop, - // but then it would run exactly once there - Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); - if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || - (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { - redundancyCheck = false; - } +#if DEBUG_ORDERING + if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER) { + INVALID_OPERATION("not greater"); } - - TermList rhsS = rhsApplied.apply(); - if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsS, lhs, appl)) { +#endif + } else { + if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER)) { continue; } + } - Literal* resLit = EqHelper::replace(lit,trm,rhsS); - if(EqHelper::isEqTautology(resLit)) { - env.statistics->forwardDemodulationsToEqTaut++; - premises = pvi( getSingletonIterator(dd->clause)); - return true; + // encompassing demodulation is fine when rewriting the smaller guy + if (redundancyCheck && _encompassing) { + // this will only run at most once; + // could have been factored out of the getGeneralizations loop, + // but then it would run exactly once there + Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); + if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || + (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { + redundancyCheck = false; } + } - RStack resLits; - resLits->push(resLit); - - for(unsigned i=0;ipush(curr); - } - } + TermList rhsS = subs->applyToBoundResult(rhs); + if (lhs.isVar()) { + rhsS = eqSortSubs.apply(rhsS, 0); + } - env.statistics->forwardDemodulations++; + if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsS, lhs, appl)) { + continue; + } - premises = pvi( getSingletonIterator(dd->clause)); - replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, dd->clause)); - if(env.options->proofExtra() == Options::ProofExtra::FULL) - env.proofExtra.insert(replacement, new ForwardDemodulationExtra(lhs, trm)); - // ConditionalRedundancyHandler::transfer(cl, replacement); + Literal* resLit = EqHelper::replace(lit,trm,rhsS); + if(EqHelper::isEqTautology(resLit)) { + env.statistics->forwardDemodulationsToEqTaut++; + premises = pvi( getSingletonIterator(qr.data->clause)); return true; } -#if DEBUG_ORDERING - for (const auto& dd : qr.data->dds) { - ASS_EQ(dd->clause->length(),1); - - if (dd->clause->store() == Clause::NONE) { - continue; - } + RStack resLits; + resLits->push(resLit); - if(!ColorHelper::compatible(cl->color(), dd->clause->color())) { - continue; - } - - AppliedTerm rhsApplied(dd->rhs,appl,true); - bool preordered = dd->preordered; - - if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),rhsApplied)!=Ordering::GREATER)) { - continue; + for(unsigned i=0;ipush(curr); } + } - // encompassing demodulation is fine when rewriting the smaller guy - if (redundancyCheck && _encompassing) { - // this will only run at most once; - // could have been factored out of the getGeneralizations loop, - // but then it would run exactly once there - Ordering::Result litOrder = ordering.getEqualityArgumentOrder(lit); - if ((trm==*lit->nthArgument(0) && litOrder == Ordering::LESS) || - (trm==*lit->nthArgument(1) && litOrder == Ordering::GREATER)) { - redundancyCheck = false; - } - } + env.statistics->forwardDemodulations++; - if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsApplied.apply(), lhs, appl)) { - continue; - } - INVALID_OPERATION("forward demodulation missed"); - } -#endif + premises = pvi( getSingletonIterator(qr.data->clause)); + replacement = Clause::fromStack(*resLits, SimplifyingInference2(InferenceRule::FORWARD_DEMODULATION, cl, qr.data->clause)); + if(env.options->proofExtra() == Options::ProofExtra::FULL) + env.proofExtra.insert(replacement, new ForwardDemodulationExtra(lhs, trm)); + return true; } } } @@ -280,4 +249,4 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* template class ForwardDemodulationImpl; template class ForwardDemodulationImpl; -} +} \ No newline at end of file diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index f303618e0..500de03f2 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -27,7 +27,7 @@ namespace Kernel { std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) { switch (t) { - case OrderingComparator::BranchTag::T_DATA: + case OrderingComparator::BranchTag::T_RESULT: out << "r"; break; case OrderingComparator::BranchTag::T_TERM: @@ -44,8 +44,8 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node { out << (OrderingComparator::BranchTag)node.tag << (node.ready?" ":"? "); switch (node.tag) { - case OrderingComparator::BranchTag::T_DATA: { - out << node.data; + case OrderingComparator::BranchTag::T_RESULT: { + out << node.result; break; } case OrderingComparator::BranchTag::T_POLY: { @@ -81,14 +81,10 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } str << *kv.first->node() << std::endl; if (seen.insert(kv.first->node())) { - if (kv.first->node()->tag==OrderingComparator::BranchTag::T_DATA) { - if (kv.first->node()->data) { - todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); - } - } else { + if (kv.first->node()->tag!=OrderingComparator::BranchTag::T_RESULT) { todo.push(std::make_pair(&kv.first->node()->ngeBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); } } } @@ -177,17 +173,16 @@ std::string OrderingComparator::to_dot() const style += "processed,"; } switch (n->tag) { - case BranchTag::T_DATA: { - auto alt = n->alternative.node(); - if (!alt) { + case BranchTag::T_RESULT: { + if (!n->result) { // do not output anything for the fail node style += "sinknode,"; label += ""; break; } style += "datanode,"; - label += Int::toString((unsigned long)n->data); - edges += getBranch(id, alt, EdgeTag::ALT); + label += Int::toString((unsigned long)n->result); + // edges += getBranch(id, alt, EdgeTag::ALT); break; } case BranchTag::T_TERM: { @@ -231,28 +226,25 @@ std::string OrderingComparator::to_dot() const } OrderingComparator::OrderingComparator(const Ordering& ord) -: _ord(ord), _source(nullptr, Branch()), _sink(_source), _curr(&_source), _prev(nullptr) +: _ord(ord), _source(false), _fail(_source), _curr(&_source), _prev(nullptr) { - _sink.node()->ready = true; + _fail.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; -void* OrderingComparator::next(const SubstApplicator* applicator) +bool OrderingComparator::check(const SubstApplicator* applicator) { + _curr = &_source; + _prev = nullptr; ASS(_curr); for (;;) { expand(); auto node = _curr->node(); ASS(node->ready); - if (node->tag == BranchTag::T_DATA) { - if (!node->data) { - return nullptr; - } - _prev = _curr; - _curr = &node->alternative; - return node->data; + if (node->tag == BranchTag::T_RESULT) { + return node->result; } Ordering::Result comp = Ordering::INCOMPARABLE; @@ -299,33 +291,33 @@ void* OrderingComparator::next(const SubstApplicator* applicator) _prev = _curr; _curr = &node->getBranch(comp); } - return nullptr; + ASSERTION_VIOLATION; } -void OrderingComparator::insert(const Stack& comps, void* result) +void OrderingComparator::insert(const Stack& ordCons) { - ASS(result); static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; // we mutate current fail node and add a new one - auto curr = &_sink; - Branch newFail(nullptr, Branch()); + // cout << "before " << *this << endl; + auto curr = &_fail; + Branch newFail(false); newFail.node()->ready = true; curr->node()->~Node(); curr->node()->ready = false; - if (comps.isNonEmpty()) { + if (ordCons.isNonEmpty()) { curr->node()->tag = T_TERM; - curr->node()->lhs = comps[0].lhs; - curr->node()->rhs = comps[0].rhs; + curr->node()->lhs = ordCons[0].lhs; + curr->node()->rhs = ordCons[0].rhs; for (unsigned i = 0; i < 3; i++) { - if (ordVals[i] != comps[0].rel) { + if (ordVals[i] != ordCons[0].rel) { curr->node()->getBranch(ordVals[i]) = newFail; } } - curr = &curr->node()->getBranch(comps[0].rel); - for (unsigned i = 1; i < comps.size(); i++) { - auto [lhs,rhs,rel] = comps[i]; + curr = &curr->node()->getBranch(ordCons[0].rel); + for (unsigned i = 1; i < ordCons.size(); i++) { + auto [lhs,rhs,rel] = ordCons[i]; *curr = OrderingComparator::Branch(lhs, rhs); for (unsigned i = 0; i < 3; i++) { if (ordVals[i] != rel) { @@ -334,14 +326,16 @@ void OrderingComparator::insert(const Stack& comps, void* } curr = &curr->node()->getBranch(rel); } - *curr = Branch(result, newFail); + *curr = Branch(true); } else { - curr->node()->tag = T_DATA; - curr->node()->data = result; - curr->node()->alternative = newFail; + curr->node()->tag = T_RESULT; + curr->node()->result = true; } + curr->node()->ready = true; - _sink = newFail; + _fail = newFail; + ASS(_fail.node()->ready); + ASS(!_fail.node()->result); } void OrderingComparator::expand() @@ -351,25 +345,16 @@ void OrderingComparator::expand() { auto node = _curr->node(); - if (node->tag == BranchTag::T_DATA) { - ASS(node->data); // no fail nodes here - // if refcnt > 1 we copy the node and - // we can also safely use the original - if (node->refcnt > 1) { - *_curr = Branch(node->data, node->alternative); - } - _curr->node()->trace = getCurrentTrace().release(); - _curr->node()->ready = true; - return; - } + ASS_NEQ(node->tag, BranchTag::T_RESULT); + if (node->tag == BranchTag::T_POLY) { // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { auto varCoeffPairs = new Stack(*node->varCoeffPairs); *_curr = Branch(node->w, varCoeffPairs); - _curr->node()->eqBranch = node->eqBranch; _curr->node()->gtBranch = node->gtBranch; + _curr->node()->eqBranch = node->eqBranch; _curr->node()->ngeBranch = node->ngeBranch; } @@ -555,7 +540,7 @@ ScopedPtr OrderingComparator::getCurrentTrace() } return ScopedPtr(trace.release()); } - case BranchTag::T_DATA: { + case BranchTag::T_RESULT: { return ScopedPtr(new Trace(*_prev->node()->trace)); } case BranchTag::T_POLY: { @@ -601,15 +586,8 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other OrderingComparator::Node::~Node() { - switch(tag) { - case T_DATA: - alternative.~Branch(); - break; - case T_TERM: - break; - case T_POLY: - delete varCoeffPairs; - break; + if (tag == T_POLY) { + delete varCoeffPairs; } ready = false; delete trace; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index c0c3a818f..3a08c5b49 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -34,10 +34,8 @@ struct OrderingComparator OrderingComparator(const Ordering& ord); virtual ~OrderingComparator(); - void reset() { _curr = &_source; _prev = nullptr; /* _trace.reset(); */ } - - void* next(const SubstApplicator* applicator); - void insert(const Stack& comps, void* result); + bool check(const SubstApplicator* applicator); + void insert(const Stack& comps); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); std::string to_dot() const; @@ -49,7 +47,7 @@ struct OrderingComparator void processPolyCase(); enum BranchTag { - T_DATA = 0u, + T_RESULT = 0u, T_TERM = 1u, T_POLY = 2u, }; @@ -69,6 +67,9 @@ struct OrderingComparator } Branch() = default; + explicit Branch(bool result) { + setNode(new Node(result)); + } template Branch(S&& s, T&& t) { setNode(new Node(std::forward(s), std::forward(t))); } @@ -99,10 +100,10 @@ struct OrderingComparator auto& getBranch(Ordering::Result r) { switch (r) { - case Ordering::EQUAL: - return eqBranch; case Ordering::GREATER: return gtBranch; + case Ordering::EQUAL: + return eqBranch; case Ordering::INCOMPARABLE: return ngeBranch; default: @@ -110,8 +111,8 @@ struct OrderingComparator } } - explicit Node(void* data, Branch alternative) - : tag(T_DATA), data(data), alternative(alternative) {} + explicit Node(bool result) + : tag(T_RESULT), result(result) {} explicit Node(TermList lhs, TermList rhs) : tag(T_TERM), lhs(lhs), rhs(rhs) {} explicit Node(uint64_t w, Stack* varCoeffPairs) @@ -128,18 +129,17 @@ struct OrderingComparator bool ready = false; union { - void* data = nullptr; + bool result; TermList lhs; int64_t w; }; union { - Branch alternative; TermList rhs; Stack* varCoeffPairs; }; - Branch eqBranch; Branch gtBranch; + Branch eqBranch; Branch ngeBranch; int refcnt = 0; Trace* trace = nullptr; @@ -147,7 +147,7 @@ struct OrderingComparator const Ordering& _ord; Branch _source; - Branch _sink; + Branch _fail; Branch* _curr; Branch* _prev; // Trace _trace; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 258c54a2b..2c52f97af 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -126,7 +126,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(entries->comparator); entries->entries.push(ptr); - entries->comparator->insert(ptr->ordCons, ptr); + entries->comparator->insert(ptr->ordCons); return true; } @@ -155,7 +155,7 @@ class ConditionalRedundancyHandler::ConstraintIndex auto es = new Entries(); es->entries.push(ptr); es->comparator = ord->createComparator(); - es->comparator->insert(ptr->ordCons, ptr); + es->comparator->insert(ptr->ordCons); code.push(CodeOp::getSuccess(es)); #if LINEARIZE @@ -196,85 +196,26 @@ class ConditionalRedundancyHandler::ConstraintIndex while ((es = matcher.next())) { ASS(es->comparator); - es->comparator->reset(); - ConditionalRedundancyEntry* e = nullptr; - while ((e = static_cast(es->comparator->next(&applicator)))) { - - if (!e->active) { - continue; - } - - // check AVATAR constraints - if (!e->splits->isSubsetOf(splits)) { - continue; - } - - // check literal conditions - auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { - return lits->member(SubstHelper::apply(lit,applicator)); - }); - if (!subsetof) { - continue; - } - + auto res = es->comparator->check(&applicator); #if DEBUG_ORDERING - auto ordCons_crosscheck = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { + auto ordCons_crosscheck = iterTraits(es->entries.iter()).any([ord,&applicator](auto e) { + return iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; }); - if (!ordCons_crosscheck) { - cout << e << endl; + }); + if (res != ordCons_crosscheck) { + cout << res << " " << ordCons_crosscheck << endl; + cout << *es->comparator << endl; + for (const auto& e : es->entries) { cout << *e << endl; - cout << *es->comparator << endl; - INVALID_OPERATION("conditional redundancy ordering check failed"); - } -#endif - - // collect statistics - // TODO fix ordering constraint stats -#if DEBUG_ORDERING - if (e->ordCons.isNonEmpty()) { - env.statistics->skippedInferencesDueToOrderingConstraints++; } + INVALID_OPERATION("conditional redundancy ordering check mismatch"); + } #endif - if (!e->lits->isEmpty()) { - env.statistics->skippedInferencesDueToLiteralConstraints++; - } - if (!e->splits->isEmpty()) { - env.statistics->skippedInferencesDueToAvatarConstraints++; - } + if (res) { matcher.reset(); return true; } -#if DEBUG_ORDERING - for (const auto& e : es->entries) { - if (!e->active) { - continue; - } - - // check AVATAR constraints - if (!e->splits->isSubsetOf(splits)) { - continue; - } - - // check literal conditions - auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { - return lits->member(SubstHelper::apply(lit,applicator)); - }); - if (!subsetof) { - continue; - } - - // check ordering constraints - auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; - }); - if (!ordCons_ok) { - continue; - } - - INVALID_OPERATION("conditional redundancy entry missed"); - } -#endif } matcher.reset(); From b6ca68520ebee2b82a58e27fe1739ce561c6fbea Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 18 Nov 2024 09:40:13 +0100 Subject: [PATCH 39/64] Add initial version of checking ground redundancy for clauses and for equation orientations; needs lot of work still --- Inferences/Superposition.cpp | 2 +- Kernel/Clause.cpp | 8 +- Kernel/Clause.hpp | 20 ++++ Kernel/OrderingComparator.cpp | 155 +++++++++++++++++++++++-- Kernel/OrderingComparator.hpp | 21 +++- Kernel/PartialOrdering.cpp | 7 +- Kernel/PartialOrdering.hpp | 6 + Saturation/SaturationAlgorithm.cpp | 6 + Shell/ConditionalRedundancyHandler.cpp | 104 ++++++++++++++++- Shell/ConditionalRedundancyHandler.hpp | 8 +- 10 files changed, 320 insertions(+), 17 deletions(-) diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index 5bf148158..0f82d47a1 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -343,7 +343,7 @@ Clause* Superposition::performSuperposition( const auto& condRedHandler = _salg->condRedHandler(); if (!unifier->usesUwa()) { - if (!condRedHandler.checkSuperposition(eqClause, eqLit, rwClause, rwLit, eqIsResult, subst.ptr())) { + if (!condRedHandler.checkSuperposition(eqClause, eqLit, eqLHS, rwClause, rwLit, eqIsResult, subst.ptr())) { return 0; } } diff --git a/Kernel/Clause.cpp b/Kernel/Clause.cpp index ff5fcbe6e..a557e7af7 100644 --- a/Kernel/Clause.cpp +++ b/Kernel/Clause.cpp @@ -78,7 +78,13 @@ Clause::Clause(Literal* const* lits, unsigned length, Inference inf) _reductionTimestamp(0), _literalPositions(0), _numActiveSplits(0), - _auxTimestamp(0) + _auxTimestamp(0), + _redundant(false), + _ltrRedundant(false), + _rtlRedundant(false), + _redundantSubs(nullptr), + _ltrRedundantSubs(nullptr), + _rtlRedundantSubs(nullptr) { // MS: TODO: not sure if this belongs here and whether EXTENSIONALITY_AXIOM input types ever appear anywhere (as a vampire-extension TPTP formula role) if(inference().inputType() == UnitInputType::EXTENSIONALITY_AXIOM){ diff --git a/Kernel/Clause.hpp b/Kernel/Clause.hpp index 07de871aa..cfaf1d180 100644 --- a/Kernel/Clause.hpp +++ b/Kernel/Clause.hpp @@ -362,6 +362,20 @@ class Clause bool computable(); + bool redundant() const { return _redundant; } + void markRedundant() { _redundant = true; } + bool ltrRedundant() const { return _ltrRedundant; } + void markLtrRedundant() { _ltrRedundant = true; } + bool rtlRedundant() const { return _rtlRedundant; } + void markRtlRedundant() { _rtlRedundant = true; } + + void* redundantSubs() const { return _redundantSubs; } + void setRedundantSubs(void* s) { _redundantSubs = s; } + void* ltrRedundantSubs() const { return _ltrRedundantSubs; } + void setLtrRedundantSubs(void* s) { _ltrRedundantSubs = s; } + void* rtlRedundantSubs() const { return _rtlRedundantSubs; } + void setRtlRedundantSubs(void* s) { _rtlRedundantSubs = s; } + protected: /** number of literals */ unsigned _length : 20; @@ -397,6 +411,12 @@ class Clause size_t _auxTimestamp; void* _auxData; + bool _redundant; + bool _ltrRedundant; + bool _rtlRedundant; + void* _redundantSubs; + void* _ltrRedundantSubs; + void* _rtlRedundantSubs; static size_t _auxCurrTimestamp; #if VDEBUG diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 500de03f2..53dbbf740 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -228,7 +228,6 @@ std::string OrderingComparator::to_dot() const OrderingComparator::OrderingComparator(const Ordering& ord) : _ord(ord), _source(false), _fail(_source), _curr(&_source), _prev(nullptr) { - _fail.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; @@ -294,14 +293,13 @@ bool OrderingComparator::check(const SubstApplicator* applicator) ASSERTION_VIOLATION; } -void OrderingComparator::insert(const Stack& ordCons) +void OrderingComparator::insert(const OrderingConstraints& ordCons) { static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; // we mutate current fail node and add a new one // cout << "before " << *this << endl; auto curr = &_fail; Branch newFail(false); - newFail.node()->ready = true; curr->node()->~Node(); curr->node()->ready = false; @@ -330,8 +328,8 @@ void OrderingComparator::insert(const Stack& ordCons) } else { curr->node()->tag = T_RESULT; curr->node()->result = true; + curr->node()->ready = true; } - curr->node()->ready = true; _fail = newFail; ASS(_fail.node()->ready); @@ -398,6 +396,15 @@ void OrderingComparator::processPolyCase() auto trace = getCurrentTrace(); + // If this happens this branch is invalid. + // Since normal execution cannot reach it, + // we can put a "success" here to make things + // easier in subsumption/simplification. + if (!trace) { + *_curr = Branch(true); + return; + } + unsigned pos = 0; unsigned neg = 0; for (unsigned i = 0; i < varCoeffPairs->size();) { @@ -448,6 +455,15 @@ void OrderingComparator::processVarCase() { auto node = _curr->node(); auto trace = getCurrentTrace(); + + // If this happens this branch is invalid. + // Since normal execution cannot reach it, + // we can put a "success" here to make things + // easier in subsumption/simplification. + if (!trace) { + *_curr = Branch(true); + return; + } Ordering::Result val; if (trace->get(node->lhs, node->rhs, val)) { if (val == Ordering::GREATER) { @@ -499,7 +515,7 @@ void OrderingComparator::processVarCase() ScopedPtr OrderingComparator::getCurrentTrace() { - ASS(!_curr->node()->ready); + // ASS(!_curr->node()->ready); if (!_prev) { return ScopedPtr(new Trace()); @@ -521,20 +537,29 @@ ScopedPtr OrderingComparator::getCurrentTrace() } else { res = Ordering::INCOMPARABLE; } - ALWAYS(trace->set({ lhs, rhs, res })); + // ALWAYS(trace->set({ lhs, rhs, res })); + if (!trace->set({ lhs, rhs, res })) { + return ScopedPtr(); + } ASS(lhs.isVar() || rhs.isVar()); if (res == Ordering::INCOMPARABLE) { if (lhs.isTerm()) { SubtermIterator stit(lhs.term()); while (stit.hasNext()) { - ALWAYS(trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })); + // ALWAYS(trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })); + if (!trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })) { + return ScopedPtr(); + } } } } else { if (rhs.isTerm()) { SubtermIterator stit(rhs.term()); while (stit.hasNext()) { - ALWAYS(trace->set({ lhs, stit.next(), Ordering::GREATER })); + // ALWAYS(trace->set({ lhs, stit.next(), Ordering::GREATER })); + if (!trace->set({ lhs, stit.next(), Ordering::GREATER })) { + return ScopedPtr(); + } } } } @@ -550,6 +575,120 @@ ScopedPtr OrderingComparator::getCurrentTrace() ASSERTION_VIOLATION; } +OrderingComparator::Subsumption::Subsumption(OrderingComparator& subsumer, const Ordering& ord, const OrderingConstraints& ordCons, bool ground) + : subsumer(subsumer), subsumed(ord.createComparator()), path({ &subsumer._source }), ground(ground) +{ + subsumed->insert(ordCons); +} + +bool OrderingComparator::Subsumption::check() +{ + while (path.isNonEmpty()) { + if (path.size()==1) { + subsumer._prev = nullptr; + } else { + subsumer._prev = path[path.size()-2]; + } + subsumer._curr = path.top(); + subsumer.expand(); + + switch (subsumer._curr->node()->tag) { + case BranchTag::T_POLY: + case BranchTag::T_TERM: { + path.push(&subsumer._curr->node()->gtBranch); + break; + } + case BranchTag::T_RESULT: { + if (!checkLeaf()) { + return false; + } + // find next node to check + while (path.isNonEmpty()) { + auto prev = path.size()==1 ? nullptr : path[path.size()-2]->node(); + auto curr = path.pop(); + ASS(!prev || prev->tag == BranchTag::T_POLY || prev->tag == BranchTag::T_TERM); + + if (prev) { + // if there is a previous node and we were either in the gt or eq + // branches, just go to next branch in order, otherwise backtrack + if (curr == &prev->gtBranch) { + path.push(&prev->eqBranch); + break; + } + if (curr == &prev->eqBranch) { + path.push(&prev->ngeBranch); + break; + } + } + } + break; + } + } + } + + ASS(path.isEmpty()); + return true; +} + +bool OrderingComparator::Subsumption::checkLeaf() +{ + if (subsumer._curr->node()->result) { + return true; + } + + auto trace = subsumer.getCurrentTrace(); + if (!trace) { + return true; + } + if (ground && trace->hasIncomp()) { + return true; + } + Stack> todo; + todo.push({ nullptr, &subsumed->_source }); + while (todo.isNonEmpty()) { + auto [prev, curr] = todo.pop(); + subsumed->_prev = prev; + subsumed->_curr = curr; + subsumed->expand(); + + switch (subsumed->_curr->node()->tag) { + case BranchTag::T_POLY: { + return false; + } + case BranchTag::T_RESULT: { + if (subsumed->_curr->node()->result) { + return false; + } + break; + } + case BranchTag::T_TERM: { + auto lhs = subsumed->_curr->node()->lhs; + auto rhs = subsumed->_curr->node()->rhs; + Ordering::Result val; + if (!trace->get(lhs, rhs, val)) { + return false; + } + switch (val) { + case Ordering::GREATER: { + todo.push({ subsumed->_curr, &subsumed->_curr->node()->gtBranch }); + break; + } + case Ordering::EQUAL: { + todo.push({ subsumed->_curr, &subsumed->_curr->node()->eqBranch }); + break; + } + default: { + todo.push({ subsumed->_curr, &subsumed->_curr->node()->ngeBranch }); + break; + } + } + break; + } + } + } + return true; +} + OrderingComparator::Branch::~Branch() { setNode(nullptr); diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 3a08c5b49..0499dcca5 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -22,6 +22,8 @@ namespace Kernel { +using OrderingConstraints = Stack; + /** * Class implementing runtime specialized ordering check between two terms. * The comparator is created and called from inside the respective ordering @@ -30,16 +32,32 @@ namespace Kernel { */ struct OrderingComparator { +protected: + struct Branch; public: OrderingComparator(const Ordering& ord); virtual ~OrderingComparator(); bool check(const SubstApplicator* applicator); - void insert(const Stack& comps); + void insert(const OrderingConstraints& comps); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); std::string to_dot() const; + class Subsumption { + public: + Subsumption(OrderingComparator& subsumer, const Ordering& ord, const OrderingConstraints& comps, bool ground); + bool check(); + + private: + bool checkLeaf(); + + OrderingComparator& subsumer; + OrderingComparatorUP subsumed; + Stack path; + bool ground; + }; + protected: void expand(); virtual void expandTermCase(); @@ -69,6 +87,7 @@ struct OrderingComparator Branch() = default; explicit Branch(bool result) { setNode(new Node(result)); + _node->ready = true; } template Branch(S&& s, T&& t) { setNode(new Node(std::forward(s), std::forward(t))); diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 46102ba7a..82820a0d9 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -96,10 +96,10 @@ PoComp resultToPoComp(Result r, bool reversed) { } PartialOrdering::PartialOrdering() - : _nodes(), _size(0), _array(nullptr) {} + : _nodes(), _size(0), _array(nullptr), _hasIncomp(false) {} PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _nodes(other._nodes), _size(_nodes.size()), _array(nullptr) + : _nodes(other._nodes), _size(_nodes.size()), _array(nullptr), _hasIncomp(other._hasIncomp) { size_t arrSize = ((_size - 1) * _size / 2); if (arrSize) { @@ -274,6 +274,9 @@ bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) return false; } _array[idx] = new_v; + if (new_v == PoComp::INCOMPARABLE) { + _hasIncomp = true; + } return true; } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 0e02dccbe..93de2baaa 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -44,10 +44,15 @@ class PartialOrdering PartialOrdering(); PartialOrdering(const PartialOrdering& other); ~PartialOrdering(); + PartialOrdering& operator=(const PartialOrdering& other) = delete; bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; bool set(Ordering::Constraint con); + // Returns if PO contains full incomparaibility yet. + // Useful to discard branches when reasoning over ground terms. + bool hasIncomp() const { return _hasIncomp; } + std::string to_string() const; private: @@ -66,6 +71,7 @@ class PartialOrdering Map _nodes; size_t _size; PoComp* _array; + bool _hasIncomp; }; }; diff --git a/Saturation/SaturationAlgorithm.cpp b/Saturation/SaturationAlgorithm.cpp index 2033e33c2..21fd9a521 100644 --- a/Saturation/SaturationAlgorithm.cpp +++ b/Saturation/SaturationAlgorithm.cpp @@ -1281,6 +1281,12 @@ void SaturationAlgorithm::doOneAlgorithmStep() throw MainLoopFinishedException(res); } + auto acl = _active->clauses(); + while (acl.hasNext()) { + auto cl = acl.next(); + _conditionalRedundancyHandler->checkSubsumption(cl); + } + Clause* cl = nullptr; { TIME_TRACE(TimeTrace::PASSIVE_CONTAINER_MAINTENANCE); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 2c52f97af..ce4fd5a99 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -114,7 +114,6 @@ class ConditionalRedundancyHandler::ConstraintIndex return true; } -private: #if VDEBUG Clause* _cl; #endif @@ -421,13 +420,26 @@ DHMap Condition template bool ConditionalRedundancyHandlerImpl::checkSuperposition( - Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, + Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const { if constexpr (!enabled) { return true; } + if (eqClause->redundant() || rwClause->redundant()) { + env.statistics->skippedSuperposition++; + return false; + } + if (eqClause->ltrRedundant() && eqLHS == eqLit->termArg(0)) { + env.statistics->skippedSuperposition++; + return false; + } + if (eqClause->rtlRedundant() && eqLHS == eqLit->termArg(1)) { + env.statistics->skippedSuperposition++; + return false; + } + auto rwLits = LiteralSet::getEmpty(); if constexpr (litC) { rwLits = LiteralSet::getFromIterator(rwClause->iterLits().filter([rwLit](Literal* lit) { @@ -756,4 +768,92 @@ void ConditionalRedundancyHandlerImpl::checkEquati }); } +template +void ConditionalRedundancyHandlerImpl::checkSubsumption(Clause* cl) const +{ + if (!enabled) { + return; + } + + auto clDataPtr = getDataPtr(cl, /*doAllocate=*/false); + if (!clDataPtr) { + return; + } + + if (cl->redundant()) { + return; + } + + struct Applicator : public SubstApplicator { + TermList operator()(unsigned v) const override { return TermList::var(v); } + } appl; + + auto ts = (*clDataPtr)->getInstances(appl); + if ((*clDataPtr)->isEmpty()) { + return; + } + + static ConstraintIndex::SubstMatcher matcher; + matcher.init((*clDataPtr), ts); + Entries* es = matcher.next(); + matcher.reset(); + // there can be only one such matching currently + if (!es) { + return; + } + ASS(es->comparator); + auto subs = static_cast(cl->redundantSubs()); + if (!subs) { + subs = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); + cl->setRedundantSubs(subs); + } + // cout << "checking redundancy of " << *cl << endl; + if (subs->check()) { + cl->markRedundant(); + env.statistics->generalizedInductionApplication++; + if (cl->ltrRedundant() || cl->rtlRedundant()) { + // cout << "became fully redundant " << *cl << endl; + } + return; + } + if (_ord->compare((*cl)[0]->termArg(0),(*cl)[0]->termArg(1))!=Ordering::INCOMPARABLE) { + return; + } + + auto subsLtr = static_cast(cl->ltrRedundantSubs()); + auto subsRtl = static_cast(cl->rtlRedundantSubs()); + if (!subsLtr || !subsRtl) { + Renaming r; + for (const auto t : ts) { + r.normalizeVariables(t); + } + auto lhs = r.apply((*cl)[0]->termArg(0)); + auto rhs = r.apply((*cl)[0]->termArg(1)); + if (!subsLtr) { + subsLtr = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, { { lhs, rhs, Ordering::GREATER } }, /*ground=*/true); + cl->setLtrRedundantSubs(subsLtr); + } + if (!subsRtl) { + subsRtl = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, { { rhs, lhs, Ordering::GREATER } }, /*ground=*/true); + cl->setRtlRedundantSubs(subsRtl); + } + } + if (!cl->ltrRedundant()) { + // cout << "checking redundancy of " << (*cl)[0]->termArg(0) << " -> " << (*cl)[0]->termArg(1) << endl; + if (subsLtr->check()) { + env.statistics->generalizedInductionApplicationInProof++; + // cout << "redundant " << (*cl)[0]->termArg(0) << " -> " << (*cl)[0]->termArg(1) << endl; + cl->markLtrRedundant(); + } + } + if (!cl->rtlRedundant()) { + // cout << "checking redundancy of " << (*cl)[0]->termArg(1) << " -> " << (*cl)[0]->termArg(0) << endl; + if (subsRtl->check()) { + env.statistics->generalizedInductionApplicationInProof++; + // cout << "redundant " << (*cl)[0]->termArg(1) << " -> " << (*cl)[0]->termArg(0) << endl; + cl->markRtlRedundant(); + } + } +} + } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 0033e378e..3b8f9e9c0 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -100,7 +100,7 @@ class ConditionalRedundancyHandler virtual ~ConditionalRedundancyHandler() = default; virtual bool checkSuperposition( - Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const = 0; + Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const = 0; virtual bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, @@ -115,6 +115,8 @@ class ConditionalRedundancyHandler virtual void checkEquations(Clause* cl) const = 0; + virtual void checkSubsumption(Clause* cl) const = 0; + static void transfer(Clause* from, Clause* to); protected: @@ -138,7 +140,7 @@ class ConditionalRedundancyHandlerImpl /** Returns false if superposition should be skipped. */ bool checkSuperposition( - Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const override; + Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const override; bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, @@ -159,6 +161,8 @@ class ConditionalRedundancyHandlerImpl void checkEquations(Clause* cl) const override; + void checkSubsumption(Clause* cl) const override; + private: bool _redundancyCheck; bool _encompassing; From 18c5088197afba4f02c07cb7892181efe3d5a68a Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 19 Nov 2024 17:23:58 +0100 Subject: [PATCH 40/64] Clean up things around checking ground redundancy a bit --- Kernel/Clause.cpp | 8 +- Kernel/Clause.hpp | 20 ---- Shell/ConditionalRedundancyHandler.cpp | 129 ++++++++++++------------- Shell/Statistics.cpp | 5 + Shell/Statistics.hpp | 2 + 5 files changed, 72 insertions(+), 92 deletions(-) diff --git a/Kernel/Clause.cpp b/Kernel/Clause.cpp index a557e7af7..ff5fcbe6e 100644 --- a/Kernel/Clause.cpp +++ b/Kernel/Clause.cpp @@ -78,13 +78,7 @@ Clause::Clause(Literal* const* lits, unsigned length, Inference inf) _reductionTimestamp(0), _literalPositions(0), _numActiveSplits(0), - _auxTimestamp(0), - _redundant(false), - _ltrRedundant(false), - _rtlRedundant(false), - _redundantSubs(nullptr), - _ltrRedundantSubs(nullptr), - _rtlRedundantSubs(nullptr) + _auxTimestamp(0) { // MS: TODO: not sure if this belongs here and whether EXTENSIONALITY_AXIOM input types ever appear anywhere (as a vampire-extension TPTP formula role) if(inference().inputType() == UnitInputType::EXTENSIONALITY_AXIOM){ diff --git a/Kernel/Clause.hpp b/Kernel/Clause.hpp index cfaf1d180..07de871aa 100644 --- a/Kernel/Clause.hpp +++ b/Kernel/Clause.hpp @@ -362,20 +362,6 @@ class Clause bool computable(); - bool redundant() const { return _redundant; } - void markRedundant() { _redundant = true; } - bool ltrRedundant() const { return _ltrRedundant; } - void markLtrRedundant() { _ltrRedundant = true; } - bool rtlRedundant() const { return _rtlRedundant; } - void markRtlRedundant() { _rtlRedundant = true; } - - void* redundantSubs() const { return _redundantSubs; } - void setRedundantSubs(void* s) { _redundantSubs = s; } - void* ltrRedundantSubs() const { return _ltrRedundantSubs; } - void setLtrRedundantSubs(void* s) { _ltrRedundantSubs = s; } - void* rtlRedundantSubs() const { return _rtlRedundantSubs; } - void setRtlRedundantSubs(void* s) { _rtlRedundantSubs = s; } - protected: /** number of literals */ unsigned _length : 20; @@ -411,12 +397,6 @@ class Clause size_t _auxTimestamp; void* _auxData; - bool _redundant; - bool _ltrRedundant; - bool _rtlRedundant; - void* _redundantSubs; - void* _ltrRedundantSubs; - void* _rtlRedundantSubs; static size_t _auxCurrTimestamp; #if VDEBUG diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index ce4fd5a99..8dc44a3f1 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -25,6 +25,8 @@ using namespace std; using namespace Indexing; +using Subsumption = OrderingComparator::Subsumption; + namespace Shell { @@ -77,6 +79,10 @@ class ConditionalRedundancyHandler::ConstraintIndex #endif for (unsigned i = 0; i < cl->length(); i++) { SortHelper::collectVariableSorts((*cl)[i], _varSorts); + if (i < cl->numSelected()) { + _litSubs.push({ nullptr, nullptr }); + _litRedundant.push({ false, false }); + } } } @@ -234,6 +240,10 @@ class ConditionalRedundancyHandler::ConstraintIndex } DHMap _varSorts; + Subsumption* _subs = nullptr; + bool _redundant = false; + Stack> _litSubs; + Stack> _litRedundant; ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const { @@ -427,15 +437,25 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp return true; } - if (eqClause->redundant() || rwClause->redundant()) { - env.statistics->skippedSuperposition++; - return false; - } - if (eqClause->ltrRedundant() && eqLHS == eqLit->termArg(0)) { - env.statistics->skippedSuperposition++; - return false; + auto eqClDataPtr = getDataPtr(eqClause, /*doAllocate=*/false); + if (eqClDataPtr) { + if ((*eqClDataPtr)->_redundant) { + env.statistics->skippedSuperposition++; + return false; + } + auto i = eqClause->getLiteralPosition(eqLit); + if (eqLHS == eqLit->termArg(0) && (*eqClDataPtr)->_litRedundant[i].first) { + env.statistics->skippedSuperposition++; + return false; + } + if (eqLHS == eqLit->termArg(1) && (*eqClDataPtr)->_litRedundant[i].second) { + env.statistics->skippedSuperposition++; + return false; + } } - if (eqClause->rtlRedundant() && eqLHS == eqLit->termArg(1)) { + + auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); + if (rwClDataPtr && (*rwClDataPtr)->_redundant) { env.statistics->skippedSuperposition++; return false; } @@ -454,7 +474,6 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp rwSplits = rwClause->splits(); } - auto eqClDataPtr = getDataPtr(eqClause, /*doAllocate=*/false); if (eqClDataPtr && !(*eqClDataPtr)->check(_ord, subs, eqIsResult, OrderingConstraints(), rwLits, rwSplits)) { env.statistics->skippedSuperposition++; return false; @@ -474,7 +493,6 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp eqSplits = eqClause->splits(); } - auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); if (rwClDataPtr && !(*rwClDataPtr)->check(_ord, subs, !eqIsResult, OrderingConstraints(), eqLits, eqSplits)) { env.statistics->skippedSuperposition++; return false; @@ -779,79 +797,60 @@ void ConditionalRedundancyHandlerImpl::checkSubsum if (!clDataPtr) { return; } + auto cld = *clDataPtr; - if (cl->redundant()) { - return; - } - - struct Applicator : public SubstApplicator { - TermList operator()(unsigned v) const override { return TermList::var(v); } - } appl; - - auto ts = (*clDataPtr)->getInstances(appl); - if ((*clDataPtr)->isEmpty()) { + if (cld->_redundant || cld->isEmpty()) { return; } + auto ts = cld->getInstances([](unsigned v) { return TermList::var(v); }); static ConstraintIndex::SubstMatcher matcher; matcher.init((*clDataPtr), ts); Entries* es = matcher.next(); matcher.reset(); - // there can be only one such matching currently + // there can be only one such matching under linearization +#if !LINEARIZE + static_assert(false); +#endif if (!es) { return; } ASS(es->comparator); - auto subs = static_cast(cl->redundantSubs()); - if (!subs) { - subs = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); - cl->setRedundantSubs(subs); - } - // cout << "checking redundancy of " << *cl << endl; - if (subs->check()) { - cl->markRedundant(); - env.statistics->generalizedInductionApplication++; - if (cl->ltrRedundant() || cl->rtlRedundant()) { - // cout << "became fully redundant " << *cl << endl; - } - return; + if (!cld->_subs) { + cld->_subs = new Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); } - if (_ord->compare((*cl)[0]->termArg(0),(*cl)[0]->termArg(1))!=Ordering::INCOMPARABLE) { + if (cld->_subs->check()) { + cld->_redundant = true; + env.statistics->groundRedundantClauses++; return; } - auto subsLtr = static_cast(cl->ltrRedundantSubs()); - auto subsRtl = static_cast(cl->rtlRedundantSubs()); - if (!subsLtr || !subsRtl) { - Renaming r; - for (const auto t : ts) { - r.normalizeVariables(t); + for (unsigned i = 0; i < cl->numSelected(); i++) { + auto lit = (*cl)[i]; + if (!lit->isEquality() || _ord->getEqualityArgumentOrder(lit)!=Ordering::INCOMPARABLE) { + continue; } - auto lhs = r.apply((*cl)[0]->termArg(0)); - auto rhs = r.apply((*cl)[0]->termArg(1)); + + auto& [subsLtr, subsRtl] = cld->_litSubs[i]; + auto& [redLtr, redRtl] = cld->_litRedundant[i]; if (!subsLtr) { - subsLtr = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, { { lhs, rhs, Ordering::GREATER } }, /*ground=*/true); - cl->setLtrRedundantSubs(subsLtr); - } - if (!subsRtl) { - subsRtl = new OrderingComparator::Subsumption(*es->comparator.get(), *_ord, { { rhs, lhs, Ordering::GREATER } }, /*ground=*/true); - cl->setRtlRedundantSubs(subsRtl); - } - } - if (!cl->ltrRedundant()) { - // cout << "checking redundancy of " << (*cl)[0]->termArg(0) << " -> " << (*cl)[0]->termArg(1) << endl; - if (subsLtr->check()) { - env.statistics->generalizedInductionApplicationInProof++; - // cout << "redundant " << (*cl)[0]->termArg(0) << " -> " << (*cl)[0]->termArg(1) << endl; - cl->markLtrRedundant(); - } - } - if (!cl->rtlRedundant()) { - // cout << "checking redundancy of " << (*cl)[0]->termArg(1) << " -> " << (*cl)[0]->termArg(0) << endl; - if (subsRtl->check()) { - env.statistics->generalizedInductionApplicationInProof++; - // cout << "redundant " << (*cl)[0]->termArg(1) << " -> " << (*cl)[0]->termArg(0) << endl; - cl->markRtlRedundant(); + ASS(!subsRtl); + Renaming r; + for (const auto t : ts) { + r.normalizeVariables(t); + } + auto lhs = r.apply(lit->termArg(0)); + auto rhs = r.apply(lit->termArg(1)); + subsLtr = new Subsumption(*es->comparator.get(), *_ord, { { lhs, rhs, Ordering::GREATER } }, /*ground=*/true); + subsRtl = new Subsumption(*es->comparator.get(), *_ord, { { rhs, lhs, Ordering::GREATER } }, /*ground=*/true); + } + if (!redLtr && subsLtr->check()) { + redLtr = true; + env.statistics->groundRedundantEquationOrientations++; + } + if (!redRtl && subsRtl->check()) { + redRtl = true; + env.statistics->groundRedundantEquationOrientations++; } } } diff --git a/Shell/Statistics.cpp b/Shell/Statistics.cpp index ebc53761f..a1a148a88 100644 --- a/Shell/Statistics.cpp +++ b/Shell/Statistics.cpp @@ -130,6 +130,8 @@ Statistics::Statistics() condensations(0), globalSubsumption(0), interpretedSimplifications(0), + groundRedundantClauses(0), + groundRedundantEquationOrientations(0), asgViolations(0), asgCnt(0), @@ -310,6 +312,7 @@ void Statistics::print(ostream& out) +( evaluationCnt - evaluationIncomp - evaluationGreater) +innerRewrites +booleanSimps + +groundRedundantClauses+groundRedundantEquationOrientations ); COND_OUT("Duplicate literals", duplicateLiterals); COND_OUT("Trivial inequalities", trivialInequalities); @@ -324,6 +327,8 @@ void Statistics::print(ostream& out) COND_OUT("Condensations", condensations); COND_OUT("Global subsumptions", globalSubsumption); COND_OUT("Interpreted simplifications", interpretedSimplifications); + COND_OUT("Ground redundant clauses", groundRedundantClauses); + COND_OUT("Ground redundant eq. orientations", groundRedundantEquationOrientations); COND_OUT("asg count", asgCnt); COND_OUT("asg results not smaller than the premis", asgViolations); diff --git a/Shell/Statistics.hpp b/Shell/Statistics.hpp index 1530748f2..429bac706 100644 --- a/Shell/Statistics.hpp +++ b/Shell/Statistics.hpp @@ -192,6 +192,8 @@ class Statistics { unsigned globalSubsumption; /** number of interpreted simplifications */ unsigned interpretedSimplifications; + unsigned groundRedundantClauses; + unsigned groundRedundantEquationOrientations; /** how often did asg not simplify correctly. */ unsigned asgViolations; From 19ab19b4892db9ae48006beb5d651b83d812dc10 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 19 Nov 2024 18:48:11 +0100 Subject: [PATCH 41/64] Fail in partial ordering when finding an inconsistency in the inferred loop --- Kernel/PartialOrdering.cpp | 89 +++++++++++++++++++++----------------- Kernel/PartialOrdering.hpp | 8 ++-- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 82820a0d9..5ea1efb24 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -19,6 +19,13 @@ #include "Lib/Stack.hpp" #include "Lib/Metaiterators.hpp" +#define RETURN_IF_FAIL(Cond) \ + { \ + if (!(Cond)) { \ + return false; \ + } \ + } + namespace Kernel { using namespace std; @@ -223,14 +230,14 @@ bool PartialOrdering::set(Ordering::Constraint con) } PoComp old_val = idx_of(x, y); PoComp new_val = resultToPoComp(con.rel, reversed); - if (set_idx_of(x, y, new_val)) { - // if something's changed, we calculate the transitive closure - if (new_val != old_val) { - set_inferred(x, y, new_val); - } - return true; + + RETURN_IF_FAIL(set_idx_of(x, y, new_val)); + + // if something's changed, we calculate the transitive closure + if (new_val != old_val) { + RETURN_IF_FAIL(set_inferred(x, y, new_val)); } - return false; + return true; } size_t PartialOrdering::idx_of_elem(TermList t) const @@ -305,7 +312,7 @@ PoComp PartialOrdering::idx_of_safe(size_t x, size_t y) const } } -void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) +bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) { ASS_NEQ(x,y); @@ -322,14 +329,14 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // if rel = ≤: z ≤ x ∧ x ≤ y → z ≤ y // if rel = ≥: z ≥ x ∧ x ≥ y → z ≥ y if (r == rel || r == PoComp::EQUAL) { - ALWAYS(set_idx_of_safe(z, y, rel)); + RETURN_IF_FAIL(set_idx_of_safe(z, y, rel)); above.push(z); continue; } // if rel = ≤: z ≱ x ∧ x ≤ y → z ≱ y // if rel = ≥: z ≰ x ∧ x ≥ y → z ≰ y if (r == wkn || r == PoComp::INCOMPARABLE) { - ALWAYS(set_idx_of_safe(z, y, wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn)); above_w.push(z); continue; } @@ -337,14 +344,14 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // x rel y ∧ y rel z → x rel z // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { - ALWAYS(set_idx_of_safe(x, z, rel)); + RETURN_IF_FAIL(set_idx_of_safe(x, z, rel)); below.push(z); continue; } // x rel y ∧ y wkn z → x wkn z // x rel y ∧ y inc z → x wkn z if (r == wkn || r == PoComp::INCOMPARABLE) { - ALWAYS(set_idx_of_safe(x, z, wkn)); + RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn)); below_w.push(z); continue; } @@ -353,20 +360,21 @@ void PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - ALWAYS(set_idx_of_safe(z,u,rel)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,rel)); } for (const auto& u : below_w) { - ALWAYS(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); } } for (const auto& z : above_w) { for (const auto& u : below) { - ALWAYS(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); } } + return true; } -void PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) +bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) { ASS_NEQ(x,y); @@ -381,14 +389,14 @@ void PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) auto r = idx_of_safe(z, x); // z ≤ x ∧ x ≱ y → z ≱ y if (r == rel || r == PoComp::EQUAL) { - ALWAYS(set_idx_of_safe(z, y, wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn)); above.push(z); continue; } r = idx_of_safe(y, z); // x ≱ y ∧ y ≤ z → x ≱ z if (r == rel || r == PoComp::EQUAL) { - ALWAYS(set_idx_of_safe(x, z, wkn)); + RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn)); below.push(z); continue; } @@ -397,12 +405,13 @@ void PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - ALWAYS(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); } } + return true; } -void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) +bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) { ASS_NEQ(x,y); @@ -417,19 +426,19 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) } auto r = idx_of_safe(z, x); if (r != PoComp::UNKNOWN) { - ALWAYS(set_idx_of_safe(z, y, r)); + RETURN_IF_FAIL(set_idx_of_safe(z, y, r)); x_rel.push({ z, r }); continue; } r = idx_of_safe(y, z); if (r != PoComp::UNKNOWN) { - ALWAYS(set_idx_of_safe(x, z, r)); + RETURN_IF_FAIL(set_idx_of_safe(x, z, r)); y_rel.push({ z, r }); } } if (y_rel.isEmpty()) { - return; + return true; } // we assume x = y @@ -438,7 +447,7 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) case PoComp::EQUAL: { for (const auto& [u,ru] : y_rel) { // z = x ∧ x ru u → z ru u - ALWAYS(set_idx_of_safe(z, u, ru)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, ru)); } break; } @@ -448,12 +457,12 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z > x ∧ x ≥ u → z > u case PoComp::EQUAL: case PoComp::GREATER: - ALWAYS(set_idx_of_safe(z, u, PoComp::GREATER)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::GREATER)); break; // z > x ∧ x ≰ u → z ≰ u case PoComp::NLEQ: case PoComp::INCOMPARABLE: - ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); break; // z > x ∧ x < u implies nothing case PoComp::LESS: @@ -472,12 +481,12 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z < x ∧ x ≤ u → z < u case PoComp::EQUAL: case PoComp::LESS: - ALWAYS(set_idx_of_safe(z, u, PoComp::LESS)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::LESS)); break; // z < x ∧ x ≱ u → z ≱ u case PoComp::NGEQ: case PoComp::INCOMPARABLE: - ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); break; // z < x ∧ x > u implies nothing case PoComp::GREATER: @@ -495,15 +504,15 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) switch (ru) { // z ≰ x ∧ x > u → z ≰ u case PoComp::GREATER: - ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); break; // z ⋈ x ∧ x = u → z ⋈ u case PoComp::EQUAL: - ALWAYS(set_idx_of_safe(z, u, PoComp::INCOMPARABLE)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::INCOMPARABLE)); break; // z ≱ x ∧ x < u → z ≱ u case PoComp::LESS: - ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); break; // z ⋈ x ∧ x ≱ u implies nothing case PoComp::NGEQ: @@ -524,7 +533,7 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≱ x ∧ x ≤ u → z ≱ u case PoComp::EQUAL: case PoComp::LESS: - ALWAYS(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); break; // z ≱ x ∧ x > u implies nothing case PoComp::GREATER: @@ -547,7 +556,7 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≰ x ∧ x ≥ u → z ≰ u case PoComp::GREATER: case PoComp::EQUAL: - ALWAYS(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); break; // z ≰ x ∧ x < u implies nothing case PoComp::LESS: @@ -568,9 +577,10 @@ void PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) ASSERTION_VIOLATION; } } + return true; } -void PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) +bool PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) { switch (result) { /* x > y: then ∀z. y ≥ z, also x > z, @@ -579,7 +589,7 @@ void PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) /* x < y: then ∀z. y ≤ z, also x < z, and ∀z. z ≤ x, also z < y */ case PoComp::LESS: - set_inferred_loop(x, y, result); + RETURN_IF_FAIL(set_inferred_loop(x, y, result)); break; /* x = y: then ∀z. z = x, also z = y and ∀z. z = y, also z = x @@ -588,19 +598,20 @@ void PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) and ∀z. z < x, also z < y and ∀z. z < y, also z < x */ case PoComp::EQUAL: - set_inferred_loop_eq(x, y); + RETURN_IF_FAIL(set_inferred_loop_eq(x, y)); break; case PoComp::NGEQ: case PoComp::NLEQ: - set_inferred_loop_inc(x, y, result); + RETURN_IF_FAIL(set_inferred_loop_inc(x, y, result)); break; case PoComp::INCOMPARABLE: - set_inferred_loop_inc(x, y, PoComp::NGEQ); - set_inferred_loop_inc(x, y, PoComp::NLEQ); + RETURN_IF_FAIL(set_inferred_loop_inc(x, y, PoComp::NGEQ)); + RETURN_IF_FAIL(set_inferred_loop_inc(x, y, PoComp::NLEQ)); break; default: break; } + return true; } string idx_to_string(PoComp c) { diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 93de2baaa..ac7d1a060 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -63,10 +63,10 @@ class PartialOrdering bool set_idx_of(size_t x, size_t y, PoComp v); bool set_idx_of_safe(size_t x, size_t y, PoComp v); - void set_inferred(size_t x, size_t y, PoComp result); - void set_inferred_loop(size_t x, size_t y, PoComp rel); - void set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); - void set_inferred_loop_eq(size_t x, size_t y); + bool set_inferred(size_t x, size_t y, PoComp result); + bool set_inferred_loop(size_t x, size_t y, PoComp rel); + bool set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); + bool set_inferred_loop_eq(size_t x, size_t y); Map _nodes; size_t _size; From 9e84254c2ea247bf487c0935114519928201d70c Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 21 Nov 2024 20:17:18 +0100 Subject: [PATCH 42/64] Move things around a bit in partial ordering so that we can detect transitivity better --- Kernel/OrderingComparator.cpp | 52 +--- Kernel/PartialOrdering.cpp | 442 +++++++++++++++++++++++++++++----- Kernel/PartialOrdering.hpp | 24 +- 3 files changed, 405 insertions(+), 113 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 53dbbf740..23ad0dfe9 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -475,32 +475,6 @@ void OrderingComparator::processVarCase() } return; } - // TODO eventually incorporate this into the Trace - if (node->rhs.isTerm()) { - SubtermIterator sti(node->rhs.term()); - while (sti.hasNext()) { - auto st = sti.next(); - if (trace->get(node->lhs, st, val)) { - if (val == Ordering::INCOMPARABLE || val == Ordering::LESS) { - *_curr = node->ngeBranch; - return; - } - } - } - } - if (node->lhs.isTerm()) { - SubtermIterator sti(node->lhs.term()); - while (sti.hasNext()) { - auto st = sti.next(); - if (trace->get(st, node->rhs, val)) { - // node->lhs > st ≥ node->rhs → node->lhs > node->rhs - if (val == Ordering::GREATER || val == Ordering::EQUAL) { - *_curr = node->gtBranch; - return; - } - } - } - } // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { @@ -515,10 +489,10 @@ void OrderingComparator::processVarCase() ScopedPtr OrderingComparator::getCurrentTrace() { - // ASS(!_curr->node()->ready); + ASS(!_curr->node()->ready || _curr->node() == _fail.node()); if (!_prev) { - return ScopedPtr(new Trace()); + return ScopedPtr(new Trace(_ord)); } ASS(_prev->node()->ready); @@ -541,28 +515,6 @@ ScopedPtr OrderingComparator::getCurrentTrace() if (!trace->set({ lhs, rhs, res })) { return ScopedPtr(); } - ASS(lhs.isVar() || rhs.isVar()); - if (res == Ordering::INCOMPARABLE) { - if (lhs.isTerm()) { - SubtermIterator stit(lhs.term()); - while (stit.hasNext()) { - // ALWAYS(trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })); - if (!trace->set({ stit.next(), rhs, Ordering::INCOMPARABLE })) { - return ScopedPtr(); - } - } - } - } else { - if (rhs.isTerm()) { - SubtermIterator stit(rhs.term()); - while (stit.hasNext()) { - // ALWAYS(trace->set({ lhs, stit.next(), Ordering::GREATER })); - if (!trace->set({ lhs, stit.next(), Ordering::GREATER })) { - return ScopedPtr(); - } - } - } - } return ScopedPtr(trace.release()); } case BranchTag::T_RESULT: { diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 5ea1efb24..ecac7764d 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -102,11 +102,11 @@ PoComp resultToPoComp(Result r, bool reversed) { } } -PartialOrdering::PartialOrdering() - : _nodes(), _size(0), _array(nullptr), _hasIncomp(false) {} +PartialOrdering::PartialOrdering(const Ordering& ord) + : _ord(ord), _nodes(), _size(0), _array(nullptr), _hasIncomp(false), _prev(nullptr) {} PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _nodes(other._nodes), _size(_nodes.size()), _array(nullptr), _hasIncomp(other._hasIncomp) + : _ord(other._ord), _nodes(other._nodes), _size(_nodes.size()), _array(nullptr), _hasIncomp(other._hasIncomp), _prev(&other) { size_t arrSize = ((_size - 1) * _size / 2); if (arrSize) { @@ -125,22 +125,187 @@ PartialOrdering::~PartialOrdering() } } +PoComp PartialOrdering::get_one_external(TermList t, size_t idx) const +{ + PoComp res = PoComp::UNKNOWN; + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + if (e.value()==idx) { + continue; + } + auto val = idx_of_safe(e.value(),idx); + if (val == PoComp::UNKNOWN) { + continue; + } + auto comp = _ord.compare(t,e.key()); + switch (comp) { + case Ordering::GREATER: { + switch (val) { + case PoComp::EQUAL: + case PoComp::GREATER: + // t > e ≥ x -> t > x + ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); + case PoComp::NLEQ: + case PoComp::INCOMPARABLE: + // t > e ≰ x -> t ≰ x + ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); + default: + break; + } + break; + } + case Ordering::EQUAL: { + return val; + } + case Ordering::LESS: { + switch (val) { + case PoComp::EQUAL: + case PoComp::LESS: + // t < e ≤ x -> t < x + ALWAYS(checkCompatibility(res, PoComp::LESS, res)); + case PoComp::NGEQ: + case PoComp::INCOMPARABLE: + // t < e ≱ x -> t ≱ x + ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); + default: + break; + } + break; + } + case Ordering::INCOMPARABLE: { + break; + } + } + } + return res; +} + +PoComp PartialOrdering::get_two_external(TermList t1, TermList t2) const +{ + PoComp res = PoComp::UNKNOWN; + Stack> t1_rel; // ∃x. t1 rel x + Stack> t2_rel; // ∃x. x rel t2 + + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + auto comp1 = _ord.compare(t1,e.key()); + if (comp1 != Ordering::INCOMPARABLE) { + t1_rel.push({ e.value(), comp1 }); + } + auto comp2 = _ord.compare(e.key(),t2); + if (comp2 != Ordering::INCOMPARABLE) { + t2_rel.push({ e.value(), comp2 }); + } + } + for (const auto& [e1,r1] : t1_rel) { + for (const auto& [e2,r2] : t2_rel) { + auto r = e1 == e2 ? PoComp::EQUAL : idx_of_safe(e1,e2); + switch (r) { + case PoComp::UNKNOWN: + break; + case PoComp::EQUAL: { + switch (r1) { + case Ordering::GREATER: { + if (r2 != Ordering::LESS) { + // t1 > e1 = e2 ≥ t2 -> t1 > t2 + ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); + } + break; + } + case Ordering::EQUAL: { + // t1 = e1 = e2 r2 t2 -> t1 r2 t2 + ALWAYS(checkCompatibility(res, resultToPoComp(r2, false), res)); + break; + } + case Ordering::LESS: { + if (r2 != Ordering::GREATER) { + // t1 < e1 = e2 ≤ t2 -> t1 < t2 + ALWAYS(checkCompatibility(res, PoComp::LESS, res)); + } + break; + } + case Ordering::INCOMPARABLE: + ASSERTION_VIOLATION; + } + break; + } + case PoComp::GREATER: + case PoComp::NLEQ: { + if (r1 != Ordering::LESS && r2 != Ordering::LESS) { + // t1 ≥ e1 > e2 ≥ t2 -> t1 > t2 + // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 + ALWAYS(checkCompatibility(res, r, res)); + } + break; + } + case PoComp::LESS: + case PoComp::NGEQ: { + if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { + // t1 ≤ e1 < e2 ≤ t2 -> t1 < t2 + // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 + ALWAYS(checkCompatibility(res, r, res)); + } + break; + } + case PoComp::INCOMPARABLE: { + if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { + // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 + ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); + } + if (r1 != Ordering::LESS && r2 != Ordering::LESS) { + // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 + ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); + } + break; + } + } + } + } + return res; +} + bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const { + // comparable terms should be handled by caller + ASS_EQ(_ord.compare(lhs,rhs),Ordering::INCOMPARABLE); + // proper term pairs should be handled by caller + ASS(lhs.isVar() || rhs.isVar()); + if (lhs == rhs) { res = Result::EQUAL; return true; } - if (!_nodes.find(lhs) || !_nodes.find(rhs)) { - return false; - } - size_t x = idx_of_elem(lhs); - size_t y = idx_of_elem(rhs); - bool reversed = x > y; - if (reversed) { - swap(x,y); + PoComp val; + bool reversed = false; + if (!_nodes.find(lhs) && !_nodes.find(rhs)) + { + val = get_two_external(lhs, rhs); + } + else if (!_nodes.find(lhs)) + { + ASS(_nodes.find(rhs)); + size_t y = idx_of_elem(rhs); + val = get_one_external(lhs, y); + } + else if (!_nodes.find(rhs)) + { + ASS(_nodes.find(lhs)); + size_t x = idx_of_elem(lhs); + val = get_one_external(rhs, x); + reversed = true; + } + else + { + size_t x = idx_of_elem(lhs); + size_t y = idx_of_elem(rhs); + reversed = x > y; + if (reversed) { + swap(x,y); + } + val = idx_of(x,y); } - PoComp val = idx_of(x,y); if (val == PoComp::UNKNOWN) { return false; } @@ -228,15 +393,18 @@ bool PartialOrdering::set(Ordering::Constraint con) if (reversed) { swap(x,y); } - PoComp old_val = idx_of(x, y); PoComp new_val = resultToPoComp(con.rel, reversed); - RETURN_IF_FAIL(set_idx_of(x, y, new_val)); + bool changed; + RETURN_IF_FAIL(set_idx_of(x, y, new_val, changed)); // if something's changed, we calculate the transitive closure - if (new_val != old_val) { + if (changed) { RETURN_IF_FAIL(set_inferred(x, y, new_val)); } +#if DEBUG_ORDERING + // debug_check(); +#endif return true; } @@ -268,18 +436,38 @@ size_t PartialOrdering::idx_of_elem_ext(TermList t) array_delete(prevArray, prevSize); DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); } + + // fill out new row with known values + size_t idx = _size-1; + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + if (e.value()==idx) { + continue; + } + auto comp = _ord.compare(e.key(),t); + if (comp == Ordering::INCOMPARABLE) { + continue; + } + auto val = resultToPoComp(comp, false); + bool unused; + ALWAYS(set_idx_of(e.value(), idx, val, unused)); + ALWAYS(set_inferred(e.value(), idx, val)); + } } return *ptr; } -bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) +bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v, bool& changed) { size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); PoComp new_v; if (!checkCompatibility(_array[idx], v, new_v)) { + changed = false; return false; } + changed = (_array[idx] != new_v); _array[idx] = new_v; if (new_v == PoComp::INCOMPARABLE) { _hasIncomp = true; @@ -287,12 +475,12 @@ bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v) return true; } -bool PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v) +bool PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed) { if (x < y) { - return set_idx_of(x,y,v); + return set_idx_of(x,y,v,changed); } else { - return set_idx_of(y,x,reverse(v)); + return set_idx_of(y,x,reverse(v),changed); } } @@ -321,6 +509,8 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) Stack below; Stack below_w; auto wkn = weaken(rel); // weakened variant of rel + bool changed; + for (size_t z = 0; z < _size; z++) { if (z == x || z == y) { continue; @@ -329,46 +519,55 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // if rel = ≤: z ≤ x ∧ x ≤ y → z ≤ y // if rel = ≥: z ≥ x ∧ x ≥ y → z ≥ y if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, rel)); - above.push(z); - continue; + RETURN_IF_FAIL(set_idx_of_safe(z, y, rel, changed)); + if (changed) { + above.push(z); + // TODO find out why we should continue here + // continue; + } } // if rel = ≤: z ≱ x ∧ x ≤ y → z ≱ y // if rel = ≥: z ≰ x ∧ x ≥ y → z ≰ y - if (r == wkn || r == PoComp::INCOMPARABLE) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn)); - above_w.push(z); - continue; + else if (r == wkn || r == PoComp::INCOMPARABLE) { + RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn, changed)); + if (changed) { + above_w.push(z); + // TODO find out why we should continue here + // continue; + } } + r = idx_of_safe(y, z); // x rel y ∧ y rel z → x rel z // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, rel)); - below.push(z); - continue; + RETURN_IF_FAIL(set_idx_of_safe(x, z, rel, changed)); + if (changed) { + below.push(z); + } } // x rel y ∧ y wkn z → x wkn z // x rel y ∧ y inc z → x wkn z - if (r == wkn || r == PoComp::INCOMPARABLE) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn)); - below_w.push(z); - continue; + else if (r == wkn || r == PoComp::INCOMPARABLE) { + RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn, changed)); + if (changed) { + below_w.push(z); + } } } // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,rel)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,rel,changed)); } for (const auto& u : below_w) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); } } for (const auto& z : above_w) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); } } return true; @@ -381,6 +580,7 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) Stack above; Stack below; auto rel = strengthen(wkn); // stronger variant of wkn + bool changed; for (size_t z = 0; z < _size; z++) { if (z == x || z == y) { @@ -388,24 +588,30 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) } auto r = idx_of_safe(z, x); // z ≤ x ∧ x ≱ y → z ≱ y + // z ≥ x ∧ x ≰ y → z ≰ y if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn)); - above.push(z); - continue; + RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn, changed)); + if (changed) { + above.push(z); + // TODO find out why we should continue here + // continue; + } } r = idx_of_safe(y, z); // x ≱ y ∧ y ≤ z → x ≱ z + // x ≰ y ∧ y ≥ z → x ≰ z if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn)); - below.push(z); - continue; + RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn, changed)); + if (changed) { + below.push(z); + } } } // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn)); + RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); } } return true; @@ -419,6 +625,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) Stack> x_rel; // pairs (z, rel) s.t. y rel z Stack> y_rel; + bool changed; for (size_t z = 0; z < _size; z++) { if (z == x || z == y) { @@ -426,14 +633,19 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) } auto r = idx_of_safe(z, x); if (r != PoComp::UNKNOWN) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, r)); - x_rel.push({ z, r }); - continue; + RETURN_IF_FAIL(set_idx_of_safe(z, y, r, changed)); + if (changed) { + x_rel.push({ z, r }); + // TODO find out why we should continue here + // continue; + } } r = idx_of_safe(y, z); if (r != PoComp::UNKNOWN) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, r)); - y_rel.push({ z, r }); + RETURN_IF_FAIL(set_idx_of_safe(x, z, r, changed)); + if (changed) { + y_rel.push({ z, r }); + } } } @@ -447,7 +659,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) case PoComp::EQUAL: { for (const auto& [u,ru] : y_rel) { // z = x ∧ x ru u → z ru u - RETURN_IF_FAIL(set_idx_of_safe(z, u, ru)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, ru, changed)); } break; } @@ -457,12 +669,12 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z > x ∧ x ≥ u → z > u case PoComp::EQUAL: case PoComp::GREATER: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::GREATER)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::GREATER, changed)); break; // z > x ∧ x ≰ u → z ≰ u case PoComp::NLEQ: case PoComp::INCOMPARABLE: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); break; // z > x ∧ x < u implies nothing case PoComp::LESS: @@ -481,12 +693,12 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z < x ∧ x ≤ u → z < u case PoComp::EQUAL: case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::LESS)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::LESS, changed)); break; // z < x ∧ x ≱ u → z ≱ u case PoComp::NGEQ: case PoComp::INCOMPARABLE: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); break; // z < x ∧ x > u implies nothing case PoComp::GREATER: @@ -504,15 +716,15 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) switch (ru) { // z ≰ x ∧ x > u → z ≰ u case PoComp::GREATER: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); break; // z ⋈ x ∧ x = u → z ⋈ u case PoComp::EQUAL: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::INCOMPARABLE)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::INCOMPARABLE, changed)); break; // z ≱ x ∧ x < u → z ≱ u case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); break; // z ⋈ x ∧ x ≱ u implies nothing case PoComp::NGEQ: @@ -533,7 +745,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≱ x ∧ x ≤ u → z ≱ u case PoComp::EQUAL: case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); break; // z ≱ x ∧ x > u implies nothing case PoComp::GREATER: @@ -556,7 +768,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≰ x ∧ x ≥ u → z ≰ u case PoComp::GREATER: case PoComp::EQUAL: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ)); + RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); break; // z ≰ x ∧ x < u implies nothing case PoComp::LESS: @@ -689,4 +901,118 @@ string PartialOrdering::to_string() const return str.str(); } +string PartialOrdering::all_to_string() const +{ + stringstream res; + auto curr = this; + while (curr) { + res << curr << " " << curr->_array << endl; + res << curr->to_string() << endl; + curr = curr->_prev; + } + return res.str(); +} + +#if DEBUG_ORDERING +void PartialOrdering::debug_check() const +{ + auto output_args = [this](size_t x, size_t y, size_t z) { + return all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); + }; + + auto check_val = [&output_args](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { + if (actual_val == PoComp::UNKNOWN) { + INVALID_OPERATION(output_args(x,y,z)); + } + if (expected_val == PoComp::NLEQ) { + if (actual_val != PoComp::NLEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::GREATER) { + INVALID_OPERATION(output_args(x,y,z)); + } + } else if (expected_val == PoComp::NGEQ) { + if (actual_val != PoComp::NGEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::LESS) { + INVALID_OPERATION(output_args(x,y,z)); + } + } else { + if (actual_val != expected_val) { + INVALID_OPERATION(output_args(x,y,z)); + } + } + }; + + decltype(_nodes)::Iterator it1(_nodes); + while (it1.hasNext()) { + auto& e1 = it1.next(); + + decltype(_nodes)::Iterator it2(_nodes); + while (it2.hasNext()) { + auto& e2 = it2.next(); + if (e1.value() == e2.value()) { + continue; + } + auto v12 = idx_of_safe(e1.value(),e2.value()); + if (v12 == PoComp::UNKNOWN) { + continue; + } + auto comp = _ord.compare(e1.key(),e2.key()); + if (comp != Ordering::INCOMPARABLE) { + check_val(v12, resultToPoComp(comp, false), e1.value(), e2.value(), e2.value()); + } + + decltype(_nodes)::Iterator it3(_nodes); + while (it3.hasNext()) { + auto& e3 = it3.next(); + if (e1.value() == e3.value() || e2.value() == e3.value()) { + continue; + } + + auto v13 = idx_of_safe(e1.value(),e3.value()); + if (v13 == PoComp::UNKNOWN) { + continue; + } + + auto v23 = idx_of_safe(e2.value(),e3.value()); + + switch (v12) { + case PoComp::UNKNOWN: + break; + case PoComp::EQUAL: + // x = y rel z -> x rel z + check_val(v13, v23, e1.value(), e2.value(), e3.value()); + break; + case PoComp::GREATER: + case PoComp::NLEQ: { + if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { + // x > y ≥ z -> x > z + // x ≰ y ≥ z -> x ≰ z + check_val(v13, v12, e1.value(), e2.value(), e3.value()); + } + break; + } + case PoComp::LESS: + case PoComp::NGEQ: { + if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { + // x < y ≤ z -> x < z + // x ≱ y ≤ z -> x ≱ z + check_val(v13, v12, e1.value(), e2.value(), e3.value()); + } + break; + } + case PoComp::INCOMPARABLE: { + if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { + // x ≰ y ≥ z -> x ≰ z + check_val(v13, PoComp::NLEQ, e1.value(), e2.value(), e3.value()); + } + if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { + // x ≱ y ≤ z -> x ≱ z + check_val(v13, PoComp::NGEQ, e1.value(), e2.value(), e3.value()); + } + break; + } + } + } + } + } +} +#endif + } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index ac7d1a060..56e9a0e19 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -38,40 +38,54 @@ enum class PoComp : uint8_t { INCOMPARABLE, }; +std::string idx_to_string(PoComp c); +std::string idx_to_infix(PoComp c); +bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); + class PartialOrdering { public: - PartialOrdering(); + PartialOrdering(const Ordering& ord); PartialOrdering(const PartialOrdering& other); ~PartialOrdering(); - PartialOrdering& operator=(const PartialOrdering& other) = delete; + PartialOrdering& operator=(const PartialOrdering&) = delete; bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; bool set(Ordering::Constraint con); - // Returns if PO contains full incomparaibility yet. + // Returns if PO contains full incomparability yet. // Useful to discard branches when reasoning over ground terms. bool hasIncomp() const { return _hasIncomp; } std::string to_string() const; + std::string all_to_string() const; private: size_t idx_of_elem(TermList t) const; size_t idx_of_elem_ext(TermList t); PoComp idx_of(size_t x, size_t y) const; PoComp idx_of_safe(size_t x, size_t y) const; - bool set_idx_of(size_t x, size_t y, PoComp v); - bool set_idx_of_safe(size_t x, size_t y, PoComp v); + bool set_idx_of(size_t x, size_t y, PoComp v, bool& changed); + bool set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed); bool set_inferred(size_t x, size_t y, PoComp result); bool set_inferred_loop(size_t x, size_t y, PoComp rel); bool set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); bool set_inferred_loop_eq(size_t x, size_t y); + PoComp get_one_external(TermList t, size_t idx) const; + PoComp get_two_external(TermList t1, TermList t2) const; + +#if DEBUG_ORDERING + void debug_check() const; +#endif + + const Ordering& _ord; Map _nodes; size_t _size; PoComp* _array; bool _hasIncomp; + const PartialOrdering* _prev; }; }; From 9e24eda0bbfd7628c4244560b517d1a8be049760 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 22 Nov 2024 15:57:32 +0100 Subject: [PATCH 43/64] Move parts independent of terms to a cleaner partial ordering class --- CMakeLists.txt | 2 + Forwards.hpp | 1 + Kernel/OrderingComparator.hpp | 4 +- Kernel/PartialOrdering.cpp | 586 ++++++--------------------------- Kernel/PartialOrdering.hpp | 34 +- Kernel/TermPartialOrdering.cpp | 426 ++++++++++++++++++++++++ Kernel/TermPartialOrdering.hpp | 63 ++++ 7 files changed, 606 insertions(+), 510 deletions(-) create mode 100644 Kernel/TermPartialOrdering.cpp create mode 100644 Kernel/TermPartialOrdering.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0a85d5ef..68bfdd358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,6 +235,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/Substitution.cpp Kernel/Term.cpp Kernel/TermIterators.cpp + Kernel/TermPartialOrdering.cpp Kernel/TermTransformer.cpp Kernel/Theory.cpp Kernel/Signature.cpp @@ -285,6 +286,7 @@ set(VAMPIRE_KERNEL_SOURCES Kernel/Substitution.hpp Kernel/Term.hpp Kernel/TermIterators.hpp + Kernel/TermPartialOrdering.hpp Kernel/TermTransformer.hpp Kernel/Theory.hpp Kernel/Signature.hpp diff --git a/Forwards.hpp b/Forwards.hpp index 34662f6c1..72c7737e8 100644 --- a/Forwards.hpp +++ b/Forwards.hpp @@ -105,6 +105,7 @@ class Ordering; typedef Lib::SmartPtr OrderingSP; struct OrderingComparator; typedef std::unique_ptr OrderingComparatorUP; +class PartialOrdering; typedef unsigned SplitLevel; typedef const SharedSet SplitSet; diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 0499dcca5..6e737f8a9 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -16,7 +16,7 @@ #include "Forwards.hpp" -#include "PartialOrdering.hpp" +#include "TermPartialOrdering.hpp" #include "Ordering.hpp" @@ -107,7 +107,7 @@ struct OrderingComparator using VarCoeffPair = std::pair; - using Trace = PartialOrdering; + using Trace = TermPartialOrdering; ScopedPtr getCurrentTrace(); diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index ecac7764d..644367089 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -71,262 +71,6 @@ constexpr PoComp strengthen(PoComp v) { } } -Result poCompToResult(PoComp c) { - switch (c) { - case PoComp::GREATER: - return Result::GREATER; - case PoComp::EQUAL: - return Result::EQUAL; - case PoComp::LESS: - return Result::LESS; - case PoComp::NGEQ: - case PoComp::NLEQ: - case PoComp::INCOMPARABLE: - return Result::INCOMPARABLE; - default: - break; - } - ASSERTION_VIOLATION; -} - -PoComp resultToPoComp(Result r, bool reversed) { - switch (r) { - case Result::GREATER: - return reversed ? PoComp::LESS : PoComp::GREATER; - case Result::EQUAL: - return PoComp::EQUAL; - case Result::LESS: - return reversed ? PoComp::GREATER : PoComp::LESS; - case Result::INCOMPARABLE: - return reversed ? PoComp::NLEQ : PoComp::NGEQ; - } -} - -PartialOrdering::PartialOrdering(const Ordering& ord) - : _ord(ord), _nodes(), _size(0), _array(nullptr), _hasIncomp(false), _prev(nullptr) {} - -PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _ord(other._ord), _nodes(other._nodes), _size(_nodes.size()), _array(nullptr), _hasIncomp(other._hasIncomp), _prev(&other) -{ - size_t arrSize = ((_size - 1) * _size / 2); - if (arrSize) { - void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); - _array = array_new(mem, arrSize); - memcpy(_array,other._array,arrSize*sizeof(PoComp)); - } -} - -PartialOrdering::~PartialOrdering() -{ - size_t arrSize = ((_size - 1) * _size / 2); - if (arrSize) { - array_delete(_array, arrSize); - DEALLOC_KNOWN(_array, arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); - } -} - -PoComp PartialOrdering::get_one_external(TermList t, size_t idx) const -{ - PoComp res = PoComp::UNKNOWN; - decltype(_nodes)::Iterator it(_nodes); - while (it.hasNext()) { - auto& e = it.next(); - if (e.value()==idx) { - continue; - } - auto val = idx_of_safe(e.value(),idx); - if (val == PoComp::UNKNOWN) { - continue; - } - auto comp = _ord.compare(t,e.key()); - switch (comp) { - case Ordering::GREATER: { - switch (val) { - case PoComp::EQUAL: - case PoComp::GREATER: - // t > e ≥ x -> t > x - ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); - case PoComp::NLEQ: - case PoComp::INCOMPARABLE: - // t > e ≰ x -> t ≰ x - ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); - default: - break; - } - break; - } - case Ordering::EQUAL: { - return val; - } - case Ordering::LESS: { - switch (val) { - case PoComp::EQUAL: - case PoComp::LESS: - // t < e ≤ x -> t < x - ALWAYS(checkCompatibility(res, PoComp::LESS, res)); - case PoComp::NGEQ: - case PoComp::INCOMPARABLE: - // t < e ≱ x -> t ≱ x - ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); - default: - break; - } - break; - } - case Ordering::INCOMPARABLE: { - break; - } - } - } - return res; -} - -PoComp PartialOrdering::get_two_external(TermList t1, TermList t2) const -{ - PoComp res = PoComp::UNKNOWN; - Stack> t1_rel; // ∃x. t1 rel x - Stack> t2_rel; // ∃x. x rel t2 - - decltype(_nodes)::Iterator it(_nodes); - while (it.hasNext()) { - auto& e = it.next(); - auto comp1 = _ord.compare(t1,e.key()); - if (comp1 != Ordering::INCOMPARABLE) { - t1_rel.push({ e.value(), comp1 }); - } - auto comp2 = _ord.compare(e.key(),t2); - if (comp2 != Ordering::INCOMPARABLE) { - t2_rel.push({ e.value(), comp2 }); - } - } - for (const auto& [e1,r1] : t1_rel) { - for (const auto& [e2,r2] : t2_rel) { - auto r = e1 == e2 ? PoComp::EQUAL : idx_of_safe(e1,e2); - switch (r) { - case PoComp::UNKNOWN: - break; - case PoComp::EQUAL: { - switch (r1) { - case Ordering::GREATER: { - if (r2 != Ordering::LESS) { - // t1 > e1 = e2 ≥ t2 -> t1 > t2 - ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); - } - break; - } - case Ordering::EQUAL: { - // t1 = e1 = e2 r2 t2 -> t1 r2 t2 - ALWAYS(checkCompatibility(res, resultToPoComp(r2, false), res)); - break; - } - case Ordering::LESS: { - if (r2 != Ordering::GREATER) { - // t1 < e1 = e2 ≤ t2 -> t1 < t2 - ALWAYS(checkCompatibility(res, PoComp::LESS, res)); - } - break; - } - case Ordering::INCOMPARABLE: - ASSERTION_VIOLATION; - } - break; - } - case PoComp::GREATER: - case PoComp::NLEQ: { - if (r1 != Ordering::LESS && r2 != Ordering::LESS) { - // t1 ≥ e1 > e2 ≥ t2 -> t1 > t2 - // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 - ALWAYS(checkCompatibility(res, r, res)); - } - break; - } - case PoComp::LESS: - case PoComp::NGEQ: { - if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { - // t1 ≤ e1 < e2 ≤ t2 -> t1 < t2 - // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 - ALWAYS(checkCompatibility(res, r, res)); - } - break; - } - case PoComp::INCOMPARABLE: { - if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { - // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 - ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); - } - if (r1 != Ordering::LESS && r2 != Ordering::LESS) { - // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 - ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); - } - break; - } - } - } - } - return res; -} - -bool PartialOrdering::get(TermList lhs, TermList rhs, Result& res) const -{ - // comparable terms should be handled by caller - ASS_EQ(_ord.compare(lhs,rhs),Ordering::INCOMPARABLE); - // proper term pairs should be handled by caller - ASS(lhs.isVar() || rhs.isVar()); - - if (lhs == rhs) { - res = Result::EQUAL; - return true; - } - PoComp val; - bool reversed = false; - if (!_nodes.find(lhs) && !_nodes.find(rhs)) - { - val = get_two_external(lhs, rhs); - } - else if (!_nodes.find(lhs)) - { - ASS(_nodes.find(rhs)); - size_t y = idx_of_elem(rhs); - val = get_one_external(lhs, y); - } - else if (!_nodes.find(rhs)) - { - ASS(_nodes.find(lhs)); - size_t x = idx_of_elem(lhs); - val = get_one_external(rhs, x); - reversed = true; - } - else - { - size_t x = idx_of_elem(lhs); - size_t y = idx_of_elem(rhs); - reversed = x > y; - if (reversed) { - swap(x,y); - } - val = idx_of(x,y); - } - if (val == PoComp::UNKNOWN) { - return false; - } - // if we only have INCOMPARABLE in the "other direction" - // as we use isGreater which never gives LESS, we cannot - // distinguish between the two LESS and INCOMPARABLE - if (reversed) { - if (val == PoComp::NGEQ) { - return false; - } - res = Ordering::reverse(poCompToResult(val)); - return true; - } else { - if (val == PoComp::NLEQ) { - return false; - } - res = poCompToResult(val); - return true; - } -} - bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) { if (old == PoComp::UNKNOWN) { @@ -380,82 +124,120 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) ASSERTION_VIOLATION; } -bool PartialOrdering::set(Ordering::Constraint con) +string idx_to_string(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + return "UNKNOWN"; + case PoComp::GREATER: + return "GREATER"; + case PoComp::EQUAL: + return "EQUAL"; + case PoComp::LESS: + return "LESS"; + case PoComp::NGEQ: + return "NGEQ"; + case PoComp::NLEQ: + return "NLEQ"; + case PoComp::INCOMPARABLE: + return "INCOMPARABLE"; + } +} + +string idx_to_infix(PoComp c) { + switch (c) { + case PoComp::UNKNOWN: + return "?"; + case PoComp::GREATER: + return ">"; + case PoComp::EQUAL: + return "="; + case PoComp::LESS: + return "<"; + case PoComp::NGEQ: + return "≱"; + case PoComp::NLEQ: + return "≰"; + case PoComp::INCOMPARABLE: + return "⋈"; + } +} + +PartialOrdering::PartialOrdering() + : _size(0), _array(nullptr), _hasIncomp(false), _prev(nullptr) {} + +PartialOrdering::PartialOrdering(const PartialOrdering& other) + : _size(other._size), _array(nullptr), _hasIncomp(other._hasIncomp), _prev(&other) +{ + size_t arrSize = ((_size - 1) * _size / 2); + if (arrSize) { + void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); + _array = array_new(mem, arrSize); + memcpy(_array,other._array,arrSize*sizeof(PoComp)); + } +} + +PartialOrdering::~PartialOrdering() +{ + size_t arrSize = ((_size - 1) * _size / 2); + if (arrSize) { + array_delete(_array, arrSize); + DEALLOC_KNOWN(_array, arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); + } +} + +PoComp PartialOrdering::get(size_t x, size_t y) const +{ + ASS_L(x,_size); + ASS_L(y,_size); + + return (x < y) ? get_unsafe(x,y) : reverse(get_unsafe(y,x)); +} + +bool PartialOrdering::set(size_t x, size_t y, PoComp v) { - ASS_EQ(_size,_nodes.size()); - if (con.lhs == con.rhs) { - return true; // TODO should we check anything here? + ASS_L(x,_size); + ASS_L(y,_size); + + if (x == y) { + return true; } - size_t x = idx_of_elem_ext(con.lhs); - size_t y = idx_of_elem_ext(con.rhs); + // TODO remove this reverse thing bool reversed = x > y; if (reversed) { swap(x,y); } - PoComp new_val = resultToPoComp(con.rel, reversed); - bool changed; - RETURN_IF_FAIL(set_idx_of(x, y, new_val, changed)); + RETURN_IF_FAIL(set_idx_of(x, y, v, changed)); // if something's changed, we calculate the transitive closure if (changed) { - RETURN_IF_FAIL(set_inferred(x, y, new_val)); + // TODO we could use the value that we get from compatibility checking here + RETURN_IF_FAIL(set_inferred(x, y, v)); } -#if DEBUG_ORDERING - // debug_check(); -#endif return true; } -size_t PartialOrdering::idx_of_elem(TermList t) const -{ - ASS(_nodes.find(t)); - return _nodes.get(t); -} - -size_t PartialOrdering::idx_of_elem_ext(TermList t) +void PartialOrdering::extend() { - size_t *ptr; - if (_nodes.getValuePtr(t, ptr, _size)) { - // extend array - size_t prevSize = ((_size - 1) * _size / 2); - auto prevArray = _array; - _size++; - if (_size>1) { - size_t newSize = prevSize + _size; - void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); - _array = array_new(mem, newSize); - std::memset(_array, 0, newSize*sizeof(PoComp)); - if (prevArray) { - memcpy(_array,prevArray,prevSize*sizeof(PoComp)); - } - } - // remove previous array - if (prevSize) { - array_delete(prevArray, prevSize); - DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); - } - - // fill out new row with known values - size_t idx = _size-1; - decltype(_nodes)::Iterator it(_nodes); - while (it.hasNext()) { - auto& e = it.next(); - if (e.value()==idx) { - continue; - } - auto comp = _ord.compare(e.key(),t); - if (comp == Ordering::INCOMPARABLE) { - continue; - } - auto val = resultToPoComp(comp, false); - bool unused; - ALWAYS(set_idx_of(e.value(), idx, val, unused)); - ALWAYS(set_inferred(e.value(), idx, val)); - } + // extend array + size_t prevSize = ((_size - 1) * _size / 2); + auto prevArray = _array; + _size++; + if (_size>1) { + size_t newSize = prevSize + _size; + void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); + _array = array_new(mem, newSize); + std::memset(_array, 0, newSize*sizeof(PoComp)); + if (prevArray) { + memcpy(_array,prevArray,prevSize*sizeof(PoComp)); + } + } + // remove previous array + if (prevSize) { + array_delete(prevArray, prevSize); + DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); } - return *ptr; } bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v, bool& changed) @@ -484,22 +266,13 @@ bool PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v, bool& change } } -PoComp PartialOrdering::idx_of(size_t x, size_t y) const +PoComp PartialOrdering::get_unsafe(size_t x, size_t y) const { size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); return _array[idx]; } -PoComp PartialOrdering::idx_of_safe(size_t x, size_t y) const -{ - if (x < y) { - return idx_of(x,y); - } else { - return reverse(idx_of(y,x)); - } -} - bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) { ASS_NEQ(x,y); @@ -515,7 +288,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) if (z == x || z == y) { continue; } - auto r = idx_of_safe(z, x); + auto r = get(z, x); // if rel = ≤: z ≤ x ∧ x ≤ y → z ≤ y // if rel = ≥: z ≥ x ∧ x ≥ y → z ≥ y if (r == rel || r == PoComp::EQUAL) { @@ -537,7 +310,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) } } - r = idx_of_safe(y, z); + r = get(y, z); // x rel y ∧ y rel z → x rel z // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { @@ -586,7 +359,7 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) if (z == x || z == y) { continue; } - auto r = idx_of_safe(z, x); + auto r = get(z, x); // z ≤ x ∧ x ≱ y → z ≱ y // z ≥ x ∧ x ≰ y → z ≰ y if (r == rel || r == PoComp::EQUAL) { @@ -597,7 +370,7 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) // continue; } } - r = idx_of_safe(y, z); + r = get(y, z); // x ≱ y ∧ y ≤ z → x ≱ z // x ≰ y ∧ y ≥ z → x ≰ z if (r == rel || r == PoComp::EQUAL) { @@ -631,7 +404,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) if (z == x || z == y) { continue; } - auto r = idx_of_safe(z, x); + auto r = get(z, x); if (r != PoComp::UNKNOWN) { RETURN_IF_FAIL(set_idx_of_safe(z, y, r, changed)); if (changed) { @@ -640,7 +413,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // continue; } } - r = idx_of_safe(y, z); + r = get(y, z); if (r != PoComp::UNKNOWN) { RETURN_IF_FAIL(set_idx_of_safe(x, z, r, changed)); if (changed) { @@ -826,57 +599,12 @@ bool PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) return true; } -string idx_to_string(PoComp c) { - switch (c) { - case PoComp::UNKNOWN: - return "UNKNOWN"; - case PoComp::GREATER: - return "GREATER"; - case PoComp::EQUAL: - return "EQUAL"; - case PoComp::LESS: - return "LESS"; - case PoComp::NGEQ: - return "NGEQ"; - case PoComp::NLEQ: - return "NLEQ"; - case PoComp::INCOMPARABLE: - return "INCOMPARABLE"; - } -} - -string idx_to_infix(PoComp c) { - switch (c) { - case PoComp::UNKNOWN: - return "?"; - case PoComp::GREATER: - return ">"; - case PoComp::EQUAL: - return "="; - case PoComp::LESS: - return "<"; - case PoComp::NGEQ: - return "≱"; - case PoComp::NLEQ: - return "≰"; - case PoComp::INCOMPARABLE: - return "⋈"; - } -} - string PartialOrdering::to_string() const { - if (_nodes.size()<2) { + if (_size == 0) { return " {} "; } stringstream str; - typename Map::Iterator it(_nodes); - while (it.hasNext()) { - const auto& e = it.next(); - str << e.value() << ": " << e.key() << ", "; - } - str << endl; - size_t s = _size-1; size_t w = 0; while (s) { s /= 10; w++; } @@ -887,7 +615,7 @@ string PartialOrdering::to_string() const if (w>1) { str << std::setw(w-1) << " "; } - str << idx_to_infix(idx_of(j,i)) << " "; + str << idx_to_infix(get_unsafe(j,i)) << " "; } if (w>1) { str << std::setw(w-1) << " "; @@ -913,106 +641,4 @@ string PartialOrdering::all_to_string() const return res.str(); } -#if DEBUG_ORDERING -void PartialOrdering::debug_check() const -{ - auto output_args = [this](size_t x, size_t y, size_t z) { - return all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); - }; - - auto check_val = [&output_args](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { - if (actual_val == PoComp::UNKNOWN) { - INVALID_OPERATION(output_args(x,y,z)); - } - if (expected_val == PoComp::NLEQ) { - if (actual_val != PoComp::NLEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::GREATER) { - INVALID_OPERATION(output_args(x,y,z)); - } - } else if (expected_val == PoComp::NGEQ) { - if (actual_val != PoComp::NGEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::LESS) { - INVALID_OPERATION(output_args(x,y,z)); - } - } else { - if (actual_val != expected_val) { - INVALID_OPERATION(output_args(x,y,z)); - } - } - }; - - decltype(_nodes)::Iterator it1(_nodes); - while (it1.hasNext()) { - auto& e1 = it1.next(); - - decltype(_nodes)::Iterator it2(_nodes); - while (it2.hasNext()) { - auto& e2 = it2.next(); - if (e1.value() == e2.value()) { - continue; - } - auto v12 = idx_of_safe(e1.value(),e2.value()); - if (v12 == PoComp::UNKNOWN) { - continue; - } - auto comp = _ord.compare(e1.key(),e2.key()); - if (comp != Ordering::INCOMPARABLE) { - check_val(v12, resultToPoComp(comp, false), e1.value(), e2.value(), e2.value()); - } - - decltype(_nodes)::Iterator it3(_nodes); - while (it3.hasNext()) { - auto& e3 = it3.next(); - if (e1.value() == e3.value() || e2.value() == e3.value()) { - continue; - } - - auto v13 = idx_of_safe(e1.value(),e3.value()); - if (v13 == PoComp::UNKNOWN) { - continue; - } - - auto v23 = idx_of_safe(e2.value(),e3.value()); - - switch (v12) { - case PoComp::UNKNOWN: - break; - case PoComp::EQUAL: - // x = y rel z -> x rel z - check_val(v13, v23, e1.value(), e2.value(), e3.value()); - break; - case PoComp::GREATER: - case PoComp::NLEQ: { - if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { - // x > y ≥ z -> x > z - // x ≰ y ≥ z -> x ≰ z - check_val(v13, v12, e1.value(), e2.value(), e3.value()); - } - break; - } - case PoComp::LESS: - case PoComp::NGEQ: { - if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { - // x < y ≤ z -> x < z - // x ≱ y ≤ z -> x ≱ z - check_val(v13, v12, e1.value(), e2.value(), e3.value()); - } - break; - } - case PoComp::INCOMPARABLE: { - if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { - // x ≰ y ≥ z -> x ≰ z - check_val(v13, PoComp::NLEQ, e1.value(), e2.value(), e3.value()); - } - if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { - // x ≱ y ≤ z -> x ≱ z - check_val(v13, PoComp::NGEQ, e1.value(), e2.value(), e3.value()); - } - break; - } - } - } - } - } -} -#endif - } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 56e9a0e19..cf70b5e40 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -15,19 +15,10 @@ #ifndef __PartialOrdering__ #define __PartialOrdering__ -#include "Forwards.hpp" - -#include "Lib/DHMap.hpp" -#include "Lib/VirtualIterator.hpp" - -#include "Ordering.hpp" +#include namespace Kernel { -using namespace Lib; - -using Result = Ordering::Result; - enum class PoComp : uint8_t { UNKNOWN, GREATER, @@ -38,20 +29,19 @@ enum class PoComp : uint8_t { INCOMPARABLE, }; -std::string idx_to_string(PoComp c); -std::string idx_to_infix(PoComp c); bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); class PartialOrdering { public: - PartialOrdering(const Ordering& ord); + PartialOrdering(); PartialOrdering(const PartialOrdering& other); ~PartialOrdering(); PartialOrdering& operator=(const PartialOrdering&) = delete; - bool get(TermList lhs, TermList rhs, Ordering::Result& res) const; - bool set(Ordering::Constraint con); + PoComp get(size_t x, size_t y) const; + bool set(size_t x, size_t y, PoComp v); + void extend(); // Returns if PO contains full incomparability yet. // Useful to discard branches when reasoning over ground terms. @@ -61,10 +51,7 @@ class PartialOrdering std::string all_to_string() const; private: - size_t idx_of_elem(TermList t) const; - size_t idx_of_elem_ext(TermList t); - PoComp idx_of(size_t x, size_t y) const; - PoComp idx_of_safe(size_t x, size_t y) const; + PoComp get_unsafe(size_t x, size_t y) const; bool set_idx_of(size_t x, size_t y, PoComp v, bool& changed); bool set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed); @@ -73,15 +60,6 @@ class PartialOrdering bool set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); bool set_inferred_loop_eq(size_t x, size_t y); - PoComp get_one_external(TermList t, size_t idx) const; - PoComp get_two_external(TermList t1, TermList t2) const; - -#if DEBUG_ORDERING - void debug_check() const; -#endif - - const Ordering& _ord; - Map _nodes; size_t _size; PoComp* _array; bool _hasIncomp; diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp new file mode 100644 index 000000000..4aa0aadc0 --- /dev/null +++ b/Kernel/TermPartialOrdering.cpp @@ -0,0 +1,426 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file TermPartialOrdering.cpp + * Implements class TermPartialOrdering. + */ + +#include +#include + +#include "TermPartialOrdering.hpp" + +namespace Kernel { + +using namespace std; + +Result poCompToResult(PoComp c) { + switch (c) { + case PoComp::GREATER: + return Result::GREATER; + case PoComp::EQUAL: + return Result::EQUAL; + case PoComp::LESS: + return Result::LESS; + case PoComp::NGEQ: + case PoComp::NLEQ: + case PoComp::INCOMPARABLE: + return Result::INCOMPARABLE; + default: + break; + } + ASSERTION_VIOLATION; +} + +PoComp resultToPoComp(Result r, bool reversed) { + switch (r) { + case Result::GREATER: + return reversed ? PoComp::LESS : PoComp::GREATER; + case Result::EQUAL: + return PoComp::EQUAL; + case Result::LESS: + return reversed ? PoComp::GREATER : PoComp::LESS; + case Result::INCOMPARABLE: + return reversed ? PoComp::NLEQ : PoComp::NGEQ; + } +} + +PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const +{ + PoComp res = PoComp::UNKNOWN; + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + if (e.value()==idx) { + continue; + } + auto val = _po.get(e.value(),idx); + if (val == PoComp::UNKNOWN) { + continue; + } + auto comp = _ord.compare(t,e.key()); + switch (comp) { + case Ordering::GREATER: { + switch (val) { + case PoComp::EQUAL: + case PoComp::GREATER: + // t > e ≥ x -> t > x + ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); + case PoComp::NLEQ: + case PoComp::INCOMPARABLE: + // t > e ≰ x -> t ≰ x + ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); + default: + break; + } + break; + } + case Ordering::EQUAL: { + return val; + } + case Ordering::LESS: { + switch (val) { + case PoComp::EQUAL: + case PoComp::LESS: + // t < e ≤ x -> t < x + ALWAYS(checkCompatibility(res, PoComp::LESS, res)); + case PoComp::NGEQ: + case PoComp::INCOMPARABLE: + // t < e ≱ x -> t ≱ x + ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); + default: + break; + } + break; + } + case Ordering::INCOMPARABLE: { + break; + } + } + } + return res; +} + +PoComp TermPartialOrdering::get_two_external(TermList t1, TermList t2) const +{ + PoComp res = PoComp::UNKNOWN; + Stack> t1_rel; // ∃x. t1 rel x + Stack> t2_rel; // ∃x. x rel t2 + + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + auto comp1 = _ord.compare(t1,e.key()); + if (comp1 != Ordering::INCOMPARABLE) { + t1_rel.push({ e.value(), comp1 }); + } + auto comp2 = _ord.compare(e.key(),t2); + if (comp2 != Ordering::INCOMPARABLE) { + t2_rel.push({ e.value(), comp2 }); + } + } + for (const auto& [e1,r1] : t1_rel) { + for (const auto& [e2,r2] : t2_rel) { + auto r = e1 == e2 ? PoComp::EQUAL : _po.get(e1,e2); + switch (r) { + case PoComp::UNKNOWN: + break; + case PoComp::EQUAL: { + switch (r1) { + case Ordering::GREATER: { + if (r2 != Ordering::LESS) { + // t1 > e1 = e2 ≥ t2 -> t1 > t2 + ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); + } + break; + } + case Ordering::EQUAL: { + // t1 = e1 = e2 r2 t2 -> t1 r2 t2 + ALWAYS(checkCompatibility(res, resultToPoComp(r2, false), res)); + break; + } + case Ordering::LESS: { + if (r2 != Ordering::GREATER) { + // t1 < e1 = e2 ≤ t2 -> t1 < t2 + ALWAYS(checkCompatibility(res, PoComp::LESS, res)); + } + break; + } + case Ordering::INCOMPARABLE: + ASSERTION_VIOLATION; + } + break; + } + case PoComp::GREATER: + case PoComp::NLEQ: { + if (r1 != Ordering::LESS && r2 != Ordering::LESS) { + // t1 ≥ e1 > e2 ≥ t2 -> t1 > t2 + // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 + ALWAYS(checkCompatibility(res, r, res)); + } + break; + } + case PoComp::LESS: + case PoComp::NGEQ: { + if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { + // t1 ≤ e1 < e2 ≤ t2 -> t1 < t2 + // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 + ALWAYS(checkCompatibility(res, r, res)); + } + break; + } + case PoComp::INCOMPARABLE: { + if (r1 != Ordering::GREATER && r2 != Ordering::GREATER) { + // t1 ≤ e1 ≱ e2 ≤ t2 -> t1 ≱ t2 + ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); + } + if (r1 != Ordering::LESS && r2 != Ordering::LESS) { + // t1 ≥ e1 ≰ e2 ≥ t2 -> t1 ≰ t2 + ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); + } + break; + } + } + } + } + return res; +} + +bool TermPartialOrdering::get(TermList lhs, TermList rhs, Result& res) const +{ + // comparable terms should be handled by caller + ASS_EQ(_ord.compare(lhs,rhs),Ordering::INCOMPARABLE); + // proper term pairs should be handled by caller + ASS(lhs.isVar() || rhs.isVar()); + + if (lhs == rhs) { + res = Result::EQUAL; + return true; + } + PoComp val; + bool reversed = false; + if (!_nodes.find(lhs) && !_nodes.find(rhs)) + { + val = get_two_external(lhs, rhs); + } + else if (!_nodes.find(lhs)) + { + ASS(_nodes.find(rhs)); + size_t y = idx_of_elem(rhs); + val = get_one_external(lhs, y); + } + else if (!_nodes.find(rhs)) + { + ASS(_nodes.find(lhs)); + size_t x = idx_of_elem(lhs); + val = get_one_external(rhs, x); + reversed = true; + } + else + { + size_t x = idx_of_elem(lhs); + size_t y = idx_of_elem(rhs); + reversed = x > y; + if (reversed) { + swap(x,y); + } + val = _po.get(x,y); + } + if (val == PoComp::UNKNOWN) { + return false; + } + // if we only have INCOMPARABLE in the "other direction" + // as we use isGreater which never gives LESS, we cannot + // distinguish between the two LESS and INCOMPARABLE + if (reversed) { + if (val == PoComp::NGEQ) { + return false; + } + res = Ordering::reverse(poCompToResult(val)); + return true; + } else { + if (val == PoComp::NLEQ) { + return false; + } + res = poCompToResult(val); + return true; + } +} + +bool TermPartialOrdering::set(Ordering::Constraint con) +{ + size_t x = idx_of_elem_ext(con.lhs); + size_t y = idx_of_elem_ext(con.rhs); + + bool reversed = x > y; + if (reversed) { + swap(x,y); + } + PoComp new_val = resultToPoComp(con.rel, reversed); + if (!_po.set(x, y, new_val)) { + return false; + } +#if DEBUG_ORDERING + // debug_check(); +#endif + return true; +} + +bool TermPartialOrdering::hasIncomp() const +{ + return _po.hasIncomp(); +} + +size_t TermPartialOrdering::idx_of_elem(TermList t) const +{ + ASS(_nodes.find(t)); + return _nodes.get(t); +} + +size_t TermPartialOrdering::idx_of_elem_ext(TermList t) +{ + size_t *ptr; + if (_nodes.getValuePtr(t, ptr, _nodes.size())) { + _po.extend(); + + // fill out new row with known values + size_t idx = _nodes.size()-1; + decltype(_nodes)::Iterator it(_nodes); + while (it.hasNext()) { + auto& e = it.next(); + if (e.value()==idx) { + continue; + } + auto comp = _ord.compare(e.key(),t); + if (comp == Ordering::INCOMPARABLE) { + continue; + } + auto val = resultToPoComp(comp, false); + ALWAYS(_po.set(e.value(), idx, val)); + } + } + return *ptr; +} + +string TermPartialOrdering::to_string() const +{ + stringstream str; + typename Map::Iterator it(_nodes); + while (it.hasNext()) { + const auto& e = it.next(); + str << e.value() << ": " << e.key() << ", "; + } + str << endl << _po.to_string(); + return str.str(); +} + +#if DEBUG_ORDERING +void TermPartialOrdering::debug_check() const +{ + auto output_args = [this](size_t x, size_t y, size_t z) { + return _po.all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); + }; + + auto check_val = [&output_args](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { + if (actual_val == PoComp::UNKNOWN) { + INVALID_OPERATION(output_args(x,y,z)); + } + if (expected_val == PoComp::NLEQ) { + if (actual_val != PoComp::NLEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::GREATER) { + INVALID_OPERATION(output_args(x,y,z)); + } + } else if (expected_val == PoComp::NGEQ) { + if (actual_val != PoComp::NGEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::LESS) { + INVALID_OPERATION(output_args(x,y,z)); + } + } else { + if (actual_val != expected_val) { + INVALID_OPERATION(output_args(x,y,z)); + } + } + }; + + decltype(_nodes)::Iterator it1(_nodes); + while (it1.hasNext()) { + auto& e1 = it1.next(); + + decltype(_nodes)::Iterator it2(_nodes); + while (it2.hasNext()) { + auto& e2 = it2.next(); + if (e1.value() == e2.value()) { + continue; + } + auto v12 = _po.get(e1.value(),e2.value()); + if (v12 == PoComp::UNKNOWN) { + continue; + } + auto comp = _ord.compare(e1.key(),e2.key()); + if (comp != Ordering::INCOMPARABLE) { + check_val(v12, resultToPoComp(comp, false), e1.value(), e2.value(), e2.value()); + } + + decltype(_nodes)::Iterator it3(_nodes); + while (it3.hasNext()) { + auto& e3 = it3.next(); + if (e1.value() == e3.value() || e2.value() == e3.value()) { + continue; + } + + auto v13 = _po.get(e1.value(),e3.value()); + if (v13 == PoComp::UNKNOWN) { + continue; + } + + auto v23 = _po.get(e2.value(),e3.value()); + + switch (v12) { + case PoComp::UNKNOWN: + break; + case PoComp::EQUAL: + // x = y rel z -> x rel z + check_val(v13, v23, e1.value(), e2.value(), e3.value()); + break; + case PoComp::GREATER: + case PoComp::NLEQ: { + if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { + // x > y ≥ z -> x > z + // x ≰ y ≥ z -> x ≰ z + check_val(v13, v12, e1.value(), e2.value(), e3.value()); + } + break; + } + case PoComp::LESS: + case PoComp::NGEQ: { + if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { + // x < y ≤ z -> x < z + // x ≱ y ≤ z -> x ≱ z + check_val(v13, v12, e1.value(), e2.value(), e3.value()); + } + break; + } + case PoComp::INCOMPARABLE: { + if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { + // x ≰ y ≥ z -> x ≰ z + check_val(v13, PoComp::NLEQ, e1.value(), e2.value(), e3.value()); + } + if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { + // x ≱ y ≤ z -> x ≱ z + check_val(v13, PoComp::NGEQ, e1.value(), e2.value(), e3.value()); + } + break; + } + } + } + } + } +} +#endif + +} diff --git a/Kernel/TermPartialOrdering.hpp b/Kernel/TermPartialOrdering.hpp new file mode 100644 index 000000000..46a386942 --- /dev/null +++ b/Kernel/TermPartialOrdering.hpp @@ -0,0 +1,63 @@ +/* + * This file is part of the source code of the software program + * Vampire. It is protected by applicable + * copyright laws. + * + * This source code is distributed under the licence found here + * https://vprover.github.io/license.html + * and in the source directory + */ +/** + * @file TermPartialOrdering.hpp + * Defines class TermPartialOrdering. + */ + +#ifndef __TermPartialOrdering__ +#define __TermPartialOrdering__ + +#include "Forwards.hpp" + +#include "Lib/DHMap.hpp" + +#include "Ordering.hpp" +#include "PartialOrdering.hpp" + +namespace Kernel { + +using namespace Lib; +using Result = Ordering::Result; + +class TermPartialOrdering +{ +public: + TermPartialOrdering(const Ordering& ord) : _ord(ord) {} + ~TermPartialOrdering() = default; + + bool get(TermList lhs, TermList rhs, Result& res) const; + bool set(Ordering::Constraint con); + + // Returns if PO contains full incomparability yet. + // Useful to discard branches when reasoning over ground terms. + bool hasIncomp() const; + + std::string to_string() const; + +private: + PoComp get_one_external(TermList t, size_t idx) const; + PoComp get_two_external(TermList t1, TermList t2) const; + + size_t idx_of_elem(TermList t) const; + size_t idx_of_elem_ext(TermList t); + +#if DEBUG_ORDERING + void debug_check() const; +#endif + + const Ordering& _ord; + Map _nodes; + PartialOrdering _po; +}; + +}; + +#endif /* __PartialOrdering__ */ \ No newline at end of file From a9e029eb8829f3357f49ae3e0a307272ef6aca5f Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 22 Nov 2024 19:22:06 +0100 Subject: [PATCH 44/64] Cache partial orderings and term partial orderings --- Kernel/OrderingComparator.cpp | 22 ++++-------- Kernel/OrderingComparator.hpp | 4 +-- Kernel/PartialOrdering.cpp | 65 ++++++++++++++++++++++++++-------- Kernel/PartialOrdering.hpp | 18 ++++++---- Kernel/TermPartialOrdering.cpp | 56 ++++++++++++++++++++++------- Kernel/TermPartialOrdering.hpp | 7 ++-- 6 files changed, 119 insertions(+), 53 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 23ad0dfe9..439583ac2 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -448,7 +448,7 @@ void OrderingComparator::processPolyCase() return e1.second>e2.second; }); _curr->node()->ready = true; - _curr->node()->trace = trace.release(); + _curr->node()->trace = trace; } void OrderingComparator::processVarCase() @@ -484,15 +484,15 @@ void OrderingComparator::processVarCase() _curr->node()->ngeBranch = node->ngeBranch; } _curr->node()->ready = true; - _curr->node()->trace = trace.release(); + _curr->node()->trace = trace; } -ScopedPtr OrderingComparator::getCurrentTrace() +const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() { ASS(!_curr->node()->ready || _curr->node() == _fail.node()); if (!_prev) { - return ScopedPtr(new Trace(_ord)); + return Trace::getEmpty(_ord); } ASS(_prev->node()->ready); @@ -500,7 +500,6 @@ ScopedPtr OrderingComparator::getCurrentTrace() switch (_prev->node()->tag) { case BranchTag::T_TERM: { - auto trace = ScopedPtr(new Trace(*_prev->node()->trace)); auto lhs = _prev->node()->lhs; auto rhs = _prev->node()->rhs; Ordering::Result res; @@ -511,17 +510,11 @@ ScopedPtr OrderingComparator::getCurrentTrace() } else { res = Ordering::INCOMPARABLE; } - // ALWAYS(trace->set({ lhs, rhs, res })); - if (!trace->set({ lhs, rhs, res })) { - return ScopedPtr(); - } - return ScopedPtr(trace.release()); - } - case BranchTag::T_RESULT: { - return ScopedPtr(new Trace(*_prev->node()->trace)); + return Trace::set(_prev->node()->trace, { lhs, rhs, res }); } + case BranchTag::T_RESULT: case BranchTag::T_POLY: { - return ScopedPtr(new Trace(*_prev->node()->trace)); + return _prev->node()->trace; } } ASSERTION_VIOLATION; @@ -681,7 +674,6 @@ OrderingComparator::Node::~Node() delete varCoeffPairs; } ready = false; - delete trace; trace = nullptr; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 6e737f8a9..ce7e1a1f6 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -109,7 +109,7 @@ struct OrderingComparator using Trace = TermPartialOrdering; - ScopedPtr getCurrentTrace(); + const Trace* getCurrentTrace(); struct Node { static_assert(sizeof(uint64_t) == sizeof(Branch)); @@ -161,7 +161,7 @@ struct OrderingComparator Branch eqBranch; Branch ngeBranch; int refcnt = 0; - Trace* trace = nullptr; + const Trace* trace = nullptr; }; const Ordering& _ord; diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 644367089..5e17fccdd 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -193,29 +193,63 @@ PoComp PartialOrdering::get(size_t x, size_t y) const return (x < y) ? get_unsafe(x,y) : reverse(get_unsafe(y,x)); } -bool PartialOrdering::set(size_t x, size_t y, PoComp v) +const PartialOrdering* PartialOrdering::getEmpty() { - ASS_L(x,_size); - ASS_L(y,_size); + static PartialOrdering empty; + return ∅ +} + +const PartialOrdering* PartialOrdering::set(const PartialOrdering* po, size_t x, size_t y, PoComp v) +{ + ASS(po); + ASS_L(x,po->_size); + ASS_L(y,po->_size); if (x == y) { - return true; + return po; } - // TODO remove this reverse thing - bool reversed = x > y; - if (reversed) { - swap(x,y); - } - bool changed; - RETURN_IF_FAIL(set_idx_of(x, y, v, changed)); + static DHMap, const PartialOrdering*> cache; - // if something's changed, we calculate the transitive closure - if (changed) { + const PartialOrdering** ptr; + if (cache.getValuePtr(make_tuple(po, x, y, v), ptr, nullptr)) { + // TODO remove this reverse thing + bool reversed = x > y; + if (reversed) { + swap(x,y); + } + auto res = new PartialOrdering(*po); + bool changed; + if (!res->set_idx_of(x, y, v, changed)) { + delete res; + *ptr = nullptr; + } else if (!changed) { + delete res; + *ptr = po; + } + // if something's changed, we calculate the transitive closure // TODO we could use the value that we get from compatibility checking here - RETURN_IF_FAIL(set_inferred(x, y, v)); + else if (!res->set_inferred(x, y, v)) { + delete res; + *ptr = nullptr; + } else { + *ptr = res; + } } - return true; + return *ptr; +} + +const PartialOrdering* PartialOrdering::extend(const PartialOrdering* po) +{ + static DHMap cache; + + const PartialOrdering** ptr; + if (cache.getValuePtr(po, ptr, nullptr)) { + auto res = new PartialOrdering(*po); + res->extend(); + *ptr = res; + } + return *ptr; } void PartialOrdering::extend() @@ -229,6 +263,7 @@ void PartialOrdering::extend() void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); _array = array_new(mem, newSize); std::memset(_array, 0, newSize*sizeof(PoComp)); + static_assert(static_cast(PoComp::UNKNOWN) == 0); if (prevArray) { memcpy(_array,prevArray,prevSize*sizeof(PoComp)); } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index cf70b5e40..2020c6799 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -34,14 +34,11 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); class PartialOrdering { public: - PartialOrdering(); - PartialOrdering(const PartialOrdering& other); - ~PartialOrdering(); - PartialOrdering& operator=(const PartialOrdering&) = delete; - PoComp get(size_t x, size_t y) const; - bool set(size_t x, size_t y, PoComp v); - void extend(); + + static const PartialOrdering* getEmpty(); + static const PartialOrdering* set(const PartialOrdering* po, size_t x, size_t y, PoComp v); + static const PartialOrdering* extend(const PartialOrdering* po); // Returns if PO contains full incomparability yet. // Useful to discard branches when reasoning over ground terms. @@ -51,6 +48,13 @@ class PartialOrdering std::string all_to_string() const; private: + PartialOrdering(); + PartialOrdering(const PartialOrdering& other); + ~PartialOrdering(); + PartialOrdering& operator=(const PartialOrdering&) = delete; + + void extend(); + PoComp get_unsafe(size_t x, size_t y) const; bool set_idx_of(size_t x, size_t y, PoComp v, bool& changed); bool set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed); diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index 4aa0aadc0..9c7708341 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -61,7 +61,7 @@ PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const if (e.value()==idx) { continue; } - auto val = _po.get(e.value(),idx); + auto val = _po->get(e.value(),idx); if (val == PoComp::UNKNOWN) { continue; } @@ -73,10 +73,14 @@ PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const case PoComp::GREATER: // t > e ≥ x -> t > x ALWAYS(checkCompatibility(res, PoComp::GREATER, res)); + return res; case PoComp::NLEQ: case PoComp::INCOMPARABLE: // t > e ≰ x -> t ≰ x ALWAYS(checkCompatibility(res, PoComp::NLEQ, res)); + if (res == PoComp::INCOMPARABLE) { + return res; + } default: break; } @@ -91,10 +95,14 @@ PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const case PoComp::LESS: // t < e ≤ x -> t < x ALWAYS(checkCompatibility(res, PoComp::LESS, res)); + return res; case PoComp::NGEQ: case PoComp::INCOMPARABLE: // t < e ≱ x -> t ≱ x ALWAYS(checkCompatibility(res, PoComp::NGEQ, res)); + if (res == PoComp::INCOMPARABLE) { + return res; + } default: break; } @@ -128,7 +136,7 @@ PoComp TermPartialOrdering::get_two_external(TermList t1, TermList t2) const } for (const auto& [e1,r1] : t1_rel) { for (const auto& [e2,r2] : t2_rel) { - auto r = e1 == e2 ? PoComp::EQUAL : _po.get(e1,e2); + auto r = e1 == e2 ? PoComp::EQUAL : _po->get(e1,e2); switch (r) { case PoComp::UNKNOWN: break; @@ -231,7 +239,7 @@ bool TermPartialOrdering::get(TermList lhs, TermList rhs, Result& res) const if (reversed) { swap(x,y); } - val = _po.get(x,y); + val = _po->get(x,y); } if (val == PoComp::UNKNOWN) { return false; @@ -264,7 +272,8 @@ bool TermPartialOrdering::set(Ordering::Constraint con) swap(x,y); } PoComp new_val = resultToPoComp(con.rel, reversed); - if (!_po.set(x, y, new_val)) { + _po = PartialOrdering::set(_po, x, y, new_val); + if (!_po) { return false; } #if DEBUG_ORDERING @@ -275,7 +284,29 @@ bool TermPartialOrdering::set(Ordering::Constraint con) bool TermPartialOrdering::hasIncomp() const { - return _po.hasIncomp(); + return _po->hasIncomp(); +} + +const TermPartialOrdering* TermPartialOrdering::getEmpty(const Ordering& ord) +{ + static TermPartialOrdering empty(ord); + return ∅ +} + +const TermPartialOrdering* TermPartialOrdering::set(const TermPartialOrdering* tpo, Ordering::Constraint con) +{ + static DHMap, const TermPartialOrdering*> cache; + const TermPartialOrdering** ptr; + if (cache.getValuePtr(make_tuple(tpo, con.lhs, con.rhs, con.rel), ptr, nullptr)) { + auto res = new TermPartialOrdering(*tpo); + if (!res->set(con)) { + delete res; + *ptr = nullptr; + } else { + *ptr = res; + } + } + return *ptr; } size_t TermPartialOrdering::idx_of_elem(TermList t) const @@ -288,7 +319,7 @@ size_t TermPartialOrdering::idx_of_elem_ext(TermList t) { size_t *ptr; if (_nodes.getValuePtr(t, ptr, _nodes.size())) { - _po.extend(); + _po = PartialOrdering::extend(_po); // fill out new row with known values size_t idx = _nodes.size()-1; @@ -303,7 +334,8 @@ size_t TermPartialOrdering::idx_of_elem_ext(TermList t) continue; } auto val = resultToPoComp(comp, false); - ALWAYS(_po.set(e.value(), idx, val)); + _po = PartialOrdering::set(_po, e.value(), idx, val); + ASS(_po); } } return *ptr; @@ -317,7 +349,7 @@ string TermPartialOrdering::to_string() const const auto& e = it.next(); str << e.value() << ": " << e.key() << ", "; } - str << endl << _po.to_string(); + str << endl << _po->to_string(); return str.str(); } @@ -325,7 +357,7 @@ string TermPartialOrdering::to_string() const void TermPartialOrdering::debug_check() const { auto output_args = [this](size_t x, size_t y, size_t z) { - return _po.all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); + return _po->all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); }; auto check_val = [&output_args](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { @@ -357,7 +389,7 @@ void TermPartialOrdering::debug_check() const if (e1.value() == e2.value()) { continue; } - auto v12 = _po.get(e1.value(),e2.value()); + auto v12 = _po->get(e1.value(),e2.value()); if (v12 == PoComp::UNKNOWN) { continue; } @@ -373,12 +405,12 @@ void TermPartialOrdering::debug_check() const continue; } - auto v13 = _po.get(e1.value(),e3.value()); + auto v13 = _po->get(e1.value(),e3.value()); if (v13 == PoComp::UNKNOWN) { continue; } - auto v23 = _po.get(e2.value(),e3.value()); + auto v23 = _po->get(e2.value(),e3.value()); switch (v12) { case PoComp::UNKNOWN: diff --git a/Kernel/TermPartialOrdering.hpp b/Kernel/TermPartialOrdering.hpp index 46a386942..15ef17212 100644 --- a/Kernel/TermPartialOrdering.hpp +++ b/Kernel/TermPartialOrdering.hpp @@ -30,12 +30,15 @@ using Result = Ordering::Result; class TermPartialOrdering { public: - TermPartialOrdering(const Ordering& ord) : _ord(ord) {} + TermPartialOrdering(const Ordering& ord) : _ord(ord), _po(PartialOrdering::getEmpty()) {} ~TermPartialOrdering() = default; bool get(TermList lhs, TermList rhs, Result& res) const; bool set(Ordering::Constraint con); + static const TermPartialOrdering* getEmpty(const Ordering& ord); + static const TermPartialOrdering* set(const TermPartialOrdering* tpo, Ordering::Constraint con); + // Returns if PO contains full incomparability yet. // Useful to discard branches when reasoning over ground terms. bool hasIncomp() const; @@ -55,7 +58,7 @@ class TermPartialOrdering const Ordering& _ord; Map _nodes; - PartialOrdering _po; + const PartialOrdering* _po; }; }; From d27aa1e834856888f2eab6893d363a0444a74fe7 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 25 Nov 2024 09:45:06 +0100 Subject: [PATCH 45/64] Skip superpositions based on rwClause too; only store original comparisons for debugging in conditional redundancy handler --- Inferences/Superposition.cpp | 8 ++--- Shell/ConditionalRedundancyHandler.cpp | 43 ++++++++++++++++++++------ Shell/ConditionalRedundancyHandler.hpp | 12 +++++-- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index 0f82d47a1..8b3587a3b 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -343,7 +343,7 @@ Clause* Superposition::performSuperposition( const auto& condRedHandler = _salg->condRedHandler(); if (!unifier->usesUwa()) { - if (!condRedHandler.checkSuperposition(eqClause, eqLit, eqLHS, rwClause, rwLit, eqIsResult, subst.ptr())) { + if (!condRedHandler.checkSuperposition(eqClause, eqLit, eqLHS, rwClause, rwLit, rwTerm, eqIsResult, subst.ptr())) { return 0; } } @@ -534,9 +534,9 @@ Clause* Superposition::performSuperposition( rwTerm )); - if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { - condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); - } + // if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { + // condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); + // } return clause; } diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 8dc44a3f1..f6192212c 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -130,7 +130,11 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(entries->comparator); - entries->entries.push(ptr); +#if DEBUG_ORDERING + // we push subsumed ones as well to check subsumption + entries->comps.push(ptr); +#endif + entries->comparator->insert(ptr->ordCons); return true; } @@ -158,7 +162,9 @@ class ConditionalRedundancyHandler::ConstraintIndex compiler.updateCodeTree(this); auto es = new Entries(); - es->entries.push(ptr); +#if DEBUG_ORDERING + es->comps.push(ptr); +#endif es->comparator = ord->createComparator(); es->comparator->insert(ptr->ordCons); code.push(CodeOp::getSuccess(es)); @@ -203,7 +209,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(es->comparator); auto res = es->comparator->check(&applicator); #if DEBUG_ORDERING - auto ordCons_crosscheck = iterTraits(es->entries.iter()).any([ord,&applicator](auto e) { + auto ordCons_crosscheck = iterTraits(es->comps.iter()).any([ord,&applicator](auto e) { return iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; }); @@ -211,7 +217,7 @@ class ConditionalRedundancyHandler::ConstraintIndex if (res != ordCons_crosscheck) { cout << res << " " << ordCons_crosscheck << endl; cout << *es->comparator << endl; - for (const auto& e : es->entries) { + for (const auto& e : es->comps) { cout << *e << endl; } INVALID_OPERATION("conditional redundancy ordering check mismatch"); @@ -336,7 +342,9 @@ class ConditionalRedundancyHandler::ConstraintIndex static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { auto es = op->getSuccessResult(); - iterTraits(decltype(es->entries)::Iterator(es->entries)).forEach([](ConditionalRedundancyEntry* e) { delete e; }); +#if DEBUG_ORDERING + iterTraits(decltype(es->comps)::Iterator(es->comps)).forEach([](ConditionalRedundancyEntry* e) { delete e; }); +#endif delete es; } } @@ -430,7 +438,7 @@ DHMap Condition template bool ConditionalRedundancyHandlerImpl::checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, + Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, TermList rwTerm, bool eqIsResult, ResultSubstitution* subs) const { if constexpr (!enabled) { @@ -455,9 +463,26 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp } auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); - if (rwClDataPtr && (*rwClDataPtr)->_redundant) { - env.statistics->skippedSuperposition++; - return false; + if (rwClDataPtr) { + if ((*rwClDataPtr)->_redundant) { + env.statistics->skippedSuperposition++; + return false; + } + auto i = rwClause->getLiteralPosition(rwLit); + auto leftred = (*rwClDataPtr)->_litRedundant[i].first; + auto rightred = (*rwClDataPtr)->_litRedundant[i].second; + if (leftred && rightred) { + env.statistics->skippedSuperposition++; + return false; + } + if (leftred && !rwLit->termArg(1).containsSubterm(rwTerm)) { + env.statistics->skippedSuperposition++; + return false; + } + if (rightred && !rwLit->termArg(0).containsSubterm(rwTerm)) { + env.statistics->skippedSuperposition++; + return false; + } } auto rwLits = LiteralSet::getEmpty(); diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index 3b8f9e9c0..d7e61d384 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -86,7 +86,9 @@ struct ConditionalRedundancyEntry }; struct Entries { - Stack entries; +#if DEBUG_ORDERING + Stack comps; +#endif OrderingComparatorUP comparator; }; @@ -100,7 +102,9 @@ class ConditionalRedundancyHandler virtual ~ConditionalRedundancyHandler() = default; virtual bool checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const = 0; + Clause* eqClause, Literal* eqLit, TermList eqLHS, + Clause* rwClause, Literal* rwLit, TermList rwTerm, + bool eqIsResult, ResultSubstitution* subs) const = 0; virtual bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, @@ -140,7 +144,9 @@ class ConditionalRedundancyHandlerImpl /** Returns false if superposition should be skipped. */ bool checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const override; + Clause* eqClause, Literal* eqLit, TermList eqLHS, + Clause* rwClause, Literal* rwLit, TermList rwTerm, + bool eqIsResult, ResultSubstitution* subs) const override; bool insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, From 02851d4b5f5d1fe6af9bfe15e2657f350549fccf Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 25 Nov 2024 14:36:49 +0100 Subject: [PATCH 46/64] Change ordering comparator subsumption implementation to one which iterates through both subsumer and to-be-subsumed at once, returning a bit faster --- Kernel/OrderingComparator.cpp | 158 ++++++++++++++++++---------------- Kernel/OrderingComparator.hpp | 4 +- 2 files changed, 85 insertions(+), 77 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 439583ac2..f564f74d3 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -521,47 +521,87 @@ const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() } OrderingComparator::Subsumption::Subsumption(OrderingComparator& subsumer, const Ordering& ord, const OrderingConstraints& ordCons, bool ground) - : subsumer(subsumer), subsumed(ord.createComparator()), path({ &subsumer._source }), ground(ground) + : subsumer(subsumer), subsumed(ord.createComparator()), ground(ground) { subsumed->insert(ordCons); + path.push({ &subsumer._source, nullptr, &subsumed->_source }); } +#define SUBSUMPTION_MAX_ITERATIONS 500 + bool OrderingComparator::Subsumption::check() { + unsigned cnt = 0; while (path.isNonEmpty()) { + if (cnt++ > SUBSUMPTION_MAX_ITERATIONS) { + return false; + } + if (path.size()==1) { subsumer._prev = nullptr; } else { - subsumer._prev = path[path.size()-2]; + subsumer._prev = get<0>(path[path.size()-2]); } - subsumer._curr = path.top(); + subsumer._curr = get<0>(path.top()); subsumer.expand(); - switch (subsumer._curr->node()->tag) { - case BranchTag::T_POLY: - case BranchTag::T_TERM: { - path.push(&subsumer._curr->node()->gtBranch); + auto lnode = subsumer._curr->node(); + if (lnode->tag == BranchTag::T_RESULT && lnode->result) { + pushNext(); + continue; + } + + auto trace = lnode->trace ? lnode->trace : subsumer.getCurrentTrace(); + if (!trace || (ground && trace->hasIncomp())) { + pushNext(); + continue; + } + + subsumed->_prev = get<1>(path.top()); + subsumed->_curr = get<2>(path.top()); + subsumed->expand(); + auto rnode = subsumed->_curr->node(); + + switch (rnode->tag) { + case BranchTag::T_POLY: { + if (lnode->tag == BranchTag::T_RESULT) { + return false; + } + path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); break; } case BranchTag::T_RESULT: { - if (!checkLeaf()) { - return false; + if (rnode->result) { + if (lnode->tag == BranchTag::T_RESULT) { + return false; + } + path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); + } else { + pushNext(); } - // find next node to check - while (path.isNonEmpty()) { - auto prev = path.size()==1 ? nullptr : path[path.size()-2]->node(); - auto curr = path.pop(); - ASS(!prev || prev->tag == BranchTag::T_POLY || prev->tag == BranchTag::T_TERM); - - if (prev) { - // if there is a previous node and we were either in the gt or eq - // branches, just go to next branch in order, otherwise backtrack - if (curr == &prev->gtBranch) { - path.push(&prev->eqBranch); + break; + } + case BranchTag::T_TERM: { + auto lhs = rnode->lhs; + auto rhs = rnode->rhs; + Ordering::Result val; + if (!trace->get(lhs, rhs, val)) { + if (lnode->tag == BranchTag::T_RESULT) { + return false; + } + path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); + } else { + switch (val) { + case Ordering::GREATER: { + path.top() = { subsumer._curr, subsumed->_curr, &rnode->gtBranch }; break; } - if (curr == &prev->eqBranch) { - path.push(&prev->ngeBranch); + case Ordering::EQUAL: { + path.top() = { subsumer._curr, subsumed->_curr, &rnode->eqBranch }; + break; + } + default: { + path.top() = { subsumer._curr, subsumed->_curr, &rnode->ngeBranch }; break; } } @@ -575,63 +615,31 @@ bool OrderingComparator::Subsumption::check() return true; } -bool OrderingComparator::Subsumption::checkLeaf() +void OrderingComparator::Subsumption::pushNext() { - if (subsumer._curr->node()->result) { - return true; - } - - auto trace = subsumer.getCurrentTrace(); - if (!trace) { - return true; - } - if (ground && trace->hasIncomp()) { - return true; - } - Stack> todo; - todo.push({ nullptr, &subsumed->_source }); - while (todo.isNonEmpty()) { - auto [prev, curr] = todo.pop(); - subsumed->_prev = prev; - subsumed->_curr = curr; - subsumed->expand(); + while (path.isNonEmpty()) { + auto curr = get<0>(path.pop()); + if (path.isEmpty()) { + continue; + } - switch (subsumed->_curr->node()->tag) { - case BranchTag::T_POLY: { - return false; - } - case BranchTag::T_RESULT: { - if (subsumed->_curr->node()->result) { - return false; - } - break; - } - case BranchTag::T_TERM: { - auto lhs = subsumed->_curr->node()->lhs; - auto rhs = subsumed->_curr->node()->rhs; - Ordering::Result val; - if (!trace->get(lhs, rhs, val)) { - return false; - } - switch (val) { - case Ordering::GREATER: { - todo.push({ subsumed->_curr, &subsumed->_curr->node()->gtBranch }); - break; - } - case Ordering::EQUAL: { - todo.push({ subsumed->_curr, &subsumed->_curr->node()->eqBranch }); - break; - } - default: { - todo.push({ subsumed->_curr, &subsumed->_curr->node()->ngeBranch }); - break; - } - } - break; - } + auto prevE = path.top(); + auto prev = get<0>(prevE)->node(); + ASS(prev->tag == BranchTag::T_POLY || prev->tag == BranchTag::T_TERM); + if (!prev) { + continue; + } + // if there is a previous node and we were either in the gt or eq + // branches, just go to next branch in order, otherwise backtrack + if (curr == &prev->gtBranch) { + path.push({ &prev->eqBranch, get<1>(prevE), get<2>(prevE) }); + break; + } + if (curr == &prev->eqBranch) { + path.push({ &prev->ngeBranch, get<1>(prevE), get<2>(prevE) }); + break; } } - return true; } OrderingComparator::Branch::~Branch() diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index ce7e1a1f6..13c831d87 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -50,11 +50,11 @@ struct OrderingComparator bool check(); private: - bool checkLeaf(); + void pushNext(); OrderingComparator& subsumer; OrderingComparatorUP subsumed; - Stack path; + Stack> path; bool ground; }; From feb2a6a6c0a8fe05668b6ce0eb7cf3b937069db4 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 27 Nov 2024 15:47:39 +0100 Subject: [PATCH 47/64] Some smaller changes --- Kernel/OrderingComparator.cpp | 24 ++++++---- Kernel/PartialOrdering.cpp | 25 ++--------- Kernel/PartialOrdering.hpp | 1 + Kernel/TermPartialOrdering.cpp | 31 +++++++++++-- Kernel/TermPartialOrdering.hpp | 1 + Saturation/SaturationAlgorithm.cpp | 12 ++--- Shell/ConditionalRedundancyHandler.cpp | 62 +++++++++++++------------- 7 files changed, 86 insertions(+), 70 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index f564f74d3..cd92d6742 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -28,13 +28,13 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& { switch (t) { case OrderingComparator::BranchTag::T_RESULT: - out << "r"; + out << "res"; break; case OrderingComparator::BranchTag::T_TERM: - out << "c"; + out << "term"; break; case OrderingComparator::BranchTag::T_POLY: - out << "w"; + out << "poly"; break; } return out; @@ -49,9 +49,18 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node break; } case OrderingComparator::BranchTag::T_POLY: { - out << node.w << " "; - for (const auto& [var, coeff] : *node.varCoeffPairs) { - out << "X" << var << " " << coeff << " "; + out << node.w; + for (unsigned i = 0; i < node.varCoeffPairs->size(); i++) { + const auto& [var, coeff] = (*node.varCoeffPairs)[i]; + ASS_NEQ(coeff,0); + // output sign + out << (coeff<0 ? " - " : " + "); + // output coefficient + if (abs(coeff) != 1) { + out << abs(coeff) << " * "; + } + // output variable + out << "X" << var; } break; } @@ -626,9 +635,6 @@ void OrderingComparator::Subsumption::pushNext() auto prevE = path.top(); auto prev = get<0>(prevE)->node(); ASS(prev->tag == BranchTag::T_POLY || prev->tag == BranchTag::T_TERM); - if (!prev) { - continue; - } // if there is a previous node and we were either in the gt or eq // branches, just go to next branch in order, otherwise backtrack if (curr == &prev->gtBranch) { diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 5e17fccdd..61f2a7e4a 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -124,26 +124,7 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) ASSERTION_VIOLATION; } -string idx_to_string(PoComp c) { - switch (c) { - case PoComp::UNKNOWN: - return "UNKNOWN"; - case PoComp::GREATER: - return "GREATER"; - case PoComp::EQUAL: - return "EQUAL"; - case PoComp::LESS: - return "LESS"; - case PoComp::NGEQ: - return "NGEQ"; - case PoComp::NLEQ: - return "NLEQ"; - case PoComp::INCOMPARABLE: - return "INCOMPARABLE"; - } -} - -string idx_to_infix(PoComp c) { +string po_to_infix(PoComp c) { switch (c) { case PoComp::UNKNOWN: return "?"; @@ -650,12 +631,12 @@ string PartialOrdering::to_string() const if (w>1) { str << std::setw(w-1) << " "; } - str << idx_to_infix(get_unsafe(j,i)) << " "; + str << po_to_infix(get_unsafe(j,i)) << " "; } if (w>1) { str << std::setw(w-1) << " "; } - str << idx_to_infix(PoComp::EQUAL) << " " << endl; + str << po_to_infix(PoComp::EQUAL) << " " << endl; } str << std::setw(w) << " " << " "; for (size_t i = 0; i < _size; i++) { diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 2020c6799..29fdc9f2f 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -30,6 +30,7 @@ enum class PoComp : uint8_t { }; bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); +std::string po_to_infix(PoComp c); class PartialOrdering { diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index 9c7708341..390912f0e 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -344,15 +344,38 @@ size_t TermPartialOrdering::idx_of_elem_ext(TermList t) string TermPartialOrdering::to_string() const { stringstream str; - typename Map::Iterator it(_nodes); - while (it.hasNext()) { - const auto& e = it.next(); - str << e.value() << ": " << e.key() << ", "; + for (unsigned i = 0; i < _nodes.size(); i++) { + typename Map::Iterator it(_nodes); + while (it.hasNext()) { + const auto& e = it.next(); + if (e.value() != i) { + continue; + } + str << e.value() << ": " << e.key() << ", "; + } } str << endl << _po->to_string(); return str.str(); } +string TermPartialOrdering::to_nice_string() const +{ + stringstream str; + typename Map::Iterator it1(_nodes); + while (it1.hasNext()) { + const auto& e1 = it1.next(); + typename Map::Iterator it2(_nodes); + while (it2.hasNext()) { + const auto& e2 = it2.next(); + if (e1.value() >= e2.value()) { + continue; + } + str << e1.key() << " " << po_to_infix(_po->get(e1.value(),e2.value())) << " " << e2.key() << endl; + } + } + return str.str(); +} + #if DEBUG_ORDERING void TermPartialOrdering::debug_check() const { diff --git a/Kernel/TermPartialOrdering.hpp b/Kernel/TermPartialOrdering.hpp index 15ef17212..1413d6a2c 100644 --- a/Kernel/TermPartialOrdering.hpp +++ b/Kernel/TermPartialOrdering.hpp @@ -44,6 +44,7 @@ class TermPartialOrdering bool hasIncomp() const; std::string to_string() const; + std::string to_nice_string() const; private: PoComp get_one_external(TermList t, size_t idx) const; diff --git a/Saturation/SaturationAlgorithm.cpp b/Saturation/SaturationAlgorithm.cpp index 21fd9a521..0532d028b 100644 --- a/Saturation/SaturationAlgorithm.cpp +++ b/Saturation/SaturationAlgorithm.cpp @@ -1281,11 +1281,11 @@ void SaturationAlgorithm::doOneAlgorithmStep() throw MainLoopFinishedException(res); } - auto acl = _active->clauses(); - while (acl.hasNext()) { - auto cl = acl.next(); - _conditionalRedundancyHandler->checkSubsumption(cl); - } + // auto acl = _active->clauses(); + // while (acl.hasNext()) { + // auto cl = acl.next(); + // _conditionalRedundancyHandler->checkSubsumption(cl); + // } Clause* cl = nullptr; { @@ -1300,6 +1300,8 @@ void SaturationAlgorithm::doOneAlgorithmStep() } activate(cl); + + _conditionalRedundancyHandler->checkSubsumption(cl); } /** diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index f6192212c..0a6d163f0 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -828,38 +828,30 @@ void ConditionalRedundancyHandlerImpl::checkSubsum return; } - auto ts = cld->getInstances([](unsigned v) { return TermList::var(v); }); - static ConstraintIndex::SubstMatcher matcher; - matcher.init((*clDataPtr), ts); - Entries* es = matcher.next(); - matcher.reset(); - // there can be only one such matching under linearization + if (!cld->_subs) { + auto ts = cld->getInstances([](unsigned v) { return TermList::var(v); }); + static ConstraintIndex::SubstMatcher matcher; + matcher.init((*clDataPtr), ts); + Entries* es = matcher.next(); + matcher.reset(); + // there can be only one such matching under linearization #if !LINEARIZE - static_assert(false); + static_assert(false); #endif - if (!es) { - return; - } - ASS(es->comparator); - if (!cld->_subs) { - cld->_subs = new Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); - } - if (cld->_subs->check()) { - cld->_redundant = true; - env.statistics->groundRedundantClauses++; - return; - } - - for (unsigned i = 0; i < cl->numSelected(); i++) { - auto lit = (*cl)[i]; - if (!lit->isEquality() || _ord->getEqualityArgumentOrder(lit)!=Ordering::INCOMPARABLE) { - continue; + if (!es) { + return; } + ASS(es->comparator); - auto& [subsLtr, subsRtl] = cld->_litSubs[i]; - auto& [redLtr, redRtl] = cld->_litRedundant[i]; - if (!subsLtr) { - ASS(!subsRtl); + cld->_subs = new Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); + for (unsigned i = 0; i < cl->numSelected(); i++) { + auto lit = (*cl)[i]; + if (!lit->isEquality() || _ord->getEqualityArgumentOrder(lit)!=Ordering::INCOMPARABLE) { + continue; + } + + auto& [subsLtr, subsRtl] = cld->_litSubs[i]; + ASS(!subsLtr && !subsRtl); Renaming r; for (const auto t : ts) { r.normalizeVariables(t); @@ -869,11 +861,21 @@ void ConditionalRedundancyHandlerImpl::checkSubsum subsLtr = new Subsumption(*es->comparator.get(), *_ord, { { lhs, rhs, Ordering::GREATER } }, /*ground=*/true); subsRtl = new Subsumption(*es->comparator.get(), *_ord, { { rhs, lhs, Ordering::GREATER } }, /*ground=*/true); } - if (!redLtr && subsLtr->check()) { + } + if (cld->_subs->check()) { + cld->_redundant = true; + env.statistics->groundRedundantClauses++; + return; + } + + for (unsigned i = 0; i < cl->numSelected(); i++) { + auto& [subsLtr, subsRtl] = cld->_litSubs[i]; + auto& [redLtr, redRtl] = cld->_litRedundant[i]; + if (!redLtr && subsLtr && subsLtr->check()) { redLtr = true; env.statistics->groundRedundantEquationOrientations++; } - if (!redRtl && subsRtl->check()) { + if (!redRtl && subsRtl && subsRtl->check()) { redRtl = true; env.statistics->groundRedundantEquationOrientations++; } From a7b68b263dc6cfdc0be304403c01cd5b837e94ec Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 28 Nov 2024 09:20:54 +0100 Subject: [PATCH 48/64] Fix things for Linux build --- Kernel/FlatTerm.cpp | 45 ++++++-------------------- Kernel/FlatTerm.hpp | 1 - Kernel/OrderingComparator.cpp | 2 ++ Kernel/PartialOrdering.cpp | 10 ++++-- Shell/ConditionalRedundancyHandler.cpp | 9 +++--- 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/Kernel/FlatTerm.cpp b/Kernel/FlatTerm.cpp index 53d089c43..a29d7a23b 100644 --- a/Kernel/FlatTerm.cpp +++ b/Kernel/FlatTerm.cpp @@ -33,11 +33,14 @@ using namespace Lib; */ void* FlatTerm::operator new(size_t sz,unsigned num) { - ASS_GE(num,1); + ASS_GE(num,0); ASS_EQ(sz, sizeof(FlatTerm)); //one entry is already accounted for in the size of the FlatTerm object - size_t size=sizeof(FlatTerm)+(num-1)*sizeof(Entry); + size_t size = sizeof(FlatTerm); + if (num > 0) { + size += (num-1)*sizeof(Entry); + } return ALLOC_KNOWN(size,"FlatTerm"); } @@ -47,10 +50,13 @@ void* FlatTerm::operator new(size_t sz,unsigned num) */ void FlatTerm::destroy() { - ASS_GE(_length,1); + ASS_GE(_length,0); //one entry is already accounted for in the size of the FlatTerm object - size_t size=sizeof(FlatTerm)+(_length-1)*sizeof(Entry); + size_t size = sizeof(FlatTerm); + if (_length > 0) { + size += (_length-1)*sizeof(Entry); + } DEALLOC_KNOWN(this, size,"FlatTerm"); } @@ -131,37 +137,6 @@ FlatTerm* FlatTerm::create(TermList t) return res; } -FlatTerm* FlatTerm::create(TermStack ts) -{ - size_t entries=0; - for (auto& tl : ts) { - entries += tl.isVar() ? 1 : getEntryCount(tl.term()); - } - - FlatTerm* res=new(entries) FlatTerm(entries); - size_t fti=0; - - for (auto& tl : ts) { - if (tl.isVar()) { - pushVar(res, fti, tl.var()); - continue; - } - auto t = tl.term(); - (*res)[fti++]=Entry(FUN, - t->isLiteral() ? static_cast(t)->header() : t->functor()); - (*res)[fti++]=Entry(t); - (*res)[fti++]=Entry(FUN_RIGHT_OFS, getEntryCount(t)); - - SubtermIterator sti(t); - while(sti.hasNext()) { - pushTermList(res, fti, sti.next()); - } - } - ASS_EQ(fti, entries); - - return res; -} - FlatTerm* FlatTerm::createUnexpanded(Term* t) { size_t entries=getEntryCount(t); diff --git a/Kernel/FlatTerm.hpp b/Kernel/FlatTerm.hpp index a42a4771e..8efb41e6b 100644 --- a/Kernel/FlatTerm.hpp +++ b/Kernel/FlatTerm.hpp @@ -26,7 +26,6 @@ class FlatTerm public: static FlatTerm* create(Term* t); static FlatTerm* create(TermList t); - static FlatTerm* create(TermStack ts); /** * Similar to @b create but only allocates the flat term, * and does not fill out its content. The caller has to diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index cd92d6742..fce945829 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -18,6 +18,8 @@ #include "KBO.hpp" #include "SubstHelper.hpp" +#include + #include "OrderingComparator.hpp" using namespace std; diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 61f2a7e4a..09bf1752a 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -47,6 +47,7 @@ constexpr PoComp reverse(PoComp v) { case PoComp::INCOMPARABLE: return PoComp::INCOMPARABLE; } + ASSERTION_VIOLATION; } constexpr PoComp weaken(PoComp v) { @@ -56,8 +57,9 @@ constexpr PoComp weaken(PoComp v) { case PoComp::LESS: return PoComp::NGEQ; default: - ASSERTION_VIOLATION; + break; } + ASSERTION_VIOLATION; } constexpr PoComp strengthen(PoComp v) { @@ -67,8 +69,9 @@ constexpr PoComp strengthen(PoComp v) { case PoComp::NGEQ: return PoComp::LESS; default: - ASSERTION_VIOLATION; + break; } + ASSERTION_VIOLATION; } bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) @@ -119,7 +122,7 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) } break; default: - ASSERTION_VIOLATION; + break; } ASSERTION_VIOLATION; } @@ -141,6 +144,7 @@ string po_to_infix(PoComp c) { case PoComp::INCOMPARABLE: return "⋈"; } + ASSERTION_VIOLATION; } PartialOrdering::PartialOrdering() diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 0a6d163f0..bb3876524 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -79,10 +79,8 @@ class ConditionalRedundancyHandler::ConstraintIndex #endif for (unsigned i = 0; i < cl->length(); i++) { SortHelper::collectVariableSorts((*cl)[i], _varSorts); - if (i < cl->numSelected()) { - _litSubs.push({ nullptr, nullptr }); - _litRedundant.push({ false, false }); - } + _litSubs.push({ nullptr, nullptr }); + _litRedundant.push({ false, false }); } } @@ -174,7 +172,7 @@ class ConditionalRedundancyHandler::ConstraintIndex VariantMatcher vm; Stack firstsInBlocks; - FlatTerm* ft = FlatTerm::create(ts); + FlatTerm* ft = FlatTerm::createUnexpanded(ts); vm.init(ft, this, &firstsInBlocks); if (vm.next()) { @@ -839,6 +837,7 @@ void ConditionalRedundancyHandlerImpl::checkSubsum static_assert(false); #endif if (!es) { + // in this case we try to create the subsumption next time return; } ASS(es->comparator); From 21902c90980da940695851233e637deecc20cbc2 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 4 Dec 2024 19:36:24 +0100 Subject: [PATCH 49/64] Clean up branch --- Indexing/CodeTree.cpp | 73 ++--- Indexing/CodeTree.hpp | 17 +- Indexing/TermCodeTree.hpp | 6 - Inferences/BackwardDemodulation.cpp | 22 +- Inferences/Superposition.cpp | 13 +- Saturation/SaturationAlgorithm.cpp | 10 - Saturation/Splitter.cpp | 15 +- Saturation/Splitter.hpp | 1 - Shell/ConditionalRedundancyHandler.cpp | 420 ++++++------------------- Shell/ConditionalRedundancyHandler.hpp | 51 +-- 10 files changed, 148 insertions(+), 480 deletions(-) diff --git a/Indexing/CodeTree.cpp b/Indexing/CodeTree.cpp index 59e6dc238..5d336f4b2 100644 --- a/Indexing/CodeTree.cpp +++ b/Indexing/CodeTree.cpp @@ -543,7 +543,7 @@ inline bool CodeTree::BaseMatcher::doCheckGroundTerm() //////////////// auxiliary //////////////////// CodeTree::CodeTree() -: _onCodeOpDestroying(0), _curTimeStamp(0), _maxVarCnt(1), _maxTreeDepth(0), _entryPoint(0) +: _onCodeOpDestroying(0), _curTimeStamp(0), _maxVarCnt(1), _entryPoint(0) { } @@ -644,30 +644,30 @@ void CodeTree::visitAllOps(Visitor visitor) const std::ostream& operator<<(std::ostream& out, const CodeTree& ct) { - ct.visitAllOps([&out,&ct](const CodeTree::CodeOp* op, unsigned depth) { + ct.visitAllOps([&out](const CodeTree::CodeOp* op, unsigned depth) { for (unsigned i = 0; i < depth; i++) { out << " "; } - out << *op << (op->isSuccess()?" "+ct.leafToString(op):"") << std::endl; + out << *op << std::endl; }); return out; } //////////////// insertion //////////////////// -template -CodeTree::Compiler::Compiler(CodeStack& code) : code(code), nextVarNum(0), nextGlobalVarNum(0) {} +template +CodeTree::Compiler::Compiler(CodeStack& code) : code(code), nextVarNum(0), nextGlobalVarNum(0) {} -template -void CodeTree::Compiler::nextLit() +template +void CodeTree::Compiler::nextLit() { ASS(forLits); nextVarNum = 0; varMap.reset(); } -template -void CodeTree::Compiler::updateCodeTree(CodeTree* tree) +template +void CodeTree::Compiler::updateCodeTree(CodeTree* tree) { //update the max. number of variables, if necessary if(nextGlobalVarNum>tree->_maxVarCnt) { @@ -678,8 +678,8 @@ void CodeTree::Compiler::updateCodeTree(CodeTree* tree) } } -template -void CodeTree::Compiler::handleTerm(const Term* trm) +template +void CodeTree::Compiler::handleTerm(const Term* trm) { ASS(!forLits || trm->isLiteral()); @@ -722,40 +722,28 @@ void CodeTree::Compiler::handleTerm(const Term* trm) } } -template -void CodeTree::Compiler::handleVar(unsigned var, Stack* globalCounterparts) +template +void CodeTree::Compiler::handleVar(unsigned var, Stack* globalCounterparts) { - ASS(!forLits || !linearize); - unsigned* varNumPtr; - if constexpr (linearize) { - if (varMap.getValuePtr(var,varNumPtr)) { - *varNumPtr = nextVarNum; - } else { - eqCons.push(make_pair(*varNumPtr, nextVarNum)); - } - code.push(CodeOp::getTermOp(ASSIGN_VAR, nextVarNum)); - nextVarNum++; - } else { - if (varMap.getValuePtr(var,varNumPtr)) { - *varNumPtr = nextVarNum++; - code.push(CodeOp::getTermOp(ASSIGN_VAR, *varNumPtr)); - - if constexpr (forLits) { - unsigned* globalVarNumPtr; - if (globalVarMap.getValuePtr(var,globalVarNumPtr)) { - *globalVarNumPtr = nextGlobalVarNum++; - } - globalCounterparts->push(*globalVarNumPtr); + if (varMap.getValuePtr(var,varNumPtr)) { + *varNumPtr = nextVarNum++; + code.push(CodeOp::getTermOp(ASSIGN_VAR, *varNumPtr)); + + if constexpr (forLits) { + unsigned* globalVarNumPtr; + if (globalVarMap.getValuePtr(var,globalVarNumPtr)) { + *globalVarNumPtr = nextGlobalVarNum++; } - } else { - code.push(CodeOp::getTermOp(CHECK_VAR, *varNumPtr)); + globalCounterparts->push(*globalVarNumPtr); } + } else { + code.push(CodeOp::getTermOp(CHECK_VAR, *varNumPtr)); } } -template -void CodeTree::Compiler::handleSubterms(const Term* trm, Stack& globalCounterparts) +template +void CodeTree::Compiler::handleSubterms(const Term* trm, Stack& globalCounterparts) { SubtermIterator sti(trm); while (sti.hasNext()) { @@ -779,7 +767,6 @@ void CodeTree::Compiler::handleSubterms(const Term* trm, Sta template struct CodeTree::Compiler; template struct CodeTree::Compiler; -template struct CodeTree::Compiler; /** * Build CodeBlock object from the last @b cnt instructions on the @@ -816,10 +803,6 @@ void CodeTree::incorporate(CodeStack& code) { ASS(code.top().isSuccess()); - if (code.size() > _maxTreeDepth) { - _maxTreeDepth = code.size(); - } - if(isEmpty()) { _entryPoint=buildBlock(code, code.length(), 0); code.reset(); @@ -1176,7 +1159,6 @@ void CodeTree::RemovingMatcher::init(CodeOp* entry_, LitInfo* linfos_, matchingClauses=tree->_clauseCodeTree; bindings.ensure(tree->_maxVarCnt); - btStack.reserve(tree->_maxTreeDepth); btStack.reset(); curLInfo=0; @@ -1364,7 +1346,6 @@ void CodeTree::Matcher::init(CodeTree* tree_, CodeOp* entry_) curLInfo=0; btStack.reset(); bindings.ensure(tree->_maxVarCnt); - btStack.reserve(tree->_maxTreeDepth); } bool CodeTree::Matcher::execute() @@ -1383,7 +1364,7 @@ bool CodeTree::Matcher::execute() bool shouldBacktrack=false; for(;;) { if(op->alternative()) { - btStack.pushUnsafe(BTPoint(tp, op->alternative())); + btStack.push(BTPoint(tp, op->alternative())); } switch(op->_instruction()) { case SUCCESS_OR_FAIL: diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index d943bd2bf..0504484ba 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -60,8 +60,8 @@ class CodeTree public: CodeTree(); - virtual ~CodeTree(); - + ~CodeTree(); + struct LitInfo { LitInfo() {} @@ -202,7 +202,7 @@ class CodeTree return _data(); } - template inline T* getSuccessResult() const { ASS(isSuccess()); return _data(); } + template inline T* getSuccessResult() { ASS(isSuccess()); return _data(); } inline ILStruct* getILS() { ASS(isLitEnd()); return _data(); } inline const ILStruct* getILS() const { return _data(); } @@ -350,6 +350,7 @@ class CodeTree * a call to the @b prepareLiteral function). */ FlatTerm* ft; + }; //////// auxiliary methods ////////// @@ -367,7 +368,7 @@ class CodeTree typedef DHMap VarMap; - template + template struct Compiler { Compiler(CodeStack& code); @@ -384,7 +385,6 @@ class CodeTree unsigned nextGlobalVarNum; VarMap varMap; VarMap globalVarMap; - Stack> eqCons; }; using LitCompiler = Compiler; @@ -461,8 +461,7 @@ class CodeTree struct BTPoint { BTPoint() {} - BTPoint(size_t tp, CodeOp* op) - : tp(tp), op(op) {} + BTPoint(size_t tp, CodeOp* op) : tp(tp), op(op) {} /** Position in the flat term */ size_t tp; @@ -546,8 +545,6 @@ class CodeTree void incTimeStamp(); - virtual std::string leafToString(const CodeOp* success) const { return ""; } - //////// member variables ////////// @@ -556,7 +553,6 @@ class CodeTree /** maximal number of local variables in a stored term/literal (always at least 1) */ unsigned _maxVarCnt; - unsigned _maxTreeDepth; CodeBlock* _entryPoint; @@ -565,4 +561,3 @@ class CodeTree } #endif // __CodeTree__ - diff --git a/Indexing/TermCodeTree.hpp b/Indexing/TermCodeTree.hpp index d332ac88e..c61d63671 100644 --- a/Indexing/TermCodeTree.hpp +++ b/Indexing/TermCodeTree.hpp @@ -44,12 +44,6 @@ class TermCodeTree : public CodeTree protected: static void onCodeOpDestroying(CodeOp* op); - std::string leafToString(const CodeOp* success) const override { - std::stringstream str; - str << *success->getSuccessResult(); - return str.str(); - } - public: TermCodeTree(); diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index e56974b5f..668294210 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -102,14 +102,10 @@ struct BackwardDemodulation::ResultFn typedef DHMultiset ClauseSet; ResultFn(Clause* cl, BackwardDemodulation& parent, const DemodulationHelper& helper) - : _cl(cl), _helper(helper), _ordering(parent._salg->getOrdering()), _comps() + : _cl(cl), _helper(helper), _ordering(parent._salg->getOrdering()) { ASS_EQ(_cl->length(),1); _eqLit=(*_cl)[0]; - _comps.first = _ordering.createComparator(); - _comps.first->insert({ { *_eqLit->nthArgument(0), *_eqLit->nthArgument(1), Ordering::GREATER } }); - _comps.second = _ordering.createComparator(); - _comps.second->insert({ { *_eqLit->nthArgument(1), *_eqLit->nthArgument(0), Ordering::GREATER } }); _removed=SmartPtr(new ClauseSet()); } @@ -147,21 +143,9 @@ struct BackwardDemodulation::ResultFn TermList lhsS=qr.data->term; - auto& comp = lhs==*_eqLit->nthArgument(0) ? _comps.first : _comps.second; - if (!comp->check(&appl)) { -#if DEBUG_ORDERING - if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))==Ordering::GREATER) { - INVALID_OPERATION("backward check should be greater"); - } -#endif - return BwSimplificationRecord(0); - } -#if DEBUG_ORDERING if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { - INVALID_OPERATION("backward check not greater"); - // return BwSimplificationRecord(0); + return BwSimplificationRecord(0); } -#endif TermList rhsS=subs->applyToBoundQuery(rhs); @@ -208,8 +192,6 @@ struct BackwardDemodulation::ResultFn const DemodulationHelper& _helper; Ordering& _ordering; - - std::pair _comps; }; diff --git a/Inferences/Superposition.cpp b/Inferences/Superposition.cpp index 8b3587a3b..55de9b223 100644 --- a/Inferences/Superposition.cpp +++ b/Inferences/Superposition.cpp @@ -343,7 +343,7 @@ Clause* Superposition::performSuperposition( const auto& condRedHandler = _salg->condRedHandler(); if (!unifier->usesUwa()) { - if (!condRedHandler.checkSuperposition(eqClause, eqLit, eqLHS, rwClause, rwLit, rwTerm, eqIsResult, subst.ptr())) { + if (!condRedHandler.checkSuperposition(eqClause, eqLit, rwClause, rwLit, eqIsResult, subst.ptr())) { return 0; } } @@ -380,11 +380,8 @@ Clause* Superposition::performSuperposition( } if (!unifier->usesUwa()) { - if (!condRedHandler.insertSuperposition( - eqClause, rwClause, rwTermS, tgtTermS, eqLHS, rwLitS, eqLit, comp, eqIsResult, subst.ptr())) - { - return 0; - } + condRedHandler.insertSuperposition( + eqClause, rwClause, rwTermS, tgtTermS, eqLHS, rwLitS, eqLit, comp, eqIsResult, subst.ptr()); } Literal* tgtLitS = EqHelper::replace(rwLitS,rwTermS,tgtTermS); @@ -534,9 +531,5 @@ Clause* Superposition::performSuperposition( rwTerm )); - // if (rwTermS != *rwLitS->nthArgument(0) && rwTermS != *rwLitS->nthArgument(1) && comp == Ordering::INCOMPARABLE) { - // condRedHandler.initWithEquation(clause, rwTermS, tgtTermS); - // } - return clause; } diff --git a/Saturation/SaturationAlgorithm.cpp b/Saturation/SaturationAlgorithm.cpp index 0532d028b..e4197f31f 100644 --- a/Saturation/SaturationAlgorithm.cpp +++ b/Saturation/SaturationAlgorithm.cpp @@ -265,8 +265,6 @@ SaturationAlgorithm::~SaturationAlgorithm() { ASS_EQ(s_instance,this); - ConditionalRedundancyHandler::destroyAllClauseData(); - s_instance = 0; if (_splitter) { @@ -1281,12 +1279,6 @@ void SaturationAlgorithm::doOneAlgorithmStep() throw MainLoopFinishedException(res); } - // auto acl = _active->clauses(); - // while (acl.hasNext()) { - // auto cl = acl.next(); - // _conditionalRedundancyHandler->checkSubsumption(cl); - // } - Clause* cl = nullptr; { TIME_TRACE(TimeTrace::PASSIVE_CONTAINER_MAINTENANCE); @@ -1300,8 +1292,6 @@ void SaturationAlgorithm::doOneAlgorithmStep() } activate(cl); - - _conditionalRedundancyHandler->checkSubsumption(cl); } /** diff --git a/Saturation/Splitter.cpp b/Saturation/Splitter.cpp index 8f96ff159..933dfc042 100644 --- a/Saturation/Splitter.cpp +++ b/Saturation/Splitter.cpp @@ -835,7 +835,7 @@ void Splitter::onAllProcessed() // but would need to maintain them even when _deleteDeactivated == Options::SplittingDeleteDeactivated::ON if (allSplitLevelsActive(rcl->splits())) { RSTAT_CTR_INC("fast_clauses_restored"); - addNewClause(rcl); + _sa->addNewClause(rcl); } else { RSTAT_CTR_INC("fast_clauses_not_restored"); } @@ -1520,17 +1520,12 @@ bool Splitter::allSplitLevelsActive(SplitSet* s) return true; } -void Splitter::addNewClause(Clause* cl) +void Splitter::onNewClause(Clause* cl) { // when using AVATAR, we could have performed // generating inferences on the clause previously, // so we need to reset the data. ConditionalRedundancyHandler::destroyClauseData(cl); - _sa->addNewClause(cl); -} - -void Splitter::onNewClause(Clause* cl) -{ if (cl->inference().rule() == InferenceRule::AVATAR_ASSERTION_REINTRODUCTION) { // Do not assign splits from premises if cl originated by re-introducing AVATAR assertions (avoids looping) @@ -1680,7 +1675,7 @@ void Splitter::addComponents(const SplitLevelStack& toAdd) //we need to put the component clause among children, //so that it is backtracked when we remove the component sr->children.push(sr->component); - addNewClause(sr->component); + _sa->addNewClause(sr->component); } else { // children were kept, so we just put them back RCClauseStack::Iterator chit(sr->children); @@ -1688,7 +1683,7 @@ void Splitter::addComponents(const SplitLevelStack& toAdd) Clause* cl = chit.next(); cl->incNumActiveSplits(); if (cl->getNumActiveSplits() == (int)cl->splits()->size()) { - addNewClause(cl); + _sa->addNewClause(cl); //check that restored clause does not depend on inactive splits ASS(allSplitLevelsActive(cl->splits())); } @@ -1762,7 +1757,7 @@ void Splitter::removeComponents(const SplitLevelStack& toRemove) ASS_EQ(rcl->store(), Clause::NONE); rcl->invalidateMyReductionRecords(); // to make sure we don't unfreeze this clause a second time - addNewClause(rcl); + _sa->addNewClause(rcl); // TODO: keep statistics in release ? // RSTAT_MCTR_INC("unfrozen clauses",rcl->getFreezeCount()); diff --git a/Saturation/Splitter.hpp b/Saturation/Splitter.hpp index 379e82677..309bc98c0 100644 --- a/Saturation/Splitter.hpp +++ b/Saturation/Splitter.hpp @@ -186,7 +186,6 @@ class Splitter { void onClauseReduction(Clause* cl, ClauseIterator premises, Clause* replacement); void addConditionalRedundancyEntry(SplitSet* splits, ConditionalRedundancyEntry* e); - void addNewClause(Clause* cl); void onNewClause(Clause* cl); void onAllProcessed(); bool handleEmptyClause(Clause* cl); diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index bb3876524..e6e1e5f09 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -25,8 +25,6 @@ using namespace std; using namespace Indexing; -using Subsumption = OrderingComparator::Subsumption; - namespace Shell { @@ -51,21 +49,6 @@ bool checkVars(const TermStack& ts, T s) return true; } -std::ostream& operator<<(std::ostream& str, const ConditionalRedundancyEntry& e) -{ - if (!e.active) { - str << "not active"; - } else { - str << *e.splits << "; " << *e.lits << "; "; -#if DEBUG_ORDERING - iterTraits(e.ordCons.iter()).forEach([&str](const Ordering::Constraint& con) { - str << con; - }); -#endif - } - return str; -} - class ConditionalRedundancyHandler::ConstraintIndex : public CodeTree { @@ -79,25 +62,23 @@ class ConditionalRedundancyHandler::ConstraintIndex #endif for (unsigned i = 0; i < cl->length(); i++) { SortHelper::collectVariableSorts((*cl)[i], _varSorts); - _litSubs.push({ nullptr, nullptr }); - _litRedundant.push({ false, false }); } } - bool check(const Ordering* ord, ResultSubstitution* subst, bool result, const OrderingConstraints& ordCons, const LiteralSet* lits, const SplitSet* splits) + bool check(const Ordering* ord, ResultSubstitution* subst, bool result, const LiteralSet* lits, const SplitSet* splits) { if (_varSorts.isEmpty()) { return true; } auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - return !check(ts, ord, ordCons, lits, splits); + return !check(ts, ord, lits, splits); } - bool insert(const Ordering* ord, ResultSubstitution* subst, bool result, Splitter* splitter, + void insert(ResultSubstitution* subst, bool result, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) { auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + insert(ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } bool checkAndInsert(const Ordering* ord, ResultSubstitution* subst, bool result, bool doInsert, Splitter* splitter, @@ -109,43 +90,24 @@ class ConditionalRedundancyHandler::ConstraintIndex return true; } auto ts = getInstances([subst,result](unsigned v) { return subst->applyTo(TermList::var(v),result); }); - if (check(ts, ord, ordCons, lits, splits)) { + if (check(ts, ord, lits, splits)) { return false; } if (doInsert) { - return insert(ord, ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); + insert(ts, createEntry(ts, splitter, std::move(ordCons), lits, splits)); } return true; } +private: #if VDEBUG Clause* _cl; #endif - bool insert(const Ordering* ord, Entries* entries, ConditionalRedundancyEntry* ptr) - { - ASS(ptr->active); - - ASS(entries->comparator); - -#if DEBUG_ORDERING - // we push subsumed ones as well to check subsumption - entries->comps.push(ptr); -#endif - - entries->comparator->insert(ptr->ordCons); - return true; - } - - bool insert(const Ordering* ord, const TermStack& ts, ConditionalRedundancyEntry* ptr) + void insert(const TermStack& ts, ConditionalRedundancyEntry* ptr) { CodeStack code; -#define LINEARIZE 1 -#if LINEARIZE - Compiler compiler(code); -#else TermCompiler compiler(code); -#endif for (const auto& t : ts) { if (t.isVar()) { compiler.handleVar(t.var()); @@ -154,42 +116,14 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(t.isTerm()); compiler.handleTerm(t.term()); } - for (const auto& [x,y] : compiler.eqCons) { - ptr->ordCons.push({ TermList::var(x), TermList::var(y), Ordering::EQUAL }); - } compiler.updateCodeTree(this); - auto es = new Entries(); -#if DEBUG_ORDERING - es->comps.push(ptr); -#endif - es->comparator = ord->createComparator(); - es->comparator->insert(ptr->ordCons); - code.push(CodeOp::getSuccess(es)); - -#if LINEARIZE - if (!isEmpty()) { - VariantMatcher vm; - Stack firstsInBlocks; - - FlatTerm* ft = FlatTerm::createUnexpanded(ts); - vm.init(ft, this, &firstsInBlocks); - - if (vm.next()) { - ASS(vm.op->isSuccess()); - auto es = vm.op->template getSuccessResult(); - ft->destroy(); - return insert(ord, es, ptr); - } - ft->destroy(); - } -#endif - + // just put anything non-null in there to get a valid success + code.push(CodeOp::getSuccess(ptr)); incorporate(code); - return true; } - bool check(const TermStack& ts, const Ordering* ord, const OrderingConstraints& ordCons, const LiteralSet* lits, const SplitSet* splits) + bool check(const TermStack& ts, const Ordering* ord, const LiteralSet* lits, const SplitSet* splits) { if (isEmpty()) { return false; @@ -201,30 +135,49 @@ class ConditionalRedundancyHandler::ConstraintIndex } applicator; matcher.init(this, ts); - Entries* es; - while ((es = matcher.next())) + ConditionalRedundancyEntry* e; + while ((e = matcher.next())) { - ASS(es->comparator); - auto res = es->comparator->check(&applicator); -#if DEBUG_ORDERING - auto ordCons_crosscheck = iterTraits(es->comps.iter()).any([ord,&applicator](auto e) { - return iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { - return ord->compare(AppliedTerm(ordCon.lhs,&applicator,true),AppliedTerm(ordCon.rhs,&applicator,true))==ordCon.rel; - }); + if (!e->active) { + continue; + } + + // check AVATAR constraints + if (!e->splits->isSubsetOf(splits)) { + continue; + } + + // check literal conditions + auto subsetof = e->lits->iter().all([lits,&applicator](Literal* lit) { + return lits->member(SubstHelper::apply(lit,applicator)); }); - if (res != ordCons_crosscheck) { - cout << res << " " << ordCons_crosscheck << endl; - cout << *es->comparator << endl; - for (const auto& e : es->comps) { - cout << *e << endl; + if (!subsetof) { + continue; + } + + // check ordering constraints + auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { + if (!ordCon.comp) { + ordCon.comp = ord->createComparator(); + ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }); } - INVALID_OPERATION("conditional redundancy ordering check mismatch"); + return ordCon.comp->check(&applicator); + }); + if (!ordCons_ok) { + continue; } -#endif - if (res) { - matcher.reset(); - return true; + + // collect statistics + if (e->ordCons.isNonEmpty()) { + env.statistics->skippedInferencesDueToOrderingConstraints++; + } + if (!e->lits->isEmpty()) { + env.statistics->skippedInferencesDueToLiteralConstraints++; + } + if (!e->splits->isEmpty()) { + env.statistics->skippedInferencesDueToAvatarConstraints++; } + return true; } matcher.reset(); @@ -244,10 +197,6 @@ class ConditionalRedundancyHandler::ConstraintIndex } DHMap _varSorts; - Subsumption* _subs = nullptr; - bool _redundant = false; - Stack> _litSubs; - Stack> _litRedundant; ConditionalRedundancyEntry* createEntry(const TermStack& ts, Splitter* splitter, OrderingConstraints&& ordCons, const LiteralSet* lits, SplitSet* splits) const { @@ -262,6 +211,7 @@ class ConditionalRedundancyHandler::ConstraintIndex } for (auto& ordCon : ordCons) { + ASS(!ordCon.comp); ASS(checkVars(ts,ordCon.lhs)); ASS(checkVars(ts,ordCon.rhs)); ASS(ordCon.lhs.containsAllVariablesOf(ordCon.rhs)); @@ -275,7 +225,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ASS(checkVars(ts,lit)); }); #endif - + e->lits = LiteralSet::getFromIterator(lits->iter().map([&r](Literal* lit) { return r.apply(lit); })); @@ -308,7 +258,7 @@ class ConditionalRedundancyHandler::ConstraintIndex ft->destroy(); } - Entries* next() + ConditionalRedundancyEntry* next() { if (finished()) { //all possible matches are exhausted @@ -321,39 +271,15 @@ class ConditionalRedundancyHandler::ConstraintIndex } ASS(op->isSuccess()); - return op->getSuccessResult(); - } - }; - - struct VariantMatcher - : public RemovingMatcher - { - public: - void init(FlatTerm* ft_, CodeTree* tree_, Stack* firstsInBlocks_) { - RemovingMatcher::init(tree_->getEntryPoint(), 0, 0, tree_, firstsInBlocks_); - ft=ft_; - tp=0; - op=entry; + return op->getSuccessResult(); } }; static void onCodeOpDestroying(CodeOp* op) { if (op->isSuccess()) { - auto es = op->getSuccessResult(); -#if DEBUG_ORDERING - iterTraits(decltype(es->comps)::Iterator(es->comps)).forEach([](ConditionalRedundancyEntry* e) { delete e; }); -#endif - delete es; + op->getSuccessResult()->release(); } } - - std::string leafToString(const CodeOp* op) const override { - std::stringstream str; - ASS(op->isSuccess()); - auto es = op->getSuccessResult(); - str << *es->comparator; - return str.str(); - } }; // ConditionalRedundancyHandler @@ -398,13 +324,22 @@ void ConditionalRedundancyHandler::destroyClauseData(Clause* cl) delete ptr; } -void ConditionalRedundancyHandler::destroyAllClauseData() +void ConditionalRedundancyHandler::checkEquations(Clause* cl) const { - decltype(clauseData)::Iterator it(clauseData); - while (it.hasNext()) { - auto data = it.next(); - delete data; - } + cl->iterLits().forEach([cl](Literal* lit){ + if (!lit->isEquality() || lit->isNegative()) { + return; + } + auto t0 = lit->termArg(0); + auto t1 = lit->termArg(1); + RobSubstitution subs; + if (!subs.unify(t0,0,t1,0)) { + return; + } + auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); + auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); + (*clDataPtr)->insert(rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); + }); } ConditionalRedundancyHandler::ConstraintIndex** ConditionalRedundancyHandler::getDataPtr(Clause* cl, bool doAllocate) @@ -420,69 +355,19 @@ ConditionalRedundancyHandler::ConstraintIndex** ConditionalRedundancyHandler::ge return ptr; } -void ConditionalRedundancyHandler::transfer(Clause* from, Clause* to) -{ - ConstraintIndex* ptr = nullptr; - clauseData.pop(from, ptr); - if (!ptr) { - return; - } - ALWAYS(clauseData.insert(to, ptr)); -} - DHMap ConditionalRedundancyHandler::clauseData; // ConditionalRedundancyHandlerImpl template bool ConditionalRedundancyHandlerImpl::checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, Clause* rwClause, Literal* rwLit, TermList rwTerm, + Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const { if constexpr (!enabled) { return true; } - auto eqClDataPtr = getDataPtr(eqClause, /*doAllocate=*/false); - if (eqClDataPtr) { - if ((*eqClDataPtr)->_redundant) { - env.statistics->skippedSuperposition++; - return false; - } - auto i = eqClause->getLiteralPosition(eqLit); - if (eqLHS == eqLit->termArg(0) && (*eqClDataPtr)->_litRedundant[i].first) { - env.statistics->skippedSuperposition++; - return false; - } - if (eqLHS == eqLit->termArg(1) && (*eqClDataPtr)->_litRedundant[i].second) { - env.statistics->skippedSuperposition++; - return false; - } - } - - auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); - if (rwClDataPtr) { - if ((*rwClDataPtr)->_redundant) { - env.statistics->skippedSuperposition++; - return false; - } - auto i = rwClause->getLiteralPosition(rwLit); - auto leftred = (*rwClDataPtr)->_litRedundant[i].first; - auto rightred = (*rwClDataPtr)->_litRedundant[i].second; - if (leftred && rightred) { - env.statistics->skippedSuperposition++; - return false; - } - if (leftred && !rwLit->termArg(1).containsSubterm(rwTerm)) { - env.statistics->skippedSuperposition++; - return false; - } - if (rightred && !rwLit->termArg(0).containsSubterm(rwTerm)) { - env.statistics->skippedSuperposition++; - return false; - } - } - auto rwLits = LiteralSet::getEmpty(); if constexpr (litC) { rwLits = LiteralSet::getFromIterator(rwClause->iterLits().filter([rwLit](Literal* lit) { @@ -497,7 +382,8 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp rwSplits = rwClause->splits(); } - if (eqClDataPtr && !(*eqClDataPtr)->check(_ord, subs, eqIsResult, OrderingConstraints(), rwLits, rwSplits)) { + auto eqClDataPtr = getDataPtr(eqClause, /*doAllocate=*/false); + if (eqClDataPtr && !(*eqClDataPtr)->check(_ord, subs, eqIsResult, rwLits, rwSplits)) { env.statistics->skippedSuperposition++; return false; } @@ -516,7 +402,8 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp eqSplits = eqClause->splits(); } - if (rwClDataPtr && !(*rwClDataPtr)->check(_ord, subs, !eqIsResult, OrderingConstraints(), eqLits, eqSplits)) { + auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/false); + if (rwClDataPtr && !(*rwClDataPtr)->check(_ord, subs, !eqIsResult, eqLits, eqSplits)) { env.statistics->skippedSuperposition++; return false; } @@ -525,12 +412,12 @@ bool ConditionalRedundancyHandlerImpl::checkSuperp } template -bool ConditionalRedundancyHandlerImpl::insertSuperposition( +void ConditionalRedundancyHandlerImpl::insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const { if constexpr (!enabled) { - return true; + return; } struct Applicator : SubstApplicator { @@ -553,21 +440,20 @@ bool ConditionalRedundancyHandlerImpl::insertSuper if constexpr (ordC) { // TODO we cannot handle them together yet if (eqComp != Ordering::LESS) { - if (!rwTermS.containsAllVariablesOf(tgtTermS)) { - return true; + if (!premiseRedundant || !rwTermS.containsAllVariablesOf(tgtTermS)) { + return; } - ordCons.push({ rwTermS, tgtTermS, Ordering::GREATER }); - } - if (!premiseRedundant) { + ordCons.push(OrderingConstraint(rwTermS, tgtTermS)); + } else if (!premiseRedundant) { TermList other = EqHelper::getOtherEqualitySide(rwLitS, rwTermS); if (otherComp != Ordering::INCOMPARABLE || !other.containsAllVariablesOf(tgtTermS)) { - return true; + return; } - ordCons.push({ other, tgtTermS, Ordering::GREATER }); + ordCons.push(OrderingConstraint(other, tgtTermS)); } } else { if (eqComp != Ordering::LESS || !premiseRedundant) { - return true; + return; } } @@ -575,7 +461,7 @@ bool ConditionalRedundancyHandlerImpl::insertSuper auto lits = LiteralSet::getEmpty(); if constexpr (litC) { if (eqClause->numSelected()!=1) { - return true; + return; } lits = LiteralSet::getFromIterator(eqClause->iterLits().filter([eqLit,eqLHS](Literal* lit) { return lit != eqLit && eqLHS.containsAllVariablesOf(TermList(lit)); @@ -583,11 +469,11 @@ bool ConditionalRedundancyHandlerImpl::insertSuper return subs->applyTo(lit,eqIsResult); })); if (eqClause->size()>lits->size()+1) { - return true; + return; } } else { if (eqClause->length()!=1) { - return true; + return; } } @@ -597,16 +483,12 @@ bool ConditionalRedundancyHandlerImpl::insertSuper splits = eqClause->splits()->subtract(rwClause->splits()); } else { if (!eqClause->noSplits()) { - return true; + return; } } auto rwClDataPtr = getDataPtr(rwClause, /*doAllocate=*/true); - if (!(*rwClDataPtr)->insert(_ord, subs, !eqIsResult, _splitter, std::move(ordCons), lits, splits)) { - env.statistics->skippedSuperposition++; - return false; - } - return true; + (*rwClDataPtr)->insert(subs, !eqIsResult, _splitter, std::move(ordCons), lits, splits); } template @@ -725,8 +607,6 @@ bool ConditionalRedundancyHandlerImpl::isSuperposi Clause* rwCl, Literal* rwLit, TermList rwTerm, TermList tgtTerm, Clause* eqCl, TermList eqLHS, const SubstApplicator* eqApplicator, Ordering::Result& tord) const { - ASS(enabled); - // if check is turned off, we always report redundant if (!_redundancyCheck) { return true; @@ -757,128 +637,4 @@ bool ConditionalRedundancyHandlerImpl::isSuperposi // TODO perform ordering check for rest of rwCl } -template -void ConditionalRedundancyHandlerImpl::initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const -{ - if (!enabled) { - return; - } - - if (!ordC) { - return; - } - - if (!tgtTerm.containsAllVariablesOf(rwTerm)) { - return; - } - OrderingConstraints ordCons; - ordCons.push({ tgtTerm, rwTerm, Ordering::GREATER }); - auto lits = LiteralSet::getEmpty(); - auto splits = SplitSet::getEmpty(); - - struct RenamingSubstitution : public ResultSubstitution { - TermList applyTo(TermList t, unsigned index) override { return t; } - void output(std::ostream&) const override {} - } subst; - - auto clDataPtr = getDataPtr(resClause, /*doAllocate=*/true); - (*clDataPtr)->insert(_ord, &subst, true, _splitter, std::move(ordCons), lits, splits); -} - -template -void ConditionalRedundancyHandlerImpl::checkEquations(Clause* cl) const -{ - if (!enabled) { - return; - } - - // TODO return if not enabled - cl->iterLits().forEach([cl,this](Literal* lit){ - if (!lit->isEquality() || lit->isNegative()) { - return; - } - auto t0 = lit->termArg(0); - auto t1 = lit->termArg(1); - RobSubstitution subs; - if (!subs.unify(t0,0,t1,0)) { - return; - } - auto clDataPtr = getDataPtr(cl, /*doAllocate=*/true); - auto rsubs = ResultSubstitution::fromSubstitution(&subs, 0, 0); - (*clDataPtr)->insert(_ord, rsubs.ptr(), /*result*/false, /*splitter*/nullptr, OrderingConstraints(), LiteralSet::getEmpty(), SplitSet::getEmpty()); - }); -} - -template -void ConditionalRedundancyHandlerImpl::checkSubsumption(Clause* cl) const -{ - if (!enabled) { - return; - } - - auto clDataPtr = getDataPtr(cl, /*doAllocate=*/false); - if (!clDataPtr) { - return; - } - auto cld = *clDataPtr; - - if (cld->_redundant || cld->isEmpty()) { - return; - } - - if (!cld->_subs) { - auto ts = cld->getInstances([](unsigned v) { return TermList::var(v); }); - static ConstraintIndex::SubstMatcher matcher; - matcher.init((*clDataPtr), ts); - Entries* es = matcher.next(); - matcher.reset(); - // there can be only one such matching under linearization -#if !LINEARIZE - static_assert(false); -#endif - if (!es) { - // in this case we try to create the subsumption next time - return; - } - ASS(es->comparator); - - cld->_subs = new Subsumption(*es->comparator.get(), *_ord, OrderingConstraints(), /*ground=*/true); - for (unsigned i = 0; i < cl->numSelected(); i++) { - auto lit = (*cl)[i]; - if (!lit->isEquality() || _ord->getEqualityArgumentOrder(lit)!=Ordering::INCOMPARABLE) { - continue; - } - - auto& [subsLtr, subsRtl] = cld->_litSubs[i]; - ASS(!subsLtr && !subsRtl); - Renaming r; - for (const auto t : ts) { - r.normalizeVariables(t); - } - auto lhs = r.apply(lit->termArg(0)); - auto rhs = r.apply(lit->termArg(1)); - subsLtr = new Subsumption(*es->comparator.get(), *_ord, { { lhs, rhs, Ordering::GREATER } }, /*ground=*/true); - subsRtl = new Subsumption(*es->comparator.get(), *_ord, { { rhs, lhs, Ordering::GREATER } }, /*ground=*/true); - } - } - if (cld->_subs->check()) { - cld->_redundant = true; - env.statistics->groundRedundantClauses++; - return; - } - - for (unsigned i = 0; i < cl->numSelected(); i++) { - auto& [subsLtr, subsRtl] = cld->_litSubs[i]; - auto& [redLtr, redRtl] = cld->_litRedundant[i]; - if (!redLtr && subsLtr && subsLtr->check()) { - redLtr = true; - env.statistics->groundRedundantEquationOrientations++; - } - if (!redRtl && subsRtl && subsRtl->check()) { - redRtl = true; - env.statistics->groundRedundantEquationOrientations++; - } - } -} - } diff --git a/Shell/ConditionalRedundancyHandler.hpp b/Shell/ConditionalRedundancyHandler.hpp index d7e61d384..3e9b06a4a 100644 --- a/Shell/ConditionalRedundancyHandler.hpp +++ b/Shell/ConditionalRedundancyHandler.hpp @@ -56,11 +56,18 @@ namespace Shell { using namespace Lib; using namespace Indexing; -using OrderingConstraints = Stack; using LiteralSet = SharedSet; -struct ConditionalRedundancyEntry -{ +struct OrderingConstraint { + OrderingConstraint(TermList lhs, TermList rhs) : lhs(lhs), rhs(rhs), comp() {} + TermList lhs; + TermList rhs; + OrderingComparatorUP comp; +}; + +using OrderingConstraints = Stack; + +struct ConditionalRedundancyEntry { OrderingConstraints ordCons; const LiteralSet* lits; SplitSet* splits; @@ -85,28 +92,18 @@ struct ConditionalRedundancyEntry } }; -struct Entries { -#if DEBUG_ORDERING - Stack comps; -#endif - OrderingComparatorUP comparator; -}; - class ConditionalRedundancyHandler { public: static ConditionalRedundancyHandler* create(const Options& opts, const Ordering* ord, Splitter* splitter); static void destroyClauseData(Clause* cl); - static void destroyAllClauseData(); virtual ~ConditionalRedundancyHandler() = default; virtual bool checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, - Clause* rwClause, Literal* rwLit, TermList rwTerm, - bool eqIsResult, ResultSubstitution* subs) const = 0; + Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const = 0; - virtual bool insertSuperposition( + virtual void insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const = 0; @@ -115,13 +112,7 @@ class ConditionalRedundancyHandler virtual bool handleReductiveUnaryInference(Clause* premise, RobSubstitution* subs) const = 0; - virtual void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const = 0; - - virtual void checkEquations(Clause* cl) const = 0; - - virtual void checkSubsumption(Clause* cl) const = 0; - - static void transfer(Clause* from, Clause* to); + void checkEquations(Clause* cl) const; protected: class ConstraintIndex; @@ -140,15 +131,13 @@ class ConditionalRedundancyHandlerImpl ConditionalRedundancyHandlerImpl(const Options& opts, const Ordering* ord, Splitter* splitter) : _redundancyCheck(opts.demodulationRedundancyCheck() != Options::DemodulationRedundancyCheck::OFF), _encompassing(opts.demodulationRedundancyCheck() == Options::DemodulationRedundancyCheck::ENCOMPASS), - _splitter(splitter), _ord(ord) {} + _ord(ord), _splitter(splitter) {} /** Returns false if superposition should be skipped. */ bool checkSuperposition( - Clause* eqClause, Literal* eqLit, TermList eqLHS, - Clause* rwClause, Literal* rwLit, TermList rwTerm, - bool eqIsResult, ResultSubstitution* subs) const override; + Clause* eqClause, Literal* eqLit, Clause* rwClause, Literal* rwLit, bool eqIsResult, ResultSubstitution* subs) const override; - bool insertSuperposition( + void insertSuperposition( Clause* eqClause, Clause* rwClause, TermList rwTermS, TermList tgtTermS, TermList eqLHS, Literal* rwLitS, Literal* eqLit, Ordering::Result eqComp, bool eqIsResult, ResultSubstitution* subs) const override; @@ -163,17 +152,11 @@ class ConditionalRedundancyHandlerImpl Clause* rwCl, Literal* rwLit, TermList rwTerm, TermList tgtTerm, Clause* eqCl, TermList eqLHS, const SubstApplicator* eqApplicator, Ordering::Result& tord) const; - void initWithEquation(Clause* resClause, TermList rwTerm, TermList tgtTerm) const override; - - void checkEquations(Clause* cl) const override; - - void checkSubsumption(Clause* cl) const override; - private: bool _redundancyCheck; bool _encompassing; - Splitter* _splitter; const Ordering* _ord; + Splitter* _splitter; }; }; From 5e502843b1a117365965be0ae034ba99cb38d2c5 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 4 Dec 2024 20:01:36 +0100 Subject: [PATCH 50/64] Clean up branch more --- Indexing/CodeTree.hpp | 1 + Indexing/Index.hpp | 2 +- Indexing/TermCodeTree.cpp | 2 +- Indexing/TermCodeTree.hpp | 2 +- Inferences/ForwardDemodulation.cpp | 2 +- Kernel/FlatTerm.cpp | 45 +++++++++++++++++++++++------- Kernel/FlatTerm.hpp | 1 + Lib/Stack.hpp | 8 ------ Shell/Statistics.cpp | 5 ---- Shell/Statistics.hpp | 2 -- 10 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Indexing/CodeTree.hpp b/Indexing/CodeTree.hpp index 0504484ba..35086fc5a 100644 --- a/Indexing/CodeTree.hpp +++ b/Indexing/CodeTree.hpp @@ -561,3 +561,4 @@ class CodeTree } #endif // __CodeTree__ + diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index 75ef7a45e..bde0ef2c5 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -207,4 +207,4 @@ class Index }; }; -#endif /*__Indexing_Index__*/ \ No newline at end of file +#endif /*__Indexing_Index__*/ diff --git a/Indexing/TermCodeTree.cpp b/Indexing/TermCodeTree.cpp index c8b5c5168..dea8ad9c8 100644 --- a/Indexing/TermCodeTree.cpp +++ b/Indexing/TermCodeTree.cpp @@ -192,4 +192,4 @@ Data* TermCodeTree::TermMatcher::next() template class TermCodeTree; template class TermCodeTree; -}; \ No newline at end of file +}; diff --git a/Indexing/TermCodeTree.hpp b/Indexing/TermCodeTree.hpp index c61d63671..62e7ccf32 100644 --- a/Indexing/TermCodeTree.hpp +++ b/Indexing/TermCodeTree.hpp @@ -43,7 +43,7 @@ class TermCodeTree : public CodeTree { protected: static void onCodeOpDestroying(CodeOp* op); - + public: TermCodeTree(); diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 550037451..d51d60b44 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -249,4 +249,4 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* template class ForwardDemodulationImpl; template class ForwardDemodulationImpl; -} \ No newline at end of file +} diff --git a/Kernel/FlatTerm.cpp b/Kernel/FlatTerm.cpp index a29d7a23b..53d089c43 100644 --- a/Kernel/FlatTerm.cpp +++ b/Kernel/FlatTerm.cpp @@ -33,14 +33,11 @@ using namespace Lib; */ void* FlatTerm::operator new(size_t sz,unsigned num) { - ASS_GE(num,0); + ASS_GE(num,1); ASS_EQ(sz, sizeof(FlatTerm)); //one entry is already accounted for in the size of the FlatTerm object - size_t size = sizeof(FlatTerm); - if (num > 0) { - size += (num-1)*sizeof(Entry); - } + size_t size=sizeof(FlatTerm)+(num-1)*sizeof(Entry); return ALLOC_KNOWN(size,"FlatTerm"); } @@ -50,13 +47,10 @@ void* FlatTerm::operator new(size_t sz,unsigned num) */ void FlatTerm::destroy() { - ASS_GE(_length,0); + ASS_GE(_length,1); //one entry is already accounted for in the size of the FlatTerm object - size_t size = sizeof(FlatTerm); - if (_length > 0) { - size += (_length-1)*sizeof(Entry); - } + size_t size=sizeof(FlatTerm)+(_length-1)*sizeof(Entry); DEALLOC_KNOWN(this, size,"FlatTerm"); } @@ -137,6 +131,37 @@ FlatTerm* FlatTerm::create(TermList t) return res; } +FlatTerm* FlatTerm::create(TermStack ts) +{ + size_t entries=0; + for (auto& tl : ts) { + entries += tl.isVar() ? 1 : getEntryCount(tl.term()); + } + + FlatTerm* res=new(entries) FlatTerm(entries); + size_t fti=0; + + for (auto& tl : ts) { + if (tl.isVar()) { + pushVar(res, fti, tl.var()); + continue; + } + auto t = tl.term(); + (*res)[fti++]=Entry(FUN, + t->isLiteral() ? static_cast(t)->header() : t->functor()); + (*res)[fti++]=Entry(t); + (*res)[fti++]=Entry(FUN_RIGHT_OFS, getEntryCount(t)); + + SubtermIterator sti(t); + while(sti.hasNext()) { + pushTermList(res, fti, sti.next()); + } + } + ASS_EQ(fti, entries); + + return res; +} + FlatTerm* FlatTerm::createUnexpanded(Term* t) { size_t entries=getEntryCount(t); diff --git a/Kernel/FlatTerm.hpp b/Kernel/FlatTerm.hpp index 8efb41e6b..a42a4771e 100644 --- a/Kernel/FlatTerm.hpp +++ b/Kernel/FlatTerm.hpp @@ -26,6 +26,7 @@ class FlatTerm public: static FlatTerm* create(Term* t); static FlatTerm* create(TermList t); + static FlatTerm* create(TermStack ts); /** * Similar to @b create but only allocates the flat term, * and does not fill out its content. The caller has to diff --git a/Lib/Stack.hpp b/Lib/Stack.hpp index 6b47d95c7..cecb76d82 100644 --- a/Lib/Stack.hpp +++ b/Lib/Stack.hpp @@ -330,14 +330,6 @@ class Stack _cursor++; } // Stack::push() - inline - void pushUnsafe(C elem) - { - ASS(_cursor < _end); - ::new(_cursor) C(std::move(elem)); - _cursor++; - } // Stack::push() - /** * Pop the stack and return the popped element. * @since 11/03/2006 Bellevue diff --git a/Shell/Statistics.cpp b/Shell/Statistics.cpp index a1a148a88..ebc53761f 100644 --- a/Shell/Statistics.cpp +++ b/Shell/Statistics.cpp @@ -130,8 +130,6 @@ Statistics::Statistics() condensations(0), globalSubsumption(0), interpretedSimplifications(0), - groundRedundantClauses(0), - groundRedundantEquationOrientations(0), asgViolations(0), asgCnt(0), @@ -312,7 +310,6 @@ void Statistics::print(ostream& out) +( evaluationCnt - evaluationIncomp - evaluationGreater) +innerRewrites +booleanSimps - +groundRedundantClauses+groundRedundantEquationOrientations ); COND_OUT("Duplicate literals", duplicateLiterals); COND_OUT("Trivial inequalities", trivialInequalities); @@ -327,8 +324,6 @@ void Statistics::print(ostream& out) COND_OUT("Condensations", condensations); COND_OUT("Global subsumptions", globalSubsumption); COND_OUT("Interpreted simplifications", interpretedSimplifications); - COND_OUT("Ground redundant clauses", groundRedundantClauses); - COND_OUT("Ground redundant eq. orientations", groundRedundantEquationOrientations); COND_OUT("asg count", asgCnt); COND_OUT("asg results not smaller than the premis", asgViolations); diff --git a/Shell/Statistics.hpp b/Shell/Statistics.hpp index 429bac706..1530748f2 100644 --- a/Shell/Statistics.hpp +++ b/Shell/Statistics.hpp @@ -192,8 +192,6 @@ class Statistics { unsigned globalSubsumption; /** number of interpreted simplifications */ unsigned interpretedSimplifications; - unsigned groundRedundantClauses; - unsigned groundRedundantEquationOrientations; /** how often did asg not simplify correctly. */ unsigned asgViolations; From 0ece61aff1ee2804140120ad61b6ef2449f54502 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Thu, 5 Dec 2024 10:49:20 +0100 Subject: [PATCH 51/64] Remove OrderingComparator::Subsumption --- Kernel/OrderingComparator.cpp | 119 ---------------------------------- Kernel/OrderingComparator.hpp | 14 ---- 2 files changed, 133 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index fce945829..685c04ebe 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -531,125 +531,6 @@ const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() ASSERTION_VIOLATION; } -OrderingComparator::Subsumption::Subsumption(OrderingComparator& subsumer, const Ordering& ord, const OrderingConstraints& ordCons, bool ground) - : subsumer(subsumer), subsumed(ord.createComparator()), ground(ground) -{ - subsumed->insert(ordCons); - path.push({ &subsumer._source, nullptr, &subsumed->_source }); -} - -#define SUBSUMPTION_MAX_ITERATIONS 500 - -bool OrderingComparator::Subsumption::check() -{ - unsigned cnt = 0; - while (path.isNonEmpty()) { - if (cnt++ > SUBSUMPTION_MAX_ITERATIONS) { - return false; - } - - if (path.size()==1) { - subsumer._prev = nullptr; - } else { - subsumer._prev = get<0>(path[path.size()-2]); - } - subsumer._curr = get<0>(path.top()); - subsumer.expand(); - - auto lnode = subsumer._curr->node(); - if (lnode->tag == BranchTag::T_RESULT && lnode->result) { - pushNext(); - continue; - } - - auto trace = lnode->trace ? lnode->trace : subsumer.getCurrentTrace(); - if (!trace || (ground && trace->hasIncomp())) { - pushNext(); - continue; - } - - subsumed->_prev = get<1>(path.top()); - subsumed->_curr = get<2>(path.top()); - subsumed->expand(); - auto rnode = subsumed->_curr->node(); - - switch (rnode->tag) { - case BranchTag::T_POLY: { - if (lnode->tag == BranchTag::T_RESULT) { - return false; - } - path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); - break; - } - case BranchTag::T_RESULT: { - if (rnode->result) { - if (lnode->tag == BranchTag::T_RESULT) { - return false; - } - path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); - } else { - pushNext(); - } - break; - } - case BranchTag::T_TERM: { - auto lhs = rnode->lhs; - auto rhs = rnode->rhs; - Ordering::Result val; - if (!trace->get(lhs, rhs, val)) { - if (lnode->tag == BranchTag::T_RESULT) { - return false; - } - path.push({ &lnode->gtBranch, subsumed->_prev, subsumed->_curr }); - } else { - switch (val) { - case Ordering::GREATER: { - path.top() = { subsumer._curr, subsumed->_curr, &rnode->gtBranch }; - break; - } - case Ordering::EQUAL: { - path.top() = { subsumer._curr, subsumed->_curr, &rnode->eqBranch }; - break; - } - default: { - path.top() = { subsumer._curr, subsumed->_curr, &rnode->ngeBranch }; - break; - } - } - } - break; - } - } - } - - ASS(path.isEmpty()); - return true; -} - -void OrderingComparator::Subsumption::pushNext() -{ - while (path.isNonEmpty()) { - auto curr = get<0>(path.pop()); - if (path.isEmpty()) { - continue; - } - - auto prevE = path.top(); - auto prev = get<0>(prevE)->node(); - ASS(prev->tag == BranchTag::T_POLY || prev->tag == BranchTag::T_TERM); - // if there is a previous node and we were either in the gt or eq - // branches, just go to next branch in order, otherwise backtrack - if (curr == &prev->gtBranch) { - path.push({ &prev->eqBranch, get<1>(prevE), get<2>(prevE) }); - break; - } - if (curr == &prev->eqBranch) { - path.push({ &prev->ngeBranch, get<1>(prevE), get<2>(prevE) }); - break; - } - } -} - OrderingComparator::Branch::~Branch() { setNode(nullptr); diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 13c831d87..f79bcf2a6 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -44,20 +44,6 @@ struct OrderingComparator friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); std::string to_dot() const; - class Subsumption { - public: - Subsumption(OrderingComparator& subsumer, const Ordering& ord, const OrderingConstraints& comps, bool ground); - bool check(); - - private: - void pushNext(); - - OrderingComparator& subsumer; - OrderingComparatorUP subsumed; - Stack> path; - bool ground; - }; - protected: void expand(); virtual void expandTermCase(); From 2ce858541d4a95e94c4aa940a4d05a4ba30c2a73 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 6 Dec 2024 13:32:23 +0100 Subject: [PATCH 52/64] Perfectly share polynomials in OrderingComparator --- Kernel/KBOComparator.cpp | 10 +-- Kernel/OrderingComparator.cpp | 157 ++++++++++++++++++++++++---------- Kernel/OrderingComparator.hpp | 20 ++++- 3 files changed, 129 insertions(+), 58 deletions(-) diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index 6a1504a34..c9b82429e 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -36,13 +36,13 @@ void KBOComparator::expandTermCase() #endif auto w = state->_weightDiff; decltype(state->_varDiffs)::Iterator vit(state->_varDiffs); - ScopedPtr nonzeros(new Stack()); + Stack nonzeros; while (vit.hasNext()) { unsigned v; int cnt; vit.next(v,cnt); if (cnt!=0) { - nonzeros->push(make_pair(v,cnt)); + nonzeros.push({ v, cnt }); w-=cnt; // we have to remove the variable weights from w } if (cnt<0) { @@ -66,13 +66,9 @@ void KBOComparator::expandTermCase() auto curr = _curr; bool weightAdded = (w < 0 || varInbalance); if (weightAdded) { - sort(nonzeros->begin(),nonzeros->end(),[](const auto& e1, const auto& e2) { - return e1.second>e2.second; - }); // we mutate the original node curr->node()->tag = T_POLY; - curr->node()->w = w; - curr->node()->varCoeffPairs = nonzeros.release(); + curr->node()->poly = Polynomial::get(w, nonzeros); curr->node()->gtBranch = gtBranch; curr->node()->ngeBranch = ngeBranch; curr = &curr->node()->eqBranch; diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 685c04ebe..fc729fb77 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -30,13 +30,13 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& { switch (t) { case OrderingComparator::BranchTag::T_RESULT: - out << "res"; + out << "r"; break; case OrderingComparator::BranchTag::T_TERM: - out << "term"; + out << "t"; break; case OrderingComparator::BranchTag::T_POLY: - out << "poly"; + out << "p"; break; } return out; @@ -51,19 +51,7 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node break; } case OrderingComparator::BranchTag::T_POLY: { - out << node.w; - for (unsigned i = 0; i < node.varCoeffPairs->size(); i++) { - const auto& [var, coeff] = (*node.varCoeffPairs)[i]; - ASS_NEQ(coeff,0); - // output sign - out << (coeff<0 ? " - " : " + "); - // output coefficient - if (abs(coeff) != 1) { - out << abs(coeff) << " * "; - } - // output variable - out << "X" << var; - } + out << node.poly; break; } case OrderingComparator::BranchTag::T_TERM: { @@ -74,6 +62,32 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node return out; } +std::ostream& operator<<(std::ostream& out, const OrderingComparator::Polynomial& poly) +{ + bool first = true; + for (const auto& [var, coeff] : poly.pos) { + out << (first ? "" : " + "); + first = false; + if (coeff!=1) { + out << coeff << " * "; + } + out << TermList::var(var); + } + for (const auto& [var, coeff] : poly.neg) { + out << (first ? "- " : " - "); + first = false; + if (coeff!=-1) { + out << std::abs(coeff) << " * "; + } + out << TermList::var(var); + } + if (poly.constant) { + out << (poly.constant<0 ? " - " : " + "); + out << std::abs(poly.constant); + } + return out; +} + std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) { Stack> todo; @@ -210,8 +224,8 @@ std::string OrderingComparator::to_dot() const style += "polynode,"; bool first = true; label += "$"; - for (const auto& [var, coeff] : *n->varCoeffPairs) { - label += coeff<0 ? "-" : (first ? "" : "+"); + for (const auto& [var, coeff] : n->poly->pos) { + label += first ? "" : "+"; first = false; auto a = std::abs(coeff); if (a==1) { @@ -220,9 +234,19 @@ std::string OrderingComparator::to_dot() const label += Int::toString(a) + "\\cdot " + to_tikz_term(TermList::var(var)); } } - if (n->w) { - label += n->w<0 ? "-" : (first ? "" : "+"); - label += Int::toString((int)std::abs(n->w)); + for (const auto& [var, coeff] : n->poly->neg) { + label += "-"; + first = false; + auto a = std::abs(coeff); + if (a==1) { + label += to_tikz_term(TermList::var(var)); + } else { + label += Int::toString(a) + "\\cdot " + to_tikz_term(TermList::var(var)); + } + } + if (n->poly->constant) { + label += n->poly->constant<0 ? "-" : (first ? "" : "+"); + label += Int::toString((int)std::abs(n->poly->constant)); } label += "$"; edges += getBranch(id, n->gtBranch.node(), EdgeTag::GT); @@ -261,15 +285,25 @@ bool OrderingComparator::check(const SubstApplicator* applicator) if (node->tag == BranchTag::T_TERM) { comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); - // _trace.set({ node->lhs, node->rhs, comp }); } else { ASS(node->tag == BranchTag::T_POLY); const auto& kbo = static_cast(_ord); - auto weight = node->w; + auto weight = node->poly->constant; ZIArray varDiffs; - for (const auto& [var, coeff] : *node->varCoeffPairs) { + for (const auto& [var, coeff] : node->poly->pos) { + AppliedTerm tt(TermList::var(var), applicator, true); + + VariableIterator vit(tt.term); + while (vit.hasNext()) { + auto v = vit.next(); + varDiffs[v.var()] += coeff; + } + int64_t w = kbo.computeWeight(tt); + weight += coeff*w; + } + for (const auto& [var, coeff] : node->poly->neg) { AppliedTerm tt(TermList::var(var), applicator, true); VariableIterator vit(tt.term); @@ -360,8 +394,7 @@ void OrderingComparator::expand() // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { - auto varCoeffPairs = new Stack(*node->varCoeffPairs); - *_curr = Branch(node->w, varCoeffPairs); + *_curr = Branch(node->poly); _curr->node()->gtBranch = node->gtBranch; _curr->node()->eqBranch = node->eqBranch; _curr->node()->ngeBranch = node->ngeBranch; @@ -403,8 +436,6 @@ void OrderingComparator::expandTermCase() void OrderingComparator::processPolyCase() { auto node = _curr->node(); - auto varCoeffPairs = node->varCoeffPairs; - auto trace = getCurrentTrace(); // If this happens this branch is invalid. @@ -418,22 +449,26 @@ void OrderingComparator::processPolyCase() unsigned pos = 0; unsigned neg = 0; - for (unsigned i = 0; i < varCoeffPairs->size();) { - auto& [var, coeff] = (*varCoeffPairs)[i]; - for (unsigned j = i+1; j < varCoeffPairs->size();) { - auto& [var2, coeff2] = (*varCoeffPairs)[j]; + + auto vcs = node->poly->pos; + vcs.loadFromIterator(node->poly->neg.iter()); + + for (unsigned i = 0; i < vcs.size();) { + auto& [var, coeff] = vcs[i]; + for (unsigned j = i+1; j < vcs.size();) { + auto& [var2, coeff2] = vcs[j]; Ordering::Result res; if (trace->get(TermList::var(var), TermList::var(var2), res) && res == Ordering::EQUAL) { coeff += coeff2; - swap((*varCoeffPairs)[j],varCoeffPairs->top()); - varCoeffPairs->pop(); + swap(vcs[j],vcs.top()); + vcs.pop(); continue; } j++; } if (coeff == 0) { - swap((*varCoeffPairs)[i],varCoeffPairs->top()); - varCoeffPairs->pop(); + swap(vcs[i],vcs.top()); + vcs.pop(); continue; } else if (coeff > 0) { pos++; @@ -443,23 +478,22 @@ void OrderingComparator::processPolyCase() i++; } - if (node->w == 0 && pos == 0 && neg == 0) { + auto constant = node->poly->constant; + if (constant == 0 && pos == 0 && neg == 0) { *_curr = node->eqBranch; return; } - if (node->w >= 0 && neg == 0) { + if (constant >= 0 && neg == 0) { *_curr = node->gtBranch; return; } - if (node->w <= 0 && pos == 0) { + if (constant <= 0 && pos == 0) { *_curr = node->ngeBranch; return; } - sort(varCoeffPairs->begin(),varCoeffPairs->end(),[](const auto& e1, const auto& e2) { - return e1.second>e2.second; - }); - _curr->node()->ready = true; - _curr->node()->trace = trace; + node->poly = Polynomial::get(constant, vcs); + node->ready = true; + node->trace = trace; } void OrderingComparator::processVarCase() @@ -498,6 +532,38 @@ void OrderingComparator::processVarCase() _curr->node()->trace = trace; } +const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int constant, const Stack& vcs) +{ + static Set polys; + + auto pos = iterTraits(Stack::ConstRefIterator(vcs)).filter([](const auto& vc) { + return vc.second > 0; + }).collect>(); + sort(pos.begin(),pos.end(),[](const auto& vc1, const auto& vc2) { + return vc1.first::ConstRefIterator(vcs)).filter([](const auto& vc) { + return vc.second < 0; + }).collect>(); + sort(neg.begin(),neg.end(),[](const auto& vc1, const auto& vc2) { + return vc1.firstconstant = constant; + p->pos = std::move(pos); + p->neg = std::move(neg); + return p; + }, + HashUtils::combine(DefaultHash::hash(constant), DefaultHash::hash(pos), DefaultHash::hash(neg)), + [&](Polynomial* p) { return p->constant == constant && p->pos == pos && p->neg == neg; }, + unused); +} + const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() { ASS(!_curr->node()->ready || _curr->node() == _fail.node()); @@ -567,9 +633,6 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other OrderingComparator::Node::~Node() { - if (tag == T_POLY) { - delete varCoeffPairs; - } ready = false; trace = nullptr; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index f79bcf2a6..d19e597f9 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -57,6 +57,7 @@ struct OrderingComparator }; struct Node; + struct Polynomial; struct Branch { Node* node() const { return _node; } @@ -78,6 +79,9 @@ struct OrderingComparator template Branch(S&& s, T&& t) { setNode(new Node(std::forward(s), std::forward(t))); } + Branch(const Polynomial* p) { + setNode(new Node(p)); + } ~Branch(); Branch(const Branch& other); Branch& operator=(const Branch& other); @@ -90,9 +94,18 @@ struct OrderingComparator friend std::ostream& operator<<(std::ostream& out, const Node& node); friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); + friend std::ostream& operator<<(std::ostream& out, const Polynomial& poly); using VarCoeffPair = std::pair; + struct Polynomial { + static const Polynomial* get(int constant, const Stack& vcs); + + int constant; + Stack pos; + Stack neg; + }; + using Trace = TermPartialOrdering; const Trace* getCurrentTrace(); @@ -120,8 +133,8 @@ struct OrderingComparator : tag(T_RESULT), result(result) {} explicit Node(TermList lhs, TermList rhs) : tag(T_TERM), lhs(lhs), rhs(rhs) {} - explicit Node(uint64_t w, Stack* varCoeffPairs) - : tag(T_POLY), w(w), varCoeffPairs(varCoeffPairs) {} + explicit Node(const Polynomial* p) + : tag(T_POLY), poly(p) {} Node(const Node&) = delete; Node& operator=(const Node&) = delete; @@ -136,11 +149,10 @@ struct OrderingComparator union { bool result; TermList lhs; - int64_t w; + const Polynomial* poly; }; union { TermList rhs; - Stack* varCoeffPairs; }; Branch gtBranch; From 9c01da7b73c015f1e752e494b5669eb35d0e36c0 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 7 Dec 2024 11:20:43 +0100 Subject: [PATCH 53/64] Minor fixes --- Kernel/OrderingComparator.cpp | 2 +- Kernel/TermPartialOrdering.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index fc729fb77..510d567e4 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -51,7 +51,7 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node break; } case OrderingComparator::BranchTag::T_POLY: { - out << node.poly; + out << *node.poly; break; } case OrderingComparator::BranchTag::T_TERM: { diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index 390912f0e..d2b111351 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -370,7 +370,11 @@ string TermPartialOrdering::to_nice_string() const if (e1.value() >= e2.value()) { continue; } - str << e1.key() << " " << po_to_infix(_po->get(e1.value(),e2.value())) << " " << e2.key() << endl; + auto pocomp = _po->get(e1.value(),e2.value()); + if (pocomp == PoComp::UNKNOWN) { + continue; + } + str << e1.key() << " " << po_to_infix(pocomp) << " " << e2.key() << endl; } } return str.str(); From 240e2838dd2a129666df2a231724760d55d27b5c Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Wed, 11 Dec 2024 14:57:32 +0100 Subject: [PATCH 54/64] Fix error in debug mode due to not using the correct hash function in Set --- Kernel/OrderingComparator.cpp | 18 ++++++++---------- Kernel/OrderingComparator.hpp | 5 +++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 510d567e4..854428bdc 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -534,7 +534,7 @@ void OrderingComparator::processVarCase() const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int constant, const Stack& vcs) { - static Set polys; + static Set> polys; auto pos = iterTraits(Stack::ConstRefIterator(vcs)).filter([](const auto& vc) { return vc.second > 0; @@ -550,17 +550,15 @@ const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int co return vc1.firstconstant = constant; - p->pos = std::move(pos); - p->neg = std::move(neg); - return p; - }, - HashUtils::combine(DefaultHash::hash(constant), DefaultHash::hash(pos), DefaultHash::hash(neg)), - [&](Polynomial* p) { return p->constant == constant && p->pos == pos && p->neg == neg; }, + [&](){ return new Polynomial(std::move(poly)); }, + poly.defaultHash(), + [&](Polynomial* p) { return *p == poly; }, unused); } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index d19e597f9..0ea700982 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -101,6 +101,11 @@ struct OrderingComparator struct Polynomial { static const Polynomial* get(int constant, const Stack& vcs); + auto asTuple() const { return std::make_tuple(constant, pos, neg); } + + IMPL_HASH_FROM_TUPLE(Polynomial); + IMPL_COMPARISONS_FROM_TUPLE(Polynomial); + int constant; Stack pos; Stack neg; From 92a7f5a733d6dde183d04b38493ed8d40a97e4af Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 13 Dec 2024 10:22:43 +0100 Subject: [PATCH 55/64] Sync content from other branch; from now on they will contain the same OrderingComparator implementation --- Indexing/Index.hpp | 2 +- Inferences/ForwardDemodulation.cpp | 3 +- Kernel/OrderingComparator.cpp | 194 ++++++++++++++++--------- Kernel/OrderingComparator.hpp | 35 +++-- Shell/ConditionalRedundancyHandler.cpp | 5 +- 5 files changed, 148 insertions(+), 91 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index bde0ef2c5..0dc8166f3 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -119,7 +119,7 @@ struct DemodulatorData DemodulatorData(TypedTermList term, TermList rhs, Clause* clause, bool preordered, const Ordering& ord) : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator(ord.createComparator()) { - comparator->insert({ { term, rhs, Ordering::GREATER } }); + comparator->insert({ { term, rhs, Ordering::GREATER } }, (void*)0x1); #if VDEBUG ASS(term.containsAllVariablesOf(rhs)); ASS(!preordered || ord.compare(term,rhs)==Ordering::GREATER); diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index d51d60b44..0192dc975 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -173,7 +173,8 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* auto appl = lhs.isVar() ? (SubstApplicator*)&applWithEqSort : (SubstApplicator*)&applWithoutEqSort; if (_precompiledComparison) { - if (!preordered && (_preorderedOnly || !qr.data->comparator->check(appl))) { + qr.data->comparator->reset(); + if (!preordered && (_preorderedOnly || !qr.data->comparator->next(appl))) { #if DEBUG_ORDERING if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { INVALID_OPERATION("greater"); diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 854428bdc..60d3e6810 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -18,10 +18,10 @@ #include "KBO.hpp" #include "SubstHelper.hpp" -#include - #include "OrderingComparator.hpp" +#include + using namespace std; namespace Kernel { @@ -29,8 +29,8 @@ namespace Kernel { std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) { switch (t) { - case OrderingComparator::BranchTag::T_RESULT: - out << "r"; + case OrderingComparator::BranchTag::T_DATA: + out << "d"; break; case OrderingComparator::BranchTag::T_TERM: out << "t"; @@ -46,8 +46,8 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node { out << (OrderingComparator::BranchTag)node.tag << (node.ready?" ":"? "); switch (node.tag) { - case OrderingComparator::BranchTag::T_RESULT: { - out << node.result; + case OrderingComparator::BranchTag::T_DATA: { + out << node.data; break; } case OrderingComparator::BranchTag::T_POLY: { @@ -106,10 +106,14 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } str << *kv.first->node() << std::endl; if (seen.insert(kv.first->node())) { - if (kv.first->node()->tag!=OrderingComparator::BranchTag::T_RESULT) { + if (kv.first->node()->tag==OrderingComparator::BranchTag::T_DATA) { + if (kv.first->node()->data) { + todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); + } + } else { todo.push(std::make_pair(&kv.first->node()->ngeBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); } } } @@ -198,16 +202,17 @@ std::string OrderingComparator::to_dot() const style += "processed,"; } switch (n->tag) { - case BranchTag::T_RESULT: { - if (!n->result) { + case BranchTag::T_DATA: { + auto alt = n->alternative.node(); + if (!alt) { // do not output anything for the fail node style += "sinknode,"; label += ""; break; } style += "datanode,"; - label += Int::toString((unsigned long)n->result); - // edges += getBranch(id, alt, EdgeTag::ALT); + label += Int::toString((unsigned long)n->data); + edges += getBranch(id, alt, EdgeTag::ALT); break; } case BranchTag::T_TERM: { @@ -261,24 +266,28 @@ std::string OrderingComparator::to_dot() const } OrderingComparator::OrderingComparator(const Ordering& ord) -: _ord(ord), _source(false), _fail(_source), _curr(&_source), _prev(nullptr) +: _ord(ord), _source(nullptr, Branch()), _sink(_source), _curr(&_source), _prev(nullptr) { + _sink.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; -bool OrderingComparator::check(const SubstApplicator* applicator) +void* OrderingComparator::next(const SubstApplicator* applicator) { - _curr = &_source; - _prev = nullptr; ASS(_curr); for (;;) { expand(); auto node = _curr->node(); ASS(node->ready); - if (node->tag == BranchTag::T_RESULT) { - return node->result; + if (node->tag == BranchTag::T_DATA) { + if (!node->data) { + return nullptr; + } + _prev = _curr; + _curr = &node->alternative; + return node->data; } Ordering::Result comp = Ordering::INCOMPARABLE; @@ -335,32 +344,33 @@ bool OrderingComparator::check(const SubstApplicator* applicator) _prev = _curr; _curr = &node->getBranch(comp); } - ASSERTION_VIOLATION; + return nullptr; } -void OrderingComparator::insert(const OrderingConstraints& ordCons) +void OrderingComparator::insert(const Stack& comps, void* result) { + ASS(result); static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; // we mutate current fail node and add a new one - // cout << "before " << *this << endl; - auto curr = &_fail; - Branch newFail(false); + auto curr = &_sink; + Branch newFail(nullptr, Branch()); + newFail.node()->ready = true; curr->node()->~Node(); curr->node()->ready = false; - if (ordCons.isNonEmpty()) { + if (comps.isNonEmpty()) { curr->node()->tag = T_TERM; - curr->node()->lhs = ordCons[0].lhs; - curr->node()->rhs = ordCons[0].rhs; + curr->node()->lhs = comps[0].lhs; + curr->node()->rhs = comps[0].rhs; for (unsigned i = 0; i < 3; i++) { - if (ordVals[i] != ordCons[0].rel) { + if (ordVals[i] != comps[0].rel) { curr->node()->getBranch(ordVals[i]) = newFail; } } - curr = &curr->node()->getBranch(ordCons[0].rel); - for (unsigned i = 1; i < ordCons.size(); i++) { - auto [lhs,rhs,rel] = ordCons[i]; + curr = &curr->node()->getBranch(comps[0].rel); + for (unsigned i = 1; i < comps.size(); i++) { + auto [lhs,rhs,rel] = comps[i]; *curr = OrderingComparator::Branch(lhs, rhs); for (unsigned i = 0; i < 3; i++) { if (ordVals[i] != rel) { @@ -369,16 +379,14 @@ void OrderingComparator::insert(const OrderingConstraints& ordCons) } curr = &curr->node()->getBranch(rel); } - *curr = Branch(true); + *curr = Branch(result, newFail); } else { - curr->node()->tag = T_RESULT; - curr->node()->result = true; - curr->node()->ready = true; + curr->node()->tag = T_DATA; + curr->node()->data = result; + curr->node()->alternative = newFail; } - _fail = newFail; - ASS(_fail.node()->ready); - ASS(!_fail.node()->result); + _sink = newFail; } void OrderingComparator::expand() @@ -388,18 +396,19 @@ void OrderingComparator::expand() { auto node = _curr->node(); - ASS_NEQ(node->tag, BranchTag::T_RESULT); - - if (node->tag == BranchTag::T_POLY) { + if (node->tag == BranchTag::T_DATA) { + ASS(node->data); // no fail nodes here // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { - *_curr = Branch(node->poly); - _curr->node()->gtBranch = node->gtBranch; - _curr->node()->eqBranch = node->eqBranch; - _curr->node()->ngeBranch = node->ngeBranch; + *_curr = Branch(node->data, node->alternative); } - + _curr->node()->trace = getCurrentTrace(); + _curr->node()->prevPoly = getPrevPoly(); + _curr->node()->ready = true; + return; + } + if (node->tag == BranchTag::T_POLY) { processPolyCase(); continue; } @@ -438,15 +447,6 @@ void OrderingComparator::processPolyCase() auto node = _curr->node(); auto trace = getCurrentTrace(); - // If this happens this branch is invalid. - // Since normal execution cannot reach it, - // we can put a "success" here to make things - // easier in subsumption/simplification. - if (!trace) { - *_curr = Branch(true); - return; - } - unsigned pos = 0; unsigned neg = 0; @@ -491,24 +491,54 @@ void OrderingComparator::processPolyCase() *_curr = node->ngeBranch; return; } - node->poly = Polynomial::get(constant, vcs); - node->ready = true; - node->trace = trace; + auto poly = Polynomial::get(constant, vcs); + auto prevPoly = getPrevPoly(); + + // check if we have seen this polynomial + // on the path leading here + auto polyIt = prevPoly; + while (polyIt.first) { + ASS_EQ(polyIt.first->tag, BranchTag::T_POLY); + if (polyIt.first->poly == poly) { + switch (polyIt.second) { + case Ordering::GREATER: { + *_curr = node->gtBranch; + return; + } + case Ordering::EQUAL: { + *_curr = node->eqBranch; + return; + } + case Ordering::INCOMPARABLE: { + *_curr = node->ngeBranch; + return; + } + default: + break; + } + } + polyIt = polyIt.first->prevPoly; + } + + // if refcnt > 1 we copy the node and + // we can also safely use the original + if (node->refcnt > 1) { + *_curr = Branch(node->poly); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->ngeBranch = node->ngeBranch; + } + + _curr->node()->poly = poly; + _curr->node()->prevPoly = prevPoly; + _curr->node()->trace = trace; + _curr->node()->ready = true; } void OrderingComparator::processVarCase() { auto node = _curr->node(); auto trace = getCurrentTrace(); - - // If this happens this branch is invalid. - // Since normal execution cannot reach it, - // we can put a "success" here to make things - // easier in subsumption/simplification. - if (!trace) { - *_curr = Branch(true); - return; - } Ordering::Result val; if (trace->get(node->lhs, node->rhs, val)) { if (val == Ordering::GREATER) { @@ -529,6 +559,7 @@ void OrderingComparator::processVarCase() _curr->node()->ngeBranch = node->ngeBranch; } _curr->node()->ready = true; + _curr->node()->prevPoly = getPrevPoly(); _curr->node()->trace = trace; } @@ -564,7 +595,7 @@ const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int co const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() { - ASS(!_curr->node()->ready || _curr->node() == _fail.node()); + ASS(!_curr->node()->ready); if (!_prev) { return Trace::getEmpty(_ord); @@ -587,7 +618,7 @@ const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() } return Trace::set(_prev->node()->trace, { lhs, rhs, res }); } - case BranchTag::T_RESULT: + case BranchTag::T_DATA: case BranchTag::T_POLY: { return _prev->node()->trace; } @@ -595,6 +626,29 @@ const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() ASSERTION_VIOLATION; } +std::pair OrderingComparator::getPrevPoly() +{ + auto res = make_pair((Node*)nullptr, Ordering::INCOMPARABLE); + if (_prev) { + // take value from previous node by default + res = _prev->node()->prevPoly; + + // override value if the previous is a poly node + if (_prev->node()->tag == BranchTag::T_POLY) { + res.first = _prev->node(); + if (_curr == &_prev->node()->gtBranch) { + res.second = Ordering::GREATER; + } else if (_curr == &_prev->node()->eqBranch) { + res.second = Ordering::EQUAL; + } else { + ASS_EQ(_curr, &_prev->node()->ngeBranch); + res.second = Ordering::INCOMPARABLE; + } + } + } + return res; +} + OrderingComparator::Branch::~Branch() { setNode(nullptr); @@ -631,8 +685,10 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other OrderingComparator::Node::~Node() { + if (tag==T_DATA) { + alternative.~Branch(); + } ready = false; - trace = nullptr; } void OrderingComparator::Node::incRefCnt() diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 0ea700982..7512c6071 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -22,8 +22,6 @@ namespace Kernel { -using OrderingConstraints = Stack; - /** * Class implementing runtime specialized ordering check between two terms. * The comparator is created and called from inside the respective ordering @@ -32,14 +30,14 @@ using OrderingConstraints = Stack; */ struct OrderingComparator { -protected: - struct Branch; public: OrderingComparator(const Ordering& ord); virtual ~OrderingComparator(); - bool check(const SubstApplicator* applicator); - void insert(const OrderingConstraints& comps); + void reset() { _curr = &_source; _prev = nullptr; /* _trace.reset(); */ } + + void* next(const SubstApplicator* applicator); + void insert(const Stack& comps, void* result); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); std::string to_dot() const; @@ -51,7 +49,7 @@ struct OrderingComparator void processPolyCase(); enum BranchTag { - T_RESULT = 0u, + T_DATA = 0u, T_TERM = 1u, T_POLY = 2u, }; @@ -72,10 +70,6 @@ struct OrderingComparator } Branch() = default; - explicit Branch(bool result) { - setNode(new Node(result)); - _node->ready = true; - } template Branch(S&& s, T&& t) { setNode(new Node(std::forward(s), std::forward(t))); } @@ -114,6 +108,7 @@ struct OrderingComparator using Trace = TermPartialOrdering; const Trace* getCurrentTrace(); + std::pair getPrevPoly(); struct Node { static_assert(sizeof(uint64_t) == sizeof(Branch)); @@ -123,10 +118,10 @@ struct OrderingComparator auto& getBranch(Ordering::Result r) { switch (r) { - case Ordering::GREATER: - return gtBranch; case Ordering::EQUAL: return eqBranch; + case Ordering::GREATER: + return gtBranch; case Ordering::INCOMPARABLE: return ngeBranch; default: @@ -134,8 +129,8 @@ struct OrderingComparator } } - explicit Node(bool result) - : tag(T_RESULT), result(result) {} + explicit Node(void* data, Branch alternative) + : tag(T_DATA), data(data), alternative(alternative) {} explicit Node(TermList lhs, TermList rhs) : tag(T_TERM), lhs(lhs), rhs(rhs) {} explicit Node(const Polynomial* p) @@ -152,24 +147,28 @@ struct OrderingComparator bool ready = false; union { - bool result; + void* data = nullptr; TermList lhs; const Polynomial* poly; }; union { + Branch alternative; TermList rhs; }; - Branch gtBranch; Branch eqBranch; + Branch gtBranch; Branch ngeBranch; int refcnt = 0; const Trace* trace = nullptr; + // points to the previous node containing a polynomial and branch + // that was taken, otherwise null if no such node exists. + std::pair prevPoly = { nullptr, Result::INCOMPARABLE }; }; const Ordering& _ord; Branch _source; - Branch _fail; + Branch _sink; Branch* _curr; Branch* _prev; // Trace _trace; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index e6e1e5f09..1cc36ece9 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -159,9 +159,10 @@ class ConditionalRedundancyHandler::ConstraintIndex auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { if (!ordCon.comp) { ordCon.comp = ord->createComparator(); - ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }); + ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }, (void*)0x1); } - return ordCon.comp->check(&applicator); + ordCon.comp->reset(); + return ordCon.comp->next(&applicator); }); if (!ordCons_ok) { continue; From d255284848ba2614cb39f8197092418f7167ffcc Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sun, 22 Dec 2024 19:02:33 +0100 Subject: [PATCH 56/64] Prepare for PR --- Inferences/ForwardDemodulation.cpp | 4 +- Kernel/KBOComparator.cpp | 4 +- Kernel/KBOComparator.hpp | 2 +- Kernel/LPOComparator.cpp | 6 +- Kernel/LPOComparator.hpp | 2 +- Kernel/Ordering.hpp | 9 - Kernel/OrderingComparator.cpp | 603 +++++++++---------------- Kernel/OrderingComparator.hpp | 182 ++++---- Kernel/PartialOrdering.cpp | 174 ++++--- Kernel/PartialOrdering.hpp | 51 ++- Kernel/TermPartialOrdering.cpp | 239 +++++----- Kernel/TermPartialOrdering.hpp | 53 ++- Shell/ConditionalRedundancyHandler.cpp | 4 +- 13 files changed, 580 insertions(+), 753 deletions(-) diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 0192dc975..23f1af308 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -173,8 +173,8 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* auto appl = lhs.isVar() ? (SubstApplicator*)&applWithEqSort : (SubstApplicator*)&applWithoutEqSort; if (_precompiledComparison) { - qr.data->comparator->reset(); - if (!preordered && (_preorderedOnly || !qr.data->comparator->next(appl))) { + qr.data->comparator->init(appl); + if (!preordered && (_preorderedOnly || !qr.data->comparator->next())) { #if DEBUG_ORDERING if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { INVALID_OPERATION("greater"); diff --git a/Kernel/KBOComparator.cpp b/Kernel/KBOComparator.cpp index b4b72a9c6..b15be3592 100644 --- a/Kernel/KBOComparator.cpp +++ b/Kernel/KBOComparator.cpp @@ -21,7 +21,7 @@ using namespace std; using namespace Lib; using namespace Shell; -void KBOComparator::expandTermCase() +void KBOComparator::processTermNode() { const auto& kbo = static_cast(_ord); @@ -66,7 +66,7 @@ void KBOComparator::expandTermCase() bool weightAdded = (w < 0 || varInbalance); if (weightAdded) { // we mutate the original node - curr->node()->tag = T_POLY; + curr->node()->tag = Node::T_POLY; curr->node()->poly = Polynomial::get(w, nonzeros); curr->node()->gtBranch = gtBranch; curr->node()->ngeBranch = ngeBranch; diff --git a/Kernel/KBOComparator.hpp b/Kernel/KBOComparator.hpp index 359b49f34..fedc36811 100644 --- a/Kernel/KBOComparator.hpp +++ b/Kernel/KBOComparator.hpp @@ -33,7 +33,7 @@ class KBOComparator public: KBOComparator(const Ordering& ord) : OrderingComparator(ord) {} - void expandTermCase() override; + void processTermNode() override; }; } diff --git a/Kernel/LPOComparator.cpp b/Kernel/LPOComparator.cpp index 21aad1f79..874db6088 100644 --- a/Kernel/LPOComparator.cpp +++ b/Kernel/LPOComparator.cpp @@ -48,7 +48,7 @@ void LPOComparator::alphaChain(Branch* branch, Term* s, unsigned i, TermList tl2 *branch = std::move(fail); } -void LPOComparator::expandTermCase() +void LPOComparator::processTermNode() { // take temporary ownership of node auto node = _curr->node(); @@ -58,7 +58,7 @@ void LPOComparator::expandTermCase() auto gtBranch = node->gtBranch; auto ngeBranch = node->ngeBranch; - ASS_EQ(node->tag, T_TERM); + ASS_EQ(node->tag, Node::T_TERM); ASS(!node->ready); ASS(lhs.isTerm() && rhs.isTerm()); @@ -78,7 +78,7 @@ void LPOComparator::expandTermCase() auto t_arg = *rhs.term()->nthArgument(i); if (i == 0) { // we mutate the original node in the first iteration - ASS_EQ(curr->node()->tag, T_TERM); + ASS_EQ(curr->node()->tag, Node::T_TERM); curr->node()->lhs = s_arg; curr->node()->rhs = t_arg; } else { diff --git a/Kernel/LPOComparator.hpp b/Kernel/LPOComparator.hpp index 152194af0..fdc05e54f 100644 --- a/Kernel/LPOComparator.hpp +++ b/Kernel/LPOComparator.hpp @@ -26,7 +26,7 @@ class LPOComparator public: LPOComparator(const Ordering& ord) : OrderingComparator(ord) {} - void expandTermCase() override; + void processTermNode() override; private: static void majoChain(Branch* branch, TermList tl1, Term* t, unsigned i, Branch success, Branch fail); diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index 176b8a5fc..cf1bf1f84 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -76,15 +76,6 @@ class Ordering return out << "UNKNOWN"; } - struct Constraint { - TermList lhs; - TermList rhs; - Result rel; - - friend std::ostream& operator<<(std::ostream& out, const Constraint& self) - { return out << self.lhs << " " << self.rhs << " " << resultToString(self.rel); } - }; - virtual ~Ordering() = default; /** Return the result of comparing @b l1 and @b l2 */ diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 60d3e6810..261d0297c 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -20,268 +20,39 @@ #include "OrderingComparator.hpp" -#include - using namespace std; namespace Kernel { -std::ostream& operator<<(std::ostream& out, const OrderingComparator::BranchTag& t) -{ - switch (t) { - case OrderingComparator::BranchTag::T_DATA: - out << "d"; - break; - case OrderingComparator::BranchTag::T_TERM: - out << "t"; - break; - case OrderingComparator::BranchTag::T_POLY: - out << "p"; - break; - } - return out; -} - -std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node) -{ - out << (OrderingComparator::BranchTag)node.tag << (node.ready?" ":"? "); - switch (node.tag) { - case OrderingComparator::BranchTag::T_DATA: { - out << node.data; - break; - } - case OrderingComparator::BranchTag::T_POLY: { - out << *node.poly; - break; - } - case OrderingComparator::BranchTag::T_TERM: { - out << node.lhs << " " << node.rhs; - break; - } - } - return out; -} - -std::ostream& operator<<(std::ostream& out, const OrderingComparator::Polynomial& poly) -{ - bool first = true; - for (const auto& [var, coeff] : poly.pos) { - out << (first ? "" : " + "); - first = false; - if (coeff!=1) { - out << coeff << " * "; - } - out << TermList::var(var); - } - for (const auto& [var, coeff] : poly.neg) { - out << (first ? "- " : " - "); - first = false; - if (coeff!=-1) { - out << std::abs(coeff) << " * "; - } - out << TermList::var(var); - } - if (poly.constant) { - out << (poly.constant<0 ? " - " : " + "); - out << std::abs(poly.constant); - } - return out; -} - -std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) -{ - Stack> todo; - todo.push(std::make_pair(&comp._source,0)); - // Note: using this set we get a more compact representation - DHSet seen; - - while (todo.isNonEmpty()) { - auto kv = todo.pop(); - for (unsigned i = 0; i < kv.second; i++) { - if (i+1 == kv.second) { - str << " |--"; - } else { - str << " | "; - } - } - str << *kv.first->node() << std::endl; - if (seen.insert(kv.first->node())) { - if (kv.first->node()->tag==OrderingComparator::BranchTag::T_DATA) { - if (kv.first->node()->data) { - todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); - } - } else { - todo.push(std::make_pair(&kv.first->node()->ngeBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); - todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); - } - } - } - return str; -} - -std::string to_tikz_term(TermList t) -{ - if (t.isVar()) { - switch (t.var()) { - case 0: - return "x"; - case 1: - return "y"; - case 2: - return "z"; - default: - return "x_"+Int::toString(t.var()); - } - } - auto tt = t.term(); - auto res = tt->functionName() + "("; - for (unsigned i = 0; i < tt->arity(); i++) { - res += to_tikz_term(*tt->nthArgument(i)) + ","; - } - res += ")"; - return res; -} - -std::string OrderingComparator::to_dot() const -{ - std::deque todo; - todo.push_back(_source.node()); - // Note: using this set we get a more compact representation - DHMap seen; - - seen.insert(_source.node(), 0); - unsigned cnt = 1; - - auto getId = [&todo,&seen,&cnt](auto n) { - unsigned* ptr; - if (seen.getValuePtr(n,ptr)) { - todo.push_back(n); - *ptr = cnt++; - } - return *ptr; - }; - - enum class EdgeTag { - GT, - EQ, - INC, - ALT, - }; - auto getBranch = [&getId](unsigned from, auto to_node, EdgeTag tag) -> std::string - { - auto res = "n" + Int::toString(from) + " -> n" + Int::toString(getId(to_node)); - switch (tag) { - case EdgeTag::GT: - res += " [style = gtedge]"; - break; - case EdgeTag::EQ: - res += " [style = eqedge]"; - break; - case EdgeTag::INC: - res += " [style = ngeedge]"; - break; - case EdgeTag::ALT: - res += " [style = trueedge]"; - break; - } - return res + ";\n"; - }; - - std::string nodes = "source [style = invisible, label = \"\"];\n"; - std::string edges = "source -> n0 [style = trueedge];\n"; - - while (!todo.empty()) { - auto n = todo.front(); - todo.pop_front(); - auto id = seen.get(n); - - std::string style = ""; - std::string label = ""; - if (n->ready) { - style += "processed,"; - } - switch (n->tag) { - case BranchTag::T_DATA: { - auto alt = n->alternative.node(); - if (!alt) { - // do not output anything for the fail node - style += "sinknode,"; - label += ""; - break; - } - style += "datanode,"; - label += Int::toString((unsigned long)n->data); - edges += getBranch(id, alt, EdgeTag::ALT); - break; - } - case BranchTag::T_TERM: { - // nodes += "termnode] (n" + Int::toString(id) + ") at (" + Int::toString(x) + "," + Int::toString(y) + ") {$" - // + to_tikz_term(n->lhs) + " \\comp " + to_tikz_term(n->rhs) + "$};\n"; - style += "termnode,"; - label += "$" + to_tikz_term(n->lhs) + " \\comp " + to_tikz_term(n->rhs) + "$"; - edges += getBranch(id, n->gtBranch.node(), EdgeTag::GT); - edges += getBranch(id, n->eqBranch.node(), EdgeTag::EQ); - edges += getBranch(id, n->ngeBranch.node(), EdgeTag::INC); - break; - } - case BranchTag::T_POLY: { - style += "polynode,"; - bool first = true; - label += "$"; - for (const auto& [var, coeff] : n->poly->pos) { - label += first ? "" : "+"; - first = false; - auto a = std::abs(coeff); - if (a==1) { - label += to_tikz_term(TermList::var(var)); - } else { - label += Int::toString(a) + "\\cdot " + to_tikz_term(TermList::var(var)); - } - } - for (const auto& [var, coeff] : n->poly->neg) { - label += "-"; - first = false; - auto a = std::abs(coeff); - if (a==1) { - label += to_tikz_term(TermList::var(var)); - } else { - label += Int::toString(a) + "\\cdot " + to_tikz_term(TermList::var(var)); - } - } - if (n->poly->constant) { - label += n->poly->constant<0 ? "-" : (first ? "" : "+"); - label += Int::toString((int)std::abs(n->poly->constant)); - } - label += "$"; - edges += getBranch(id, n->gtBranch.node(), EdgeTag::GT); - edges += getBranch(id, n->eqBranch.node(), EdgeTag::EQ); - edges += getBranch(id, n->ngeBranch.node(), EdgeTag::INC); - break; - } - } - nodes += "n" + Int::toString(id) + " [\n style = \"" + style + "\"\n label = \"" + label + "\"\n];\n"; - } - return "digraph {\nnodesep = 0;\nsep = 0;\nranksep = 0;\nesep = 0;\n" + nodes + "\n" + edges + "}\n"; -} +// OrderingComparator OrderingComparator::OrderingComparator(const Ordering& ord) -: _ord(ord), _source(nullptr, Branch()), _sink(_source), _curr(&_source), _prev(nullptr) +: _ord(ord), _source(nullptr, Branch()), _sink(_source), _curr(&_source), _prev(nullptr), _appl(nullptr) { _sink.node()->ready = true; } OrderingComparator::~OrderingComparator() = default; -void* OrderingComparator::next(const SubstApplicator* applicator) +void OrderingComparator::init(const SubstApplicator* appl) { + _curr = &_source; + _prev = nullptr; + _appl = appl; +} + +void* OrderingComparator::next() +{ + ASS(_appl); ASS(_curr); + for (;;) { - expand(); + processCurrentNode(); + auto node = _curr->node(); ASS(node->ready); - if (node->tag == BranchTag::T_DATA) { + if (node->tag == Node::T_DATA) { if (!node->data) { return nullptr; } @@ -291,29 +62,20 @@ void* OrderingComparator::next(const SubstApplicator* applicator) } Ordering::Result comp = Ordering::INCOMPARABLE; - if (node->tag == BranchTag::T_TERM) { + if (node->tag == Node::T_TERM) { - comp = _ord.isGreaterOrEq(AppliedTerm(node->lhs,applicator,true),AppliedTerm(node->rhs,applicator,true)); + comp = _ord.isGreaterOrEq( + AppliedTerm(node->lhs, _appl, true), + AppliedTerm(node->rhs, _appl, true)); } else { - ASS(node->tag == BranchTag::T_POLY); + ASS(node->tag == Node::T_POLY); const auto& kbo = static_cast(_ord); auto weight = node->poly->constant; ZIArray varDiffs; - for (const auto& [var, coeff] : node->poly->pos) { - AppliedTerm tt(TermList::var(var), applicator, true); - - VariableIterator vit(tt.term); - while (vit.hasNext()) { - auto v = vit.next(); - varDiffs[v.var()] += coeff; - } - int64_t w = kbo.computeWeight(tt); - weight += coeff*w; - } - for (const auto& [var, coeff] : node->poly->neg) { - AppliedTerm tt(TermList::var(var), applicator, true); + for (const auto& [var, coeff] : node->poly->varCoeffPairs) { + AppliedTerm tt(TermList::var(var), _appl, true); VariableIterator vit(tt.term); while (vit.hasNext()) { @@ -347,10 +109,10 @@ void* OrderingComparator::next(const SubstApplicator* applicator) return nullptr; } -void OrderingComparator::insert(const Stack& comps, void* result) +void OrderingComparator::insert(const Stack& comps, void* data) { - ASS(result); - static Ordering::Result ordVals[] = { Ordering::EQUAL, Ordering::GREATER, Ordering::INCOMPARABLE }; + ASS(data); + static Ordering::Result ordVals[] = { Ordering::GREATER, Ordering::EQUAL, Ordering::INCOMPARABLE }; // we mutate current fail node and add a new one auto curr = &_sink; Branch newFail(nullptr, Branch()); @@ -360,7 +122,7 @@ void OrderingComparator::insert(const Stack& comps, void* curr->node()->ready = false; if (comps.isNonEmpty()) { - curr->node()->tag = T_TERM; + curr->node()->tag = Node::T_TERM; curr->node()->lhs = comps[0].lhs; curr->node()->rhs = comps[0].rhs; for (unsigned i = 0; i < 3; i++) { @@ -379,24 +141,24 @@ void OrderingComparator::insert(const Stack& comps, void* } curr = &curr->node()->getBranch(rel); } - *curr = Branch(result, newFail); + *curr = Branch(data, newFail); } else { - curr->node()->tag = T_DATA; - curr->node()->data = result; + curr->node()->tag = Node::T_DATA; + curr->node()->data = data; curr->node()->alternative = newFail; } _sink = newFail; } -void OrderingComparator::expand() +void OrderingComparator::processCurrentNode() { ASS(_curr->node()); while (!_curr->node()->ready) { auto node = _curr->node(); - if (node->tag == BranchTag::T_DATA) { + if (node->tag == Node::T_DATA) { ASS(node->data); // no fail nodes here // if refcnt > 1 we copy the node and // we can also safely use the original @@ -404,12 +166,11 @@ void OrderingComparator::expand() *_curr = Branch(node->data, node->alternative); } _curr->node()->trace = getCurrentTrace(); - _curr->node()->prevPoly = getPrevPoly(); _curr->node()->ready = true; return; } - if (node->tag == BranchTag::T_POLY) { - processPolyCase(); + if (node->tag == Node::T_POLY) { + processPolyNode(); continue; } @@ -428,21 +189,41 @@ void OrderingComparator::expand() } // If we have a variable, we cannot expand further. if (node->lhs.isVar() || node->rhs.isVar()) { - processVarCase(); + processVarNode(); continue; } - - expandTermCase(); + processTermNode(); } } -void OrderingComparator::expandTermCase() +void OrderingComparator::processVarNode() { - ASS(_curr->node() && !_curr->node()->ready); + auto node = _curr->node(); + auto trace = getCurrentTrace(); + Ordering::Result val; + if (trace->get(node->lhs, node->rhs, val)) { + if (val == Ordering::GREATER) { + *_curr = node->gtBranch; + } else if (val == Ordering::EQUAL) { + *_curr = node->eqBranch; + } else { + *_curr = node->ngeBranch; + } + return; + } + // if refcnt > 1 we copy the node and + // we can also safely use the original + if (node->refcnt > 1) { + *_curr = Branch(node->lhs, node->rhs); + _curr->node()->eqBranch = node->eqBranch; + _curr->node()->gtBranch = node->gtBranch; + _curr->node()->ngeBranch = node->ngeBranch; + } _curr->node()->ready = true; + _curr->node()->trace = trace; } -void OrderingComparator::processPolyCase() +void OrderingComparator::processPolyNode() { auto node = _curr->node(); auto trace = getCurrentTrace(); @@ -450,8 +231,7 @@ void OrderingComparator::processPolyCase() unsigned pos = 0; unsigned neg = 0; - auto vcs = node->poly->pos; - vcs.loadFromIterator(node->poly->neg.iter()); + auto vcs = node->poly->varCoeffPairs; for (unsigned i = 0; i < vcs.size();) { auto& [var, coeff] = vcs[i]; @@ -492,105 +272,25 @@ void OrderingComparator::processPolyCase() return; } auto poly = Polynomial::get(constant, vcs); - auto prevPoly = getPrevPoly(); - - // check if we have seen this polynomial - // on the path leading here - auto polyIt = prevPoly; - while (polyIt.first) { - ASS_EQ(polyIt.first->tag, BranchTag::T_POLY); - if (polyIt.first->poly == poly) { - switch (polyIt.second) { - case Ordering::GREATER: { - *_curr = node->gtBranch; - return; - } - case Ordering::EQUAL: { - *_curr = node->eqBranch; - return; - } - case Ordering::INCOMPARABLE: { - *_curr = node->ngeBranch; - return; - } - default: - break; - } - } - polyIt = polyIt.first->prevPoly; - } // if refcnt > 1 we copy the node and // we can also safely use the original if (node->refcnt > 1) { - *_curr = Branch(node->poly); + *_curr = Branch(poly); _curr->node()->eqBranch = node->eqBranch; _curr->node()->gtBranch = node->gtBranch; _curr->node()->ngeBranch = node->ngeBranch; + } else { + _curr->node()->poly = poly; } - - _curr->node()->poly = poly; - _curr->node()->prevPoly = prevPoly; _curr->node()->trace = trace; _curr->node()->ready = true; } -void OrderingComparator::processVarCase() +void OrderingComparator::processTermNode() { - auto node = _curr->node(); - auto trace = getCurrentTrace(); - Ordering::Result val; - if (trace->get(node->lhs, node->rhs, val)) { - if (val == Ordering::GREATER) { - *_curr = node->gtBranch; - } else if (val == Ordering::EQUAL) { - *_curr = node->eqBranch; - } else { - *_curr = node->ngeBranch; - } - return; - } - // if refcnt > 1 we copy the node and - // we can also safely use the original - if (node->refcnt > 1) { - *_curr = Branch(node->lhs, node->rhs); - _curr->node()->eqBranch = node->eqBranch; - _curr->node()->gtBranch = node->gtBranch; - _curr->node()->ngeBranch = node->ngeBranch; - } + ASS(_curr->node() && !_curr->node()->ready); _curr->node()->ready = true; - _curr->node()->prevPoly = getPrevPoly(); - _curr->node()->trace = trace; -} - -const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int constant, const Stack& vcs) -{ - static Set> polys; - - auto pos = iterTraits(Stack::ConstRefIterator(vcs)).filter([](const auto& vc) { - return vc.second > 0; - }).collect>(); - sort(pos.begin(),pos.end(),[](const auto& vc1, const auto& vc2) { - return vc1.first::ConstRefIterator(vcs)).filter([](const auto& vc) { - return vc.second < 0; - }).collect>(); - sort(neg.begin(),neg.end(),[](const auto& vc1, const auto& vc2) { - return vc1.firstnode()->trace); switch (_prev->node()->tag) { - case BranchTag::T_TERM: { + case Node::T_TERM: { auto lhs = _prev->node()->lhs; auto rhs = _prev->node()->rhs; Ordering::Result res; @@ -618,35 +318,29 @@ const OrderingComparator::Trace* OrderingComparator::getCurrentTrace() } return Trace::set(_prev->node()->trace, { lhs, rhs, res }); } - case BranchTag::T_DATA: - case BranchTag::T_POLY: { + case Node::T_DATA: + case Node::T_POLY: { return _prev->node()->trace; } } ASSERTION_VIOLATION; } -std::pair OrderingComparator::getPrevPoly() +// Branch + +OrderingComparator::Branch::Branch(void* data, Branch alt) { - auto res = make_pair((Node*)nullptr, Ordering::INCOMPARABLE); - if (_prev) { - // take value from previous node by default - res = _prev->node()->prevPoly; - - // override value if the previous is a poly node - if (_prev->node()->tag == BranchTag::T_POLY) { - res.first = _prev->node(); - if (_curr == &_prev->node()->gtBranch) { - res.second = Ordering::GREATER; - } else if (_curr == &_prev->node()->eqBranch) { - res.second = Ordering::EQUAL; - } else { - ASS_EQ(_curr, &_prev->node()->ngeBranch); - res.second = Ordering::INCOMPARABLE; - } - } - } - return res; + setNode(new Node(data, alt)); +} + +OrderingComparator::Branch::Branch(TermList lhs, TermList rhs) +{ + setNode(new Node(lhs, rhs)); +} + +OrderingComparator::Branch::Branch(const Polynomial* p) +{ + setNode(new Node(p)); } OrderingComparator::Branch::~Branch() @@ -659,6 +353,22 @@ OrderingComparator::Branch::Branch(const Branch& other) setNode(other._node); } +OrderingComparator::Node* OrderingComparator::Branch::node() const +{ + return _node; +} + +void OrderingComparator::Branch::setNode(Node* node) +{ + if (node) { + node->incRefCnt(); + } + if (_node) { + _node->decRefCnt(); + } + _node = node; +} + OrderingComparator::Branch& OrderingComparator::Branch::operator=(const Branch& other) { if (&other==this) { @@ -683,6 +393,17 @@ OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other return *this; } +// Node + +OrderingComparator::Node::Node(void* data, Branch alternative) + : tag(T_DATA), data(data), alternative(alternative) {} + +OrderingComparator::Node::Node(TermList lhs, TermList rhs) + : tag(T_TERM), lhs(lhs), rhs(rhs) {} + +OrderingComparator::Node::Node(const Polynomial* p) + : tag(T_POLY), poly(p) {} + OrderingComparator::Node::~Node() { if (tag==T_DATA) { @@ -705,4 +426,110 @@ void OrderingComparator::Node::decRefCnt() } } +OrderingComparator::Branch& OrderingComparator::Node::getBranch(Ordering::Result r) +{ + switch (r) { + case Ordering::EQUAL: return eqBranch; + case Ordering::GREATER: return gtBranch; + case Ordering::INCOMPARABLE: return ngeBranch; + default: ASSERTION_VIOLATION; + } +} + +// Polynomial + +const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int constant, const Stack& varCoeffPairs) +{ + static Set> polys; + + sort(varCoeffPairs.begin(),varCoeffPairs.end(),[](const auto& vc1, const auto& vc2) { + auto vc1pos = vc1.second>0; + auto vc2pos = vc2.second>0; + return (vc1pos && !vc2pos) || (vc1pos == vc2pos && vc1.first 0) { + out << (first ? "" : " + "); + } else { + out << (first ? "- " : " - "); + } + first = false; + auto abscoeff = std::abs(coeff); + if (abscoeff!=1) { + out << abscoeff << " * "; + } + out << TermList::var(var); + } + if (poly.constant) { + out << (poly.constant<0 ? " - " : " + "); + out << std::abs(poly.constant); + } + return out; +} + +std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) +{ + Stack> todo; + todo.push(std::make_pair(&comp._source,0)); + // Note: using this set we get a more compact representation + DHSet seen; + + while (todo.isNonEmpty()) { + auto kv = todo.pop(); + for (unsigned i = 0; i < kv.second; i++) { + str << ((i+1 == kv.second) ? " |--" : " | "); + } + str << *kv.first->node() << std::endl; + if (seen.insert(kv.first->node())) { + if (kv.first->node()->tag==OrderingComparator::Node::Tag::T_DATA) { + if (kv.first->node()->data) { + todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); + } + } else { + todo.push(std::make_pair(&kv.first->node()->ngeBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->eqBranch,kv.second+1)); + todo.push(std::make_pair(&kv.first->node()->gtBranch,kv.second+1)); + } + } + } + return str; +} + } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 7512c6071..59fe581a0 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -23,9 +23,15 @@ namespace Kernel { /** - * Class implementing runtime specialized ordering check between two terms. - * The comparator is created and called from inside the respective ordering - * object, but owned by the caller, so the destructor is exposed as virtual. + * Class implementing term ordering diagrams which handle the following + * problem. Given pairs (C_1,d_1),...,(C_n,d_n) where C_i are conjunctions + * of ordering constraints and d_i are arbitrary data, and a substitution θ, + * we want to retrieve all d_i s.t. C_iθ is true efficiently. + * + * TODO: refer to paper after publishing. + * + * The diagrams are created and called from inside a specific ordering + * object (KBO or LPO), but owned by the caller, so the destructor is virtual. * See @b KBOComparator and @b LPOComparator for implementation details. */ struct OrderingComparator @@ -34,118 +40,99 @@ struct OrderingComparator OrderingComparator(const Ordering& ord); virtual ~OrderingComparator(); - void reset() { _curr = &_source; _prev = nullptr; /* _trace.reset(); */ } + /** Has to be called each time a new retrieval is started. */ + void init(const SubstApplicator* appl); - void* next(const SubstApplicator* applicator); - void insert(const Stack& comps, void* result); + /** After calling @b init, repeated calls to @b next results in all + * user-defined (non-null) data that has true corresponding ordering + * constraints, or in null when no further such data can be retreived. */ + void* next(); + + /** Inserts a conjunctions of term ordering constraints and user-allocated data. */ + void insert(const Stack& cons, void* data); friend std::ostream& operator<<(std::ostream& out, const OrderingComparator& comp); - std::string to_dot() const; + +private: + /** Processes current node until it is either (i) a term or poly node whose result + * cannot be inferred from earlier comparisons, or (ii) a data node. + * We maintain the invariant that the subgraph containing only processed nodes + * in the diagram is a tree, so that each node can be reached via exactly one path. */ + void processCurrentNode(); + void processVarNode(); + void processPolyNode(); protected: - void expand(); - virtual void expandTermCase(); - void processVarCase(); - void processPolyCase(); - - enum BranchTag { - T_DATA = 0u, - T_TERM = 1u, - T_POLY = 2u, - }; + /** Implements one step of a definitional expansion + * for two terms in a specific term ordering. + * See @b KBOComparator and @b LPOComparator. */ + virtual void processTermNode(); + + /** As noted above, a processed node can be reached via exactly one path, + * and we use this to get a conjunction of term ordering constraints on + * this path which is then used to simplify the node. The trace contains + * these constraints. */ + using Trace = TermPartialOrdering; + const Trace* getCurrentTrace(); struct Node; struct Polynomial; + /** A branch is essentially a shared pointer for a node, + * except the node takes care of its own lifecycle. */ struct Branch { - Node* node() const { return _node; } - void setNode(Node* node) { - if (node) { - node->incRefCnt(); - } - if (_node) { - _node->decRefCnt(); - } - _node = node; - } - Branch() = default; - template Branch(S&& s, T&& t) { - setNode(new Node(std::forward(s), std::forward(t))); - } - Branch(const Polynomial* p) { - setNode(new Node(p)); - } + Branch(void* data, Branch alt); + Branch(TermList lhs, TermList rhs); + Branch(const Polynomial* p); + ~Branch(); + Branch(const Branch& other); Branch& operator=(const Branch& other); Branch(Branch&& other); Branch& operator=(Branch&& other); + Node* node() const; + void setNode(Node* node); + private: Node* _node = nullptr; }; - friend std::ostream& operator<<(std::ostream& out, const Node& node); - friend std::ostream& operator<<(std::ostream& out, const BranchTag& t); - friend std::ostream& operator<<(std::ostream& out, const Polynomial& poly); - - using VarCoeffPair = std::pair; - - struct Polynomial { - static const Polynomial* get(int constant, const Stack& vcs); + /** A node is a structure that either + * (i) contains user-defined data, or + * (ii) represents a term comparison, or + * (iii) represents a polynomial zero check. + */ + struct Node { + enum Tag { + T_DATA = 0u, + T_TERM = 1u, + T_POLY = 2u, + } tag; - auto asTuple() const { return std::make_tuple(constant, pos, neg); } + explicit Node(void* data, Branch alternative); + explicit Node(TermList lhs, TermList rhs); + explicit Node(const Polynomial* p); - IMPL_HASH_FROM_TUPLE(Polynomial); - IMPL_COMPARISONS_FROM_TUPLE(Polynomial); + ~Node(); - int constant; - Stack pos; - Stack neg; - }; + Node(const Node&) = delete; + Node& operator=(const Node&) = delete; - using Trace = TermPartialOrdering; + void incRefCnt(); + void decRefCnt(); - const Trace* getCurrentTrace(); - std::pair getPrevPoly(); + Branch& getBranch(Ordering::Result r); - struct Node { + // We need all this data to be of the same size static_assert(sizeof(uint64_t) == sizeof(Branch)); static_assert(sizeof(uint64_t) == sizeof(TermList)); static_assert(sizeof(uint64_t) == sizeof(void*)); static_assert(sizeof(uint64_t) == sizeof(int64_t)); - auto& getBranch(Ordering::Result r) { - switch (r) { - case Ordering::EQUAL: - return eqBranch; - case Ordering::GREATER: - return gtBranch; - case Ordering::INCOMPARABLE: - return ngeBranch; - default: - ASSERTION_VIOLATION; - } - } - - explicit Node(void* data, Branch alternative) - : tag(T_DATA), data(data), alternative(alternative) {} - explicit Node(TermList lhs, TermList rhs) - : tag(T_TERM), lhs(lhs), rhs(rhs) {} - explicit Node(const Polynomial* p) - : tag(T_POLY), poly(p) {} - Node(const Node&) = delete; - Node& operator=(const Node&) = delete; - - ~Node(); - - void incRefCnt(); - void decRefCnt(); - - BranchTag tag; - bool ready = false; - + // Tag specific data union { void* data = nullptr; TermList lhs; @@ -156,22 +143,41 @@ struct OrderingComparator TermList rhs; }; - Branch eqBranch; Branch gtBranch; + Branch eqBranch; Branch ngeBranch; + bool ready = false; int refcnt = 0; const Trace* trace = nullptr; - // points to the previous node containing a polynomial and branch - // that was taken, otherwise null if no such node exists. - std::pair prevPoly = { nullptr, Result::INCOMPARABLE }; }; + using VarCoeffPair = std::pair; + + struct Polynomial { + static const Polynomial* get(int constant, const Stack& varCoeffPairs); + + auto asTuple() const { return std::make_tuple(constant, varCoeffPairs); } + + IMPL_HASH_FROM_TUPLE(Polynomial); + IMPL_COMPARISONS_FROM_TUPLE(Polynomial); + + int constant; + // variable-coefficient pairs sorted by sign + // (positive first), and then by variable + // e.g. X1 + 2 ⋅ X4 - 5 ⋅ X0 - X3 + Stack varCoeffPairs; + }; + + friend std::ostream& operator<<(std::ostream& out, const Node::Tag& t); + friend std::ostream& operator<<(std::ostream& out, const Node& node); + friend std::ostream& operator<<(std::ostream& out, const Polynomial& poly); + const Ordering& _ord; Branch _source; Branch _sink; Branch* _curr; Branch* _prev; - // Trace _trace; + const SubstApplicator* _appl; }; } // namespace Kernel diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index 09bf1752a..a8cbda28c 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -127,7 +127,7 @@ bool checkCompatibility(PoComp old, PoComp curr, PoComp& res) ASSERTION_VIOLATION; } -string po_to_infix(PoComp c) { +string pocompToInfix(PoComp c) { switch (c) { case PoComp::UNKNOWN: return "?"; @@ -148,10 +148,10 @@ string po_to_infix(PoComp c) { } PartialOrdering::PartialOrdering() - : _size(0), _array(nullptr), _hasIncomp(false), _prev(nullptr) {} + : _size(0), _array(nullptr) {} PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _size(other._size), _array(nullptr), _hasIncomp(other._hasIncomp), _prev(&other) + : _size(other._size), _array(nullptr) { size_t arrSize = ((_size - 1) * _size / 2); if (arrSize) { @@ -175,7 +175,7 @@ PoComp PartialOrdering::get(size_t x, size_t y) const ASS_L(x,_size); ASS_L(y,_size); - return (x < y) ? get_unsafe(x,y) : reverse(get_unsafe(y,x)); + return (x < y) ? getUnsafe(x,y) : reverse(getUnsafe(y,x)); } const PartialOrdering* PartialOrdering::getEmpty() @@ -205,7 +205,7 @@ const PartialOrdering* PartialOrdering::set(const PartialOrdering* po, size_t x, } auto res = new PartialOrdering(*po); bool changed; - if (!res->set_idx_of(x, y, v, changed)) { + if (!res->setRel(x, y, v, changed)) { delete res; *ptr = nullptr; } else if (!changed) { @@ -214,7 +214,7 @@ const PartialOrdering* PartialOrdering::set(const PartialOrdering* po, size_t x, } // if something's changed, we calculate the transitive closure // TODO we could use the value that we get from compatibility checking here - else if (!res->set_inferred(x, y, v)) { + else if (!res->setInferred(x, y, v)) { delete res; *ptr = nullptr; } else { @@ -260,7 +260,7 @@ void PartialOrdering::extend() } } -bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v, bool& changed) +bool PartialOrdering::setRel(size_t x, size_t y, PoComp v, bool& changed) { size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); @@ -271,29 +271,60 @@ bool PartialOrdering::set_idx_of(size_t x, size_t y, PoComp v, bool& changed) } changed = (_array[idx] != new_v); _array[idx] = new_v; - if (new_v == PoComp::INCOMPARABLE) { - _hasIncomp = true; - } return true; } -bool PartialOrdering::set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed) +bool PartialOrdering::setRelSafe(size_t x, size_t y, PoComp v, bool& changed) { if (x < y) { - return set_idx_of(x,y,v,changed); + return setRel(x,y,v,changed); } else { - return set_idx_of(y,x,reverse(v),changed); + return setRel(y,x,reverse(v),changed); } } -PoComp PartialOrdering::get_unsafe(size_t x, size_t y) const +PoComp PartialOrdering::getUnsafe(size_t x, size_t y) const { size_t idx = y*(y-1)/2 + x; ASS_L(idx,((_size - 1) * _size / 2)); return _array[idx]; } -bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) +bool PartialOrdering::setInferred(size_t x, size_t y, PoComp result) +{ + switch (result) { + /* x > y: then ∀z. y ≥ z, also x > z, + and ∀z. z ≥ x, also z > y */ + case PoComp::GREATER: + /* x < y: then ∀z. y ≤ z, also x < z, + and ∀z. z ≤ x, also z < y */ + case PoComp::LESS: + RETURN_IF_FAIL(setInferredHelper(x, y, result)); + break; + /* x = y: then ∀z. z = x, also z = y + and ∀z. z = y, also z = x + and ∀z. z > x, also z > y + and ∀z. z > y, also z > x + and ∀z. z < x, also z < y + and ∀z. z < y, also z < x */ + case PoComp::EQUAL: + RETURN_IF_FAIL(setInferredHelperEq(x, y)); + break; + case PoComp::NGEQ: + case PoComp::NLEQ: + RETURN_IF_FAIL(setInferredHelperInc(x, y, result)); + break; + case PoComp::INCOMPARABLE: + RETURN_IF_FAIL(setInferredHelperInc(x, y, PoComp::NGEQ)); + RETURN_IF_FAIL(setInferredHelperInc(x, y, PoComp::NLEQ)); + break; + default: + break; + } + return true; +} + +bool PartialOrdering::setInferredHelper(size_t x, size_t y, PoComp rel) { ASS_NEQ(x,y); @@ -312,7 +343,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // if rel = ≤: z ≤ x ∧ x ≤ y → z ≤ y // if rel = ≥: z ≥ x ∧ x ≥ y → z ≥ y if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, rel, changed)); + RETURN_IF_FAIL(setRelSafe(z, y, rel, changed)); if (changed) { above.push(z); // TODO find out why we should continue here @@ -322,7 +353,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // if rel = ≤: z ≱ x ∧ x ≤ y → z ≱ y // if rel = ≥: z ≰ x ∧ x ≥ y → z ≰ y else if (r == wkn || r == PoComp::INCOMPARABLE) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn, changed)); + RETURN_IF_FAIL(setRelSafe(z, y, wkn, changed)); if (changed) { above_w.push(z); // TODO find out why we should continue here @@ -334,7 +365,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // x rel y ∧ y rel z → x rel z // x rel y ∧ y = z → x rel z if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, rel, changed)); + RETURN_IF_FAIL(setRelSafe(x, z, rel, changed)); if (changed) { below.push(z); } @@ -342,7 +373,7 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // x rel y ∧ y wkn z → x wkn z // x rel y ∧ y inc z → x wkn z else if (r == wkn || r == PoComp::INCOMPARABLE) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn, changed)); + RETURN_IF_FAIL(setRelSafe(x, z, wkn, changed)); if (changed) { below_w.push(z); } @@ -352,21 +383,21 @@ bool PartialOrdering::set_inferred_loop(size_t x, size_t y, PoComp rel) // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,rel,changed)); + RETURN_IF_FAIL(setRelSafe(z,u,rel,changed)); } for (const auto& u : below_w) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); + RETURN_IF_FAIL(setRelSafe(z,u,wkn,changed)); } } for (const auto& z : above_w) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); + RETURN_IF_FAIL(setRelSafe(z,u,wkn,changed)); } } return true; } -bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) +bool PartialOrdering::setInferredHelperInc(size_t x, size_t y, PoComp wkn) { ASS_NEQ(x,y); @@ -383,7 +414,7 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) // z ≤ x ∧ x ≱ y → z ≱ y // z ≥ x ∧ x ≰ y → z ≰ y if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, wkn, changed)); + RETURN_IF_FAIL(setRelSafe(z, y, wkn, changed)); if (changed) { above.push(z); // TODO find out why we should continue here @@ -394,7 +425,7 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) // x ≱ y ∧ y ≤ z → x ≱ z // x ≰ y ∧ y ≥ z → x ≰ z if (r == rel || r == PoComp::EQUAL) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, wkn, changed)); + RETURN_IF_FAIL(setRelSafe(x, z, wkn, changed)); if (changed) { below.push(z); } @@ -404,13 +435,13 @@ bool PartialOrdering::set_inferred_loop_inc(size_t x, size_t y, PoComp wkn) // connect all pairs that have been derived for (const auto& z : above) { for (const auto& u : below) { - RETURN_IF_FAIL(set_idx_of_safe(z,u,wkn,changed)); + RETURN_IF_FAIL(setRelSafe(z,u,wkn,changed)); } } return true; } -bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) +bool PartialOrdering::setInferredHelperEq(size_t x, size_t y) { ASS_NEQ(x,y); @@ -426,7 +457,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) } auto r = get(z, x); if (r != PoComp::UNKNOWN) { - RETURN_IF_FAIL(set_idx_of_safe(z, y, r, changed)); + RETURN_IF_FAIL(setRelSafe(z, y, r, changed)); if (changed) { x_rel.push({ z, r }); // TODO find out why we should continue here @@ -435,7 +466,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) } r = get(y, z); if (r != PoComp::UNKNOWN) { - RETURN_IF_FAIL(set_idx_of_safe(x, z, r, changed)); + RETURN_IF_FAIL(setRelSafe(x, z, r, changed)); if (changed) { y_rel.push({ z, r }); } @@ -452,7 +483,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) case PoComp::EQUAL: { for (const auto& [u,ru] : y_rel) { // z = x ∧ x ru u → z ru u - RETURN_IF_FAIL(set_idx_of_safe(z, u, ru, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, ru, changed)); } break; } @@ -462,12 +493,12 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z > x ∧ x ≥ u → z > u case PoComp::EQUAL: case PoComp::GREATER: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::GREATER, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::GREATER, changed)); break; // z > x ∧ x ≰ u → z ≰ u case PoComp::NLEQ: case PoComp::INCOMPARABLE: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NLEQ, changed)); break; // z > x ∧ x < u implies nothing case PoComp::LESS: @@ -486,12 +517,12 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z < x ∧ x ≤ u → z < u case PoComp::EQUAL: case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::LESS, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::LESS, changed)); break; // z < x ∧ x ≱ u → z ≱ u case PoComp::NGEQ: case PoComp::INCOMPARABLE: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NGEQ, changed)); break; // z < x ∧ x > u implies nothing case PoComp::GREATER: @@ -509,15 +540,15 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) switch (ru) { // z ≰ x ∧ x > u → z ≰ u case PoComp::GREATER: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NLEQ, changed)); break; // z ⋈ x ∧ x = u → z ⋈ u case PoComp::EQUAL: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::INCOMPARABLE, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::INCOMPARABLE, changed)); break; // z ≱ x ∧ x < u → z ≱ u case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NGEQ, changed)); break; // z ⋈ x ∧ x ≱ u implies nothing case PoComp::NGEQ: @@ -538,7 +569,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≱ x ∧ x ≤ u → z ≱ u case PoComp::EQUAL: case PoComp::LESS: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NGEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NGEQ, changed)); break; // z ≱ x ∧ x > u implies nothing case PoComp::GREATER: @@ -561,7 +592,7 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) // z ≰ x ∧ x ≥ u → z ≰ u case PoComp::GREATER: case PoComp::EQUAL: - RETURN_IF_FAIL(set_idx_of_safe(z, u, PoComp::NLEQ, changed)); + RETURN_IF_FAIL(setRelSafe(z, u, PoComp::NLEQ, changed)); break; // z ≰ x ∧ x < u implies nothing case PoComp::LESS: @@ -585,80 +616,33 @@ bool PartialOrdering::set_inferred_loop_eq(size_t x, size_t y) return true; } -bool PartialOrdering::set_inferred(size_t x, size_t y, PoComp result) +ostream& operator<<(ostream& str, const PartialOrdering& po) { - switch (result) { - /* x > y: then ∀z. y ≥ z, also x > z, - and ∀z. z ≥ x, also z > y */ - case PoComp::GREATER: - /* x < y: then ∀z. y ≤ z, also x < z, - and ∀z. z ≤ x, also z < y */ - case PoComp::LESS: - RETURN_IF_FAIL(set_inferred_loop(x, y, result)); - break; - /* x = y: then ∀z. z = x, also z = y - and ∀z. z = y, also z = x - and ∀z. z > x, also z > y - and ∀z. z > y, also z > x - and ∀z. z < x, also z < y - and ∀z. z < y, also z < x */ - case PoComp::EQUAL: - RETURN_IF_FAIL(set_inferred_loop_eq(x, y)); - break; - case PoComp::NGEQ: - case PoComp::NLEQ: - RETURN_IF_FAIL(set_inferred_loop_inc(x, y, result)); - break; - case PoComp::INCOMPARABLE: - RETURN_IF_FAIL(set_inferred_loop_inc(x, y, PoComp::NGEQ)); - RETURN_IF_FAIL(set_inferred_loop_inc(x, y, PoComp::NLEQ)); - break; - default: - break; + if (po._size == 0) { + return str << " {} "; } - return true; -} - -string PartialOrdering::to_string() const -{ - if (_size == 0) { - return " {} "; - } - stringstream str; - size_t s = _size-1; + size_t s = po._size-1; size_t w = 0; while (s) { s /= 10; w++; } - for (size_t i = 0; i < _size; i++) { + for (size_t i = 0; i < po._size; i++) { str << std::setw(w) << i << " "; for (size_t j = 0; j < i; j++) { if (w>1) { str << std::setw(w-1) << " "; } - str << po_to_infix(get_unsafe(j,i)) << " "; + str << pocompToInfix(po.getUnsafe(j,i)) << " "; } if (w>1) { str << std::setw(w-1) << " "; } - str << po_to_infix(PoComp::EQUAL) << " " << endl; + str << pocompToInfix(PoComp::EQUAL) << " " << endl; } str << std::setw(w) << " " << " "; - for (size_t i = 0; i < _size; i++) { + for (size_t i = 0; i < po._size; i++) { str << std::setw(w) << i << " "; } - return str.str(); -} - -string PartialOrdering::all_to_string() const -{ - stringstream res; - auto curr = this; - while (curr) { - res << curr << " " << curr->_array << endl; - res << curr->to_string() << endl; - curr = curr->_prev; - } - return res.str(); + return str; } } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index 29fdc9f2f..a597f35ac 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -9,7 +9,7 @@ */ /** * @file PartialOrdering.hpp - * Defines class PartialOrdering. + * Defines a partial ordering between elements of some set. */ #ifndef __PartialOrdering__ @@ -19,6 +19,9 @@ namespace Kernel { +/** This corresponds to the values we can handle between two elements. + * Note that incomparability is also possible, namely ≱ (NGEQ), + * ≰ (NLEQ) and their conjunction (INCOMPARABLE). */ enum class PoComp : uint8_t { UNKNOWN, GREATER, @@ -30,45 +33,53 @@ enum class PoComp : uint8_t { }; bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); -std::string po_to_infix(PoComp c); - +std::string pocompToInfix(PoComp c); + +/** + * Partial ordering between elements of some set. The set elements + * are denoted by IDs inside the class, which is given by order of + * appearance, as explained below. The set elements are abstracted + * via these IDs to increase sharing among partial ordering objects. + * Hence, operations modifying the objects are performed through + * static methods. + */ class PartialOrdering { public: + /** Get relation between two elements with IDs @b x and @b y. */ PoComp get(size_t x, size_t y) const; + /** Get empty partial ordering. */ static const PartialOrdering* getEmpty(); - static const PartialOrdering* set(const PartialOrdering* po, size_t x, size_t y, PoComp v); + /** Add new element to partial ordering. The ID of this + * element is set to @b size()-1 of the new partial ordering. */ static const PartialOrdering* extend(const PartialOrdering* po); + /** Tries to set relation between two elements with IDs @b x and @b y, + * and performs transitive closure over the entire set so far. + * If this fails, returns null, otherwise returns a non-null object. */ + static const PartialOrdering* set(const PartialOrdering* po, size_t x, size_t y, PoComp v); - // Returns if PO contains full incomparability yet. - // Useful to discard branches when reasoning over ground terms. - bool hasIncomp() const { return _hasIncomp; } - - std::string to_string() const; - std::string all_to_string() const; + friend std::ostream& operator<<(std::ostream& str, const PartialOrdering& po); private: PartialOrdering(); - PartialOrdering(const PartialOrdering& other); ~PartialOrdering(); + PartialOrdering(const PartialOrdering& other); PartialOrdering& operator=(const PartialOrdering&) = delete; void extend(); - PoComp get_unsafe(size_t x, size_t y) const; - bool set_idx_of(size_t x, size_t y, PoComp v, bool& changed); - bool set_idx_of_safe(size_t x, size_t y, PoComp v, bool& changed); + PoComp getUnsafe(size_t x, size_t y) const; + bool setRel(size_t x, size_t y, PoComp v, bool& changed); + bool setRelSafe(size_t x, size_t y, PoComp v, bool& changed); - bool set_inferred(size_t x, size_t y, PoComp result); - bool set_inferred_loop(size_t x, size_t y, PoComp rel); - bool set_inferred_loop_inc(size_t x, size_t y, PoComp wkn); - bool set_inferred_loop_eq(size_t x, size_t y); + bool setInferred(size_t x, size_t y, PoComp result); + bool setInferredHelper(size_t x, size_t y, PoComp rel); + bool setInferredHelperInc(size_t x, size_t y, PoComp wkn); + bool setInferredHelperEq(size_t x, size_t y); size_t _size; PoComp* _array; - bool _hasIncomp; - const PartialOrdering* _prev; }; }; diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index d2b111351..76f1b69f0 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -21,6 +21,8 @@ namespace Kernel { using namespace std; +// Helper functions + Result poCompToResult(PoComp c) { switch (c) { case PoComp::GREATER: @@ -52,7 +54,96 @@ PoComp resultToPoComp(Result r, bool reversed) { } } -PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const +// TermPartialOrdering + +bool TermPartialOrdering::get(TermList lhs, TermList rhs, Result& res) const +{ + // comparable terms should be handled by caller + ASS_EQ(_ord.compare(lhs,rhs),Ordering::INCOMPARABLE); + // proper term pairs should be handled by caller + ASS(lhs.isVar() || rhs.isVar()); + + if (lhs == rhs) { + res = Result::EQUAL; + return true; + } + PoComp val; + bool reversed = false; + // If one or two of the terms is not in the partial ordering, + // we try to relate them through terms in the relation + if (!_nodes.find(lhs) && !_nodes.find(rhs)) + { + val = getTwoExternal(lhs, rhs); + } + else if (!_nodes.find(lhs)) + { + ASS(_nodes.find(rhs)); + size_t y = getId(rhs); + val = getOneExternal(lhs, y); + } + else if (!_nodes.find(rhs)) + { + ASS(_nodes.find(lhs)); + size_t x = getId(lhs); + val = getOneExternal(rhs, x); + reversed = true; + } + // Otherwise we relate them directly assuming that + // the relation is already transitively closed. + else + { + size_t x = getId(lhs); + size_t y = getId(rhs); + reversed = x > y; + if (reversed) { + swap(x,y); + } + val = _po->get(x,y); + } + if (val == PoComp::UNKNOWN) { + return false; + } + // TODO: we currently assume that the caller is + // only interested in lhs ≱ rhs, so if we only + // have lhs ≰ rhs, we do not return anything. + if (reversed) { + if (val == PoComp::NGEQ) { + return false; + } + res = Ordering::reverse(poCompToResult(val)); + return true; + } else { + if (val == PoComp::NLEQ) { + return false; + } + res = poCompToResult(val); + return true; + } +} + +const TermPartialOrdering* TermPartialOrdering::getEmpty(const Ordering& ord) +{ + static TermPartialOrdering empty(ord); + return ∅ +} + +const TermPartialOrdering* TermPartialOrdering::set(const TermPartialOrdering* tpo, TermOrderingConstraint con) +{ + static DHMap, const TermPartialOrdering*> cache; + const TermPartialOrdering** ptr; + if (cache.getValuePtr(make_tuple(tpo, con.lhs, con.rhs, con.rel), ptr, nullptr)) { + auto res = new TermPartialOrdering(*tpo); + if (!res->set(con)) { + delete res; + *ptr = nullptr; + } else { + *ptr = res; + } + } + return *ptr; +} + +PoComp TermPartialOrdering::getOneExternal(TermList t, size_t idx) const { PoComp res = PoComp::UNKNOWN; decltype(_nodes)::Iterator it(_nodes); @@ -116,7 +207,7 @@ PoComp TermPartialOrdering::get_one_external(TermList t, size_t idx) const return res; } -PoComp TermPartialOrdering::get_two_external(TermList t1, TermList t2) const +PoComp TermPartialOrdering::getTwoExternal(TermList t1, TermList t2) const { PoComp res = PoComp::UNKNOWN; Stack> t1_rel; // ∃x. t1 rel x @@ -201,71 +292,10 @@ PoComp TermPartialOrdering::get_two_external(TermList t1, TermList t2) const return res; } -bool TermPartialOrdering::get(TermList lhs, TermList rhs, Result& res) const -{ - // comparable terms should be handled by caller - ASS_EQ(_ord.compare(lhs,rhs),Ordering::INCOMPARABLE); - // proper term pairs should be handled by caller - ASS(lhs.isVar() || rhs.isVar()); - - if (lhs == rhs) { - res = Result::EQUAL; - return true; - } - PoComp val; - bool reversed = false; - if (!_nodes.find(lhs) && !_nodes.find(rhs)) - { - val = get_two_external(lhs, rhs); - } - else if (!_nodes.find(lhs)) - { - ASS(_nodes.find(rhs)); - size_t y = idx_of_elem(rhs); - val = get_one_external(lhs, y); - } - else if (!_nodes.find(rhs)) - { - ASS(_nodes.find(lhs)); - size_t x = idx_of_elem(lhs); - val = get_one_external(rhs, x); - reversed = true; - } - else - { - size_t x = idx_of_elem(lhs); - size_t y = idx_of_elem(rhs); - reversed = x > y; - if (reversed) { - swap(x,y); - } - val = _po->get(x,y); - } - if (val == PoComp::UNKNOWN) { - return false; - } - // if we only have INCOMPARABLE in the "other direction" - // as we use isGreater which never gives LESS, we cannot - // distinguish between the two LESS and INCOMPARABLE - if (reversed) { - if (val == PoComp::NGEQ) { - return false; - } - res = Ordering::reverse(poCompToResult(val)); - return true; - } else { - if (val == PoComp::NLEQ) { - return false; - } - res = poCompToResult(val); - return true; - } -} - -bool TermPartialOrdering::set(Ordering::Constraint con) +bool TermPartialOrdering::set(TermOrderingConstraint con) { - size_t x = idx_of_elem_ext(con.lhs); - size_t y = idx_of_elem_ext(con.rhs); + size_t x = getIdExt(con.lhs); + size_t y = getIdExt(con.rhs); bool reversed = x > y; if (reversed) { @@ -282,40 +312,13 @@ bool TermPartialOrdering::set(Ordering::Constraint con) return true; } -bool TermPartialOrdering::hasIncomp() const -{ - return _po->hasIncomp(); -} - -const TermPartialOrdering* TermPartialOrdering::getEmpty(const Ordering& ord) -{ - static TermPartialOrdering empty(ord); - return ∅ -} - -const TermPartialOrdering* TermPartialOrdering::set(const TermPartialOrdering* tpo, Ordering::Constraint con) -{ - static DHMap, const TermPartialOrdering*> cache; - const TermPartialOrdering** ptr; - if (cache.getValuePtr(make_tuple(tpo, con.lhs, con.rhs, con.rel), ptr, nullptr)) { - auto res = new TermPartialOrdering(*tpo); - if (!res->set(con)) { - delete res; - *ptr = nullptr; - } else { - *ptr = res; - } - } - return *ptr; -} - -size_t TermPartialOrdering::idx_of_elem(TermList t) const +size_t TermPartialOrdering::getId(TermList t) const { ASS(_nodes.find(t)); return _nodes.get(t); } -size_t TermPartialOrdering::idx_of_elem_ext(TermList t) +size_t TermPartialOrdering::getIdExt(TermList t) { size_t *ptr; if (_nodes.getValuePtr(t, ptr, _nodes.size())) { @@ -341,67 +344,49 @@ size_t TermPartialOrdering::idx_of_elem_ext(TermList t) return *ptr; } -string TermPartialOrdering::to_string() const +ostream& operator<<(ostream& str, const TermPartialOrdering& tpo) { - stringstream str; - for (unsigned i = 0; i < _nodes.size(); i++) { - typename Map::Iterator it(_nodes); - while (it.hasNext()) { - const auto& e = it.next(); - if (e.value() != i) { - continue; - } - str << e.value() << ": " << e.key() << ", "; - } - } - str << endl << _po->to_string(); - return str.str(); -} - -string TermPartialOrdering::to_nice_string() const -{ - stringstream str; - typename Map::Iterator it1(_nodes); + typename Map::Iterator it1(tpo._nodes); while (it1.hasNext()) { const auto& e1 = it1.next(); - typename Map::Iterator it2(_nodes); + typename Map::Iterator it2(tpo._nodes); while (it2.hasNext()) { const auto& e2 = it2.next(); if (e1.value() >= e2.value()) { continue; } - auto pocomp = _po->get(e1.value(),e2.value()); + auto pocomp = tpo._po->get(e1.value(),e2.value()); if (pocomp == PoComp::UNKNOWN) { continue; } - str << e1.key() << " " << po_to_infix(pocomp) << " " << e2.key() << endl; + str << e1.key() << " " << pocompToInfix(pocomp) << " " << e2.key() << endl; } } - return str.str(); + return str; } #if DEBUG_ORDERING void TermPartialOrdering::debug_check() const { - auto output_args = [this](size_t x, size_t y, size_t z) { - return _po->all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); - }; + // auto output_args = [this](size_t x, size_t y, size_t z) { + // return _po->all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); + // }; - auto check_val = [&output_args](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { + auto check_val = [/* &output_args */](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { if (actual_val == PoComp::UNKNOWN) { - INVALID_OPERATION(output_args(x,y,z)); + // INVALID_OPERATION(output_args(x,y,z)); } if (expected_val == PoComp::NLEQ) { if (actual_val != PoComp::NLEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::GREATER) { - INVALID_OPERATION(output_args(x,y,z)); + // INVALID_OPERATION(output_args(x,y,z)); } } else if (expected_val == PoComp::NGEQ) { if (actual_val != PoComp::NGEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::LESS) { - INVALID_OPERATION(output_args(x,y,z)); + // INVALID_OPERATION(output_args(x,y,z)); } } else { if (actual_val != expected_val) { - INVALID_OPERATION(output_args(x,y,z)); + // INVALID_OPERATION(output_args(x,y,z)); } } }; diff --git a/Kernel/TermPartialOrdering.hpp b/Kernel/TermPartialOrdering.hpp index 1413d6a2c..6d6756297 100644 --- a/Kernel/TermPartialOrdering.hpp +++ b/Kernel/TermPartialOrdering.hpp @@ -27,31 +27,54 @@ namespace Kernel { using namespace Lib; using Result = Ordering::Result; +/** + * Class for ordering constraints capturing expressions + * s ≻ t, s = t, s ≺ t or s ⋈ t for some terms s and t. + */ +struct TermOrderingConstraint { + TermList lhs; + TermList rhs; + Result rel; + + friend std::ostream& operator<<(std::ostream& out, const TermOrderingConstraint& con) + { return out << con.lhs << " " << con.rhs << " " << con.rel; } +}; + +/** + * Class that represents a partial ordering between terms. + * Uses @b PartialOrdering and is built similarly to increase + * sharing. + * + * Note that the structure is not complete as it is an under- + * approximation of the actual relation. For example, given + * x = f(y,z) and y = z, we should conclude x = f(z,y) but + * this is in general hard to calculate so we fail. + */ class TermPartialOrdering { public: - TermPartialOrdering(const Ordering& ord) : _ord(ord), _po(PartialOrdering::getEmpty()) {} - ~TermPartialOrdering() = default; - + /** Gets relation between two terms. If they are related, returns true + * and set the relation in @b res. Otherwise returns false. */ bool get(TermList lhs, TermList rhs, Result& res) const; - bool set(Ordering::Constraint con); + /** Get empty relation. */ static const TermPartialOrdering* getEmpty(const Ordering& ord); - static const TermPartialOrdering* set(const TermPartialOrdering* tpo, Ordering::Constraint con); + /** Set relation between two terms given by a term ordering constraint. */ + static const TermPartialOrdering* set(const TermPartialOrdering* tpo, TermOrderingConstraint con); - // Returns if PO contains full incomparability yet. - // Useful to discard branches when reasoning over ground terms. - bool hasIncomp() const; - - std::string to_string() const; - std::string to_nice_string() const; + friend std::ostream& operator<<(std::ostream& str, const TermPartialOrdering& tpo); private: - PoComp get_one_external(TermList t, size_t idx) const; - PoComp get_two_external(TermList t1, TermList t2) const; + TermPartialOrdering(const Ordering& ord) : _ord(ord), _po(PartialOrdering::getEmpty()) {} + ~TermPartialOrdering() = default; + + bool set(TermOrderingConstraint con); + + PoComp getOneExternal(TermList t, size_t idx) const; + PoComp getTwoExternal(TermList t1, TermList t2) const; - size_t idx_of_elem(TermList t) const; - size_t idx_of_elem_ext(TermList t); + size_t getId(TermList t) const; + size_t getIdExt(TermList t); #if DEBUG_ORDERING void debug_check() const; diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 1cc36ece9..2d7bb83a5 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -161,8 +161,8 @@ class ConditionalRedundancyHandler::ConstraintIndex ordCon.comp = ord->createComparator(); ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }, (void*)0x1); } - ordCon.comp->reset(); - return ordCon.comp->next(&applicator); + ordCon.comp->init(&applicator); + return ordCon.comp->next(); }); if (!ordCons_ok) { continue; From 0cd43d6e58c4082fb996c66de3a0380e4a30b94a Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Mon, 23 Dec 2024 13:53:49 +0100 Subject: [PATCH 57/64] Add new files to Makefile --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e84e34b3f..d9494ed37 100644 --- a/Makefile +++ b/Makefile @@ -193,8 +193,9 @@ VK_OBJ= Kernel/Clause.o\ Kernel/MLMatcherSD.o\ Kernel/MLVariant.o\ Kernel/Ordering.o\ - Kernel/Ordering_Equality.o\ Kernel/OrderingComparator.o\ + Kernel/Ordering_Equality.o\ + Kernel/PartialOrdering.o\ Kernel/Problem.o\ Kernel/Renaming.o\ Kernel/RobSubstitution.o\ @@ -206,9 +207,10 @@ VK_OBJ= Kernel/Clause.o\ Kernel/SubformulaIterator.o\ Kernel/Substitution.o\ Kernel/Term.o\ - Kernel/PolynomialNormalizer.o\ - Kernel/Polynomial.o\ + Kernel/PolynomialNormalizer.o\ + Kernel/Polynomial.o\ Kernel/TermIterators.o\ + Kernel/TermPartialOrdering.o\ Kernel/TermTransformer.o\ Kernel/Theory.o\ Kernel/Signature.o\ From 169bb52dcccbe8179b33be4d7df21de75205c1ba Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 3 Jan 2025 13:56:42 +0100 Subject: [PATCH 58/64] Clean up ctor/assignment operators for OrderingComparator::Branch; add less vague comment --- Kernel/OrderingComparator.cpp | 29 ++++++++--------------------- Kernel/OrderingComparator.hpp | 3 +-- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 261d0297c..6c702203d 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -160,8 +160,8 @@ void OrderingComparator::processCurrentNode() if (node->tag == Node::T_DATA) { ASS(node->data); // no fail nodes here - // if refcnt > 1 we copy the node and - // we can also safely use the original + // if refcnt > 1 we have to copy the node, + // otherwise we can mutate the original if (node->refcnt > 1) { *_curr = Branch(node->data, node->alternative); } @@ -211,8 +211,8 @@ void OrderingComparator::processVarNode() } return; } - // if refcnt > 1 we copy the node and - // we can also safely use the original + // if refcnt > 1 we have to copy the node, + // otherwise we can mutate the original if (node->refcnt > 1) { *_curr = Branch(node->lhs, node->rhs); _curr->node()->eqBranch = node->eqBranch; @@ -273,8 +273,8 @@ void OrderingComparator::processPolyNode() } auto poly = Polynomial::get(constant, vcs); - // if refcnt > 1 we copy the node and - // we can also safely use the original + // if refcnt > 1 we have to copy the node, + // otherwise we can mutate the original if (node->refcnt > 1) { *_curr = Branch(poly); _curr->node()->eqBranch = node->eqBranch; @@ -369,26 +369,13 @@ void OrderingComparator::Branch::setNode(Node* node) _node = node; } -OrderingComparator::Branch& OrderingComparator::Branch::operator=(const Branch& other) -{ - if (&other==this) { - return *this; - } - setNode(other.node()); - return *this; -} - OrderingComparator::Branch::Branch(Branch&& other) - : _node(other._node) { - other._node = nullptr; + swap(_node,other._node); } -OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch&& other) +OrderingComparator::Branch& OrderingComparator::Branch::operator=(Branch other) { - if (&other==this) { - return *this; - } swap(_node,other._node); return *this; } diff --git a/Kernel/OrderingComparator.hpp b/Kernel/OrderingComparator.hpp index 59fe581a0..3df30640c 100644 --- a/Kernel/OrderingComparator.hpp +++ b/Kernel/OrderingComparator.hpp @@ -89,9 +89,8 @@ struct OrderingComparator ~Branch(); Branch(const Branch& other); - Branch& operator=(const Branch& other); Branch(Branch&& other); - Branch& operator=(Branch&& other); + Branch& operator=(Branch other); Node* node() const; void setNode(Node* node); From c816f4e1abfa7b28c4cfc83e6a6ead6dafa94c20 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 3 Jan 2025 14:10:12 +0100 Subject: [PATCH 59/64] Clean up mentions to enums; remove debug code except checks in fw demodulation; clean up fw demodulation a bit --- Inferences/ForwardDemodulation.cpp | 28 +++----- Kernel/Ordering.hpp | 2 - Kernel/OrderingComparator.cpp | 22 +++--- Kernel/TermPartialOrdering.cpp | 110 +---------------------------- Kernel/TermPartialOrdering.hpp | 4 -- 5 files changed, 26 insertions(+), 140 deletions(-) diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 23f1af308..944a9dc57 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -162,9 +162,6 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* } } - TermList rhs = qr.data->rhs; - bool preordered = qr.data->preordered; - auto subs = qr.unifier; ASS(subs->isIdentityOnQueryWhenResultBound()); @@ -172,23 +169,21 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* Applicator applWithoutEqSort(subs.ptr()); auto appl = lhs.isVar() ? (SubstApplicator*)&applWithEqSort : (SubstApplicator*)&applWithoutEqSort; + AppliedTerm rhsApplied(qr.data->rhs,appl,true); + bool preordered = qr.data->preordered; + if (_precompiledComparison) { +#if VDEBUG + auto dcomp = ordering.isGreaterOrEq(trm,rhsApplied); +#endif qr.data->comparator->init(appl); if (!preordered && (_preorderedOnly || !qr.data->comparator->next())) { -#if DEBUG_ORDERING - if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))==Ordering::GREATER) { - INVALID_OPERATION("greater"); - } -#endif + ASS_NEQ(dcomp,Ordering::GREATER); continue; } -#if DEBUG_ORDERING - if (ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER) { - INVALID_OPERATION("not greater"); - } -#endif + ASS_EQ(dcomp,Ordering::GREATER); } else { - if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(AppliedTerm(trm),AppliedTerm(rhs,appl,true))!=Ordering::GREATER)) { + if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(trm,rhsApplied)!=Ordering::GREATER)) { continue; } } @@ -205,10 +200,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* } } - TermList rhsS = subs->applyToBoundResult(rhs); - if (lhs.isVar()) { - rhsS = eqSortSubs.apply(rhsS, 0); - } + TermList rhsS = rhsApplied.apply(); if (redundancyCheck && !_helper.isPremiseRedundant(cl, lit, trm, rhsS, lhs, appl)) { continue; diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index cf1bf1f84..adee6df69 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -30,8 +30,6 @@ #include "Lib/Portability.hpp" #include "Kernel/SubstHelper.hpp" -#define DEBUG_ORDERING 0 - namespace Kernel { diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index 6c702203d..c8bf3db7d 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -69,7 +69,7 @@ void* OrderingComparator::next() AppliedTerm(node->rhs, _appl, true)); } else { - ASS(node->tag == Node::T_POLY); + ASS_EQ(node->tag, Node::T_POLY); const auto& kbo = static_cast(_ord); auto weight = node->poly->constant; @@ -451,20 +451,24 @@ const OrderingComparator::Polynomial* OrderingComparator::Polynomial::get(int co std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node::Tag& t) { + using Tag = OrderingComparator::Node::Tag; switch (t) { - case OrderingComparator::Node::T_DATA: return out << "d"; - case OrderingComparator::Node::T_TERM: return out << "t"; - case OrderingComparator::Node::T_POLY: return out << "p"; + case Tag::T_DATA: return out << "d"; + case Tag::T_TERM: return out << "t"; + case Tag::T_POLY: return out << "p"; + default: ASSERTION_VIOLATION; } } std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node) { - out << (OrderingComparator::Node::Tag)node.tag << (node.ready?" ":"? "); + using Tag = OrderingComparator::Node::Tag; + out << (Tag)node.tag << (node.ready?" ":"? "); switch (node.tag) { - case OrderingComparator::Node::Tag::T_DATA: return out << node.data; - case OrderingComparator::Node::Tag::T_POLY: return out << *node.poly; - case OrderingComparator::Node::Tag::T_TERM: return out << node.lhs << " " << node.rhs; + case Tag::T_DATA: return out << node.data; + case Tag::T_POLY: return out << *node.poly; + case Tag::T_TERM: return out << node.lhs << " " << node.rhs; + default: ASSERTION_VIOLATION; } } @@ -505,7 +509,7 @@ std::ostream& operator<<(std::ostream& str, const OrderingComparator& comp) } str << *kv.first->node() << std::endl; if (seen.insert(kv.first->node())) { - if (kv.first->node()->tag==OrderingComparator::Node::Tag::T_DATA) { + if (kv.first->node()->tag==OrderingComparator::Node::T_DATA) { if (kv.first->node()->data) { todo.push(std::make_pair(&kv.first->node()->alternative,kv.second+1)); } diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index 76f1b69f0..b990bef2f 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -36,9 +36,8 @@ Result poCompToResult(PoComp c) { case PoComp::INCOMPARABLE: return Result::INCOMPARABLE; default: - break; + ASSERTION_VIOLATION; } - ASSERTION_VIOLATION; } PoComp resultToPoComp(Result r, bool reversed) { @@ -51,6 +50,8 @@ PoComp resultToPoComp(Result r, bool reversed) { return reversed ? PoComp::GREATER : PoComp::LESS; case Result::INCOMPARABLE: return reversed ? PoComp::NLEQ : PoComp::NGEQ; + default: + ASSERTION_VIOLATION; } } @@ -306,9 +307,6 @@ bool TermPartialOrdering::set(TermOrderingConstraint con) if (!_po) { return false; } -#if DEBUG_ORDERING - // debug_check(); -#endif return true; } @@ -365,106 +363,4 @@ ostream& operator<<(ostream& str, const TermPartialOrdering& tpo) return str; } -#if DEBUG_ORDERING -void TermPartialOrdering::debug_check() const -{ - // auto output_args = [this](size_t x, size_t y, size_t z) { - // return _po->all_to_string() + " at " + Int::toString(x) + ", " + Int::toString(y) + ", " + Int::toString(z); - // }; - - auto check_val = [/* &output_args */](auto actual_val, auto expected_val, size_t x, size_t y, size_t z) { - if (actual_val == PoComp::UNKNOWN) { - // INVALID_OPERATION(output_args(x,y,z)); - } - if (expected_val == PoComp::NLEQ) { - if (actual_val != PoComp::NLEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::GREATER) { - // INVALID_OPERATION(output_args(x,y,z)); - } - } else if (expected_val == PoComp::NGEQ) { - if (actual_val != PoComp::NGEQ && actual_val != PoComp::INCOMPARABLE && actual_val != PoComp::LESS) { - // INVALID_OPERATION(output_args(x,y,z)); - } - } else { - if (actual_val != expected_val) { - // INVALID_OPERATION(output_args(x,y,z)); - } - } - }; - - decltype(_nodes)::Iterator it1(_nodes); - while (it1.hasNext()) { - auto& e1 = it1.next(); - - decltype(_nodes)::Iterator it2(_nodes); - while (it2.hasNext()) { - auto& e2 = it2.next(); - if (e1.value() == e2.value()) { - continue; - } - auto v12 = _po->get(e1.value(),e2.value()); - if (v12 == PoComp::UNKNOWN) { - continue; - } - auto comp = _ord.compare(e1.key(),e2.key()); - if (comp != Ordering::INCOMPARABLE) { - check_val(v12, resultToPoComp(comp, false), e1.value(), e2.value(), e2.value()); - } - - decltype(_nodes)::Iterator it3(_nodes); - while (it3.hasNext()) { - auto& e3 = it3.next(); - if (e1.value() == e3.value() || e2.value() == e3.value()) { - continue; - } - - auto v13 = _po->get(e1.value(),e3.value()); - if (v13 == PoComp::UNKNOWN) { - continue; - } - - auto v23 = _po->get(e2.value(),e3.value()); - - switch (v12) { - case PoComp::UNKNOWN: - break; - case PoComp::EQUAL: - // x = y rel z -> x rel z - check_val(v13, v23, e1.value(), e2.value(), e3.value()); - break; - case PoComp::GREATER: - case PoComp::NLEQ: { - if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { - // x > y ≥ z -> x > z - // x ≰ y ≥ z -> x ≰ z - check_val(v13, v12, e1.value(), e2.value(), e3.value()); - } - break; - } - case PoComp::LESS: - case PoComp::NGEQ: { - if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { - // x < y ≤ z -> x < z - // x ≱ y ≤ z -> x ≱ z - check_val(v13, v12, e1.value(), e2.value(), e3.value()); - } - break; - } - case PoComp::INCOMPARABLE: { - if (v23 == PoComp::EQUAL || v23 == PoComp::GREATER) { - // x ≰ y ≥ z -> x ≰ z - check_val(v13, PoComp::NLEQ, e1.value(), e2.value(), e3.value()); - } - if (v23 == PoComp::EQUAL || v23 == PoComp::LESS) { - // x ≱ y ≤ z -> x ≱ z - check_val(v13, PoComp::NGEQ, e1.value(), e2.value(), e3.value()); - } - break; - } - } - } - } - } -} -#endif - } diff --git a/Kernel/TermPartialOrdering.hpp b/Kernel/TermPartialOrdering.hpp index 6d6756297..9a70ecee7 100644 --- a/Kernel/TermPartialOrdering.hpp +++ b/Kernel/TermPartialOrdering.hpp @@ -76,10 +76,6 @@ class TermPartialOrdering size_t getId(TermList t) const; size_t getIdExt(TermList t); -#if DEBUG_ORDERING - void debug_check() const; -#endif - const Ordering& _ord; Map _nodes; const PartialOrdering* _po; From 60607bca8e34c57707b158c66bc756f1aba1bde2 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 3 Jan 2025 14:50:04 +0100 Subject: [PATCH 60/64] Document PartialOrdering --- Kernel/PartialOrdering.hpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index a597f35ac..c29dc31d1 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -9,7 +9,6 @@ */ /** * @file PartialOrdering.hpp - * Defines a partial ordering between elements of some set. */ #ifndef __PartialOrdering__ @@ -35,13 +34,24 @@ enum class PoComp : uint8_t { bool checkCompatibility(PoComp old, PoComp curr, PoComp& res); std::string pocompToInfix(PoComp c); -/** - * Partial ordering between elements of some set. The set elements - * are denoted by IDs inside the class, which is given by order of - * appearance, as explained below. The set elements are abstracted - * via these IDs to increase sharing among partial ordering objects. - * Hence, operations modifying the objects are performed through - * static methods. +/** + * Partial ordering between elements of some set. + * + * We initially have an empty relation, and we extend this by + * maintaining a triangular array where each entry is a @b PoComp + * value. After each extension we compute the transitive closure + * of the current relation. Assuming this was done for the previous + * relation, it is enough to compute what has become "connected" + * through the newly added value. In certain cases, this extension + * fails as the new relation would be contradictory. This state + * is represented by a null partial ordering. + * + * The set elements are denoted by IDs inside the class, which is + * given by order of appearance, as explained below. The set + * elements are abstracted via these IDs to increase sharing among + * partial ordering objects. Hence, operations modifying the + * objects are performed through static methods, and we get shared + * heap-allocated objects, or null if the operation fails. */ class PartialOrdering { @@ -52,7 +62,7 @@ class PartialOrdering /** Get empty partial ordering. */ static const PartialOrdering* getEmpty(); /** Add new element to partial ordering. The ID of this - * element is set to @b size()-1 of the new partial ordering. */ + * element is set to @b _size-1 of the new partial ordering. */ static const PartialOrdering* extend(const PartialOrdering* po); /** Tries to set relation between two elements with IDs @b x and @b y, * and performs transitive closure over the entire set so far. From 345d7c5119168e5d97b1420e1ce1da38cc7885af Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Fri, 3 Jan 2025 15:47:02 +0100 Subject: [PATCH 61/64] Change partial ordering underlying array to vector --- Kernel/PartialOrdering.cpp | 46 +++----------------------------------- Kernel/PartialOrdering.hpp | 11 ++++----- 2 files changed, 9 insertions(+), 48 deletions(-) diff --git a/Kernel/PartialOrdering.cpp b/Kernel/PartialOrdering.cpp index a8cbda28c..356ab03c9 100644 --- a/Kernel/PartialOrdering.cpp +++ b/Kernel/PartialOrdering.cpp @@ -147,29 +147,6 @@ string pocompToInfix(PoComp c) { ASSERTION_VIOLATION; } -PartialOrdering::PartialOrdering() - : _size(0), _array(nullptr) {} - -PartialOrdering::PartialOrdering(const PartialOrdering& other) - : _size(other._size), _array(nullptr) -{ - size_t arrSize = ((_size - 1) * _size / 2); - if (arrSize) { - void* mem = ALLOC_KNOWN(arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); - _array = array_new(mem, arrSize); - memcpy(_array,other._array,arrSize*sizeof(PoComp)); - } -} - -PartialOrdering::~PartialOrdering() -{ - size_t arrSize = ((_size - 1) * _size / 2); - if (arrSize) { - array_delete(_array, arrSize); - DEALLOC_KNOWN(_array, arrSize*sizeof(PoComp), "Kernel::PartialOrdering"); - } -} - PoComp PartialOrdering::get(size_t x, size_t y) const { ASS_L(x,_size); @@ -239,31 +216,14 @@ const PartialOrdering* PartialOrdering::extend(const PartialOrdering* po) void PartialOrdering::extend() { - // extend array - size_t prevSize = ((_size - 1) * _size / 2); - auto prevArray = _array; _size++; - if (_size>1) { - size_t newSize = prevSize + _size; - void* mem = ALLOC_KNOWN(newSize*sizeof(PoComp), "Kernel::PartialOrdering"); - _array = array_new(mem, newSize); - std::memset(_array, 0, newSize*sizeof(PoComp)); - static_assert(static_cast(PoComp::UNKNOWN) == 0); - if (prevArray) { - memcpy(_array,prevArray,prevSize*sizeof(PoComp)); - } - } - // remove previous array - if (prevSize) { - array_delete(prevArray, prevSize); - DEALLOC_KNOWN(prevArray, prevSize*sizeof(PoComp), "Kernel::PartialOrdering"); - } + _array.insert(_array.end(),_size,PoComp::UNKNOWN); } bool PartialOrdering::setRel(size_t x, size_t y, PoComp v, bool& changed) { size_t idx = y*(y-1)/2 + x; - ASS_L(idx,((_size - 1) * _size / 2)); + ASS_L(idx,_array.size()); PoComp new_v; if (!checkCompatibility(_array[idx], v, new_v)) { changed = false; @@ -286,7 +246,7 @@ bool PartialOrdering::setRelSafe(size_t x, size_t y, PoComp v, bool& changed) PoComp PartialOrdering::getUnsafe(size_t x, size_t y) const { size_t idx = y*(y-1)/2 + x; - ASS_L(idx,((_size - 1) * _size / 2)); + ASS_L(idx,_array.size()); return _array[idx]; } diff --git a/Kernel/PartialOrdering.hpp b/Kernel/PartialOrdering.hpp index c29dc31d1..40b676b3b 100644 --- a/Kernel/PartialOrdering.hpp +++ b/Kernel/PartialOrdering.hpp @@ -15,6 +15,7 @@ #define __PartialOrdering__ #include +#include namespace Kernel { @@ -72,9 +73,9 @@ class PartialOrdering friend std::ostream& operator<<(std::ostream& str, const PartialOrdering& po); private: - PartialOrdering(); - ~PartialOrdering(); - PartialOrdering(const PartialOrdering& other); + PartialOrdering() = default; + ~PartialOrdering() = default; + PartialOrdering(const PartialOrdering&) = default; PartialOrdering& operator=(const PartialOrdering&) = delete; void extend(); @@ -88,8 +89,8 @@ class PartialOrdering bool setInferredHelperInc(size_t x, size_t y, PoComp wkn); bool setInferredHelperEq(size_t x, size_t y); - size_t _size; - PoComp* _array; + size_t _size = 0; + std::vector _array; }; }; From aa1fab0704d9b78dafd5a7530155bf6ce228e2a2 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Sat, 4 Jan 2025 14:27:09 +0100 Subject: [PATCH 62/64] Remove default from switches where it makes sense; use valid pointer for success in comparator insertions --- Indexing/Index.hpp | 3 ++- Kernel/OrderingComparator.cpp | 7 ++++--- Kernel/TermPartialOrdering.cpp | 7 ++++--- Shell/ConditionalRedundancyHandler.cpp | 5 +++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Indexing/Index.hpp b/Indexing/Index.hpp index abefb7194..6f53d94f2 100644 --- a/Indexing/Index.hpp +++ b/Indexing/Index.hpp @@ -119,7 +119,8 @@ struct DemodulatorData DemodulatorData(TypedTermList term, TermList rhs, Clause* clause, bool preordered, const Ordering& ord) : term(term), rhs(rhs), clause(clause), preordered(preordered), comparator(ord.createComparator()) { - comparator->insert({ { term, rhs, Ordering::GREATER } }, (void*)0x1); + // insert pointer to owner as non-null value representing success + comparator->insert({ { term, rhs, Ordering::GREATER } }, this); #if VDEBUG ASS(term.containsAllVariablesOf(rhs)); ASS(!preordered || ord.compare(term,rhs)==Ordering::GREATER); diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index c8bf3db7d..ee822339d 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -419,8 +419,9 @@ OrderingComparator::Branch& OrderingComparator::Node::getBranch(Ordering::Result case Ordering::EQUAL: return eqBranch; case Ordering::GREATER: return gtBranch; case Ordering::INCOMPARABLE: return ngeBranch; - default: ASSERTION_VIOLATION; + case Ordering::LESS: break; // no distinction between less and incomparable } + ASSERTION_VIOLATION; } // Polynomial @@ -456,8 +457,8 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node::Tag& case Tag::T_DATA: return out << "d"; case Tag::T_TERM: return out << "t"; case Tag::T_POLY: return out << "p"; - default: ASSERTION_VIOLATION; } + ASSERTION_VIOLATION; } std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node) @@ -468,8 +469,8 @@ std::ostream& operator<<(std::ostream& out, const OrderingComparator::Node& node case Tag::T_DATA: return out << node.data; case Tag::T_POLY: return out << *node.poly; case Tag::T_TERM: return out << node.lhs << " " << node.rhs; - default: ASSERTION_VIOLATION; } + ASSERTION_VIOLATION; } std::ostream& operator<<(std::ostream& out, const OrderingComparator::Polynomial& poly) diff --git a/Kernel/TermPartialOrdering.cpp b/Kernel/TermPartialOrdering.cpp index b990bef2f..cbb87a424 100644 --- a/Kernel/TermPartialOrdering.cpp +++ b/Kernel/TermPartialOrdering.cpp @@ -35,9 +35,11 @@ Result poCompToResult(PoComp c) { case PoComp::NLEQ: case PoComp::INCOMPARABLE: return Result::INCOMPARABLE; - default: + case PoComp::UNKNOWN: + // no unknowns here ASSERTION_VIOLATION; } + ASSERTION_VIOLATION; } PoComp resultToPoComp(Result r, bool reversed) { @@ -50,9 +52,8 @@ PoComp resultToPoComp(Result r, bool reversed) { return reversed ? PoComp::GREATER : PoComp::LESS; case Result::INCOMPARABLE: return reversed ? PoComp::NLEQ : PoComp::NGEQ; - default: - ASSERTION_VIOLATION; } + ASSERTION_VIOLATION; } // TermPartialOrdering diff --git a/Shell/ConditionalRedundancyHandler.cpp b/Shell/ConditionalRedundancyHandler.cpp index 2d7bb83a5..4bef1b262 100644 --- a/Shell/ConditionalRedundancyHandler.cpp +++ b/Shell/ConditionalRedundancyHandler.cpp @@ -156,10 +156,11 @@ class ConditionalRedundancyHandler::ConstraintIndex } // check ordering constraints - auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator](auto& ordCon) { + auto ordCons_ok = iterTraits(e->ordCons.iter()).all([ord,&applicator,e](auto& ordCon) { if (!ordCon.comp) { ordCon.comp = ord->createComparator(); - ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }, (void*)0x1); + // insert pointer to owner as non-null value representing success + ordCon.comp->insert({ { ordCon.lhs, ordCon.rhs, Ordering::GREATER } }, e); } ordCon.comp->init(&applicator); return ordCon.comp->next(); From d5658707dd004e2be0b3f1cc3294b52d7ec811d3 Mon Sep 17 00:00:00 2001 From: Martin Suda Date: Sun, 5 Jan 2025 09:13:58 +0100 Subject: [PATCH 63/64] typo --- Kernel/MainLoop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kernel/MainLoop.cpp b/Kernel/MainLoop.cpp index 6ac0e5434..9ff78b463 100644 --- a/Kernel/MainLoop.cpp +++ b/Kernel/MainLoop.cpp @@ -104,7 +104,7 @@ MainLoop* MainLoop::createFromOptions(Problem& prb, const Options& opt) switch (opt.saturationAlgorithm()) { case Options::SaturationAlgorithm::FINITE_MODEL_BUILDING: if(env.getMainProblem()->hasPolymorphicSym() || env.getMainProblem()->isHigherOrder()){ - USER_ERROR("Finite model buillding is currently not compatible with polymorphism or higher-order constructs"); + USER_ERROR("Finite model building is currently not compatible with polymorphism or higher-order constructs"); } if(env.options->outputMode() == Shell::Options::Output::UCORE){ USER_ERROR("Finite model building is not compatible with producing unsat cores"); From 88333846cfab6732626920dfe3f676ea3bddaaa7 Mon Sep 17 00:00:00 2001 From: Marton Hajdu Date: Tue, 7 Jan 2025 12:00:24 +0100 Subject: [PATCH 64/64] Rename isGreaterOrEq to compareUnidirectional and document it properly --- Inferences/BackwardDemodulation.cpp | 2 +- Inferences/ForwardDemodulation.cpp | 4 ++-- Kernel/KBO.cpp | 2 +- Kernel/KBO.hpp | 2 +- Kernel/LPO.cpp | 2 +- Kernel/LPO.hpp | 2 +- Kernel/Ordering.hpp | 17 ++++++++++++++--- Kernel/OrderingComparator.cpp | 2 +- UnitTests/tKBO.cpp | 8 ++++---- 9 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Inferences/BackwardDemodulation.cpp b/Inferences/BackwardDemodulation.cpp index 668294210..42a5016d8 100644 --- a/Inferences/BackwardDemodulation.cpp +++ b/Inferences/BackwardDemodulation.cpp @@ -143,7 +143,7 @@ struct BackwardDemodulation::ResultFn TermList lhsS=qr.data->term; - if (_ordering.isGreaterOrEq(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { + if (_ordering.compareUnidirectional(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) { return BwSimplificationRecord(0); } diff --git a/Inferences/ForwardDemodulation.cpp b/Inferences/ForwardDemodulation.cpp index 944a9dc57..94dff709b 100644 --- a/Inferences/ForwardDemodulation.cpp +++ b/Inferences/ForwardDemodulation.cpp @@ -174,7 +174,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* if (_precompiledComparison) { #if VDEBUG - auto dcomp = ordering.isGreaterOrEq(trm,rhsApplied); + auto dcomp = ordering.compareUnidirectional(trm,rhsApplied); #endif qr.data->comparator->init(appl); if (!preordered && (_preorderedOnly || !qr.data->comparator->next())) { @@ -183,7 +183,7 @@ bool ForwardDemodulationImpl::perform(Clause* cl, Clause* } ASS_EQ(dcomp,Ordering::GREATER); } else { - if (!preordered && (_preorderedOnly || ordering.isGreaterOrEq(trm,rhsApplied)!=Ordering::GREATER)) { + if (!preordered && (_preorderedOnly || ordering.compareUnidirectional(trm,rhsApplied)!=Ordering::GREATER)) { continue; } } diff --git a/Kernel/KBO.cpp b/Kernel/KBO.cpp index 7d6476bb4..2ab8bd388 100644 --- a/Kernel/KBO.cpp +++ b/Kernel/KBO.cpp @@ -805,7 +805,7 @@ Ordering::Result KBO::compare(AppliedTerm tl1, AppliedTerm tl2) const return res; } -Ordering::Result KBO::isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const +Ordering::Result KBO::compareUnidirectional(AppliedTerm tl1, AppliedTerm tl2) const { if (tl1.equalsShallow(tl2)) { return EQUAL; diff --git a/Kernel/KBO.hpp b/Kernel/KBO.hpp index e6816124b..fe48be58b 100644 --- a/Kernel/KBO.hpp +++ b/Kernel/KBO.hpp @@ -161,7 +161,7 @@ class KBO Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm t1, AppliedTerm t2) const override; - Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const override; + Result compareUnidirectional(AppliedTerm t1, AppliedTerm t2) const override; OrderingComparatorUP createComparator() const override; protected: diff --git a/Kernel/LPO.cpp b/Kernel/LPO.cpp index 7d7627fce..b6aee2005 100644 --- a/Kernel/LPO.cpp +++ b/Kernel/LPO.cpp @@ -96,7 +96,7 @@ Ordering::Result LPO::compare(AppliedTerm tl1, AppliedTerm tl2) const return clpo(tl1, tl2); } -Ordering::Result LPO::isGreaterOrEq(AppliedTerm lhs, AppliedTerm rhs) const +Ordering::Result LPO::compareUnidirectional(AppliedTerm lhs, AppliedTerm rhs) const { return lpo(lhs,rhs); } diff --git a/Kernel/LPO.hpp b/Kernel/LPO.hpp index 32cda5f38..ba5aeff61 100644 --- a/Kernel/LPO.hpp +++ b/Kernel/LPO.hpp @@ -47,7 +47,7 @@ class LPO using PrecedenceOrdering::compare; Result compare(TermList tl1, TermList tl2) const override; Result compare(AppliedTerm tl1, AppliedTerm tl2) const override; - Result isGreaterOrEq(AppliedTerm tl1, AppliedTerm tl2) const override; + Result compareUnidirectional(AppliedTerm tl1, AppliedTerm tl2) const override; OrderingComparatorUP createComparator() const override; void showConcrete(std::ostream&) const override; diff --git a/Kernel/Ordering.hpp b/Kernel/Ordering.hpp index adee6df69..87e9d4e1a 100644 --- a/Kernel/Ordering.hpp +++ b/Kernel/Ordering.hpp @@ -87,9 +87,20 @@ class Ordering virtual Result compare(AppliedTerm lhs, AppliedTerm rhs) const { return compare(lhs.apply(), rhs.apply()); } - /** Optimised function used for checking that @b t1 is greater than @b t2, - * under some substitutions captured by @b AppliedTerm. */ - virtual Result isGreaterOrEq(AppliedTerm t1, AppliedTerm t2) const + /** Unidirectional comparison of @b t1 and @b t2 under some + * substitutions captured by @b AppliedTerm which returns: + * (a) GREATER if and only if t1 ≻ t2, + * (b) EQUAL if and only if t1 = t2, + * (c) LESS only if t1 ≺ t2, + * (d) INCOMPARABLE only if t1 ⪰̸ t2. + * That is, the function need not distinguish between t1 less + * than t2 and t1 and t2 being incomparable, which allows for + * some optimisations (see KBO and LPO implementation). + * + * This is useful in simplifications such as demodulation where + * only the result being greater matters and in runtime specialized + * ordering checks (see OrderingComparator). */ + virtual Result compareUnidirectional(AppliedTerm t1, AppliedTerm t2) const { return compare(t1, t2); } /** Creates optimised object for ordering checks. @see OrderingComparator. */ diff --git a/Kernel/OrderingComparator.cpp b/Kernel/OrderingComparator.cpp index ee822339d..e9aa560db 100644 --- a/Kernel/OrderingComparator.cpp +++ b/Kernel/OrderingComparator.cpp @@ -64,7 +64,7 @@ void* OrderingComparator::next() Ordering::Result comp = Ordering::INCOMPARABLE; if (node->tag == Node::T_TERM) { - comp = _ord.isGreaterOrEq( + comp = _ord.compareUnidirectional( AppliedTerm(node->lhs, _appl, true), AppliedTerm(node->rhs, _appl, true)); diff --git a/UnitTests/tKBO.cpp b/UnitTests/tKBO.cpp index c8cf833cf..5c7ad7eea 100644 --- a/UnitTests/tKBO.cpp +++ b/UnitTests/tKBO.cpp @@ -382,8 +382,8 @@ TEST_FUN(kbo_test23) { // isGreater tests bool isGreaterSymmetric(const KBO& ord, TermList t1, TermList t2) { - return ord.isGreaterOrEq(AppliedTerm(t1),AppliedTerm(t2))==Ordering::GREATER - && ord.isGreaterOrEq(AppliedTerm(t2),AppliedTerm(t1))!=Ordering::GREATER; + return ord.compareUnidirectional(AppliedTerm(t1),AppliedTerm(t2))==Ordering::GREATER + && ord.compareUnidirectional(AppliedTerm(t2),AppliedTerm(t1))!=Ordering::GREATER; } TEST_FUN(kbo_isGreater_test01) { @@ -430,8 +430,8 @@ TEST_FUN(kbo_isGreater_test04) { auto ord = kbo(weights(make_pair(f, 10u)), weights()); - ASS(ord.isGreaterOrEq(AppliedTerm(f(x)), AppliedTerm(g(g(g(g(g(y)))))))!=Ordering::GREATER); - ASS(ord.isGreaterOrEq(AppliedTerm(g(g(g(g(g(y)))))), AppliedTerm(f(x)))!=Ordering::GREATER); + ASS(ord.compareUnidirectional(AppliedTerm(f(x)), AppliedTerm(g(g(g(g(g(y)))))))!=Ordering::GREATER); + ASS(ord.compareUnidirectional(AppliedTerm(g(g(g(g(g(y)))))), AppliedTerm(f(x)))!=Ordering::GREATER); } TEST_FUN(kbo_isGreater_test05) {