1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Haniel Barbosa, Andrew Reynolds |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 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 |
|
* Implementation of lazy trie. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/lazy_trie.h" |
17 |
|
|
18 |
|
namespace cvc5 { |
19 |
|
namespace theory { |
20 |
|
namespace quantifiers { |
21 |
|
|
22 |
2335 |
Node LazyTrie::add(Node n, |
23 |
|
LazyTrieEvaluator* ev, |
24 |
|
unsigned index, |
25 |
|
unsigned ntotal, |
26 |
|
bool forceKeep) |
27 |
|
{ |
28 |
2335 |
LazyTrie* lt = this; |
29 |
113259 |
while (lt != NULL) |
30 |
|
{ |
31 |
57797 |
if (index == ntotal) |
32 |
|
{ |
33 |
|
// lazy child holds the leaf data |
34 |
1216 |
if (lt->d_lazy_child.isNull() || forceKeep) |
35 |
|
{ |
36 |
513 |
lt->d_lazy_child = n; |
37 |
|
} |
38 |
3551 |
return lt->d_lazy_child; |
39 |
|
} |
40 |
56581 |
if (lt->d_children.empty()) |
41 |
|
{ |
42 |
19901 |
if (lt->d_lazy_child.isNull()) |
43 |
|
{ |
44 |
|
// no one has been here, we are done |
45 |
1119 |
lt->d_lazy_child = n; |
46 |
1119 |
return lt->d_lazy_child; |
47 |
|
} |
48 |
|
// evaluate the lazy child |
49 |
37564 |
Node e_lc = ev->evaluate(lt->d_lazy_child, index); |
50 |
|
// store at next level |
51 |
18782 |
lt->d_children[e_lc].d_lazy_child = lt->d_lazy_child; |
52 |
|
// replace |
53 |
18782 |
lt->d_lazy_child = Node::null(); |
54 |
|
} |
55 |
|
// recurse |
56 |
110924 |
Node e = ev->evaluate(n, index); |
57 |
55462 |
lt = <->d_children[e]; |
58 |
55462 |
index = index + 1; |
59 |
|
} |
60 |
|
return Node::null(); |
61 |
|
} |
62 |
|
|
63 |
224 |
void LazyTrieMulti::addClassifier(LazyTrieEvaluator* ev, unsigned ntotal) |
64 |
|
{ |
65 |
448 |
Trace("lazy-trie-multi") << "LazyTrieM: Adding classifier " << ntotal + 1 |
66 |
224 |
<< "\n"; |
67 |
448 |
std::vector<IndTriePair> visit; |
68 |
224 |
unsigned index = 0; |
69 |
|
LazyTrie* trie; |
70 |
224 |
visit.push_back(IndTriePair(0, &d_trie)); |
71 |
1028 |
while (!visit.empty()) |
72 |
|
{ |
73 |
402 |
index = visit.back().first; |
74 |
402 |
trie = visit.back().second; |
75 |
402 |
visit.pop_back(); |
76 |
|
// not at (previous) last level, traverse children |
77 |
402 |
if (index < ntotal) |
78 |
|
{ |
79 |
267 |
for (std::pair<const Node, LazyTrie>& p_nt : trie->d_children) |
80 |
|
{ |
81 |
178 |
visit.push_back(IndTriePair(index + 1, &p_nt.second)); |
82 |
|
} |
83 |
178 |
continue; |
84 |
|
} |
85 |
313 |
Assert(trie->d_children.empty()); |
86 |
|
// if last level and no element at leaf, ignore |
87 |
313 |
if (trie->d_lazy_child.isNull()) |
88 |
|
{ |
89 |
|
continue; |
90 |
|
} |
91 |
|
// apply new classifier |
92 |
313 |
Assert(d_rep_to_class.find(trie->d_lazy_child) != d_rep_to_class.end()); |
93 |
626 |
std::vector<Node> prev_sep_class = d_rep_to_class[trie->d_lazy_child]; |
94 |
313 |
if (Trace.isOn("lazy-trie-multi")) |
95 |
|
{ |
96 |
|
Trace("lazy-trie-multi") << "...last level. Prev sep class: \n"; |
97 |
|
for (const Node& n : prev_sep_class) |
98 |
|
{ |
99 |
|
Trace("lazy-trie-multi") << "...... " << n << "\n"; |
100 |
|
} |
101 |
|
} |
102 |
|
// make new sepclass of lc a singleton with itself |
103 |
313 |
d_rep_to_class.erase(trie->d_lazy_child); |
104 |
|
// replace |
105 |
313 |
trie->d_lazy_child = Node::null(); |
106 |
938 |
for (const Node& n : prev_sep_class) |
107 |
|
{ |
108 |
1087 |
Node eval = ev->evaluate(n, index); |
109 |
625 |
std::map<Node, LazyTrie>::iterator it = trie->d_children.find(eval); |
110 |
788 |
if (it != trie->d_children.end()) |
111 |
|
{ |
112 |
|
// add n to to map of item in next level |
113 |
326 |
Trace("lazy-trie-multi") << "...add " << n << " to the class of " |
114 |
163 |
<< it->second.d_lazy_child << "\n"; |
115 |
163 |
d_rep_to_class[it->second.d_lazy_child].push_back(n); |
116 |
163 |
continue; |
117 |
|
} |
118 |
|
// store at next level |
119 |
462 |
trie->d_children[eval].d_lazy_child = n; |
120 |
|
// create new map |
121 |
462 |
Trace("lazy-trie-multi") << "...create new class for : " << n << "\n"; |
122 |
462 |
Assert(d_rep_to_class.find(n) == d_rep_to_class.end()); |
123 |
462 |
d_rep_to_class[n].clear(); |
124 |
462 |
d_rep_to_class[n].push_back(n); |
125 |
|
} |
126 |
|
} |
127 |
224 |
} |
128 |
|
|
129 |
485 |
Node LazyTrieMulti::add(Node f, LazyTrieEvaluator* ev, unsigned ntotal) |
130 |
|
{ |
131 |
485 |
Trace("lazy-trie-multi") << "LazyTrieM: Adding " << f << "\n"; |
132 |
485 |
Node res = d_trie.add(f, ev, 0, ntotal, false); |
133 |
|
// f was added to the separation class with representative res |
134 |
485 |
if (res != f) |
135 |
|
{ |
136 |
692 |
Trace("lazy-trie-multi") << "... added " << f << " to the sepclass of " |
137 |
346 |
<< res << "\n"; |
138 |
346 |
Assert(d_rep_to_class.find(res) != d_rep_to_class.end()); |
139 |
346 |
Assert(!d_rep_to_class[res].empty()); |
140 |
346 |
d_rep_to_class[res].push_back(f); |
141 |
346 |
return res; |
142 |
|
} |
143 |
|
// f is the representatitve of a singleton seperation class |
144 |
278 |
Trace("lazy-trie-multi") << "... added " << f |
145 |
139 |
<< " as the rep of the sepclass with itself\n"; |
146 |
139 |
Assert(d_rep_to_class.find(res) == d_rep_to_class.end()); |
147 |
139 |
d_rep_to_class[res].clear(); |
148 |
139 |
d_rep_to_class[res].push_back(f); |
149 |
139 |
return res; |
150 |
|
} |
151 |
|
|
152 |
139 |
void LazyTrieMulti::clear() |
153 |
|
{ |
154 |
139 |
d_trie.clear(); |
155 |
139 |
d_rep_to_class.clear(); |
156 |
139 |
} |
157 |
|
|
158 |
|
} // namespace quantifiers |
159 |
|
} // namespace theory |
160 |
29502 |
} // namespace cvc5 |