diff --git a/README.md b/README.md index 5ff519b9..bef3ffcf 100644 --- a/README.md +++ b/README.md @@ -108,17 +108,26 @@ target_link_libraries(MyApp PRIVATE Oasis::Oasis) ```c++ #include #include // C++23 +#include +#include #include #include +#include int main() { + SimplifyVisitor simplifyVisitor{}; Oasis::Add sum { Oasis::Real{2.0}, Oasis::Real{3.0} }; - auto simplified = sum.Simplify(); + auto expr = sum.Accept(simplifiedVisitor); + if (!expr) { // Error Case + std::println(expr.error()); + return EXIT_FAILURE; + } + auto simplified = std::move(expr).value(); std::println("Result: {}", simplified->ToString()); return EXIT_SUCCESS; diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index b41736c7..faa95afa 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -20,6 +20,8 @@ set(Oasis_HEADERS Oasis/Pi.hpp Oasis/Real.hpp Oasis/RecursiveCast.hpp + Oasis/SimplifyVisitor.hpp + Oasis/Sine.hpp Oasis/Subtract.hpp Oasis/UnaryExpression.hpp Oasis/Undefined.hpp diff --git a/include/Oasis/Add.hpp b/include/Oasis/Add.hpp index b61e6d7f..56274e3d 100644 --- a/include/Oasis/Add.hpp +++ b/include/Oasis/Add.hpp @@ -20,7 +20,7 @@ class Add< public: using BinaryExpression::BinaryExpression; - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Integrate(const Expression& integrationVariable) const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/BinaryExpression.hpp b/include/Oasis/BinaryExpression.hpp index 30af5a1b..f7b56a89 100644 --- a/include/Oasis/BinaryExpression.hpp +++ b/include/Oasis/BinaryExpression.hpp @@ -11,6 +11,7 @@ #include #include "Expression.hpp" +#include "Oasis/SimplifyVisitor.hpp" #include "RecursiveCast.hpp" #include "Visit.hpp" @@ -199,7 +200,13 @@ class BinaryExpression : public Expression { [[nodiscard]] auto Simplify() const -> std::unique_ptr override { - return Generalize()->Simplify(); + SimplifyVisitor simplifyVisitor {}; + auto e = Generalize(); + auto s = e->Accept(simplifyVisitor); + if (!s) { + return e; + } + return std::move(s).value(); } [[nodiscard]] auto Integrate(const Expression& integrationVariable) const -> std::unique_ptr override @@ -361,11 +368,17 @@ class BinaryExpression : public Expression { auto Substitute(const Expression& var, const Expression& val) -> std::unique_ptr override { + // TODO: FIX WITH VISITOR? std::unique_ptr left = ((GetMostSigOp()).Copy())->Substitute(var, val); std::unique_ptr right = ((GetLeastSigOp().Copy())->Substitute(var, val)); DerivedT comb = DerivedT { *left, *right }; - auto ret = comb.Simplify(); - return ret; + + Oasis::SimplifyVisitor simplifyVisitor {}; + auto simplified = comb.Accept(simplifyVisitor); + if (!simplified) { + return comb.Generalize(); + } + return std::move(simplified.value()); } /** * Swaps the operands of this expression. diff --git a/include/Oasis/Derivative.hpp b/include/Oasis/Derivative.hpp index bab38b2c..f7bc925f 100644 --- a/include/Oasis/Derivative.hpp +++ b/include/Oasis/Derivative.hpp @@ -21,7 +21,7 @@ class Derivative : public BinaryExpression { Derivative(const Expression& Exp, const Expression& Var); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr override; diff --git a/include/Oasis/Divide.hpp b/include/Oasis/Divide.hpp index 19a412ab..96d720af 100644 --- a/include/Oasis/Divide.hpp +++ b/include/Oasis/Divide.hpp @@ -21,7 +21,7 @@ class Divide : public BinaryExpression { Divide(const Expression& dividend, const Expression& divisor); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/Exponent.hpp b/include/Oasis/Exponent.hpp index bf9a3d1c..84ebb207 100644 --- a/include/Oasis/Exponent.hpp +++ b/include/Oasis/Exponent.hpp @@ -22,7 +22,7 @@ class Exponent : public BinaryExpression { Exponent(const Expression& base, const Expression& power); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/Expression.hpp b/include/Oasis/Expression.hpp index 2053875b..c41bf97c 100644 --- a/include/Oasis/Expression.hpp +++ b/include/Oasis/Expression.hpp @@ -38,7 +38,8 @@ enum class ExpressionType { Matrix, Pi, EulerNumber, - Magnitude + Magnitude, + Sine }; /** @@ -210,7 +211,7 @@ template auto Expression::Accept(T& visitor) const -> typename T::RetT { try { - return boost::any_cast(this->AcceptInternal(visitor)); + return boost::any_cast(this->AcceptInternal(static_cast(visitor))); } catch (boost::bad_any_cast& e) { return std::unexpected { e.what() }; } diff --git a/include/Oasis/Integral.hpp b/include/Oasis/Integral.hpp index 5241648a..42d013ba 100644 --- a/include/Oasis/Integral.hpp +++ b/include/Oasis/Integral.hpp @@ -23,8 +23,9 @@ class Integral : public BinaryExpression { Integral(const Expression& integrand, const Expression& differential); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; - [[nodiscard]] auto Simplify(const Expression& upper, const Expression& lower) const -> std::unique_ptr /* final */; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + + [[deprecated]] [[nodiscard]] auto Simplify(const Expression& upper, const Expression& lower) const -> std::unique_ptr /* final */; EXPRESSION_TYPE(Integral) EXPRESSION_CATEGORY(Associative | Commutative) diff --git a/include/Oasis/Log.hpp b/include/Oasis/Log.hpp index 7c1a1f7d..31e3cfb1 100644 --- a/include/Oasis/Log.hpp +++ b/include/Oasis/Log.hpp @@ -22,7 +22,7 @@ class Log : public BinaryExpression { Log(const Expression& base, const Expression& argument); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Integrate(const Expression& integrationVariable) const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/Magnitude.hpp b/include/Oasis/Magnitude.hpp index df542a7d..6b45cf99 100644 --- a/include/Oasis/Magnitude.hpp +++ b/include/Oasis/Magnitude.hpp @@ -13,6 +13,7 @@ #include "Imaginary.hpp" #include "Matrix.hpp" #include "Multiply.hpp" +#include "Oasis/SimplifyVisitor.hpp" #include "Real.hpp" #include "RecursiveCast.hpp" #include "UnaryExpression.hpp" @@ -24,7 +25,7 @@ namespace Oasis { * @tparam OperandT Type of child operand * This represents magnitude/absolute value */ -template +template class Magnitude final : public UnaryExpression { public: Magnitude() = default; @@ -38,8 +39,9 @@ class Magnitude final : public UnaryExpression { { } - [[nodiscard]] auto Simplify() const -> std::unique_ptr override + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr override { + SimplifyVisitor simplifyVisitor {}; auto simpOp = this->GetOperand().Simplify(); if (auto realCase = RecursiveCast(*simpOp); realCase != nullptr) { double val = realCase->GetValue(); @@ -49,7 +51,12 @@ class Magnitude final : public UnaryExpression { return std::make_unique(1.0); } if (auto mulImgCase = RecursiveCast>(*simpOp); mulImgCase != nullptr) { - return Magnitude { mulImgCase->GetMostSigOp() }.Simplify(); + auto e = Magnitude { mulImgCase->GetMostSigOp() }; + auto s = e.Accept(simplifyVisitor); + if (!s) { + return e.Generalize(); + } + return std::move(s).value(); } if (auto addCase = RecursiveCast>(*simpOp); addCase != nullptr) { return Exponent { Add { Exponent { addCase->GetMostSigOp(), Real { 2 } }, @@ -79,12 +86,13 @@ class Magnitude final : public UnaryExpression { [[nodiscard]] auto Differentiate(const Expression& var) const -> std::unique_ptr override { // TODO: Implement + Oasis::SimplifyVisitor simplifyVisitor {}; const std::unique_ptr operandDerivative = this->GetOperand().Differentiate(var); return Magnitude { *operandDerivative } - .Simplify(); + .Generalize(); } [[nodiscard]] auto Integrate(const Expression& integrationVar) const -> std::unique_ptr override @@ -94,7 +102,7 @@ class Magnitude final : public UnaryExpression { return Magnitude { *operandDerivative } - .Simplify(); + .Generalize(); } EXPRESSION_TYPE(Magnitude) diff --git a/include/Oasis/Multiply.hpp b/include/Oasis/Multiply.hpp index 14546868..701486a0 100644 --- a/include/Oasis/Multiply.hpp +++ b/include/Oasis/Multiply.hpp @@ -19,7 +19,7 @@ class Multiply : public BinaryExpression { public: using BinaryExpression::BinaryExpression; - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/Negate.hpp b/include/Oasis/Negate.hpp index e9c715ae..930573b4 100644 --- a/include/Oasis/Negate.hpp +++ b/include/Oasis/Negate.hpp @@ -10,7 +10,7 @@ namespace Oasis { -template +template class Negate final : public UnaryExpression { public: Negate() = default; @@ -24,7 +24,7 @@ class Negate final : public UnaryExpression { { } - [[nodiscard]] auto Simplify() const -> std::unique_ptr override + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr override { return Multiply { Real { -1.0 }, @@ -39,7 +39,7 @@ class Negate final : public UnaryExpression { return Negate { *operandDerivative } - .Simplify(); + .Generalize(); // TODO: FIX WITH VISITOR } EXPRESSION_TYPE(Negate) diff --git a/include/Oasis/SimplifyVisitor.hpp b/include/Oasis/SimplifyVisitor.hpp new file mode 100644 index 00000000..4b85e63a --- /dev/null +++ b/include/Oasis/SimplifyVisitor.hpp @@ -0,0 +1,57 @@ +// +// Created by Andrew Nazareth on 9/23/25. +// + +#ifndef SIMPLIFYVISITOR_HPP +#define SIMPLIFYVISITOR_HPP + +#include +#include + +#include + +#include "Oasis/Visit.hpp" + +namespace Oasis { + +struct SimplifyOpts { + enum class AngleUnits { + RADIANS, + DEGREES, + } angleUnits + = AngleUnits::RADIANS; +}; + +class SimplifyVisitor final : public TypedVisitor>, std::string>> { +public: + SimplifyVisitor(); + explicit SimplifyVisitor(SimplifyOpts& opts); + + auto TypedVisit(const Real& real) -> RetT override; + auto TypedVisit(const Imaginary& imaginary) -> RetT override; + auto TypedVisit(const Variable& variable) -> RetT override; + auto TypedVisit(const Undefined& undefined) -> RetT override; + auto TypedVisit(const Add& add) -> RetT override; + auto TypedVisit(const Subtract& subtract) -> RetT override; + auto TypedVisit(const Multiply& multiply) -> RetT override; + auto TypedVisit(const Divide& divide) -> RetT override; + auto TypedVisit(const Exponent& exponent) -> RetT override; + auto TypedVisit(const Log& log) -> RetT override; + auto TypedVisit(const Negate& negate) -> RetT override; + auto TypedVisit(const Sine& sine) -> RetT override; + auto TypedVisit(const Derivative& derivative) -> RetT override; + auto TypedVisit(const Integral& integral) -> RetT override; + auto TypedVisit(const Matrix& matrix) -> RetT override; + auto TypedVisit(const EulerNumber&) -> RetT override; + auto TypedVisit(const Pi&) -> RetT override; + auto TypedVisit(const Magnitude& magnitude) -> RetT override; + + [[nodiscard]] SimplifyOpts GetOptions() const; + +private: + SimplifyOpts options; +}; + +} // Oasis + +#endif // SIMPLIFYVISITOR_HPP diff --git a/include/Oasis/Sine.hpp b/include/Oasis/Sine.hpp new file mode 100644 index 00000000..1fad4778 --- /dev/null +++ b/include/Oasis/Sine.hpp @@ -0,0 +1,41 @@ +// +// Created by Andrew Nazareth on 9/19/25. +// + +#ifndef OASIS_SINE_HPP +#define OASIS_SINE_HPP + +#include "UnaryExpression.hpp" + +namespace Oasis { + +template +class Sine; + +template <> +class Sine final : public UnaryExpression { +public: + Sine() = default; + Sine(const Sine& other) + : UnaryExpression(other) + { + } + + explicit Sine(const Expression& operand) + : UnaryExpression(operand) + { + } + + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr override; + + [[nodiscard]] auto Differentiate(const Expression& var) const -> std::unique_ptr override; + + [[nodiscard]] auto Integrate(const Expression& var) const -> std::unique_ptr override; + + EXPRESSION_TYPE(Sine) + EXPRESSION_CATEGORY(UnExp) +}; + +} // Oasis + +#endif // OASIS_SINE_HPP diff --git a/include/Oasis/Subtract.hpp b/include/Oasis/Subtract.hpp index c869dc51..fcf85181 100644 --- a/include/Oasis/Subtract.hpp +++ b/include/Oasis/Subtract.hpp @@ -22,7 +22,7 @@ class Subtract : public BinaryExpression { Subtract(const Expression& minuend, const Expression& subtrahend); - [[nodiscard]] auto Simplify() const -> std::unique_ptr final; + [[deprecated]] [[nodiscard]] auto Simplify() const -> std::unique_ptr final; [[nodiscard]] auto Differentiate(const Expression& differentiationVariable) const -> std::unique_ptr final; diff --git a/include/Oasis/UnaryExpression.hpp b/include/Oasis/UnaryExpression.hpp index 5f5395ca..b1673f64 100644 --- a/include/Oasis/UnaryExpression.hpp +++ b/include/Oasis/UnaryExpression.hpp @@ -10,7 +10,7 @@ namespace Oasis { -template