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/Completion.h>
|
||||||
|
|
||||||
|
#include <anthem/ASTUtils.h>
|
||||||
#include <anthem/ASTVisitors.h>
|
#include <anthem/ASTVisitors.h>
|
||||||
|
|
||||||
namespace anthem
|
namespace anthem
|
||||||
@ -41,6 +42,16 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
|||||||
checkMatchingPredicates(predicate.arguments[i], otherPredicate.arguments[i]);
|
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>();
|
auto or_ = ast::Formula::make<ast::Or>();
|
||||||
|
|
||||||
// Build the conjunction of all formulas with the predicate as consequent
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement variable lists
|
ast::VariableStack variableStack;
|
||||||
std::vector<ast::Variable> variables = {ast::Variable("dummy", ast::Variable::Type::UserDefined)};
|
variableStack.push(&variables);
|
||||||
auto exists = ast::Formula::make<ast::Exists>(std::move(variables), std::move(implies.antecedent));
|
|
||||||
|
|
||||||
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)
|
if (i > formulasBegin)
|
||||||
formulas.erase(formulas.begin() + i);
|
formulas.erase(formulas.begin() + i);
|
||||||
@ -70,6 +88,9 @@ void completePredicate(const ast::Predicate &predicate, std::vector<ast::Formula
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (or_.get<ast::Or>().arguments.size() == 1)
|
||||||
|
or_ = or_.get<ast::Or>().arguments.front();
|
||||||
|
|
||||||
// Build the biconditional within the completed formula
|
// Build the biconditional within the completed formula
|
||||||
auto biconditional = ast::Formula::make<ast::Biconditional>(ast::deepCopy(predicate), std::move(or_));
|
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;
|
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));
|
auto completedFormula = ast::Formula::make<ast::ForAll>(std::move(variables), std::move(biconditional));
|
||||||
|
|
||||||
formulas[formulasBegin] = std::move(completedFormula);
|
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);
|
Clingo::parse_program(fileContent.c_str(), translateStatement, logger);
|
||||||
|
|
||||||
|
if (context.simplify)
|
||||||
|
for (auto &formula : formulas)
|
||||||
|
simplify(formula);
|
||||||
|
|
||||||
if (context.complete)
|
if (context.complete)
|
||||||
complete(formulas);
|
complete(formulas);
|
||||||
|
|
||||||
for (auto i = formulas.begin(); i != formulas.end(); i++)
|
for (const auto &formula : formulas)
|
||||||
{
|
|
||||||
auto &formula = *i;
|
|
||||||
|
|
||||||
if (context.simplify)
|
|
||||||
simplify(formula);
|
|
||||||
|
|
||||||
context.logger.outputStream() << formula << std::endl;
|
context.logger.outputStream() << formula << std::endl;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user