89#ifndef OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
90#define OR_TOOLS_MATH_OPT_CPP_VARIABLE_AND_EXPRESSIONS_H_
94#include <initializer_list>
100#include "absl/container/flat_hash_map.h"
111class LinearExpression;
127 inline int64_t
id()
const;
135 inline const std::string&
name()
const;
137 template <
typename H>
197#ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
251 template <
typename Iterable>
252 inline void AddSum(
const Iterable& items);
290 template <
typename LeftIterable,
typename RightIterable>
292 const RightIterable& right);
296 inline double offset()
const;
313 inline const absl::flat_hash_map<VariableId, double>&
raw_terms()
const;
315#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
316 static thread_local int num_calls_default_constructor_;
317 static thread_local int num_calls_copy_constructor_;
318 static thread_local int num_calls_move_constructor_;
319 static thread_local int num_calls_initializer_list_constructor_;
321 static void ResetCounters();
326 friend std::ostream&
operator<<(std::ostream& ostr,
331 double offset_ = 0.0;
354template <
typename Iterable>
380template <
typename LeftIterable,
typename RightIterable>
382 const RightIterable& right);
445 inline operator bool()
const;
623 template <
typename H>
698#ifndef MATH_OPT_USE_EXPRESSION_COUNTERS
717 inline double offset()
const;
723 inline const absl::flat_hash_map<QuadraticProductId, double>&
758#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
759 static thread_local int num_calls_default_constructor_;
760 static thread_local int num_calls_copy_constructor_;
761 static thread_local int num_calls_move_constructor_;
762 static thread_local int num_calls_initializer_list_constructor_;
763 static thread_local int num_calls_linear_expression_constructor_;
765 static void ResetCounters();
770 friend std::ostream&
operator<<(std::ostream& ostr,
772 inline void CheckModelsAgree();
776 double offset_ = 0.0;
883 : storage_(storage), id_(id) {
909 return H::combine(std::move(h), variable.id_.value(), variable.storage_);
914 const std::string&
name = variable.
name();
916 ostr <<
"__var#" << variable.
id() <<
"__";
982#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
983 ++num_calls_initializer_list_constructor_;
985 for (
const auto& term :
terms) {
988 terms_[term.variable] += term.coefficient;
1002 expr.offset_ = -expr.offset_;
1003 for (
auto term : expr.terms_) {
1004 term.second = -term.second;
1052 return std::move(lhs) +
LinearTerm(rhs, 1.0);
1056 return LinearTerm(lhs, 1.0) + std::move(rhs);
1112 auto ret = -std::move(rhs);
1118 return std::move(lhs) -
LinearTerm(rhs, 1.0);
1122 return LinearTerm(lhs, 1.0) - std::move(rhs);
1131 auto ret = -std::move(rhs);
1157 terms_.Add(other.terms_);
1158 offset_ += other.offset_;
1177 terms_.Subtract(other.terms_);
1178 offset_ -= other.offset_;
1198 for (
auto term : terms_) {
1199 term.second *=
value;
1206 for (
auto term : terms_) {
1207 term.second /=
value;
1212template <
typename Iterable>
1214 for (
const auto& item : items) {
1219template <
typename Iterable>
1226template <
typename LeftIterable,
typename RightIterable>
1228 const RightIterable& right) {
1231 auto l = begin(left);
1232 auto r = begin(right);
1233 auto l_end =
end(left);
1234 auto r_end =
end(right);
1235 for (; l != l_end && r != r_end; ++l, ++r) {
1236 *
this += (*l) * (*r);
1239 <<
"left had more elements than right, sizes should be equal";
1241 <<
"right had more elements than left, sizes should be equal";
1244template <
typename LeftIterable,
typename RightIterable>
1246 const RightIterable& right) {
1257 return terms_.storage();
1262 return terms_.raw_map();
1272 : lhs(
std::move(lhs)), rhs(
std::move(rhs)) {}
1274inline VariablesEquality::operator bool()
const {
1275 return lhs.
typed_id() == rhs.typed_id() && lhs.storage() == rhs.storage();
1286 return !(lhs == rhs);
1306 : expression(
std::move(expression)),
1312 : expression({{eq.
lhs, 1.0}, {eq.
rhs, -1.0}}, 0.0),
1318 : expression(
std::move(lb_expression.expression)),
1324 : expression(
std::move(ub_expression.expression)),
1428 std::move(lhs), -std::numeric_limits<double>::infinity(),
1436 std::move(lhs), 0.0,
1437 std::numeric_limits<double>::infinity());
1444 std::move(lhs), -std::numeric_limits<double>::infinity(),
1452 std::move(lhs), 0.0,
1453 std::numeric_limits<double>::infinity());
1460 std::move(rhs), 0.0,
1461 std::numeric_limits<double>::infinity());
1468 std::move(rhs), -std::numeric_limits<double>::infinity(),
1473 return std::move(lhs) <=
LinearTerm(rhs, 1.0);
1477 return std::move(lhs) >=
LinearTerm(rhs, 1.0);
1481 return LinearTerm(lhs, 1.0) <= std::move(rhs);
1485 return LinearTerm(lhs, 1.0) >= std::move(rhs);
1492 -std::numeric_limits<double>::infinity(),
1500 std::numeric_limits<double>::infinity());
1549 return std::move(lhs) ==
LinearTerm(rhs, 1.0);
1553 return LinearTerm(lhs, 1.0) == std::move(rhs);
1607 : storage_(storage), variable_ids_(id) {
1608 if (variable_ids_.first > variable_ids_.second) {
1610 swap(variable_ids_.first, variable_ids_.second);
1618 CHECK_EQ(first_variable.storage(), second_variable.storage())
1626template <
typename H>
1628 return H::combine(std::move(h), key.
typed_id().first.value(),
1637 return !(lhs == rhs);
1646 : first_variable_(
std::move(first_variable)),
1647 second_variable_(
std::move(second_variable)),
1668 const std::initializer_list<QuadraticTerm> quadratic_terms,
1669 const std::initializer_list<LinearTerm> linear_terms,
const double offset)
1671#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1672 ++num_calls_initializer_list_constructor_;
1675 linear_terms_[term.variable] += term.coefficient;
1678 quadratic_terms_[term.GetKey()] += term.coefficient();
1693 : linear_terms_(
std::move(expr.terms_)),
1695#ifdef MATH_OPT_USE_EXPRESSION_COUNTERS
1696 ++num_calls_linear_expression_constructor_;
1703void QuadraticExpression::CheckModelsAgree() {
1704 const ModelStorage*
const quadratic_model = quadratic_terms_.storage();
1705 const ModelStorage*
const linear_model = linear_terms_.storage();
1706 if ((linear_model !=
nullptr) && (quadratic_model !=
nullptr) &&
1707 (quadratic_model != linear_model)) {
1723 return linear_terms_;
1727 return quadratic_terms_;
1730const absl::flat_hash_map<VariableId, double>&
1732 return linear_terms_.raw_map();
1735const absl::flat_hash_map<QuadraticProductId, double>&
1737 return quadratic_terms_.raw_map();
1856 term.coefficient_ *= -1.0;
1862 expr.offset_ = -expr.offset_;
1863 for (
auto term : expr.linear_terms_) {
1864 term.second = -term.second;
1866 for (
auto term : expr.quadratic_terms_) {
1867 term.second = -term.second;
1877 auto expr = -std::move(rhs);
1887 return LinearTerm(lhs, 1.0) - std::move(rhs);
1895 auto expr = -std::move(rhs);
1908 auto expr = -std::move(rhs);
1983 rhs.coefficient_ *= lhs;
2068 for (
const auto& [lhs_var, lhs_coeff] : lhs.
terms()) {
2069 for (
const auto& [rhs_var, rhs_coeff] : rhs.
terms()) {
2070 expr +=
QuadraticTerm(lhs_var, rhs_var, lhs_coeff * rhs_coeff);
2078 lhs.coefficient_ *= rhs;
2091 lhs.coefficient_ /= rhs;
2115 linear_terms_[variable] += 1;
2128 offset_ += expr.
offset();
2129 linear_terms_.Add(expr.
terms());
2143 offset_ += expr.
offset();
2157 linear_terms_[variable] -= 1;
2170 offset_ -= expr.
offset();
2171 linear_terms_.Subtract(expr.
terms());
2185 offset_ -= expr.
offset();
2193 coefficient_ *=
value;
2201 for (
auto term : linear_terms_) {
2202 term.second *=
value;
2204 for (
auto term : quadratic_terms_) {
2205 term.second *=
value;
2213 coefficient_ /=
value;
2221 for (
auto term : linear_terms_) {
2222 term.second /=
value;
2224 for (
auto term : quadratic_terms_) {
2225 term.second /=
value;
#define CHECK_EQ(val1, val2)
#define DCHECK(condition)
LinearExpression & operator+=(const LinearExpression &other)
LinearExpression & operator/=(double value)
double Evaluate(const VariableMap< double > &variable_values) const
double EvaluateWithDefaultZero(const VariableMap< double > &variable_values) const
friend LinearExpression operator-(LinearExpression expr)
LinearExpression & operator-=(const LinearExpression &other)
LinearExpression & operator*=(double value)
void AddInnerProduct(const LeftIterable &left, const RightIterable &right)
const absl::flat_hash_map< VariableId, double > & raw_terms() const
friend std::ostream & operator<<(std::ostream &ostr, const LinearExpression &expression)
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
friend std::ostream & operator<<(std::ostream &ostr, const QuadraticExpression &expr)
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
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)
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)
const std::string & name() const
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)
const ModelStorage * storage() const
VariableId typed_id() const
constexpr absl::string_view kObjectsFromOtherModelStorage
LowerBoundedLinearExpression operator>=(LinearExpression expression, double constant)
std::pair< VariableId, VariableId > QuadraticProductId
LinearExpression Sum(const Iterable &items)
std::ostream & operator<<(std::ostream &out, const E value)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
LinearExpression operator-(LinearExpression expr)
LinearExpression InnerProduct(const LeftIterable &left, const RightIterable &right)
LowerBoundedLinearExpression operator<=(double constant, LinearExpression expression)
bool operator==(const LinearConstraint &lhs, const LinearConstraint &rhs)
bool operator!=(const LinearConstraint &lhs, const LinearConstraint &rhs)
H AbslHashValue(H h, const LinearConstraint &linear_constraint)
LinearExpression operator+(Variable lhs, double rhs)
LinearTerm operator*(double coefficient, LinearTerm term)
LinearTerm operator/(LinearTerm term, double coefficient)
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
LinearTerm operator-() const
LinearTerm & operator/=(double d)
LinearTerm(Variable variable, double coefficient)
LinearTerm & operator*=(double d)
LinearExpression expression
LowerBoundedLinearExpression(LinearExpression expression, double lower_bound)
UpperBoundedLinearExpression(LinearExpression expression, double upper_bound)
LinearExpression expression
VariablesEquality(Variable lhs, Variable rhs)