From 6aee6d63182e99f4a5981c666bdeef662da3fd98 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 14 May 2026 01:53:24 -0600 Subject: [PATCH] style: rustfmt the Phase 1 test additions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The per-file Phase 1 test commits were written without running rustfmt as I went; this pass formats the new test code (long assert_eq! lines wrapped, etc.). Formatting-only — no behavioural change. --- examples/btsp_kroab.rs | 66 ++++++++++++++++++------ examples/mo_knapsack.rs | 56 ++++++++++++--------- examples/tsp_operators_compare.rs | 78 +++++++++++++++++++++-------- examples/tsp_ulysses16.rs | 5 +- src/algorithms/age_moea.rs | 23 +++++++-- src/algorithms/bayesian_opt.rs | 5 +- src/algorithms/cma_es.rs | 40 ++++++++++++--- src/algorithms/genetic_algorithm.rs | 15 ++++-- src/algorithms/grea.rs | 7 ++- src/algorithms/hill_climber.rs | 10 +++- src/algorithms/hype.rs | 5 +- src/algorithms/hyperband.rs | 25 +++++++-- src/algorithms/ibea.rs | 5 +- src/algorithms/mopso.rs | 12 ++++- src/algorithms/nelder_mead.rs | 20 ++++++-- src/algorithms/paes.rs | 18 +++++-- src/algorithms/pesa2.rs | 5 +- src/algorithms/random_search.rs | 6 ++- src/algorithms/rvea.rs | 5 +- src/algorithms/snes.rs | 15 ++++-- src/algorithms/umda.rs | 20 ++++++-- src/explorer/mod.rs | 55 ++++++++++++-------- src/metrics/hypervolume.rs | 20 ++++---- src/metrics/spacing.rs | 5 +- src/operators/permutation.rs | 10 +++- src/operators/real.rs | 22 +++++--- src/pareto/archive.rs | 10 +++- src/pareto/crowding.rs | 12 ++++- src/selection/tournament.rs | 52 +++++++++++++++---- 29 files changed, 466 insertions(+), 161 deletions(-) diff --git a/examples/btsp_kroab.rs b/examples/btsp_kroab.rs index 3cf8906..e65b8bb 100644 --- a/examples/btsp_kroab.rs +++ b/examples/btsp_kroab.rs @@ -33,23 +33,59 @@ use heuropt::prelude::*; /// First 25 cities of TSPLIB KroA100 (EUC_2D). const KROA_25: [(f64, f64); 25] = [ - (1380.0, 939.0), (2848.0, 96.0), (3510.0, 1671.0), (457.0, 334.0), - (3888.0, 666.0), (984.0, 965.0), (2721.0, 1482.0), (1286.0, 525.0), - (2716.0, 1432.0),(738.0, 1325.0), (1251.0, 1832.0), (2728.0, 1698.0), - (3815.0, 169.0), (3683.0, 1533.0),(1247.0, 1945.0), (123.0, 862.0), - (1234.0, 1946.0),(252.0, 1240.0), (611.0, 673.0), (2576.0, 1676.0), - (928.0, 1700.0), (53.0, 857.0), (1807.0, 1711.0), (274.0, 1420.0), + (1380.0, 939.0), + (2848.0, 96.0), + (3510.0, 1671.0), + (457.0, 334.0), + (3888.0, 666.0), + (984.0, 965.0), + (2721.0, 1482.0), + (1286.0, 525.0), + (2716.0, 1432.0), + (738.0, 1325.0), + (1251.0, 1832.0), + (2728.0, 1698.0), + (3815.0, 169.0), + (3683.0, 1533.0), + (1247.0, 1945.0), + (123.0, 862.0), + (1234.0, 1946.0), + (252.0, 1240.0), + (611.0, 673.0), + (2576.0, 1676.0), + (928.0, 1700.0), + (53.0, 857.0), + (1807.0, 1711.0), + (274.0, 1420.0), (2574.0, 946.0), ]; /// First 25 cities of TSPLIB KroB100 (EUC_2D). const KROB_25: [(f64, f64); 25] = [ - (3140.0, 1401.0),(556.0, 1056.0), (3675.0, 1522.0), (1182.0, 1853.0), - (3595.0, 1340.0),(1936.0, 953.0), (2722.0, 1311.0), (2839.0, 2055.0), - (2253.0, 1242.0),(3142.0, 1591.0),(627.0, 1336.0), (936.0, 211.0), - (4014.0, 471.0), (1376.0, 1452.0),(3289.0, 593.0), (1453.0, 67.0), - (1014.0, 1944.0),(2811.0, 1080.0),(3010.0, 1290.0), (1817.0, 1517.0), - (510.0, 458.0), (1717.0, 1693.0),(1252.0, 1633.0), (1693.0, 1374.0), + (3140.0, 1401.0), + (556.0, 1056.0), + (3675.0, 1522.0), + (1182.0, 1853.0), + (3595.0, 1340.0), + (1936.0, 953.0), + (2722.0, 1311.0), + (2839.0, 2055.0), + (2253.0, 1242.0), + (3142.0, 1591.0), + (627.0, 1336.0), + (936.0, 211.0), + (4014.0, 471.0), + (1376.0, 1452.0), + (3289.0, 593.0), + (1453.0, 67.0), + (1014.0, 1944.0), + (2811.0, 1080.0), + (3010.0, 1290.0), + (1817.0, 1517.0), + (510.0, 458.0), + (1717.0, 1693.0), + (1252.0, 1633.0), + (1693.0, 1374.0), (539.0, 1378.0), ]; @@ -182,6 +218,8 @@ fn main() { let owned: Vec>> = result.pareto_front.to_vec(); let hv = hypervolume_2d(&owned, &problem.objectives(), ref_point); println!(); - println!("Hypervolume vs. reference ({}, {}): {:.0}", - ref_point[0], ref_point[1], hv); + println!( + "Hypervolume vs. reference ({}, {}): {:.0}", + ref_point[0], ref_point[1], hv + ); } diff --git a/examples/mo_knapsack.rs b/examples/mo_knapsack.rs index 567cf28..33ac032 100644 --- a/examples/mo_knapsack.rs +++ b/examples/mo_knapsack.rs @@ -39,24 +39,21 @@ const N_ITEMS: usize = 30; /// Profit vector A (one of two objectives), U(10, 100) style. const PROFITS_A: [f64; N_ITEMS] = [ - 61.0, 17.0, 92.0, 49.0, 73.0, 28.0, 84.0, 36.0, 55.0, 78.0, - 23.0, 91.0, 12.0, 67.0, 45.0, 58.0, 33.0, 71.0, 14.0, 26.0, - 87.0, 42.0, 19.0, 65.0, 30.0, 51.0, 79.0, 22.0, 47.0, 88.0, + 61.0, 17.0, 92.0, 49.0, 73.0, 28.0, 84.0, 36.0, 55.0, 78.0, 23.0, 91.0, 12.0, 67.0, 45.0, 58.0, + 33.0, 71.0, 14.0, 26.0, 87.0, 42.0, 19.0, 65.0, 30.0, 51.0, 79.0, 22.0, 47.0, 88.0, ]; /// Profit vector B (the other objective). Intentionally anti-correlated with /// A on many items so the Pareto front spans a wide trade-off. const PROFITS_B: [f64; N_ITEMS] = [ - 24.0, 81.0, 16.0, 67.0, 29.0, 73.0, 41.0, 60.0, 52.0, 19.0, - 77.0, 34.0, 95.0, 22.0, 71.0, 88.0, 56.0, 27.0, 64.0, 90.0, - 18.0, 43.0, 79.0, 31.0, 85.0, 25.0, 38.0, 92.0, 70.0, 13.0, + 24.0, 81.0, 16.0, 67.0, 29.0, 73.0, 41.0, 60.0, 52.0, 19.0, 77.0, 34.0, 95.0, 22.0, 71.0, 88.0, + 56.0, 27.0, 64.0, 90.0, 18.0, 43.0, 79.0, 31.0, 85.0, 25.0, 38.0, 92.0, 70.0, 13.0, ]; /// Item weights. const WEIGHTS: [f64; N_ITEMS] = [ - 35.0, 58.0, 22.0, 71.0, 14.0, 86.0, 31.0, 53.0, 78.0, 19.0, - 44.0, 16.0, 67.0, 88.0, 25.0, 51.0, 33.0, 74.0, 12.0, 47.0, - 63.0, 28.0, 91.0, 36.0, 55.0, 17.0, 82.0, 41.0, 24.0, 68.0, + 35.0, 58.0, 22.0, 71.0, 14.0, 86.0, 31.0, 53.0, 78.0, 19.0, 44.0, 16.0, 67.0, 88.0, 25.0, 51.0, + 33.0, 74.0, 12.0, 47.0, 63.0, 28.0, 91.0, 36.0, 55.0, 17.0, 82.0, 41.0, 24.0, 68.0, ]; /// Capacity = roughly half the total weight (standard Zitzler-Thiele convention). @@ -79,16 +76,16 @@ impl Problem for BiKnapsack { } fn evaluate(&self, take: &Vec) -> Evaluation { - let (pa, pb, w) = take.iter().enumerate().fold( - (0.0_f64, 0.0_f64, 0.0_f64), - |(pa, pb, w), (i, &t)| { - if t { - (pa + PROFITS_A[i], pb + PROFITS_B[i], w + WEIGHTS[i]) - } else { - (pa, pb, w) - } - }, - ); + let (pa, pb, w) = + take.iter() + .enumerate() + .fold((0.0_f64, 0.0_f64, 0.0_f64), |(pa, pb, w), (i, &t)| { + if t { + (pa + PROFITS_A[i], pb + PROFITS_B[i], w + WEIGHTS[i]) + } else { + (pa, pb, w) + } + }); // Penalty: large coefficient on weight overrun, applied to both objectives. let overrun = (w - self.cap).max(0.0); let penalty = 1000.0 * overrun; @@ -122,7 +119,10 @@ struct OnePointCrossoverBool; impl Variation> for OnePointCrossoverBool { fn vary(&mut self, parents: &[Vec], rng: &mut Rng) -> Vec> { - assert!(parents.len() >= 2, "OnePointCrossoverBool requires 2 parents"); + assert!( + parents.len() >= 2, + "OnePointCrossoverBool requires 2 parents" + ); let p1 = &parents[0]; let p2 = &parents[1]; assert_eq!(p1.len(), p2.len(), "parent lengths differ"); @@ -154,14 +154,19 @@ fn main() { RandomBinary { n: N_ITEMS }, CompositeVariation { crossover: OnePointCrossoverBool, - mutation: BitFlipMutation { probability: 1.0 / N_ITEMS as f64 }, + mutation: BitFlipMutation { + probability: 1.0 / N_ITEMS as f64, + }, }, ); let result = optimizer.run(&problem); println!("Bi-objective 0/1 knapsack — Zitzler–Thiele style, 30 items"); - println!("Capacity = {:.0} (≈ half of total weight {:.0})", - cap, WEIGHTS.iter().sum::()); + println!( + "Capacity = {:.0} (≈ half of total weight {:.0})", + cap, + WEIGHTS.iter().sum::() + ); println!(); println!("Total evaluations: {}", result.evaluations); println!("Pareto-front size: {}", result.pareto_front.len()); @@ -202,5 +207,8 @@ fn main() { let owned: Vec>> = result.pareto_front.to_vec(); let hv = hypervolume_2d(&owned, &problem.objectives(), ref_point); println!(); - println!("Hypervolume vs. reference (profit_A=0, profit_B=0): {:.0}", hv); + println!( + "Hypervolume vs. reference (profit_A=0, profit_B=0): {:.0}", + hv + ); } diff --git a/examples/tsp_operators_compare.rs b/examples/tsp_operators_compare.rs index 3ecad5e..28b16b2 100644 --- a/examples/tsp_operators_compare.rs +++ b/examples/tsp_operators_compare.rs @@ -27,23 +27,59 @@ use std::time::Instant; /// First 25 cities of TSPLIB KroA100 (EUC_2D). const KROA_25: [(f64, f64); 25] = [ - (1380.0, 939.0), (2848.0, 96.0), (3510.0, 1671.0), (457.0, 334.0), - (3888.0, 666.0), (984.0, 965.0), (2721.0, 1482.0), (1286.0, 525.0), - (2716.0, 1432.0),(738.0, 1325.0), (1251.0, 1832.0), (2728.0, 1698.0), - (3815.0, 169.0), (3683.0, 1533.0),(1247.0, 1945.0), (123.0, 862.0), - (1234.0, 1946.0),(252.0, 1240.0), (611.0, 673.0), (2576.0, 1676.0), - (928.0, 1700.0), (53.0, 857.0), (1807.0, 1711.0), (274.0, 1420.0), + (1380.0, 939.0), + (2848.0, 96.0), + (3510.0, 1671.0), + (457.0, 334.0), + (3888.0, 666.0), + (984.0, 965.0), + (2721.0, 1482.0), + (1286.0, 525.0), + (2716.0, 1432.0), + (738.0, 1325.0), + (1251.0, 1832.0), + (2728.0, 1698.0), + (3815.0, 169.0), + (3683.0, 1533.0), + (1247.0, 1945.0), + (123.0, 862.0), + (1234.0, 1946.0), + (252.0, 1240.0), + (611.0, 673.0), + (2576.0, 1676.0), + (928.0, 1700.0), + (53.0, 857.0), + (1807.0, 1711.0), + (274.0, 1420.0), (2574.0, 946.0), ]; /// First 25 cities of TSPLIB KroB100 (EUC_2D). const KROB_25: [(f64, f64); 25] = [ - (3140.0, 1401.0),(556.0, 1056.0), (3675.0, 1522.0), (1182.0, 1853.0), - (3595.0, 1340.0),(1936.0, 953.0), (2722.0, 1311.0), (2839.0, 2055.0), - (2253.0, 1242.0),(3142.0, 1591.0),(627.0, 1336.0), (936.0, 211.0), - (4014.0, 471.0), (1376.0, 1452.0),(3289.0, 593.0), (1453.0, 67.0), - (1014.0, 1944.0),(2811.0, 1080.0),(3010.0, 1290.0), (1817.0, 1517.0), - (510.0, 458.0), (1717.0, 1693.0),(1252.0, 1633.0), (1693.0, 1374.0), + (3140.0, 1401.0), + (556.0, 1056.0), + (3675.0, 1522.0), + (1182.0, 1853.0), + (3595.0, 1340.0), + (1936.0, 953.0), + (2722.0, 1311.0), + (2839.0, 2055.0), + (2253.0, 1242.0), + (3142.0, 1591.0), + (627.0, 1336.0), + (936.0, 211.0), + (4014.0, 471.0), + (1376.0, 1452.0), + (3289.0, 593.0), + (1453.0, 67.0), + (1014.0, 1944.0), + (2811.0, 1080.0), + (3010.0, 1290.0), + (1817.0, 1517.0), + (510.0, 458.0), + (1717.0, 1693.0), + (1252.0, 1633.0), + (1693.0, 1374.0), (539.0, 1378.0), ]; @@ -177,7 +213,10 @@ fn main() { println!("Bi-objective TSP (KroAB-25): NSGA-II crossover showdown"); println!("Same population, generations, seed across all runs."); println!("Mutation held constant at InversionMutation."); - println!("Reference point for hypervolume: ({:.0}, {:.0})", REF_POINT[0], REF_POINT[1]); + println!( + "Reference point for hypervolume: ({:.0}, {:.0})", + REF_POINT[0], REF_POINT[1] + ); println!(); let runs = vec![ @@ -189,13 +228,7 @@ fn main() { println!( " {:<24} | {:>5} {:>5} | {:>17} | {:>17} | {:>14} | {:>6}", - "crossover", - "size", - "uniq", - "A-corner (A, B)", - "B-corner (A, B)", - "hypervolume", - "time" + "crossover", "size", "uniq", "A-corner (A, B)", "B-corner (A, B)", "hypervolume", "time" ); println!(" {}", "-".repeat(106)); for r in &runs { @@ -223,5 +256,8 @@ fn main() { .unwrap_or(std::cmp::Ordering::Equal) }) .expect("non-empty runs"); - println!("Best by hypervolume: {} ({:.0})", winner.name, winner.hypervolume); + println!( + "Best by hypervolume: {} ({:.0})", + winner.name, winner.hypervolume + ); } diff --git a/examples/tsp_ulysses16.rs b/examples/tsp_ulysses16.rs index ac77bc6..4f7d613 100644 --- a/examples/tsp_ulysses16.rs +++ b/examples/tsp_ulysses16.rs @@ -152,7 +152,10 @@ fn main() { println!("Source: TSPLIB95 (Groetschel/Padberg)"); println!(); println!("Known optimum: {:>8.0}", KNOWN_OPTIMUM); - println!("GA best found: {:>8.0} (gap {:+.0}, {:+.2}%)", best_len, gap_abs, gap_pct); + println!( + "GA best found: {:>8.0} (gap {:+.0}, {:+.2}%)", + best_len, gap_abs, gap_pct + ); println!(); println!("Total evaluations: {}", result.evaluations); println!("Final population: {}", result.population.len()); diff --git a/src/algorithms/age_moea.rs b/src/algorithms/age_moea.rs index dfde1c6..29fbbe6 100644 --- a/src/algorithms/age_moea.rs +++ b/src/algorithms/age_moea.rs @@ -599,7 +599,10 @@ mod tests { // direction and the loss tie-breaking. let translated = vec![vec![1.0, 0.0], vec![0.0, 1.0]]; let p = estimate_p(&[0, 1], &translated, 2); - assert!((p - 0.25).abs() < 1e-12, "expected smallest candidate, got {p}"); + assert!( + (p - 0.25).abs() < 1e-12, + "expected smallest candidate, got {p}" + ); } #[test] @@ -625,7 +628,11 @@ mod tests { mutation: PolynomialMutation::new(bounds, 20.0, 1.0), }; let mut opt = AgeMoea::new( - AgeMoeaConfig { population_size: 8, generations: 10, seed: 7 }, + AgeMoeaConfig { + population_size: 8, + generations: 10, + seed: 7, + }, initializer, variation, ); @@ -666,7 +673,11 @@ mod tests { }; for pop in [4_usize, 12, 30] { let mut opt = AgeMoea::new( - AgeMoeaConfig { population_size: pop, generations: 5, seed: 13 }, + AgeMoeaConfig { + population_size: pop, + generations: 5, + seed: 13, + }, initializer.clone(), variation.clone(), ); @@ -690,7 +701,11 @@ mod tests { let pop = 6_usize; let gens = 4_usize; let mut opt = AgeMoea::new( - AgeMoeaConfig { population_size: pop, generations: gens, seed: 13 }, + AgeMoeaConfig { + population_size: pop, + generations: gens, + seed: 13, + }, initializer, variation, ); diff --git a/src/algorithms/bayesian_opt.rs b/src/algorithms/bayesian_opt.rs index 594773c..76f7506 100644 --- a/src/algorithms/bayesian_opt.rs +++ b/src/algorithms/bayesian_opt.rs @@ -644,7 +644,10 @@ mod tests { // k = exp(-0.5 * (1)^2) = exp(-0.5) ≈ 0.6065 let got = rbf_kernel(&[0.0], &[1.0], &[1.0], 1.0); let expected = (-0.5_f64).exp(); - assert!((got - expected).abs() < 1e-12, "got {got}, expected {expected}"); + assert!( + (got - expected).abs() < 1e-12, + "got {got}, expected {expected}" + ); } #[test] diff --git a/src/algorithms/cma_es.rs b/src/algorithms/cma_es.rs index 0d6de95..317da3a 100644 --- a/src/algorithms/cma_es.rs +++ b/src/algorithms/cma_es.rs @@ -766,19 +766,37 @@ mod tests { a.constraint_violation = 0.0; let mut b = Evaluation::new(vec![1.0]); b.constraint_violation = 1.0; - assert_eq!(compare_so(&a, &b, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare_so(&b, &a, Direction::Minimize), std::cmp::Ordering::Greater); + assert_eq!( + compare_so(&a, &b, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare_so(&b, &a, Direction::Minimize), + std::cmp::Ordering::Greater + ); } #[test] fn compare_so_two_feasible_under_min_and_max() { let a = Evaluation::new(vec![1.0]); let b = Evaluation::new(vec![2.0]); - assert_eq!(compare_so(&a, &b, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare_so(&b, &a, Direction::Minimize), std::cmp::Ordering::Greater); + assert_eq!( + compare_so(&a, &b, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare_so(&b, &a, Direction::Minimize), + std::cmp::Ordering::Greater + ); // Maximize inverts. - assert_eq!(compare_so(&a, &b, Direction::Maximize), std::cmp::Ordering::Greater); - assert_eq!(compare_so(&b, &a, Direction::Maximize), std::cmp::Ordering::Less); + assert_eq!( + compare_so(&a, &b, Direction::Maximize), + std::cmp::Ordering::Greater + ); + assert_eq!( + compare_so(&b, &a, Direction::Maximize), + std::cmp::Ordering::Less + ); } #[test] @@ -787,8 +805,14 @@ mod tests { a.constraint_violation = 0.5; let mut b = Evaluation::new(vec![0.0]); b.constraint_violation = 1.0; - assert_eq!(compare_so(&a, &b, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare_so(&b, &a, Direction::Minimize), std::cmp::Ordering::Greater); + assert_eq!( + compare_so(&a, &b, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare_so(&b, &a, Direction::Minimize), + std::cmp::Ordering::Greater + ); } #[test] diff --git a/src/algorithms/genetic_algorithm.rs b/src/algorithms/genetic_algorithm.rs index ab6c3e1..2452b18 100644 --- a/src/algorithms/genetic_algorithm.rs +++ b/src/algorithms/genetic_algorithm.rs @@ -446,15 +446,24 @@ mod tests { fn compare_for_fitness_two_feasible_min_and_max() { let lo = fc(1.0); let hi = fc(2.0); - assert_eq!(compare_for_fitness(&lo, &hi, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare_for_fitness(&lo, &hi, Direction::Maximize), std::cmp::Ordering::Greater); + assert_eq!( + compare_for_fitness(&lo, &hi, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare_for_fitness(&lo, &hi, Direction::Maximize), + std::cmp::Ordering::Greater + ); } #[test] fn compare_for_fitness_two_infeasible_lower_violation_wins() { let low = fc_cv(0.0, 0.3); let high = fc_cv(0.0, 0.9); - assert_eq!(compare_for_fitness(&low, &high, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare_for_fitness(&low, &high, Direction::Minimize), + std::cmp::Ordering::Less + ); } /// `survival_selection` carries `elitism` parents and `n - elitism` diff --git a/src/algorithms/grea.rs b/src/algorithms/grea.rs index 1f70883..b497f94 100644 --- a/src/algorithms/grea.rs +++ b/src/algorithms/grea.rs @@ -415,7 +415,12 @@ mod tests { mutation: PolynomialMutation::new(bounds, 20.0, 1.0), }; let mut opt = Grea::new( - GreaConfig { population_size: pop, generations: 5, grid_divisions: 8, seed: 3 }, + GreaConfig { + population_size: pop, + generations: 5, + grid_divisions: 8, + seed: 3, + }, initializer, variation, ); diff --git a/src/algorithms/hill_climber.rs b/src/algorithms/hill_climber.rs index 8973aa2..edfca49 100644 --- a/src/algorithms/hill_climber.rs +++ b/src/algorithms/hill_climber.rs @@ -290,7 +290,10 @@ mod tests { #[test] fn hill_climber_never_worsens_objective() { let mut opt = HillClimber::new( - HillClimberConfig { iterations: 200, seed: 5 }, + HillClimberConfig { + iterations: 200, + seed: 5, + }, RealBounds::new(vec![(-3.0, 3.0); 2]), GaussianMutation { sigma: 0.3 }, ); @@ -306,7 +309,10 @@ mod tests { #[test] fn hill_climber_decreases_sphere() { let mut opt = HillClimber::new( - HillClimberConfig { iterations: 500, seed: 11 }, + HillClimberConfig { + iterations: 500, + seed: 11, + }, RealBounds::new(vec![(-3.0, 3.0)]), GaussianMutation { sigma: 0.2 }, ); diff --git a/src/algorithms/hype.rs b/src/algorithms/hype.rs index 66dfa8f..77b4a94 100644 --- a/src/algorithms/hype.rs +++ b/src/algorithms/hype.rs @@ -595,6 +595,9 @@ mod tests { wins0 += 1; } } - assert!(wins0 > 130, "index 0 won only {wins0}/200 — comparison likely flipped"); + assert!( + wins0 > 130, + "index 0 won only {wins0}/200 — comparison likely flipped" + ); } } diff --git a/src/algorithms/hyperband.rs b/src/algorithms/hyperband.rs index b300039..f12c0ea 100644 --- a/src/algorithms/hyperband.rs +++ b/src/algorithms/hyperband.rs @@ -451,16 +451,31 @@ mod tests { fn compare_feasibility_first_and_direction() { let feasible = Evaluation::new(vec![10.0]); let infeasible = Evaluation::constrained(vec![0.0], 1.0); - assert_eq!(compare(&feasible, &infeasible, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare(&infeasible, &feasible, Direction::Minimize), std::cmp::Ordering::Greater); + assert_eq!( + compare(&feasible, &infeasible, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare(&infeasible, &feasible, Direction::Minimize), + std::cmp::Ordering::Greater + ); let lo = Evaluation::new(vec![1.0]); let hi = Evaluation::new(vec![2.0]); - assert_eq!(compare(&lo, &hi, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare(&lo, &hi, Direction::Maximize), std::cmp::Ordering::Greater); + assert_eq!( + compare(&lo, &hi, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare(&lo, &hi, Direction::Maximize), + std::cmp::Ordering::Greater + ); // two infeasible: smaller violation is "Less" (better). let v_lo = Evaluation::constrained(vec![0.0], 0.2); let v_hi = Evaluation::constrained(vec![0.0], 0.8); - assert_eq!(compare(&v_lo, &v_hi, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare(&v_lo, &v_hi, Direction::Minimize), + std::cmp::Ordering::Less + ); } #[test] diff --git a/src/algorithms/ibea.rs b/src/algorithms/ibea.rs index 9c3de2f..d414d71 100644 --- a/src/algorithms/ibea.rs +++ b/src/algorithms/ibea.rs @@ -501,7 +501,10 @@ mod tests { let pool = vec![ibea_cand(vec![1.0, 1.0]), ibea_cand(vec![2.0, 2.0])]; let fit = compute_fitness(&pool, &ibea_space(), 0.05); assert_eq!(fit.len(), 2); - assert!(fit[0] > fit[1], "dominating point should score higher: {fit:?}"); + assert!( + fit[0] > fit[1], + "dominating point should score higher: {fit:?}" + ); } #[test] diff --git a/src/algorithms/mopso.rs b/src/algorithms/mopso.rs index 202489a..ce5852e 100644 --- a/src/algorithms/mopso.rs +++ b/src/algorithms/mopso.rs @@ -408,8 +408,16 @@ mod tests { // Determinism cross-check. let mut opt2 = make_optimizer(7); let r2 = opt2.run(&SchafferN1); - let f1: Vec> = r.pareto_front.iter().map(|c| c.evaluation.objectives.clone()).collect(); - let f2: Vec> = r2.pareto_front.iter().map(|c| c.evaluation.objectives.clone()).collect(); + let f1: Vec> = r + .pareto_front + .iter() + .map(|c| c.evaluation.objectives.clone()) + .collect(); + let f2: Vec> = r2 + .pareto_front + .iter() + .map(|c| c.evaluation.objectives.clone()) + .collect(); assert_eq!(f1, f2); } } diff --git a/src/algorithms/nelder_mead.rs b/src/algorithms/nelder_mead.rs index 7760a12..178d37f 100644 --- a/src/algorithms/nelder_mead.rs +++ b/src/algorithms/nelder_mead.rs @@ -560,14 +560,26 @@ mod tests { fn compare_feasibility_first_and_direction() { let feasible = Evaluation::new(vec![10.0]); let infeasible = Evaluation::constrained(vec![0.0], 1.0); - assert_eq!(compare(&feasible, &infeasible, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare(&feasible, &infeasible, Direction::Minimize), + std::cmp::Ordering::Less + ); let lo = Evaluation::new(vec![1.0]); let hi = Evaluation::new(vec![2.0]); - assert_eq!(compare(&lo, &hi, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare(&lo, &hi, Direction::Maximize), std::cmp::Ordering::Greater); + assert_eq!( + compare(&lo, &hi, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare(&lo, &hi, Direction::Maximize), + std::cmp::Ordering::Greater + ); let v_lo = Evaluation::constrained(vec![0.0], 0.2); let v_hi = Evaluation::constrained(vec![0.0], 0.8); - assert_eq!(compare(&v_lo, &v_hi, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare(&v_lo, &v_hi, Direction::Minimize), + std::cmp::Ordering::Less + ); } #[test] diff --git a/src/algorithms/paes.rs b/src/algorithms/paes.rs index 39551a7..12491c0 100644 --- a/src/algorithms/paes.rs +++ b/src/algorithms/paes.rs @@ -313,7 +313,11 @@ mod tests { fn produces_deterministic_nonempty_front() { let make = || { Paes::new( - PaesConfig { iterations: 40, archive_size: 10, seed: 5 }, + PaesConfig { + iterations: 40, + archive_size: 10, + seed: 5, + }, RealBounds::new(vec![(-5.0, 5.0)]), GaussianMutation { sigma: 0.3 }, ) @@ -321,8 +325,16 @@ mod tests { let r1 = make().run(&SchafferN1); let r2 = make().run(&SchafferN1); assert!(!r1.pareto_front.is_empty()); - let f1: Vec> = r1.pareto_front.iter().map(|c| c.evaluation.objectives.clone()).collect(); - let f2: Vec> = r2.pareto_front.iter().map(|c| c.evaluation.objectives.clone()).collect(); + let f1: Vec> = r1 + .pareto_front + .iter() + .map(|c| c.evaluation.objectives.clone()) + .collect(); + let f2: Vec> = r2 + .pareto_front + .iter() + .map(|c| c.evaluation.objectives.clone()) + .collect(); assert_eq!(f1, f2); // Archive never exceeds its configured cap. assert!(r1.pareto_front.len() <= 10); diff --git a/src/algorithms/pesa2.rs b/src/algorithms/pesa2.rs index 94110ba..84e8f2f 100644 --- a/src/algorithms/pesa2.rs +++ b/src/algorithms/pesa2.rs @@ -560,6 +560,9 @@ mod tests { } // Index 2 wins whenever it's drawn against 0 or 1, plus half its // self-draws — clear majority. - assert!(picked_uncrowded > 150, "uncrowded picked {picked_uncrowded}/300"); + assert!( + picked_uncrowded > 150, + "uncrowded picked {picked_uncrowded}/300" + ); } } diff --git a/src/algorithms/random_search.rs b/src/algorithms/random_search.rs index 4b0d2fc..474ee7f 100644 --- a/src/algorithms/random_search.rs +++ b/src/algorithms/random_search.rs @@ -224,7 +224,11 @@ mod tests { #[test] fn best_is_no_worse_than_any_sample() { let mut opt = RandomSearch::new( - RandomSearchConfig { iterations: 50, batch_size: 2, seed: 9 }, + RandomSearchConfig { + iterations: 50, + batch_size: 2, + seed: 9, + }, RealBounds::new(vec![(-3.0, 3.0)]), ); let r = opt.run(&Sphere1D); diff --git a/src/algorithms/rvea.rs b/src/algorithms/rvea.rs index 87806d1..f17d5cb 100644 --- a/src/algorithms/rvea.rs +++ b/src/algorithms/rvea.rs @@ -591,6 +591,9 @@ mod tests { fn smallest_neighbor_angle_of_orthogonal_refs_is_pi_over_2() { let refs = vec![vec![1.0, 0.0], vec![0.0, 1.0]]; let a = smallest_neighbor_angle(&refs); - assert!((a - std::f64::consts::FRAC_PI_2).abs() < 1e-9, "angle = {a}"); + assert!( + (a - std::f64::consts::FRAC_PI_2).abs() < 1e-9, + "angle = {a}" + ); } } diff --git a/src/algorithms/snes.rs b/src/algorithms/snes.rs index 7182673..4c9fb91 100644 --- a/src/algorithms/snes.rs +++ b/src/algorithms/snes.rs @@ -483,11 +483,20 @@ mod tests { fn compare_feasibility_first_and_direction() { let feasible = Evaluation::new(vec![100.0]); let infeasible = Evaluation::constrained(vec![0.0], 1.0); - assert_eq!(compare(&feasible, &infeasible, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare(&feasible, &infeasible, Direction::Minimize), + std::cmp::Ordering::Less + ); let lo = Evaluation::new(vec![1.0]); let hi = Evaluation::new(vec![2.0]); - assert_eq!(compare(&lo, &hi, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare(&lo, &hi, Direction::Maximize), std::cmp::Ordering::Greater); + assert_eq!( + compare(&lo, &hi, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare(&lo, &hi, Direction::Maximize), + std::cmp::Ordering::Greater + ); } #[test] diff --git a/src/algorithms/umda.rs b/src/algorithms/umda.rs index 520da3e..b88a519 100644 --- a/src/algorithms/umda.rs +++ b/src/algorithms/umda.rs @@ -456,14 +456,26 @@ mod tests { fn compare_so_feasibility_first_and_direction() { let feasible = Evaluation::new(vec![100.0]); let infeasible = Evaluation::constrained(vec![0.0], 1.0); - assert_eq!(compare_so(&feasible, &infeasible, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare_so(&feasible, &infeasible, Direction::Minimize), + std::cmp::Ordering::Less + ); let lo = Evaluation::new(vec![1.0]); let hi = Evaluation::new(vec![2.0]); - assert_eq!(compare_so(&lo, &hi, Direction::Minimize), std::cmp::Ordering::Less); - assert_eq!(compare_so(&lo, &hi, Direction::Maximize), std::cmp::Ordering::Greater); + assert_eq!( + compare_so(&lo, &hi, Direction::Minimize), + std::cmp::Ordering::Less + ); + assert_eq!( + compare_so(&lo, &hi, Direction::Maximize), + std::cmp::Ordering::Greater + ); let v_lo = Evaluation::constrained(vec![0.0], 0.2); let v_hi = Evaluation::constrained(vec![0.0], 0.8); - assert_eq!(compare_so(&v_lo, &v_hi, Direction::Minimize), std::cmp::Ordering::Less); + assert_eq!( + compare_so(&v_lo, &v_hi, Direction::Minimize), + std::cmp::Ordering::Less + ); } #[test] diff --git a/src/explorer/mod.rs b/src/explorer/mod.rs index 0a9f64f..0a308c7 100644 --- a/src/explorer/mod.rs +++ b/src/explorer/mod.rs @@ -598,9 +598,18 @@ mod tests { let v: Vec = vec![-3, 0, 7]; let got = v.to_decision_values(); assert_eq!(got.len(), 3); - assert_eq!(got[0], serde_json::Value::Number(serde_json::Number::from(-3i64))); - assert_eq!(got[1], serde_json::Value::Number(serde_json::Number::from(0i64))); - assert_eq!(got[2], serde_json::Value::Number(serde_json::Number::from(7i64))); + assert_eq!( + got[0], + serde_json::Value::Number(serde_json::Number::from(-3i64)) + ); + assert_eq!( + got[1], + serde_json::Value::Number(serde_json::Number::from(0i64)) + ); + assert_eq!( + got[2], + serde_json::Value::Number(serde_json::Number::from(7i64)) + ); } /// Pins the *exact* booleans, not just the count. @@ -642,8 +651,7 @@ mod tests { fn from_result_propagates_evaluation_and_generation_counts() { let problem = SingleObjMin; let cands = vec![Candidate::new(vec![1.0], Evaluation::new(vec![1.0]))]; - let result = - OptimizationResult::new(Population::new(cands.clone()), cands, None, 137, 9); + let result = OptimizationResult::new(Population::new(cands.clone()), cands, None, 137, 9); let export = ExplorerExport::from_result(&problem, &result); assert_eq!(export.run.evaluations, 137); assert_eq!(export.run.generations, 9); @@ -654,8 +662,8 @@ mod tests { fn with_problem_name_sets_field_and_preserves_other_state() { let problem = SingleObjMin; let result = make_result(vec![vec![1.0]], |d| vec![d[0]]); - let export = ExplorerExport::from_result(&problem, &result) - .with_problem_name("Toy Problem"); + let export = + ExplorerExport::from_result(&problem, &result).with_problem_name("Toy Problem"); assert_eq!(export.run.problem_name.as_deref(), Some("Toy Problem")); // The candidates and objectives should still be intact, proving the // chained builder isn't replacing the whole struct. @@ -678,9 +686,12 @@ mod tests { fn with_timestamp_sets_field_and_preserves_other_state() { let problem = SingleObjMin; let result = make_result(vec![vec![1.0]], |d| vec![d[0]]); - let export = ExplorerExport::from_result(&problem, &result) - .with_timestamp("2025-01-01T00:00:00Z"); - assert_eq!(export.run.timestamp.as_deref(), Some("2025-01-01T00:00:00Z")); + let export = + ExplorerExport::from_result(&problem, &result).with_timestamp("2025-01-01T00:00:00Z"); + assert_eq!( + export.run.timestamp.as_deref(), + Some("2025-01-01T00:00:00Z") + ); assert_eq!(export.candidates.len(), 1); } @@ -708,8 +719,7 @@ mod tests { fn to_writer_emits_full_export() { let problem = SingleObjMin; let result = make_result(vec![vec![1.0]], |d| vec![d[0]]); - let export = ExplorerExport::from_result(&problem, &result) - .with_problem_name("MyProblem"); + let export = ExplorerExport::from_result(&problem, &result).with_problem_name("MyProblem"); let mut buf: Vec = Vec::new(); export.to_writer(&mut buf).unwrap(); assert!(!buf.is_empty()); @@ -725,16 +735,15 @@ mod tests { use std::io::Read; let problem = SingleObjMin; let result = make_result(vec![vec![1.0]], |d| vec![d[0]]); - let export = ExplorerExport::from_result(&problem, &result) - .with_problem_name("OnDisk"); + let export = ExplorerExport::from_result(&problem, &result).with_problem_name("OnDisk"); let dir = std::env::temp_dir(); - let path = dir.join(format!( - "heuropt-explorer-test-{}.json", - std::process::id() - )); + let path = dir.join(format!("heuropt-explorer-test-{}.json", std::process::id())); export.to_file(&path).unwrap(); let mut s = String::new(); - std::fs::File::open(&path).unwrap().read_to_string(&mut s).unwrap(); + std::fs::File::open(&path) + .unwrap() + .read_to_string(&mut s) + .unwrap(); let _ = std::fs::remove_file(&path); let back: ExplorerExport = serde_json::from_str(&s).unwrap(); assert_eq!(back.run.problem_name.as_deref(), Some("OnDisk")); @@ -777,7 +786,10 @@ mod tests { )); super::to_file(&path, &problem, &DummyAlgo, &result).unwrap(); let mut s = String::new(); - std::fs::File::open(&path).unwrap().read_to_string(&mut s).unwrap(); + std::fs::File::open(&path) + .unwrap() + .read_to_string(&mut s) + .unwrap(); let _ = std::fs::remove_file(&path); let back: ExplorerExport = serde_json::from_str(&s).unwrap(); assert_eq!(back.run.algorithm.as_deref(), Some("DummyAlgo")); @@ -877,8 +889,7 @@ mod tests { /// the pad (too few objectives) and truncate (too many) cases. #[test] fn candidate_to_export_pads_short_objectives_with_nan() { - let c: Candidate> = - Candidate::new(vec![1.0], Evaluation::new(vec![1.0])); + let c: Candidate> = Candidate::new(vec![1.0], Evaluation::new(vec![1.0])); let exported = candidate_to_export(&c, 0, 3); assert_eq!(exported.objectives.len(), 3); assert_eq!(exported.objectives[0], 1.0); diff --git a/src/metrics/hypervolume.rs b/src/metrics/hypervolume.rs index 008eafa..d09071f 100644 --- a/src/metrics/hypervolume.rs +++ b/src/metrics/hypervolume.rs @@ -560,12 +560,12 @@ mod nd_tests { /// positive value for a dominating point. #[test] fn hypervolume_nd_from_evaluations_empty_and_nonempty() { - let s = ObjectiveSpace::new(vec![ - Objective::minimize("f1"), - Objective::minimize("f2"), - ]); + let s = ObjectiveSpace::new(vec![Objective::minimize("f1"), Objective::minimize("f2")]); let empty: Vec<&Evaluation> = Vec::new(); - assert_eq!(hypervolume_nd_from_evaluations(&empty, &s, &[2.0, 2.0]), 0.0); + assert_eq!( + hypervolume_nd_from_evaluations(&empty, &s, &[2.0, 2.0]), + 0.0 + ); let e = Evaluation::new(vec![1.0, 1.0]); let evals = vec![&e]; @@ -577,13 +577,13 @@ mod nd_tests { /// A point that does not strictly dominate the reference contributes 0. #[test] fn hypervolume_nd_from_evaluations_skips_non_dominating() { - let s = ObjectiveSpace::new(vec![ - Objective::minimize("f1"), - Objective::minimize("f2"), - ]); + let s = ObjectiveSpace::new(vec![Objective::minimize("f1"), Objective::minimize("f2")]); // (2, 1): axis 0 equals the reference → not strictly dominating. let e = Evaluation::new(vec![2.0, 1.0]); let evals = vec![&e]; - assert_eq!(hypervolume_nd_from_evaluations(&evals, &s, &[2.0, 2.0]), 0.0); + assert_eq!( + hypervolume_nd_from_evaluations(&evals, &s, &[2.0, 2.0]), + 0.0 + ); } } diff --git a/src/metrics/spacing.rs b/src/metrics/spacing.rs index 9b5862a..538086b 100644 --- a/src/metrics/spacing.rs +++ b/src/metrics/spacing.rs @@ -135,7 +135,10 @@ mod tests { ]; let got = spacing(&front, &s); let expected = (1536.0_f64 / 27.0).sqrt(); - assert!((got - expected).abs() < 1e-9, "got {got}, expected {expected}"); + assert!( + (got - expected).abs() < 1e-9, + "got {got}, expected {expected}" + ); } /// A perfectly even front has zero spacing — the variance term is 0. diff --git a/src/operators/permutation.rs b/src/operators/permutation.rs index 97fb9b9..1353197 100644 --- a/src/operators/permutation.rs +++ b/src/operators/permutation.rs @@ -994,7 +994,10 @@ mod tests { let c = m.vary(std::slice::from_ref(&parent), &mut rng); c[0] != parent }); - assert!(any_changed, "InversionMutation never modified an 8-element parent across 30 seeds"); + assert!( + any_changed, + "InversionMutation never modified an 8-element parent across 30 seeds" + ); } /// `InsertionMutation` shifts an element across many seeds; at least one @@ -1195,6 +1198,9 @@ mod tests { let kids = erx.vary(&[p1.clone(), p2.clone()], &mut rng); kids[0] != kids[1] }); - assert!(any_distinct, "ERX never produced distinct children across 30 seeds"); + assert!( + any_distinct, + "ERX never produced distinct children across 30 seeds" + ); } } diff --git a/src/operators/real.rs b/src/operators/real.rs index 62fac68..f070d9c 100644 --- a/src/operators/real.rs +++ b/src/operators/real.rs @@ -733,7 +733,11 @@ mod tests { // snapshot, by design. fn assert_close_slice(got: &[f64], want: &[f64], tol: f64) { - assert_eq!(got.len(), want.len(), "length mismatch: got {got:?} want {want:?}"); + assert_eq!( + got.len(), + want.len(), + "length mismatch: got {got:?} want {want:?}" + ); for (g, w) in got.iter().zip(want.iter()) { assert!((g - w).abs() < tol, "got {g}, want {w}; full got = {got:?}"); } @@ -747,7 +751,11 @@ mod tests { let children = m.vary(std::slice::from_ref(&parent), &mut rng); assert_close_slice( &children[0], - &[1.034_713_959_180_981_7, 2.066_469_060_997_062_6, 3.131_288_178_686_977], + &[ + 1.034_713_959_180_981_7, + 2.066_469_060_997_062_6, + 3.131_288_178_686_977, + ], 1e-12, ); } @@ -854,7 +862,10 @@ mod tests { // Same seed → same δ; the only difference is the (hi-lo) factor. // Ratio must be ≈ 10. let ratio = wide / narrow; - assert!((ratio - 10.0).abs() < 1e-12, "ratio = {ratio}, narrow={narrow}, wide={wide}"); + assert!( + (ratio - 10.0).abs() < 1e-12, + "ratio = {ratio}, narrow={narrow}, wide={wide}" + ); } #[test] @@ -890,10 +901,7 @@ mod tests { fn mantegna_sigma_u_alpha_1_0_pinned() { // alpha = 1.0: sin(π/2) = 1, gamma(2) = 1, gamma(1) = 1 → σᵤ ≈ 1. let got = mantegna_sigma_u(1.0); - assert!( - (got - 1.0).abs() < 1e-12, - "mantegna_sigma_u(1.0) = {got}", - ); + assert!((got - 1.0).abs() < 1e-12, "mantegna_sigma_u(1.0) = {got}",); } #[test] diff --git a/src/pareto/archive.rs b/src/pareto/archive.rs index c8c6fc6..2ccb6da 100644 --- a/src/pareto/archive.rs +++ b/src/pareto/archive.rs @@ -317,9 +317,15 @@ mod tests { #[test] fn infeasible_candidate_with_smaller_violation_evicts_larger() { let mut a = ParetoArchive::::new(space_min2()); - a.insert(Candidate::new(1u32, Evaluation::constrained(vec![0.0, 0.0], 1.0))); + a.insert(Candidate::new( + 1u32, + Evaluation::constrained(vec![0.0, 0.0], 1.0), + )); // Smaller violation → dominates the existing infeasible member. - a.insert(Candidate::new(2u32, Evaluation::constrained(vec![9.0, 9.0], 0.5))); + a.insert(Candidate::new( + 2u32, + Evaluation::constrained(vec![9.0, 9.0], 0.5), + )); assert_eq!(a.members().len(), 1); assert_eq!(a.members()[0].decision, 2); } diff --git a/src/pareto/crowding.rs b/src/pareto/crowding.rs index aa06bce..aee2e07 100644 --- a/src/pareto/crowding.rs +++ b/src/pareto/crowding.rs @@ -169,7 +169,11 @@ mod tests { fn interior_point_distance_is_pinned() { let s = space_min2(); // Front along the line f1 + f2 = 4: (0,4), (2,2), (4,0). - let pop = [cand(vec![0.0, 4.0]), cand(vec![2.0, 2.0]), cand(vec![4.0, 0.0])]; + let pop = [ + cand(vec![0.0, 4.0]), + cand(vec![2.0, 2.0]), + cand(vec![4.0, 0.0]), + ]; let d = crowding_distance(&pop, &[0, 1, 2], &s); // Boundary points are infinite; the middle point gets // (4-0)/4 + (4-0)/4 = 2.0 (objective 0 span 4, objective 1 span 4). @@ -184,7 +188,11 @@ mod tests { fn asymmetric_interior_distance_is_pinned() { let s = space_min2(); // (0,10), (1,2), (10,0): objective-0 span = 10, objective-1 span = 10. - let pop = [cand(vec![0.0, 10.0]), cand(vec![1.0, 2.0]), cand(vec![10.0, 0.0])]; + let pop = [ + cand(vec![0.0, 10.0]), + cand(vec![1.0, 2.0]), + cand(vec![10.0, 0.0]), + ]; let d = crowding_distance(&pop, &[0, 1, 2], &s); // middle point: obj0 (10-0)/10 = 1.0; obj1 (10-0)/10 = 1.0 → 2.0. assert!((d[1] - 2.0).abs() < 1e-12, "got {}", d[1]); diff --git a/src/selection/tournament.rs b/src/selection/tournament.rs index ab9ef9c..764ec39 100644 --- a/src/selection/tournament.rs +++ b/src/selection/tournament.rs @@ -282,15 +282,27 @@ mod tests { let feasible = cand_min(1, 100.0); let infeasible = constrained(2, 0.0, 1.0); assert!(challenger_wins(&feasible, &infeasible, Direction::Minimize)); - assert!(!challenger_wins(&infeasible, &feasible, Direction::Minimize)); + assert!(!challenger_wins( + &infeasible, + &feasible, + Direction::Minimize + )); } #[test] fn challenger_wins_two_infeasible_compares_violation() { let less_violating = constrained(1, 0.0, 0.5); let more_violating = constrained(2, 0.0, 1.0); - assert!(challenger_wins(&less_violating, &more_violating, Direction::Minimize)); - assert!(!challenger_wins(&more_violating, &less_violating, Direction::Minimize)); + assert!(challenger_wins( + &less_violating, + &more_violating, + Direction::Minimize + )); + assert!(!challenger_wins( + &more_violating, + &less_violating, + Direction::Minimize + )); } #[test] @@ -330,17 +342,37 @@ mod tests { let feasible_a = Evaluation::new(vec![10.0]); let infeasible_b = Evaluation::constrained(vec![0.0], 1.0); // feasible vs infeasible - assert!(better_by_feasibility(&feasible_a, &infeasible_b, Direction::Minimize)); - assert!(!better_by_feasibility(&infeasible_b, &feasible_a, Direction::Minimize)); + assert!(better_by_feasibility( + &feasible_a, + &infeasible_b, + Direction::Minimize + )); + assert!(!better_by_feasibility( + &infeasible_b, + &feasible_a, + Direction::Minimize + )); // two infeasible: smaller violation wins let low_cv = Evaluation::constrained(vec![0.0], 0.3); let high_cv = Evaluation::constrained(vec![0.0], 0.9); - assert!(better_by_feasibility(&low_cv, &high_cv, Direction::Minimize)); - assert!(!better_by_feasibility(&high_cv, &low_cv, Direction::Minimize)); + assert!(better_by_feasibility( + &low_cv, + &high_cv, + Direction::Minimize + )); + assert!(!better_by_feasibility( + &high_cv, + &low_cv, + Direction::Minimize + )); // two feasible: delegates to better_by_objective let feasible_lower = Evaluation::new(vec![1.0]); let feasible_higher = Evaluation::new(vec![2.0]); - assert!(better_by_feasibility(&feasible_lower, &feasible_higher, Direction::Minimize)); + assert!(better_by_feasibility( + &feasible_lower, + &feasible_higher, + Direction::Minimize + )); } #[test] @@ -349,8 +381,8 @@ mod tests { // must rank first regardless of objective value. let s = ObjectiveSpace::new(vec![Objective::minimize("f")]); let pop = [ - constrained(1, 0.0, 2.0), // infeasible, great objective - cand_min(2, 100.0), // feasible, terrible objective + constrained(1, 0.0, 2.0), // infeasible, great objective + cand_min(2, 100.0), // feasible, terrible objective ]; let mut rng = rng_from_seed(7); let picks = stochastic_ranking_select(&pop, &s, 0.0, 1, &mut rng);