src/lib.rs

changeset 72
e9a460a0e638
parent 67
95bb12bdb6ac
child 73
9c6432200aba
--- a/src/lib.rs	Fri May 15 14:40:02 2026 -0500
+++ b/src/lib.rs	Sun Jul 19 07:34:39 2026 +0200
@@ -14,7 +14,6 @@
 use alg_tools::parallelism::{set_max_threads, set_num_threads};
 use clap::Parser;
 use serde::{Deserialize, Serialize};
-use serde_json;
 use serde_with::skip_serializing_none;
 use std::num::NonZeroUsize;
 
@@ -47,10 +46,9 @@
     pub use measures::*;
 }
 
-use run::{AlgorithmConfig, DefaultAlgorithm, Named, PlotLevel, RunnableExperiment};
+use run::{DefaultAlgorithm, PlotLevel, RunnableExperiment};
 use subproblem::InnerMethod;
 use types::{ClapFloat, Float};
-use DefaultAlgorithm::*;
 
 /// Trait for customising the experiments available from the command line
 pub trait ExperimentSetup:
@@ -84,8 +82,7 @@
     ///
     /// Not all algorithms are available for all the experiments.
     /// In particular, only PDPS is available for the experiments with L¹ data term.
-    #[arg(value_enum, value_name = "ALGORITHM", long, short = 'a',
-           default_values_t = [FB, PDPS, SlidingFB, FW, RadonFB])]
+    #[arg(value_enum, value_name = "ALGORITHM", long, short = 'a')]
     algorithm: Vec<DefaultAlgorithm>,
 
     /// Saved algorithm configration(s) to use on the experiments
@@ -144,48 +141,66 @@
     ///
     /// The first parameter is the number of bootstrap insertion iterations, and the second
     /// the maximum number of iterations on each of them.
-    bootstrap_insertions: Option<Vec<usize>>,
+    pub bootstrap_insertions: Option<Vec<usize>>,
 
     #[arg(long, requires = "algorithm")]
     /// Primal step length parameter override for --algorithm.
     ///
     /// Only use if running just a single algorithm, as different algorithms have different
     /// regularisation parameters. Does not affect the algorithms fw and fwrelax.
-    tau0: Option<F>,
+    pub tau0: Option<F>,
 
     #[arg(long, requires = "algorithm")]
     /// Second primal step length parameter override for SlidingPDPS.
     ///
     /// Only use if running just a single algorithm, as different algorithms have different
     /// regularisation parameters.
-    sigmap0: Option<F>,
+    pub sigmap0: Option<F>,
 
     #[arg(long, requires = "algorithm")]
     /// Dual step length parameter override for --algorithm.
     ///
     /// Only use if running just a single algorithm, as different algorithms have different
     /// regularisation parameters. Only affects PDPS.
-    sigma0: Option<F>,
+    pub sigma0: Option<F>,
 
     #[arg(long)]
     /// Normalised transport step length for sliding methods.
-    theta0: Option<F>,
+    pub theta0: Option<F>,
+
+    #[arg(long)]
+    /// Unnormalised transport step length for sliding methods, multiplied by tau.
+    pub tautheta: Option<F>,
 
     #[arg(long)]
-    /// A posteriori transport tolerance multiplier (C_pos)
-    transport_tolerance_pos: Option<F>,
+    /// A posteriori transport tolerance multiplier
+    pub transport_tolerance: Option<F>,
+
+    #[arg(long)]
+    /// Multiplier for rough estimate of ℓ_{∇v}. Should be ≥ 1.
+    /// If explicit τθ is given, ℓ_{∇v} is one divided by this number times τθ.
+    /// Otherwise, if  τθ relative to an estimate of ℓ_{∇v}, this number multiplies that estimate.
+    pub gradv_lipest_mult: Option<F>,
 
     #[arg(long)]
     /// Transport adaptation factor. Must be in (0, 1).
-    transport_adaptation: Option<F>,
+    pub transport_adaptation: Option<F>,
+
+    #[arg(long)]
+    /// Whether partially transported spikes are allowed.
+    pub allow_partial_transport: Option<bool>,
+
+    #[arg(long)]
+    /// Use an alternative remainder control rule.
+    pub alt_remainder_control: Option<bool>,
 
     #[arg(long)]
     /// Minimal step length parameter for sliding methods.
-    tau0_min: Option<F>,
+    pub tau0_min: Option<F>,
 
     #[arg(value_enum, long)]
     /// PDPS acceleration, when available.
