src/iterate.rs

branch
dev
changeset 41
121cf065e9ed
parent 40
daf0e3a70c79
child 46
bd924d62d952
equal deleted inserted replaced
40:daf0e3a70c79 41:121cf065e9ed
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 }

mercurial