Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * Arithmetic equality solver 11 : : */ 12 : : 13 : : #include "theory/arith/equality_solver.h" 14 : : 15 : : #include "theory/arith/inference_manager.h" 16 : : #include "theory/arith/linear/congruence_manager.h" 17 : : 18 : : using namespace cvc5::internal::kind; 19 : : 20 : : namespace cvc5::internal { 21 : : namespace theory { 22 : : namespace arith { 23 : : 24 : 51048 : EqualitySolver::EqualitySolver(Env& env, 25 : : TheoryState& astate, 26 : 51048 : InferenceManager& aim) 27 : : : EnvObj(env), 28 : 51048 : d_astate(astate), 29 : 51048 : d_aim(aim), 30 : 51048 : d_notify(*this), 31 : 51048 : d_ee(nullptr), 32 : 51048 : d_propLits(context()), 33 : 51048 : d_acm(nullptr) 34 : : { 35 : 51048 : } 36 : : 37 : 51048 : bool EqualitySolver::needsEqualityEngine(EeSetupInfo& esi) 38 : : { 39 : 51048 : esi.d_notify = &d_notify; 40 : 51048 : esi.d_name = "arith::ee"; 41 : 51048 : return true; 42 : : } 43 : : 44 : 51048 : void EqualitySolver::finishInit() 45 : : { 46 : 51048 : d_ee = d_astate.getEqualityEngine(); 47 : : // add the function kinds 48 : 51048 : d_ee->addFunctionKind(Kind::NONLINEAR_MULT); 49 : 51048 : d_ee->addFunctionKind(Kind::EXPONENTIAL); 50 : 51048 : d_ee->addFunctionKind(Kind::SINE); 51 : 51048 : d_ee->addFunctionKind(Kind::IAND); 52 : 51048 : d_ee->addFunctionKind(Kind::PIAND); 53 : 51048 : d_ee->addFunctionKind(Kind::POW2); 54 : 51048 : } 55 : : 56 : 9254 : bool EqualitySolver::preNotifyFact(TNode atom, 57 : : CVC5_UNUSED bool pol, 58 : : TNode fact, 59 : : CVC5_UNUSED bool isPrereg, 60 : : CVC5_UNUSED bool isInternal) 61 : : { 62 [ + + ]: 9254 : if (atom.getKind() != Kind::EQUAL) 63 : : { 64 : : // finished processing, since not beneficial to add non-equality facts 65 : 3691 : return true; 66 : : } 67 [ + - ]: 11126 : Trace("arith-eq-solver") << "EqualitySolver::preNotifyFact: " << fact 68 : 5563 : << std::endl; 69 : : // we will process 70 : 5563 : return false; 71 : : } 72 : : 73 : 54333 : TrustNode EqualitySolver::explain(TNode lit) 74 : : { 75 [ + - ]: 54333 : Trace("arith-eq-solver-debug") << "explain " << lit << "?" << std::endl; 76 [ + + ]: 54333 : if (d_acm != nullptr) 77 : : { 78 : : // if we are using the congruence manager, consult whether it can explain 79 [ + + ]: 54275 : if (d_acm->canExplain(lit)) 80 : : { 81 : 37628 : return d_acm->explain(lit); 82 : : } 83 : : // otherwise, don't explain 84 : 16647 : return TrustNode::null(); 85 : : } 86 : : // check if we propagated it? 87 [ + - ]: 58 : if (d_propLits.find(lit) == d_propLits.end()) 88 : : { 89 [ + - ]: 58 : Trace("arith-eq-solver-debug") << "...did not propagate" << std::endl; 90 : 58 : return TrustNode::null(); 91 : : } 92 [ - - ]: 0 : Trace("arith-eq-solver-debug") 93 : 0 : << "...explain via inference manager" << std::endl; 94 : : // if we did, explain with the arithmetic inference manager 95 : 0 : return d_aim.explainLit(lit); 96 : : } 97 : : 98 : 51048 : void EqualitySolver::setCongruenceManager(linear::ArithCongruenceManager* acm) 99 : : { 100 : 51048 : d_acm = acm; 101 : 51048 : } 102 : : 103 : 1738827 : bool EqualitySolver::propagateLit(Node lit) 104 : : { 105 [ + + ]: 1738827 : if (d_acm != nullptr) 106 : : { 107 : : // if we are using the congruence manager, notify it 108 : 1738534 : return d_acm->propagate(lit); 109 : : } 110 : : // if we've already propagated, ignore 111 [ - + ]: 293 : if (d_aim.hasPropagated(lit)) 112 : : { 113 : 0 : return true; 114 : : } 115 : : // notice this is only used when ee-mode=distributed 116 : : // remember that this was a literal we propagated 117 [ + - ]: 293 : Trace("arith-eq-solver-debug") << "propagate lit " << lit << std::endl; 118 : 293 : d_propLits.insert(lit); 119 : 293 : return d_aim.propagateLit(lit); 120 : : } 121 : 3787 : void EqualitySolver::conflictEqConstantMerge(TNode a, TNode b) 122 : : { 123 [ + - ]: 3787 : if (d_acm != nullptr) 124 : : { 125 : : // if we are using the congruence manager, notify it 126 : 3787 : Node eq = a.eqNode(b); 127 : 3787 : d_acm->propagate(eq); 128 : 3787 : return; 129 : 3787 : } 130 : 0 : d_aim.conflictEqConstantMerge(a, b); 131 : : } 132 : : 133 : 0 : bool EqualitySolver::EqualitySolverNotify::eqNotifyTriggerPredicate( 134 : : TNode predicate, bool value) 135 : : { 136 [ - - ]: 0 : Trace("arith-eq-solver") << "...propagate (predicate) " << predicate << " -> " 137 : 0 : << value << std::endl; 138 [ - - ]: 0 : if (value) 139 : : { 140 : 0 : return d_es.propagateLit(predicate); 141 : : } 142 : 0 : return d_es.propagateLit(predicate.notNode()); 143 : : } 144 : : 145 : 1738827 : bool EqualitySolver::EqualitySolverNotify::eqNotifyTriggerTermEquality( 146 : : CVC5_UNUSED TheoryId tag, TNode t1, TNode t2, bool value) 147 : : { 148 [ + - ][ - + ]: 3477654 : Trace("arith-eq-solver") << "...propagate (term eq) " << t1.eqNode(t2) [ - - ] 149 : 1738827 : << " -> " << value << std::endl; 150 [ + + ]: 1738827 : if (value) 151 : : { 152 : 1401014 : return d_es.propagateLit(t1.eqNode(t2)); 153 : : } 154 : 337813 : return d_es.propagateLit(t1.eqNode(t2).notNode()); 155 : : } 156 : : 157 : 3787 : void EqualitySolver::EqualitySolverNotify::eqNotifyConstantTermMerge(TNode t1, 158 : : TNode t2) 159 : : { 160 [ + - ]: 7574 : Trace("arith-eq-solver") << "...conflict merge " << t1 << " " << t2 161 : 3787 : << std::endl; 162 : 3787 : d_es.conflictEqConstantMerge(t1, t2); 163 : 3787 : } 164 : : 165 : : } // namespace arith 166 : : } // namespace theory 167 : : } // namespace cvc5::internal