experiment_parallel_vs_sequential/
experiment_parallel_vs_sequential.rs1use std::time::Duration;
2
3use roma_lib::algorithms::{
4 GeneticAlgorithmParameters,
5 HillClimbingParameters,
6 PSOParameters,
7 SimulatedAnnealingParameters,
8 TerminationCriteria,
9 TerminationCriterion,
10};
11use roma_lib::experiment::{Experiment, ExperimentReport};
12use roma_lib::operator::{BinaryTournamentSelection, BitFlipMutation, SinglePointCrossover};
13use roma_lib::problem::{KnapsackBuilder, Problem};
14use roma_lib::utils::{measure_result, speedup};
15
16fn build_problem() -> impl Problem<bool, f64> + Sync {
17 KnapsackBuilder::new()
18 .with_capacity(150.0)
19 .add_item(1.0, 2.0)
20 .add_item(2.0, 6.0)
21 .add_item(3.0, 7.0)
22 .add_item(10.0, 20.0)
23 .add_item(20.0, 30.0)
24 .add_item(30.0, 60.0)
25 .add_item(35.0, 65.0)
26 .add_item(45.0, 100.0)
27 .add_item(55.0, 120.0)
28 .add_item(75.0, 211.0)
29 .add_item(80.0, 160.0)
30 .add_item(90.0, 301.0)
31 .add_item(150.0, 301.0)
32 .build()
33}
34
35fn run_experiment(parallel: bool, runs: usize) -> Result<(Duration, ExperimentReport), String> {
36 let problem = build_problem();
37
38 let hill_climbing_case = HillClimbingParameters::new(
39 BitFlipMutation::new(),
40 0.12,
41 TerminationCriteria::new(vec![TerminationCriterion::MaxIterations(180)]),
42 )
43 .with_seed(111);
44
45 let genetic_algorithm_case = GeneticAlgorithmParameters::new(
47 80,
48 0.90,
49 0.06,
50 SinglePointCrossover::new(),
51 BitFlipMutation::new(),
52 BinaryTournamentSelection::new(),
53 TerminationCriteria::new(vec![TerminationCriterion::MaxIterations(60)]),
54 )
55 .with_elite_size(1)
56 .with_seed(222)
57 .sequential();
58
59 let simulated_annealing_case = SimulatedAnnealingParameters::new(
60 BitFlipMutation::new(),
61 0.10,
62 45.0,
63 0.985,
64 TerminationCriteria::new(vec![TerminationCriterion::MaxIterations(220)]),
65 )
66 .with_seed(333);
67
68 let pso_case = PSOParameters::new(
69 50,
70 0.72,
71 1.49,
72 1.49,
73 TerminationCriteria::new(vec![TerminationCriterion::MaxIterations(120)]),
74 )
75 .with_velocity_clamp(4.0)
76 .with_seed(444);
77
78 let experiment = Experiment::new(problem)
79 .with_runs(runs)
80 .add_case(hill_climbing_case)
81 .add_case(genetic_algorithm_case)
82 .add_case(simulated_annealing_case)
83 .add_case(pso_case);
84
85 measure_result(|| {
86 if parallel {
87 experiment.with_parallel().execute()
88 } else {
89 experiment.sequential().execute()
90 }
91 })
92}
93
94fn main() {
95 let runs = 24;
96
97 println!("Simple benchmark: Sequential vs parallel experiment execution");
98 println!("Cases: 4 | Runs per case: {}", runs);
99
100 let (sequential_time, sequential_report) = match run_experiment(false, runs) {
101 Ok(value) => value,
102 Err(error) => {
103 eprintln!("Sequential execution error: {}", error);
104 return;
105 }
106 };
107
108 let (parallel_time, parallel_report) = match run_experiment(true, runs) {
109 Ok(value) => value,
110 Err(error) => {
111 eprintln!("Parallel execution error: {}", error);
112 return;
113 }
114 };
115
116 let speedup = speedup(sequential_time, parallel_time);
117
118 println!("\nTiming results:");
119 println!(" Sequential: {:?}", sequential_time);
120 println!(" Parallel : {:?}", parallel_time);
121 println!(" Speedup : {:.2}x", speedup);
122
123 println!("\nSequential summary (top 2 by best):");
124 for summary in sequential_report.summaries.iter().take(2) {
125 println!(
126 " - {} | best={:.4} mean={:.4}",
127 summary.case_name, summary.best, summary.mean
128 );
129 }
130
131 println!("\nParallel summary (top 2 by best):");
132 for summary in parallel_report.summaries.iter().take(2) {
133 println!(
134 " - {} | best={:.4} mean={:.4}",
135 summary.case_name, summary.best, summary.mean
136 );
137 }
138}