summaryrefslogtreecommitdiff
path: root/src/expr/proof_node.cpp
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2020-04-20 14:53:07 -0500
committerGitHub <noreply@github.com>2020-04-20 14:53:07 -0500
commita76b222149e828ed0fe7fb6e91684552dc7b64ec (patch)
treedaed349df6924755c2a1e32d601f03328aa00da7 /src/expr/proof_node.cpp
parentecf3e9c874095e836b5ea4d9bed6b063b2a5f108 (diff)
Add SCOPE proof rule (#4332)
This rule is dual to ASSUME. It is a way of closing free assumptions to conclude an implication. It also changes getId -> getRule.
Diffstat (limited to 'src/expr/proof_node.cpp')
-rw-r--r--src/expr/proof_node.cpp55
1 files changed, 46 insertions, 9 deletions
diff --git a/src/expr/proof_node.cpp b/src/expr/proof_node.cpp
index 94c175025..b5e391049 100644
--- a/src/expr/proof_node.cpp
+++ b/src/expr/proof_node.cpp
@@ -23,7 +23,7 @@ ProofNode::ProofNode(PfRule id,
setValue(id, children, args);
}
-PfRule ProofNode::getId() const { return d_id; }
+PfRule ProofNode::getRule() const { return d_rule; }
const std::vector<std::shared_ptr<ProofNode>>& ProofNode::getChildren() const
{
@@ -34,11 +34,14 @@ const std::vector<Node>& ProofNode::getArguments() const { return d_args; }
Node ProofNode::getResult() const { return d_proven; }
-void ProofNode::getAssumptions(std::vector<Node>& assump) const
+void ProofNode::getFreeAssumptions(std::vector<Node>& assump) const
{
- std::unordered_set<const ProofNode*> visited;
- std::unordered_set<const ProofNode*>::iterator it;
+ // visited set false after preorder traversal, true after postorder traversal
+ std::unordered_map<const ProofNode*, bool> visited;
+ std::unordered_map<const ProofNode*, bool>::iterator it;
std::vector<const ProofNode*> visit;
+ // the current set of formulas bound by SCOPE
+ std::unordered_set<Node, NodeHashFunction> currentScope;
const ProofNode* cur;
visit.push_back(this);
do
@@ -48,35 +51,69 @@ void ProofNode::getAssumptions(std::vector<Node>& assump) const
it = visited.find(cur);
if (it == visited.end())
{
- visited.insert(cur);
- if (cur->getId() == PfRule::ASSUME)
+ visited[cur] = true;
+ PfRule id = cur->getRule();
+ if (id == PfRule::ASSUME)
{
- assump.push_back(cur->d_proven);
+ Assert(cur->d_args.size() == 1);
+ Node f = cur->d_args[0];
+ if (currentScope.find(f) == currentScope.end())
+ {
+ assump.push_back(f);
+ }
}
else
{
+ if (id == PfRule::SCOPE)
+ {
+ // mark that its arguments are bound in the current scope
+ for (const Node& a : cur->d_args)
+ {
+ // should not have assumption shadowing
+ Assert(currentScope.find(a) != currentScope.end());
+ currentScope.insert(a);
+ }
+ // will need to unbind the variables below
+ visited[cur] = false;
+ }
for (const std::shared_ptr<ProofNode>& cp : cur->d_children)
{
visit.push_back(cp.get());
}
}
}
+ else if (!it->second)
+ {
+ Assert(cur->getRule() == PfRule::SCOPE);
+ // unbind its assumptions
+ for (const Node& a : cur->d_args)
+ {
+ currentScope.erase(a);
+ }
+ }
} while (!visit.empty());
}
+bool ProofNode::isClosed() const
+{
+ std::vector<Node> assumps;
+ getFreeAssumptions(assumps);
+ return assumps.empty();
+}
+
void ProofNode::setValue(
PfRule id,
const std::vector<std::shared_ptr<ProofNode>>& children,
const std::vector<Node>& args)
{
- d_id = id;
+ d_rule = id;
d_children = children;
d_args = args;
}
void ProofNode::printDebug(std::ostream& os) const
{
- os << "(" << d_id;
+ os << "(" << d_rule;
for (const std::shared_ptr<ProofNode>& c : d_children)
{
os << " ";
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback