From d6a811e363e1f3effbb2aa9a14be1d235fabac14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Sat, 21 Apr 2018 17:47:27 +0200 Subject: [PATCH] Move arithmetic check to separate header Checking whether terms are arithmetic will be used not just in integer variable detection but also in simplifying formulas with integer variables. For this purpose, the arithmetic check is moved to a commonly accessible header file. --- include/anthem/Arithmetics.h | 154 ++++++++++++++++++++++++ src/anthem/IntegerVariableDetection.cpp | 105 +--------------- 2 files changed, 159 insertions(+), 100 deletions(-) create mode 100644 include/anthem/Arithmetics.h diff --git a/include/anthem/Arithmetics.h b/include/anthem/Arithmetics.h new file mode 100644 index 0000000..e867e73 --- /dev/null +++ b/include/anthem/Arithmetics.h @@ -0,0 +1,154 @@ +#ifndef __ANTHEM__ARITHMETICS_H +#define __ANTHEM__ARITHMETICS_H + +#include + +namespace anthem +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Arithmetics +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct DefaultVariableDomainAccessor +{ + ast::Domain operator()(const ast::Variable &variable) + { + return variable.declaration->domain; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +EvaluationResult isArithmetic(const ast::Term &term, Arguments &&...); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +struct IsTermArithmeticVisitor +{ + template + static EvaluationResult visit(const ast::BinaryOperation &binaryOperation, Arguments &&... arguments) + { + const auto isLeftArithemtic = isArithmetic(binaryOperation.left, std::forward(arguments)...); + const auto isRightArithmetic = isArithmetic(binaryOperation.right, std::forward(arguments)...); + + if (isLeftArithemtic == EvaluationResult::Error || isRightArithmetic == EvaluationResult::Error) + return EvaluationResult::Error; + + if (isLeftArithemtic == EvaluationResult::False || isRightArithmetic == EvaluationResult::False) + return EvaluationResult::Error; + + if (isLeftArithemtic == EvaluationResult::Unknown || isRightArithmetic == EvaluationResult::Unknown) + return EvaluationResult::Unknown; + + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::Boolean &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::Function &function, Arguments &&...) + { + switch (function.declaration->domain) + { + case ast::Domain::General: + return EvaluationResult::False; + case ast::Domain::Integer: + return EvaluationResult::True; + case ast::Domain::Unknown: + return EvaluationResult::Unknown; + } + + return EvaluationResult::Unknown; + } + + template + static EvaluationResult visit(const ast::Integer &, Arguments &&...) + { + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::Interval &interval, Arguments &&... arguments) + { + const auto isFromArithmetic = isArithmetic(interval.from, std::forward(arguments)...); + const auto isToArithmetic = isArithmetic(interval.to, std::forward(arguments)...); + + if (isFromArithmetic == EvaluationResult::Error || isToArithmetic == EvaluationResult::Error) + return EvaluationResult::Error; + + if (isFromArithmetic == EvaluationResult::False || isToArithmetic == EvaluationResult::False) + return EvaluationResult::Error; + + if (isFromArithmetic == EvaluationResult::Unknown || isToArithmetic == EvaluationResult::Unknown) + return EvaluationResult::Unknown; + + return EvaluationResult::True; + } + + template + static EvaluationResult visit(const ast::SpecialInteger &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::String &, Arguments &&...) + { + return EvaluationResult::False; + } + + template + static EvaluationResult visit(const ast::UnaryOperation &unaryOperation, Arguments &&... arguments) + { + const auto isArgumentArithmetic = isArithmetic(unaryOperation.argument, std::forward(arguments)...); + + switch (unaryOperation.operator_) + { + case ast::UnaryOperation::Operator::Absolute: + return (isArgumentArithmetic == EvaluationResult::False ? EvaluationResult::Error : isArgumentArithmetic); + } + + return EvaluationResult::Unknown; + } + + template + static EvaluationResult visit(const ast::Variable &variable, Arguments &&... arguments) + { + const auto domain = VariableDomainAccessor()(variable, std::forward(arguments)...); + + switch (domain) + { + case ast::Domain::General: + return EvaluationResult::False; + case ast::Domain::Integer: + return EvaluationResult::True; + case ast::Domain::Unknown: + return EvaluationResult::Unknown; + } + + return EvaluationResult::Unknown; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +EvaluationResult isArithmetic(const ast::Term &term, Arguments &&... arguments) +{ + return term.accept(IsTermArithmeticVisitor(), std::forward(arguments)...); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} + +#endif diff --git a/src/anthem/IntegerVariableDetection.cpp b/src/anthem/IntegerVariableDetection.cpp index efc411c..af4aa4b 100644 --- a/src/anthem/IntegerVariableDetection.cpp +++ b/src/anthem/IntegerVariableDetection.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -44,107 +45,11 @@ void clearVariableDomainMap(VariableDomainMap &variableDomainMap) //////////////////////////////////////////////////////////////////////////////////////////////////// -EvaluationResult isArithmetic(const ast::Term &term, VariableDomainMap &variableDomainMap); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -struct IsTermArithmeticVisitor +struct VariableDomainMapAccessor { - static EvaluationResult visit(const ast::BinaryOperation &binaryOperation, VariableDomainMap &variableDomainMap) + ast::Domain operator()(const ast::Variable &variable, VariableDomainMap &variableDomainMap) { - const auto isLeftArithemtic = isArithmetic(binaryOperation.left, variableDomainMap); - const auto isRightArithmetic = isArithmetic(binaryOperation.right, variableDomainMap); - - if (isLeftArithemtic == EvaluationResult::Error || isRightArithmetic == EvaluationResult::Error) - return EvaluationResult::Error; - - if (isLeftArithemtic == EvaluationResult::False || isRightArithmetic == EvaluationResult::False) - return EvaluationResult::Error; - - if (isLeftArithemtic == EvaluationResult::Unknown || isRightArithmetic == EvaluationResult::Unknown) - return EvaluationResult::Unknown; - - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::Boolean &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::Function &function, VariableDomainMap &) - { - switch (function.declaration->domain) - { - case ast::Domain::General: - return EvaluationResult::False; - case ast::Domain::Integer: - return EvaluationResult::True; - case ast::Domain::Unknown: - return EvaluationResult::Unknown; - } - - return EvaluationResult::Unknown; - } - - static EvaluationResult visit(const ast::Integer &, VariableDomainMap &) - { - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::Interval &interval, VariableDomainMap &variableDomainMap) - { - const auto isFromArithmetic = isArithmetic(interval.from, variableDomainMap); - const auto isToArithmetic = isArithmetic(interval.to, variableDomainMap); - - if (isFromArithmetic == EvaluationResult::Error || isToArithmetic == EvaluationResult::Error) - return EvaluationResult::Error; - - if (isFromArithmetic == EvaluationResult::False || isToArithmetic == EvaluationResult::False) - return EvaluationResult::Error; - - if (isFromArithmetic == EvaluationResult::Unknown || isToArithmetic == EvaluationResult::Unknown) - return EvaluationResult::Unknown; - - return EvaluationResult::True; - } - - static EvaluationResult visit(const ast::SpecialInteger &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::String &, VariableDomainMap &) - { - return EvaluationResult::False; - } - - static EvaluationResult visit(const ast::UnaryOperation &unaryOperation, VariableDomainMap &variableDomainMap) - { - const auto isArgumentArithmetic = isArithmetic(unaryOperation.argument, variableDomainMap); - - switch (unaryOperation.operator_) - { - case ast::UnaryOperation::Operator::Absolute: - return (isArgumentArithmetic == EvaluationResult::False ? EvaluationResult::Error : isArgumentArithmetic); - } - - return EvaluationResult::Unknown; - } - - static EvaluationResult visit(const ast::Variable &variable, VariableDomainMap &variableDomainMap) - { - switch (domain(variable, variableDomainMap)) - { - case ast::Domain::General: - return EvaluationResult::False; - case ast::Domain::Integer: - return EvaluationResult::True; - case ast::Domain::Unknown: - return EvaluationResult::Unknown; - } - - return EvaluationResult::Unknown; + return domain(variable, variableDomainMap); } }; @@ -152,7 +57,7 @@ struct IsTermArithmeticVisitor EvaluationResult isArithmetic(const ast::Term &term, VariableDomainMap &variableDomainMap) { - return term.accept(IsTermArithmeticVisitor(), variableDomainMap); + return isArithmetic(term, variableDomainMap); } ////////////////////////////////////////////////////////////////////////////////////////////////////