Save log to a CSV file

Tue, 22 Oct 2024 08:27:45 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 22 Oct 2024 08:27:45 -0500
changeset 12
3b05a8b45b95
parent 11
933242e0f3b8
child 13
f67949050a32

Save log to a CSV file

Cargo.toml file | annotate | diff | comparison | revisions
src/cube.rs file | annotate | diff | comparison | revisions
src/fb.rs file | annotate | diff | comparison | revisions
src/main.rs file | annotate | diff | comparison | revisions
--- a/Cargo.toml	Mon Oct 21 23:07:01 2024 -0500
+++ b/Cargo.toml	Tue Oct 22 08:27:45 2024 -0500
@@ -22,3 +22,4 @@
 alg_tools = { version = "~0.3.0-dev", path = "../alg_tools", default-features = false }
 colored = "~2.0.0"
 image = "~0.24.3"
+serde_repr = "0.1"
--- a/src/cube.rs	Mon Oct 21 23:07:01 2024 -0500
+++ b/src/cube.rs	Tue Oct 22 08:27:45 2024 -0500
@@ -1,19 +1,20 @@
 
-use core::f64;
-
+use serde_repr::*;
+use serde::Serialize;
 use alg_tools::loc::Loc;
 use alg_tools::norms::{Norm, L2};
 use crate::manifold::{ManifoldPoint, EmbeddedManifoldPoint};
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum Face {F1, F2, F3, F4, F5, F6}
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)]
+#[repr(u8)]
+pub enum Face {F1 = 1, F2 = 2, F3 = 3, F4 = 4, F5 = 5, F6 = 6}
 use Face::*;
 
 pub type Point = Loc<f64, 2>;
 
 pub type AdjacentFaces = [Face; 4];
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize)]
 pub enum Path {
     Direct { destination : Face },
     Indirect { destination : Face, intermediate : Face },
@@ -216,7 +217,7 @@
     }
 }
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
 pub struct OnCube {
     face : Face,
     point : Point,
@@ -244,6 +245,10 @@
         }
         (best_tan, best_len)
     }
+
+    pub fn face(&self) -> Face {
+        self.face
+    }
 }
 
 
--- a/src/fb.rs	Mon Oct 21 23:07:01 2024 -0500
+++ b/src/fb.rs	Tue Oct 22 08:27:45 2024 -0500
@@ -4,7 +4,6 @@
 use serde::Serialize;
 use std::iter::Sum as SumTrait;
 use colored::ColoredString;
-
 use crate::manifold::{EmbeddedManifoldPoint, ManifoldPoint};
 
 /// Trait for function objects that implement gradients
@@ -40,10 +39,13 @@
     fn prox(&self, τ : f64, x : M) -> M;
 }
 
+/// This structure is used to store information from algorithm iterations
 #[derive(Clone,Debug,Serialize)]
 pub struct IterInfo<M> {
-    value : f64,
-    point : M,
+    /// Function value
+    pub value : f64,
+    /// Current iterate
+    pub point : M,
 }
 
 impl<M : ManifoldPoint + EmbeddedManifoldPoint> LogRepr for IterInfo<M> {
@@ -55,6 +57,11 @@
     }
 }
 
