14 #ifndef OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_ 15 #define OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_ 23 #include "absl/memory/memory.h" 24 #include "ortools/base/basictypes.h" 25 #include "ortools/base/integral_types.h" 26 #include "ortools/base/logging.h" 27 #include "ortools/base/macros.h" 28 #include "ortools/util/time_limit.h" 32 class BaseKnapsackSolver;
168 #if defined(USE_SCIP) 185 void Init(
const std::vector<int64>& profits,
186 const std::vector<std::vector<int64> >& weights,
187 const std::vector<int64>& capacities);
213 time_limit_seconds_ = time_limit_seconds;
214 time_limit_ = absl::make_unique<TimeLimit>(time_limit_seconds_);
220 int ReduceCapacities(
int num_items,
221 const std::vector<std::vector<int64> >& weights,
222 const std::vector<int64>& capacities,
223 std::vector<std::vector<int64> >* reduced_weights,
224 std::vector<int64>* reduced_capacities);
225 int ReduceProblem(
int num_items);
226 void ComputeAdditionalProfit(
const std::vector<int64>& profits);
227 void InitReducedProblem(
const std::vector<int64>& profits,
228 const std::vector<std::vector<int64> >& weights,
229 const std::vector<int64>& capacities);
231 std::unique_ptr<BaseKnapsackSolver> solver_;
232 std::vector<bool> known_value_;
233 std::vector<bool> best_solution_;
234 bool is_solution_optimal_ =
false;
235 std::vector<int> mapping_reduced_item_id_;
236 bool is_problem_solved_;
237 int64 additional_profit_;
239 double time_limit_seconds_;
240 std::unique_ptr<TimeLimit> time_limit_;
272 struct KnapsackAssignment {
273 KnapsackAssignment(
int _item_id,
bool _is_in)
274 : item_id(_item_id), is_in(_is_in) {}
291 struct KnapsackItem {
292 KnapsackItem(
int _id, int64 _weight, int64 _profit)
293 : id(_id), weight(_weight), profit(_profit) {}
294 double GetEfficiency(int64 profit_max)
const {
296 ? static_cast<double>(profit) / static_cast<double>(weight)
297 : static_cast<double>(profit_max);
306 typedef KnapsackItem* KnapsackItemPtr;
316 class KnapsackSearchNode {
318 KnapsackSearchNode(
const KnapsackSearchNode*
const parent,
319 const KnapsackAssignment& assignment);
320 int depth()
const {
return depth_; }
321 const KnapsackSearchNode*
const parent()
const {
return parent_; }
322 const KnapsackAssignment& assignment()
const {
return assignment_; }
324 int64 current_profit()
const {
return current_profit_; }
325 void set_current_profit(int64 profit) { current_profit_ = profit; }
327 int64 profit_upper_bound()
const {
return profit_upper_bound_; }
328 void set_profit_upper_bound(int64 profit) { profit_upper_bound_ = profit; }
330 int next_item_id()
const {
return next_item_id_; }
331 void set_next_item_id(
int id) { next_item_id_ = id; }
337 const KnapsackSearchNode*
const parent_;
338 KnapsackAssignment assignment_;
344 int64 current_profit_;
345 int64 profit_upper_bound_;
351 DISALLOW_COPY_AND_ASSIGN(KnapsackSearchNode);
370 class KnapsackSearchPath {
372 KnapsackSearchPath(
const KnapsackSearchNode& from,
373 const KnapsackSearchNode& to);
375 const KnapsackSearchNode& from()
const {
return from_; }
376 const KnapsackSearchNode& via()
const {
return *via_; }
377 const KnapsackSearchNode& to()
const {
return to_; }
378 const KnapsackSearchNode* MoveUpToDepth(
const KnapsackSearchNode& node,
382 const KnapsackSearchNode& from_;
383 const KnapsackSearchNode* via_;
384 const KnapsackSearchNode& to_;
386 DISALLOW_COPY_AND_ASSIGN(KnapsackSearchPath);
391 class KnapsackState {
396 void Init(
int number_of_items);
400 bool UpdateState(
bool revert,
const KnapsackAssignment& assignment);
402 int GetNumberOfItems()
const {
return is_bound_.size(); }
403 bool is_bound(
int id)
const {
return is_bound_.at(
id); }
404 bool is_in(
int id)
const {
return is_in_.at(
id); }
411 std::vector<bool> is_bound_;
412 std::vector<bool> is_in_;
414 DISALLOW_COPY_AND_ASSIGN(KnapsackState);
425 class KnapsackPropagator {
427 explicit KnapsackPropagator(
const KnapsackState& state);
428 virtual ~KnapsackPropagator();
431 void Init(
const std::vector<int64>& profits,
432 const std::vector<int64>& weights);
436 bool Update(
bool revert,
const KnapsackAssignment& assignment);
439 virtual void ComputeProfitBounds() = 0;
442 virtual int GetNextItemId()
const = 0;
444 int64 current_profit()
const {
return current_profit_; }
445 int64 profit_lower_bound()
const {
return profit_lower_bound_; }
446 int64 profit_upper_bound()
const {
return profit_upper_bound_; }
454 void CopyCurrentStateToSolution(
bool has_one_propagator,
455 std::vector<bool>* solution)
const;
460 virtual void InitPropagator() = 0;
464 virtual bool UpdatePropagator(
bool revert,
465 const KnapsackAssignment& assignment) = 0;
472 virtual void CopyCurrentStateToSolutionPropagator(
473 std::vector<bool>* solution)
const = 0;
475 const KnapsackState& state()
const {
return state_; }
476 const std::vector<KnapsackItemPtr>& items()
const {
return items_; }
478 void set_profit_lower_bound(int64 profit) { profit_lower_bound_ = profit; }
479 void set_profit_upper_bound(int64 profit) { profit_upper_bound_ = profit; }
482 std::vector<KnapsackItemPtr> items_;
483 int64 current_profit_;
484 int64 profit_lower_bound_;
485 int64 profit_upper_bound_;
486 const KnapsackState& state_;
488 DISALLOW_COPY_AND_ASSIGN(KnapsackPropagator);
511 class KnapsackCapacityPropagator :
public KnapsackPropagator {
513 KnapsackCapacityPropagator(
const KnapsackState& state, int64 capacity);
514 ~KnapsackCapacityPropagator()
override;
515 void ComputeProfitBounds()
override;
516 int GetNextItemId()
const override {
return break_item_id_; }
521 void InitPropagator()
override;
524 bool UpdatePropagator(
bool revert,
525 const KnapsackAssignment& assignment)
override;
526 void CopyCurrentStateToSolutionPropagator(
527 std::vector<bool>* solution)
const override;
538 int64 GetAdditionalProfit(int64 remaining_capacity,
int break_item_id)
const;
540 const int64 capacity_;
541 int64 consumed_capacity_;
543 std::vector<KnapsackItemPtr> sorted_items_;
546 DISALLOW_COPY_AND_ASSIGN(KnapsackCapacityPropagator);
551 class BaseKnapsackSolver {
553 explicit BaseKnapsackSolver(
const std::string& solver_name)
554 : solver_name_(solver_name) {}
555 virtual ~BaseKnapsackSolver() {}
558 virtual void Init(
const std::vector<int64>& profits,
559 const std::vector<std::vector<int64> >& weights,
560 const std::vector<int64>& capacities) = 0;
565 virtual void GetLowerAndUpperBoundWhenItem(
int item_id,
bool is_item_in,
570 virtual int64 Solve(TimeLimit* time_limit,
bool* is_solution_optimal) = 0;
573 virtual bool best_solution(
int item_id)
const = 0;
575 virtual std::string GetName()
const {
return solver_name_; }
578 const std::string solver_name_;
590 class KnapsackGenericSolver :
public BaseKnapsackSolver {
592 explicit KnapsackGenericSolver(
const std::string& solver_name);
593 ~KnapsackGenericSolver()
override;
596 void Init(
const std::vector<int64>& profits,
597 const std::vector<std::vector<int64> >& weights,
598 const std::vector<int64>& capacities)
override;
599 int GetNumberOfItems()
const {
return state_.GetNumberOfItems(); }
600 void GetLowerAndUpperBoundWhenItem(
int item_id,
bool is_item_in,
602 int64* upper_bound)
override;
607 void set_master_propagator_id(
int master_propagator_id) {
608 master_propagator_id_ = master_propagator_id;
612 int64 Solve(TimeLimit* time_limit,
bool* is_solution_optimal)
override;
614 bool best_solution(
int item_id)
const override {
615 return best_solution_.at(item_id);
625 bool UpdatePropagators(
const KnapsackSearchPath& path);
629 bool IncrementalUpdate(
bool revert,
const KnapsackAssignment& assignment);
631 void UpdateBestSolution();
635 bool MakeNewNode(
const KnapsackSearchNode& node,
bool is_in);
638 int64 GetAggregatedProfitUpperBound()
const;
639 bool HasOnePropagator()
const {
return propagators_.size() == 1; }
640 int64 GetCurrentProfit()
const {
641 return propagators_.at(master_propagator_id_)->current_profit();
643 int64 GetNextItemId()
const {
644 return propagators_.at(master_propagator_id_)->GetNextItemId();
647 std::vector<KnapsackPropagator*> propagators_;
648 int master_propagator_id_;
649 std::vector<KnapsackSearchNode*> search_nodes_;
650 KnapsackState state_;
651 int64 best_solution_profit_;
652 std::vector<bool> best_solution_;
654 DISALLOW_COPY_AND_ASSIGN(KnapsackGenericSolver);
659 #endif // OR_TOOLS_ALGORITHMS_KNAPSACK_SOLVER_H_ bool BestSolutionContains(int item_id) const
Returns true if the item 'item_id' is packed in the optimal knapsack.
bool IsSolutionOptimal() const
Returns true if the solution was proven optimal.
std::string GetName() const
This library solves knapsack problems.
SolverType
Enum controlling which underlying algorithm is used.
void set_use_reduction(bool use_reduction)
KnapsackSolver(const std::string &solver_name)
void Init(const std::vector< int64 > &profits, const std::vector< std::vector< int64 > > &weights, const std::vector< int64 > &capacities)
Initializes the solver and enters the problem to be solved.
Dynamic Programming approach for single dimension problems.
bool use_reduction() const
void set_time_limit(double time_limit_seconds)
Time limit in seconds.
virtual ~KnapsackSolver()
Optimized method for single dimension small problems.
int64 Solve()
Solves the problem and returns the profit of the optimal solution.