Source code for assetlife.policies._run_to_failure_policies

"""Run-to-failure maintenance policies."""

from __future__ import annotations

from typing_extensions import override

import numpy as np
import optype.numpy as onp

from ._base import BaseRunToFailurePolicy, OneCycleExpectedCosts
from assetlife.lifetime_models._base import ParametricLifetimeModel
from assetlife.stochastic_processes._renewal_processes import RenewalRewardProcess
from assetlife.typing import CoercibleFloat64_1D, Float64_1D, Timeline


[docs] class OneCycleRunToFailurePolicy(BaseRunToFailurePolicy[ParametricLifetimeModel[()]]): r"""One-cycle run-to-failure policy. Asset is replaced upon failure with cost :math:`c_f`. Only one replacement cycle is considered. Parameters ---------- lifetime_model : ParametricLifetimeModel Lifetime model representing durations between events. """ period_before_discounting: float def __init__( self, lifetime_model: ParametricLifetimeModel[()], period_before_discounting: float = 1.0, ) -> None: super().__init__(lifetime_model) self.period_before_discounting = period_before_discounting @property def _expected_costs(self) -> OneCycleExpectedCosts: return OneCycleExpectedCosts( self.baseline, period_before_discounting=self.period_before_discounting, )
[docs] @override def expected_net_present_value( self, tf: float, nb_steps: int, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> tuple[Timeline, onp.Array1D[np.float64] | onp.Array2D[np.float64]]: return self._expected_costs.expected_net_present_value( tf, nb_steps, a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def expected_equivalent_annual_cost( self, tf: float, nb_steps: int, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> tuple[Timeline, onp.Array1D[np.float64] | onp.Array2D[np.float64]]: return self._expected_costs.expected_equivalent_annual_cost( tf, nb_steps, a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def asymptotic_expected_net_present_value( self, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> Float64_1D: return self._expected_costs.asymptotic_expected_net_present_value( a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def asymptotic_expected_equivalent_annual_cost( self, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> Float64_1D: return self._expected_costs.asymptotic_expected_equivalent_annual_cost( a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] class RunToFailurePolicy(BaseRunToFailurePolicy[ParametricLifetimeModel[()]]): r"""Run-to-failure renewal policy. Asset is replaced upon failure with cost :math:`c_f`. Parameters ---------- lifetime_model : ParametricLifetimeModel Lifetime model representing durations between events. References ---------- .. [1] Van der Weide, J. A. M., & Van Noortwijk, J. M. (2008). Renewal theory with exponential and hyperbolic discounting. Probability in the Engineering and Informational Sciences, 22(1), 53-74. """ @property def _stochastic_reward_process(self) -> RenewalRewardProcess: return RenewalRewardProcess(self.baseline)
[docs] @override def expected_net_present_value( self, tf: float, nb_steps: int, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> tuple[Timeline, onp.Array1D[np.float64] | onp.Array2D[np.float64]]: return self._stochastic_reward_process.expected_total_reward( tf, nb_steps, a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def expected_equivalent_annual_cost( self, tf: float, nb_steps: int, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> tuple[Timeline, onp.Array1D[np.float64] | onp.Array2D[np.float64]]: return self._stochastic_reward_process.expected_equivalent_annual_worth( tf, nb_steps, a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def asymptotic_expected_net_present_value( self, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> Float64_1D: return self._stochastic_reward_process.asymptotic_expected_total_reward( a0=a0, cf=cf, discounting_rate=discounting_rate )
[docs] @override def asymptotic_expected_equivalent_annual_cost( self, *, cf: CoercibleFloat64_1D, a0: CoercibleFloat64_1D | None = None, discounting_rate: float = 0.0, ) -> Float64_1D: return ( self._stochastic_reward_process.asymptotic_expected_equivalent_annual_worth( a0=a0, cf=cf, discounting_rate=discounting_rate ) )