14#ifndef ORTOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_
15#define ORTOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_
22#include "absl/strings/string_view.h"
197 void Init(
const std::vector<int64_t>& profits,
198 const std::vector<std::vector<int64_t> >& weights,
199 const std::vector<int64_t>& capacities);
217 time_limit_seconds_ = time_limit_seconds;
218 time_limit_ = std::make_unique<TimeLimit>(time_limit_seconds_);
224 int ReduceCapacities(
int num_items,
225 const std::vector<std::vector<int64_t> >& weights,
226 const std::vector<int64_t>& capacities,
227 std::vector<std::vector<int64_t> >* reduced_weights,
228 std::vector<int64_t>* reduced_capacities);
229 int ReduceProblem(
int num_items);
230 void ComputeAdditionalProfit(
const std::vector<int64_t>& profits);
231 void InitReducedProblem(
const std::vector<int64_t>& profits,
232 const std::vector<std::vector<int64_t> >& weights,
233 const std::vector<int64_t>& capacities);
235 std::unique_ptr<BaseKnapsackSolver> solver_;
236 std::vector<bool> known_value_;
237 std::vector<bool> best_solution_;
238 bool is_solution_optimal_ =
false;
239 std::vector<int> mapping_reduced_item_id_;
240 bool is_problem_solved_;
241 int64_t additional_profit_;
243 double time_limit_seconds_;
244 std::unique_ptr<TimeLimit> time_limit_;
298 ?
static_cast<double>(
profit) /
static_cast<double>(
weight)
299 :
static_cast<double>(profit_max);
329 int depth()
const {
return depth_; }
353 int64_t current_profit_;
354 int64_t profit_upper_bound_;
377class KnapsackSearchPath {
415 void Init(
int number_of_items);
422 bool is_bound(
int id)
const {
return is_bound_.at(
id); }
423 bool is_in(
int id)
const {
return is_in_.at(
id); }
430 std::vector<bool> is_bound_;
431 std::vector<bool> is_in_;
454 void Init(
const std::vector<int64_t>& profits,
455 const std::vector<int64_t>& weights);
496 std::vector<bool>*
solution)
const = 0;
499 const std::vector<KnapsackItemPtr>&
items()
const {
return items_; }
505 std::vector<KnapsackItemPtr> items_;
506 int64_t current_profit_;
507 int64_t profit_lower_bound_;
508 int64_t profit_upper_bound_;
554 std::vector<bool>*
solution)
const override;
565 int64_t GetAdditionalProfit(int64_t remaining_capacity,
566 int break_item_id)
const;
568 const int64_t capacity_;
569 int64_t consumed_capacity_;
571 std::vector<KnapsackItemPtr> sorted_items_;
580 : solver_name_(solver_name) {}
584 virtual void Init(
const std::vector<int64_t>& profits,
585 const std::vector<std::vector<int64_t> >& weights,
586 const std::vector<int64_t>& capacities) = 0;
592 int64_t* lower_bound,
593 int64_t* upper_bound);
596 virtual int64_t
Solve(
TimeLimit* time_limit,
double time_limit_in_seconds,
597 bool* is_solution_optimal) = 0;
602 virtual std::string
GetName()
const {
return solver_name_; }
605 const std::string solver_name_;
630 void Init(
const std::vector<int64_t>& profits,
631 const std::vector<std::vector<int64_t> >& weights,
632 const std::vector<int64_t>& capacities)
override;
635 int64_t* lower_bound,
636 int64_t* upper_bound)
override;
642 primary_propagator_id_ = primary_propagator_id;
646 int64_t
Solve(
TimeLimit* time_limit,
double time_limit_in_seconds,
647 bool* is_solution_optimal)
override;
650 return best_solution_.at(item_id);
666 void UpdateBestSolution();
673 int64_t GetAggregatedProfitUpperBound()
const;
674 bool HasOnePropagator()
const {
return propagators_.size() == 1; }
675 int64_t GetCurrentProfit()
const {
676 return propagators_.at(primary_propagator_id_)->current_profit();
678 int64_t GetNextItemId()
const {
679 return propagators_.at(primary_propagator_id_)->GetNextItemId();
682 std::vector<KnapsackPropagator*> propagators_;
683 int primary_propagator_id_;
684 std::vector<KnapsackSearchNode*> search_nodes_;
685 KnapsackState state_;
686 int64_t best_solution_profit_;
687 std::vector<bool> best_solution_;
This is the base class for knapsack solvers.
virtual bool best_solution(int item_id) const =0
Returns true if the item 'item_id' is packed in the optimal knapsack.
virtual int64_t Solve(TimeLimit *time_limit, double time_limit_in_seconds, bool *is_solution_optimal)=0
Solves the problem and returns the profit of the optimal solution.
virtual void Init(const std::vector< int64_t > &profits, const std::vector< std::vector< int64_t > > &weights, const std::vector< int64_t > &capacities)=0
Initializes the solver and enters the problem to be solved.
BaseKnapsackSolver(absl::string_view solver_name)
virtual ~BaseKnapsackSolver()=default
virtual void GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, int64_t *lower_bound, int64_t *upper_bound)
virtual std::string GetName() const
KnapsackCapacityPropagator is a KnapsackPropagator used to enforce a capacity constraint.
void CopyCurrentStateToSolutionPropagator(std::vector< bool > *solution) const override
~KnapsackCapacityPropagator() override
KnapsackCapacityPropagator & operator=(const KnapsackCapacityPropagator &)=delete
KnapsackCapacityPropagator(const KnapsackState &state, int64_t capacity)
void InitPropagator() override
bool UpdatePropagator(bool revert, const KnapsackAssignment &assignment) override
int GetNextItemId() const override
void ComputeProfitBounds() override
KnapsackGenericSolver is the multi-dimensional knapsack solver class.
void GetLowerAndUpperBoundWhenItem(int item_id, bool is_item_in, int64_t *lower_bound, int64_t *upper_bound) override
void set_primary_propagator_id(int primary_propagator_id)
bool best_solution(int item_id) const override
Returns true if the item 'item_id' is packed in the optimal knapsack.
~KnapsackGenericSolver() override
int GetNumberOfItems() const
void Init(const std::vector< int64_t > &profits, const std::vector< std::vector< int64_t > > &weights, const std::vector< int64_t > &capacities) override
Initializes the solver and enters the problem to be solved.
KnapsackGenericSolver & operator=(const KnapsackGenericSolver &)=delete
KnapsackGenericSolver(const std::string &solver_name)
int64_t Solve(TimeLimit *time_limit, double time_limit_in_seconds, bool *is_solution_optimal) override
Solves the problem and returns the profit of the optimal solution.
KnapsackPropagator is the base class for modeling and propagating a constraint given an assignment.
KnapsackPropagator & operator=(const KnapsackPropagator &)=delete
void set_profit_upper_bound(int64_t profit)
virtual int GetNextItemId() const =0
void CopyCurrentStateToSolution(bool has_one_propagator, std::vector< bool > *solution) const
int64_t profit_lower_bound() const
bool Update(bool revert, const KnapsackAssignment &assignment)
void set_profit_lower_bound(int64_t profit)
void Init(const std::vector< int64_t > &profits, const std::vector< int64_t > &weights)
Initializes data structure and then calls InitPropagator.
virtual void ComputeProfitBounds()=0
const KnapsackState & state() const
KnapsackPropagator(const KnapsackState &state)
virtual ~KnapsackPropagator()
virtual void CopyCurrentStateToSolutionPropagator(std::vector< bool > *solution) const =0
virtual bool UpdatePropagator(bool revert, const KnapsackAssignment &assignment)=0
int64_t profit_upper_bound() const
const std::vector< KnapsackItemPtr > & items() const
virtual void InitPropagator()=0
int64_t current_profit() const
int64_t profit_upper_bound() const
KnapsackSearchNode(const KnapsackSearchNode *parent, const KnapsackAssignment &assignment)
const KnapsackAssignment & assignment() const
void set_current_profit(int64_t profit)
KnapsackSearchNode & operator=(const KnapsackSearchNode &)=delete
void set_next_item_id(int id)
int64_t current_profit() const
const KnapsackSearchNode * parent() const
KnapsackSearchNode(const KnapsackSearchNode &)=delete
void set_profit_upper_bound(int64_t profit)
const KnapsackSearchNode & via() const
KnapsackSearchPath(const KnapsackSearchNode &from, const KnapsackSearchNode &to)
const KnapsackSearchNode & to() const
const KnapsackSearchNode & from() const
const KnapsackSearchNode * MoveUpToDepth(const KnapsackSearchNode &node, int depth) const
KnapsackSearchPath & operator=(const KnapsackSearchPath &)=delete
bool use_reduction() const
void set_time_limit(double time_limit_seconds)
Time limit in seconds.
KnapsackSolver(const KnapsackSolver &)=delete
bool BestSolutionContains(int item_id) const
Returns true if the item 'item_id' is packed in the optimal knapsack.
void Init(const std::vector< int64_t > &profits, const std::vector< std::vector< int64_t > > &weights, const std::vector< int64_t > &capacities)
Initializes the solver and enters the problem to be solved.
KnapsackSolver(const std::string &solver_name)
SolverType
Enum controlling which underlying algorithm is used.
@ KNAPSACK_DIVIDE_AND_CONQUER_SOLVER
@ KNAPSACK_BRUTE_FORCE_SOLVER
@ KNAPSACK_MULTIDIMENSION_XPRESS_MIP_SOLVER
@ KNAPSACK_MULTIDIMENSION_CP_SAT_SOLVER
@ KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER
@ KNAPSACK_64ITEMS_SOLVER
@ KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER
@ KNAPSACK_MULTIDIMENSION_CPLEX_MIP_SOLVER
@ KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER
@ KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER
bool IsSolutionOptimal() const
Returns true if the solution was proven optimal.
KnapsackSolver & operator=(const KnapsackSolver &)=delete
virtual ~KnapsackSolver()
void set_use_reduction(bool use_reduction)
std::string GetName() const
int64_t Solve()
Solves the problem and returns the profit of the optimal solution.
KnapsackState represents a partial solution to the knapsack problem.
bool UpdateState(bool revert, const KnapsackAssignment &assignment)
void Init(int number_of_items)
int GetNumberOfItems() const
KnapsackState & operator=(const KnapsackState &)=delete
bool is_bound(int id) const
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
KnapsackItem * KnapsackItemPtr
KnapsackAssignment(int _item_id, bool _is_in)
KnapsackItem(int _id, int64_t _weight, int64_t _profit)
double GetEfficiency(int64_t profit_max) const