-    acceleration: Option<pdps::Acceleration>,
+    pub acceleration: Option<pdps::Acceleration>,
 
     // #[arg(long)]
     // /// Perform postprocess weight optimisation for saved iterations
@@ -196,58 +211,57 @@
     /// Merging frequency, if merging enabled (every n iterations)
     ///
     /// Only affects FB, FISTA, and PDPS.
-    merge_every: Option<usize>,
+    pub merge_every: Option<usize>,
 
     #[arg(long)]
     /// Enable merging (default: determined by algorithm)
-    merge: Option<bool>,
+    pub merge: Option<bool>,
 
     #[arg(long)]
     /// Merging radius (default: determined by experiment)
-    merge_radius: Option<F>,
+    pub merge_radius: Option<F>,
 
     #[arg(long)]
     /// Interpolate when merging (default : determined by algorithm)
-    merge_interp: Option<bool>,
+    pub merge_interp: Option<bool>,
 
     #[arg(long)]
     /// Enable final merging (default: determined by algorithm)
-    final_merging: Option<bool>,
+    pub final_merging: Option<bool>,
 
     #[arg(long)]
     /// Enable fitness-based merging for relevant FB-type methods.
     /// This has worse convergence guarantees that merging based on optimality conditions.
-    fitness_merging: Option<bool>,
+    pub fitness_merging: Option<bool>,
 
     #[arg(long, value_names = &["ε", "θ", "p"])]
     /// Set the tolerance to ε_k = ε/(1+θk)^p
-    tolerance: Option<Vec<F>>,
+    pub tolerance: Option<Vec<F>>,
 
     #[arg(long)]
     /// Method for solving inner optimisation problems
-    inner_method: Option<InnerMethod>,
+    pub inner_method: Option<InnerMethod>,
 
     #[arg(long)]
     /// Step length parameter for inner problem
-    inner_τ0: Option<F>,
+    pub inner_τ0: Option<F>,
 
     #[arg(long, value_names = &["τ0", "σ0"])]
     /// Dual step length parameter for inner problem
-    inner_pdps_τσ0: Option<Vec<F>>,
+    pub inner_pdps_τσ0: Option<Vec<F>>,
 
     #[arg(long, value_names = &["τ", "growth"])]
     /// Inner proximal point method step length and its growth
-    inner_pp_τ: Option<Vec<F>>,
+    pub inner_pp_τ: Option<Vec<F>>,
 
     #[arg(long)]
     /// Inner tolerance multiplier
-    inner_tol: Option<F>,
+    pub inner_tol: Option<F>,
 }
 
 /// A generic entry point for binaries based on this library
 pub fn common_main<E: ExperimentSetup>() -> DynResult<()> {
-    let full_cli = FusedCommandLineArgs::<E>::parse();
-    let cli = &full_cli.general;
+    let cli = FusedCommandLineArgs::<E>::parse();
 
     #[cfg(debug_assertions)]
     {
@@ -267,32 +281,16 @@
         );
     }
 
-    if let Some(n_threads) = cli.num_threads {
+    if let Some(n_threads) = cli.general.num_threads {
         let n = NonZeroUsize::new(n_threads).expect("Invalid thread count");
         set_num_threads(n);
     } else {
-        let m = NonZeroUsize::new(cli.max_threads).expect("Invalid maximum thread count");
+        let m = NonZeroUsize::new(cli.general.max_threads).expect("Invalid maximum thread count");
         set_max_threads(m);
     }
 
-    for experiment in full_cli.experiment_setup.runnables()? {
-        let mut algs: Vec<Named<AlgorithmConfig<E::FloatType>>> = cli
-            .algorithm
-            .iter()
-            .map(|alg| {
-                let cfg = alg
-                    .default_config()
-                    .cli_override(&experiment.algorithm_overrides(*alg))
-                    .cli_override(&full_cli.algorithm_overrides);
-                alg.to_named(cfg)
-            })
-            .collect();
-        for filename in cli.saved_algorithm.iter() {
-            let f = std::fs::File::open(filename)?;
-            let alg = serde_json::from_reader(f)?;
-            algs.push(alg);
-        }
-        experiment.runall(&cli, (!algs.is_empty()).then_some(algs))?;
+    for experiment in cli.experiment_setup.runnables()? {
+        experiment.runall(&cli.general, &cli.algorithm_overrides)?;
     }
 
     Ok(())

mercurial