5#ifndef OASIS_BOUNDEDBINARYEXPRESSION_HPP
6#define OASIS_BOUNDEDBINARYEXPRESSION_HPP
24template <
template <IExpression, IExpression, IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT, IExpression LowerBoundT = Expression, IExpression UpperBoundT = LowerBoundT>
27 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT, LowerBoundT, UpperBoundT>;
28 using DerivedGeneralized = DerivedT<Expression, Expression, Expression, Expression>;
56 DerivedSpecialized copy;
58 if (this->mostSigOp) {
59 subflow.emplace([
this, ©](tf::Subflow& sbf) {
60 copy.SetMostSigOp(mostSigOp->Copy(sbf), sbf);
64 if (this->leastSigOp) {
65 subflow.emplace([
this, ©](tf::Subflow& sbf) {
66 copy.SetLeastSigOp(leastSigOp->Copy(sbf), sbf);
76 return Generalize()->Differentiate(differentiationVariable);
80 if (this->
GetType() != other.GetType()) {
84 const auto otherGeneralized = other.Generalize();
85 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
87 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
89 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
90 if (mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
91 mostSigOpMismatch = !mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
94 mostSigOpMismatch =
true;
97 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
98 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
99 leastSigOpMismatch = !leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
102 mostSigOpMismatch =
true;
105 if (!mostSigOpMismatch && !leastSigOpMismatch) {
117 otherBinaryGeneralized.Flatten(otherFlattened);
119 for (
const auto& thisOperand : thisFlattened) {
120 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
121 return thisOperand->Equals(*otherOperand);
123 == otherFlattened.end()) {
133 DerivedGeneralized generalized;
135 if (this->mostSigOp) {
136 generalized.SetMostSigOp(*this->mostSigOp->Copy());
139 if (this->leastSigOp) {
140 generalized.SetLeastSigOp(*this->leastSigOp->Copy());
148 DerivedGeneralized generalized;
150 if (this->mostSigOp) {
151 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
152 generalized.SetMostSigOp(*this->mostSigOp->Copy(sbf));
156 if (this->leastSigOp) {
157 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
158 generalized.SetLeastSigOp(*this->leastSigOp->Copy(sbf));
171 tf::Task generalizeTask = subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
175 tf::Task simplifyTask = subflow.emplace([&generalized, &simplified](tf::Subflow& sbf) {
176 simplified = generalized->Simplify(sbf);
179 simplifyTask.succeed(generalizeTask);
187 if (this->
GetType() != other.GetType()) {
192 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
194 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
195 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
196 if (!mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
202 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
203 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
204 if (!leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
215 if (this->
GetType() != other.GetType()) {
221 tf::Task generalizeTask = subflow.emplace([&](tf::Subflow& sbf) {
222 otherGeneralized = other.Generalize(sbf);
225 bool mostSigOpEquivalent =
false, leastSigOpEquivalent =
false;
227 if (this->mostSigOp) {
228 tf::Task compMostSigOp = subflow.emplace([
this, &otherGeneralized, &mostSigOpEquivalent](tf::Subflow& sbf) {
229 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasMostSigOp()) {
230 mostSigOpEquivalent = mostSigOp->StructurallyEquivalent(otherBinary.GetMostSigOp(), sbf);
234 compMostSigOp.succeed(generalizeTask);
237 if (this->leastSigOp) {
238 tf::Task compLeastSigOp = subflow.emplace([
this, &otherGeneralized, &leastSigOpEquivalent](tf::Subflow& sbf) {
239 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasLeastSigOp()) {
240 leastSigOpEquivalent = leastSigOp->StructurallyEquivalent(otherBinary.GetLeastSigOp(), sbf);
244 compLeastSigOp.succeed(generalizeTask);
249 return mostSigOpEquivalent && leastSigOpEquivalent;
265 if (this->mostSigOp->template Is<DerivedT>()) {
266 auto generalizedMostSigOp = this->mostSigOp->Generalize();
267 const auto& mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
268 mostSigOp.Flatten(out);
270 out.push_back(this->mostSigOp->Copy());
273 if (this->leastSigOp->template Is<DerivedT>()) {
274 auto generalizedLeastSigOp = this->leastSigOp->Generalize();
275 const auto& leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
276 leastSigOp.Flatten(out);
278 out.push_back(this->leastSigOp->Copy());
288 assert(mostSigOp !=
nullptr);
298 assert(leastSigOp !=
nullptr);
308 return mostSigOp !=
nullptr;
317 return leastSigOp !=
nullptr;
324 template <
typename T>
329 this->mostSigOp = op.Copy();
338 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
339 mostSigOp = std::move(castedOp);
350 template <
typename T>
355 this->leastSigOp = op.Copy();
364 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
365 leastSigOp = std::move(castedOp);
376 DerivedGeneralized comb { *left, *right };
387 return DerivedT { *this->leastSigOp, *this->mostSigOp };
392 void Serialize(SerializationVisitor& visitor)
const override
395 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
396 visitor.Serialize(derivedGeneralized);
A concept for an operand of a binary expression with bounds.
Definition BoundedBinaryExpression.hpp:25
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BoundedBinaryExpression.hpp:74
auto SwapOperands() const -> DerivedSpecialized
Swaps the operands of this expression.
Definition BoundedBinaryExpression.hpp:385
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:286
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BoundedBinaryExpression.hpp:263
auto Simplify(tf::Subflow &subflow) const -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:167
BoundedBinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BoundedBinaryExpression.hpp:43
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:372
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BoundedBinaryExpression.hpp:78
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:326
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BoundedBinaryExpression.hpp:131
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BoundedBinaryExpression.hpp:306
void Serialize(SerializationVisitor &visitor) const override
Definition BoundedBinaryExpression.hpp:392
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:296
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BoundedBinaryExpression.hpp:315
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:352
auto Generalize(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:146
auto Copy(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:54
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BoundedBinaryExpression.hpp:49
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BoundedBinaryExpression.hpp:185
auto operator=(const BoundedBinaryExpression &other) -> BoundedBinaryExpression &=default
auto StructurallyEquivalent(const Expression &other, tf::Subflow &subflow) const -> bool final
Definition BoundedBinaryExpression.hpp:213
BoundedBinaryExpression()=default
BoundedBinaryExpression(const BoundedBinaryExpression &other)
Definition BoundedBinaryExpression.hpp:32
A concept base class for both Unary and BoundedBinary expressions.
Definition BoundedExpression.hpp:23
An expression.
Definition Expression.hpp:63
virtual auto GetCategory() const -> uint32_t
Gets the category of this expression.
Definition Expression.cpp:219
virtual auto GetType() const -> ExpressionType
Gets the type of this expression.
Definition Expression.cpp:229
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:53
@ Associative
Definition Expression.hpp:50