argmin/core/
termination.rs

1// Copyright 2018-2020 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! # Termination
9//!
10//! Defines reasons for termination.
11//!
12//! TODO:
13//!   * Maybe it is better to define a trait (with `terminated` and `text` methods), because it
14//!     would allow implementers of solvers to define their own `TerminationReason`s. However, this
15//!     would require a lot of work.
16
17use serde::{Deserialize, Serialize};
18
19/// Indicates why the optimization algorithm stopped
20#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
21pub enum TerminationReason {
22    /// In case it has not terminated yet
23    NotTerminated,
24    /// Maximum number of iterations reached
25    MaxItersReached,
26    /// Target cost function value reached
27    TargetCostReached,
28    /// Target precision reached
29    TargetPrecisionReached,
30    /// Cost function value did not change
31    NoChangeInCost,
32    /// Acceped stall iter exceeded
33    AcceptedStallIterExceeded,
34    /// Best stall iter exceeded
35    BestStallIterExceeded,
36    /// Condition for Line search met
37    LineSearchConditionMet,
38    /// Target tolerance reached
39    TargetToleranceReached,
40    /// Aborted
41    Aborted,
42}
43
44impl TerminationReason {
45    /// Returns `true` if a solver terminated and `false` otherwise
46    pub fn terminated(self) -> bool {
47        match self {
48            TerminationReason::NotTerminated => false,
49            _ => true,
50        }
51    }
52
53    /// Returns a texual representation of what happened
54    pub fn text(&self) -> &str {
55        match *self {
56            TerminationReason::NotTerminated => "Not terminated",
57            TerminationReason::MaxItersReached => "Maximum number of iterations reached",
58            TerminationReason::TargetCostReached => "Target cost value reached",
59            TerminationReason::TargetPrecisionReached => "Target precision reached",
60            TerminationReason::NoChangeInCost => "No change in cost function value",
61            TerminationReason::AcceptedStallIterExceeded => "Accepted stall iterations exceeded",
62            TerminationReason::BestStallIterExceeded => "Best stall iterations exceeded",
63            TerminationReason::LineSearchConditionMet => "Line search condition met",
64            TerminationReason::TargetToleranceReached => "Target tolerance reached",
65            TerminationReason::Aborted => "Optimization aborted",
66        }
67    }
68}
69
70impl std::fmt::Display for TerminationReason {
71    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72        write!(f, "{}", self.text())
73    }
74}
75
76impl Default for TerminationReason {
77    fn default() -> Self {
78        TerminationReason::NotTerminated
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    send_sync_test!(termination_reason, TerminationReason);
87}