Skip to main content

jagua_rs/probs/bpp/entities/
instance.rs

1use crate::entities::Item;
2use crate::probs::bpp::entities::bin::Bin;
3use crate::probs::bpp::util::assertions::instance_item_bin_ids_correct;
4use itertools::Itertools;
5use std::sync::Arc;
6
7#[derive(Debug, Clone)]
8/// Instance of the Bin Packing Problem.
9pub struct BPInstance {
10    /// The items to be packed and their demands
11    pub items: Vec<(Arc<Item>, usize)>,
12    /// Set of bins available to pack the items
13    pub bins: Vec<Bin>,
14}
15
16impl BPInstance {
17    #[must_use]
18    pub fn new(items: Vec<(Arc<Item>, usize)>, bins: Vec<Bin>) -> Self {
19        assert!(instance_item_bin_ids_correct(&items, &bins));
20
21        assert!(items.iter().map(|(item, _)| item.external_id).all_unique());
22        Self { items, bins }
23    }
24
25    #[allow(clippy::cast_precision_loss)]
26    #[must_use]
27    pub fn item_area(&self) -> f32 {
28        self.items
29            .iter()
30            .map(|(item, qty)| item.shape_orig.area() * *qty as f32)
31            .sum()
32    }
33
34    #[must_use]
35    pub fn item_qty(&self, idx: usize) -> usize {
36        self.items[idx].1
37    }
38
39    pub fn bins(&self) -> impl Iterator<Item = &Bin> {
40        self.bins.iter()
41    }
42
43    #[must_use]
44    pub fn bin_qty(&self, id: usize) -> usize {
45        self.bins[id].stock
46    }
47
48    #[must_use]
49    pub fn total_item_qty(&self) -> usize {
50        self.items.iter().map(|(_, qty)| *qty).sum()
51    }
52
53    /// Retrieve an item by its internal index.
54    #[must_use]
55    pub fn item(&self, idx: usize) -> &Arc<Item> {
56        &self.items[idx].0
57    }
58
59    /// Resolve an external item ID, returning None for unknown or zero-demand items.
60    #[must_use]
61    pub fn item_idx(&self, external_id: u64) -> Option<usize> {
62        self.items
63            .iter()
64            .find(|(item, _)| item.external_id == external_id)
65            .map(|(item, _)| item.idx)
66    }
67}