static bool check(TNode node, const SubstitutionMap::NodeMap& substitutions) { SubstitutionMap::NodeMap::const_iterator it = substitutions.begin(); SubstitutionMap::NodeMap::const_iterator it_end = substitutions.end(); Debug("substitution") << "checking " << node << endl; for (; it != it_end; ++ it) { Debug("substitution") << "-- hasSubterm( " << (*it).first << " ) ?" << endl; if (node.hasSubterm((*it).first)) { Debug("substitution") << "-- FAIL" << endl; return false; } } Debug("substitution") << "-- SUCCEED" << endl; return true; }
bool AlgebraicSolver::isSubstitutableIn(TNode node, TNode in) { if (node.getMetaKind() == kind::metakind::VARIABLE && !in.hasSubterm(node)) return true; return false; }
bool AlgebraicSolver::solve(TNode fact, TNode reason, SubstitutionEx& subst) { if (fact.getKind() != kind::EQUAL) return false; TNode left = fact[0]; TNode right = fact[1]; if (left.isVar() && !right.hasSubterm(left)) { bool changed = subst.addSubstitution(left, right, reason); return changed; } if (right.isVar() && !left.hasSubterm(right)) { bool changed = subst.addSubstitution(right, left, reason); return changed; } // xor simplification if (right.getKind() == kind::BITVECTOR_XOR && left.getKind() == kind::BITVECTOR_XOR) { TNode var = left[0]; if (var.getMetaKind() != kind::metakind::VARIABLE) return false; // simplify xor with same variable on both sides if (right.hasSubterm(var)) { std::vector<Node> right_children; for (unsigned i = 0; i < right.getNumChildren(); ++i) { if (right[i] != var) right_children.push_back(right[i]); } Assert (right_children.size()); Node new_right = right_children.size() > 1 ? utils::mkNode(kind::BITVECTOR_XOR, right_children) : right_children[0]; std::vector<Node> left_children; for (unsigned i = 1; i < left.getNumChildren(); ++i) { left_children.push_back(left[i]); } Node new_left = left_children.size() > 1 ? utils::mkNode(kind::BITVECTOR_XOR, left_children) : left_children[0]; Node new_fact = utils::mkNode(kind::EQUAL, new_left, new_right); bool changed = subst.addSubstitution(fact, new_fact, reason); return changed; } NodeBuilder<> nb(kind::BITVECTOR_XOR); for (unsigned i = 1; i < left.getNumChildren(); ++i) { nb << left[i]; } Node inverse = left.getNumChildren() == 2? (Node)left[1] : (Node)nb; Node new_right = utils::mkNode(kind::BITVECTOR_XOR, right, inverse); bool changed = subst.addSubstitution(var, new_right, reason); if (Dump.isOn("bv-algebraic")) { Node query = utils::mkNot(utils::mkNode(kind::IFF, fact, utils::mkNode(kind::EQUAL, var, new_right))); Dump("bv-algebraic") << EchoCommand("ThoeryBV::AlgebraicSolver::substitution explanation"); Dump("bv-algebraic") << PushCommand(); Dump("bv-algebraic") << AssertCommand(query.toExpr()); Dump("bv-algebraic") << CheckSatCommand(); Dump("bv-algebraic") << PopCommand(); } return changed; } // (a xor t = a) <=> (t = 0) if (left.getKind() == kind::BITVECTOR_XOR && right.getMetaKind() == kind::metakind::VARIABLE && left.hasSubterm(right)) { TNode var = right; Node new_left = utils::mkNode(kind::BITVECTOR_XOR, var, left); Node zero = utils::mkConst(utils::getSize(var), 0u); Node new_fact = utils::mkNode(kind::EQUAL, zero, new_left); bool changed = subst.addSubstitution(fact, new_fact, reason); return changed; } if (right.getKind() == kind::BITVECTOR_XOR && left.getMetaKind() == kind::metakind::VARIABLE && right.hasSubterm(left)) { TNode var = left; Node new_right = utils::mkNode(kind::BITVECTOR_XOR, var, right); Node zero = utils::mkConst(utils::getSize(var), 0u); Node new_fact = utils::mkNode(kind::EQUAL, zero, new_right); bool changed = subst.addSubstitution(fact, new_fact, reason); return changed; } // (a xor b = 0) <=> (a = b) if (left.getKind() == kind::BITVECTOR_XOR && left.getNumChildren() == 2 && right.getKind() == kind::CONST_BITVECTOR && right.getConst<BitVector>() == BitVector(utils::getSize(left), 0u)) { Node new_fact = utils::mkNode(kind::EQUAL, left[0], left[1]); bool changed = subst.addSubstitution(fact, new_fact, reason); return changed; } return false; }