| 55 } |
55 } |
| 56 } |
56 } |
| 57 |
57 |
| 58 impl<F: Float, T: GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T {} |
58 impl<F: Float, T: GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T {} |
| 59 |
59 |
| 60 /// A [`RealMapping`] that provides rough bounds as well as minimisation and maximisation. |
60 /// A real-valued [`Mapping`] that provides rough bounds as well as minimisation and maximisation. |
| 61 pub trait MinMaxMapping<Domain: Space, F: Float = f64>: |
61 pub trait MinMaxMapping<Domain: Space, F: Float = f64>: |
| 62 Mapping<Domain, Codomain = F> + Bounded<F> |
62 Mapping<Domain, Codomain = F> + Bounded<F> |
| 63 { |
63 { |
| 64 /// Maximise the mapping within stated value `tolerance`. |
64 /// Maximise the mapping within stated value `tolerance`. |
| 65 /// |
65 /// |
| 70 /// Maximise the mapping within stated value `tolerance` subject to a lower bound. |
70 /// Maximise the mapping within stated value `tolerance` subject to a lower bound. |
| 71 /// |
71 /// |
| 72 /// At most `max_steps` refinement steps are taken. |
72 /// At most `max_steps` refinement steps are taken. |
| 73 /// Returns the approximate maximiser and the corresponding function value when one is found |
73 /// Returns the approximate maximiser and the corresponding function value when one is found |
| 74 /// above the `bound` threshold, otherwise `None`. |
74 /// above the `bound` threshold, otherwise `None`. |
| 75 fn maximise_above(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)>; |
75 fn maximise_above(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)> { |
| |
76 let res @ (_, v) = self.maximise(tolerance, max_steps); |
| |
77 (v > bound).then_some(res) |
| |
78 } |
| 76 |
79 |
| 77 /// Minimise the mapping within stated value `tolerance`. |
80 /// Minimise the mapping within stated value `tolerance`. |
| 78 /// |
81 /// |
| 79 /// At most `max_steps` refinement steps are taken. |
82 /// At most `max_steps` refinement steps are taken. |
| 80 /// Returns the approximate minimiser and the corresponding function value. |
83 /// Returns the approximate minimiser and the corresponding function value. |
| 82 |
85 |
| 83 /// Minimise the mapping within stated value `tolerance` subject to a lower bound. |
86 /// Minimise the mapping within stated value `tolerance` subject to a lower bound. |
| 84 /// |
87 /// |
| 85 /// At most `max_steps` refinement steps are taken. |
88 /// At most `max_steps` refinement steps are taken. |
| 86 /// Returns the approximate minimiser and the corresponding function value when one is found |
89 /// Returns the approximate minimiser and the corresponding function value when one is found |
| 87 /// above the `bound` threshold, otherwise `None`. |
90 /// below the `bound` threshold, otherwise `None`. |
| 88 fn minimise_below(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)>; |
91 fn minimise_below(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)> { |
| |
92 let res @ (_, v) = self.minimise(tolerance, max_steps); |
| |
93 (v < bound).then_some(res) |
| |
94 } |
| 89 |
95 |
| 90 /// Verify that the mapping has a given upper `bound` within indicated `tolerance`. |
96 /// Verify that the mapping has a given upper `bound` within indicated `tolerance`. |
| 91 /// |
97 /// |
| 92 /// At most `max_steps` refinement steps are taken. |
98 /// At most `max_steps` refinement steps are taken. |
| 93 fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool; |
99 fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
| |
100 match self.maximise_above(bound, tolerance, max_steps) { |
| |
101 None => true, |
| |
102 Some((_, v)) => v <= bound, |
| |
103 } |
| |
104 } |
| 94 |
105 |
| 95 /// Verify that the mapping has a given lower `bound` within indicated `tolerance`. |
106 /// Verify that the mapping has a given lower `bound` within indicated `tolerance`. |
| 96 /// |
107 /// |
| 97 /// At most `max_steps` refinement steps are taken. |
108 /// At most `max_steps` refinement steps are taken. |
| 98 fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool; |
109 fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { |
| |
110 match self.minimise_below(bound, tolerance, max_steps) { |
| |
111 None => true, |
| |
112 Some((_, v)) => v >= bound, |
| |
113 } |
| |
114 } |
| 99 } |
115 } |
| 100 |
116 |
| 101 /// Upper and lower bounds on an `F`-valued function. |
117 /// Upper and lower bounds on an `F`-valued function. |
| 102 #[derive(Copy, Clone, Debug)] |
118 #[derive(Copy, Clone, Debug)] |
| 103 pub struct Bounds<F>( |
119 pub struct Bounds<F>( |