+/// The forward-backward method on manifolds.
+///
+/// `f` is the smooth, `g` the nonsmooth function, `x` the initial iterate,
+/// `τ` the step length parameter, and `iterator` controls the iteration count
+/// and verbosity. Return the final iterate.
 pub fn forward_backward<M, F, G, I>(
     f : &F,
     g : &G,
@@ -66,10 +73,13 @@
       F : Desc<M> +  Mapping<M, Codomain = f64>,
       G : Prox<M> +  Mapping<M, Codomain = f64>,
       I : AlgIteratorFactory<IterInfo<M>> {
-    
+
+    // Perform as many iterations as requested by `iterator`.
     for i in iterator.iter() {
+        // Forward-backward step
         x = g.prox(τ, f.desc(τ, x));
 
+        // If requested by `iterator`, calculate function value and store iterate.
         i.if_verbose(|| {
             IterInfo {
                 value : f.apply(&x) + g.apply(&x),
@@ -78,5 +88,6 @@
         })
     }
 
+    // Return final iterate.
     x
 }
--- a/src/main.rs	Mon Oct 21 23:07:01 2024 -0500
+++ b/src/main.rs	Tue Oct 22 08:27:45 2024 -0500
@@ -5,9 +5,13 @@
 #![allow(mixed_script_confusables)]
 #![allow(confusable_idents)]
 
+use serde::Serialize;
 use dist::DistToSquaredDiv2;
-use fb::forward_backward;
+use fb::{forward_backward, IterInfo};
 use manifold::EmbeddedManifoldPoint;
+use alg_tools::logger::Logger;
+use alg_tools::tabledump::TableDump;
+use alg_tools::error::DynError;
 use cube::*;
 use image::{
     ImageFormat,
@@ -22,15 +26,29 @@
 mod zero;
 
 fn main() {
-    simple_test()
+    simple_cube_test().unwrap()
 }
 
-fn simple_test() {
+/// Helper structure for saving the log into a CSV file
+#[derive(Serialize)]
+struct CSVLog {
+    iter : usize,
+    value : f64,
+    face : Face,
+    x : f64,
+    y : f64,
+    z : f64
+}
+
+static PREFIX : &str = "res";
+
+/// A simple test on the cube
+fn simple_cube_test() -> DynError {
     use alg_tools::loc::Loc;
     use Face::*;
     use zero::ZeroFn;
     use alg_tools::mapping::{Sum, Apply};
-    use alg_tools::iterate::{AlgIteratorOptions, Verbose};
+    use alg_tools::iterate::{AlgIteratorOptions, AlgIteratorFactory, Verbose};
     
     let points = [
         //OnCube::new(F1, Loc([0.5, 0.5])),
@@ -47,21 +65,37 @@
     let f = Sum::new(points.into_iter().map(DistToSquaredDiv2));
     let g = ZeroFn::new();
     let τ = 0.1;
+    
+    let mut logger = Logger::new();
+    let logmap = |iter, IterInfo { value, point } : IterInfo<OnCube>| {
+        let Loc([x,y,z]) = point.embedded_coords();
+        let face = point.face();
+        CSVLog { iter, value, face, x,  y, z }
+    };
     let iter = AlgIteratorOptions{
         max_iter : 100,
         verbose_iter : Verbose::Every(1),
         .. Default::default()
-    };
+    }.mapped(logmap)
+     .into_log(&mut logger);
 
     let x̂ = forward_backward(&f, &g, x, τ, iter);
     println!("result = {}\n{:?}", x̂.embedded_coords(), &x̂);
 
+    std::fs::create_dir_all(PREFIX)?;
+
+    logger.write_csv(format!("{PREFIX}/log.txt"))?;
+
     for face in Face::all() {
-        write_face(format!("{face}"), face, 128, |x| f.apply(x) + g.apply(x))
+        write_face(format!("{PREFIX}/{face}"), face, 128, |x| f.apply(x) + g.apply(x))?;
     }
+
+    Ok(())
 }
 
-fn write_face(filename : String, face : Face, n : usize, mut f : impl FnMut(&OnCube) -> f64) {
+/// Writes the values of `f` on `face` of a [`OnCube`] into a PNG file
+/// with resolution `n × n`.
+fn write_face(filename : String, face : Face, n : usize, mut f : impl FnMut(&OnCube) -> f64) -> DynError {
     use alg_tools::lingrid::LinSpace;
     use alg_tools::loc::Loc;
     use alg_tools::types::*;
@@ -84,6 +118,7 @@
             *p = Rgb(rgb.map(|v| (v*(u8::RANGE_MAX as f64)) as u8))
         });
 
-    img.save_with_format(format!("{filename}.png"), ImageFormat::Png)
-        .expect("Image save error");
+    img.save_with_format(format!("{filename}.png"), ImageFormat::Png)?;
+
+    Ok(())
 }

mercurial