Added back completion support.

This commit is contained in:
2017-06-01 02:37:45 +02:00
parent c47bd3c934
commit 4baed6fbc6
7 changed files with 144 additions and 165 deletions

View File

@@ -16,56 +16,6 @@ namespace ast
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Replacing Variables
////////////////////////////////////////////////////////////////////////////////////////////////////
// Replaces all occurrences of a variable in a given term with another term
struct ReplaceVariableInTermVisitor : public RecursiveTermVisitor<ReplaceVariableInTermVisitor>
{
static void accept(Variable &variable, Term &, const VariableDeclaration *original, VariableDeclaration *replacement)
{
if (variable.declaration == original)
variable.declaration = replacement;
}
// Ignore all other types of expressions
template<class T>
static void accept(T &, Term &, const VariableDeclaration *, VariableDeclaration *)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Replaces all occurrences of a variable in a given formula with a term
struct ReplaceVariableInFormulaVisitor : public RecursiveFormulaVisitor<ReplaceVariableInFormulaVisitor>
{
static void accept(Comparison &comparison, Formula &, const VariableDeclaration *original, VariableDeclaration *replacement)
{
comparison.left.accept(ReplaceVariableInTermVisitor(), comparison.left, original, replacement);
comparison.right.accept(ReplaceVariableInTermVisitor(), comparison.right, original, replacement);
}
static void accept(In &in, Formula &, const VariableDeclaration *original, VariableDeclaration *replacement)
{
in.element.accept(ReplaceVariableInTermVisitor(), in.element, original, replacement);
in.set.accept(ReplaceVariableInTermVisitor(), in.set, original, replacement);
}
static void accept(Predicate &predicate, Formula &, const VariableDeclaration *original, VariableDeclaration *replacement)
{
for (auto &argument : predicate.arguments)
argument.accept(ReplaceVariableInTermVisitor(), argument, original, replacement);
}
// Ignore all other types of expressions
template<class T>
static void accept(T &, Formula &, const VariableDeclaration *, VariableDeclaration *)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Preparing Copying
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -192,25 +192,6 @@ struct CollectFreeVariablesVisitor
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<VariableDeclaration *> collectFreeVariables(Formula &formula)
{
VariableStack variableStack;
return collectFreeVariables(formula, variableStack);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<VariableDeclaration *> collectFreeVariables(Formula &formula, VariableStack &variableStack)
{
std::vector<VariableDeclaration *> freeVariables;
formula.accept(CollectFreeVariablesVisitor(), variableStack, freeVariables);
return freeVariables;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct CollectPredicatesVisitor : public RecursiveFormulaVisitor<CollectPredicatesVisitor>
{
static void accept(const Predicate &predicate, const Formula &, std::vector<const Predicate *> &predicates)

View File

@@ -1,8 +1,10 @@
#include <anthem/Completion.h>
#include <anthem/AST.h>
#include <anthem/ASTCopy.h>
#include <anthem/ASTUtils.h>
#include <anthem/ASTVisitors.h>
#include <anthem/Exception.h>
#include <anthem/Utils.h>
namespace anthem
@@ -14,33 +16,14 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// Copies the parameters of a predicate
std::vector<std::unique_ptr<ast::VariableDeclaration>> copyParameters(const ast::Predicate &predicate)
{
std::vector<std::unique_ptr<ast::VariableDeclaration>> parameters;
/*parameters.reserve(predicate.arity());
for (const auto &argument : predicate.arguments)
{
assert(argument.is<ast::Variable>());
// TODO: reimplement
//parameters.emplace_back(ast::deepCopy(parameter.get<ast::VariableDeclaration>()));
}*/
return parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Builds the conjunction within the completed formula for a given predicate
ast::Formula buildCompletedFormulaDisjunction(const ast::Predicate &predicate, std::vector<std::unique_ptr<ast::VariableDeclaration>> &parameters, std::vector<ast::ScopedFormula> &scopedFormulas)
ast::Formula buildCompletedFormulaDisjunction(const ast::Predicate &predicate, const ast::VariableDeclarationPointers &parameters, std::vector<ast::ScopedFormula> &scopedFormulas)
{
auto disjunction = ast::Formula::make<ast::Or>();
/*ast::VariableStack variableStack;
variableStack.push(&parameters);
assert(predicate.arguments.size() == parameters.size());
// Build the conjunction of all formulas with the predicate as consequent
// Build the disjunction of all formulas with the predicate as consequent
for (auto &scopedFormula : scopedFormulas)
{
assert(scopedFormula.formula.is<ast::Implies>());
@@ -54,18 +37,36 @@ ast::Formula buildCompletedFormulaDisjunction(const ast::Predicate &predicate, s
if (!ast::matches(predicate, otherPredicate))
continue;
auto variables = ast::collectFreeVariables(implies.antecedent, variableStack);
assert(otherPredicate.arguments.size() == parameters.size());
// TODO: avoid deep copies
// TODO: reimplement
if (variables.empty())
disjunction.get<ast::Or>().arguments.emplace_back(ast::deepCopy(implies.antecedent));
// Each formula with the predicate as its consequent currently has its own copy of the predicates parameters
// These need to be linked to the new, unique set of parameters
for (size_t i = 0; i < parameters.size(); i++)
{
assert(otherPredicate.arguments[i].is<ast::Variable>());
const auto &otherVariable = otherPredicate.arguments[i].get<ast::Variable>();
scopedFormula.formula.accept(ast::ReplaceVariableInFormulaVisitor(), scopedFormula.formula, otherVariable.declaration, parameters[i].get());
}
// Remove all the head variables, because they are not free variables after completion
const auto isHeadVariable =
[](const auto &variableDeclaration)
{
return variableDeclaration->type == ast::VariableDeclaration::Type::Head;
};
auto &freeVariables = scopedFormula.freeVariables;
freeVariables.erase(std::remove_if(freeVariables.begin(), freeVariables.end(), isHeadVariable), freeVariables.end());
if (freeVariables.empty())
disjunction.get<ast::Or>().arguments.emplace_back(std::move(implies.antecedent));
else
{
auto exists = ast::Formula::make<ast::Exists>(std::move(variables), ast::deepCopy(implies.antecedent));
auto exists = ast::Formula::make<ast::Exists>(std::move(freeVariables), std::move(implies.antecedent));
disjunction.get<ast::Or>().arguments.emplace_back(std::move(exists));
}
}*/
}
return disjunction;
}
@@ -77,7 +78,7 @@ ast::Formula buildCompletedFormulaQuantified(ast::Predicate &&predicate, ast::Fo
{
assert(innerFormula.is<ast::Or>());
/*if (innerFormula.get<ast::Or>().arguments.empty())
if (innerFormula.get<ast::Or>().arguments.empty())
return ast::Formula::make<ast::Not>(std::move(predicate));
if (innerFormula.get<ast::Or>().arguments.size() == 1)
@@ -91,72 +92,77 @@ ast::Formula buildCompletedFormulaQuantified(ast::Predicate &&predicate, ast::Fo
return std::move(predicate);
else
return ast::Formula::make<ast::Not>(std::move(predicate));
}*/
}
return ast::Formula::make<ast::Biconditional>(std::move(predicate), std::move(innerFormula));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void completePredicate(ast::Predicate &&predicate, std::vector<ast::ScopedFormula> &scopedFormulas, std::vector<ast::ScopedFormula> &completedScopedFormulas)
ast::Formula completePredicate(const ast::Predicate &predicate, std::vector<ast::ScopedFormula> &scopedFormulas)
{
/*auto parameters = copyParameters(predicate);
auto completedFormulaDisjunction = buildCompletedFormulaDisjunction(predicate, parameters, scopedFormulas);
auto completedFormulaQuantified = buildCompletedFormulaQuantified(std::move(predicate), std::move(completedFormulaDisjunction));
// Create new set of parameters for the completed definition for the predicate
ast::VariableDeclarationPointers parameters;
parameters.reserve(predicate.arguments.size());
if (parameters.empty())
std::vector<ast::Term> arguments;
arguments.reserve(predicate.arguments.size());
for (size_t i = 0; i < predicate.arguments.size(); i++)
{
completedFormulas.emplace_back(std::move(completedFormulaQuantified));
return;
parameters.emplace_back(std::make_unique<ast::VariableDeclaration>(ast::VariableDeclaration::Type::Head));
arguments.emplace_back(ast::Term::make<ast::Variable>(parameters.back().get()));
}
auto completedFormula = ast::Formula::make<ast::ForAll>(std::move(parameters), std::move(completedFormulaQuantified));
completedFormulas.emplace_back(std::move(completedFormula));*/
ast::Predicate predicateCopy(std::string(predicate.name), std::move(arguments));
auto completedFormulaDisjunction = buildCompletedFormulaDisjunction(predicateCopy, parameters, scopedFormulas);
auto completedFormulaQuantified = buildCompletedFormulaQuantified(std::move(predicateCopy), std::move(completedFormulaDisjunction));
if (parameters.empty())
return completedFormulaQuantified;
return ast::Formula::make<ast::ForAll>(std::move(parameters), std::move(completedFormulaQuantified));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void completeIntegrityConstraint(ast::Formula &formula, std::vector<ast::ScopedFormula> &)
ast::Formula completeIntegrityConstraint(ast::ScopedFormula &scopedFormula)
{
/*assert(formula.is<ast::Implies>());
auto &implies = formula.get<ast::Implies>();
assert(scopedFormula.formula.is<ast::Implies>());
auto &implies = scopedFormula.formula.get<ast::Implies>();
assert(implies.consequent.is<ast::Boolean>());
assert(implies.consequent.get<ast::Boolean>().value == false);
auto variables = ast::collectFreeVariables(implies.antecedent);
auto argument = ast::Formula::make<ast::Not>(std::move(implies.antecedent));
// TODO: avoid deep copies
// TODO: reimplement
auto argument = ast::Formula::make<ast::Not>(ast::deepCopy(implies.antecedent));
auto &freeVariables = scopedFormula.freeVariables;
if (variables.empty())
{
completedFormulas.emplace_back(std::move(argument));
return;
}
if (freeVariables.empty())
return argument;
auto completedFormula = ast::Formula::make<ast::ForAll>(std::move(variables), std::move(argument));
completedFormulas.emplace_back(std::move(completedFormula));*/
return ast::Formula::make<ast::ForAll>(std::move(freeVariables), std::move(argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void complete(std::vector<ast::ScopedFormula> &scopedFormulas)
std::vector<ast::Formula> complete(std::vector<ast::ScopedFormula> &&scopedFormulas)
{
/*// Check whether formulas are in normal form
// Check whether formulas are in normal form
for (const auto &scopedFormula : scopedFormulas)
{
if (!scopedFormula.formula.is<ast::Implies>())
throw std::runtime_error("cannot perform completion, formula not in normal form");
throw CompletionException("cannot perform completion, formula not in normal form");
auto &implies = scopedFormula.formula.get<ast::Implies>();
if (!implies.consequent.is<ast::Predicate>() && !implies.consequent.is<ast::Boolean>())
throw std::runtime_error("cannot perform completion, only single predicates and Booleans supported as formula consequent currently");
throw CompletionException("cannot perform completion, only single predicates and Booleans supported as formula consequent currently");
}
std::vector<const ast::Predicate *> predicates;
// Get a list of all predicates
for (const auto &scopedFormula : scopedFormulas)
ast::collectPredicates(scopedFormula.formula, predicates);
@@ -171,24 +177,11 @@ void complete(std::vector<ast::ScopedFormula> &scopedFormulas)
return lhs->arity() < rhs->arity();
});
std::vector<ast::ScopedFormula> completedScopedFormulas;
std::vector<ast::Formula> completedFormulas;
// Complete predicates
for (const auto *predicate : predicates)
{
// Create the signature of the predicate
ast::Predicate signature(std::string(predicate->name));
signature.arguments.reserve(predicate->arguments.size());
// TODO: reimplement
for (std::size_t i = 0; i < predicate->arguments.size(); i++)
{
auto variableName = std::string(AuxiliaryHeadVariablePrefix) + std::to_string(i + 1);
signature.arguments.emplace_back(ast::Term::make<ast::Variable>(std::move(variableName), ast::VariableDeclaration::Type::Reserved));
}
completePredicate(std::move(signature), scopedFormulas, completedScopedFormulas);
}
completedFormulas.emplace_back(completePredicate(*predicate, scopedFormulas));
// Complete integrity constraints
for (auto &scopedFormula : scopedFormulas)
@@ -204,10 +197,10 @@ void complete(std::vector<ast::ScopedFormula> &scopedFormulas)
if (boolean.value == true)
continue;
completeIntegrityConstraint(scopedFormula.formula, completedScopedFormulas);
completedFormulas.emplace_back(completeIntegrityConstraint(scopedFormula));
}
std::swap(scopedFormulas, completedScopedFormulas);*/
return completedFormulas;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -59,14 +59,24 @@ void translate(const char *fileName, std::istream &stream, Context &context)
for (auto &scopedFormula : scopedFormulas)
simplify(scopedFormula.formula);
if (context.complete)
complete(scopedFormulas);
ast::PrintContext printContext;
for (const auto &scopedFormula : scopedFormulas)
if (!context.complete)
{
ast::print(context.logger.outputStream(), scopedFormula.formula, printContext);
for (const auto &scopedFormula : scopedFormulas)
{
ast::print(context.logger.outputStream(), scopedFormula.formula, printContext);
context.logger.outputStream() << std::endl;
}
return;
}
auto completedFormulas = complete(std::move(scopedFormulas));
for (const auto &completedFormula : completedFormulas)
{
ast::print(context.logger.outputStream(), completedFormula, printContext);
context.logger.outputStream() << std::endl;
}
}