26#include "absl/base/attributes.h"
27#include "absl/memory/memory.h"
43 void Reset()
override;
51 double new_value,
double old_value)
override;
60 int64_t
nodes()
const override;
66 bool IsLP()
const override;
67 bool IsMIP()
const override;
85 bool IsKnapsackModel()
const;
88 double GetVariableValueFromSolution(
const MPVariable*
var)
const;
91 std::unique_ptr<KnapsackSolver> knapsack_solver_;
92 std::vector<int64_t> profits_;
93 std::vector<std::vector<int64_t>> weights_;
94 std::vector<int64_t> capacities_;
105 if (!IsKnapsackModel()) {
106 LOG(ERROR) <<
"Model is not a knapsack model";
116 if (profits_.size() <= 64 && capacities_.size() == 1) {
120 std::make_unique<KnapsackSolver>(solver_type,
"linear_solver");
121 const double time_limit_seconds =
124 : std::numeric_limits<double>::infinity();
125 knapsack_solver_->set_time_limit(time_limit_seconds);
126 knapsack_solver_->Init(profits_, weights_, capacities_);
127 knapsack_solver_->Solve();
131 for (
int var_id = 0; var_id <
solver_->variables_.size(); ++var_id) {
133 const double value = GetVariableValueFromSolution(
var);
145 knapsack_solver_.reset(
nullptr);
149 NonIncrementalChange();
153 NonIncrementalChange();
157 NonIncrementalChange();
161 NonIncrementalChange();
165 NonIncrementalChange();
169 NonIncrementalChange();
174 double new_value,
double old_value) {
175 NonIncrementalChange();
179 NonIncrementalChange();
184 NonIncrementalChange();
188 NonIncrementalChange();
204 int variable_index)
const {
216 return "knapsack_solver-0.0";
230 weights_.resize(
solver_->constraints_.size());
231 capacities_.resize(
solver_->constraints_.size(),
232 std::numeric_limits<int64_t>::max());
235 double fixed_usage = 0.0;
238 for (
const auto& entry :
ct->coefficients_) {
239 const int var_index = entry.first->index();
241 if (IsVariableFixedToValue(entry.first, 1.0)) {
242 fixed_usage += entry.second;
243 }
else if (!IsVariableFixedToValue(entry.first, 0.0)) {
249 const double capacity =
ct->ub() - fixed_usage;
252 double relative_error = 0.0;
253 double scaling_factor = 0.0;
255 std::numeric_limits<int64_t>::max(),
256 &scaling_factor, &relative_error);
259 std::vector<int64_t> scaled_coefficients(
solver_->variables_.size(), 0);
260 for (
const auto& entry :
ct->coefficients_) {
261 if (!IsVariableFixed(entry.first)) {
262 scaled_coefficients[entry.first->index()] =
263 static_cast<int64_t
>(round(scaling_factor * entry.second)) / gcd;
266 weights_[
row].swap(scaled_coefficients);
268 static_cast<int64_t
>(round(scaling_factor * capacity)) / gcd;
274 for (
const auto& entry :
solver_->objective_->coefficients_) {
278 if (!IsVariableFixed(entry.first)) {
282 double relative_error = 0.0;
283 double scaling_factor = 0.0;
285 std::numeric_limits<int64_t>::max(),
286 &scaling_factor, &relative_error);
288 std::vector<int64_t> scaled_coefficients(
solver_->variables_.size(), 0);
289 for (
const auto& entry :
solver_->objective_->coefficients_) {
290 scaled_coefficients[entry.first->index()] =
291 static_cast<int64_t
>(round(scaling_factor * entry.second)) / gcd;
293 profits_.swap(scaled_coefficients);
312bool KnapsackInterface::IsKnapsackModel()
const {
316 if (
var->lb() <= -1.0 ||
var->ub() >= 2.0 || !
var->integer()) {
321 for (
const auto& entry :
solver_->objective_->coefficients_) {
322 if (entry.second < 0) {
329 if (
ct->lb() > 0.0) {
332 for (
const auto& entry :
ct->coefficients_) {
333 if (entry.second < 0) {
342bool KnapsackInterface::IsVariableFixedToValue(
const MPVariable*
var,
343 double value)
const {
344 const double lb_round_up = ceil(
var->lb());
345 return value == lb_round_up &&
floor(
var->ub()) == lb_round_up;
348bool KnapsackInterface::IsVariableFixed(
const MPVariable*
var)
const {
349 return IsVariableFixedToValue(
var, 0.0) || IsVariableFixedToValue(
var, 1.0);
352double KnapsackInterface::GetVariableValueFromSolution(
353 const MPVariable*
var)
const {
354 return !IsVariableFixedToValue(
var, 0.0) &&
355 (knapsack_solver_->BestSolutionContains(
var->index()) ||
356 IsVariableFixedToValue(
var, 1.0))
void SetDualTolerance(double value) override
~KnapsackInterface() override
void SetVariableInteger(int index, bool integer) override
Modifies integrality of an extracted variable.
int64_t nodes() const override
void ClearConstraint(MPConstraint *constraint) override
Clears a constraint from all its terms.
void ExtractNewVariables() override
Extracts the variables that have not been extracted yet.
int64_t iterations() const override
---— Query statistics on the solution and the solve ---—
std::string SolverVersion() const override
Returns a string describing the underlying solver and its version.
void Reset() override
--— Model modifications and extraction --—
void ExtractNewConstraints() override
Extracts the constraints that have not been extracted yet.
void SetVariableBounds(int index, double lb, double ub) override
Modifies bounds of an extracted variable.
void SetCoefficient(MPConstraint *constraint, const MPVariable *variable, double new_value, double old_value) override
Changes a coefficient in a constraint.
void AddVariable(MPVariable *var) override
Add a variable.
void SetLpAlgorithm(int value) override
void SetRelativeMipGap(double value) override
Sets each parameter in the underlying solver.
void AddRowConstraint(MPConstraint *ct) override
Adds a linear constraint.
void * underlying_solver() override
Returns the underlying solver.
void SetObjectiveCoefficient(const MPVariable *variable, double coefficient) override
Changes a coefficient in the linear objective.
MPSolver::BasisStatus row_status(int constraint_index) const override
Returns the basis status of a row.
void SetObjectiveOffset(double value) override
Changes the constant term in the linear objective.
void SetConstraintBounds(int index, double lb, double ub) override
Modify bounds of an extracted variable.
void ClearObjective() override
Clears the objective from all its terms.
void SetPrimalTolerance(double value) override
void SetOptimizationDirection(bool maximize) override
Sets the optimization direction (min/max).
MPSolver::BasisStatus column_status(int variable_index) const override
Returns the basis status of a constraint.
KnapsackInterface(MPSolver *solver)
void ExtractObjective() override
Extracts the objective.
void SetParameters(const MPSolverParameters ¶m) override
Sets all parameters in the underlying solver.
void SetScalingMode(int value) override
Sets the scaling mode.
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
--— Solve --—
bool IsContinuous() const override
--— Misc --—
bool IsMIP() const override
Returns true if the problem is discrete and linear.
bool IsLP() const override
Returns true if the problem is continuous and linear.
void SetPresolveMode(int value) override
@ KNAPSACK_64ITEMS_SOLVER
@ KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER
void set_variable_as_extracted(int var_index, bool extracted)
friend class MPConstraint
To access the maximize_ bool and the MPSolver.
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
Resets the extraction information.
int last_variable_index_
Index in MPSolver::constraints_ of last variable extracted.
int last_constraint_index_
Index in MPSolver::variables_ of last constraint extracted.
bool variable_is_extracted(int var_index) const
static constexpr int64_t kUnknownNumberOfNodes
void ExtractModel()
Extracts model stored in MPSolver.
double objective_value_
The value of the objective function.
bool maximize_
Optimization direction.
void SetCommonParameters(const MPSolverParameters ¶m)
Sets parameters common to LP and MIP in the underlying solver.
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
Indicates whether the model and the solution are synchronized.
int64_t time_limit() const
@ MODEL_INVALID
the model is trivially invalid (NaN coefficients, etc).
@ FEASIBLE
feasible, or stopped by limit.
The class for variables of a Mathematical Programming (MP) model.
absl::Span< const double > coefficients
In SWIG mode, we don't want anything besides these top-level includes.
MPSolverInterface * BuildKnapsackInterface(MPSolver *const solver)
Register Knapsack solver in the global linear solver factory.
double GetBestScalingOfDoublesToInt64(absl::Span< const double > input, absl::Span< const double > lb, absl::Span< const double > ub, int64_t max_absolute_sum)
int64_t ComputeGcdOfRoundedDoubles(absl::Span< const double > x, double scaling_factor)