jagua_rs/probs/spp/io/
import.rs

1use 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/// Imports an instance into the library
12pub 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    // Initialize the base width for 100% density
48    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
64/// Imports a solution into the library.
65pub 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}