18#include "absl/container/btree_map.h"
19#include "absl/flags/flag.h"
24#include "ortools/packing/vector_bin_packing.pb.h"
27 "File to store the solver specific optimization proto.");
33double ConvertVectorBinPackingProblem(
const vbp::VectorBinPackingProblem&
input,
34 ArcFlowGraph* graph) {
37 const int num_items =
input.item_size();
38 const int num_dims =
input.resource_capacity_size();
41 std::vector<std::vector<int>> shapes(num_items);
42 std::vector<int> demands(num_items);
43 std::vector<int> capacities(num_dims);
44 for (
int i = 0; i < num_items; ++i) {
45 shapes[i].assign(
input.item(i).resource_usage().begin(),
46 input.item(i).resource_usage().end());
47 demands[i] =
input.item(i).num_copies();
49 for (
int i = 0; i < num_dims; ++i) {
50 capacities[i] =
input.resource_capacity(i);
54 for (
int i = 0; i < num_items; ++i) {
55 const int max_copies =
input.item(i).max_number_of_copies_per_bin();
56 if (max_copies == 0 || max_copies >= demands[i])
continue;
57 capacities.push_back(max_copies);
58 for (
int j = 0; j < num_items; ++j) {
59 shapes[j].push_back(i == j);
64 const double arc_flow_time = timer.
Get();
66 VLOG(1) <<
"The arc-flow grah has " << graph->nodes.size() <<
" nodes, and "
67 << graph->arcs.size() <<
" arcs. It was created by exploring "
68 << graph->num_dp_states
69 <<
" states in the dynamic programming phase in " << arc_flow_time
76 const vbp::VectorBinPackingProblem& problem,
78 const std::string& mip_params,
double time_limit,
int num_threads,
81 const double arc_flow_time = ConvertVectorBinPackingProblem(problem, &graph);
85 max_num_bins = max_bins;
87 for (
const auto& item : problem.item()) {
88 max_num_bins += item.num_copies();
91 const int num_types = problem.item_size();
92 std::vector<std::vector<MPVariable*>> incoming_vars(graph.
nodes.size());
93 std::vector<std::vector<MPVariable*>> outgoing_vars(graph.
nodes.size());
94 std::vector<MPVariable*> arc_to_var(graph.
arcs.size());
95 std::vector<std::vector<MPVariable*>> item_to_vars(num_types);
97 MPSolver solver(
"VectorBinPacking", solver_type);
100 for (
int v = 0; v < graph.
arcs.size(); ++v) {
103 solver.
MakeIntVar(0, max_num_bins, absl::StrCat(
"a", v));
104 incoming_vars[
arc.destination].push_back(
var);
105 outgoing_vars[
arc.source].push_back(
var);
106 if (
arc.item_index != -1) {
107 item_to_vars[
arc.item_index].push_back(
var);
113 for (
int i = 0; i < num_types; ++i) {
115 problem.item(i).num_copies(), problem.item(i).num_copies());
117 ct->SetCoefficient(
var, 1.0);
122 for (
int n = 1; n < graph.
nodes.size() - 1; ++n) {
125 ct->SetCoefficient(
var, 1.0);
128 ct->SetCoefficient(
var, -1.0);
136 ct->SetCoefficient(
var, 1.0);
138 ct->SetCoefficient(obj_var, -1.0);
143 const int sink_node = graph.
nodes.size() - 1;
145 ct->SetCoefficient(
var, 1.0);
147 ct->SetCoefficient(obj_var, -1.0);
153 if (!absl::GetFlag(FLAGS_arc_flow_dump_model).empty()) {
154 MPModelProto output_model;
165 vbp::VectorBinPackingSolution solution;
166 solution.set_solve_time_in_seconds(solver.
wall_time() / 1000.0);
167 solution.set_arc_flow_time_in_seconds(arc_flow_time);
170 solution.set_status(vbp::OPTIMAL);
171 solution.set_objective_value(objective->
Value());
173 solution.set_status(vbp::FEASIBLE);
174 solution.set_objective_value(objective->
Value());
176 solution.set_status(vbp::INFEASIBLE);
182 struct NextCountItem {
187 std::vector<std::vector<NextCountItem>> node_to_next_count_item(
189 for (
int v = 0; v < graph.
arcs.size(); ++v) {
191 static_cast<int>(std::round(arc_to_var[v]->solution_value()));
192 if (count == 0)
continue;
194 node_to_next_count_item[
arc.source].push_back(
195 {
arc.destination, count,
arc.item_index});
203 const auto pop_next_item = [&node_to_next_count_item](
int node) {
204 CHECK(!node_to_next_count_item[node].empty());
205 auto& [
next, count, item] = node_to_next_count_item[node].back();
209 node_to_next_count_item[node].pop_back();
211 return NextItem({
next, item});
214 const int start_node = 0;
215 const int end_node = graph.
nodes.size() - 1;
216 while (!node_to_next_count_item[start_node].empty()) {
217 absl::btree_map<int, int> item_count;
218 int current = start_node;
219 while (current != end_node) {
220 const auto& [
next, item] = pop_next_item(current);
228 vbp::VectorBinPackingOneBinInSolution* bin = solution.add_bins();
229 for (
const auto& [item, count] : item_count) {
230 bin->add_item_indices(item);
231 bin->add_item_copies(count);
ABSL_FLAG(std::string, arc_flow_dump_model, "", "File to store the solver specific optimization proto.")
#define CHECK_EQ(val1, val2)
#define CHECK_GT(val1, val2)
#define CHECK_NE(val1, val2)
#define VLOG(verboselevel)
The class for constraints of a Mathematical Programming (MP) model.
A class to express a linear objective.
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
double Value() const
Returns the objective value of the best solution found so far.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
MPConstraint * MakeRowConstraint(double lb, double ub)
Creates a linear constraint with given bounds.
ResultStatus
The status of solving the problem.
@ FEASIBLE
feasible, or stopped by limit.
@ INFEASIBLE
proven infeasible.
int64_t wall_time() const
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
ResultStatus Solve()
Solves the problem using the default parameter values.
void EnableOutput()
Enables solver logging.
MPObjective * MutableObjective()
Returns the mutable objective object.
void SetTimeLimit(absl::Duration time_limit)
The class for variables of a Mathematical Programming (MP) model.
ModelSharedTimeLimit * time_limit
absl::Status SetTextProto(const absl::string_view &filename, const google::protobuf::Message &proto, int flags)
vbp::VectorBinPackingSolution SolveVectorBinPackingWithArcFlow(const vbp::VectorBinPackingProblem &problem, MPSolver::OptimizationProblemType solver_type, const std::string &mip_params, double time_limit, int num_threads, int max_bins)
ArcFlowGraph BuildArcFlowGraph(const std::vector< int > &bin_dimensions, const std::vector< std::vector< int > > &item_dimensions_by_type, const std::vector< int > &demand_by_type)
Collection of objects used to extend the Constraint Solver library.
static int input(yyscan_t yyscanner)
std::vector< std::vector< int > > nodes