5#ifndef OASIS_BOUNDEDBINARYEXPRESSION_HPP
6#define OASIS_BOUNDEDBINARYEXPRESSION_HPP
14template <
template <IExpression, IExpression, IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT, IExpression LowerBoundT = Expression, IExpression UpperBoundT = LowerBoundT>
17 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT, LowerBoundT, UpperBoundT>;
18 using DerivedGeneralized = DerivedT<Expression, Expression, Expression, Expression>;
46 DerivedSpecialized copy;
48 if (this->mostSigOp) {
49 subflow.emplace([
this, ©](tf::Subflow& sbf) {
50 copy.SetMostSigOp(mostSigOp->Copy(sbf), sbf);
54 if (this->leastSigOp) {
55 subflow.emplace([
this, ©](tf::Subflow& sbf) {
56 copy.SetLeastSigOp(leastSigOp->Copy(sbf), sbf);
66 return Generalize()->Differentiate(differentiationVariable);
70 if (this->
GetType() != other.GetType()) {
74 const auto otherGeneralized = other.Generalize();
75 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
77 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
79 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
80 if (mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
81 mostSigOpMismatch = !mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
84 mostSigOpMismatch =
true;
87 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
88 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
89 leastSigOpMismatch = !leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
92 mostSigOpMismatch =
true;
95 if (!mostSigOpMismatch && !leastSigOpMismatch) {
107 otherBinaryGeneralized.Flatten(otherFlattened);
109 for (
const auto& thisOperand : thisFlattened) {
110 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
111 return thisOperand->Equals(*otherOperand);
113 == otherFlattened.end()) {
123 DerivedGeneralized generalized;
125 if (this->mostSigOp) {
126 generalized.SetMostSigOp(*this->mostSigOp->Copy());
129 if (this->leastSigOp) {
130 generalized.SetLeastSigOp(*this->leastSigOp->Copy());
138 DerivedGeneralized generalized;
140 if (this->mostSigOp) {
141 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
142 generalized.SetMostSigOp(*this->mostSigOp->Copy(sbf));
146 if (this->leastSigOp) {
147 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
148 generalized.SetLeastSigOp(*this->leastSigOp->Copy(sbf));
166 tf::Task generalizeTask = subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
170 tf::Task simplifyTask = subflow.emplace([&generalized, &simplified](tf::Subflow& sbf) {
171 simplified = generalized->Simplify(sbf);
174 simplifyTask.succeed(generalizeTask);
182 if (this->
GetType() != other.GetType()) {
187 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
189 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
190 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
191 if (!mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
197 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
198 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
199 if (!leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
210 if (this->
GetType() != other.GetType()) {
216 tf::Task generalizeTask = subflow.emplace([&](tf::Subflow& sbf) {
217 otherGeneralized = other.Generalize(sbf);
220 bool mostSigOpEquivalent =
false, leastSigOpEquivalent =
false;
222 if (this->mostSigOp) {
223 tf::Task compMostSigOp = subflow.emplace([
this, &otherGeneralized, &mostSigOpEquivalent](tf::Subflow& sbf) {
224 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasMostSigOp()) {
225 mostSigOpEquivalent = mostSigOp->StructurallyEquivalent(otherBinary.GetMostSigOp(), sbf);
229 compMostSigOp.succeed(generalizeTask);
232 if (this->leastSigOp) {
233 tf::Task compLeastSigOp = subflow.emplace([
this, &otherGeneralized, &leastSigOpEquivalent](tf::Subflow& sbf) {
234 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasLeastSigOp()) {
235 leastSigOpEquivalent = leastSigOp->StructurallyEquivalent(otherBinary.GetLeastSigOp(), sbf);
239 compLeastSigOp.succeed(generalizeTask);
244 return mostSigOpEquivalent && leastSigOpEquivalent;
260 if (this->mostSigOp->template Is<DerivedT>()) {
261 auto generalizedMostSigOp = this->mostSigOp->Generalize();
262 const auto& mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
263 mostSigOp.Flatten(out);
265 out.push_back(this->mostSigOp->Copy());
268 if (this->leastSigOp->template Is<DerivedT>()) {
269 auto generalizedLeastSigOp = this->leastSigOp->Generalize();
270 const auto& leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
271 leastSigOp.Flatten(out);
273 out.push_back(this->leastSigOp->Copy());
283 assert(mostSigOp !=
nullptr);
293 assert(leastSigOp !=
nullptr);
303 return mostSigOp !=
nullptr;
312 return leastSigOp !=
nullptr;
319 template <
typename T>
324 this->mostSigOp = op.Copy();
333 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
334 mostSigOp = std::move(castedOp);
345 template <
typename T>
350 this->leastSigOp = op.Copy();
359 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
360 leastSigOp = std::move(castedOp);
371 DerivedGeneralized comb { *left, *right };
372 auto ret = comb.Simplify();
381 return DerivedT { *this->leastSigOp, *this->mostSigOp };
389 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
Definition BoundedBinaryExpression.hpp:15
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BoundedBinaryExpression.hpp:64
auto SwapOperands() const -> DerivedSpecialized
Swaps the operands of this expression.
Definition BoundedBinaryExpression.hpp:379
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:281
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BoundedBinaryExpression.hpp:258
auto Simplify(tf::Subflow &subflow) const -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:162
BoundedBinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BoundedBinaryExpression.hpp:33
auto Simplify() const -> std::unique_ptr< Expression > override
Simplifies this expression.
Definition BoundedBinaryExpression.hpp:157
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:367
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BoundedBinaryExpression.hpp:68
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:321
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BoundedBinaryExpression.hpp:121
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BoundedBinaryExpression.hpp:301
void Serialize(SerializationVisitor &visitor) const override
This function serializes the expression object.
Definition BoundedBinaryExpression.hpp:386
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:291
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BoundedBinaryExpression.hpp:310
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:347
auto Generalize(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:136
auto Copy(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:44
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BoundedBinaryExpression.hpp:39
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BoundedBinaryExpression.hpp:180
auto operator=(const BoundedBinaryExpression &other) -> BoundedBinaryExpression &=default
auto StructurallyEquivalent(const Expression &other, tf::Subflow &subflow) const -> bool final
Definition BoundedBinaryExpression.hpp:208
BoundedBinaryExpression()=default
BoundedBinaryExpression(const BoundedBinaryExpression &other)
Definition BoundedBinaryExpression.hpp:22
Definition BoundedExpression.hpp:15
An expression.
Definition Expression.hpp:56
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
Definition Serialization.hpp:50
virtual void Serialize(const Real &real)=0
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:48
@ Associative
Definition Expression.hpp:43