1 /********************* */
2 /*! \file substitutions.cpp
4 ** Original author: dejan
5 ** Major contributors: none
6 ** Minor contributors (to current version): none
7 ** This file is part of the CVC4 prototype.
8 ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
9 ** Courant Institute of Mathematical Sciences
10 ** New York University
11 ** See the file COPYING in the top-level source directory for licensing
12 ** information.\endverbatim
14 ** \brief A substitution mapping for theory simplification
16 ** A substitution mapping for theory simplification.
19 #include "theory/substitutions.h"
26 struct substitution_stack_element
{
29 substitution_stack_element(TNode node
)
30 : node(node
), children_added(false) {}
33 Node
SubstitutionMap::internalSubstitute(TNode t
, NodeCache
& substitutionCache
) {
35 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< ")" << std::endl
;
37 // If nothing to substitute just return the node
38 if (substitutionCache
.empty()) {
42 // Do a topological sort of the subexpressions and substitute them
43 vector
<substitution_stack_element
> toVisit
;
44 toVisit
.push_back((TNode
) t
);
46 while (!toVisit
.empty())
48 // The current node we are processing
49 substitution_stack_element
& stackHead
= toVisit
.back();
50 TNode current
= stackHead
.node
;
52 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< "): processing " << current
<< std::endl
;
54 // If node already in the cache we're done, pop from the stack
55 NodeCache::iterator find
= substitutionCache
.find(current
);
56 if (find
!= substitutionCache
.end()) {
61 // Not yet substituted, so process
62 if (stackHead
.children_added
) {
63 // Children have been processed, so substitute
64 NodeBuilder
<> builder(current
.getKind());
65 if (current
.getMetaKind() == kind::metakind::PARAMETERIZED
) {
66 builder
<< current
.getOperator();
68 for (unsigned i
= 0; i
< current
.getNumChildren(); ++ i
) {
69 Assert(substitutionCache
.find(current
[i
]) != substitutionCache
.end());
70 builder
<< Node(substitutionCache
[current
[i
]]);
72 // Mark the substitution and continue
73 Node result
= builder
;
74 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< "): setting " << current
<< " -> " << result
<< std::endl
;
75 substitutionCache
[current
] = result
;
78 // Mark that we have added the children if any
79 if (current
.getNumChildren() > 0) {
80 stackHead
.children_added
= true;
81 // We need to add the children
82 for(TNode::iterator child_it
= current
.begin(); child_it
!= current
.end(); ++ child_it
) {
83 TNode childNode
= *child_it
;
84 NodeCache::iterator childFind
= substitutionCache
.find(childNode
);
85 if (childFind
== substitutionCache
.end()) {
86 toVisit
.push_back(childNode
);
90 // No children, so we're done
91 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< "): setting " << current
<< " -> " << current
<< std::endl
;
92 substitutionCache
[current
] = current
;
98 // Return the substituted version
99 return substitutionCache
[t
];
102 void SubstitutionMap::addSubstitution(TNode x
, TNode t
, bool invalidateCache
) {
103 Debug("substitution") << "SubstitutionMap::addSubstitution(" << x
<< ", " << t
<< ")" << std::endl
;
104 Assert(d_substitutions
.find(x
) == d_substitutions
.end());
106 // Temporary substitution cache
110 // Put in the new substitutions into the old ones
111 NodeMap::iterator it
= d_substitutions
.begin();
112 NodeMap::iterator it_end
= d_substitutions
.end();
113 for(; it
!= it_end
; ++ it
) {
114 d_substitutions
[(*it
).first
] = internalSubstitute((*it
).second
, tempCache
);
117 // Put the new substitution in
118 d_substitutions
[x
] = t
;
120 // Also invalidate the cache
121 if (invalidateCache
) {
122 d_cacheInvalidated
= true;
126 static bool check(TNode node
, const SubstitutionMap::NodeMap
& substitutions
) CVC4_UNUSED
;
127 static bool check(TNode node
, const SubstitutionMap::NodeMap
& substitutions
) {
128 SubstitutionMap::NodeMap::const_iterator it
= substitutions
.begin();
129 SubstitutionMap::NodeMap::const_iterator it_end
= substitutions
.end();
130 Debug("substitution") << "checking " << node
<< std::endl
;
131 for (; it
!= it_end
; ++ it
) {
132 Debug("substitution") << "-- hasSubterm( " << (*it
).first
<< " ) ?" << std::endl
;
133 if (node
.hasSubterm((*it
).first
)) {
134 Debug("substitution") << "-- FAIL" << std::endl
;
138 Debug("substitution") << "-- SUCCEED" << std::endl
;
142 Node
SubstitutionMap::apply(TNode t
) {
144 Debug("substitution") << "SubstitutionMap::apply(" << t
<< ")" << std::endl
;
147 if (d_cacheInvalidated
) {
148 SubstitutionMap::NodeMap::const_iterator it
= d_substitutions
.begin();
149 SubstitutionMap::NodeMap::const_iterator it_end
= d_substitutions
.end();
150 d_substitutionCache
.clear();
151 for (; it
!= it_end
; ++ it
) {
152 d_substitutionCache
[(*it
).first
] = (*it
).second
;
154 d_cacheInvalidated
= false;
155 Debug("substitution") << "-- reset the cache" << std::endl
;
158 // Perform the substitution
159 Node result
= internalSubstitute(t
, d_substitutionCache
);
160 Debug("substitution") << "SubstitutionMap::apply(" << t
<< ") => " << result
<< std::endl
;
162 Assert(check(result
, d_substitutions
));
167 void SubstitutionMap::print(ostream
& out
) const {
168 NodeMap::const_iterator it
= d_substitutions
.begin();
169 NodeMap::const_iterator it_end
= d_substitutions
.end();
170 for (; it
!= it_end
; ++ it
) {
171 out
<< (*it
).first
<< " -> " << (*it
).second
<< endl
;
175 }/* CVC4::theory namespace */
177 std::ostream
& operator<<(std::ostream
& out
, const theory::SubstitutionMap::iterator
& i
) {
178 return out
<< "[CDMap-iterator]";
181 }/* CVC4 namespace */