22 #include "absl/container/flat_hash_map.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/str_join.h"
34 class ArcFlowBuilder {
37 ArcFlowBuilder(
const std::vector<int>& bin_dimensions,
38 const std::vector<std::vector<int>>& item_dimensions_by_type,
39 const std::vector<int>& demand_by_type);
46 int64_t NumDpStates()
const;
56 double NormalizedSize(
const std::vector<int>& bin_dimensions)
const;
72 void ForwardCreationPass(DpState* dp_state);
75 void BackwardCompressionPass(
int state_index);
77 void ForwardCompressionPass(
const std::vector<int>& source_node);
80 bool CanFitNewItem(
const std::vector<int>&
used_dimensions,
int item)
const;
86 int LookupOrCreateDpState(
int item,
int quantity,
89 const std::vector<int> bin_dimensions_;
90 std::vector<Item> items_;
92 typedef absl::flat_hash_map<std::vector<int>,
int> VectorIntIntMap;
98 std::vector<DpState*> dp_states_;
99 std::vector<std::vector<VectorIntIntMap>> dp_state_index_;
105 absl::flat_hash_map<std::vector<int>,
int> node_indices_;
106 std::vector<std::vector<int>> nodes_;
108 std::set<ArcFlowGraph::Arc> arcs_;
111 double ArcFlowBuilder::Item::NormalizedSize(
112 const std::vector<int>& bin_dimensions)
const {
114 for (
int i = 0; i < bin_dimensions.size(); ++i) {
115 size +=
static_cast<double>(
dimensions[i]) / bin_dimensions[i];
120 int64_t ArcFlowBuilder::NumDpStates()
const {
122 for (
const auto& it1 : dp_state_index_) {
123 for (
const auto& it2 : it1) {
130 ArcFlowBuilder::ArcFlowBuilder(
131 const std::vector<int>& bin_dimensions,
132 const std::vector<std::vector<int>>& item_dimensions_by_type,
133 const std::vector<int>& demand_by_type)
134 : bin_dimensions_(bin_dimensions) {
136 for (
int i = 0; i < bin_dimensions.size(); ++i) {
137 CHECK_GT(bin_dimensions[i], 0);
140 const int num_items = item_dimensions_by_type.size();
141 items_.resize(num_items);
142 for (
int i = 0; i < num_items; ++i) {
143 items_[i].dimensions = item_dimensions_by_type[i];
144 items_[i].demand = demand_by_type[i];
145 items_[i].original_index = i;
147 std::sort(items_.begin(), items_.end(), [&](
const Item&
a,
const Item&
b) {
148 return a.NormalizedSize(bin_dimensions_) >
149 b.NormalizedSize(bin_dimensions_);
153 bool ArcFlowBuilder::CanFitNewItem(
const std::vector<int>&
used_dimensions,
155 for (
int d = 0; d < bin_dimensions_.size(); ++d) {
163 std::vector<int> ArcFlowBuilder::AddItem(
167 for (
int d = 0; d < bin_dimensions_.size(); ++d) {
168 result[d] += items_[item].dimensions[d];
173 int ArcFlowBuilder::GetOrCreateNode(
const std::vector<int>&
used_dimensions) {
175 if (it != node_indices_.end()) {
178 const int index = node_indices_.size();
184 ArcFlowGraph ArcFlowBuilder::BuildVectorBinPackingGraph() {
186 dp_state_index_.resize(items_.size());
187 for (
int i = 0; i < items_.size(); ++i) {
188 dp_state_index_[i].resize(items_[i].
demand + 1);
193 std::vector<int> zero(bin_dimensions_.size(), 0);
194 dp_states_.push_back(
new DpState({0, 0, zero, -1, -1}));
195 for (
int i = 0; i < dp_states_.size(); ++i) {
196 ForwardCreationPass(dp_states_[i]);
202 const int64_t num_dp_states = NumDpStates();
203 dp_state_index_.clear();
206 const int num_states = dp_states_.size();
207 std::vector<std::pair<int, int>> flat_deps;
208 for (
int i = 0; i < dp_states_.size(); ++i) {
209 if (dp_states_[i]->
up_child != -1) {
210 flat_deps.push_back(std::make_pair(dp_states_[i]->
up_child, i));
213 flat_deps.push_back(std::make_pair(dp_states_[i]->
right_child, i));
216 const std::vector<int> sorted_work =
218 for (
const int w : sorted_work) {
219 BackwardCompressionPass(w);
223 const std::vector<int> source_node = dp_states_[0]->used_dimensions;
226 ForwardCompressionPass(source_node);
230 const int sink_node_index = nodes_.size() - 1;
231 for (
int node = 1; node < sink_node_index; ++node) {
232 arcs_.insert({node, sink_node_index, -1});
236 result.arcs.assign(arcs_.begin(), arcs_.end());
237 result.nodes.assign(nodes_.begin(), nodes_.end());
238 result.num_dp_states = num_dp_states;
242 int ArcFlowBuilder::LookupOrCreateDpState(
244 VectorIntIntMap& map = dp_state_index_[item][quantity];
247 if (
index == dp_states_.size()) {
248 dp_states_.push_back(
254 void ArcFlowBuilder::ForwardCreationPass(DpState* dp_state) {
255 const int item = dp_state->cur_item_index;
256 const int quantity = dp_state->cur_item_quantity;
260 if (item < items_.size() - 1) {
261 dp_state->up_child = LookupOrCreateDpState(item + 1, 0,
used_dimensions);
263 dp_state->up_child = -1;
269 dp_state->right_child = LookupOrCreateDpState(item, quantity + 1, added);
271 dp_state->right_child = -1;
275 void ArcFlowBuilder::BackwardCompressionPass(
int state_index) {
277 std::vector<int>& result = dp_states_[state_index]->used_dimensions;
280 const int up_index = dp_states_[state_index]->up_child;
281 const std::vector<int>& result_up =
282 up_index == -1 ? bin_dimensions_ : dp_states_[up_index]->used_dimensions;
286 const int right_index = dp_states_[state_index]->right_child;
287 if (right_index == -1)
return;
288 const std::vector<int>& result_right =
289 dp_states_[right_index]->used_dimensions;
290 const Item& item = items_[dp_states_[state_index]->cur_item_index];
291 for (
int d = 0; d < bin_dimensions_.size(); ++d) {
292 result[d] =
std::min(result[d], result_right[d] - item.dimensions[d]);
296 const int node = GetOrCreateNode(result);
297 const int right_node = GetOrCreateNode(result_right);
298 DCHECK_NE(node, right_node);
299 arcs_.insert({node, right_node, item.original_index});
301 if (result != result_up) {
302 const int up_node = GetOrCreateNode(result_up);
303 arcs_.insert({node, up_node, -1});
311 void ArcFlowBuilder::ForwardCompressionPass(
312 const std::vector<int>& source_node) {
313 const int num_nodes = node_indices_.size();
314 const int num_dims = bin_dimensions_.size();
315 std::set<ArcFlowGraph::Arc> new_arcs;
316 std::vector<std::vector<int>> new_nodes;
317 VectorIntIntMap new_node_indices;
318 std::vector<int> node_remap(num_nodes, -1);
320 std::vector<int> reverse_item_index_map(items_.size(), -1);
321 for (
int i = 0; i < items_.size(); ++i) {
322 reverse_item_index_map[items_[i].original_index] = i;
325 std::vector<std::pair<int, int>> forward_deps;
326 std::vector<std::vector<ArcFlowGraph::Arc>> incoming_arcs(num_nodes);
327 for (
const ArcFlowGraph::Arc&
arc : arcs_) {
328 forward_deps.push_back(std::make_pair(
arc.source,
arc.destination));
329 incoming_arcs[
arc.destination].push_back(
arc);
332 const std::vector<int> sorted_work =
335 const int old_source_node = GetOrCreateNode(source_node);
336 const int old_sink_node = GetOrCreateNode(bin_dimensions_);
337 CHECK_EQ(sorted_work.front(), old_source_node);
338 CHECK_EQ(sorted_work.back(), old_sink_node);
342 for (
const int w : sorted_work) {
343 std::vector<int> new_used(num_dims, 0);
344 if (w == sorted_work.back()) {
345 new_used = bin_dimensions_;
347 for (
const ArcFlowGraph::Arc&
arc : incoming_arcs[w]) {
349 arc.item_index == -1 ? -1 : reverse_item_index_map[
arc.item_index];
350 const int prev_node = node_remap[
arc.source];
351 const std::vector<int>& prev = new_nodes[prev_node];
352 DCHECK_NE(prev_node, -1);
353 for (
int d = 0; d < num_dims; ++d) {
358 new_used[d] =
std::max(new_used[d], prev[d]);
363 const auto& it = new_node_indices.find(new_used);
364 if (it != new_node_indices.end()) {
365 node_remap[w] = it->second;
367 const int new_index = new_nodes.size();
368 new_nodes.push_back(new_used);
369 new_node_indices[new_used] = new_index;
370 node_remap[w] = new_index;
374 for (
const ArcFlowGraph::Arc&
arc : arcs_) {
375 CHECK_NE(node_remap[
arc.source], -1);
376 CHECK_NE(node_remap[
arc.destination], -1);
378 if (
arc.item_index == -1 &&
379 node_remap[
arc.source] == node_remap[
arc.destination])
382 {node_remap[
arc.source], node_remap[
arc.destination],
arc.item_index});
384 VLOG(1) <<
"Reduced nodes from " << num_nodes <<
" to " << new_nodes.size();
385 VLOG(1) <<
"Reduced arcs from " << arcs_.size() <<
" to " << new_arcs.size();
388 CHECK_NE(node_remap[old_source_node], -1);
389 CHECK_EQ(0, node_remap[old_source_node]);
390 CHECK_NE(node_remap[old_sink_node], -1);
391 CHECK_EQ(nodes_.size() - 1, node_remap[old_sink_node]);
397 if (source != other.
source)
return source < other.
source;
403 const std::vector<int>& bin_dimensions,
404 const std::vector<std::vector<int>>& item_dimensions_by_type,
405 const std::vector<int>& demand_by_type) {
406 ArcFlowBuilder afb(bin_dimensions, item_dimensions_by_type, demand_by_type);
407 return afb.BuildVectorBinPackingGraph();
std::vector< int > dimensions
std::vector< int > used_dimensions
void STLDeleteElements(T *container)
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.
std::vector< int > DenseIntStableTopologicalSortOrDie(int num_nodes, const std::vector< std::pair< int, int >> &arcs)
#define VLOG(verboselevel)