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 find
= substitutionCache
.find(result
);
75 if (find
!= substitutionCache
.end()) {
76 result
= find
->second
;
78 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< "): setting " << current
<< " -> " << result
<< std::endl
;
79 substitutionCache
[current
] = result
;
82 // Mark that we have added the children if any
83 if (current
.getNumChildren() > 0) {
84 stackHead
.children_added
= true;
85 // We need to add the children
86 for(TNode::iterator child_it
= current
.begin(); child_it
!= current
.end(); ++ child_it
) {
87 TNode childNode
= *child_it
;
88 NodeCache::iterator childFind
= substitutionCache
.find(childNode
);
89 if (childFind
== substitutionCache
.end()) {
90 toVisit
.push_back(childNode
);
94 // No children, so we're done
95 Debug("substitution::internal") << "SubstitutionMap::internalSubstitute(" << t
<< "): setting " << current
<< " -> " << current
<< std::endl
;
96 substitutionCache
[current
] = current
;
102 // Return the substituted version
103 return substitutionCache
[t
];
106 void SubstitutionMap::addSubstitution(TNode x
, TNode t
, bool invalidateCache
) {
107 Debug("substitution") << "SubstitutionMap::addSubstitution(" << x
<< ", " << t
<< ")" << std::endl
;
108 Assert(d_substitutions
.find(x
) == d_substitutions
.end());
110 // Temporary substitution cache
114 // Put in the new substitutions into the old ones
115 NodeMap::iterator it
= d_substitutions
.begin();
116 NodeMap::iterator it_end
= d_substitutions
.end();
117 for(; it
!= it_end
; ++ it
) {
118 d_substitutions
[(*it
).first
] = internalSubstitute((*it
).second
, tempCache
);
121 // Put the new substitution in, but apply existing substitutions to rhs first
122 d_substitutions
[x
] = apply(t
);
124 // Also invalidate the cache
125 if (invalidateCache
) {
126 d_cacheInvalidated
= true;
129 d_substitutionCache
[x
] = d_substitutions
[x
];
133 static bool check(TNode node
, const SubstitutionMap::NodeMap
& substitutions
) CVC4_UNUSED
;
134 static bool check(TNode node
, const SubstitutionMap::NodeMap
& substitutions
) {
135 SubstitutionMap::NodeMap::const_iterator it
= substitutions
.begin();
136 SubstitutionMap::NodeMap::const_iterator it_end
= substitutions
.end();
137 Debug("substitution") << "checking " << node
<< std::endl
;
138 for (; it
!= it_end
; ++ it
) {
139 Debug("substitution") << "-- hasSubterm( " << (*it
).first
<< " ) ?" << std::endl
;
140 if (node
.hasSubterm((*it
).first
)) {
141 Debug("substitution") << "-- FAIL" << std::endl
;
145 Debug("substitution") << "-- SUCCEED" << std::endl
;
149 Node
SubstitutionMap::apply(TNode t
) {
151 Debug("substitution") << "SubstitutionMap::apply(" << t
<< ")" << std::endl
;
154 if (d_cacheInvalidated
) {
155 SubstitutionMap::NodeMap::const_iterator it
= d_substitutions
.begin();
156 SubstitutionMap::NodeMap::const_iterator it_end
= d_substitutions
.end();
157 d_substitutionCache
.clear();
158 for (; it
!= it_end
; ++ it
) {
159 d_substitutionCache
[(*it
).first
] = (*it
).second
;
161 d_cacheInvalidated
= false;
162 Debug("substitution") << "-- reset the cache" << std::endl
;
165 // Perform the substitution
166 Node result
= internalSubstitute(t
, d_substitutionCache
);
167 Debug("substitution") << "SubstitutionMap::apply(" << t
<< ") => " << result
<< std::endl
;
169 Assert(check(result
, d_substitutions
));
174 void SubstitutionMap::print(ostream
& out
) const {
175 NodeMap::const_iterator it
= d_substitutions
.begin();
176 NodeMap::const_iterator it_end
= d_substitutions
.end();
177 for (; it
!= it_end
; ++ it
) {
178 out
<< (*it
).first
<< " -> " << (*it
).second
<< endl
;
182 }/* CVC4::theory namespace */
184 std::ostream
& operator<<(std::ostream
& out
, const theory::SubstitutionMap::iterator
& i
) {
185 return out
<< "[CDMap-iterator]";
188 }/* CVC4 namespace */