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
11#[allow(clippy::cast_precision_loss)]
13pub fn import_instance(importer: &Importer, ext_instance: &ExtSPInstance) -> Result<SPInstance> {
14 let items: Vec<(Item, usize)> = {
15 let mut items = ext_instance
16 .items
17 .par_iter()
18 .map(|ext_item| {
19 let item = importer.import_item(&ext_item.base)?;
20 let demand = usize::try_from(ext_item.demand).unwrap();
21 Ok((item, demand))
22 })
23 .collect::<Result<Vec<(Item, usize)>>>()?;
24
25 items.sort_by_key(|(item, _)| item.id);
26 items.retain(|(_, demand)| *demand > 0);
27
28 ensure!(
29 items.iter().enumerate().all(|(i, (item, _))| item.id == i),
30 "All items should have consecutive IDs starting from 0. IDs: {:?}",
31 items.iter().map(|(item, _)| item.id).sorted().collect_vec()
32 );
33 ensure!(
34 !items.is_empty(),
35 "ExtSPInstance must have at least one item with positive demand"
36 );
37
38 items
39 };
40
41 let total_item_area = items
42 .iter()
43 .map(|(item, demand)| item.area() * *demand as f32)
44 .sum::<f32>();
45
46 let fixed_height = ext_instance.strip_height;
47
48 let width = total_item_area / fixed_height;
50
51 let base_strip = Strip::new(
52 fixed_height,
53 importer.cde_config,
54 ShapeModifyConfig {
55 offset: importer.shape_modify_config.offset,
56 simplify_tolerance: None,
57 narrow_concavity_cutoff: None,
58 },
59 width,
60 )?;
61
62 Ok(SPInstance::new(items, base_strip))
63}
64
65#[must_use]
67pub fn import_solution(instance: &SPInstance, ext_solution: &ExtSPSolution) -> SPSolution {
68 let mut prob = SPProblem::new(instance.clone());
69 prob.change_strip_width(ext_solution.strip_width);
70
71 for ext_placement in ext_solution.layout.placed_items.iter().cloned() {
72 let item_id = usize::try_from(ext_placement.item_id).unwrap();
73 let d_transf = {
74 let ext_transf = DTransformation::from(ext_placement.transformation);
75 let item = &instance.item(item_id);
76 ext_to_int_transformation(&ext_transf, &item.shape_orig.pre_transform)
77 };
78 prob.place_item(SPPlacement { item_id, d_transf });
79 }
80
81 prob.save()
82}