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