{
// If x is less than t based on an ordering, then we use { x -> t } as a
// substitution to the children of ite( x = t ^ C, s, t ) below.
- std::vector<Node> vars;
- std::vector<Node> subs;
- inferSubstitution(n[0], vars, subs, true);
+ Subs subs;
+ inferSubstitution(n[0], subs, true);
- if (!vars.empty())
+ if (!subs.empty())
{
// reverse substitution to opposite child
// r{ x -> t } = s implies ite( x=t ^ C, s, r ) ---> r
// We can use ordinary substitute since the result of the substitution
// is not being returned. In other words, nn is only being used to query
// whether the second branch is a generalization of the first.
- Node nn =
- t2.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
+ Node nn = subs.apply(t2);
if (nn != t2)
{
nn = d_rew.rewrite(nn);
// ite( x=t ^ C, s, r ) ---> ite( x=t ^ C, s{ x -> t }, r )
// must use partial substitute here, to avoid substitution into witness
std::map<Kind, bool> rkinds;
- nn = partialSubstitute(t1, vars, subs, rkinds);
+ nn = partialSubstitute(t1, subs, rkinds);
nn = d_rew.rewrite(nn);
if (nn != t1)
{
if (!eq.isNull())
{
// see if it corresponds to a substitution
- std::vector<Node> vars;
- std::vector<Node> subs;
- if (inferSubstitution(eq, vars, subs))
+ Subs subs;
+ if (inferSubstitution(eq, subs))
{
- Assert(vars.size() == 1);
+ Assert(subs.size() == 1);
std::vector<Node> children;
bool childrenChanged = false;
// apply to all other children
// Substitution is only applicable to compatible kinds. We always
// use the partialSubstitute method to avoid substitution into
// witness terms.
- ccs = partialSubstitute(ccs, vars, subs, bcp_kinds);
+ ccs = partialSubstitute(ccs, subs, bcp_kinds);
childrenChanged = childrenChanged || n[j] != ccs;
}
children.push_back(ccs);
}
Node ExtendedRewriter::partialSubstitute(
- Node n,
- const std::vector<Node>& vars,
- const std::vector<Node>& subs,
- const std::map<Kind, bool>& rkinds) const
+ Node n, const Subs& subs, const std::map<Kind, bool>& rkinds) const
{
- Assert(vars.size() == subs.size());
std::map<Node, Node> assign;
- for (size_t i = 0, nvars = vars.size(); i < nvars; i++)
+ for (size_t i = 0, nvars = subs.size(); i < nvars; i++)
{
- assign[vars[i]] = subs[i];
+ assign[subs.d_vars[i]] = subs.d_subs[i];
}
return partialSubstitute(n, assign, rkinds);
}
return Node::null();
}
-bool ExtendedRewriter::inferSubstitution(Node n,
- std::vector<Node>& vars,
- std::vector<Node>& subs,
- bool usePred) const
+bool ExtendedRewriter::inferSubstitution(Node n, Subs& subs, bool usePred) const
{
if (n.getKind() == AND)
{
bool ret = false;
for (const Node& nc : n)
{
- bool cret = inferSubstitution(nc, vars, subs, usePred);
+ bool cret = inferSubstitution(nc, subs, usePred);
ret = ret || cret;
}
return ret;
{
if (n[i].isConst())
{
- vars.push_back(n[1 - i]);
- subs.push_back(n[i]);
+ subs.add(n[1 - i], n[i]);
return true;
}
if (n[i].isVar())
Assert(TermUtil::isNegate(n[i].getKind()));
r2 = TermUtil::mkNegate(n[i].getKind(), r2);
}
- // TODO (#1706) : union find
- if (std::find(vars.begin(), vars.end(), r1) == vars.end())
+ if (!subs.contains(r1))
{
- vars.push_back(r1);
- subs.push_back(r2);
+ subs.add(r1, r2);
return true;
}
}
if (usePred)
{
bool negated = n.getKind() == NOT;
- vars.push_back(negated ? n[0] : n);
- subs.push_back(negated ? d_false : d_true);
+ Node var = negated ? n[0] : n;
+ Node s = NodeManager::currentNM()->mkConst(!negated);
+ subs.add(var, s);
return true;
}
return false;
#include <unordered_map>
#include "expr/node.h"
+#include "expr/subs.h"
namespace cvc5::internal {
namespace theory {
Node partialSubstitute(Node n,
const std::map<Node, Node>& assign,
const std::map<Kind, bool>& rkinds) const;
- /** same as above, with vectors */
+ /** same as above, with the subs utility */
Node partialSubstitute(Node n,
- const std::vector<Node>& vars,
- const std::vector<Node>& subs,
+ const Subs& subs,
const std::map<Kind, bool>& rkinds) const;
/** solve equality
*
* If n is an equality of the form x = t, where t is either:
* (1) a constant, or
* (2) a variable y such that x < y based on an ordering,
- * then this method adds x to vars and y to subs and return true, otherwise
+ * then this method adds {x -> y} to subs and return true, otherwise
* it returns false.
* If usePred is true, we may additionally add n -> true, or n[0] -> false
* is n is a negation.
*/
- bool inferSubstitution(Node n,
- std::vector<Node>& vars,
- std::vector<Node>& subs,
- bool usePred = false) const;
+ bool inferSubstitution(Node n, Subs& subs, bool usePred = false) const;
/** extended rewrite
*
* Prints debug information, indicating the rewrite n ---> ret was found.