25#include "absl/base/attributes.h"
26#include "absl/container/flat_hash_set.h"
27#include "absl/log/check.h"
28#include "absl/strings/str_cat.h"
29#include "absl/types/span.h"
41 if (coeff == 0)
return;
45 terms_.push_back({
var, coeff});
53 if (coeff == 0)
return;
58 terms_.push_back({expr.
var, coeff * expr.
coeff});
73 for (
int i = 0;
i < expr.
vars.size(); ++
i) {
76 terms_.push_back({expr.
vars[
i], expr.
coeffs[
i] * coeff});
81 offset_ += expr.
offset * coeff;
85 absl::Span<const LiteralValueValue> product) {
86 if (product.empty())
return true;
91 product_min = std::min(product_min, term.left_value * term.right_value);
95 IntegerValue coeff = term.left_value * term.right_value - product_min;
96 if (coeff == 0)
continue;
107 bool* is_quadratic) {
108 if (integer_trail->
IsFixed(left)) {
110 }
else if (integer_trail->
IsFixed(right)) {
113 const IntegerValue left_min = integer_trail->
LowerBound(left);
114 const IntegerValue right_min = integer_trail->
LowerBound(right);
119 if (is_quadratic !=
nullptr) *is_quadratic =
true;
129 DCHECK(encoder_ !=
nullptr);
131 bool view_is_direct =
true;
136 if (view_is_direct) {
170 const int shifted_size =
size - 3;
175 for (;
i < shifted_size;
i += 4) {
176 a0 +=
static_cast<double>(constraint.
coeffs[
i].value()) *
177 values[constraint.
vars[
i]];
178 a1 +=
static_cast<double>(constraint.
coeffs[
i + 1].value()) *
179 values[constraint.
vars[
i + 1]];
180 a2 +=
static_cast<double>(constraint.
coeffs[
i + 2].value()) *
181 values[constraint.
vars[
i + 2]];
182 a3 +=
static_cast<double>(constraint.
coeffs[
i + 3].value()) *
183 values[constraint.
vars[
i + 3]];
185 double activity = a0 + a1 + a2 + a3;
187 activity +=
static_cast<double>(constraint.
coeffs[
i].value()) *
188 values[constraint.
vars[
i]];
190 activity +=
static_cast<double>(constraint.
coeffs[
i + 1].value()) *
191 values[constraint.
vars[
i + 1]];
193 activity +=
static_cast<double>(constraint.
coeffs[
i + 2].value()) *
194 values[constraint.
vars[
i + 2]];
203 for (
int i = 0;
i <
ct.num_terms; ++
i) {
206 return std::sqrt(sum);
210 IntegerValue result(0);
211 for (
int i = 0;
i <
ct.num_terms; ++
i) {
221 double scalar_product = 0.0;
224 IntegerVariable var1 = ct1.
vars[index_1];
225 IntegerVariable var2 = ct2.
vars[index_2];
228 scalar_product +=
static_cast<double>(ct1.
coeffs[index_1].value()) *
229 static_cast<double>(ct2.
coeffs[index_2].value());
232 var1 = ct1.
vars[index_1];
233 var2 = ct2.
vars[index_2];
234 }
else if (var1 > var2) {
236 var2 = ct2.
vars[index_2];
239 var1 = ct1.
vars[index_1];
242 return scalar_product;
248IntegerValue ComputeGcd(absl::Span<const IntegerValue> values) {
249 if (values.empty())
return IntegerValue(1);
251 for (
const IntegerValue
value : values) {
255 if (gcd < 0)
return IntegerValue(1);
256 return IntegerValue(gcd);
263 const IntegerValue gcd = ComputeGcd(
264 {constraint->
coeffs.get(),
static_cast<size_t>(constraint->
num_terms)});
265 if (gcd == 1)
return;
281 for (
int i = 0;
i <
size; ++
i) {
282 if (constraint->
coeffs[
i] == 0)
continue;
283 constraint->
vars[new_size] = constraint->
vars[
i];
287 constraint->
resize(new_size);
292 for (
int i = 0;
i <
size; ++
i) {
293 const IntegerValue coeff = constraint->
coeffs[
i];
295 constraint->
coeffs[
i] = -coeff;
303 for (
int i = 0;
i <
size; ++
i) {
304 const IntegerVariable
var = constraint->
vars[
i];
315 for (
int i = 0;
i <
vars.size(); ++
i) {
322 IntegerValue result =
offset;
323 for (
int i = 0;
i <
vars.size(); ++
i) {
331 IntegerValue result =
offset;
332 for (
int i = 0;
i <
vars.size(); ++
i) {
343 IntegerValue result =
offset;
344 for (
int i = 0;
i <
vars.size(); ++
i) {
355 if (
vars.empty())
return absl::StrCat(
offset.value());
357 for (
int i = 0;
i <
vars.size(); ++
i) {
358 absl::StrAppend(&result,
i > 0 ?
" " :
"",
362 absl::StrAppend(&result,
" + ",
offset.value());
368 absl::flat_hash_set<IntegerVariable> seen_variables;
369 const int size =
ct.num_terms;
370 for (
int i = 0;
i <
size; ++
i) {
372 if (!seen_variables.insert(
ct.vars[
i]).second)
return false;
374 if (!seen_variables.insert(
NegationOf(
ct.vars[
i])).second)
return false;
383 for (
int i = 0;
i < expr.
vars.size(); ++
i) {
388 canonical_expr.
vars.push_back(expr.
vars[
i]);
392 return canonical_expr;
399 int64_t positive_sum(0);
400 int64_t negative_sum(0);
402 const IntegerVariable
var = constraint.
vars[
i];
403 const IntegerValue coeff = constraint.
coeffs[
i];
407 int64_t min_prod =
CapProd(coeff.value(), lb.value());
408 int64_t max_prod =
CapProd(coeff.value(), ub.value());
409 if (min_prod > max_prod) std::swap(min_prod, max_prod);
411 positive_sum =
CapAdd(positive_sum, std::max(int64_t{0}, max_prod));
412 negative_sum =
CapAdd(negative_sum, std::min(int64_t{0}, min_prod));
415 const int64_t limit = std::numeric_limits<int64_t>::max();
416 if (positive_sum >= limit)
return false;
417 if (negative_sum <= -limit)
return false;
418 if (
CapSub(positive_sum, negative_sum) >= limit)
return false;
434 for (
int i = 0;
i < expr.
vars.size(); ++
i) {
448 for (
int i = 0;
i < expr.
vars.size(); ++
i) {
455 return IntegerValue(0);
461 for (
int i = 0;
i < expr.
vars.size(); ++
i) {
466 return IntegerValue(0);
471 IntegerValue min_activity(0);
472 IntegerValue max_activity(0);
474 for (
int i = 0;
i <
size; ++
i) {
475 const IntegerVariable
var = constraint.
vars[
i];
476 const IntegerValue coeff = constraint.
coeffs[
i];
481 if (!
AddProductTo(lb, coeff, &min_activity))
return true;
482 if (!
AddProductTo(ub, coeff, &max_activity))
return true;
484 if (!
AddProductTo(ub, coeff, &min_activity))
return true;
485 if (!
AddProductTo(lb, coeff, &max_activity))
return true;
static int64_t GCD64(int64_t x, int64_t y)
ABSL_MUST_USE_RESULT bool LiteralOrNegationHasView(Literal lit, IntegerVariable *view=nullptr, bool *view_is_direct=nullptr) const
IntegerValue LowerBound(IntegerVariable i) const
Returns the current lower/upper bound of the given integer variable.
IntegerValue UpperBound(IntegerVariable i) const
IntegerValue FixedValue(IntegerVariable i) const
Checks that the variable is fixed and returns its value.
bool IsFixed(IntegerVariable i) const
Checks if the variable is fixed.
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
Returns globally valid lower/upper bound on the given integer variable.
void AddQuadraticLowerBound(AffineExpression left, AffineExpression right, IntegerTrail *integer_trail, bool *is_quadratic=nullptr)
LinearExpression BuildExpression()
ABSL_MUST_USE_RESULT bool AddLiteralTerm(Literal lit, IntegerValue coeff=IntegerValue(1))
void AddTerm(IntegerVariable var, IntegerValue coeff)
void AddLinearExpression(const LinearExpression &expr)
void AddConstant(IntegerValue value)
Adds the corresponding term to the current linear expression.
LinearConstraint BuildConstraint(IntegerValue lb, IntegerValue ub)
ABSL_MUST_USE_RESULT bool AddDecomposedProduct(absl::Span< const LiteralValueValue > product)
double ComputeActivity(const LinearConstraint &constraint, const util_intops::StrongVector< IntegerVariable, double > &values)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
Computes result += a * b, and return false iff there is an overflow.
void DivideByGCD(LinearConstraint *constraint)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
IntType IntTypeAbs(IntType t)
double ComputeL2Norm(const LinearConstraint &ct)
Returns sqrt(sum square(coeff)).
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
void RemoveZeroTerms(LinearConstraint *constraint)
Removes the entries with a coefficient of zero.
IntegerValue ComputeInfinityNorm(const LinearConstraint &ct)
Returns the maximum absolute value of the coefficients.
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Returns the vector of the negated variables.
std::string IntegerTermDebugString(IntegerVariable var, IntegerValue coeff)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
bool PossibleOverflow(const IntegerTrail &integer_trail, const LinearConstraint &constraint)
void CleanTermsAndFillConstraint(std::vector< std::pair< IntegerVariable, IntegerValue > > *terms, LinearExpression *output)
void MakeAllCoefficientsPositive(LinearConstraint *constraint)
Makes all coefficients positive by transforming a variable to its negation.
LinearExpression CanonicalizeExpr(const LinearExpression &expr)
LinearExpression PositiveVarExpr(const LinearExpression &expr)
Returns the same expression with positive variables.
IntegerValue GetCoefficient(const IntegerVariable var, const LinearExpression &expr)
void MakeAllVariablesPositive(LinearConstraint *constraint)
Makes all variables "positive" by transforming a variable to its negation.
IntegerValue GetCoefficientOfPositiveVar(const IntegerVariable var, const LinearExpression &expr)
bool ValidateLinearConstraintForOverflow(const LinearConstraint &constraint, const IntegerTrail &integer_trail)
bool NoDuplicateVariable(const LinearConstraint &ct)
Returns false if duplicate variables are found in ct.
bool VariableIsPositive(IntegerVariable i)
double ToDouble(IntegerValue value)
double ScalarProduct(const LinearConstraint &ct1, const LinearConstraint &ct2)
In SWIG mode, we don't want anything besides these top-level includes.
bool AtMinOrMaxInt64(int64_t x)
Checks if x is equal to the min or the max value of an int64_t.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapSub(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
std::unique_ptr< IntegerValue[]> coeffs
std::unique_ptr< IntegerVariable[]> vars
IntegerValue LevelZeroMin(IntegerTrail *integer_trail) const
IntegerValue Min(const IntegerTrail &integer_trail) const
double LpValue(const util_intops::StrongVector< IntegerVariable, double > &lp_values) const
Return[s] the evaluation of the linear expression.
std::string DebugString() const
std::vector< IntegerVariable > vars
std::vector< IntegerValue > coeffs
IntegerValue Max(const IntegerTrail &integer_trail) const