jagua_rs/probs/spp/io/
import.rs1use crate::entities::{Instance, Item};
2use crate::geometry::DTransformation;
3use crate::geometry::shape_modification::ShapeModifyConfig;
4use crate::io::import::{Importer, ext_to_int_transformation};
5use crate::probs::spp::entities::{SPInstance, SPPlacement, SPProblem, SPSolution, Strip};
6use crate::probs::spp::io::ext_repr::{ExtSPInstance, ExtSPSolution};
7use anyhow::{Result, ensure};
8use itertools::Itertools;
9use rayon::prelude::*;
10
11pub fn import_instance(importer: &Importer, ext_instance: &ExtSPInstance) -> Result<SPInstance> {
13 let items: Vec<(Item, usize)> = {
14 let mut items = ext_instance
15 .items
16 .par_iter()
17 .map(|ext_item| {
18 let item = importer.import_item(&ext_item.base)?;
19 let demand = ext_item.demand as usize;
20 Ok((item, demand))
21 })
22 .collect::<Result<Vec<(Item, usize)>>>()?;
23
24 items.sort_by_key(|(item, _)| item.id);
25 items.retain(|(_, demand)| *demand > 0);
26
27 ensure!(
28 items.iter().enumerate().all(|(i, (item, _))| item.id == i),
29 "All items should have consecutive IDs starting from 0. IDs: {:?}",
30 items.iter().map(|(item, _)| item.id).sorted().collect_vec()
31 );
32 ensure!(
33 !items.is_empty(),
34 "ExtSPInstance must have at least one item with positive demand"
35 );
36
37 items
38 };
39
40 let total_item_area = items
41 .iter()
42 .map(|(item, demand)| item.area() * *demand as f32)
43 .sum::<f32>();
44
45 let fixed_height = ext_instance.strip_height;
46
47 let width = total_item_area / fixed_height;
49
50 let base_strip = Strip::new(
51 fixed_height,
52 importer.cde_config,
53 ShapeModifyConfig {
54 offset: importer.shape_modify_config.offset,
55 simplify_tolerance: None,
56 narrow_concavity_cutoff_ratio: None,
57 },
58 width,
59 )?;
60
61 Ok(SPInstance::new(items, base_strip))
62}
63
64pub fn import_solution(instance: &SPInstance, ext_solution: &ExtSPSolution) -> SPSolution {
66 let mut prob = SPProblem::new(instance.clone());
67 prob.change_strip_width(ext_solution.strip_width);
68
69 for ext_placement in ext_solution.layout.placed_items.iter().cloned() {
70 let item_id = ext_placement.item_id as usize;
71 let d_transf = {
72 let ext_transf = DTransformation::from(ext_placement.transformation);
73 let item = &instance.item(item_id);
74 ext_to_int_transformation(&ext_transf, &item.shape_orig.pre_transform)
75 };
76 prob.place_item(SPPlacement { item_id, d_transf });
77 }
78
79 prob.save()
80}