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 : : * Skolem definition manager. 11 : : */ 12 : : 13 : : #include "prop/skolem_def_manager.h" 14 : : 15 : : namespace cvc5::internal { 16 : : namespace prop { 17 : : 18 : 51624 : SkolemDefManager::SkolemDefManager(context::Context* context, 19 : 51624 : context::UserContext* userContext) 20 : 51624 : : d_skDefs(userContext), d_skActive(context), d_hasSkolems(userContext) 21 : : { 22 : 51624 : } 23 : : 24 : 51279 : SkolemDefManager::~SkolemDefManager() {} 25 : : 26 : 61928 : void SkolemDefManager::notifySkolemDefinition(TNode skolem, Node def) 27 : : { 28 : : // Notice that skolem should have kind SKOLEM 29 [ + - ]: 123856 : Trace("sk-defs") << "notifySkolemDefinition: " << def << " for " << skolem 30 : 61928 : << std::endl; 31 : : // in very rare cases, a skolem may be generated twice for terms that are 32 : : // equivalent up to purification 33 [ + + ]: 61928 : if (d_skDefs.find(skolem) == d_skDefs.end()) 34 : : { 35 : : // should not have already computed whether the skolem has skolems or 36 : : // otherwise we should have marked that we have skolems, or else 37 : : // our computation of hasSkolems is wrong after adding this definition 38 : 58253 : Assert(d_hasSkolems.find(skolem) == d_hasSkolems.end() 39 : : || d_hasSkolems[skolem]); 40 : 58253 : d_skDefs.insert(skolem, def); 41 : : } 42 : 61928 : } 43 : : 44 : 4390 : TNode SkolemDefManager::getDefinitionForSkolem(TNode skolem) const 45 : : { 46 : 4390 : NodeNodeMap::const_iterator it = d_skDefs.find(skolem); 47 : 4390 : Assert(it != d_skDefs.end()) << "No skolem def for " << skolem; 48 : 8780 : return it->second; 49 : : } 50 : : 51 : 13018384 : void SkolemDefManager::notifyAsserted(TNode literal, 52 : : std::vector<TNode>& activatedSkolems) 53 : : { 54 [ + + ]: 13018384 : if (d_skActive.size() == d_skDefs.size()) 55 : : { 56 : : // already activated all skolems 57 : 7807707 : return; 58 : : } 59 : 5210677 : std::unordered_set<Node> defs; 60 : 5210677 : getSkolems(literal, defs, true); 61 [ + - ]: 10421354 : Trace("sk-defs") << "notifyAsserted: " << literal << " has skolems " << defs 62 : 5210677 : << std::endl; 63 [ + + ]: 12374890 : for (const Node& d : defs) 64 : : { 65 [ + + ]: 7164213 : if (d_skActive.find(d) != d_skActive.end()) 66 : : { 67 : : // already active 68 : 6347028 : continue; 69 : : } 70 : 817185 : d_skActive.insert(d); 71 [ + - ]: 817185 : Trace("sk-defs") << "...activate " << d << std::endl; 72 : : // add its definition to the activated list 73 : 817185 : activatedSkolems.push_back(d); 74 : : } 75 : 5210677 : } 76 : : 77 : 34016241 : bool SkolemDefManager::hasSkolems(TNode n) 78 : : { 79 [ + - ]: 34016241 : Trace("sk-defs-debug") << "Compute has skolems for " << n << std::endl; 80 : 34016241 : std::unordered_set<TNode> visited; 81 : 34016241 : std::unordered_set<TNode>::iterator it; 82 : 34016241 : NodeBoolMap::const_iterator itn; 83 : 34016241 : std::vector<TNode> visit; 84 : 34016241 : TNode cur; 85 : 34016241 : visit.push_back(n); 86 : : do 87 : : { 88 : 35402587 : cur = visit.back(); 89 : 35402587 : itn = d_hasSkolems.find(cur); 90 [ + + ]: 35402587 : if (itn != d_hasSkolems.end()) 91 : : { 92 : 34347706 : visit.pop_back(); 93 : : // already computed 94 : 34347706 : continue; 95 : : } 96 : 1054881 : it = visited.find(cur); 97 [ + + ]: 1054881 : if (it == visited.end()) 98 : : { 99 : 585298 : visited.insert(cur); 100 [ + + ]: 585298 : if (cur.getNumChildren() == 0) 101 : : { 102 : 115715 : visit.pop_back(); 103 : 115715 : Kind ck = cur.getKind(); 104 : : // We have skolems if we are a skolem that has a definition, or 105 : : // we are a Boolean term variable. For Boolean term variables, we do 106 : : // not make this test depend on whether the skolem has a definition, 107 : : // since that is prone to change if the Boolean term variable was 108 : : // introduced in a lemma prior to its definition being introduced. 109 : : // This is for example the case in strings reduction for Booleans, 110 : : // ground term purification for E-matching, etc. 111 : 231430 : d_hasSkolems[cur] = (ck == Kind::SKOLEM 112 [ + + ][ + + ]: 242156 : && (d_skDefs.find(cur) != d_skDefs.end() [ - - ] 113 [ + + ][ + + ]: 242156 : || cur.getType().isBoolean())); [ + + ][ - - ] 114 : : } 115 : : else 116 : : { 117 [ + + ]: 469583 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 118 : : { 119 : 80914 : visit.push_back(cur.getOperator()); 120 : : } 121 : 469583 : visit.insert(visit.end(), cur.begin(), cur.end()); 122 : : } 123 : : } 124 : : else 125 : : { 126 : 469583 : visit.pop_back(); 127 : : bool hasSkolem; 128 : 1408749 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED 129 [ + + ][ + + ]: 469583 : && d_hasSkolems[cur.getOperator()]) [ + + ][ + + ] [ - - ] 130 : : { 131 : 151 : hasSkolem = true; 132 : : } 133 : : else 134 : : { 135 : 469432 : hasSkolem = false; 136 [ + + ]: 1076214 : for (TNode i : cur) 137 : : { 138 [ - + ][ - + ]: 766914 : Assert(d_hasSkolems.find(i) != d_hasSkolems.end()); [ - - ] 139 [ + + ]: 766914 : if (d_hasSkolems[i]) 140 : : { 141 : 160132 : hasSkolem = true; 142 : 160132 : break; 143 : : } 144 [ + + ]: 766914 : } 145 : : } 146 : 469583 : d_hasSkolems[cur] = hasSkolem; 147 : : } 148 [ + + ]: 35402587 : } while (!visit.empty()); 149 [ - + ][ - + ]: 34016241 : Assert(d_hasSkolems.find(n) != d_hasSkolems.end()); [ - - ] 150 : 68032482 : return d_hasSkolems[n]; 151 : 34016241 : } 152 : : 153 : 5217232 : void SkolemDefManager::getSkolems(TNode n, 154 : : std::unordered_set<Node>& skolems, 155 : : bool useDefs) 156 : : { 157 : 5217232 : NodeNodeMap::const_iterator itd; 158 : 5217232 : std::unordered_set<TNode> visited; 159 : 5217232 : std::unordered_set<TNode>::iterator it; 160 : 5217232 : std::vector<TNode> visit; 161 : 5217232 : TNode cur; 162 : 5217232 : visit.push_back(n); 163 : : do 164 : : { 165 : 34016241 : cur = visit.back(); 166 : 34016241 : visit.pop_back(); 167 [ + + ]: 34016241 : if (!hasSkolems(cur)) 168 : : { 169 : : // does not have skolems, continue 170 : 10033072 : continue; 171 : : } 172 : 23983169 : it = visited.find(cur); 173 [ + + ]: 23983169 : if (it == visited.end()) 174 : : { 175 : 22619982 : visited.insert(cur); 176 [ + + ]: 22619982 : if (cur.isVar()) 177 : : { 178 : 7168636 : itd = d_skDefs.find(cur); 179 [ + + ]: 7168636 : if (itd != d_skDefs.end()) 180 : : { 181 [ + + ]: 7168603 : skolems.insert(useDefs ? itd->second : Node(cur)); 182 : : } 183 : 7168636 : continue; 184 : : } 185 [ + + ]: 15451346 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 186 : : { 187 : 2465004 : visit.push_back(cur.getOperator()); 188 : : } 189 : 15451346 : visit.insert(visit.end(), cur.begin(), cur.end()); 190 : : } 191 [ + + ]: 34016241 : } while (!visit.empty()); 192 : 5217232 : } 193 : : 194 : : } // namespace prop 195 : : } // namespace cvc5::internal