18 #include "absl/container/btree_map.h" 19 #include "absl/flags/flag.h" 26 ABSL_FLAG(std::string, arc_flow_dump_model,
"",
27 "File to store the solver specific optimization proto.");
33 double 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
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));
105 outgoing_vars[arc.
source].push_back(
var);
113 for (
int i = 0; i < num_types; ++i) {
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()) {
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(
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);
229 for (
const auto& [item, count] : item_count) {
ResultStatus
The status of solving the problem.
MPVariable * MakeIntVar(double lb, double ub, const std::string &name)
Creates an integer variable.
std::vector< std::vector< int > > nodes
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)
double Value() const
Returns the objective value of the best solution found so far.
ModelSharedTimeLimit * time_limit
absl::Status SetTextProto(const absl::string_view &filename, const google::protobuf::Message &proto, int flags)
#define CHECK_GT(val1, val2)
#define VLOG(verboselevel)
void SetCoefficient(const MPVariable *const var, double coeff)
Sets the coefficient of the variable in the objective.
OptimizationProblemType
The type of problems (LP or MIP) that will be solved and the underlying solver (GLOP,...
A class to express a linear objective.
MPObjective * MutableObjective()
Returns the mutable objective object.
void set_solve_time_in_seconds(double value)
void set_objective_value(double value)
void set_status(::operations_research::packing::vbp::VectorBinPackingSolveStatus value)
The class for variables of a Mathematical Programming (MP) model.
int64_t wall_time() const
bool SetSolverSpecificParametersAsString(const std::string ¶meters)
Advanced usage: pass solver specific parameters in text format.
ABSL_FLAG(std::string, arc_flow_dump_model, "", "File to store the solver specific optimization proto.")
absl::Status SetNumThreads(int num_threads)
Sets the number of threads to use by the underlying solver.
void set_arc_flow_time_in_seconds(double value)
static int input(yyscan_t yyscanner)
The class for constraints of a Mathematical Programming (MP) model.
feasible, or stopped by limit.
void EnableOutput()
Enables solver logging.
#define CHECK_EQ(val1, val2)
::operations_research::packing::vbp::VectorBinPackingOneBinInSolution * add_bins()
void SetTimeLimit(absl::Duration time_limit)
ResultStatus Solve()
Solves the problem using the default parameter values.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
Collection of objects used to extend the Constraint Solver library.
void add_item_indices(int32_t value)
int32_t num_copies() const
void ExportModelToProto(MPModelProto *output_model) const
Exports model to protocol buffer.
void add_item_copies(int32_t value)
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)
MPConstraint * MakeRowConstraint(double lb, double ub)
Creates a linear constraint with given bounds.
#define CHECK_NE(val1, val2)
const ::operations_research::packing::vbp::Item & item(int index) const