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 : 28781 : SkolemDefManager::SkolemDefManager(context::Context* context, 19 : 28781 : context::UserContext* userContext) 20 : 28781 : : d_skDefs(userContext), d_skActive(context), d_hasSkolems(userContext) 21 : : { 22 : 28781 : } 23 : : 24 : 28768 : SkolemDefManager::~SkolemDefManager() {} 25 : : 26 : 62616 : void SkolemDefManager::notifySkolemDefinition(TNode skolem, Node def) 27 : : { 28 : : // Notice that skolem should have kind SKOLEM 29 [ + - ]: 125232 : Trace("sk-defs") << "notifySkolemDefinition: " << def << " for " << skolem 30 : 62616 : << std::endl; 31 : : // in very rare cases, a skolem may be generated twice for terms that are 32 : : // equivalent up to purification 33 [ + + ]: 62616 : 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 : 59785 : Assert(d_hasSkolems.find(skolem) == d_hasSkolems.end() 39 : : || d_hasSkolems[skolem]); 40 : 59785 : d_skDefs.insert(skolem, def); 41 : : } 42 : 62616 : } 43 : : 44 : 4382 : TNode SkolemDefManager::getDefinitionForSkolem(TNode skolem) const 45 : : { 46 : 4382 : NodeNodeMap::const_iterator it = d_skDefs.find(skolem); 47 : 4382 : Assert(it != d_skDefs.end()) << "No skolem def for " << skolem; 48 : 8764 : return it->second; 49 : : } 50 : : 51 : 12936846 : void SkolemDefManager::notifyAsserted(TNode literal, 52 : : std::vector<TNode>& activatedSkolems) 53 : : { 54 [ + + ]: 12936846 : if (d_skActive.size() == d_skDefs.size()) 55 : : { 56 : : // already activated all skolems 57 : 7338631 : return; 58 : : } 59 : 5598215 : std::unordered_set<Node> defs; 60 : 5598215 : getSkolems(literal, defs, true); 61 [ + - ]: 11196430 : Trace("sk-defs") << "notifyAsserted: " << literal << " has skolems " << defs 62 : 5598215 : << std::endl; 63 [ + + ]: 13075283 : for (const Node& d : defs) 64 : : { 65 [ + + ]: 7477068 : if (d_skActive.find(d) != d_skActive.end()) 66 : : { 67 : : // already active 68 : 6584138 : continue; 69 : : } 70 : 892930 : d_skActive.insert(d); 71 [ + - ]: 892930 : Trace("sk-defs") << "...activate " << d << std::endl; 72 : : // add its definition to the activated list 73 : 892930 : activatedSkolems.push_back(d); 74 : : } 75 : 5598215 : } 76 : : 77 : 34857788 : bool SkolemDefManager::hasSkolems(TNode n) 78 : : { 79 [ + - ]: 34857788 : Trace("sk-defs-debug") << "Compute has skolems for " << n << std::endl; 80 : 34857788 : std::unordered_set<TNode> visited; 81 : 34857788 : std::unordered_set<TNode>::iterator it; 82 : 34857788 : NodeBoolMap::const_iterator itn; 83 : 34857788 : std::vector<TNode> visit; 84 : 34857788 : TNode cur; 85 : 34857788 : visit.push_back(n); 86 : : do 87 : : { 88 : 36305079 : cur = visit.back(); 89 : 36305079 : itn = d_hasSkolems.find(cur); 90 [ + + ]: 36305079 : if (itn != d_hasSkolems.end()) 91 : : { 92 : 35212552 : visit.pop_back(); 93 : : // already computed 94 : 35212552 : continue; 95 : : } 96 : 1092527 : it = visited.find(cur); 97 [ + + ]: 1092527 : if (it == visited.end()) 98 : : { 99 : 604945 : visited.insert(cur); 100 [ + + ]: 604945 : if (cur.getNumChildren() == 0) 101 : : { 102 : 117363 : visit.pop_back(); 103 : 117363 : 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 : 234726 : d_hasSkolems[cur] = (ck == Kind::SKOLEM 112 [ + + ][ + + ]: 245494 : && (d_skDefs.find(cur) != d_skDefs.end() [ - - ] 113 [ + + ][ + + ]: 245494 : || cur.getType().isBoolean())); [ + + ][ - - ] 114 : : } 115 : : else 116 : : { 117 [ + + ]: 487582 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 118 : : { 119 : 92291 : visit.push_back(cur.getOperator()); 120 : : } 121 : 487582 : visit.insert(visit.end(), cur.begin(), cur.end()); 122 : : } 123 : : } 124 : : else 125 : : { 126 : 487582 : visit.pop_back(); 127 : : bool hasSkolem; 128 : 1462746 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED 129 [ + + ][ + + ]: 487582 : && d_hasSkolems[cur.getOperator()]) [ + + ][ + + ] [ - - ] 130 : : { 131 : 151 : hasSkolem = true; 132 : : } 133 : : else 134 : : { 135 : 487431 : hasSkolem = false; 136 [ + + ]: 1121024 : for (TNode i : cur) 137 : : { 138 [ - + ][ - + ]: 796633 : Assert(d_hasSkolems.find(i) != d_hasSkolems.end()); [ - - ] 139 [ + + ]: 796633 : if (d_hasSkolems[i]) 140 : : { 141 : 163040 : hasSkolem = true; 142 : 163040 : break; 143 : : } 144 [ + + ]: 796633 : } 145 : : } 146 : 487582 : d_hasSkolems[cur] = hasSkolem; 147 : : } 148 [ + + ]: 36305079 : } while (!visit.empty()); 149 [ - + ][ - + ]: 34857788 : Assert(d_hasSkolems.find(n) != d_hasSkolems.end()); [ - - ] 150 : 69715576 : return d_hasSkolems[n]; 151 : 34857788 : } 152 : : 153 : 5604486 : void SkolemDefManager::getSkolems(TNode n, 154 : : std::unordered_set<Node>& skolems, 155 : : bool useDefs) 156 : : { 157 : 5604486 : NodeNodeMap::const_iterator itd; 158 : 5604486 : std::unordered_set<TNode> visited; 159 : 5604486 : std::unordered_set<TNode>::iterator it; 160 : 5604486 : std::vector<TNode> visit; 161 : 5604486 : TNode cur; 162 : 5604486 : visit.push_back(n); 163 : : do 164 : : { 165 : 34857788 : cur = visit.back(); 166 : 34857788 : visit.pop_back(); 167 [ + + ]: 34857788 : if (!hasSkolems(cur)) 168 : : { 169 : : // does not have skolems, continue 170 : 10329502 : continue; 171 : : } 172 : 24528286 : it = visited.find(cur); 173 [ + + ]: 24528286 : if (it == visited.end()) 174 : : { 175 : 23164972 : visited.insert(cur); 176 [ + + ]: 23164972 : if (cur.isVar()) 177 : : { 178 : 7481487 : itd = d_skDefs.find(cur); 179 [ + + ]: 7481487 : if (itd != d_skDefs.end()) 180 : : { 181 [ + + ]: 7481450 : skolems.insert(useDefs ? itd->second : Node(cur)); 182 : : } 183 : 7481487 : continue; 184 : : } 185 [ + + ]: 15683485 : if (cur.getMetaKind() == kind::metakind::PARAMETERIZED) 186 : : { 187 : 2463111 : visit.push_back(cur.getOperator()); 188 : : } 189 : 15683485 : visit.insert(visit.end(), cur.begin(), cur.end()); 190 : : } 191 [ + + ]: 34857788 : } while (!visit.empty()); 192 : 5604486 : } 193 : : 194 : : } // namespace prop 195 : : } // namespace cvc5::internal