Refactored formula simplification with Clingo’s variants.

This commit is contained in:
2017-03-23 00:44:10 +01:00
parent bf8cf75369
commit 825cd4de39
12 changed files with 296 additions and 261 deletions

View File

@@ -253,13 +253,13 @@ struct Biconditional
struct Exists
{
Exists(std::vector<VariablePointer> &&variables, Formula &&argument)
Exists(std::vector<Variable> &&variables, Formula &&argument)
: variables{std::move(variables)},
argument{std::move(argument)}
{
}
std::vector<VariablePointer> variables;
std::vector<Variable> variables;
Formula argument;
};
@@ -267,13 +267,13 @@ struct Exists
struct ForAll
{
ForAll(std::vector<VariablePointer> &&variables, Formula &&argument)
ForAll(std::vector<Variable> &&variables, Formula &&argument)
: variables{std::move(variables)},
argument{std::move(argument)}
{
}
std::vector<VariablePointer> variables;
std::vector<Variable> variables;
Formula argument;
};
@@ -332,7 +332,7 @@ Predicate deepCopy(const Predicate &other);
SpecialInteger deepCopy(const SpecialInteger &other);
String deepCopy(const String &other);
Variable deepCopy(const Variable &other);
std::vector<VariablePointer> deepCopy(const std::vector<VariablePointer> &other);
std::vector<Variable> deepCopy(const std::vector<Variable> &other);
And deepCopy(const And &other);
Biconditional deepCopy(const Biconditional &other);
Exists deepCopy(const Exists &other);
@@ -347,7 +347,7 @@ Term deepCopy(const Term &term);
std::vector<Term> deepCopy(const std::vector<Term> &terms);
////////////////////////////////////////////////////////////////////////////////////////////////////
/*
const auto deepCopyUniquePtr =
[](const auto &uniquePtr) -> typename std::decay<decltype(uniquePtr)>::type
{
@@ -370,13 +370,27 @@ const auto deepCopyUniquePtrVector =
return result;
};
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Variant>
struct VariantDeepCopyVisitor
{
template<class T>
Variant visit(const T &x)
{
return deepCopy(x);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto deepCopyVariant =
[](const auto &variant) -> typename std::decay<decltype(variant)>::type
{
return variant.match([](const auto &x) -> typename std::decay<decltype(variant)>::type {return deepCopyUniquePtr(x);});
using VariantType = typename std::decay<decltype(variant)>::type;
return variant.accept(VariantDeepCopyVisitor<VariantType>());
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -397,6 +411,22 @@ const auto deepCopyVariantVector =
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto deepCopyVector =
[](const auto &vector) -> typename std::decay<decltype(vector)>::type
{
using Type = typename std::decay<decltype(vector)>::type::value_type;
std::vector<Type> result;
result.reserve(vector.size());
for (const auto &element : vector)
result.emplace_back(deepCopy(element));
return result;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline BinaryOperation deepCopy(const BinaryOperation &other)
{
return BinaryOperation(other.operator_, deepCopy(other.left), deepCopy(other.right));
@@ -474,9 +504,9 @@ inline Variable deepCopy(const Variable &other)
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::vector<VariablePointer> deepCopy(const std::vector<VariablePointer> &other)
inline std::vector<Variable> deepCopy(const std::vector<Variable> &other)
{
return deepCopyUniquePtrVector(other);
return deepCopyVector(other);
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -3,9 +3,10 @@
#include <memory>
#include <experimental/optional>
#include <mapbox/variant.hpp>
#include <vector>
#include <clingo.hh>
namespace anthem
{
@@ -64,34 +65,34 @@ using VariablePointer = std::unique_ptr<Variable>;
// Variants
////////////////////////////////////////////////////////////////////////////////////////////////////
using FormulaT = mapbox::util::variant<
AndPointer,
BiconditionalPointer,
BooleanPointer,
ComparisonPointer,
ExistsPointer,
ForAllPointer,
ImpliesPointer,
InPointer,
NotPointer,
OrPointer,
PredicatePointer>;
using FormulaT = Clingo::Variant<
And,
Biconditional,
Boolean,
Comparison,
Exists,
ForAll,
Implies,
In,
Not,
Or,
Predicate>;
class Formula : public FormulaT
{
using FormulaT::FormulaT;
};
using TermT = mapbox::util::variant<
BinaryOperationPointer,
BooleanPointer,
ConstantPointer,
FunctionPointer,
IntegerPointer,
IntervalPointer,
SpecialIntegerPointer,
StringPointer,
VariablePointer>;
using TermT = Clingo::Variant<
BinaryOperation,
Boolean,
Constant,
Function,
Integer,
Interval,
SpecialInteger,
String,
Variable>;
class Term : public TermT
{

View File

@@ -40,11 +40,11 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::VariablePointer makeAuxiliaryBodyVariable(const int i)
ast::Variable makeAuxiliaryBodyVariable(const int i)
{
auto variableName = std::string(AuxiliaryBodyVariablePrefix) + std::to_string(i);
return std::make_unique<ast::Variable>(std::move(variableName), ast::Variable::Type::Reserved);
return ast::Variable(std::move(variableName), ast::Variable::Type::Reserved);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -88,36 +88,36 @@ struct BodyTermTranslateVisitor
throwErrorAtLocation(literal.location, "double-negated literals currently unsupported", context);
if (function.arguments.empty())
return std::make_unique<ast::Predicate>(std::string(function.name));
return ast::Formula::make<ast::Predicate>(std::string(function.name));
std::vector<ast::VariablePointer> variables;
std::vector<ast::Variable> variables;
variables.reserve(function.arguments.size());
for (size_t i = 0; i < function.arguments.size(); i++)
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + i));
auto conjunction = std::make_unique<ast::And>();
ast::And conjunction;
for (size_t i = 0; i < function.arguments.size(); i++)
{
const auto &argument = function.arguments[i];
conjunction->arguments.emplace_back(std::make_unique<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + i), translate(argument, context)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + i), translate(argument, context)));
}
auto predicate = std::make_unique<ast::Predicate>(std::string(function.name));
predicate->arguments.reserve(function.arguments.size());
ast::Predicate predicate(std::string(function.name));
predicate.arguments.reserve(function.arguments.size());
for (size_t i = 0; i < function.arguments.size(); i++)
predicate->arguments.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + i));
predicate.arguments.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + i));
if (literal.sign == Clingo::AST::Sign::None)
conjunction->arguments.emplace_back(std::move(predicate));
conjunction.arguments.emplace_back(std::move(predicate));
else
conjunction->arguments.emplace_back(std::make_unique<ast::Not>(std::move(predicate)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::Not>(std::move(predicate)));
context.auxiliaryBodyLiteralID += function.arguments.size();
return std::make_unique<ast::Exists>(std::move(variables), std::move(conjunction));
return ast::Formula::make<ast::Exists>(std::move(variables), std::move(conjunction));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Pool &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context)
@@ -150,20 +150,20 @@ struct BodyLiteralTranslateVisitor
const auto operator_ = translate(comparison.comparison);
std::vector<ast::VariablePointer> variables;
std::vector<ast::Variable> variables;
variables.reserve(2);
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID));
variables.emplace_back(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + 1));
auto conjunction = std::make_unique<ast::And>();
conjunction->arguments.reserve(3);
conjunction->arguments.emplace_back(std::make_unique<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID), translate(comparison.left, context)));
conjunction->arguments.emplace_back(std::make_unique<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + 1), translate(comparison.right, context)));
conjunction->arguments.emplace_back(std::make_unique<ast::Comparison>(operator_, makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID), makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + 1)));
ast::And conjunction;
conjunction.arguments.reserve(3);
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID), translate(comparison.left, context)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + 1), translate(comparison.right, context)));
conjunction.arguments.emplace_back(ast::Formula::make<ast::Comparison>(operator_, makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID), makeAuxiliaryBodyVariable(context.auxiliaryBodyLiteralID + 1)));
context.auxiliaryBodyLiteralID += 2;
return std::make_unique<ast::Exists>(std::move(variables), std::move(conjunction));
return ast::Formula::make<ast::Exists>(std::move(variables), std::move(conjunction));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::CSPLiteral &, const Clingo::AST::Literal &literal, Context &context)

View File

@@ -188,10 +188,10 @@ struct FunctionTermTranslateVisitor
assert(matchingTerm != context.headTerms.cend());
auto variableName = std::string(AuxiliaryHeadVariablePrefix) + std::to_string(matchingTerm - context.headTerms.cbegin() + 1);
arguments.emplace_back(std::make_unique<ast::Variable>(std::move(variableName), ast::Variable::Type::Reserved));
arguments.emplace_back(ast::Variable(std::move(variableName), ast::Variable::Type::Reserved));
}
return std::make_unique<ast::Predicate>(function.name, std::move(arguments));
return ast::Formula::make<ast::Predicate>(function.name, std::move(arguments));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context)
@@ -207,7 +207,7 @@ struct LiteralTranslateVisitor
{
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &)
{
return std::make_unique<ast::Boolean>(boolean.value);
return ast::Formula::make<ast::Boolean>(boolean.value);
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context)
@@ -245,7 +245,7 @@ struct HeadLiteralTranslateToConsequentVisitor
if (!translatedLiteral)
return std::experimental::nullopt;
return std::make_unique<ast::Not>(std::move(translatedLiteral.value()));
return ast::Formula::make<ast::Not>(std::move(translatedLiteral.value()));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
@@ -266,7 +266,7 @@ struct HeadLiteralTranslateToConsequentVisitor
arguments.emplace_back(std::move(argument.value()));
}
return std::make_unique<ast::Or>(std::move(arguments));
return ast::Formula::make<ast::Or>(std::move(arguments));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
@@ -299,7 +299,7 @@ struct HeadLiteralTranslateToConsequentVisitor
arguments.emplace_back(std::move(argument.value()));
}
return std::make_unique<ast::Or>(std::move(arguments));
return ast::Formula::make<ast::Or>(std::move(arguments));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::HeadAggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context)

View File

@@ -12,7 +12,7 @@ namespace anthem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Formula simplify(ast::Formula &&formula);
void simplify(ast::Formula &formula);
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -36,7 +36,7 @@ struct StatementVisitor
// Concatenate all head terms
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context);
auto antecedent = std::make_unique<ast::And>();
ast::And antecedent;
// Compute consequent
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, context);
@@ -53,11 +53,11 @@ struct StatementVisitor
const auto &headTerm = **i;
auto variableName = std::string(AuxiliaryHeadVariablePrefix) + std::to_string(i - context.headTerms.cbegin() + 1);
auto element = std::make_unique<ast::Variable>(std::move(variableName), ast::Variable::Type::Reserved);
auto element = ast::Variable(std::move(variableName), ast::Variable::Type::Reserved);
auto set = translate(headTerm, context);
auto in = std::make_unique<ast::In>(std::move(element), std::move(set));
auto in = ast::In(std::move(element), std::move(set));
antecedent->arguments.emplace_back(std::move(in));
antecedent.arguments.emplace_back(std::move(in));
}
// Print translated body literals
@@ -73,20 +73,20 @@ struct StatementVisitor
if (!argument)
throwErrorAtLocation(bodyLiteral.location, "could not translate body literal", context);
antecedent->arguments.emplace_back(std::move(argument.value()));
antecedent.arguments.emplace_back(std::move(argument.value()));
}
// Handle choice rules
if (context.isChoiceRule)
antecedent->arguments.emplace_back(ast::deepCopy(consequent.value()));
antecedent.arguments.emplace_back(ast::deepCopy(consequent.value()));
// Use “true” as the consequent in case it is empty
if (antecedent->arguments.empty())
return std::make_unique<ast::Implies>(std::make_unique<ast::Boolean>(true), std::move(consequent.value()));
else if (antecedent->arguments.size() == 1)
return std::make_unique<ast::Implies>(std::move(antecedent->arguments[0]), std::move(consequent.value()));
if (antecedent.arguments.empty())
return ast::Formula::make<ast::Implies>(ast::Boolean(true), std::move(consequent.value()));
else if (antecedent.arguments.size() == 1)
return ast::Formula::make<ast::Implies>(std::move(antecedent.arguments[0]), std::move(consequent.value()));
return std::make_unique<ast::Implies>(std::move(antecedent), std::move(consequent.value()));
return ast::Formula::make<ast::Implies>(std::move(antecedent), std::move(consequent.value()));
}
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Definition &, const Clingo::AST::Statement &statement, Context &context)

View File

@@ -50,17 +50,19 @@ struct TermTranslateVisitor
switch (symbol.type())
{
case Clingo::SymbolType::Number:
return std::make_unique<ast::Integer>(symbol.number());
return ast::Term::make<ast::Integer>(symbol.number());
case Clingo::SymbolType::Infimum:
return std::make_unique<ast::SpecialInteger>(ast::SpecialInteger::Type::Infimum);
return ast::Term::make<ast::SpecialInteger>(ast::SpecialInteger::Type::Infimum);
case Clingo::SymbolType::Supremum:
return std::make_unique<ast::SpecialInteger>(ast::SpecialInteger::Type::Supremum);
return ast::Term::make<ast::SpecialInteger>(ast::SpecialInteger::Type::Supremum);
case Clingo::SymbolType::String:
return std::make_unique<ast::String>(std::string(symbol.string()));
return ast::Term::make<ast::String>(std::string(symbol.string()));
case Clingo::SymbolType::Function:
{
auto function = std::make_unique<ast::Function>(symbol.name());
function->arguments.reserve(symbol.arguments().size());
auto function = ast::Term::make<ast::Function>(symbol.name());
// TODO: remove workaround
auto &functionRaw = function.get<ast::Function>();
functionRaw.arguments.reserve(symbol.arguments().size());
for (const auto &argument : symbol.arguments())
{
@@ -69,7 +71,7 @@ struct TermTranslateVisitor
if (!translatedArgument)
throwErrorAtLocation(term.location, "could not translate argument", context);
function->arguments.emplace_back(std::move(translatedArgument.value()));
functionRaw.arguments.emplace_back(std::move(translatedArgument.value()));
}
return std::move(function);
@@ -83,7 +85,7 @@ struct TermTranslateVisitor
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &)
{
return std::make_unique<ast::Variable>(std::string(variable.name), ast::Variable::Type::UserDefined);
return ast::Term::make<ast::Variable>(std::string(variable.name), ast::Variable::Type::UserDefined);
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, Context &context)
@@ -98,7 +100,7 @@ struct TermTranslateVisitor
auto left = translate(binaryOperation.left, context);
auto right = translate(binaryOperation.right, context);
return std::make_unique<ast::BinaryOperation>(operator_, std::move(left), std::move(right));
return ast::Term::make<ast::BinaryOperation>(operator_, std::move(left), std::move(right));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, Context &context)
@@ -106,7 +108,7 @@ struct TermTranslateVisitor
auto left = translate(interval.left, context);
auto right = translate(interval.right, context);
return std::make_unique<ast::Interval>(std::move(left), std::move(right));
return ast::Term::make<ast::Interval>(std::move(left), std::move(right));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context)
@@ -120,7 +122,7 @@ struct TermTranslateVisitor
for (const auto &argument : function.arguments)
arguments.emplace_back(translate(argument, context));
return std::make_unique<ast::Function>(function.name, std::move(arguments));
return ast::Term::make<ast::Function>(function.name, std::move(arguments));
}
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context)

View File

@@ -48,7 +48,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Term &term);
// Primitives
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperation::Operator operator_)
inline output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperation::Operator operator_)
{
switch (operator_)
{
@@ -69,14 +69,14 @@ output::ColorStream &operator<<(output::ColorStream &stream, BinaryOperation::Op
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const BinaryOperation &binaryOperation)
inline output::ColorStream &operator<<(output::ColorStream &stream, const BinaryOperation &binaryOperation)
{
return (stream << "(" << binaryOperation.left << " " << binaryOperation.operator_ << " " << binaryOperation.right << ")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Boolean &boolean)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Boolean &boolean)
{
if (boolean.value)
return (stream << output::Boolean("#true"));
@@ -86,7 +86,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Boolean &bool
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, Comparison::Operator operator_)
inline output::ColorStream &operator<<(output::ColorStream &stream, Comparison::Operator operator_)
{
switch (operator_)
{
@@ -109,21 +109,21 @@ output::ColorStream &operator<<(output::ColorStream &stream, Comparison::Operato
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Comparison &comparison)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Comparison &comparison)
{
return (stream << comparison.left << " " << comparison.operator_ << " " << comparison.right);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Constant &constant)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Constant &constant)
{
return (stream << constant.name);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Function &function)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Function &function)
{
stream << function.name;
@@ -148,28 +148,28 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Function &fun
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const In &in)
inline output::ColorStream &operator<<(output::ColorStream &stream, const In &in)
{
return (stream << in.element << " " << output::Keyword("in") << " " << in.set);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Integer &integer)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Integer &integer)
{
return (stream << output::Number<int>(integer.value));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Interval &interval)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Interval &interval)
{
return (stream << interval.from << ".." << interval.to);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Predicate &predicate)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Predicate &predicate)
{
stream << predicate.name;
@@ -191,7 +191,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Predicate &pr
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const SpecialInteger &specialInteger)
inline output::ColorStream &operator<<(output::ColorStream &stream, const SpecialInteger &specialInteger)
{
switch (specialInteger.type)
{
@@ -206,14 +206,14 @@ output::ColorStream &operator<<(output::ColorStream &stream, const SpecialIntege
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const String &string)
inline output::ColorStream &operator<<(output::ColorStream &stream, const String &string)
{
return (stream << output::String(string.text.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Variable &variable)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Variable &variable)
{
assert(!variable.name.empty());
assert(variable.name[0] >= 65 && variable.name[0] <= 90);
@@ -230,7 +230,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Variable &var
// Expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const And &and_)
inline output::ColorStream &operator<<(output::ColorStream &stream, const And &and_)
{
stream << "(";
@@ -247,14 +247,14 @@ output::ColorStream &operator<<(output::ColorStream &stream, const And &and_)
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Biconditional &biconditional)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Biconditional &biconditional)
{
return (stream << "(" << biconditional.left << " <-> " << biconditional.right << ")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exists)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exists)
{
stream << output::Keyword("exists") << " ";
@@ -263,7 +263,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exist
if (i != exists.variables.cbegin())
stream << ", ";
stream << (**i);
stream << (*i);
}
return (stream << " " << exists.argument);
@@ -271,7 +271,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Exists &exist
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAll)
inline output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAll)
{
stream << output::Keyword("forall") << " ";
@@ -280,7 +280,7 @@ output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAl
if (i != forAll.variables.cbegin())
stream << ", ";
stream << (**i);
stream << (*i);
}
return (stream << " " << forAll.argument);
@@ -288,21 +288,21 @@ output::ColorStream &operator<<(output::ColorStream &stream, const ForAll &forAl
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Implies &implies)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Implies &implies)
{
return (stream << "(" << implies.antecedent << " -> " << implies.consequent << ")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Not &not_)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Not &not_)
{
return (stream << output::Keyword("not ") << not_.argument);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Or &or_)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Or &or_)
{
stream << "(";
@@ -321,20 +321,28 @@ output::ColorStream &operator<<(output::ColorStream &stream, const Or &or_)
// Variants
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Formula &formula)
template<class Variant>
struct VariantPrintVisitor
{
formula.match([&](const auto &x){stream << *x;});
template<class T>
output::ColorStream &visit(const T &x, output::ColorStream &stream)
{
return (stream << x);
}
};
return stream;
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const Formula &formula)
{
return formula.accept(VariantPrintVisitor<ast::Formula>(), stream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
output::ColorStream &operator<<(output::ColorStream &stream, const Term &term)
inline output::ColorStream &operator<<(output::ColorStream &stream, const Term &term)
{
term.match([&](const auto &x){stream << *x;});
return stream;
return term.accept(VariantPrintVisitor<ast::Term>(), stream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////