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));
176 tf::Task generalizeTask = subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
180 tf::Task simplifyTask = subflow.emplace([&generalized, &simplified](tf::Subflow& sbf) {
181 simplified = generalized->Simplify(sbf);
184 simplifyTask.succeed(generalizeTask);
192 if (this->
GetType() != other.GetType()) {
197 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
199 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
200 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
201 if (!mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
207 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
208 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
209 if (!leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
220 if (this->
GetType() != other.GetType()) {
226 tf::Task generalizeTask = subflow.emplace([&](tf::Subflow& sbf) {
227 otherGeneralized = other.Generalize(sbf);
230 bool mostSigOpEquivalent =
false, leastSigOpEquivalent =
false;
232 if (this->mostSigOp) {
233 tf::Task compMostSigOp = subflow.emplace([
this, &otherGeneralized, &mostSigOpEquivalent](tf::Subflow& sbf) {
234 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasMostSigOp()) {
235 mostSigOpEquivalent = mostSigOp->StructurallyEquivalent(otherBinary.GetMostSigOp(), sbf);
239 compMostSigOp.succeed(generalizeTask);
242 if (this->leastSigOp) {
243 tf::Task compLeastSigOp = subflow.emplace([
this, &otherGeneralized, &leastSigOpEquivalent](tf::Subflow& sbf) {
244 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasLeastSigOp()) {
245 leastSigOpEquivalent = leastSigOp->StructurallyEquivalent(otherBinary.GetLeastSigOp(), sbf);
249 compLeastSigOp.succeed(generalizeTask);
254 return mostSigOpEquivalent && leastSigOpEquivalent;
270 if (this->mostSigOp->template Is<DerivedT>()) {
271 auto generalizedMostSigOp = this->mostSigOp->Generalize();
272 const auto& mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
273 mostSigOp.Flatten(out);
275 out.push_back(this->mostSigOp->Copy());
278 if (this->leastSigOp->template Is<DerivedT>()) {
279 auto generalizedLeastSigOp = this->leastSigOp->Generalize();
280 const auto& leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
281 leastSigOp.Flatten(out);
283 out.push_back(this->leastSigOp->Copy());
293 assert(mostSigOp !=
nullptr);
303 assert(leastSigOp !=
nullptr);
313 return mostSigOp !=
nullptr;
322 return leastSigOp !=
nullptr;
329 template <
typename T>
334 this->mostSigOp = op.Copy();
343 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
344 mostSigOp = std::move(castedOp);
355 template <
typename T>
360 this->leastSigOp = op.Copy();
369 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
370 leastSigOp = std::move(castedOp);
381 DerivedGeneralized comb { *left, *right };
382 auto ret = comb.Simplify();
391 return DerivedT { *this->leastSigOp, *this->mostSigOp };
396 void Serialize(SerializationVisitor& visitor)
const override
399 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
400 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:389
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:291
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BoundedBinaryExpression.hpp:268
auto Simplify(tf::Subflow &subflow) const -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:172
BoundedBinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BoundedBinaryExpression.hpp:43
auto Simplify() const -> std::unique_ptr< Expression > override
Simplifies this expression.
Definition BoundedBinaryExpression.hpp:167
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:377
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:331
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:311
void Serialize(SerializationVisitor &visitor) const override
Definition BoundedBinaryExpression.hpp:396
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:301
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BoundedBinaryExpression.hpp:320
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:357
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:190
auto operator=(const BoundedBinaryExpression &other) -> BoundedBinaryExpression &=default
auto StructurallyEquivalent(const Expression &other, tf::Subflow &subflow) const -> bool final
Definition BoundedBinaryExpression.hpp:218
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:62
virtual auto GetCategory() const -> uint32_t
Gets the category of this expression.
Definition Expression.cpp:212
virtual auto GetType() const -> ExpressionType
Gets the type of this expression.
Definition Expression.cpp:220
virtual auto Simplify() const -> std::unique_ptr< Expression >
Simplifies this expression.
Definition Expression.cpp:244
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:51
@ Associative
Definition Expression.hpp:49