Thu, 01 May 2025 15:32:10 -0500
MinMaxMapping default implementations
| src/bounds.rs | file | annotate | diff | comparison | revisions |
--- a/src/bounds.rs Thu May 01 14:53:14 2025 -0500 +++ b/src/bounds.rs Thu May 01 15:32:10 2025 -0500 @@ -57,7 +57,7 @@ impl<F: Float, T: GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T {} -/// A [`RealMapping`] that provides rough bounds as well as minimisation and maximisation. +/// A real-valued [`Mapping`] that provides rough bounds as well as minimisation and maximisation. pub trait MinMaxMapping<Domain: Space, F: Float = f64>: Mapping<Domain, Codomain = F> + Bounded<F> { @@ -72,7 +72,10 @@ /// At most `max_steps` refinement steps are taken. /// Returns the approximate maximiser and the corresponding function value when one is found /// above the `bound` threshold, otherwise `None`. - fn maximise_above(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)>; + fn maximise_above(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)> { + let res @ (_, v) = self.maximise(tolerance, max_steps); + (v > bound).then_some(res) + } /// Minimise the mapping within stated value `tolerance`. /// @@ -84,18 +87,31 @@ /// /// At most `max_steps` refinement steps are taken. /// Returns the approximate minimiser and the corresponding function value when one is found - /// above the `bound` threshold, otherwise `None`. - fn minimise_below(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)>; + /// below the `bound` threshold, otherwise `None`. + fn minimise_below(&mut self, bound: F, tolerance: F, max_steps: usize) -> Option<(Domain, F)> { + let res @ (_, v) = self.minimise(tolerance, max_steps); + (v < bound).then_some(res) + } /// Verify that the mapping has a given upper `bound` within indicated `tolerance`. /// /// At most `max_steps` refinement steps are taken. - fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool; + fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { + match self.maximise_above(bound, tolerance, max_steps) { + None => true, + Some((_, v)) => v <= bound, + } + } /// Verify that the mapping has a given lower `bound` within indicated `tolerance`. /// /// At most `max_steps` refinement steps are taken. - fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool; + fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { + match self.minimise_below(bound, tolerance, max_steps) { + None => true, + Some((_, v)) => v >= bound, + } + } } /// Upper and lower bounds on an `F`-valued function.