diff --git a/jaguars/src/entities/instance.rs b/jaguars/src/entities/instance.rs
index e4db08b..a4fa028 100644
--- a/jaguars/src/entities/instance.rs
+++ b/jaguars/src/entities/instance.rs
@@ -6,7 +6,9 @@ use crate::util::assertions;
/// Static representation of a problem instance.
#[derive(Debug)]
pub struct Instance {
+ /// Items to be packed in the instance, along with their requested quantities
items: Vec<(Item, usize)>,
+ /// Total area of all items in the instance
item_area: f64,
packing_type: PackingType,
}
diff --git a/jaguars/src/entities/problems/bin_packing.rs b/jaguars/src/entities/problems/bin_packing.rs
index 5d79458..29db927 100644
--- a/jaguars/src/entities/problems/bin_packing.rs
+++ b/jaguars/src/entities/problems/bin_packing.rs
@@ -7,8 +7,8 @@ use crate::entities::placing_option::PlacingOption;
use crate::entities::instance::{Instance, PackingType};
use crate::entities::layout::Layout;
use crate::entities::placed_item::PlacedItemUID;
-use crate::entities::problems::problem::{LayoutIndex, Problem};
-use crate::entities::problems::problem::private::ProblemPrivate;
+use crate::entities::problems::problem::{LayoutIndex, ProblemVariant};
+use crate::entities::problems::problem::private::ProblemVariantPrivate;
use crate::entities::solution::Solution;
use crate::util::assertions;
@@ -114,7 +114,7 @@ impl BPProblem {
}
}
-impl Problem for BPProblem {
+impl ProblemVariant for BPProblem {
fn place_item(&mut self, i_opt: &PlacingOption) {
let item_id = i_opt.item_id;
let layout = match &i_opt.layout_index {
@@ -280,7 +280,7 @@ impl Problem for BPProblem {
}
-impl ProblemPrivate for BPProblem {
+impl ProblemVariantPrivate for BPProblem {
fn next_solution_id(&mut self) -> usize {
self.solution_id_counter += 1;
self.solution_id_counter
diff --git a/jaguars/src/entities/problems/problem.rs b/jaguars/src/entities/problems/problem.rs
index 853fc27..f0d7169 100644
--- a/jaguars/src/entities/problems/problem.rs
+++ b/jaguars/src/entities/problems/problem.rs
@@ -9,28 +9,29 @@ use crate::entities::instance::Instance;
use crate::entities::layout::Layout;
use crate::entities::placed_item::PlacedItemUID;
use crate::entities::problems::bin_packing::BPProblem;
-use crate::entities::problems::problem::private::ProblemPrivate;
+use crate::entities::problems::problem::private::ProblemVariantPrivate;
use crate::entities::problems::strip_packing::SPProblem;
use crate::entities::solution::Solution;
-/// Enum which contains all the different types implementing the Problem trait.
+/// Enum which contains all the different types implementing the `ProblemVariant` trait.
+/// A `Problem` represents a problem instance in a modifiable state.
+/// It can insert or remove items, create a snapshot from the current state called a `Solution`,
+/// and restore its state to a previous `Solution`.
+///
/// Uses the enum_dispatch crate to have performant polymorphism for different problem types, see
/// for more information on enum_dispatch
#[derive(Clone)]
#[enum_dispatch]
-pub enum ProblemType {
+pub enum Problem {
/// Bin Packing Problem
BP(BPProblem),
/// Strip Packing Problem
SP(SPProblem),
}
-/// Trait for public shared functionality of all problem types.
-/// A `Problem` represents a problem instance in a modifiable state.
-/// It can insert or remove items, create a snapshot from the current state called a `Solution`,
-/// and restore its state to a previous `Solution`.
-#[enum_dispatch(ProblemType)]
-pub trait Problem: ProblemPrivate {
+/// Trait for public shared functionality of all problem variants.
+#[enum_dispatch(Problem)]
+pub trait ProblemVariant: ProblemVariantPrivate {
/// Places an item into the problem instance according to the given `PlacingOption`.
fn place_item(&mut self, i_opt: &PlacingOption);
@@ -51,8 +52,13 @@ pub trait Problem: ProblemPrivate {
fn layouts_mut(&mut self) -> &mut [Layout];
+
+ /// Returns layouts of the problem instance, which are currently empty (no items placed in them).
+ /// These layouts can be used to place items into.
fn empty_layouts(&self) -> &[Layout];
+ /// The quantity of each item that is requested but currently missing in the problem instance.
+ /// Indexed by item id.
fn missing_item_qtys(&self) -> &[isize];
fn usage(&mut self) -> f64 {
@@ -106,11 +112,11 @@ pub trait Problem: ProblemPrivate {
pub(super) mod private {
use enum_dispatch::enum_dispatch;
- use crate::entities::problems::problem::ProblemType;
+ use crate::entities::problems::problem::Problem;
- /// Trait for shared functionality of all problem types, but not exposed to the public.
- #[enum_dispatch(ProblemType)]
- pub trait ProblemPrivate : Clone {
+ /// Trait for shared functionality of all problem variants, but not exposed to the public.
+ #[enum_dispatch(Problem)]
+ pub trait ProblemVariantPrivate: Clone {
fn next_solution_id(&mut self) -> usize;
fn missing_item_qtys_mut(&mut self) -> &mut [isize];
diff --git a/jaguars/src/entities/problems/strip_packing.rs b/jaguars/src/entities/problems/strip_packing.rs
index 4a3993a..40108e1 100644
--- a/jaguars/src/entities/problems/strip_packing.rs
+++ b/jaguars/src/entities/problems/strip_packing.rs
@@ -10,8 +10,8 @@ use crate::entities::placing_option::PlacingOption;
use crate::entities::instance::{Instance, PackingType};
use crate::entities::layout::Layout;
use crate::entities::placed_item::PlacedItemUID;
-use crate::entities::problems::problem::{LayoutIndex, Problem};
-use crate::entities::problems::problem::private::ProblemPrivate;
+use crate::entities::problems::problem::{LayoutIndex, ProblemVariant};
+use crate::entities::problems::problem::private::ProblemVariantPrivate;
use crate::entities::solution::Solution;
use crate::geometry::geo_traits::{Shape, Transformable};
use crate::util::assertions;
@@ -103,7 +103,7 @@ impl SPProblem {
}
}
-impl Problem for SPProblem {
+impl ProblemVariant for SPProblem {
fn place_item(&mut self, i_opt: &PlacingOption) {
assert_eq!(i_opt.layout_index, LayoutIndex::Existing(0), "strip packing problems only have a single layout");
let item_id = i_opt.item_id;
@@ -173,7 +173,7 @@ impl Problem for SPProblem {
}
-impl ProblemPrivate for SPProblem {
+impl ProblemVariantPrivate for SPProblem {
fn next_solution_id(&mut self) -> usize {
self.solution_id_counter += 1;
self.solution_id_counter
diff --git a/jaguars/src/io/parser.rs b/jaguars/src/io/parser.rs
index 370c14a..ef24b3f 100644
--- a/jaguars/src/io/parser.rs
+++ b/jaguars/src/io/parser.rs
@@ -9,7 +9,7 @@ use crate::entities::instance::{Instance, PackingType};
use crate::entities::item::Item;
use crate::entities::placing_option::PlacingOption;
use crate::entities::problems::bin_packing::BPProblem;
-use crate::entities::problems::problem::{LayoutIndex, ProblemType, Problem};
+use crate::entities::problems::problem::{LayoutIndex, Problem, ProblemVariant};
use crate::entities::problems::strip_packing::SPProblem;
use crate::entities::quality_zone::QualityZone;
use crate::entities::solution::Solution;
@@ -174,14 +174,14 @@ impl Parser {
}
fn build_solution_from_json(json_layouts: &[JsonLayout], instance: Arc, cde_config: CDEConfig) -> Solution {
- let mut problem: ProblemType = match instance.packing_type() {
- PackingType::BinPacking(_) => ProblemType::BP(BPProblem::new(instance.clone())),
+ let mut problem: Problem = match instance.packing_type() {
+ PackingType::BinPacking(_) => Problem::BP(BPProblem::new(instance.clone())),
PackingType::StripPacking { .. } => {
assert_eq!(json_layouts.len(), 1);
match json_layouts[0].object_type {
JsonObjectType::Object { .. } => panic!("Strip packing solution should not contain layouts with references to an Object"),
JsonObjectType::Strip { width, height: _ } => {
- ProblemType::SP(SPProblem::new(instance.clone(), width, cde_config))
+ Problem::SP(SPProblem::new(instance.clone(), width, cde_config))
}
}
}
diff --git a/jaguars/src/util/assertions.rs b/jaguars/src/util/assertions.rs
index dccf1b9..cb387e9 100644
--- a/jaguars/src/util/assertions.rs
+++ b/jaguars/src/util/assertions.rs
@@ -16,7 +16,7 @@ use crate::entities::bin::Bin;
use crate::entities::instance::PackingType;
use crate::entities::item::Item;
use crate::entities::layout::Layout;
-use crate::entities::problems::problem::Problem;
+use crate::entities::problems::problem::ProblemVariant;
use crate::entities::solution::Solution;
use crate::entities::layout::LayoutSnapshot;
use crate::geometry::geo_traits::{Shape, Transformable};
@@ -48,7 +48,7 @@ pub fn instance_item_bin_ids_correct(items: &Vec<(Item, usize)>, packing_type: &
};
}
-pub fn problem_matches_solution(problem: &P, solution: &Solution) -> bool {
+pub fn problem_matches_solution(problem: &P, solution: &Solution) -> bool {
for l in problem.layouts() {
let sl = solution.layout_snapshots.iter().find(|sl| sl.id() == l.id()).unwrap();
match layouts_match(l, sl) {
diff --git a/lbf/benches/edge_sensitivity_bench.rs b/lbf/benches/edge_sensitivity_bench.rs
index 3981574..5303d43 100644
--- a/lbf/benches/edge_sensitivity_bench.rs
+++ b/lbf/benches/edge_sensitivity_bench.rs
@@ -9,7 +9,7 @@ use rand::prelude::{IteratorRandom, SmallRng};
use rand::SeedableRng;
use jaguars::entities::instance::Instance;
use jaguars::entities::item::Item;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant};
use jaguars::geometry::geo_traits::{Shape, TransformableFrom};
use jaguars::geometry::primitives::point::Point;
use jaguars::geometry::primitives::simple_polygon::SimplePolygon;
diff --git a/lbf/benches/fast_fail_bench.rs b/lbf/benches/fast_fail_bench.rs
index ab53c4a..d116a7a 100644
--- a/lbf/benches/fast_fail_bench.rs
+++ b/lbf/benches/fast_fail_bench.rs
@@ -13,7 +13,7 @@ use tribool::Tribool;
use jaguars::entities::instance::{Instance, PackingType};
use jaguars::entities::placed_item::PlacedItemUID;
use jaguars::entities::placing_option::PlacingOption;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem, ProblemType};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant, Problem};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::geometry::fail_fast::sp_surrogate::SPSurrogate;
use jaguars::geometry::geo_traits::TransformableFrom;
diff --git a/lbf/benches/hpg_bench.rs b/lbf/benches/hpg_bench.rs
index ff19a51..8b67f16 100644
--- a/lbf/benches/hpg_bench.rs
+++ b/lbf/benches/hpg_bench.rs
@@ -10,7 +10,7 @@ use rand::SeedableRng;
use jaguars::entities::layout::Layout;
use jaguars::entities::placing_option::PlacingOption;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::geometry::geo_traits::{Shape, TransformableFrom};
use jaguars::io::json_instance::JsonInstance;
diff --git a/lbf/benches/quadtree_bench.rs b/lbf/benches/quadtree_bench.rs
index 5731326..668fc24 100644
--- a/lbf/benches/quadtree_bench.rs
+++ b/lbf/benches/quadtree_bench.rs
@@ -11,7 +11,7 @@ use rand::seq::IteratorRandom;
use jaguars::entities::instance::{Instance, PackingType};
use jaguars::entities::placed_item::PlacedItemUID;
use jaguars::entities::placing_option::PlacingOption;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem, ProblemType};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant, Problem};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::geometry::geo_traits::TransformableFrom;
use jaguars::io::json_instance::JsonInstance;
diff --git a/lbf/benches/util.rs b/lbf/benches/util.rs
index 6f5a9fd..2d6ed79 100644
--- a/lbf/benches/util.rs
+++ b/lbf/benches/util.rs
@@ -6,7 +6,7 @@ use rand::prelude::{IteratorRandom, SmallRng};
use rand::SeedableRng;
use jaguars::entities::instance::{Instance, PackingType};
use jaguars::entities::placed_item::PlacedItemUID;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem, ProblemType};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant, Problem};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::io::json_instance::JsonInstance;
use jaguars::io::parser::Parser;
@@ -39,7 +39,7 @@ pub fn create_blf_problem(instance: Arc, config: Config, n_items_remov
lbf_optimizer.solve();
let mut problem = match lbf_optimizer.problem().clone() {
- ProblemType::SP(sp_problem) => sp_problem,
+ Problem::SP(sp_problem) => sp_problem,
_ => panic!("Expected SPProblem")
};
diff --git a/lbf/src/lbf_optimizer.rs b/lbf/src/lbf_optimizer.rs
index bf71223..b7a8100 100644
--- a/lbf/src/lbf_optimizer.rs
+++ b/lbf/src/lbf_optimizer.rs
@@ -15,7 +15,7 @@ use jaguars::entities::item::Item;
use jaguars::entities::layout::Layout;
use jaguars::entities::placing_option::PlacingOption;
use jaguars::entities::problems::bin_packing::BPProblem;
-use jaguars::entities::problems::problem::{LayoutIndex, Problem, ProblemType};
+use jaguars::entities::problems::problem::{LayoutIndex, ProblemVariant, Problem};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::entities::solution::Solution;
use jaguars::geometry::convex_hull::convex_hull_from_points;
@@ -36,7 +36,7 @@ pub const ITEM_LIMIT: usize = 1000;
pub struct LBFOptimizer {
instance: Arc,
- problem: ProblemType,
+ problem: Problem,
config: Config,
/// SmallRng is a fast, non-cryptographic PRNG
rng: SmallRng,
@@ -91,8 +91,8 @@ impl LBFOptimizer {
}
None => {
match &mut self.problem {
- ProblemType::BP(_) => break,
- ProblemType::SP(sp_problem) => {
+ Problem::BP(_) => break,
+ Problem::SP(sp_problem) => {
let new_width = sp_problem.strip_width() * 1.1;
info!("Extending the strip by 10%: {:.3}", new_width);
sp_problem.modify_strip_width(new_width);
@@ -104,8 +104,8 @@ impl LBFOptimizer {
}
match &mut self.problem {
- ProblemType::BP(_) => {}
- ProblemType::SP(sp_problem) => {
+ Problem::BP(_) => {}
+ Problem::SP(sp_problem) => {
sp_problem.fit_strip_width();
info!("Final strip width: {:.3}", sp_problem.strip_width());
}
@@ -121,7 +121,7 @@ impl LBFOptimizer {
pub fn instance(&self) -> &Arc {
&self.instance
}
- pub fn problem(&self) -> &ProblemType {
+ pub fn problem(&self) -> &Problem {
&self.problem
}
pub fn config(&self) -> &Config {
@@ -129,7 +129,7 @@ impl LBFOptimizer {
}
}
-fn find_placement(problem: &ProblemType, item: &Item, config: &Config, rng: &mut impl Rng) -> Option {
+fn find_placement(problem: &Problem, item: &Item, config: &Config, rng: &mut impl Rng) -> Option {
let layouts_to_sample =
(0..problem.layouts().len()).map(|i| (LayoutIndex::Existing(i)))
.chain((0..problem.empty_layouts().len())
@@ -144,7 +144,7 @@ fn find_placement(problem: &ProblemType, item: &Item, config: &Config, rng: &mut
best_i_opt
}
-pub fn sample_layout(problem: &ProblemType, layout_index: LayoutIndex, item: &Item, config: &Config, rng: &mut impl Rng) -> Option {
+pub fn sample_layout(problem: &Problem, layout_index: LayoutIndex, item: &Item, config: &Config, rng: &mut impl Rng) -> Option {
let item_id = item.id();
let layout: &Layout = problem.get_layout(&layout_index);
let entities_to_ignore = item.hazard_filter()