src/lib.rs

changeset 72
e9a460a0e638
parent 67
95bb12bdb6ac
child 73
9c6432200aba
equal deleted inserted replaced
71:e2953ffd4e0b 72:e9a460a0e638
12 12
13 use alg_tools::error::DynResult; 13 use alg_tools::error::DynResult;
14 use alg_tools::parallelism::{set_max_threads, set_num_threads}; 14 use alg_tools::parallelism::{set_max_threads, set_num_threads};
15 use clap::Parser; 15 use clap::Parser;
16 use serde::{Deserialize, Serialize}; 16 use serde::{Deserialize, Serialize};
17 use serde_json;
18 use serde_with::skip_serializing_none; 17 use serde_with::skip_serializing_none;
19 use std::num::NonZeroUsize; 18 use std::num::NonZeroUsize;
20 19
21 //#[cfg(feature = "pyo3")] 20 //#[cfg(feature = "pyo3")]
22 //use pyo3::pyclass; 21 //use pyo3::pyclass;
45 44
46 pub mod measures { 45 pub mod measures {
47 pub use measures::*; 46 pub use measures::*;
48 } 47 }
49 48
50 use run::{AlgorithmConfig, DefaultAlgorithm, Named, PlotLevel, RunnableExperiment}; 49 use run::{DefaultAlgorithm, PlotLevel, RunnableExperiment};
51 use subproblem::InnerMethod; 50 use subproblem::InnerMethod;
52 use types::{ClapFloat, Float}; 51 use types::{ClapFloat, Float};
53 use DefaultAlgorithm::*;
54 52
55 /// Trait for customising the experiments available from the command line 53 /// Trait for customising the experiments available from the command line
56 pub trait ExperimentSetup: 54 pub trait ExperimentSetup:
57 clap::Args + Send + Sync + 'static + Serialize + for<'a> Deserialize<'a> 55 clap::Args + Send + Sync + 'static + Serialize + for<'a> Deserialize<'a>
58 { 56 {
82 80
83 /// Default algorithm configration(s) to use on the experiments. 81 /// Default algorithm configration(s) to use on the experiments.
84 /// 82 ///
85 /// Not all algorithms are available for all the experiments. 83 /// Not all algorithms are available for all the experiments.
86 /// In particular, only PDPS is available for the experiments with L¹ data term. 84 /// In particular, only PDPS is available for the experiments with L¹ data term.
87 #[arg(value_enum, value_name = "ALGORITHM", long, short = 'a', 85 #[arg(value_enum, value_name = "ALGORITHM", long, short = 'a')]
88 default_values_t = [FB, PDPS, SlidingFB, FW, RadonFB])]
89 algorithm: Vec<DefaultAlgorithm>, 86 algorithm: Vec<DefaultAlgorithm>,
90 87
91 /// Saved algorithm configration(s) to use on the experiments 88 /// Saved algorithm configration(s) to use on the experiments
92 #[arg(value_name = "JSON_FILE", long)] 89 #[arg(value_name = "JSON_FILE", long)]
93 saved_algorithm: Vec<String>, 90 saved_algorithm: Vec<String>,
142 #[arg(long, value_names = &["COUNT", "EACH"])] 139 #[arg(long, value_names = &["COUNT", "EACH"])]
143 /// Override bootstrap insertion iterations for --algorithm. 140 /// Override bootstrap insertion iterations for --algorithm.
144 /// 141 ///
145 /// The first parameter is the number of bootstrap insertion iterations, and the second 142 /// The first parameter is the number of bootstrap insertion iterations, and the second
146 /// the maximum number of iterations on each of them. 143 /// the maximum number of iterations on each of them.
147 bootstrap_insertions: Option<Vec<usize>>, 144 pub bootstrap_insertions: Option<Vec<usize>>,
148 145
149 #[arg(long, requires = "algorithm")] 146 #[arg(long, requires = "algorithm")]
150 /// Primal step length parameter override for --algorithm. 147 /// Primal step length parameter override for --algorithm.
151 /// 148 ///
152 /// Only use if running just a single algorithm, as different algorithms have different 149 /// Only use if running just a single algorithm, as different algorithms have different
153 /// regularisation parameters. Does not affect the algorithms fw and fwrelax. 150 /// regularisation parameters. Does not affect the algorithms fw and fwrelax.
154 tau0: Option<F>, 151 pub tau0: Option<F>,
155 152
156 #[arg(long, requires = "algorithm")] 153 #[arg(long, requires = "algorithm")]
157 /// Second primal step length parameter override for SlidingPDPS. 154 /// Second primal step length parameter override for SlidingPDPS.
158 /// 155 ///
159 /// Only use if running just a single algorithm, as different algorithms have different 156 /// Only use if running just a single algorithm, as different algorithms have different
160 /// regularisation parameters. 157 /// regularisation parameters.
161 sigmap0: Option<F>, 158 pub sigmap0: Option<F>,
162 159
163 #[arg(long, requires = "algorithm")] 160 #[arg(long, requires = "algorithm")]
164 /// Dual step length parameter override for --algorithm. 161 /// Dual step length parameter override for --algorithm.
165 /// 162 ///
166 /// Only use if running just a single algorithm, as different algorithms have different 163 /// Only use if running just a single algorithm, as different algorithms have different
167 /// regularisation parameters. Only affects PDPS. 164 /// regularisation parameters. Only affects PDPS.
168 sigma0: Option<F>, 165 pub sigma0: Option<F>,
169 166
170 #[arg(long)] 167 #[arg(long)]
171 /// Normalised transport step length for sliding methods. 168 /// Normalised transport step length for sliding methods.
172 theta0: Option<F>, 169 pub theta0: Option<F>,
173 170
174 #[arg(long)] 171 #[arg(long)]
175 /// A posteriori transport tolerance multiplier (C_pos) 172 /// Unnormalised transport step length for sliding methods, multiplied by tau.
176 transport_tolerance_pos: Option<F>, 173 pub tautheta: Option<F>,
174
175 #[arg(long)]
176 /// A posteriori transport tolerance multiplier
177 pub transport_tolerance: Option<F>,
178
179 #[arg(long)]
180 /// Multiplier for rough estimate of ℓ_{∇v}. Should be ≥ 1.
181 /// If explicit τθ is given, ℓ_{∇v} is one divided by this number times τθ.
182 /// Otherwise, if τθ relative to an estimate of ℓ_{∇v}, this number multiplies that estimate.
183 pub gradv_lipest_mult: Option<F>,
177 184
178 #[arg(long)] 185 #[arg(long)]
179 /// Transport adaptation factor. Must be in (0, 1). 186 /// Transport adaptation factor. Must be in (0, 1).
180 transport_adaptation: Option<F>, 187 pub transport_adaptation: Option<F>,
188
189 #[arg(long)]
190 /// Whether partially transported spikes are allowed.
191 pub allow_partial_transport: Option<bool>,
192
193 #[arg(long)]
194 /// Use an alternative remainder control rule.
195 pub alt_remainder_control: Option<bool>,
181 196
182 #[arg(long)] 197 #[arg(long)]
183 /// Minimal step length parameter for sliding methods. 198 /// Minimal step length parameter for sliding methods.
184 tau0_min: Option<F>, 199 pub tau0_min: Option<F>,
185 200
186 #[arg(value_enum, long)] 201 #[arg(value_enum, long)]
187 /// PDPS acceleration, when available. 202 /// PDPS acceleration, when available.
188 acceleration: Option<pdps::Acceleration>, 203 pub acceleration: Option<pdps::Acceleration>,
189 204
190 // #[arg(long)] 205 // #[arg(long)]
191 // /// Perform postprocess weight optimisation for saved iterations 206 // /// Perform postprocess weight optimisation for saved iterations
192 // /// 207 // ///
193 // /// Only affects FB, FISTA, and PDPS. 208 // /// Only affects FB, FISTA, and PDPS.
194 // postprocessing : Option<bool>, 209 // postprocessing : Option<bool>,
195 #[arg(value_name = "n", long)] 210 #[arg(value_name = "n", long)]
196 /// Merging frequency, if merging enabled (every n iterations) 211 /// Merging frequency, if merging enabled (every n iterations)
197 /// 212 ///
198 /// Only affects FB, FISTA, and PDPS. 213 /// Only affects FB, FISTA, and PDPS.
199 merge_every: Option<usize>, 214 pub merge_every: Option<usize>,
200 215
201 #[arg(long)] 216 #[arg(long)]
202 /// Enable merging (default: determined by algorithm) 217 /// Enable merging (default: determined by algorithm)
203 merge: Option<bool>, 218 pub merge: Option<bool>,
204 219
205 #[arg(long)] 220 #[arg(long)]
206 /// Merging radius (default: determined by experiment) 221 /// Merging radius (default: determined by experiment)
207 merge_radius: Option<F>, 222 pub merge_radius: Option<F>,
208 223
209 #[arg(long)] 224 #[arg(long)]
210 /// Interpolate when merging (default : determined by algorithm) 225 /// Interpolate when merging (default : determined by algorithm)
211 merge_interp: Option<bool>, 226 pub merge_interp: Option<bool>,
212 227
213 #[arg(long)] 228 #[arg(long)]
214 /// Enable final merging (default: determined by algorithm) 229 /// Enable final merging (default: determined by algorithm)
215 final_merging: Option<bool>, 230 pub final_merging: Option<bool>,
216 231
217 #[arg(long)] 232 #[arg(long)]
218 /// Enable fitness-based merging for relevant FB-type methods. 233 /// Enable fitness-based merging for relevant FB-type methods.
219 /// This has worse convergence guarantees that merging based on optimality conditions. 234 /// This has worse convergence guarantees that merging based on optimality conditions.
220 fitness_merging: Option<bool>, 235 pub fitness_merging: Option<bool>,
221 236
222 #[arg(long, value_names = &["ε", "θ", "p"])] 237 #[arg(long, value_names = &["ε", "θ", "p"])]
223 /// Set the tolerance to ε_k = ε/(1+θk)^p 238 /// Set the tolerance to ε_k = ε/(1+θk)^p
224 tolerance: Option<Vec<F>>, 239 pub tolerance: Option<Vec<F>>,
225 240
226 #[arg(long)] 241 #[arg(long)]
227 /// Method for solving inner optimisation problems 242 /// Method for solving inner optimisation problems
228 inner_method: Option<InnerMethod>, 243 pub inner_method: Option<InnerMethod>,
229 244
230 #[arg(long)] 245 #[arg(long)]
231 /// Step length parameter for inner problem 246 /// Step length parameter for inner problem
232 inner_τ0: Option<F>, 247 pub inner_τ0: Option<F>,
233 248
234 #[arg(long, value_names = &["τ0", "σ0"])] 249 #[arg(long, value_names = &["τ0", "σ0"])]
235 /// Dual step length parameter for inner problem 250 /// Dual step length parameter for inner problem
236 inner_pdps_τσ0: Option<Vec<F>>, 251 pub inner_pdps_τσ0: Option<Vec<F>>,
237 252
238 #[arg(long, value_names = &["τ", "growth"])] 253 #[arg(long, value_names = &["τ", "growth"])]
239 /// Inner proximal point method step length and its growth 254 /// Inner proximal point method step length and its growth
240 inner_pp_τ: Option<Vec<F>>, 255 pub inner_pp_τ: Option<Vec<F>>,
241 256
242 #[arg(long)] 257 #[arg(long)]
243 /// Inner tolerance multiplier 258 /// Inner tolerance multiplier
244 inner_tol: Option<F>, 259 pub inner_tol: Option<F>,
245 } 260 }
246 261
247 /// A generic entry point for binaries based on this library 262 /// A generic entry point for binaries based on this library
248 pub fn common_main<E: ExperimentSetup>() -> DynResult<()> { 263 pub fn common_main<E: ExperimentSetup>() -> DynResult<()> {
249 let full_cli = FusedCommandLineArgs::<E>::parse(); 264 let cli = FusedCommandLineArgs::<E>::parse();
250 let cli = &full_cli.general;
251 265
252 #[cfg(debug_assertions)] 266 #[cfg(debug_assertions)]
253 { 267 {
254 use colored::Colorize; 268 use colored::Colorize;
255 println!( 269 println!(
265 ) 279 )
266 .red() 280 .red()
267 ); 281 );
268 } 282 }
269 283
270 if let Some(n_threads) = cli.num_threads { 284 if let Some(n_threads) = cli.general.num_threads {
271 let n = NonZeroUsize::new(n_threads).expect("Invalid thread count"); 285 let n = NonZeroUsize::new(n_threads).expect("Invalid thread count");
272 set_num_threads(n); 286 set_num_threads(n);
273 } else { 287 } else {
274 let m = NonZeroUsize::new(cli.max_threads).expect("Invalid maximum thread count"); 288 let m = NonZeroUsize::new(cli.general.max_threads).expect("Invalid maximum thread count");
275 set_max_threads(m); 289 set_max_threads(m);
276 } 290 }
277 291
278 for experiment in full_cli.experiment_setup.runnables()? { 292 for experiment in cli.experiment_setup.runnables()? {
279 let mut algs: Vec<Named<AlgorithmConfig<E::FloatType>>> = cli 293 experiment.runall(&cli.general, &cli.algorithm_overrides)?;
280 .algorithm
281 .iter()
282 .map(|alg| {
283 let cfg = alg
284 .default_config()
285 .cli_override(&experiment.algorithm_overrides(*alg))
286 .cli_override(&full_cli.algorithm_overrides);
287 alg.to_named(cfg)
288 })
289 .collect();
290 for filename in cli.saved_algorithm.iter() {
291 let f = std::fs::File::open(filename)?;
292 let alg = serde_json::from_reader(f)?;
293 algs.push(alg);
294 }
295 experiment.runall(&cli, (!algs.is_empty()).then_some(algs))?;
296 } 294 }
297 295
298 Ok(()) 296 Ok(())
299 } 297 }

mercurial