Finished implementing completion (unit tests to follow).
This commit is contained in:
parent
a23e248e7b
commit
a716da4af1
41
include/anthem/ASTUtils.h
Normal file
41
include/anthem/ASTUtils.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __ANTHEM__AST_UTILS_H
|
||||
#define __ANTHEM__AST_UTILS_H
|
||||
|
||||
#include <anthem/AST.h>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
namespace ast
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AST Utils
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VariableStack
|
||||
{
|
||||
public:
|
||||
using Layer = const std::vector<ast::Variable> *;
|
||||
|
||||
public:
|
||||
void push(Layer layer);
|
||||
void pop();
|
||||
|
||||
bool contains(const ast::Variable &variable) const;
|
||||
|
||||
private:
|
||||
std::vector<Layer> m_layers;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<ast::Variable> collectFreeVariables(const ast::Formula &formula, ast::VariableStack &variableStack);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
190
src/anthem/ASTUtils.cpp
Normal file
190
src/anthem/ASTUtils.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include <anthem/ASTUtils.h>
|
||||
|
||||
#include <anthem/ASTVisitors.h>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
namespace ast
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AST Utils
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VariableStack::push(Layer layer)
|
||||
{
|
||||
m_layers.push_back(layer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VariableStack::pop()
|
||||
{
|
||||
m_layers.pop_back();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool VariableStack::contains(const ast::Variable &variable) const
|
||||
{
|
||||
const auto variableMatches =
|
||||
[&variable](const auto &otherVariable)
|
||||
{
|
||||
return variable.name == otherVariable.name;
|
||||
};
|
||||
|
||||
const auto layerContainsVariable =
|
||||
[&variable, &variableMatches](const auto &layer)
|
||||
{
|
||||
return (std::find_if(layer->cbegin(), layer->cend(), variableMatches) != layer->cend());
|
||||
};
|
||||
|
||||
return (std::find_if(m_layers.cbegin(), m_layers.cend(), layerContainsVariable) != m_layers.cend());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CollectFreeVariablesVisitor
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Formulas
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void visit(const ast::And &and_, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
for (const auto &argument : and_.arguments)
|
||||
argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Biconditional &biconditional, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
biconditional.left.accept(*this, variableStack, freeVariables);
|
||||
biconditional.right.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Boolean &, VariableStack &, std::vector<ast::Variable> &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const ast::Comparison &comparison, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
comparison.left.accept(*this, variableStack, freeVariables);
|
||||
comparison.right.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Exists &exists, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
variableStack.push(&exists.variables);
|
||||
exists.argument.accept(*this, variableStack, freeVariables);
|
||||
variableStack.pop();
|
||||
}
|
||||
|
||||
void visit(const ast::ForAll &forAll, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
variableStack.push(&forAll.variables);
|
||||
forAll.argument.accept(*this, variableStack, freeVariables);
|
||||
variableStack.pop();
|
||||
}
|
||||
|
||||
void visit(const ast::Implies &implies, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
implies.antecedent.accept(*this, variableStack, freeVariables);
|
||||
implies.consequent.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::In &in, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
in.element.accept(*this, variableStack, freeVariables);
|
||||
in.set.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Not ¬_, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
not_.argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Or &or_, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
for (const auto &argument : or_.arguments)
|
||||
argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Predicate &predicate, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
for (const auto &argument : predicate.arguments)
|
||||
argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Terms
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void visit(const ast::BinaryOperation &binaryOperation, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
binaryOperation.left.accept(*this, variableStack, freeVariables);
|
||||
binaryOperation.right.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Constant &, VariableStack &, std::vector<ast::Variable> &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const ast::Function &function, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
for (const auto &argument : function.arguments)
|
||||
argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::Integer &, VariableStack &, std::vector<ast::Variable> &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const ast::Interval &interval, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
interval.from.accept(*this, variableStack, freeVariables);
|
||||
interval.to.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(const ast::SpecialInteger &, VariableStack &, std::vector<ast::Variable> &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const ast::String &, VariableStack &, std::vector<ast::Variable> &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const ast::Variable &variable, VariableStack &variableStack, std::vector<ast::Variable> &freeVariables)
|
||||
{
|
||||
if (variableStack.contains(variable))
|
||||
return;
|
||||
|
||||
const auto &variableMatches =
|
||||
[&variable](auto &otherVariable)
|
||||
{
|
||||
return variable.name == otherVariable.name;
|
||||
};
|
||||
|
||||
if (std::find_if(freeVariables.cbegin(), freeVariables.cend(), variableMatches) != freeVariables.cend())
|
||||
return;
|
||||
|
||||
freeVariables.emplace_back(ast::deepCopy(variable));
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<ast::Variable> collectFreeVariables(const ast::Formula &formula, ast::VariableStack &variableStack)
|
||||
{
|
||||
std::vector<ast::Variable> freeVariables;
|
||||
|
||||
formula.accept(CollectFreeVariablesVisitor(), variableStack, freeVariables);
|
||||
|
||||
return freeVariables;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <anthem/Completion.h>
|
||||
|
||||
#include <anthem/ASTUtils.h>
|
||||
#include <anthem/ASTVisitors.h>
|
||||
|
||||
namespace anthem
|
||||
@ -41,6 +42,16 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
||||
checkMatchingPredicates(predicate.arguments[i], otherPredicate.arguments[i]);
|
||||
}
|
||||
|
||||
// Copy the predicate’s arguments for the completed formula
|
||||
std::vector<ast::Variable> variables;
|
||||
variables.reserve(predicate.arguments.size());
|
||||
|
||||
for (const auto &argument : predicate.arguments)
|
||||
{
|
||||
assert(argument.is<ast::Variable>());
|
||||
variables.emplace_back(ast::deepCopy(argument.get<ast::Variable>()));
|
||||
}
|
||||
|
||||
auto or_ = ast::Formula::make<ast::Or>();
|
||||
|
||||
// Build the conjunction of all formulas with the predicate as consequent
|
||||
@ -58,11 +69,18 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: implement variable lists
|
||||
std::vector<ast::Variable> variables = {ast::Variable("dummy", ast::Variable::Type::UserDefined)};
|
||||
auto exists = ast::Formula::make<ast::Exists>(std::move(variables), std::move(implies.antecedent));
|
||||
ast::VariableStack variableStack;
|
||||
variableStack.push(&variables);
|
||||
|
||||
or_.get<ast::Or>().arguments.emplace_back(exists);
|
||||
auto variables = ast::collectFreeVariables(implies.antecedent, variableStack);
|
||||
|
||||
if (variables.empty())
|
||||
or_.get<ast::Or>().arguments.emplace_back(std::move(implies.antecedent));
|
||||
else
|
||||
{
|
||||
auto exists = ast::Formula::make<ast::Exists>(std::move(variables), std::move(implies.antecedent));
|
||||
or_.get<ast::Or>().arguments.emplace_back(std::move(exists));
|
||||
}
|
||||
|
||||
if (i > formulasBegin)
|
||||
formulas.erase(formulas.begin() + i);
|
||||
@ -70,6 +88,9 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
||||
i++;
|
||||
}
|
||||
|
||||
if (or_.get<ast::Or>().arguments.size() == 1)
|
||||
or_ = or_.get<ast::Or>().arguments.front();
|
||||
|
||||
// Build the biconditional within the completed formula
|
||||
auto biconditional = ast::Formula::make<ast::Biconditional>(ast::deepCopy(predicate), std::move(or_));
|
||||
|
||||
@ -79,16 +100,6 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the predicate’s arguments for the completed formula
|
||||
std::vector<ast::Variable> variables;
|
||||
variables.reserve(predicate.arguments.size());
|
||||
|
||||
for (const auto &argument : predicate.arguments)
|
||||
{
|
||||
assert(argument.is<ast::Variable>());
|
||||
variables.emplace_back(ast::deepCopy(argument.get<ast::Variable>()));
|
||||
}
|
||||
|
||||
auto completedFormula = ast::Formula::make<ast::ForAll>(std::move(variables), std::move(biconditional));
|
||||
|
||||
formulas[formulasBegin] = std::move(completedFormula);
|
||||
|
@ -56,18 +56,15 @@ void translate(const char *fileName, std::istream &stream, Context &context)
|
||||
|
||||
Clingo::parse_program(fileContent.c_str(), translateStatement, logger);
|
||||
|
||||
if (context.simplify)
|
||||
for (auto &formula : formulas)
|
||||
simplify(formula);
|
||||
|
||||
if (context.complete)
|
||||
complete(formulas);
|
||||
|
||||
for (auto i = formulas.begin(); i != formulas.end(); i++)
|
||||
{
|
||||
auto &formula = *i;
|
||||
|
||||
if (context.simplify)
|
||||
simplify(formula);
|
||||
|
||||
for (const auto &formula : formulas)
|
||||
context.logger.outputStream() << formula << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user