92 #ifndef OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
93 #define OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
97 #include <initializer_list>
104 #include "absl/container/flat_hash_map.h"
105 #include "absl/strings/string_view.h"
106 #include "absl/log/check.h"
118 class LinearExpression;
134 inline int64_t
id()
const;
142 inline absl::string_view
name()
const;
144 template <
typename H>
157 template <
typename V>
204 #ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
258 template <
typename Iterable>
259 inline void AddSum(
const Iterable& items);
265 template <
typename Iterable>
304 template <
typename LeftIterable,
typename RightIterable>
306 const RightIterable& right);
312 template <
typename LeftIterable,
typename RightIterable>
314 const RightIterable& right);
318 inline double offset()
const;
335 inline const absl::flat_hash_map<VariableId, double>&
raw_terms()
const;
337 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
338 static thread_local
int num_calls_default_constructor_;
339 static thread_local
int num_calls_copy_constructor_;
340 static thread_local
int num_calls_move_constructor_;
341 static thread_local
int num_calls_initializer_list_constructor_;
343 static void ResetCounters();
348 friend std::ostream&
operator<<(std::ostream& ostr,
353 double offset_ = 0.0;
379 template <
typename Iterable>
408 template <
typename LeftIterable,
typename RightIterable>
410 const RightIterable& right);
473 inline operator bool()
const;
657 template <
typename H>
665 inline std::ostream&
operator<<(std::ostream& ostr,
666 const QuadraticTermKey& key);
668 inline bool operator==(
const QuadraticTermKey lhs,
const QuadraticTermKey rhs);
669 inline bool operator!=(
const QuadraticTermKey lhs,
const QuadraticTermKey rhs);
716 template <
typename V>
735 #ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
754 inline double offset()
const;
760 inline const absl::flat_hash_map<QuadraticProductId, double>&
806 template <
typename Iterable>
807 inline void AddSum(
const Iterable& items);
830 template <
typename Iterable>
871 template <
typename LeftIterable,
typename RightIterable>
873 const RightIterable& right);
899 template <
typename LeftIterable,
typename RightIterable>
901 const RightIterable& right);
920 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
921 static thread_local
int num_calls_default_constructor_;
922 static thread_local
int num_calls_copy_constructor_;
923 static thread_local
int num_calls_move_constructor_;
924 static thread_local
int num_calls_initializer_list_constructor_;
925 static thread_local
int num_calls_linear_expression_constructor_;
927 static void ResetCounters();
932 friend std::ostream&
operator<<(std::ostream& ostr,
934 inline void CheckModelsAgree();
938 double offset_ = 0.0;
1246 : storage_(storage), id_(id) {
1267 if (
storage()->has_variable(id_)) {
1270 return "[variable deleted from model]";
1273 template <
typename H>
1275 return H::combine(std::move(h), variable.id_.value(), variable.storage_);
1280 const absl::string_view
name = variable.
name();
1282 ostr <<
"__var#" << variable.
id() <<
"__";
1346 const double offset)
1348 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1349 ++num_calls_initializer_list_constructor_;
1351 for (
const auto& term :
terms) {
1354 terms_[term.variable] += term.coefficient;
1368 expr.offset_ = -expr.offset_;
1369 for (
auto term : expr.terms_) {
1370 term.second = -term.second;
1418 return std::move(lhs) +
LinearTerm(rhs, 1.0);
1422 return LinearTerm(lhs, 1.0) + std::move(rhs);
1478 auto ret = -std::move(rhs);
1484 return std::move(lhs) -
LinearTerm(rhs, 1.0);
1488 return LinearTerm(lhs, 1.0) - std::move(rhs);
1497 auto ret = -std::move(rhs);
1523 terms_.Add(other.terms_);
1524 offset_ += other.offset_;
1543 terms_.Subtract(other.terms_);
1544 offset_ -= other.offset_;
1564 for (
auto term : terms_) {
1565 term.second *=
value;
1572 for (
auto term : terms_) {
1573 term.second /=
value;
1578 template <
typename Iterable>
1580 for (
const auto& item : items) {
1585 template <
typename Iterable>
1592 template <
typename Iterable>
1599 template <
typename LeftIterable,
typename RightIterable,
typename Expression>
1604 auto l = begin(left);
1605 auto r = begin(right);
1606 const auto l_end =
end(left);
1607 const auto r_end =
end(right);
1608 for (; l != l_end && r != r_end; ++l, ++r) {
1609 expr += (*l) * (*r);
1612 <<
"left had more elements than right, sizes should be equal";
1614 <<
"right had more elements than left, sizes should be equal";
1619 template <
typename LeftIterable,
typename RightIterable>
1621 const RightIterable& right) {
1625 template <
typename LeftIterable,
typename RightIterable>
1627 const RightIterable& right) {
1633 template <
typename LeftIterable,
typename RightIterable>
1635 const RightIterable& right) {
1644 return terms_.storage();
1649 return terms_.raw_map();
1659 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
1661 inline VariablesEquality::operator bool()
const {
1662 return lhs.
typed_id() == rhs.typed_id() && lhs.storage() == rhs.storage();
1673 return !(lhs == rhs);
1693 : expression(std::move(expression)),
1699 : expression({{eq.
lhs, 1.0}, {eq.
rhs, -1.0}}, 0.0),
1705 : expression(std::move(lb_expression.expression)),
1707 upper_bound(std::numeric_limits<double>::infinity()) {}
1711 : expression(std::move(ub_expression.expression)),
1712 lower_bound(-std::numeric_limits<double>::infinity()),
1724 const double constant) {
1734 const double constant) {
1744 const double constant) {
1745 return LinearTerm(variable, 1.0) >= constant;
1750 return constant <=
LinearTerm(variable, 1.0);
1754 const double constant) {
1764 const double constant) {
1774 const double constant) {
1775 return LinearTerm(variable, 1.0) <= constant;
1780 return constant >=
LinearTerm(variable, 1.0);
1815 std::move(lhs), -std::numeric_limits<double>::infinity(),
1823 std::move(lhs), 0.0,
1824 std::numeric_limits<double>::infinity());
1831 std::move(lhs), -std::numeric_limits<double>::infinity(),
1839 std::move(lhs), 0.0,
1840 std::numeric_limits<double>::infinity());
1847 std::move(rhs), 0.0,
1848 std::numeric_limits<double>::infinity());
1855 std::move(rhs), -std::numeric_limits<double>::infinity(),
1860 return std::move(lhs) <=
LinearTerm(rhs, 1.0);
1864 return std::move(lhs) >=
LinearTerm(rhs, 1.0);
1868 return LinearTerm(lhs, 1.0) <= std::move(rhs);
1872 return LinearTerm(lhs, 1.0) >= std::move(rhs);
1879 -std::numeric_limits<double>::infinity(),
1887 std::numeric_limits<double>::infinity());
1936 return std::move(lhs) ==
LinearTerm(rhs, 1.0);
1940 return LinearTerm(lhs, 1.0) == std::move(rhs);
1994 : storage_(storage), variable_ids_(id) {
1995 if (variable_ids_.first > variable_ids_.second) {
1997 swap(variable_ids_.first, variable_ids_.second);
2005 CHECK_EQ(first_variable.storage(), second_variable.storage())
2013 template <
typename H>
2015 return H::combine(std::move(h), key.
typed_id().first.value(),
2030 return !(lhs == rhs);
2039 : first_variable_(std::move(first_variable)),
2040 second_variable_(std::move(second_variable)),
2061 const std::initializer_list<QuadraticTerm> quadratic_terms,
2062 const std::initializer_list<LinearTerm> linear_terms,
const double offset)
2064 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2065 ++num_calls_initializer_list_constructor_;
2068 linear_terms_[term.variable] += term.coefficient;
2071 quadratic_terms_[term.GetKey()] += term.coefficient();
2086 : linear_terms_(std::move(expr.terms_)),
2088 #ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2089 ++num_calls_linear_expression_constructor_;
2096 void QuadraticExpression::CheckModelsAgree() {
2097 const ModelStorage*
const quadratic_model = quadratic_terms_.storage();
2098 const ModelStorage*
const linear_model = linear_terms_.storage();
2099 if ((linear_model !=
nullptr) && (quadratic_model !=
nullptr) &&
2100 (quadratic_model != linear_model)) {
2116 return linear_terms_;
2120 return quadratic_terms_;
2123 const absl::flat_hash_map<VariableId, double>&
2125 return linear_terms_.raw_map();
2128 const absl::flat_hash_map<QuadraticProductId, double>&
2130 return quadratic_terms_.raw_map();
2249 term.coefficient_ *= -1.0;
2255 expr.offset_ = -expr.offset_;
2256 for (
auto term : expr.linear_terms_) {
2257 term.second = -term.second;
2259 for (
auto term : expr.quadratic_terms_) {
2260 term.second = -term.second;
2270 auto expr = -std::move(rhs);
2280 return LinearTerm(lhs, 1.0) - std::move(rhs);
2288 auto expr = -std::move(rhs);
2301 auto expr = -std::move(rhs);
2376 rhs.coefficient_ *= lhs;
2396 for (
const auto& [
var, coeff] : rhs.
terms()) {
2417 for (
const auto& [
var, coeff] : rhs.
terms()) {
2428 for (
const auto& [
var, coeff] : lhs.
terms()) {
2439 for (
const auto& [
var, coeff] : lhs.
terms()) {
2452 for (
const auto& [
var, coeff] : lhs.
terms()) {
2457 for (
const auto& [
var, coeff] : rhs.
terms()) {
2461 for (
const auto& [lhs_var, lhs_coeff] : lhs.
terms()) {
2462 for (
const auto& [rhs_var, rhs_coeff] : rhs.
terms()) {
2463 expr +=
QuadraticTerm(lhs_var, rhs_var, lhs_coeff * rhs_coeff);
2471 lhs.coefficient_ *= rhs;
2484 lhs.coefficient_ /= rhs;
2508 linear_terms_[variable] += 1;
2521 offset_ += expr.
offset();
2522 linear_terms_.Add(expr.
terms());
2536 offset_ += expr.
offset();
2550 linear_terms_[variable] -= 1;
2563 offset_ -= expr.
offset();
2564 linear_terms_.Subtract(expr.
terms());
2578 offset_ -= expr.
offset();
2586 coefficient_ *=
value;
2594 for (
auto term : linear_terms_) {
2595 term.second *=
value;
2597 for (
auto term : quadratic_terms_) {
2598 term.second *=
value;
2606 coefficient_ /=
value;
2614 for (
auto term : linear_terms_) {
2615 term.second /=
value;
2617 for (
auto term : quadratic_terms_) {
2618 term.second /=
value;
2625 template <
typename Iterable>
2627 for (
const auto& item : items) {
2632 template <
typename Iterable>
2639 template <
typename LeftIterable,
typename RightIterable>
2641 const RightIterable& right) {
2645 template <
typename LeftIterable,
typename RightIterable>
2647 const LeftIterable& left,
const RightIterable& right) {
2664 : expression(std::move(lb_expression.expression)),
2672 : expression(std::move(ub_expression.expression)),
2678 : expression(std::move(expression)),
2689 : expression(std::move(lb_expression.expression)),
2691 upper_bound(std::numeric_limits<double>::infinity()) {}
2694 : expression(std::move(ub_expression.expression)),
2695 lower_bound(-std::numeric_limits<double>::infinity()),
2699 : expression(std::move(bounded_expression.expression)),
2704 : expression(std::move(lb_expression.expression)),
2706 upper_bound(std::numeric_limits<double>::infinity()) {}
2709 : expression(std::move(ub_expression.expression)),
2710 lower_bound(-std::numeric_limits<double>::infinity()),
2780 std::numeric_limits<double>::infinity());
2786 std::numeric_limits<double>::infinity());
2792 std::numeric_limits<double>::infinity());
2798 std::numeric_limits<double>::infinity());
2804 std::numeric_limits<double>::infinity());
2810 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2816 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2822 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2828 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2834 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2871 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2876 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2881 std::move(rhs) - lhs, -std::numeric_limits<double>::infinity(), 0);
2886 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2891 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2897 std::numeric_limits<double>::infinity());
2902 std::numeric_limits<double>::infinity());
2907 std::numeric_limits<double>::infinity());
2912 std::numeric_limits<double>::infinity());
2917 std::numeric_limits<double>::infinity());
2949 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2954 rhs - std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2960 std::numeric_limits<double>::infinity());
2965 std::numeric_limits<double>::infinity());
2981 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2986 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2992 std::numeric_limits<double>::infinity());
2997 std::numeric_limits<double>::infinity());
3013 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
3018 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
3024 std::numeric_limits<double>::infinity());
3029 std::numeric_limits<double>::infinity());
LinearExpression & operator+=(const LinearExpression &other)
LinearExpression & operator/=(double value)
double Evaluate(const VariableMap< double > &variable_values) const
static LinearExpression Sum(const Iterable &items)
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
friend LinearExpression operator-(LinearExpression expr)
friend std::ostream & operator<<(std::ostream &ostr, const LinearExpression &expression)
LinearExpression & operator-=(const LinearExpression &other)
LinearExpression & operator*=(double value)
static LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const absl::flat_hash_map< VariableId, double > & raw_terms() const
LinearExpression()=default
void AddSum(const Iterable &items)
const VariableMap< double > & terms() const
const ModelStorage * storage() const
const std::string & variable_name(VariableId id) const
double variable_lower_bound(VariableId id) const
bool is_variable_integer(VariableId id) const
double variable_upper_bound(VariableId id) const
double Evaluate(const VariableMap< double > &variable_values) const
QuadraticExpression & operator-=(double value)
QuadraticExpression & operator+=(double value)
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
const QuadraticTermMap< double > & quadratic_terms() const
QuadraticExpression()=default
const VariableMap< double > & linear_terms() const
static QuadraticExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
friend std::ostream & operator<<(std::ostream &ostr, const QuadraticExpression &expr)
static QuadraticExpression Sum(const Iterable &items)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const absl::flat_hash_map< QuadraticProductId, double > & raw_quadratic_terms() const
QuadraticExpression & operator/=(double value)
const absl::flat_hash_map< VariableId, double > & raw_linear_terms() const
QuadraticExpression & operator*=(double value)
friend QuadraticExpression operator-(QuadraticExpression expr)
void AddSum(const Iterable &items)
const ModelStorage * storage() const
QuadraticTerm & operator*=(double value)
friend QuadraticTerm operator*(double lhs, QuadraticTerm rhs)
friend QuadraticTerm operator-(QuadraticTerm term)
Variable first_variable() const
QuadraticTermKey GetKey() const
double coefficient() const
QuadraticTerm & operator/=(double value)
friend QuadraticTerm operator/(QuadraticTerm lhs, double rhs)
Variable second_variable() const
QuadraticTermKey(const ModelStorage *storage, QuadraticProductId id)
QuadraticProductId typed_id() const
const ModelStorage * storage() const
QuadraticProductId IdType
friend H AbslHashValue(H h, const QuadraticTermKey &key)
friend std::ostream & operator<<(std::ostream &ostr, const Variable &variable)
LinearExpression operator-() const
double upper_bound() const
friend H AbslHashValue(H h, const Variable &variable)
double lower_bound() const
Variable(const ModelStorage *storage, VariableId id)
absl::string_view name() const
const ModelStorage * storage() const
VariableId typed_id() const
constexpr absl::string_view kObjectsFromOtherModelStorage
void AddInnerProduct(const LeftIterable &left, const RightIterable &right, Expression &expr)
LowerBoundedLinearExpression operator>=(LinearExpression expression, double constant)
std::pair< VariableId, VariableId > QuadraticProductId
LinearExpression Sum(const Iterable &items)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
LinearExpression operator-(LinearExpression expr)
bool operator==(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
bool operator!=(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
LowerBoundedLinearExpression operator<=(double constant, LinearExpression expression)
LinearExpression operator+(Variable lhs, double rhs)
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
LinearTerm operator*(double coefficient, LinearTerm term)
LinearTerm operator/(LinearTerm term, double coefficient)
H AbslHashValue(H h, const IndicatorConstraint &constraint)
Collection of objects used to extend the Constraint Solver library.
std::optional< int64_t > end
double upper_bound_minus_offset() const
LinearExpression expression
BoundedLinearExpression(LinearExpression expression, double lower_bound, double upper_bound)
double lower_bound_minus_offset() const
double upper_bound_minus_offset() const
QuadraticExpression expression
BoundedQuadraticExpression(QuadraticExpression expression, double lower_bound, double upper_bound)
double lower_bound_minus_offset() const
LinearTerm operator-() const
LinearTerm & operator/=(double d)
LinearTerm(Variable variable, double coefficient)
LinearTerm & operator*=(double d)
LinearExpression expression
LowerBoundedLinearExpression(LinearExpression expression, double lower_bound)
QuadraticExpression expression
LowerBoundedQuadraticExpression(QuadraticExpression expression, double lower_bound)
UpperBoundedLinearExpression(LinearExpression expression, double upper_bound)
LinearExpression expression
UpperBoundedQuadraticExpression(QuadraticExpression expression, double upper_bound)
QuadraticExpression expression
VariablesEquality(Variable lhs, Variable rhs)