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/log/check.h"
106#include "absl/strings/string_view.h"
117class LinearExpression;
136 inline int64_t
id()
const;
139 inline const ModelStorage*
storage()
const;
144 inline absl::string_view
name()
const;
146 template <
typename H>
153 const ModelStorage* storage_;
175 inline operator bool()
const;
234#ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
294 template <
typename Iterable>
295 inline void AddSum(
const Iterable& items);
301 template <
typename Iterable>
340 template <
typename LeftIterable,
typename RightIterable>
342 const RightIterable& right);
348 template <
typename LeftIterable,
typename RightIterable>
350 const RightIterable& right);
354 inline double offset()
const;
370 inline const ModelStorage*
storage()
const;
372#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
373 static thread_local int num_calls_default_constructor_;
374 static thread_local int num_calls_copy_constructor_;
375 static thread_local int num_calls_move_constructor_;
376 static thread_local int num_calls_initializer_list_constructor_;
378 static void ResetCounters();
383 friend std::ostream&
operator<<(std::ostream& ostr,
389 inline void SetOrCheckStorage(
const ModelStorage*
storage);
394 const ModelStorage* storage_ =
nullptr;
396 double offset_ = 0.0;
422template <
typename Iterable>
451template <
typename LeftIterable,
typename RightIterable>
453 const RightIterable& right);
665 inline const ModelStorage*
storage()
const;
673 template <
typename H>
677 const ModelStorage* storage_;
681inline std::ostream&
operator<<(std::ostream& ostr,
682 const QuadraticTermKey& key);
684inline bool operator==(QuadraticTermKey lhs, QuadraticTermKey rhs);
685inline bool operator!=(QuadraticTermKey lhs, QuadraticTermKey rhs);
752#ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
777 inline double offset()
const;
824 template <
typename Iterable>
825 inline void AddSum(
const Iterable& items);
848 template <
typename Iterable>
889 template <
typename LeftIterable,
typename RightIterable>
891 const RightIterable& right);
917 template <
typename LeftIterable,
typename RightIterable>
919 const RightIterable& right);
936 inline const ModelStorage*
storage()
const;
938#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
939 static thread_local int num_calls_default_constructor_;
940 static thread_local int num_calls_copy_constructor_;
941 static thread_local int num_calls_move_constructor_;
942 static thread_local int num_calls_initializer_list_constructor_;
943 static thread_local int num_calls_linear_expression_constructor_;
945 static void ResetCounters();
950 friend std::ostream&
operator<<(std::ostream& ostr,
955 inline void SetOrCheckStorage(
const ModelStorage*
storage);
961 const ModelStorage* storage_ =
nullptr;
964 double offset_ = 0.0;
1272 : storage_(storage), id_(id) {
1273 DCHECK(storage !=
nullptr);
1283 return storage_->variable_lower_bound(id_);
1287 return storage_->variable_upper_bound(id_);
1293 if (
storage()->has_variable(id_)) {
1294 return storage_->variable_name(id_);
1296 return "[variable deleted from model]";
1299template <
typename H>
1301 return H::combine(std::move(h), variable.id_.value(), variable.storage_);
1308 ostr <<
"__var#" << variable.
id() <<
"__";
1316 return LinearExpression({LinearTerm(*
this, -1.0)}, 0.0);
1351 return LinearTerm(std::move(variable),
coefficient);
1371void LinearExpression::SetOrCheckStorage(
const ModelStorage*
const storage) {
1373 if (storage_ ==
nullptr) {
1381 : storage_(std::exchange(other.storage_,
nullptr)),
1382 terms_(std::move(other.terms_)),
1383 offset_(std::exchange(other.offset_, 0.0)) {
1384 other.terms_.clear();
1385#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1386 ++num_calls_move_constructor_;
1392 storage_ = std::exchange(other.storage_,
nullptr);
1393 terms_ = std::move(other.terms_);
1394 other.terms_.clear();
1395 offset_ = std::exchange(other.offset_, 0.0);
1400 const double offset)
1402#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1403 ++num_calls_initializer_list_constructor_;
1405 for (
const auto& term :
terms) {
1406 SetOrCheckStorage(term.variable.storage());
1409 terms_[term.variable] += term.coefficient;
1414 : LinearExpression({}, offset) {}
1417 : LinearExpression({LinearTerm(variable, 1.0)}, 0.0) {}
1420 : LinearExpression({term}, 0.0) {}
1422LinearExpression
operator-(LinearExpression expr) {
1423 expr.offset_ = -expr.offset_;
1424 for (
auto& term : expr.terms_) {
1425 term.second = -term.second;
1438LinearExpression
operator+(
const Variable lhs,
const Variable rhs) {
1439 return LinearTerm(lhs, 1.0) + LinearTerm(rhs, 1.0);
1442LinearExpression
operator+(
const LinearTerm& lhs,
const double rhs) {
1443 return LinearExpression({lhs}, rhs);
1446LinearExpression
operator+(
const double lhs,
const LinearTerm& rhs) {
1447 return LinearExpression({rhs}, lhs);
1450LinearExpression
operator+(
const LinearTerm& lhs,
const Variable rhs) {
1451 return lhs + LinearTerm(rhs, 1.0);
1454LinearExpression
operator+(
const Variable lhs,
const LinearTerm& rhs) {
1455 return LinearTerm(lhs, 1.0) + rhs;
1458LinearExpression
operator+(
const LinearTerm& lhs,
const LinearTerm& rhs) {
1459 return LinearExpression({lhs, rhs}, 0);
1462LinearExpression
operator+(LinearExpression lhs,
const double rhs) {
1467LinearExpression
operator+(
const double lhs, LinearExpression rhs) {
1473 return std::move(lhs) +
LinearTerm(rhs, 1.0);
1476LinearExpression
operator+(
const Variable lhs, LinearExpression rhs) {
1480LinearExpression
operator+(LinearExpression lhs,
const LinearTerm& rhs) {
1485LinearExpression
operator+(LinearTerm lhs, LinearExpression rhs) {
1499LinearExpression
operator-(
const double lhs,
const Variable rhs) {
1503LinearExpression
operator-(
const Variable lhs,
const Variable rhs) {
1504 return LinearTerm(lhs, 1.0) - LinearTerm(rhs, 1.0);
1507LinearExpression
operator-(
const LinearTerm& lhs,
const double rhs) {
1508 return LinearExpression({lhs}, -rhs);
1511LinearExpression
operator-(
const double lhs,
const LinearTerm& rhs) {
1512 return LinearExpression({-rhs}, lhs);
1515LinearExpression
operator-(
const LinearTerm& lhs,
const Variable rhs) {
1516 return lhs - LinearTerm(rhs, 1.0);
1519LinearExpression
operator-(
const Variable lhs,
const LinearTerm& rhs) {
1520 return LinearTerm(lhs, 1.0) - rhs;
1523LinearExpression
operator-(
const LinearTerm& lhs,
const LinearTerm& rhs) {
1524 return LinearExpression({lhs, -rhs}, 0);
1527LinearExpression
operator-(LinearExpression lhs,
const double rhs) {
1532LinearExpression
operator-(
const double lhs, LinearExpression rhs) {
1533 auto ret = -std::move(rhs);
1539 return std::move(lhs) -
LinearTerm(rhs, 1.0);
1543 return LinearTerm(lhs, 1.0) - std::move(rhs);
1546LinearExpression
operator-(LinearExpression lhs,
const LinearTerm& rhs) {
1551LinearExpression
operator-(LinearTerm lhs, LinearExpression rhs) {
1552 auto ret = -std::move(rhs);
1581 if (!other.terms_.empty()) {
1583 for (
const auto& [v, coeff] : other.terms_) {
1587 offset_ += other.offset_;
1598 SetOrCheckStorage(variable.storage());
1599 return *
this += LinearTerm(variable, 1.0);
1609 if (!other.terms_.empty()) {
1610 SetOrCheckStorage(other.
storage());
1611 for (
const auto& [v, coeff] : other.terms_) {
1615 offset_ -= other.offset_;
1626 SetOrCheckStorage(variable.storage());
1627 return *
this -= LinearTerm(variable, 1.0);
1637 for (
auto& term : terms_) {
1638 term.second *=
value;
1645 for (
auto& term : terms_) {
1646 term.second /=
value;
1651template <
typename Iterable>
1653 for (
const auto& item : items) {
1658template <
typename Iterable>
1665template <
typename Iterable>
1672template <
typename LeftIterable,
typename RightIterable,
typename Expression>
1673void AddInnerProduct(
const LeftIterable& left,
const RightIterable& right,
1677 auto l = begin(left);
1678 auto r = begin(right);
1679 const auto l_end =
end(left);
1680 const auto r_end =
end(right);
1681 for (; l != l_end && r != r_end; ++l, ++r) {
1682 expr += (*l) * (*r);
1685 <<
"left had more elements than right, sizes should be equal";
1687 <<
"right had more elements than left, sizes should be equal";
1692template <
typename LeftIterable,
typename RightIterable>
1694 const RightIterable& right) {
1698template <
typename LeftIterable,
typename RightIterable>
1700 const RightIterable& right) {
1706template <
typename LeftIterable,
typename RightIterable>
1708 const RightIterable& right) {
1725 : lhs(
std::move(lhs)), rhs(
std::move(rhs)) {}
1727inline VariablesEquality::operator bool()
const {
1728 return lhs.
typed_id() == rhs.typed_id() && lhs.storage() == rhs.storage();
1733internal::VariablesEquality
operator==(
const Variable& lhs,
1734 const Variable& rhs) {
1735 return internal::VariablesEquality(lhs, rhs);
1739 return !(lhs == rhs);
1748LowerBoundedLinearExpression::LowerBoundedLinearExpression(
1752UpperBoundedLinearExpression::UpperBoundedLinearExpression(
1753 LinearExpression expression,
const double upper_bound)
1756BoundedLinearExpression::BoundedLinearExpression(LinearExpression expression,
1759 : expression(
std::move(expression)),
1763BoundedLinearExpression::BoundedLinearExpression(
1765 : expression({{eq.
lhs, 1.0}, {eq.
rhs, -1.0}}, 0.0),
1771 : expression(
std::move(lb_expression.expression)),
1777 : expression(
std::move(ub_expression.expression)),
1790 const double constant) {
1800 const double constant) {
1810 const double constant) {
1811 return LinearTerm(variable, 1.0) >= constant;
1816 return constant <=
LinearTerm(variable, 1.0);
1820 const double constant) {
1830 const double constant) {
1840 const double constant) {
1841 return LinearTerm(variable, 1.0) <= constant;
1846 return constant >=
LinearTerm(variable, 1.0);
1856BoundedLinearExpression
operator>=(
const double lhs,
1857 LowerBoundedLinearExpression rhs) {
1881 std::move(lhs), -std::numeric_limits<double>::infinity(),
1889 std::move(lhs), 0.0,
1890 std::numeric_limits<double>::infinity());
1893BoundedLinearExpression
operator<=(LinearExpression lhs,
1894 const LinearTerm& rhs) {
1896 return BoundedLinearExpression(
1897 std::move(lhs), -std::numeric_limits<double>::infinity(),
1901BoundedLinearExpression
operator>=(LinearExpression lhs,
1902 const LinearTerm& rhs) {
1904 return BoundedLinearExpression(
1905 std::move(lhs), 0.0,
1906 std::numeric_limits<double>::infinity());
1909BoundedLinearExpression
operator<=(
const LinearTerm& lhs,
1910 LinearExpression rhs) {
1912 return BoundedLinearExpression(
1913 std::move(rhs), 0.0,
1914 std::numeric_limits<double>::infinity());
1917BoundedLinearExpression
operator>=(
const LinearTerm& lhs,
1918 LinearExpression rhs) {
1920 return BoundedLinearExpression(
1921 std::move(rhs), -std::numeric_limits<double>::infinity(),
1925BoundedLinearExpression
operator<=(LinearExpression lhs,
const Variable rhs) {
1926 return std::move(lhs) <= LinearTerm(rhs, 1.0);
1929BoundedLinearExpression
operator>=(LinearExpression lhs,
const Variable rhs) {
1930 return std::move(lhs) >= LinearTerm(rhs, 1.0);
1933BoundedLinearExpression
operator<=(
const Variable lhs, LinearExpression rhs) {
1934 return LinearTerm(lhs, 1.0) <= std::move(rhs);
1937BoundedLinearExpression
operator>=(
const Variable lhs, LinearExpression rhs) {
1938 return LinearTerm(lhs, 1.0) >= std::move(rhs);
1941BoundedLinearExpression
operator<=(
const LinearTerm& lhs,
1942 const LinearTerm& rhs) {
1945 -std::numeric_limits<double>::infinity(),
1949BoundedLinearExpression
operator>=(
const LinearTerm& lhs,
1950 const LinearTerm& rhs) {
1953 std::numeric_limits<double>::infinity());
1960BoundedLinearExpression
operator>=(
const LinearTerm& lhs,
const Variable rhs) {
1961 return lhs >= LinearTerm(rhs, 1.0);
1968BoundedLinearExpression
operator>=(
const Variable lhs,
const LinearTerm& rhs) {
1969 return LinearTerm(lhs, 1.0) >= rhs;
1972BoundedLinearExpression
operator<=(
const Variable lhs,
const Variable rhs) {
1973 return LinearTerm(lhs, 1.0) <= LinearTerm(rhs, 1.0);
1976BoundedLinearExpression
operator>=(
const Variable lhs,
const Variable rhs) {
1977 return LinearTerm(lhs, 1.0) >= LinearTerm(rhs, 1.0);
1980BoundedLinearExpression
operator==(LinearExpression lhs,
1981 const LinearExpression& rhs) {
2002 return std::move(lhs) ==
LinearTerm(rhs, 1.0);
2005BoundedLinearExpression
operator==(
const Variable lhs, LinearExpression rhs) {
2006 return LinearTerm(lhs, 1.0) == std::move(rhs);
2021BoundedLinearExpression
operator==(
const LinearTerm& lhs,
2022 const LinearTerm& rhs) {
2028BoundedLinearExpression
operator==(
const LinearTerm& lhs,
const Variable rhs) {
2032BoundedLinearExpression
operator==(
const Variable lhs,
const LinearTerm& rhs) {
2033 return LinearTerm(lhs, 1.0) == rhs;
2041BoundedLinearExpression
operator==(
const double lhs,
const LinearTerm& rhs) {
2060 : storage_(storage), variable_ids_(id) {
2061 if (variable_ids_.first > variable_ids_.second) {
2064 swap(variable_ids_.first, variable_ids_.second);
2069 const Variable second_variable)
2070 : QuadraticTermKey(first_variable.storage(), {first_variable.typed_id(),
2071 second_variable.typed_id()}) {
2072 CHECK_EQ(first_variable.storage(), second_variable.storage())
2073 << internal::kObjectsFromOtherModelStorage;
2078const ModelStorage* QuadraticTermKey::storage()
const {
return storage_; }
2080template <
typename H>
2082 return H::combine(std::move(h), key.typed_id().first.value(),
2083 key.typed_id().second.value(), key.storage());
2097 return !(lhs == rhs);
2104QuadraticTerm::QuadraticTerm(
Variable first_variable,
Variable second_variable,
2106 : first_variable_(
std::move(first_variable)),
2107 second_variable_(
std::move(second_variable)),
2109 CHECK_EQ(first_variable_.storage(), second_variable_.storage())
2110 << internal::kObjectsFromOtherModelStorage;
2113double QuadraticTerm::coefficient()
const {
return coefficient_; }
2114Variable QuadraticTerm::first_variable()
const {
return first_variable_; }
2115Variable QuadraticTerm::second_variable()
const {
return second_variable_; }
2117QuadraticTermKey QuadraticTerm::GetKey()
const {
2118 return QuadraticTermKey(
2119 first_variable_.storage(),
2120 std::make_pair(first_variable_.typed_id(), second_variable_.typed_id()));
2127void QuadraticExpression::SetOrCheckStorage(
const ModelStorage*
const storage) {
2128 CHECK(storage !=
nullptr) << internal::kKeyHasNullModelStorage;
2129 if (storage_ ==
nullptr) {
2133 CHECK_EQ(storage, storage_) << internal::kObjectsFromOtherModelStorage;
2137 : storage_(std::exchange(other.storage_,
nullptr)),
2138 quadratic_terms_(std::move(other.quadratic_terms_)),
2139 linear_terms_(std::move(other.linear_terms_)),
2140 offset_(std::exchange(other.offset_, 0.0)) {
2141 other.quadratic_terms_.clear();
2142 other.linear_terms_.clear();
2143#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2144 ++num_calls_move_constructor_;
2150 storage_ = std::exchange(other.storage_,
nullptr);
2151 quadratic_terms_ = std::move(other.quadratic_terms_);
2152 other.quadratic_terms_.clear();
2153 linear_terms_ = std::move(other.linear_terms_);
2154 other.linear_terms_.clear();
2155 offset_ = std::exchange(other.offset_, 0.0);
2159QuadraticExpression::QuadraticExpression(
2160 const std::initializer_list<QuadraticTerm> quadratic_terms,
2161 const std::initializer_list<LinearTerm> linear_terms,
const double offset)
2163#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2164 ++num_calls_initializer_list_constructor_;
2167 SetOrCheckStorage(term.variable.storage());
2168 linear_terms_[term.variable] += term.coefficient;
2172 SetOrCheckStorage(key.
storage());
2173 quadratic_terms_[key] += term.coefficient();
2178 : QuadraticExpression({}, {}, offset) {}
2184 : QuadraticExpression({}, {term}, 0.0) {}
2187 : storage_(
std::exchange(expr.storage_, nullptr)),
2188 linear_terms_(
std::move(expr.terms_)),
2189 offset_(
std::exchange(expr.offset_, 0.0)) {
2190#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
2191 ++num_calls_linear_expression_constructor_;
2196 : QuadraticExpression({term}, {}, 0.0) {}
2203 return linear_terms_;
2207 return quadratic_terms_;
2225QuadraticExpression
operator+(
const double lhs, QuadraticExpression rhs) {
2234QuadraticExpression
operator+(
const Variable lhs, QuadraticExpression rhs) {
2235 rhs += LinearTerm(lhs, 1.0);
2239QuadraticExpression
operator+(
const LinearTerm& lhs,
const QuadraticTerm& rhs) {
2240 return QuadraticExpression({rhs}, {lhs}, 0.0);
2254QuadraticExpression
operator+(
const LinearExpression& lhs,
2255 QuadraticExpression rhs) {
2260QuadraticExpression
operator+(
const QuadraticTerm& lhs,
const double rhs) {
2264QuadraticExpression
operator+(
const QuadraticTerm& lhs,
const Variable rhs) {
2268QuadraticExpression
operator+(
const QuadraticTerm& lhs,
const LinearTerm& rhs) {
2269 return QuadraticExpression({lhs}, {rhs}, 0.0);
2272QuadraticExpression
operator+(
const QuadraticTerm& lhs, LinearExpression rhs) {
2273 QuadraticExpression expr(std::move(rhs));
2278QuadraticExpression
operator+(
const QuadraticTerm& lhs,
2279 const QuadraticTerm& rhs) {
2280 return QuadraticExpression({lhs, rhs}, {}, 0.0);
2289QuadraticExpression
operator+(QuadraticExpression lhs,
const double rhs) {
2299QuadraticExpression
operator+(QuadraticExpression lhs,
const LinearTerm& rhs) {
2304QuadraticExpression
operator+(QuadraticExpression lhs,
2310QuadraticExpression
operator+(QuadraticExpression lhs,
2326 term.coefficient_ *= -1.0;
2331QuadraticExpression
operator-(QuadraticExpression expr) {
2332 expr.offset_ = -expr.offset_;
2333 for (
auto& term : expr.linear_terms_) {
2334 term.second = -term.second;
2336 for (
auto& term : expr.quadratic_terms_) {
2337 term.second = -term.second;
2342QuadraticExpression
operator-(
const double lhs,
const QuadraticTerm& rhs) {
2343 return QuadraticExpression({-rhs}, {}, lhs);
2346QuadraticExpression
operator-(
const double lhs, QuadraticExpression rhs) {
2347 auto expr = -std::move(rhs);
2356QuadraticExpression
operator-(
const Variable lhs, QuadraticExpression rhs) {
2357 return LinearTerm(lhs, 1.0) - std::move(rhs);
2360QuadraticExpression
operator-(
const LinearTerm& lhs,
const QuadraticTerm& rhs) {
2361 return QuadraticExpression({-rhs}, {lhs}, 0.0);
2365 auto expr = -std::move(rhs);
2370QuadraticExpression
operator-(LinearExpression lhs,
const QuadraticTerm& rhs) {
2371 QuadraticExpression expr(std::move(lhs));
2376QuadraticExpression
operator-(
const LinearExpression& lhs,
2377 QuadraticExpression rhs) {
2378 auto expr = -std::move(rhs);
2391QuadraticExpression
operator-(
const QuadraticTerm& lhs,
const LinearTerm& rhs) {
2395QuadraticExpression
operator-(
const QuadraticTerm& lhs, LinearExpression rhs) {
2396 QuadraticExpression expr(-std::move(rhs));
2401QuadraticExpression
operator-(
const QuadraticTerm& lhs,
2402 const QuadraticTerm& rhs) {
2403 return QuadraticExpression({lhs, -rhs}, {}, 0.0);
2437QuadraticExpression
operator-(QuadraticExpression lhs,
2438 const QuadraticTerm& rhs) {
2443QuadraticExpression
operator-(QuadraticExpression lhs,
2444 const QuadraticExpression& rhs) {
2452QuadraticTerm
operator*(
const double lhs, QuadraticTerm rhs) {
2453 rhs.coefficient_ *= lhs;
2457QuadraticExpression
operator*(
const double lhs, QuadraticExpression rhs) {
2462QuadraticTerm
operator*(Variable lhs, Variable rhs) {
2463 return QuadraticTerm(std::move(lhs), std::move(rhs), 1.0);
2471QuadraticExpression
operator*(Variable lhs,
const LinearExpression& rhs) {
2472 QuadraticExpression expr;
2473 for (
const auto& [
var, coeff] : rhs.terms()) {
2476 if (rhs.offset() != 0) {
2477 expr +=
LinearTerm(std::move(lhs), rhs.offset());
2482QuadraticTerm
operator*(LinearTerm lhs, Variable rhs) {
2483 return QuadraticTerm(std::move(lhs.variable), std::move(rhs),
2487QuadraticTerm
operator*(LinearTerm lhs, LinearTerm rhs) {
2489 lhs.coefficient * rhs.coefficient);
2492QuadraticExpression
operator*(LinearTerm lhs,
const LinearExpression& rhs) {
2494 for (
const auto& [
var, coeff] : rhs.terms()) {
2497 if (rhs.offset() != 0) {
2498 expr += LinearTerm(std::move(lhs.variable), lhs.coefficient * rhs.offset());
2503QuadraticExpression
operator*(
const LinearExpression& lhs, Variable rhs) {
2505 for (
const auto& [
var, coeff] : lhs.terms()) {
2508 if (lhs.offset() != 0) {
2516 for (
const auto& [
var, coeff] : lhs.
terms()) {
2529 for (
const auto& [
var, coeff] : lhs.
terms()) {
2534 for (
const auto& [
var, coeff] : rhs.
terms()) {
2538 for (
const auto& [lhs_var, lhs_coeff] : lhs.
terms()) {
2539 for (
const auto& [rhs_var, rhs_coeff] : rhs.
terms()) {
2540 expr += QuadraticTerm(lhs_var, rhs_var, lhs_coeff * rhs_coeff);
2548 lhs.coefficient_ *= rhs;
2552QuadraticExpression
operator*(QuadraticExpression lhs,
const double rhs) {
2560QuadraticTerm
operator/(QuadraticTerm lhs,
const double rhs) {
2561 lhs.coefficient_ /= rhs;
2565QuadraticExpression
operator/(QuadraticExpression lhs,
const double rhs) {
2585 SetOrCheckStorage(variable.
storage());
2586 linear_terms_[variable] += 1;
2591 SetOrCheckStorage(term.variable.storage());
2592 linear_terms_[term.variable] += term.coefficient;
2597 const LinearExpression& expr) {
2598 offset_ += expr.offset();
2600 if (!expr.terms().empty()) {
2601 SetOrCheckStorage(expr.storage());
2602 for (
const auto& [v, coeff] : expr.terms()) {
2603 linear_terms_[v] += coeff;
2612 SetOrCheckStorage(key.
storage());
2619 offset_ += expr.
offset();
2622 SetOrCheckStorage(expr.
storage());
2624 linear_terms_[v] += coeff;
2627 quadratic_terms_[k] += coeff;
2640 SetOrCheckStorage(variable.
storage());
2641 linear_terms_[variable] -= 1;
2652 const LinearExpression& expr) {
2653 offset_ -= expr.offset();
2655 if (!expr.terms().empty()) {
2656 SetOrCheckStorage(expr.storage());
2657 for (
const auto& [v, coeff] : expr.terms()) {
2658 linear_terms_[v] -= coeff;
2667 SetOrCheckStorage(key.
storage());
2674 offset_ -= expr.
offset();
2677 SetOrCheckStorage(expr.
storage());
2679 linear_terms_[v] -= coeff;
2682 quadratic_terms_[k] -= coeff;
2689 coefficient_ *=
value;
2697 for (
auto& term : linear_terms_) {
2698 term.second *=
value;
2700 for (
auto& term : quadratic_terms_) {
2701 term.second *=
value;
2709 coefficient_ /=
value;
2717 for (
auto& term : linear_terms_) {
2718 term.second /=
value;
2720 for (
auto& term : quadratic_terms_) {
2721 term.second /=
value;
2728template <
typename Iterable>
2730 for (
const auto& item : items) {
2735template <
typename Iterable>
2742template <
typename LeftIterable,
typename RightIterable>
2744 const RightIterable& right) {
2748template <
typename LeftIterable,
typename RightIterable>
2750 const LeftIterable& left,
const RightIterable& right) {
2766 LowerBoundedLinearExpression lb_expression)
2767 : expression(
std::move(lb_expression.expression)),
2775 : expression(
std::move(ub_expression.expression)),
2781 : expression(
std::move(expression)),
2785 internal::VariablesEquality var_equality)
2787 expression += var_equality.lhs;
2788 expression -= var_equality.rhs;
2792 : expression(
std::move(lb_expression.expression)),
2797 : expression(
std::move(ub_expression.expression)),
2802 : expression(
std::move(bounded_expression.expression)),
2807 : expression(
std::move(lb_expression.expression)),
2812 : expression(
std::move(ub_expression.expression)),
2853UpperBoundedQuadraticExpression
operator<=(
const QuadraticTerm lhs,
2863BoundedQuadraticExpression
operator>=(
const double lhs,
2864 LowerBoundedQuadraticExpression rhs) {
2865 return BoundedQuadraticExpression(std::move(rhs.expression), rhs.lower_bound,
2868BoundedQuadraticExpression
operator<=(LowerBoundedQuadraticExpression lhs,
2870 return BoundedQuadraticExpression(std::move(lhs.expression), lhs.lower_bound,
2873BoundedQuadraticExpression
operator<=(
const double lhs,
2874 UpperBoundedQuadraticExpression rhs) {
2883 std::numeric_limits<double>::infinity());
2885BoundedQuadraticExpression
operator>=(QuadraticExpression lhs,
2886 const QuadraticTerm rhs) {
2888 return BoundedQuadraticExpression(std::move(lhs), 0,
2889 std::numeric_limits<double>::infinity());
2891BoundedQuadraticExpression
operator>=(QuadraticExpression lhs,
2892 const LinearExpression& rhs) {
2895 std::numeric_limits<double>::infinity());
2897BoundedQuadraticExpression
operator>=(QuadraticExpression lhs,
2898 const LinearTerm rhs) {
2901 std::numeric_limits<double>::infinity());
2903BoundedQuadraticExpression
operator>=(QuadraticExpression lhs,
2904 const Variable rhs) {
2907 std::numeric_limits<double>::infinity());
2909BoundedQuadraticExpression
operator<=(QuadraticExpression lhs,
2910 const QuadraticExpression& rhs) {
2913 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2915BoundedQuadraticExpression
operator<=(QuadraticExpression lhs,
2916 const QuadraticTerm rhs) {
2919 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2921BoundedQuadraticExpression
operator<=(QuadraticExpression lhs,
2922 const LinearExpression& rhs) {
2925 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2927BoundedQuadraticExpression
operator<=(QuadraticExpression lhs,
2928 const LinearTerm rhs) {
2931 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2933BoundedQuadraticExpression
operator<=(QuadraticExpression lhs,
2934 const Variable rhs) {
2937 std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
2939BoundedQuadraticExpression
operator==(QuadraticExpression lhs,
2940 const QuadraticExpression& rhs) {
2944BoundedQuadraticExpression
operator==(QuadraticExpression lhs,
2945 const QuadraticTerm rhs) {
2949BoundedQuadraticExpression
operator==(QuadraticExpression lhs,
2950 const LinearExpression& rhs) {
2952 return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2954BoundedQuadraticExpression
operator==(QuadraticExpression lhs,
2955 const LinearTerm rhs) {
2957 return BoundedQuadraticExpression(std::move(lhs), 0, 0);
2964BoundedQuadraticExpression
operator==(QuadraticExpression lhs,
2974 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
2976BoundedQuadraticExpression
operator>=(
const QuadraticTerm lhs,
2977 const QuadraticTerm rhs) {
2978 return BoundedQuadraticExpression(
2979 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2981BoundedQuadraticExpression
operator>=(
const QuadraticTerm lhs,
2982 LinearExpression rhs) {
2983 return BoundedQuadraticExpression(
2984 std::move(rhs) - lhs, -std::numeric_limits<double>::infinity(), 0);
2986BoundedQuadraticExpression
operator>=(
const QuadraticTerm lhs,
2987 const LinearTerm rhs) {
2988 return BoundedQuadraticExpression(
2989 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
2991BoundedQuadraticExpression
operator>=(
const QuadraticTerm lhs,
2992 const Variable rhs) {
2993 return BoundedQuadraticExpression(
2994 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
3000 std::numeric_limits<double>::infinity());
3005 std::numeric_limits<double>::infinity());
3010 std::numeric_limits<double>::infinity());
3015 std::numeric_limits<double>::infinity());
3020 std::numeric_limits<double>::infinity());
3027BoundedQuadraticExpression
operator==(
const QuadraticTerm lhs,
3031BoundedQuadraticExpression
operator==(
const QuadraticTerm lhs,
3032 LinearExpression rhs) {
3035BoundedQuadraticExpression
operator==(
const QuadraticTerm lhs,
3036 const LinearTerm rhs) {
3037 return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3039BoundedQuadraticExpression
operator==(
const QuadraticTerm lhs,
3040 const Variable rhs) {
3041 return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3052 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
3054BoundedQuadraticExpression
operator>=(LinearExpression lhs,
3055 const QuadraticTerm rhs) {
3056 return BoundedQuadraticExpression(
3057 rhs - std::move(lhs), -std::numeric_limits<double>::infinity(), 0);
3059BoundedQuadraticExpression
operator<=(
const LinearExpression& lhs,
3060 QuadraticExpression rhs) {
3063 std::numeric_limits<double>::infinity());
3068 std::numeric_limits<double>::infinity());
3070BoundedQuadraticExpression
operator==(
const LinearExpression& lhs,
3071 QuadraticExpression rhs) {
3073 return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3075BoundedQuadraticExpression
operator==(LinearExpression lhs,
3076 const QuadraticTerm rhs) {
3077 return BoundedQuadraticExpression(rhs - std::move(lhs), 0, 0);
3084 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
3086BoundedQuadraticExpression
operator>=(
const LinearTerm lhs,
3087 const QuadraticTerm rhs) {
3088 return BoundedQuadraticExpression(
3089 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
3095 std::numeric_limits<double>::infinity());
3097BoundedQuadraticExpression
operator<=(
const LinearTerm lhs,
3098 const QuadraticTerm rhs) {
3099 return BoundedQuadraticExpression(rhs - lhs, 0,
3100 std::numeric_limits<double>::infinity());
3102BoundedQuadraticExpression
operator==(
const LinearTerm lhs,
3103 QuadraticExpression rhs) {
3105 return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3107BoundedQuadraticExpression
operator==(
const LinearTerm lhs,
3108 const QuadraticTerm rhs) {
3109 return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3116 std::move(rhs), -std::numeric_limits<double>::infinity(), 0);
3118BoundedQuadraticExpression
operator>=(
const Variable lhs,
3119 const QuadraticTerm rhs) {
3120 return BoundedQuadraticExpression(
3121 rhs - lhs, -std::numeric_limits<double>::infinity(), 0);
3127 std::numeric_limits<double>::infinity());
3129BoundedQuadraticExpression
operator<=(
const Variable lhs,
3130 const QuadraticTerm rhs) {
3131 return BoundedQuadraticExpression(rhs - lhs, 0,
3132 std::numeric_limits<double>::infinity());
3134BoundedQuadraticExpression
operator==(
const Variable lhs,
3135 QuadraticExpression rhs) {
3137 return BoundedQuadraticExpression(std::move(rhs), 0, 0);
3139BoundedQuadraticExpression
operator==(
const Variable lhs,
3140 const QuadraticTerm rhs) {
3141 return BoundedQuadraticExpression(rhs - lhs, 0, 0);
3150BoundedQuadraticExpression
operator==(
const double lhs,
3151 const QuadraticTerm rhs) {
3152 return BoundedQuadraticExpression(rhs - lhs, 0, 0);
const ModelStorage * storage() const
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
static LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
LinearExpression & operator*=(double value)
friend LinearExpression operator-(LinearExpression expr)
double Evaluate(const VariableMap< double > &variable_values) const
const VariableMap< double > & terms() const
Returns the terms in this expression.
void AddSum(const Iterable &items)
}
LinearExpression & operator-=(const LinearExpression &other)
LinearExpression()=default
friend std::ostream & operator<<(std::ostream &ostr, const LinearExpression &expression)
LinearExpression & operator+=(const LinearExpression &other)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
LinearExpression & operator=(const LinearExpression &other)=default
LinearExpression(const LinearExpression &other)=default
static LinearExpression Sum(const Iterable &items)
LinearExpression & operator/=(double value)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const QuadraticTermMap< double > & quadratic_terms() const
QuadraticExpression & operator-=(double value)
static RightIterable QuadraticExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
friend std::ostream & operator<<(std::ostream &ostr, const QuadraticExpression &expr)
const ModelStorage * storage() const
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
void AddSum(const Iterable &items)
}
const VariableMap< double > & linear_terms() const
QuadraticExpression(const QuadraticExpression &other)=default
static QuadraticExpression Sum(const Iterable &items)
QuadraticExpression & operator*=(double value)
QuadraticExpression & operator/=(double value)
double Evaluate(const VariableMap< double > &variable_values) const
QuadraticExpression()=default
friend QuadraticExpression operator-(QuadraticExpression expr)
QuadraticExpression & operator+=(double value)
QuadraticExpression & operator=(const QuadraticExpression &other)=default
QuadraticTermKey(const ModelStorage *storage, QuadraticProductId id)
Variable first() const
Returns the Variable with the smallest id.
QuadraticProductId typed_id() const
const ModelStorage * storage() const
QuadraticProductId IdType
Variable second() const
Returns the Variable the largest id.
friend H AbslHashValue(H h, const QuadraticTermKey &key)
friend QuadraticTerm operator*(double lhs, QuadraticTerm rhs)
-------------------------— Multiplication (*) --------------------------—
friend QuadraticTerm operator-(QuadraticTerm term)
------------------------— Subtraction (-) ------------------------------—
double coefficient() const
QuadraticTerm & operator/=(double value)
QuadraticTerm & operator*=(double value)
Variable first_variable() const
QuadraticTermKey GetKey() const
This is useful for working with IdMaps.
friend QuadraticTerm operator/(QuadraticTerm lhs, double rhs)
----------------------------— Division (/) -----------------------------—
Variable second_variable() const
double lower_bound() const
VariableId typed_id() const
friend std::ostream & operator<<(std::ostream &ostr, const Variable &variable)
double upper_bound() const
VariableId IdType
The typed integer used for ids.
absl::string_view name() const
const ModelStorage * storage() const
LinearExpression operator-() const
friend H AbslHashValue(H h, const Variable &variable)
Variable(const ModelStorage *storage, VariableId id)
const std::string name
A name for logging purposes.
constexpr absl::string_view kKeyHasNullModelStorage
The CHECK message to use when a KeyType::storage() is nullptr.
constexpr absl::string_view kObjectsFromOtherModelStorage
void AddInnerProduct(const LeftIterable &left, const RightIterable &right, Expression &expr)
absl::flat_hash_map< Variable, V > VariableMap
LinearExpression Sum(const Iterable &items)
LinearExpression operator+(Variable lhs, double rhs)
absl::flat_hash_map< QuadraticTermKey, V > QuadraticTermMap
LinearTerm operator*(double coefficient, LinearTerm term)
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
bool operator==(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
bool operator!=(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
LowerBoundedLinearExpression operator>=(LinearExpression expression, double constant)
RightIterable LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
LowerBoundedLinearExpression operator<=(double constant, LinearExpression expression)
LinearTerm operator/(LinearTerm term, double coefficient)
LinearExpression operator-(LinearExpression expr)
std::pair< VariableId, VariableId > QuadraticProductId
Id type used for quadratic terms, i.e. products of two variables.
H AbslHashValue(H h, const IndicatorConstraint &constraint)
In SWIG mode, we don't want anything besides these top-level includes.
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
H AbslHashValue(H h, const StrongIndex< StrongIndexName > &i)
– ABSL HASHING SUPPORT --------------------------------------------------—
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
std::optional< int64_t > end
A LinearExpression with upper and lower bounds.
BoundedLinearExpression(LinearExpression expression, double lower_bound, double upper_bound)
double upper_bound_minus_offset() const
LinearExpression expression
double lower_bound_minus_offset() const
A QuadraticExpression with upper and lower bounds.
BoundedQuadraticExpression(QuadraticExpression expression, double lower_bound, double upper_bound)
double upper_bound_minus_offset() const
QuadraticExpression expression
double lower_bound_minus_offset() const
A term in an sum of variables multiplied by coefficients.
LinearTerm(Variable variable, double coefficient)
LinearTerm & operator*=(double d)
LinearTerm operator-() const
LinearTerm & operator/=(double d)
A LinearExpression with a lower bound.
LinearExpression expression
LowerBoundedLinearExpression(LinearExpression expression, double lower_bound)
A QuadraticExpression with a lower bound.
LowerBoundedQuadraticExpression(QuadraticExpression expression, double lower_bound)
QuadraticExpression expression
A LinearExpression with an upper bound.
UpperBoundedLinearExpression(LinearExpression expression, double upper_bound)
LinearExpression expression
A QuadraticExpression with an upper bound.
UpperBoundedQuadraticExpression(QuadraticExpression expression, double upper_bound)
QuadraticExpression expression
VariablesEquality(Variable lhs, Variable rhs)