17 max_iter : 100, |
17 max_iter : 100, |
18 verbose_iter : Verbose::Every(10), |
18 verbose_iter : Verbose::Every(10), |
19 .. Default::default() |
19 .. Default::default() |
20 }; |
20 }; |
21 let mut x = 1 as float; |
21 let mut x = 1 as float; |
|
22 # let mut iter_clone = iter.clone(); |
22 iter.iterate(|state|{ |
23 iter.iterate(|state|{ |
23 // This is our computational step |
24 // This is our computational step |
24 x = x + x.sqrt(); |
25 x = x + x.sqrt(); |
25 state.if_verbose(||{ |
26 state.if_verbose(||{ |
26 // return current value when requested |
27 // return current value when requested |
27 return x |
28 return x |
28 }) |
29 }) |
29 }) |
30 }); |
|
31 // or alternatively (avoiding problems with moves) |
|
32 # iter = iter_clone; |
|
33 for state in iter.iter() { |
|
34 // This is our computational step |
|
35 x = x + x.sqrt(); |
|
36 state.if_verbose(||{ |
|
37 // return current value when requested |
|
38 return x |
|
39 }) |
|
40 } |
30 ``` |
41 ``` |
31 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. |
42 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. |
32 |
43 |
33 This will print out |
44 This will print out |
34 ```output |
45 ```output |
50 use serde::{Serialize, Deserialize}; |
61 use serde::{Serialize, Deserialize}; |
51 use cpu_time::ProcessTime; |
62 use cpu_time::ProcessTime; |
52 use std::marker::PhantomData; |
63 use std::marker::PhantomData; |
53 use std::time::Duration; |
64 use std::time::Duration; |
54 use std::error::Error; |
65 use std::error::Error; |
|
66 use std::cell::RefCell; |
55 use std::rc::Rc; |
67 use std::rc::Rc; |
56 use std::cell::Cell; |
|
57 use crate::types::*; |
68 use crate::types::*; |
58 use crate::logger::*; |
69 use crate::logger::*; |
59 |
70 |
60 /// Create the displayed presentation for log items. |
71 /// Create the displayed presentation for log items. |
61 pub trait LogRepr : Debug { |
72 pub trait LogRepr : Debug { |
390 fn is_quiet(&self) -> bool { false } |
401 fn is_quiet(&self) -> bool { false } |
391 |
402 |
392 /// Returns an an [`std::iter::Iterator`] that can be used in a `for`-loop. |
403 /// Returns an an [`std::iter::Iterator`] that can be used in a `for`-loop. |
393 fn iter(self) -> AlgIteratorIterator<Self::Iter> { |
404 fn iter(self) -> AlgIteratorIterator<Self::Iter> { |
394 AlgIteratorIterator { |
405 AlgIteratorIterator { |
395 algi : self.prepare(), |
406 algi : Rc::new(RefCell::new(self.prepare())), |
396 result : Rc::new(AlgIteratorResponse{ |
|
397 expected_iter : 0, |
|
398 response : Cell::new(Step::Quiet) |
|
399 }) |
|
400 } |
407 } |
401 } |
408 } |
402 } |
409 } |
403 |
410 |
404 /// Options for [`BasicAlgIteratorFactory`]. |
411 /// Options for [`BasicAlgIteratorFactory`]. |
1013 |
1020 |
1014 // |
1021 // |
1015 // New for-loop interface |
1022 // New for-loop interface |
1016 // |
1023 // |
1017 |
1024 |
1018 struct AlgIteratorResponse<I : AlgIterator> { |
|
1019 expected_iter : usize, |
|
1020 response : Cell<Step<I::Input, I::State>>, |
|
1021 } |
|
1022 pub struct AlgIteratorIterator<I : AlgIterator> { |
1025 pub struct AlgIteratorIterator<I : AlgIterator> { |
1023 algi : I, |
1026 algi : Rc<RefCell<I>>, |
1024 result : Rc<AlgIteratorResponse<I>>, |
|
1025 } |
1027 } |
1026 |
1028 |
1027 pub struct AlgIteratorIteration<I : AlgIterator> { |
1029 pub struct AlgIteratorIteration<I : AlgIterator> { |
1028 state : I::State, |
1030 state : I::State, |
1029 result : Rc<AlgIteratorResponse<I>>, |
1031 algi : Rc<RefCell<I>>, |
1030 } |
|
1031 |
|
1032 impl<I : AlgIterator> AlgIteratorIterator<I> { |
|
1033 fn poststep(&mut self, even_if_quiet : bool) { |
|
1034 let res = self.result.response.take(); |
|
1035 if !even_if_quiet { |
|
1036 if let Step::Quiet = res { |
|
1037 return |
|
1038 } |
|
1039 } |
|
1040 self.algi.poststep(res); |
|
1041 } |
|
1042 } |
1032 } |
1043 |
1033 |
1044 impl<I : AlgIterator> std::iter::Iterator for AlgIteratorIterator<I> { |
1034 impl<I : AlgIterator> std::iter::Iterator for AlgIteratorIterator<I> { |
1045 type Item = AlgIteratorIteration<I>; |
1035 type Item = AlgIteratorIteration<I>; |
1046 |
1036 |
1047 fn next(&mut self) -> Option<Self::Item> { |
1037 fn next(&mut self) -> Option<Self::Item> { |
1048 self.poststep(true); |
1038 let algi = self.algi.clone(); |
1049 self.algi.prestep().map(|state| AlgIteratorIteration { |
1039 RefCell::borrow_mut(&self.algi).prestep().map(|state| AlgIteratorIteration { |
1050 state, |
1040 state, |
1051 result : self.result.clone(), |
1041 algi, |
1052 }) |
1042 }) |
1053 } |
|
1054 } |
|
1055 |
|
1056 impl<I : AlgIterator> Drop for AlgIteratorIterator<I> { |
|
1057 fn drop(&mut self) { |
|
1058 self.poststep(false) |
|
1059 } |
1043 } |
1060 } |
1044 } |
1061 |
1045 |
1062 /// Types of errors that may occur |
1046 /// Types of errors that may occur |
1063 #[derive(Debug,PartialEq,Eq)] |
1047 #[derive(Debug,PartialEq,Eq)] |
1081 pub fn if_verbose(self, calc_objective : impl FnMut() -> I::Input) { |
1065 pub fn if_verbose(self, calc_objective : impl FnMut() -> I::Input) { |
1082 self.if_verbose_check(calc_objective).unwrap() |
1066 self.if_verbose_check(calc_objective).unwrap() |
1083 } |
1067 } |
1084 |
1068 |
1085 /// Version of [`Self::if_verbose`] that propagates errors instead of panicking. |
1069 /// Version of [`Self::if_verbose`] that propagates errors instead of panicking. |
1086 pub fn if_verbose_check(self, mut calc_objective : impl FnMut() -> I::Input) |
1070 pub fn if_verbose_check(self, calc_objective : impl FnMut() -> I::Input) |
1087 -> Result<(), IterationError> { |
1071 -> Result<(), IterationError> { |
1088 if self.result.expected_iter != self.state.iteration() { |
1072 let mut algi = match RefCell::try_borrow_mut(&self.algi) { |
|
1073 Err(_) => return Err(IterationError::ReportingOrderingError), |
|
1074 Ok(algi) => algi |
|
1075 }; |
|
1076 if self.state.iteration() != algi.iteration() { |
1089 Err(IterationError::ReportingOrderingError) |
1077 Err(IterationError::ReportingOrderingError) |
1090 } else { |
1078 } else { |
1091 let res = calc_objective(); |
1079 let res : Step<I::Input, I::State, std::convert::Infallible> |
1092 self.result.response.replace(Step::Result(res, self.state)); |
1080 = self.state.if_verbose(calc_objective); |
|
1081 algi.poststep(res); |
1093 Ok(()) |
1082 Ok(()) |
1094 } |
1083 } |
1095 } |
1084 } |
1096 |
1085 |
1097 /// Returns the current iteration count. |
1086 /// Returns the current iteration count. |
1149 .skip(2) |
1138 .skip(2) |
1150 .step_by(3) |
1139 .step_by(3) |
1151 .collect::<Vec<int>>()) |
1140 .collect::<Vec<int>>()) |
1152 } |
1141 } |
1153 } |
1142 } |
1154 } |
1143 |
|
1144 #[test] |
|
1145 fn iteration_for_loop() { |
|
1146 let options = AlgIteratorOptions{ |
|
1147 max_iter : 10, |
|
1148 verbose_iter : Verbose::Every(3), |
|
1149 .. Default::default() |
|
1150 }; |
|
1151 |
|
1152 { |
|
1153 let mut start = 1 as int; |
|
1154 for state in options.iter() { |
|
1155 start = start * 2; |
|
1156 state.if_verbose(|| start) |
|
1157 } |
|
1158 assert_eq!(start, (2 as int).pow(10)); |
|
1159 } |
|
1160 |
|
1161 { |
|
1162 let mut start = 1 as int; |
|
1163 let mut log = Logger::new(); |
|
1164 let factory = options.instantiate() |
|
1165 .with_iteration_number() |
|
1166 .into_log(&mut log); |
|
1167 for state in factory.iter() { |
|
1168 start = start * 2; |
|
1169 state.if_verbose(|| start) |
|
1170 } |
|
1171 assert_eq!(start, (2 as int).pow(10)); |
|
1172 assert_eq!(log.data() |
|
1173 .iter() |
|
1174 .map(|LogItem{ data : v, iter : _ }| v.clone()) |
|
1175 .collect::<Vec<int>>(), |
|
1176 (1..10).map(|i| (2 as int).pow(i)) |
|
1177 .skip(2) |
|
1178 .step_by(3) |
|
1179 .collect::<Vec<int>>()) |
|
1180 } |
|
1181 } |
|
1182 |
|
1183 } |