1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Mudathir Mohamed, Andres Noetzli |
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 |
|
* Set enumerator implementation. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/sets/theory_sets_type_enumerator.h" |
17 |
|
|
18 |
|
#include "util/bitvector.h" |
19 |
|
|
20 |
|
namespace cvc5 { |
21 |
|
namespace theory { |
22 |
|
namespace sets { |
23 |
|
|
24 |
40 |
SetEnumerator::SetEnumerator(TypeNode type, TypeEnumeratorProperties* tep) |
25 |
|
: TypeEnumeratorBase<SetEnumerator>(type), |
26 |
40 |
d_nodeManager(NodeManager::currentNM()), |
27 |
80 |
d_elementEnumerator(type.getSetElementType(), tep), |
28 |
|
d_isFinished(false), |
29 |
|
d_currentSetIndex(0), |
30 |
160 |
d_currentSet() |
31 |
|
{ |
32 |
40 |
d_currentSet = d_nodeManager->mkConst(EmptySet(type)); |
33 |
40 |
} |
34 |
|
|
35 |
10 |
SetEnumerator::SetEnumerator(const SetEnumerator& enumerator) |
36 |
20 |
: TypeEnumeratorBase<SetEnumerator>(enumerator.getType()), |
37 |
10 |
d_nodeManager(enumerator.d_nodeManager), |
38 |
|
d_elementEnumerator(enumerator.d_elementEnumerator), |
39 |
10 |
d_isFinished(enumerator.d_isFinished), |
40 |
10 |
d_currentSetIndex(enumerator.d_currentSetIndex), |
41 |
60 |
d_currentSet(enumerator.d_currentSet) |
42 |
|
{ |
43 |
10 |
} |
44 |
|
|
45 |
92 |
SetEnumerator::~SetEnumerator() {} |
46 |
|
|
47 |
182 |
Node SetEnumerator::operator*() |
48 |
|
{ |
49 |
182 |
if (d_isFinished) |
50 |
|
{ |
51 |
18 |
throw NoMoreValuesException(getType()); |
52 |
|
} |
53 |
|
|
54 |
328 |
Trace("set-type-enum") << "SetEnumerator::operator* d_currentSet = " |
55 |
164 |
<< d_currentSet << std::endl; |
56 |
|
|
57 |
164 |
return d_currentSet; |
58 |
|
} |
59 |
|
|
60 |
102 |
SetEnumerator& SetEnumerator::operator++() |
61 |
|
{ |
62 |
102 |
if (d_isFinished) |
63 |
|
{ |
64 |
32 |
Trace("set-type-enum") << "SetEnumerator::operator++ finished!" |
65 |
16 |
<< std::endl; |
66 |
32 |
Trace("set-type-enum") << "SetEnumerator::operator++ d_currentSet = " |
67 |
16 |
<< d_currentSet << std::endl; |
68 |
16 |
return *this; |
69 |
|
} |
70 |
|
|
71 |
86 |
d_currentSetIndex++; |
72 |
|
|
73 |
|
// if the index is a power of 2, get a new element from d_elementEnumerator |
74 |
86 |
if (d_currentSetIndex == static_cast<unsigned>(1 << d_elementsSoFar.size())) |
75 |
|
{ |
76 |
|
// if there are no more values from d_elementEnumerator, set d_isFinished |
77 |
|
// to true |
78 |
46 |
if (d_elementEnumerator.isFinished()) |
79 |
|
{ |
80 |
6 |
d_isFinished = true; |
81 |
|
|
82 |
12 |
Trace("set-type-enum") |
83 |
6 |
<< "SetEnumerator::operator++ finished!" << std::endl; |
84 |
12 |
Trace("set-type-enum") |
85 |
6 |
<< "SetEnumerator::operator++ d_currentSet = " << d_currentSet |
86 |
6 |
<< std::endl; |
87 |
6 |
return *this; |
88 |
|
} |
89 |
|
|
90 |
|
// get a new element and return it as a singleton set |
91 |
80 |
Node element = *d_elementEnumerator; |
92 |
40 |
d_elementsSoFar.push_back(element); |
93 |
80 |
TypeNode elementType = d_elementEnumerator.getType(); |
94 |
40 |
d_currentSet = d_nodeManager->mkSingleton(elementType, element); |
95 |
40 |
d_elementEnumerator++; |
96 |
|
} |
97 |
|
else |
98 |
|
{ |
99 |
|
// determine which elements are included in the set |
100 |
80 |
BitVector indices = BitVector(d_elementsSoFar.size(), d_currentSetIndex); |
101 |
80 |
std::vector<Node> elements; |
102 |
166 |
for (unsigned i = 0; i < d_elementsSoFar.size(); i++) |
103 |
|
{ |
104 |
|
// add the element to the set if its corresponding bit is set |
105 |
126 |
if (indices.isBitSet(i)) |
106 |
|
{ |
107 |
96 |
elements.push_back(d_elementsSoFar[i]); |
108 |
|
} |
109 |
|
} |
110 |
80 |
d_currentSet = NormalForm::elementsToSet( |
111 |
120 |
std::set<TNode>(elements.begin(), elements.end()), getType()); |
112 |
|
} |
113 |
|
|
114 |
80 |
Assert(d_currentSet.isConst()); |
115 |
|
|
116 |
160 |
Trace("set-type-enum") << "SetEnumerator::operator++ d_elementsSoFar = " |
117 |
80 |
<< d_elementsSoFar << std::endl; |
118 |
160 |
Trace("set-type-enum") << "SetEnumerator::operator++ d_currentSet = " |
119 |
80 |
<< d_currentSet << std::endl; |
120 |
|
|
121 |
80 |
return *this; |
122 |
|
} |
123 |
|
|
124 |
200 |
bool SetEnumerator::isFinished() |
125 |
|
{ |
126 |
400 |
Trace("set-type-enum") << "SetEnumerator::isFinished = " << d_isFinished |
127 |
200 |
<< std::endl; |
128 |
200 |
return d_isFinished; |
129 |
|
} |
130 |
|
|
131 |
|
} // namespace sets |
132 |
|
} // namespace theory |
133 |
31137 |
} // namespace cvc5 |