src/iterate.rs

Mon, 24 Oct 2022 10:52:19 +0300

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 24 Oct 2022 10:52:19 +0300
changeset 4
61b068c50e25
parent 3
20db884b7028
child 5
59dc4c5883f4
permissions
-rw-r--r--

Added type for numerical errors

0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3 This module provides tools for separating the computational steps of iterative
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 algorithms from visualisation and other reporting routines. The approach is heavily
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 indebted to functional programming. The computational step is to be implemented as a
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 closure. That closure gets passed a `state` parameter that implements an
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 [`if_verbose`][AlgIteratorState::if_verbose] method that is to be called to determine
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 whether function values or other potentially costly things need to be calculated on that
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 iteration. The parameter of [`if_verbose`][AlgIteratorState::if_verbose] is another
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 closure that does the necessary computation.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 ## Simple example
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 ```rust
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 use alg_tools::types::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 use alg_tools::iterate::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 let mut iter = AlgIteratorOptions{ max_iter : 100,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 verbose_iter : Verbose::Every(10),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 .. Default::default() };
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 let mut x = 1 as float;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 iter.iterate(|state|{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 // This is our computational step
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 x = x + x.sqrt();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 state.if_verbose(||{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 // return current value when requested
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 return x
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 There is no colon after `state.if_verbose`, because we need to return its value. If you do something after the step, you need to store the result in a variable and return it from the main computational step afterwards.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 This will print out
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 ```output
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 10/100 J=31.051164
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 20/100 J=108.493699
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 30/100 J=234.690039
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 40/100 J=410.056327
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 50/100 J=634.799262
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 60/100 J=909.042928
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 70/100 J=1232.870172
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 80/100 J=1606.340254
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 90/100 J=2029.497673
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 100/100 J=2502.377071
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 */
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 use colored::{Colorize,ColoredString};
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 //use num_traits::Num;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 use core::fmt::Debug;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 //use core::fmt::Display;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 //use std::sync::mpsc::Receiver;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 use serde::{Serialize, Deserialize};
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 use cpu_time::ProcessTime;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 use std::marker::PhantomData;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 use std::time::Duration;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
56 use std::error::Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 use crate::types::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58 use crate::logger::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 /// Create the displayed presentation for log items. Override for nice (condensed) presentation of rich log items, or define `show` if it is not defined for your type.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 pub trait LogRepr : Debug {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
62 fn logrepr(&self) -> ColoredString { format!("« {self:?} »").as_str().into() }
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 impl LogRepr for str {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 fn logrepr(&self) -> ColoredString { self.into() }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 impl LogRepr for String {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 fn logrepr(&self) -> ColoredString { self.as_str().into() }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 impl<T> LogRepr for T where T : Num {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
74 fn logrepr(&self) -> ColoredString { format!("J={self}").as_str().into() }
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 impl<V> LogRepr for Option<V> where V : LogRepr {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 fn logrepr(&self) -> ColoredString {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 match self {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 None => { "===missing value===".red() }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 Some(v) => { v.logrepr() }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 #[derive(Debug,Clone)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 pub struct Annotated<F>(pub F, pub String);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 impl<V> LogRepr for Annotated<V> where V : LogRepr {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 fn logrepr(&self) -> ColoredString {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 format!("{}\t| {}", self.0.logrepr(), self.1).as_str().into()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 /// Basic log item.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 pub struct LogItem<V> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99 pub iter : usize,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100 // This causes [`csv`] to crash.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 //#[serde(flatten)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 pub data : V
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 fn make_logitem<V>(iter : usize, data : V) -> LogItem<V> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 LogItem{ iter, data }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 /// State of an [`AlgIterator`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 pub trait AlgIteratorState {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
111 /// Call `call_objective` if this is a verbose iteration.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
112 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
113 /// Verbosity depends on the [`AlgIterator`] that produced this state.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
114 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
115 /// The closure `calc_objective` should return an arbitrary value of type `V`, to be inserted
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
116 /// into the log, or whatever is deemed by the [`AlgIterator`]. For usage instructions see the
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
117 /// [module documentation][self].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
118 fn if_verbose<V, E : Error>(&self, calc_objective : impl FnMut() -> V) -> Step<V, E>;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 fn iteration(&self) -> usize;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123 /// Result of a step of an [`AlgIterator`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 #[derive(Debug, Serialize)]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
125 pub enum Step<V, Fail : Error = std::convert::Infallible> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126 /// Iteration should be terminated
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 Terminated,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
128 /// Iteration should be terminated due to failure
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
129 Failure(Fail),
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 /// No result this iteration (due to verbosity settings)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 Quiet,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 /// Result of this iteration (due to verbosity settings)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 Result(V),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
136 impl<V, E : Error> Step<V, E> {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
137 /// Maps the value contained within the `Step`, if any, by the closure `f`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
138 pub fn map<U>(self, mut f : impl FnMut(V) -> U) -> Step<U, E> {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
139 match self {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
140 Step::Result(v) => Step::Result(f(v)),
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
141 Step::Failure(e) => Step::Failure(e),
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
142 Step::Quiet => Step::Quiet,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
143 Step::Terminated => Step::Terminated,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
144 }
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
145 }
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
146 }
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
147
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148 /// An iterator for algorithms, produced by [`AlgIteratorFactory.prepare`].
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
149 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
150 /// Typically not accessed directly, but transparently produced by an [`AlgIteratorFactory`].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
151 /// Every [`AlgIteratorFactory`] has to implement a corresponding `AlgIterator`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
152 pub trait AlgIterator : Sized {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 type State : AlgIteratorState;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 type Output;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
155 type Err : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157 /// Advance the iterator.
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
158 fn step(&mut self) -> Step<Self::Output, Self::Err>;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 /// Return current iteration count.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 self.state().iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 /// Return current iteration stats.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 fn state(&self) -> Self::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
168 /// Iterate the `AlgIterator` until termination.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
169 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
170 /// Returns either `()` or an error if the step closure terminated in [`Step::Failure´].
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
172 fn iterate(&mut self) -> Result<(), Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 loop {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
174 match self.step() {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
175 Step::Terminated => return Ok(()),
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
176 Step::Failure(e) => return Err(e),
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
177 _ => {},
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
182 /// Converts the `AlgIterator` into a plain [`Iterator`].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
183 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
184 /// [`Step::Quiet`] results are discarded.
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 /// (This is to avoid having to manually implement [`IntoIterator`] or [`Iterator`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 /// for every single [`AlgIterator`].)
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
187 fn downcast(self) -> AlgIteratorI<Self> {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
188 AlgIteratorI(self)
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 /// Conversion of an `AlgIterator` into a plain [`Iterator`].
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
193 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
194 /// The conversion discards [`Step::Quiet`] and panics on [`Step::Failure`].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
195 pub struct AlgIteratorI<A>(A);
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
197 impl<A> Iterator for AlgIteratorI<A>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
198 where A : AlgIterator {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 type Item = A::Output;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 fn next(&mut self) -> Option<A::Output> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 loop {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 match self.0.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 Step::Result(v) => return Some(v),
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
205 Step::Failure(e) => panic!("{e:?}"),
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 Step::Terminated => return None,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 Step::Quiet => continue,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213 /// A factory for producing an [`AlgIterator`]. To use one:
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 ///
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 /// ```rust
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216 /// use alg_tools::iterate::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217 /// let mut iter = AlgIteratorOptions::default();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 /// iter.iterate(|state|{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 /// // perform iterations
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 /// state.if_verbose(||{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 /// // calculate and return function value or other displayed data v
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 /// return 0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 /// })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 /// })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 /// ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 pub trait AlgIteratorFactory<V> : Sized {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
227 type Iter<F, E> : AlgIterator<State = Self::State, Output = Self::Output, Err = E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
228 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
229 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 type State : AlgIteratorState;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 type Output;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 /// Prepare an [`AlgIterator`], consuming the factory.
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
234 ///
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 /// The function `step_fn` should accept a `state` ([`AlgIteratorState`] parameter, and return
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 /// a [`Step`].
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
237 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
238 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
239 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
241 /// Iterate the the closure `step`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
242 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
243 /// The closure should accept one `state` ([`AlgIteratorState`] parameter,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
244 /// and return the output of `state.if_verbose`, [`Step::Terminated`] to indicate completion
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
245 /// for other reason, or [`Step::Failure`] for termination for failure.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
246 /// For usage instructions see the [module documentation][self].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
247 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
248 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
249 #[inline]
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
250 fn iterate_fallible<F, E>(self, step : F) -> Result<(), E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
251 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
252 E : Error {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
253 self.prepare(step).iterate()
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
254 }
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
255
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
256 /// Iterate the the closure `step`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
257 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
258 /// The closure should accept one `state` ([`AlgIteratorState`] parameter,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
259 /// and return the output of `state.if_verbose`. For a fallible closure,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
260 /// use [`Self::iterate_fallible`].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
261 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
262 /// For usage instructions see the [module documentation][self].
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263 ///
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
264 /// This method is equivalent to [`Self::prepare`] followed by [`AlgIterator::iterate`]
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
265 /// with the error type `E=`[`std::convert::Infallible`].
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
267 fn iterate<F>(self, step : F)
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
268 where F : FnMut(&Self::State) -> Step<V> {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
269 self.iterate_fallible(step).unwrap_or_default()
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
270 }
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
271
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
272 /// Iterate the closure `step` with data produced by `datasource`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
273 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
274 /// The closure should accept a `state` ([`AlgIteratorState`] parameter, and a data parameter
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
275 /// taken from `datasource` It should return the output of
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
276 /// `state.[if_verbose][AlgIteratorState.if_verbose]`, [`Step::Terminated`] to indicate
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
277 /// completion for other reason, or [`Step::Failure`] for termination for failure.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
278 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
279 /// If the `datasource` runs out of data, the iterator is considered having terminated
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
280 /// successsfully.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
281 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
282 /// For usage instructions see the [module documentation][self].
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
283 #[inline]
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
284 fn iterate_data_fallible<F, D, I, E>(self, mut datasource : I, mut step : F) -> Result<(), E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
285 where F : FnMut(&Self::State, D) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
286 I : Iterator<Item = D>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
287 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 self.prepare(move |state| {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
289 datasource.next().map_or(Step::Terminated, |d| step(state, d))
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290 }).iterate()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
293 /// Iterate the closure `step` with data produced by `datasource`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
294 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
295 /// The closure should accept a `state` ([`AlgIteratorState`] parameter, and a data parameter
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
296 /// taken from `datasource` It should return the output of
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
297 /// `state.[if_verbose][AlgIteratorState.if_verbose]`.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
298 ///
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
299 /// If the `datasource` runs out of data, the iterator is considered having terminated
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
300 /// successsfully.
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
301 ///
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 /// For usage instructions see the [module documentation][self].
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
304 fn iterate_data<F, D, I>(self, datasource : I, step : F)
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
305 where F : FnMut(&Self::State, D) -> Step<V>,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306 I : Iterator<Item = D> {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
307 self.iterate_data_fallible(datasource, step).unwrap_or_default()
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
308 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
310 // fn make_iterate<'own>(self)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 // -> Box<dyn (FnMut(dyn FnMut(&Self::State) -> Option<V>) -> ()) + 'own> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 // Box::new(move |step| self.iterate(step))
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313 // }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315 // fn make_iterate_data<'own, D, I>(self, datasource : I)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 // -> Box<dyn (FnMut(dyn FnMut(&Self::State, D) -> Option<V>) -> ()) + 'own>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 // where I : Iterator<Item = D> + 'own {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 // Box::new(move |step| self.iterate_data(step, datasource))
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 // }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 /// Add logging to the iterator produced by the factory.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 fn into_log<'log>(self, logger : &'log mut Logger<Self::Output>)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 -> LoggingIteratorFactory<'log, Self::Output, Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 where Self : Sized {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 LoggingIteratorFactory {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 base_options : self,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 logger,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
328 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
331 /// Map the output of the iterator produced by the factory.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 fn mapped<U, G>(self, map : G)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
333 -> MappingIteratorFactory<G, Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
334 where Self : Sized,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335 G : Fn(usize, Self::Output) -> U {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 MappingIteratorFactory {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
337 base_options : self,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
338 map
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
339 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
340 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
341
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342 /// Adds iteration number to the output. Typically followed by [`Self::into_log`].
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343 fn with_iteration_number(self)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 -> MappingIteratorFactory<fn(usize, Self::Output) -> LogItem<Self::Output>, Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345 where Self : Sized {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 self.mapped(make_logitem)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
349 /// Add timing to the iterator produced by the factory.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
350 fn timed(self) -> TimingIteratorFactory<Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
351 where Self : Sized {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 TimingIteratorFactory(self)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
353 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
354
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
355 /// Add value stopping threshold to the iterator produce by the factory
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
356 fn stop_target(self, target : Self::Output) -> ValueIteratorFactory<Self::Output, Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
357 where Self : Sized,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
358 Self::Output : Num {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
359 ValueIteratorFactory { base_options : self, target : target }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
360 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
361
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
362 /// Add stall stopping to the iterator produce by the factory
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
363 fn stop_stall(self, stall : Self::Output) -> StallIteratorFactory<Self::Output, Self>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
364 where Self : Sized,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
365 Self::Output : Num {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
366 StallIteratorFactory { base_options : self, stall : stall }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
367 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
368
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
369 /// Is the iterator quiet, i.e., on-verbose?
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
370 fn is_quiet(&self) -> bool { false }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
371 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
372
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
373 /// Options for [`BasicAlgIteratorFactory`]. Use as:
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
374 /// ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
375 /// # use alg_tools::iterate::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
376 /// let iter = AlgIteratorOptions{ max_iter : 10000, .. Default::default() };
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
377 /// ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
378 #[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
379 pub struct AlgIteratorOptions {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
380 /// Maximum number of iterations
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 pub max_iter : usize,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 /// Number of iterations between verbose iterations that display state.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383 pub verbose_iter : Verbose,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
384 /// Whether verbose iterations are displayed, or just passed onwards to a containing
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
385 /// `AlgIterator`.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
386 pub quiet : bool,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
387 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
389 #[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
390 pub enum Verbose {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
391 /// Be verbose every $n$ iterations.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
392 Every(usize),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
393 /// Be verbose every $n$ iterations and initial $m$ iterations.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
394 EveryAndInitial{ every : usize, initial : usize },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
395 /// Be verbose if iteration number $n$ divides by $b^{\text{floor}(\log_b(n))}$, where
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
396 /// $b$ is indicated logarithmic base. So, with $b=10$,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
397 /// * every iteration for first 10 iterations,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
398 /// * every 10 iterations from there on until 100 iterations,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
399 /// * every 100 iteartinos frmo there on until 1000 iterations, etc.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
400 Logarithmic(usize),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
401 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
402
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
403 impl Verbose {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
404 /// Indicates whether given iteration number is verbose
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
405 pub fn is_verbose(&self, iter : usize) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
406 match self {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
407 &Verbose::Every(every) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
408 every != 0 && iter % every == 0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
409 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
410 &Verbose::EveryAndInitial{ every, initial } => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
411 iter <= initial || (every != 0 && iter % every == 0)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
412 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
413 &Verbose::Logarithmic(base) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
414 let every = 10usize.pow((iter as float).log(base as float).floor() as u32);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
415 iter % every == 0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
416 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
417 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
418 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
419 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
420
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
421 impl Default for AlgIteratorOptions {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
422 fn default() -> AlgIteratorOptions {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
423 AlgIteratorOptions{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
424 max_iter : 1000,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
425 verbose_iter : Verbose::EveryAndInitial { every : 100, initial : 10 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
426 quiet : false
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
427 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
428 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
429 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
430
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
431 /// State of a `BasicAlgIterator`
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
432 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
433 pub struct BasicState {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
434 iter : usize,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
435 verbose : bool,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
436 calc : bool,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
437 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
438
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
439 /// [`AlgIteratorFactory`] for [`BasicAlgIterator`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
440 #[derive(Clone,Debug)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
441 pub struct BasicAlgIteratorFactory<V> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
442 options : AlgIteratorOptions,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
443 _phantoms : PhantomData<V>,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
444 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
445
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
446 /// The simplest [`AlgIterator`], reated by [`BasicAlgIteratorFactory`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
447 #[derive(Clone,Debug)]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
448 pub struct BasicAlgIterator<F, V, E : Error> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
449 options : AlgIteratorOptions,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
450 iter : usize,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
451 step_fn : F,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
452 _phantoms : PhantomData<(V, E)>,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
453 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
454
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
455 impl AlgIteratorOptions {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
456 /// [`AlgIteratorOptions`] is directly a factory for [`BasicAlgIterator`],
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
457 /// however, due to type inference issues, it may become convenient to instantiate
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
458 /// it to a specific return type for the inner step function. This method does that.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
459 pub fn instantiate<V>(&self) -> BasicAlgIteratorFactory<V> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
460 BasicAlgIteratorFactory {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
461 options : self.clone(),
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
462 _phantoms : PhantomData
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
463 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
464 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
465 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
466
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
467 impl<V> AlgIteratorFactory<V> for AlgIteratorOptions
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
468 where V : LogRepr {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
469 type State = BasicState;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
470 type Iter<F, E> = BasicAlgIterator<F, V, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
471 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
472 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
473 type Output = V;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
474
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
475 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
476 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
477 E : Error {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
478 BasicAlgIterator{
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
479 options : self,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
480 iter : 0,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
481 step_fn,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
482 _phantoms : PhantomData,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
483 }
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
484 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
485
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
486 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
487 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
488 self.quiet
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
489 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
490 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
491
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
492 impl<V> AlgIteratorFactory<V> for BasicAlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
493 where V : LogRepr {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
494 type State = BasicState;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
495 type Iter<F, E> = BasicAlgIterator<F, V, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
496 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
497 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
498 type Output = V;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
499
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
500 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
501 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
502 E : Error {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
503 BasicAlgIterator {
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
504 options : self.options,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
505 iter : 0,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
506 step_fn,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
507 _phantoms : PhantomData
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
508 }
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
509 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
510
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
511 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
512 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
513 self.options.quiet
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
514 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
515 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
516
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
517 impl<F, V, E> AlgIterator for BasicAlgIterator<F, V, E>
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
518 where V : LogRepr,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
519 E : Error,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
520 F : FnMut(&BasicState) -> Step<V, E> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
521 type State = BasicState;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
522 type Output = V;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
523 type Err = E;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
524
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
525 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
526 fn step(&mut self) -> Step<V, E> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
527 if self.iter >= self.options.max_iter {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
528 Step::Terminated
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
529 } else {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
530 self.iter += 1;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
531 let state = self.state();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
532 let res = (self.step_fn)(&state);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
533 if let Step::Result(ref val) = res {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
534 if state.verbose && !self.options.quiet {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
535 println!("{}{}/{} {}{}", "".dimmed(),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
536 state.iter,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
537 self.options.max_iter,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
538 val.logrepr(),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
539 "".clear());
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
540 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
541 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
542 res
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
543 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
544 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
545
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
546 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
547 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
548 self.iter
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
549 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
550
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
551 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
552 fn state(&self) -> BasicState {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
553 let iter = self.iter;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
554 let verbose = self.options.verbose_iter.is_verbose(iter);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
555 BasicState{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
556 iter : iter,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
557 verbose : verbose,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
558 calc : verbose,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
559 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
560 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
561 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
562
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
563 impl AlgIteratorState for BasicState {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
564 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
565 fn if_verbose<V, E : Error>(&self, mut calc_objective : impl FnMut() -> V) -> Step<V, E> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
566 if self.calc {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
567 Step::Result(calc_objective())
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
568 } else {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
569 Step::Quiet
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
570 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
571 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
572
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
573 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
574 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
575 return self.iter;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
576 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
577 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
578
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
579 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
580 // Stall detecting iteration function.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
581 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
582
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
583 /// An [`AlgIteratorFactory`] for an [`AlgIterator`] that detects “stall”
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
584 /// $(v_{k+n}-v_k)/v_k ≤ θ$, where $n$ the distance between [`Step::Result`] iterations.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
585 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
586 pub struct StallIteratorFactory<U : Num, BaseFactory> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
587 /// Basic options
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
588 pub base_options : BaseFactory,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
589 /// Stalling threshold $θ$.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
590 pub stall : U,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
591 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
592
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
593 /// Iterator produced by [`StallIteratorFactory`].
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
594 pub struct StallIterator<U : Num, BaseIterator> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
595 base_iterator : BaseIterator,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
596 stall : U,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
597 previous_value : Option<U>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
598 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
599
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
600 impl<V, U, BaseFactory> AlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
601 for StallIteratorFactory<U, BaseFactory>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
602 where BaseFactory : AlgIteratorFactory<V, Output=U>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
603 U : SignedNum + PartialOrd {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
604 type Iter<F, E> = StallIterator<U, BaseFactory::Iter<F, E>>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
605 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
606 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
607 type State = BaseFactory::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
608 type Output = BaseFactory::Output;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
609
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
610 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
611 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
612 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
613 StallIterator {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
614 base_iterator : self.base_options.prepare(step_fn),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
615 stall : self.stall,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
616 previous_value : None,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
617 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
618 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
619
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
620 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
621 self.base_options.is_quiet()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
622 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
623 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
624
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
625 impl<U, BaseIterator> AlgIterator
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
626 for StallIterator<U, BaseIterator>
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
627 where BaseIterator : AlgIterator<Output=U>,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
628 U : SignedNum + PartialOrd {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
629 type State = BaseIterator::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
630 type Output = BaseIterator::Output;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
631 type Err = BaseIterator::Err;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
632
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
633 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
634 fn step(&mut self) -> Step<U, Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
635 match self.base_iterator.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
636 Step::Result(nv) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
637 let previous_v = self.previous_value;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
638 self.previous_value = Some(nv);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
639 match previous_v {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
640 Some(pv) if (nv - pv).abs() <= self.stall * pv.abs() => Step::Terminated,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
641 _ => Step::Result(nv),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
642 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
643 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
644 val => val,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
645 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
646 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
647
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
648 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
649 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
650 self.base_iterator.iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
651 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
652
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
653 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
654 fn state(&self) -> Self::State {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
655 self.base_iterator.state()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
656 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
657 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
658
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
659 /// An [`AlgIteratorFactory`] for an [`AlgIterator`] that detect whether step function
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
660 /// return value is less than `target`, and terminates if it is.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
661 #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
662 pub struct ValueIteratorFactory<U : Num, BaseFactory> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
663 /// Basic options
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
664 pub base_options : BaseFactory,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
665 /// Stalling threshold $θ$.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
666 pub target : U,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
667 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
668
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
669 /// Iterator produced by [`ValueIteratorFactory`].
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
670 pub struct ValueIterator<U : Num, BaseIterator> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
671 base_iterator : BaseIterator,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
672 target : U,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
673 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
674
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
675 impl<V, U, BaseFactory> AlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
676 for ValueIteratorFactory<U, BaseFactory>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
677 where BaseFactory : AlgIteratorFactory<V, Output=U>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
678 U : SignedNum + PartialOrd {
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
679 type Iter<F, E> = ValueIterator<U, BaseFactory::Iter<F, E>>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
680 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
681 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
682 type State = BaseFactory::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
683 type Output = BaseFactory::Output;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
684
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
685 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
686 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
687 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
688 ValueIterator {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
689 base_iterator : self.base_options.prepare(step_fn),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
690 target : self.target
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
691 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
692 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
693
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
694 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
695 self.base_options.is_quiet()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
696 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
697 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
698
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
699 impl<U, BaseIterator> AlgIterator
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
700 for ValueIterator<U, BaseIterator>
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
701 where BaseIterator : AlgIterator<Output=U>,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
702 U : SignedNum + PartialOrd {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
703 type State = BaseIterator::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
704 type Output = BaseIterator::Output;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
705 type Err = BaseIterator::Err;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
706
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
707 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
708 fn step(&mut self) -> Step<U, Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
709 match self.base_iterator.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
710 Step::Result(v) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
711 if v <= self.target {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
712 Step::Terminated
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
713 } else {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
714 Step::Result(v)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
715 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
716 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
717 val => val,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
718 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
719 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
720
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
721 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
722 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
723 self.base_iterator.iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
724 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
725
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
726 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
727 fn state(&self) -> Self::State {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
728 self.base_iterator.state()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
729 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
730 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
731
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
732 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
733 // Logging iterator
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
734 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
735
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
736 /// [`AlgIteratorFactory`] for a logging [`AlgIterator`].
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
737 /// The `Output` of the corresponding [`LoggingIterator`] is `()`:
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
738 /// The data is only inserted into the log, and not passed onwards.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
739 /// Use as:
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
740 /// ```rust
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
741 /// use alg_tools::iterate::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
742 /// use alg_tools::logger::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
743 /// let iter = AlgIteratorOptions::default();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
744 /// let mut log = Logger::new();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
745 /// iter.into_log(&mut log).iterate(|state|{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
746 /// // perform iterations
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
747 /// state.if_verbose(||{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
748 /// // calculate and return function value or other displayed data v
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
749 /// return 0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
750 /// })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
751 /// })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
752 /// ```
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
753 #[derive(Debug)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
754 pub struct LoggingIteratorFactory<'log, U, BaseFactory> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
755 pub base_options : BaseFactory,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
756 pub logger : &'log mut Logger<U>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
757 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
758
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
759 /// Iterator produced by `LoggingIteratorFactory`.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
760 pub struct LoggingIterator<'log, U, BaseIterator> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
761 base_iterator : BaseIterator,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
762 logger : &'log mut Logger<U>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
763 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
764
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
765
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
766 impl<'log, V, BaseFactory> AlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
767 for LoggingIteratorFactory<'log, BaseFactory::Output, BaseFactory>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
768 where BaseFactory : AlgIteratorFactory<V>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
769 BaseFactory::Output : 'log {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
770 type State = BaseFactory::State;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
771 type Iter<F, E> = LoggingIterator<'log, BaseFactory::Output, BaseFactory::Iter<F, E>>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
772 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
773 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
774 type Output = ();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
775
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
776 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
777 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
778 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
779 LoggingIterator {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
780 base_iterator : self.base_options.prepare(step_fn),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
781 logger : self.logger,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
782 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
783 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
784
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
785 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
786 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
787 self.base_options.is_quiet()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
788 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
789 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
790
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
791 impl<'log, BaseIterator> AlgIterator
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
792 for LoggingIterator<'log, BaseIterator::Output, BaseIterator>
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
793 where BaseIterator : AlgIterator,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
794 BaseIterator::Output : 'log {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
795 type State = BaseIterator::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
796 type Output = ();
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
797 type Err = BaseIterator::Err;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
798
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
799 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
800 fn step(&mut self) -> Step<Self::Output, Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
801 match self.base_iterator.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
802 Step::Result(v) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
803 self.logger.log(v);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
804 Step::Quiet
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
805 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
806 Step::Quiet => Step::Quiet,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
807 Step::Terminated => Step::Terminated,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
808 Step::Failure(e) => Step::Failure(e),
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
809 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
810 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
811
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
812 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
813 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
814 self.base_iterator.iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
815 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
816
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
817 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
818 fn state(&self) -> Self::State {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
819 self.base_iterator.state()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
820 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
821 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
822
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
823 /// This [`AlgIteratorFactory`] allows output mapping.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
824 #[derive(Debug)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
825 pub struct MappingIteratorFactory<G, BaseFactory> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
826 pub base_options : BaseFactory,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
827 pub map : G,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
828 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
829
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
830 /// Iterator produced by `MappingIteratorFactory`.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
831 pub struct MappingIterator<G, BaseIterator> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
832 base_iterator : BaseIterator,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
833 map : G,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
834 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
835
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
836
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
837 impl<V, U, G, BaseFactory> AlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
838 for MappingIteratorFactory<G, BaseFactory>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
839 where BaseFactory : AlgIteratorFactory<V>,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
840 G : Fn(usize, BaseFactory::Output) -> U {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
841 type State = BaseFactory::State;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
842 type Iter<F, E> = MappingIterator<G, BaseFactory::Iter<F, E>>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
843 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
844 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
845 type Output = U;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
846
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
847 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
848 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
849 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
850 MappingIterator {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
851 base_iterator : self.base_options.prepare(step_fn),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
852 map : self.map
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
853 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
854 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
855
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
856 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
857 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
858 self.base_options.is_quiet()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
859 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
860 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
861
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
862 impl<U, G, BaseIterator> AlgIterator
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
863 for MappingIterator<G, BaseIterator>
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
864 where BaseIterator : AlgIterator,
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
865 G : Fn(usize, BaseIterator::Output) -> U {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
866 type State = BaseIterator::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
867 type Output = U;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
868 type Err = BaseIterator::Err;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
869
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
870 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
871 fn step(&mut self) -> Step<Self::Output, Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
872 match self.base_iterator.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
873 Step::Result(v) => Step::Result((self.map)(self.iteration(), v)),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
874 Step::Quiet => Step::Quiet,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
875 Step::Terminated => Step::Terminated,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
876 Step::Failure(e) => Step::Failure(e),
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
877 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
878 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
879
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
880 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
881 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
882 self.base_iterator.iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
883 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
884
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
885 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
886 fn state(&self) -> Self::State {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
887 self.base_iterator.state()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
888 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
889 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
890
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
891 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
892 // Timing iterator
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
893 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
894
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
895 /// An [`AlgIteratorFactory`] for an [`AlgIterator`] that adds CPU time spent to verbose events.
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
896 #[derive(Debug)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
897 pub struct TimingIteratorFactory<BaseFactory>(pub BaseFactory);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
898
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
899 /// Iterator produced by [`TimingIteratorFactory`]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
900 #[derive(Debug)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
901 pub struct TimingIterator<BaseIterator> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
902 base_iterator : BaseIterator,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
903 start_time : ProcessTime,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
904 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
905
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
906 /// Data `U` with production time attached
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
907 #[derive(Copy, Clone, Debug, Serialize)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
908 pub struct Timed<U> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
909 pub cpu_time : Duration,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
910 //#[serde(flatten)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
911 pub data : U
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
912 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
913
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
914 impl<T> LogRepr for Timed<T> where T : LogRepr {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
915 fn logrepr(&self) -> ColoredString {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
916 format!("[{:.3}s] {}", self.cpu_time.as_secs_f64(), self.data.logrepr()).as_str().into()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
917 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
918 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
919
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
920
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
921 impl<V, BaseFactory> AlgIteratorFactory<V>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
922 for TimingIteratorFactory<BaseFactory>
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
923 where BaseFactory : AlgIteratorFactory<V> {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
924 type State = BaseFactory::State;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
925 type Iter<F, E> = TimingIterator<BaseFactory::Iter<F, E>>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
926 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
927 E : Error;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
928 type Output = Timed<BaseFactory::Output>;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
929
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
930 fn prepare<F, E>(self, step_fn : F) -> Self::Iter<F, E>
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
931 where F : FnMut(&Self::State) -> Step<V, E>,
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
932 E : Error {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
933 TimingIterator {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
934 base_iterator : self.0.prepare(step_fn),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
935 start_time : ProcessTime::now()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
936 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
937 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
938
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
939 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
940 fn is_quiet(&self) -> bool {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
941 self.0.is_quiet()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
942 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
943 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
944
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
945 impl<BaseIterator> AlgIterator
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
946 for TimingIterator<BaseIterator>
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
947 where BaseIterator : AlgIterator {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
948 type State = BaseIterator::State;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
949 type Output = Timed<BaseIterator::Output>;
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
950 type Err = BaseIterator::Err;
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
951
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
952 #[inline]
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
953 fn step(&mut self) -> Step<Self::Output, Self::Err> {
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
954 match self.base_iterator.step() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
955 Step::Result(data) => {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
956 Step::Result(Timed{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
957 cpu_time : self.start_time.elapsed(),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
958 data
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
959 })
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
960 },
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
961 Step::Quiet => Step::Quiet,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
962 Step::Terminated => Step::Terminated,
3
20db884b7028 Allow step closure of AlgIterators to indicate succesfull termination or failure.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
963 Step::Failure(e) => Step::Failure(e),
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
964 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
965 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
966
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
967 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
968 fn iteration(&self) -> usize {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
969 self.base_iterator.iteration()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
970 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
971
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
972 #[inline]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
973 fn state(&self) -> Self::State {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
974 self.base_iterator.state()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
975 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
976 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
977
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
978 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
979 // Tests
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
980 //
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
981
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
982 #[cfg(test)]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
983 mod tests {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
984 use super::*;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
985 use crate::logger::Logger;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
986 #[test]
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
987 fn iteration() {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
988 let options = AlgIteratorOptions{
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
989 max_iter : 10,
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
990 verbose_iter : Verbose::Every(3),
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
991 .. Default::default()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
992 };
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
993
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
994 {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
995 let mut start = 1 as int;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
996 options.iterate(|state| {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
997 start = start * 2;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
998 state.if_verbose(|| start)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
999 });
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1000 assert_eq!(start, (2 as int).pow(10));
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1001 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1002
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1003 {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1004 let mut start = 1 as int;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1005 let mut log = Logger::new();
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1006 let factory = options.instantiate()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1007 .with_iteration_number()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1008 .into_log(&mut log);
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1009 factory.iterate(|state| {
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1010 start = start * 2;
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1011 state.if_verbose(|| start)
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1012 });
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1013 assert_eq!(start, (2 as int).pow(10));
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1014 assert_eq!(log.data()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1015 .iter()
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1016 .map(|LogItem{ data : v, iter : _ }| v.clone())
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1017 .collect::<Vec<int>>(),
1
df3901ec2f5d Fix some unit tests after fundamental changes that made them invalid
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
1018 (1..10).map(|i| (2 as int).pow(i))
df3901ec2f5d Fix some unit tests after fundamental changes that made them invalid
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
1019 .skip(2)
df3901ec2f5d Fix some unit tests after fundamental changes that made them invalid
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
1020 .step_by(3)
0
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1021 .collect::<Vec<int>>())
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1022 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1023 }
9f27689eb130 Initialise new clean repository
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1024 }

mercurial