Finished implementing completion (unit tests to follow).

This commit is contained in:
Patrick Lühne 2017-04-08 16:21:24 +02:00
parent a23e248e7b
commit a716da4af1
No known key found for this signature in database
GPG Key ID: 05F3611E97A70ABF
4 changed files with 261 additions and 22 deletions

41
include/anthem/ASTUtils.h Normal file
View 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
View 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 &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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -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 predicates 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 predicates 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);

View File

@ -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;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////