8#include <initializer_list>
9#include <source_location>
15#include <gch/small_vector.hpp>
17#include "sleipnir/autodiff/expression.hpp"
18#include "sleipnir/autodiff/expression_graph.hpp"
19#include "sleipnir/autodiff/expression_type.hpp"
20#include "sleipnir/autodiff/sleipnir_base.hpp"
21#include "sleipnir/util/assert.hpp"
22#include "sleipnir/util/concepts.hpp"
24#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
25#include "sleipnir/util/print.hpp"
32template <
typename Scalar>
37template <
typename Scalar>
38VariableMatrix<Scalar> gradient_tree(
39 const detail::ExpressionGraph<Scalar>& top_list,
40 const VariableMatrix<Scalar>& wrt);
44template <
typename Scalar,
int UpLo = Eigen::Lower | Eigen::Upper>
45 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
48template <
typename Scalar>
54template <
typename Scalar_>
72 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
80 slp_assert(
value.rows() == 1 &&
value.cols() == 1);
88 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
96 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
108 : expr{std::
move(expr)} {}
116 detail::make_expression_ptr<detail::ConstantExpression<Scalar>>(
value);
117 m_graph_initialized =
false;
126#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
129 if (expr->args[0] !=
nullptr) {
130 auto location = std::source_location::current();
133 "WARNING: {}:{}: {}: Modified the value of a dependent variable",
144 if (!m_graph_initialized) {
145 m_graph = detail::topological_sort(expr);
146 m_graph_initialized =
true;
148 detail::update_values(m_graph);
157 ExpressionType
type()
const {
return expr->type(); }
164 template <ScalarLike LHS, SleipnirScalarLike<Scalar> RHS>
174 template <SleipnirScalarLike<Scalar> LHS, ScalarLike RHS>
272 detail::make_expression_ptr<detail::DecisionVariableExpression<Scalar>>();
276 detail::ExpressionGraph<Scalar> m_graph;
279 bool m_graph_initialized =
false;
281 template <
typename Scalar>
283 template <
typename Scalar>
285 template <
typename Scalar>
287 template <
typename Scalar>
289 template <
typename Scalar>
292 template <
typename Scalar>
295 template <
typename Scalar>
298 template <
typename Scalar>
300 template <
typename Scalar>
302 template <
typename Scalar>
304 template <
typename Scalar>
306 template <
typename Scalar>
308 template <
typename Scalar>
311 template <
typename Scalar>
314 template <
typename Scalar>
317 template <
typename Scalar>
319 template <
typename Scalar>
321 template <
typename Scalar>
324 template <
typename Scalar>
327 template <
typename Scalar>
330 template <
typename Scalar>
333 template <
typename Scalar>
336 template <
typename Scalar>
339 template <
typename Scalar>
342 template <
typename Scalar>
345 template <
typename Scalar>
348 template <
typename Scalar>
350 template <
typename Scalar>
352 template <
typename Scalar>
354 template <
typename Scalar>
356 template <
typename Scalar>
358 template <
typename Scalar>
360 template <
typename Scalar>
365 template <
typename Scalar>
367 const detail::ExpressionGraph<Scalar>&
top_list,
369 template <
typename Scalar,
int UpLo>
370 requires(
UpLo == Eigen::Lower) || (
UpLo == (Eigen::Lower | Eigen::Upper))
372 template <
typename Scalar>
376template <
template <
typename>
typename T,
typename Scalar>
377 requires SleipnirMatrixLike<T<Scalar>, Scalar>
378Variable(T<Scalar>) -> Variable<Scalar>;
380template <std::
floating_po
int T>
381Variable(T) -> Variable<T>;
383template <std::
integral T>
384Variable(T) -> Variable<T>;
390template <
typename Scalar>
391Variable<Scalar> abs(
const Variable<Scalar>& x) {
392 return Variable{detail::abs(x.expr)};
399template <
typename Scalar>
400Variable<Scalar> acos(
const Variable<Scalar>& x) {
401 return Variable{detail::acos(x.expr)};
408template <
typename Scalar>
409Variable<Scalar> asin(
const Variable<Scalar>& x) {
410 return Variable{detail::asin(x.expr)};
417template <
typename Scalar>
418Variable<Scalar> atan(
const Variable<Scalar>& x) {
419 return Variable{detail::atan(x.expr)};
427template <
typename Scalar>
428Variable<Scalar> atan2(
const ScalarLike
auto& y,
const Variable<Scalar>& x) {
429 return Variable{detail::atan2(Variable<Scalar>(y).expr, x.expr)};
437template <
typename Scalar>
438Variable<Scalar> atan2(
const Variable<Scalar>& y,
const ScalarLike
auto& x) {
439 return Variable{detail::atan2(y.expr, Variable<Scalar>(x).expr)};
447template <
typename Scalar>
448Variable<Scalar> atan2(
const Variable<Scalar>& y,
const Variable<Scalar>& x) {
449 return Variable{detail::atan2(y.expr, x.expr)};
456template <
typename Scalar>
457Variable<Scalar> cbrt(
const Variable<Scalar>& x) {
458 return Variable{detail::cbrt(x.expr)};
465template <
typename Scalar>
466Variable<Scalar> cos(
const Variable<Scalar>& x) {
467 return Variable{detail::cos(x.expr)};
474template <
typename Scalar>
475Variable<Scalar> cosh(
const Variable<Scalar>& x) {
476 return Variable{detail::cosh(x.expr)};
483template <
typename Scalar>
484Variable<Scalar> erf(
const Variable<Scalar>& x) {
485 return Variable{detail::erf(x.expr)};
492template <
typename Scalar>
493Variable<Scalar> exp(
const Variable<Scalar>& x) {
494 return Variable{detail::exp(x.expr)};
502template <
typename Scalar>
503Variable<Scalar> hypot(
const ScalarLike
auto& x,
const Variable<Scalar>& y) {
504 return Variable{detail::hypot(Variable<Scalar>(x).expr, y.expr)};
512template <
typename Scalar>
513Variable<Scalar> hypot(
const Variable<Scalar>& x,
const ScalarLike
auto& y) {
514 return Variable{detail::hypot(x.expr, Variable<Scalar>(y).expr)};
522template <
typename Scalar>
523Variable<Scalar> hypot(
const Variable<Scalar>& x,
const Variable<Scalar>& y) {
524 return Variable{detail::hypot(x.expr, y.expr)};
531template <
typename Scalar>
532Variable<Scalar> log(
const Variable<Scalar>& x) {
533 return Variable{detail::log(x.expr)};
540template <
typename Scalar>
541Variable<Scalar> log10(
const Variable<Scalar>& x) {
542 return Variable{detail::log10(x.expr)};
552template <
typename Scalar>
553Variable<Scalar> max(
const ScalarLike
auto& a,
const Variable<Scalar>& b) {
554 return Variable{detail::max(Variable<Scalar>(a).expr, b.expr)};
564template <
typename Scalar>
565Variable<Scalar> max(
const Variable<Scalar>& a,
const ScalarLike
auto& b) {
566 return Variable{detail::max(a.expr, Variable<Scalar>(b).expr)};
576template <
typename Scalar>
577Variable<Scalar> max(
const Variable<Scalar>& a,
const Variable<Scalar>& b) {
578 return Variable{detail::max(a.expr, b.expr)};
588template <
typename Scalar>
589Variable<Scalar> min(
const ScalarLike
auto& a,
const Variable<Scalar>& b) {
590 return Variable{detail::min(Variable<Scalar>(a).expr, b.expr)};
600template <
typename Scalar>
601Variable<Scalar> min(
const Variable<Scalar>& a,
const ScalarLike
auto& b) {
602 return Variable{detail::min(a.expr, Variable<Scalar>(b).expr)};
612template <
typename Scalar>
613Variable<Scalar> min(
const Variable<Scalar>& a,
const Variable<Scalar>& b) {
614 return Variable{detail::min(a.expr, b.expr)};
622template <
typename Scalar>
623Variable<Scalar> pow(
const ScalarLike
auto& base,
624 const Variable<Scalar>& power) {
625 return Variable{detail::pow(Variable<Scalar>(base).expr, power.expr)};
633template <
typename Scalar>
634Variable<Scalar> pow(
const Variable<Scalar>& base,
635 const ScalarLike
auto& power) {
636 return Variable{detail::pow(base.expr, Variable<Scalar>(power).expr)};
644template <
typename Scalar>
645Variable<Scalar> pow(
const Variable<Scalar>& base,
646 const Variable<Scalar>& power) {
647 return Variable{detail::pow(base.expr, power.expr)};
654template <
typename Scalar>
655Variable<Scalar> sign(
const Variable<Scalar>& x) {
656 return Variable{detail::sign(x.expr)};
663template <
typename Scalar>
664Variable<Scalar> sin(
const Variable<Scalar>& x) {
665 return Variable{detail::sin(x.expr)};
672template <
typename Scalar>
673Variable<Scalar> sinh(
const Variable<Scalar>& x) {
674 return Variable{detail::sinh(x.expr)};
681template <
typename Scalar>
682Variable<Scalar> sqrt(
const Variable<Scalar>& x) {
683 return Variable{detail::sqrt(x.expr)};
690template <
typename Scalar>
691Variable<Scalar> tan(
const Variable<Scalar>& x) {
692 return Variable{detail::tan(x.expr)};
699template <
typename Scalar>
700Variable<Scalar> tanh(
const Variable<Scalar>& x) {
701 return Variable{detail::tanh(x.expr)};
710template <
typename Scalar>
711Variable<Scalar> hypot(
const Variable<Scalar>& x,
const Variable<Scalar>& y,
712 const Variable<Scalar>& z) {
713 return Variable{sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2))};
721template <
typename Scalar, ScalarLike LHS, ScalarLike RHS>
722 requires SleipnirScalarLike<LHS, Scalar> || SleipnirScalarLike<RHS, Scalar>
723auto make_constraints(LHS&& lhs, RHS&& rhs) {
724 gch::small_vector<Variable<Scalar>> constraints;
725 constraints.emplace_back(lhs - rhs);
730template <
typename Scalar, ScalarLike LHS, MatrixLike RHS>
731 requires SleipnirScalarLike<LHS, Scalar> || SleipnirMatrixLike<RHS, Scalar>
732auto make_constraints(LHS&& lhs, RHS&& rhs) {
733 gch::small_vector<Variable<Scalar>> constraints;
734 constraints.reserve(rhs.rows() * rhs.cols());
736 for (
int row = 0; row < rhs.rows(); ++row) {
737 for (
int col = 0; col < rhs.cols(); ++col) {
739 constraints.emplace_back(lhs - rhs[row, col]);
746template <
typename Scalar, MatrixLike LHS, ScalarLike RHS>
747 requires SleipnirMatrixLike<LHS, Scalar> || SleipnirScalarLike<RHS, Scalar>
748auto make_constraints(LHS&& lhs, RHS&& rhs) {
749 gch::small_vector<Variable<Scalar>> constraints;
750 constraints.reserve(lhs.rows() * lhs.cols());
752 for (
int row = 0; row < lhs.rows(); ++row) {
753 for (
int col = 0; col < lhs.cols(); ++col) {
755 constraints.emplace_back(lhs[row, col] - rhs);
762template <
typename Scalar, MatrixLike LHS, MatrixLike RHS>
763 requires SleipnirMatrixLike<LHS, Scalar> || SleipnirMatrixLike<RHS, Scalar>
764auto make_constraints(LHS&& lhs, RHS&& rhs) {
765 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
767 gch::small_vector<Variable<Scalar>> constraints;
768 constraints.reserve(lhs.rows() * lhs.cols());
770 for (
int row = 0; row < lhs.rows(); ++row) {
771 for (
int col = 0; col < lhs.cols(); ++col) {
773 constraints.emplace_back(lhs[row, col] - rhs[row, col]);
783template <
typename Scalar>
796 elem.constraints.end());
810 elem.constraints.end());
821 template <
typename LHS,
typename RHS>
840template <
typename Scalar>
853 elem.constraints.end());
867 elem.constraints.end());
879 template <
typename LHS,
typename RHS>
899template <
typename LHS,
typename RHS>
900 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
901 (ScalarLike<RHS> || MatrixLike<RHS>) && (!SleipnirType<RHS>)
902auto operator==(LHS&& lhs, RHS&& rhs) {
903 return EqualityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
910template <
typename LHS,
typename RHS>
911 requires(ScalarLike<LHS> || MatrixLike<LHS>) && (!SleipnirType<LHS>) &&
912 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
913auto operator==(LHS&& lhs, RHS&& rhs) {
914 return EqualityConstraints<typename std::decay_t<RHS>::Scalar>{lhs, rhs};
921template <
typename LHS,
typename RHS>
922 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
923 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
924auto operator==(LHS&& lhs, RHS&& rhs) {
925 return EqualityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
933template <
typename LHS,
typename RHS>
934 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
935 (ScalarLike<RHS> || MatrixLike<RHS>) &&
936 (SleipnirType<LHS> || SleipnirType<RHS>)
937auto operator<(LHS&& lhs, RHS&& rhs) {
946template <
typename LHS,
typename RHS>
947 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
948 (ScalarLike<RHS> || MatrixLike<RHS>) &&
949 (SleipnirType<LHS> || SleipnirType<RHS>)
950auto operator<=(LHS&& lhs, RHS&& rhs) {
959template <
typename LHS,
typename RHS>
960 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
961 (ScalarLike<RHS> || MatrixLike<RHS>) &&
962 (SleipnirType<LHS> || SleipnirType<RHS>)
963auto operator>(LHS&& lhs, RHS&& rhs) {
972template <
typename LHS,
typename RHS>
973 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
974 (ScalarLike<RHS> || MatrixLike<RHS>) && (!SleipnirType<RHS>)
975auto operator>=(LHS&& lhs, RHS&& rhs) {
976 return InequalityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
984template <
typename LHS,
typename RHS>
985 requires(ScalarLike<LHS> || MatrixLike<LHS>) && (!SleipnirType<LHS>) &&
986 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
987auto operator>=(LHS&& lhs, RHS&& rhs) {
988 return InequalityConstraints<typename std::decay_t<RHS>::Scalar>{lhs, rhs};
996template <
typename LHS,
typename RHS>
997 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
998 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
999auto operator>=(LHS&& lhs, RHS&& rhs) {
1000 return InequalityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
1008template <
typename L,
typename X,
typename U>
1009 requires(ScalarLike<L> || MatrixLike<L>) && SleipnirType<X> &&
1010 (ScalarLike<U> || MatrixLike<U>)
1011auto bounds(L&& l, X&& x, U&& u) {
1012 return InequalityConstraints{l <= x, x <= u};
1023template <
typename Scalar>
1024struct NumTraits<slp::Variable<Scalar>> : NumTraits<Scalar> {
1033 static constexpr int IsComplex = 0;
1035 static constexpr int IsInteger = 0;
1037 static constexpr int IsSigned = 1;
1039 static constexpr int RequireInitialization = 1;
1041 static constexpr int ReadCost = 1;
1043 static constexpr int AddCost = 3;
1045 static constexpr int MulCost = 3;
Definition hessian.hpp:35
Definition intrusive_shared_ptr.hpp:27
Definition jacobian.hpp:31
Definition sleipnir_base.hpp:9
Definition variable.hpp:55
ExpressionType type() const
Definition variable.hpp:157
friend Variable< Scalar > operator*(const LHS &lhs, const RHS &rhs)
Definition variable.hpp:165
Variable(const detail::ExpressionPtr< Scalar > &expr)
Definition variable.hpp:102
Variable< Scalar > & operator/=(const Variable< Scalar > &rhs)
Definition variable.hpp:212
Variable< Scalar > & operator*=(const Variable< Scalar > &rhs)
Definition variable.hpp:193
friend Variable< Scalar > operator+(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:222
void set_value(Scalar value)
Definition variable.hpp:125
friend Variable< Scalar > operator/(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:203
Variable(std::floating_point auto value)
Definition variable.hpp:87
constexpr Variable(detail::ExpressionPtr< Scalar > &&expr)
Definition variable.hpp:107
friend Variable< Scalar > operator+(const Variable< Scalar > &lhs)
Definition variable.hpp:265
Variable(Scalar value)
Definition variable.hpp:70
constexpr Variable(std::nullptr_t)
Constructs an empty Variable.
Definition variable.hpp:64
Variable< Scalar > & operator=(ScalarLike auto value)
Definition variable.hpp:114
Variable()=default
Constructs a linear Variable with a value of zero.
friend Variable< Scalar > operator-(const Variable< Scalar > &lhs)
Definition variable.hpp:258
friend Variable< Scalar > operator*(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:184
Variable(std::integral auto value)
Definition variable.hpp:95
Variable(SleipnirMatrixLike< Scalar > auto value)
Definition variable.hpp:79
Variable< Scalar > & operator+=(const Variable< Scalar > &rhs)
Definition variable.hpp:231
Scalar_ Scalar
Scalar type alias.
Definition variable.hpp:58
Scalar value()
Definition variable.hpp:143
Variable< Scalar > & operator-=(const Variable< Scalar > &rhs)
Definition variable.hpp:250
friend Variable< Scalar > operator-(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:241
Definition concepts.hpp:18
Definition concepts.hpp:24
Definition concepts.hpp:33
Definition concepts.hpp:15
Definition variable.hpp:784
EqualityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:825
EqualityConstraints(std::initializer_list< EqualityConstraints > equality_constraints)
Definition variable.hpp:792
gch::small_vector< Variable< Scalar > > constraints
A vector of scalar equality constraints.
Definition variable.hpp:786
EqualityConstraints(const std::vector< EqualityConstraints > &equality_constraints)
Definition variable.hpp:806
Definition variable.hpp:841
gch::small_vector< Variable< Scalar > > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:843
InequalityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:883
InequalityConstraints(const std::vector< InequalityConstraints > &inequality_constraints)
Definition variable.hpp:863
InequalityConstraints(std::initializer_list< InequalityConstraints > inequality_constraints)
Definition variable.hpp:849