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()