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.
This commit is contained in:
154
include/anthem/Arithmetics.h
Normal file
154
include/anthem/Arithmetics.h
Normal file
@@ -0,0 +1,154 @@
|
||||
#ifndef __ANTHEM__ARITHMETICS_H
|
||||
#define __ANTHEM__ARITHMETICS_H
|
||||
|
||||
#include <anthem/Utils.h>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Arithmetics
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DefaultVariableDomainAccessor
|
||||
{
|
||||
ast::Domain operator()(const ast::Variable &variable)
|
||||
{
|
||||
return variable.declaration->domain;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class VariableDomainAccessor = DefaultVariableDomainAccessor, class... Arguments>
|
||||
EvaluationResult isArithmetic(const ast::Term &term, Arguments &&...);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class VariableDomainAccessor = DefaultVariableDomainAccessor>
|
||||
struct IsTermArithmeticVisitor
|
||||
{
|
||||
template <class... Arguments>
|
||||
static EvaluationResult visit(const ast::BinaryOperation &binaryOperation, Arguments &&... arguments)
|
||||
{
|
||||
const auto isLeftArithemtic = isArithmetic<VariableDomainAccessor>(binaryOperation.left, std::forward<Arguments>(arguments)...);
|
||||
const auto isRightArithmetic = isArithmetic<VariableDomainAccessor>(binaryOperation.right, std::forward<Arguments>(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 <class... Arguments>
|
||||
static EvaluationResult visit(const ast::Boolean &, Arguments &&...)
|
||||
{
|
||||
return EvaluationResult::False;
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
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 <class... Arguments>
|
||||
static EvaluationResult visit(const ast::Integer &, Arguments &&...)
|
||||
{
|
||||
return EvaluationResult::True;
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
static EvaluationResult visit(const ast::Interval &interval, Arguments &&... arguments)
|
||||
{
|
||||
const auto isFromArithmetic = isArithmetic<VariableDomainAccessor>(interval.from, std::forward<Arguments>(arguments)...);
|
||||
const auto isToArithmetic = isArithmetic<VariableDomainAccessor>(interval.to, std::forward<Arguments>(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 <class... Arguments>
|
||||
static EvaluationResult visit(const ast::SpecialInteger &, Arguments &&...)
|
||||
{
|
||||
return EvaluationResult::False;
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
static EvaluationResult visit(const ast::String &, Arguments &&...)
|
||||
{
|
||||
return EvaluationResult::False;
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
static EvaluationResult visit(const ast::UnaryOperation &unaryOperation, Arguments &&... arguments)
|
||||
{
|
||||
const auto isArgumentArithmetic = isArithmetic<VariableDomainAccessor>(unaryOperation.argument, std::forward<Arguments>(arguments)...);
|
||||
|
||||
switch (unaryOperation.operator_)
|
||||
{
|
||||
case ast::UnaryOperation::Operator::Absolute:
|
||||
return (isArgumentArithmetic == EvaluationResult::False ? EvaluationResult::Error : isArgumentArithmetic);
|
||||
}
|
||||
|
||||
return EvaluationResult::Unknown;
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
static EvaluationResult visit(const ast::Variable &variable, Arguments &&... arguments)
|
||||
{
|
||||
const auto domain = VariableDomainAccessor()(variable, std::forward<Arguments>(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 <class VariableDomainAccessor, class... Arguments>
|
||||
EvaluationResult isArithmetic(const ast::Term &term, Arguments &&... arguments)
|
||||
{
|
||||
return term.accept(IsTermArithmeticVisitor<VariableDomainAccessor>(), std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user