Skip to content

Commit

Permalink
jaguars: ff poles changes; lbf: benches changes
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenGar committed Feb 16, 2024
1 parent 47f4b56 commit 511e131
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 82 deletions.
17 changes: 8 additions & 9 deletions jaguars/src/geometry/fail_fast/sp_surrogate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,31 @@ pub struct SPSurrogate {
pub poles: Vec<Circle>,
pub poles_bounding_circle: Circle,
pub piers: Vec<Edge>,
pub ff_pole_range: Range<usize>,
pub n_ff_poles: usize,
}

impl SPSurrogate {
pub fn new(simple_poly: &SimplePolygon, config: SPSurrogateConfig) -> Self {
let convex_hull_indices = convex_hull::convex_hull_indices(simple_poly);
let mut poles = vec![simple_poly.poi().clone()];
poles.extend(poi::generate_additional_surrogate_poles(simple_poly, config.max_poles, config.pole_coverage_goal));
poles.extend(poi::generate_additional_surrogate_poles(simple_poly, config.max_poles.saturating_sub(1), config.pole_coverage_goal));
let poles_bounding_circle = Circle::bounding_circle(&poles);

let relevant_poles_for_piers = &poles[0..config.n_ff_poles+1]; //poi + all poles that will be checked during fail fast are relevant for piers
let n_ff_poles = usize::min(config.n_ff_poles, poles.len());
let relevant_poles_for_piers = &poles[0..n_ff_poles]; //poi + all poles that will be checked during fail fast are relevant for piers
let piers = piers::generate(simple_poly, config.n_ff_piers, relevant_poles_for_piers);
let ff_pole_range = 1..config.n_ff_poles+1;

Self {
convex_hull_indices,
poles,
piers,
poles_bounding_circle,
ff_pole_range
n_ff_poles
}
}

pub fn ff_poles(&self) -> &[Circle] {
let range = self.ff_pole_range.clone();
&self.poles[range]
&self.poles[0..self.n_ff_poles]
}

pub fn ff_piers(&self) -> &[Edge] {
Expand All @@ -51,7 +50,7 @@ impl SPSurrogate {
impl Transformable for SPSurrogate {
fn transform(&mut self, t: &Transformation) -> &mut Self {
//destructuring pattern used to ensure that the code is updated accordingly when the struct changes
let Self {convex_hull_indices: _, poles, poles_bounding_circle, piers, ff_pole_range: _} = self;
let Self {convex_hull_indices: _, poles, poles_bounding_circle, piers, n_ff_poles: _} = self;

//transform poles
poles.iter_mut().for_each(|c| {
Expand All @@ -75,7 +74,7 @@ impl TransformableFrom for SPSurrogate {
debug_assert!(self.piers.len() == reference.piers.len());

//destructuring pattern used to ensure that the code is updated accordingly when the struct changes
let Self {convex_hull_indices: _, poles, poles_bounding_circle, piers, ff_pole_range: _} = self;
let Self {convex_hull_indices: _, poles, poles_bounding_circle, piers, n_ff_poles: _} = self;

for (pole, ref_pole) in poles.iter_mut().zip(reference.poles.iter()) {
pole.transform_from(ref_pole, t);
Expand Down
133 changes: 70 additions & 63 deletions lbf/benches/fast_fail_bench.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
use std::fs::File;
use std::io::BufReader;
use std::ops::RangeInclusive;
use std::path::Path;
use std::sync::Arc;

use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use itertools::Itertools;
use log::debug;
use rand::prelude::{IteratorRandom, SmallRng};
use rand::SeedableRng;
use rand_distr::num_traits::real::Real;
use tribool::Tribool;

use jaguars::entities::instance::InstanceGeneric;
use jaguars::entities::instance::{Instance};
use jaguars::entities::placed_item::PlacedItemUID;
use jaguars::entities::placing_option::PlacingOption;
use jaguars::entities::problems::problem::{LayoutIndex, ProblemGeneric, Problem};
use jaguars::entities::problems::strip_packing::SPProblem;
use jaguars::entities::problems::problem::{LayoutIndex, ProblemGeneric};
use jaguars::geometry::convex_hull;
use jaguars::geometry::fail_fast::{piers, poi};
use jaguars::geometry::fail_fast::sp_surrogate::SPSurrogate;
use jaguars::geometry::geo_traits::TransformableFrom;
use jaguars::geometry::transformation::Transformation;
use jaguars::geometry::primitives::circle::Circle;
use jaguars::geometry::primitives::simple_polygon::SimplePolygon;
use jaguars::io::json_instance::JsonInstance;
use jaguars::io::parser::Parser;
use jaguars::util::config::{CDEConfig, HazProxConfig, QuadTreeConfig, SPSurrogateConfig};
use jaguars::util::polygon_simplification::PolySimplConfig;
use lbf::config::Config;
use lbf::io;
use lbf::io::layout_to_svg::layout_to_svg;
use lbf::io::svg_util::SvgDrawOptions;
use lbf::lbf_optimizer::LBFOptimizer;
use jaguars::util::config::HazProxConfig;
use lbf::samplers::hpg_sampler::HPGSampler;
use lbf::samplers::uniform_rect_sampler::UniformAARectSampler;

use crate::util::{create_base_config, N_ITEMS_REMOVED, N_SAMPLES_PER_ITER, N_TOTAL_SAMPLES, SWIM_PATH};

criterion_main!(benches);
criterion_group!(benches, fast_fail_query_bench);

mod util;

const FF_POLE_RANGE: RangeInclusive<usize> = 0..=4;
const FF_PIER_RANGE: RangeInclusive<usize> = 0..=4;
//const FF_POLE_RANGE: &[usize] = &[0,1,2,3,4];
//const FF_PIER_RANGE: &[usize] = &[0,1,2,3,4];

const FF_POLE_RANGE: &[usize] = &[5,6,7,8,9,10];
const FF_PIER_RANGE: &[usize] = &[0];
const ITEMS_ID_TO_TEST: &[usize] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

/// Benchmark the query operation of the quadtree for different depths
/// We validate 1000 sampled transformations for each of the 5 removed items
Expand All @@ -47,63 +41,54 @@ fn fast_fail_query_bench(c: &mut Criterion) {

let mut group = c.benchmark_group("fast_fail_query_bench");

let config_combos= FF_POLE_RANGE.map(|n_ff_poles| FF_PIER_RANGE.map(|n_ff_piers| (n_ff_poles, n_ff_piers)).collect_vec()).flatten().collect_vec();
let config_combos = FF_POLE_RANGE.iter().map(|n_ff_poles|
FF_PIER_RANGE.iter().map(|n_ff_piers| (*n_ff_poles, *n_ff_piers)).collect_vec())
.flatten().collect_vec();

for ff_surr_config in config_combos {
let mut config = create_base_config();
config.cde_config.item_surrogate_config.n_ff_poles = ff_surr_config.0;
config.cde_config.item_surrogate_config.n_ff_piers = ff_surr_config.1;
let mut config = create_base_config();
config.cde_config.haz_prox = HazProxConfig::Enabled { n_cells: 5000};

let instance = util::create_instance(&json_instance, config.cde_config, config.poly_simpl_config);
let (mut problem, selected_pi_uids) = util::create_blf_problem(instance.clone(), config, N_ITEMS_REMOVED);
let instance = util::create_instance(&json_instance, config.cde_config, config.poly_simpl_config);
let (mut problem, _) = util::create_blf_problem(instance.clone(), config, N_ITEMS_REMOVED);

let mut rng = SmallRng::seed_from_u64(0);
println!("avg number of edges per item: {}", ITEMS_ID_TO_TEST.iter().map(|&item_id| instance.item(item_id).shape().number_of_points()).sum::<usize>() as f64 / ITEMS_ID_TO_TEST.len() as f64);

/*{
let draw_options = SvgDrawOptions{
quadtree: true,
surrogate: true,
..SvgDrawOptions::default()
};
let svg = io::layout_to_svg::layout_to_svg(problem.get_layout(&layout_index), &instance, draw_options);
io::write_svg(&svg, Path::new("removed_items.svg"));
}*/
let mut rng = SmallRng::seed_from_u64(0);
let layout = problem.get_layout(LayoutIndex::Existing(0));
let samples = ITEMS_ID_TO_TEST.iter()
.map(|&item_id| {
let sampler = HPGSampler::new(instance.item(item_id), layout).unwrap();
(0..N_TOTAL_SAMPLES).map(|_| sampler.sample(&mut rng)).collect_vec()
}).collect_vec();

for ff_surr_config in config_combos {
let (n_ff_poles, n_ff_piers) = ff_surr_config;

let custom_surrogates = selected_pi_uids.iter().map(|pi_uid| {
let item = instance.item(pi_uid.item_id);
let mut surrogate = item.shape().surrogate().clone();
surrogate.ff_pole_range = 0..n_ff_poles; //also check PoI, which is not standard
surrogate
}).collect_vec();

let layout = problem.get_layout(LayoutIndex::Existing(0));
let samples = (0..N_ITEMS_REMOVED)
.map(|i| selected_pi_uids[i].item_id)
.map(|item_id| {
let item = instance.item(item_id);
let sampler = HPGSampler::new(item, layout).unwrap();
(0..N_TOTAL_SAMPLES).map(
|_| sampler.sample(&mut rng)
).collect_vec()
}).collect_vec();
let custom_surrogates = ITEMS_ID_TO_TEST.iter()
.map(|&item_id| create_custom_surrogate(instance.item(item_id).shape(), n_ff_poles, n_ff_piers))
.collect_vec();

let mut samples_cycler = samples.iter().map(|s| s.chunks(N_SAMPLES_PER_ITER).cycle()).collect_vec();
let mut samples_cyclers = samples.iter()
.map(|s| s.chunks(N_SAMPLES_PER_ITER).cycle())
.collect_vec();

let mut n_invalid: i64 = 0;
let mut n_valid : i64 = 0;
let mut n_valid: i64 = 0;

let mut i_cycler = ITEMS_ID_TO_TEST.iter().enumerate().cycle();

let mut i_cycler = (0..N_ITEMS_REMOVED).cycle();
let mut buffer_shapes = ITEMS_ID_TO_TEST.iter()
.map(|&item_id| instance.item(item_id))
.map(|item| item.shape().clone_and_strip_surrogate())
.collect_vec();

group.bench_function(BenchmarkId::from_parameter(format!("{n_ff_poles}_poles_{n_ff_piers}_piers")), |b| {
b.iter(|| {
let i = i_cycler.next().unwrap();
let pi_uid = &selected_pi_uids[i];
let item = instance.item(pi_uid.item_id);
let (i, &item_id) = i_cycler.next().unwrap();
let item = instance.item(item_id);
let surrogate = &custom_surrogates[i];
let mut buffer_shape = item.shape().clone();
for transf in samples_cycler[i].next().unwrap() {
let buffer_shape = &mut buffer_shapes[i];
for transf in samples_cyclers[i].next().unwrap() {
let collides = match layout.cde().surrogate_collides(surrogate, transf, &[]) {
true => true,
false => {
Expand All @@ -121,4 +106,26 @@ fn fast_fail_query_bench(c: &mut Criterion) {
println!("{:.3}% valid", n_valid as f64 / (n_invalid + n_valid) as f64 * 100.0);
}
group.finish();
}

pub fn create_custom_surrogate(simple_poly: &SimplePolygon, n_poles: usize, n_piers: usize) -> SPSurrogate {
let convex_hull_indices = convex_hull::convex_hull_indices(simple_poly);
let mut poles = vec![simple_poly.poi().clone()];
poles.extend(poi::generate_additional_surrogate_poles(simple_poly, n_poles.saturating_sub(1), 0.9));
let poles_bounding_circle = Circle::bounding_circle(&poles);

let n_ff_poles = usize::min(n_poles, poles.len());
let relevant_poles_for_piers = &poles[0..n_ff_poles];
let piers = piers::generate(simple_poly, n_piers, relevant_poles_for_piers);

let surrogate = SPSurrogate {
convex_hull_indices,
poles,
piers,
poles_bounding_circle,
n_ff_poles,
};

dbg!(surrogate.ff_poles().len(), surrogate.ff_piers().len());
surrogate
}
13 changes: 7 additions & 6 deletions lbf/benches/hpg_bench.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fs::File;
use std::io::BufReader;
use std::ops::RangeInclusive;
use std::path::Path;

use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
Expand All @@ -24,13 +25,13 @@ use lbf::samplers::hpg_sampler::HPGSampler;
use crate::util::{create_base_config, N_ITEMS_REMOVED, N_VALID_SAMPLES, SWIM_PATH};

criterion_main!(benches);
criterion_group!(benches, hpg_update_bench, hpg_query_bench);
criterion_group!(benches,hpg_query_bench, hpg_update_bench);

mod util;

//pub const N_HPG_CELLS: [usize; 8] = [1, 50, 100, 500, 1000, 5000, 10000, 20000];

pub const N_HPG_CELLS: [usize; 6] = [100, 500, 1000, 5000, 10000, 20000];
pub const N_HPG_CELLS: [usize; 6] = [100, 500, 1000, 2000, 5000, 10000];
pub const SELECTED_ITEM_ID: usize = 1; // relatively small and "round" item, guaranteed to find valid samples even without HPG

fn hpg_query_bench(c: &mut Criterion) {
Expand Down Expand Up @@ -61,7 +62,7 @@ fn hpg_query_bench(c: &mut Criterion) {
});
}

{
/*{
let draw_options = SvgDrawOptions {
quadtree: false,
surrogate: false,
Expand All @@ -70,7 +71,7 @@ fn hpg_query_bench(c: &mut Criterion) {
};
let svg = io::layout_to_svg::layout_to_svg(problem.get_layout(LayoutIndex::Existing(0)), &instance, draw_options);
io::write_svg(&svg, Path::new(&format!("removed_items_{n_hpg_cells}.svg")));
}
}*/


let mut rng = SmallRng::seed_from_u64(0);
Expand Down Expand Up @@ -132,7 +133,7 @@ fn hpg_update_bench(c: &mut Criterion) {
});
}

{
/*{
let draw_options = SvgDrawOptions {
quadtree: false,
surrogate: false,
Expand All @@ -141,7 +142,7 @@ fn hpg_update_bench(c: &mut Criterion) {
};
let svg = io::layout_to_svg::layout_to_svg(problem.get_layout(LayoutIndex::Existing(0)), &instance, draw_options);
io::write_svg(&svg, Path::new(&format!("removed_items_{n_hpg_cells}.svg")));
}
}*/

let mut rng = SmallRng::seed_from_u64(0);

Expand Down
2 changes: 1 addition & 1 deletion lbf/benches/quadtree_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn quadtree_query_update_1000_1(c: &mut Criterion) {
for transf in sample_cycler.next().unwrap() {
buffer_shape.transform_from(item.shape(), &transf);
let collides = layout.cde().shape_collides(&buffer_shape, &[]);
criterion::black_box(collides); // prevent the compiler from optimizing the loop away
criterion::black_box(collides); //prevent the compiler from optimizing the loop away
}

problem.place_item(&PlacingOption {
Expand Down
4 changes: 2 additions & 2 deletions lbf/benches/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn create_blf_problem(instance: Instance, config: Config, n_items_removed: u
{
let draw_options = SvgDrawOptions{
quadtree: true,
surrogate: false,
surrogate: true,
haz_prox_grid: false,
..SvgDrawOptions::default()
};
Expand All @@ -81,7 +81,7 @@ pub fn create_base_config() -> Config {
item_surrogate_config: SPSurrogateConfig {
pole_coverage_goal: 0.9,
max_poles: 10,
n_ff_poles: 2,
n_ff_poles: 4,
n_ff_piers: 0,
},
},
Expand Down
2 changes: 1 addition & 1 deletion lbf/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::EPOCH;
use crate::io::json_output::JsonOutput;

pub mod json_output;
mod svg_export;
pub mod svg_export;
pub mod svg_util;
pub mod layout_to_svg;
pub mod cli;
Expand Down

0 comments on commit 511e131

Please sign in to comment.