1#![doc = include_str!("../README.md")]
2
3extern crate self as iter_solver;
4
5pub use iter_state_derive::IterState;
6
7use std::{marker::PhantomData, mem, time::{Duration, Instant}};
8
9use crate::error::{ReachMaxIteration, TimeOut};
10
11pub mod error;
12mod utils;
13mod build_test;
14
15pub trait IterState: Sized {
27 type Value;
29
30 type Solution;
32
33 fn init_from_value(initial_point: Self::Value) -> Self;
35
36 fn to_sol(&self) -> Self::Solution;
38}
39
40macro_rules! iterstate_impl {
41 ($($ty:ty),*) => {
42 $(
43 impl IterState for $ty {
44 type Value = $ty;
45 type Solution = $ty;
46 fn init_from_value(initial_point: Self::Value) -> Self {
47 initial_point
48 }
49 fn to_sol(&self) -> Self::Solution {
50 *self
51 }
52 }
53 )*
54 };
55}
56
57iterstate_impl!(
58 u8,u16,u32,u64,u128,usize,
59 i8,i16,i32,i64,i128,isize,
60 f32, f64
61);
62
63
64#[derive(Debug)]
70pub struct Solver<State, Problem, IterFn, TermFn>
71where
72State: IterState,
73IterFn: Fn(&State, &Problem) -> State,
74TermFn: Fn(&State, &Problem) -> bool,
75{
76 state: PhantomData<State>,
78 problem: PhantomData<Problem>,
80 iter_fn: IterFn,
82 term_cond: TermFn,
84}
85impl<State, Problem, IterFn, TermFn> Solver<State, Problem, IterFn, TermFn>
86where
87 State: IterState,
88 IterFn: Fn(&State, &Problem) -> State,
89 TermFn: Fn(&State, &Problem) -> bool
90{
91 pub fn new(
98 iter_fn: IterFn,
99 term_cond: TermFn
100 ) -> Self {
101 Self {
102 state: PhantomData::<State>,
103 problem: PhantomData::<Problem>,
104 iter_fn: iter_fn,
105 term_cond: term_cond
106 }
107 }
108
109 pub fn solve(&self, initial_point: State::Value, problem: &Problem) -> State::Solution {
116 let initial_state = State::init_from_value(initial_point);
118 let mut state = initial_state;
119
120 loop {
122 state = (self.iter_fn)(&state, problem);
125
126 if (self.term_cond)(&state, problem) {
128 break;
129 }
130 }
131
132 let final_state = state;
133
134 let sol = final_state.to_sol();
135
136 sol
139 }
140
141
142 pub fn solve_with_max_iteration(
157 &self,
158 initial_point: State::Value,
159 problem: &Problem,
160 max_iteration: u64
161 ) -> Result<State::Solution, error::ReachMaxIteration<State>> {
162 let mut reach_max = true;
163
164 let initial_state = State::init_from_value(initial_point);
166 let mut state = initial_state;
167
168 for _iteration in 0..max_iteration {
169 state = (self.iter_fn)(&state, problem);
172
173 if (self.term_cond)(&state, problem) {
175 reach_max = false;
176 break;
177 }
178 }
179
180 let ret_res = if !reach_max {
181 let final_state = state;
182 let sol = final_state.to_sol();
183 Ok(sol)
185 } else {
186 let final_state = state;
187 Err(ReachMaxIteration{
188 max_iteration: max_iteration,
189 final_state: final_state
190 })
191 };
192
193 ret_res
194 }
195
196 pub fn solve_with_timeout(
212 &self,
213 initial_point: State::Value,
214 problem: &Problem,
215 timeout: Duration
216 ) -> Result<State::Solution, TimeOut<State>> {
217 let start_time = Instant::now();
218 let mut is_timeout = true;
219
220 let initial_state = State::init_from_value(initial_point);
222 let mut state = initial_state;
223
224 loop {
226 state = (self.iter_fn)(&state, problem);
229
230 if start_time.elapsed() > timeout {
231 break;
232 }
233
234 if (self.term_cond)(&state, problem) {
236 is_timeout = false;
237 break;
238 }
239 }
240
241 if !is_timeout {
242 let final_state = state;
243
244 let sol = final_state.to_sol();
245
246 Ok(sol)
249 } else {
250 let final_state = state; Err(TimeOut { timeout: timeout, final_state: final_state })
252 }
253
254 }
255
256
257
258 pub fn into_iter<'prob>(self,
275 initial_point: State::Value,
276 problem: &'prob Problem
277 ) -> SolverIterator<'prob, State, Problem, IterFn, TermFn> {
278 let initial_state = State::init_from_value(initial_point);
280
281 SolverIterator {
282 problem: problem,
283 state: Some(initial_state),
284 iter_fn: self.iter_fn,
285 term_cond: self.term_cond,
286 }
288 }
289
290 pub fn change_term_cond<NewTermCond>(self, new_cond: NewTermCond) -> Solver<State, Problem, IterFn, NewTermCond>
292 where
293 NewTermCond: Fn(&State, &Problem) -> bool
294 {
295 Solver {
296 state: self.state,
297 problem: self.problem,
298 iter_fn: self.iter_fn,
299 term_cond: new_cond
300 }
301 }
302}
303
304impl<State, Problem, IterFn, TermFn> Clone for Solver<State, Problem, IterFn, TermFn>
305where
306 State: IterState,
307 IterFn: Fn(&State, &Problem) -> State + Clone,
308 TermFn: Fn(&State, &Problem) -> bool + Clone
309{
310 fn clone(&self) -> Self {
311 Self { state: PhantomData::<State>, problem: PhantomData::<Problem>, iter_fn: self.iter_fn.clone(), term_cond: self.term_cond.clone() }
312 }
313}
314
315#[derive(Debug)]
327pub struct SolverIterator<'prob, State, Problem, IterFn, TermFn>
328where
329 State: IterState,
330 IterFn: Fn(&State, &Problem) -> State,
331 TermFn: Fn(&State, &Problem) -> bool
332{
333 state: Option<State>,
334 iter_fn: IterFn,
335 term_cond: TermFn,
336 problem: &'prob Problem,
337 }
339
340impl<'prob, State, Problem, IterFn, TermFn> Iterator for SolverIterator<'prob, State, Problem, IterFn, TermFn>
341where
342 State: IterState,
343 IterFn: Fn(&State, &Problem) -> State,
344 TermFn: Fn(&State, &Problem) -> bool
345{
346 type Item = State;
347
348 fn next(&mut self) -> Option<Self::Item> {
349 let state = if (&self.state).is_none() {
350 return None;
351 } else {
352 &self.state.as_ref().unwrap()
353 };
354
355 if (self.term_cond)(&state, &self.problem) {
358 let old_state = mem::replace(&mut self.state, None);
359
360 return old_state;
361 } else {
362 let next_state = (self.iter_fn)(state, &self.problem);
363 let old_state = mem::replace(&mut self.state, Some(next_state));
364
365 return old_state;
366 }
367 }
368}
369
370
371
372
373
374
375#[cfg(test)]
376mod test {
377 mod newton {
378 use crate::{IterState, Solver};
379
380 fn f_and_df(x: f64) -> (f64, f64) {
381 let fx = x.exp() - 1.5;
382 let dfx = x.exp();
383 (fx, dfx)
384 }
385 #[test]
386 fn show() {
387 let iter_fn = |state: &f64, problem: &fn(f64) -> (f64, f64)| {
388 let x_n = *state;
389 let (fx, dfx) = problem(x_n);
390 x_n - (fx / dfx)
391 };
392
393 let term_cond = |state: &f64, problem: &fn(f64) -> (f64, f64)| {
394 let (fx, _) = problem(*state);
395 fx.abs() < 1e-6
396 };
397
398 let solver = Solver::new(iter_fn, term_cond);
399
400 let solution = solver.solve(1.5, &(f_and_df as fn(f64) -> (f64, f64)));
401
402 println!("solver's solution: {}", solution);
403 println!("use std function ln: {}", 1.5_f64.ln());
404 }
405
406 #[derive(Clone)]
407 enum Equation {
408 Exp {
409 a: f64,
411 k: f64
412 },
413
414 Square {
415 a: f64,
417 b: f64,
418 c: f64
419 }
420 }
421
422 impl Equation {
423 fn calc(&self, val: f64) -> f64 {
424 match self {
425 Self::Exp { a, k } => {
426 a * val.exp() - k
427 }
428
429 Self::Square { a, b, c } => {
430 let x2 = a * val * val;
431 let x1 = b * val;
432 let x0 = c;
433 x2 + x1 + x0
434 }
435 }
436 }
437
438 fn diff(&self, val: f64) -> f64 {
439 match self {
440 Self::Exp { a, k: _ } => {
441 a * val.exp()
442 }
443
444 Self::Square { a, b, c: _ } => {
445 ((2. * a) * val) + b
446 }
447 }
448 }
449 }
450
451 #[derive(Debug, Clone)]
452 struct NewtonState(f64);
453
454 impl IterState for NewtonState {
455 type Value = f64;
456
457 type Solution = f64;
458
459 fn init_from_value(initial_point: Self::Value) -> Self {
460 Self(initial_point)
461 }
462
463 fn to_sol(&self) -> Self::Solution {
464 self.0
465 }
466 }
467
468 #[test]
469 fn test() {
470 let iter_fn = |state: &NewtonState, problem: &Equation| {
471 let x = state.0;
472 let dx = problem.diff(x);
473 let fx = problem.calc(x);
474
475 let next_x = x - (fx / dx);
476
477 NewtonState(next_x)
478 };
479
480 let term_cond = |state: &NewtonState, problem: &Equation| {
481 let epsilon = 1e-6;
482 problem.calc(state.0) < epsilon
483 };
484
485 let solver = Solver::new(iter_fn, term_cond);
486
487 let solver1 = solver.clone().change_term_cond(|state, equation| {
488 equation.calc(state.0) < 1e-9
489 });
490
491 let prob1 = (Equation::Exp { a: 2., k: 3. }, 2.);
492
493 let cloned_and_change_cond_sol = solver1.solve(prob1.1, &prob1.0.clone());
494
495 let prob2 = (Equation::Square { a: 2., b: -5., c: 3. }, 6.);
496
497 let prob1_sol = solver.solve(prob1.1, &prob1.0);
498 let prob2_sol = solver.solve(prob2.1, &prob2.0);
499
500 println!("the numerical solution of $2e^x - 3 = 0$ is: {}", prob1_sol);
501 println!("with direct calc: {}", (1.5_f64).ln());
502 println!("the numerical solution of $2x^2 - 5x + 3 = 0$ is: {}", prob2_sol);
503 println!("with direct calc: {} or {}", ((5. + 1.)/4.) , (3./4.));
504
505 println!("cloned sol: {}", cloned_and_change_cond_sol);
506
507 assert!(prob1.0.calc(prob1_sol) < 1e-6);
508 assert!(prob2.0.calc(prob2_sol) < 1e-6)
509 }
510
511 #[test]
512 fn solver_iter() {
513 let iter_fn = |state: &NewtonState, problem: &Equation| {
514 let x = state.0;
515 let dx = problem.diff(x);
516 let fx = problem.calc(x);
517
518 let next_x = x - (fx / dx);
519
520 NewtonState(next_x)
521 };
522
523 let term_cond = |state: &NewtonState, problem: &Equation| {
524 let epsilon = 1e-6;
525 problem.calc(state.0).abs() < epsilon
526 };
527
528 let solver = Solver::new(iter_fn, term_cond);
529
530 let prob1 = (Equation::Exp { a: 2., k: 3. }, 2.);
531
532 let prob2 = (Equation::Square { a: 2., b: -5., c: 3. }, 6.);
533
534 {
535 let iter = solver.clone().into_iter(prob1.1, &prob1.0);
536 let mut counter = 0usize;
537
538 for state in iter {
539 counter += 1;
540 if counter == 5 {
541 println!("after 5 times iter, the f(x) = {}", (prob1.0).calc(state.0));
542 break;
543 }
544 }
545 }
546
547 {
550 let iter = solver.into_iter(prob2.1, &prob2.0);
551 let mut counter = 0usize;
552
553 for state in iter {
554 counter += 1;
555 if counter == 5 {
556 println!("after 5 times iter, the f(x) = {}", (prob2.0).calc(state.0));
557 break;
558 }
559 }
560 }
561 }
562 }
563
564
565 mod guard {
566 use std::time::Duration;
567
568 use crate::Solver;
569
570 #[test]
571 fn test() {
572
573 let loop_solver = Solver::new(|_state: &f64, _: &()| {*_state}, |_: &f64, _: &()| {false});
575 let try_solve = loop_solver.solve_with_timeout(0.0, &(), Duration::from_secs(1));
576
577 assert!(try_solve.is_err());
578
579 let try_solve = loop_solver.solve_with_max_iteration(0.0, &(), 10);
580 assert!(try_solve.is_err());
581
582 }
583 }
584
585
586 mod derive_test {
587 use crate::IterState;
588
589 #[derive(PartialEq, Eq , Clone, IterState, Debug)]
590 struct State(Vec<u8>, Box<String>);
591
592 #[test]
593 fn test_derive() {
594 let vec1 = vec![0,12, 39];
595 let boxed_str = Box::new("some str".to_string());
596 let s = State(vec1, boxed_str);
597 let s_cloned = s.clone();
598 assert_eq!(State::init_from_value(s_cloned), s);
599 let final_s = State::init_from_value(s.clone()).to_sol();
600 assert_eq!(final_s, s);
601 }
602 }
603}