#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#Copyright (C) 2013 Chabot Simon, Sadaoui Akim
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License along
#with this program; if not, write to the Free Software Foundation, Inc.,
#51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
r""" Voter design
This modude gives tools to design voters and compute some metrics, such as the
reliability, the availability, the Mean-Time-To-Failure, and so on.
"""
from sympy import exp, Symbol, oo
from scipy.special import binom
from itertools import combinations, chain
from fiabilipy.component import Component
__all__ = ['Voter']
ALLSUBSETS = lambda n: (chain(*[combinations(range(n), ni)
for ni in xrange(n+1)]))
[docs]class Voter(Component):
r""" A voter with identical components having a constant failure rate
This class is used to describe a voter. A voter M out-of N works if
and only if *at least* M components out of the N avaible work.
Attributes
----------
component: `Component`
the component to be replicated by the voter
N: int
the initial number of components
M: int
the minimal number of working components
lambda_ : float
the constant failure rate of the voter
mu : float, optional
the constant maintainability rate of the voter
initialy_avaible: boolean, optional
whether the component is avaible at t=0 or not
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3)
>>> voter.mttf
8333.33333333333
"""
def __init__(self, component, M, N, lambda_=0, mu=0, initialy_avaible=True):
name = '{} out-of {} − {}'.format(M, N, component.name)
super(Voter, self).__init__(name=name, lambda_=lambda_, mu=mu,
initialy_avaible=initialy_avaible)
self.component = component
self.M = M
self.N = N
def __repr__(self):
return u'Voter(%s out-of %s)' % (self.M, self.N)
def _probabilitiescomputation(self, t, method):
""" Compute the `method` (reliability, availability, maintainability) of
a voter, given its components, and the initial number of components
and the minimal number of components.
"""
prob = 0
for k in xrange(self.M, self.N+1):
a = getattr(self.component, method)(t)**k
b = (1 - getattr(self.component, method)(t))**(self.N-k)
prob += binom(self.N, k) * a * b
return prob
[docs] def reliability(self, t):
r""" Compute the reliability of the voter at `t`
This method compute the reliability of the voter at `t`.
Parameters
----------
t : float or Symbol
Returns
-------
out : float or symbolic expression
The reliability calculated for the given `t`
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3)
>>> t = Symbol('t', positive=True)
>>> voter.reliability(t)
3.0*(-exp(-0.0001*t) + 1)*exp(-0.0002*t) + 1.0*exp(-0.0003*t)
>>> voter.reliability(1000)
0.974555817870510
"""
ownrel = super(Voter, self).reliability(t)
return ownrel * self._probabilitiescomputation(t, 'reliability')
[docs] def maintainability(self, t):
r""" Compute the maintainability of the voter at `t`
This method compute the maintainability of the voter at `t`.
Parameters
----------
t : float or Symbol
Returns
-------
out : float or symbolic expression
The maintainability calculated for the given `t`
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3, mu=1e-3)
>>> t = Symbol('t', positive=True)
>>> voter.maintainability(t) #doctest: +NORMALIZE_WHITESPACE
(1.0*(-exp(-0.03*t) + 1.0)**3 + 3.0*(-exp(-0.03*t)
+ 1.0)**2*exp(-0.03*t))*(-exp(-0.001*t) + 1.0)
>>> voter.maintainability(1000)
0.632120558828558
"""
ownrel = super(Voter, self).maintainability(t)
return ownrel * self._probabilitiescomputation(t, 'maintainability')
[docs] def availability(self, t):
r""" Compute the availability of the voter at `t`
This method compute the availability of the voter at `t`.
Parameters
----------
t : float or Symbol
Returns
-------
out : float or symbolic expression
The availability calculated for the given `t`
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3, mu=1e-3)
>>> t = Symbol('t', positive=True)
>>> voter.availability(t) #doctest: +NORMALIZE_WHITESPACE
3.0*(-0.00332225913621263*exp(-0.0301*t) +
0.00332225913621265)*(0.00332225913621263*exp(-0.0301*t) +
0.996677740863787)**2 + 1.0*(0.00332225913621263*exp(-0.0301*t) +
0.996677740863787)**3
>>> voter.availability(1000)
0.999966961120940
"""
ownavail = super(Voter, self).availability(t)
return ownavail * self._probabilitiescomputation(t, 'availability')
@property
def mttf(self):
r""" Compute the Mean-Time-To-Failure of the voter
The MTTF is defined as :
:math:`MTTF = \int_{0}^{\infty} R(t)dt`
Returns
-------
out : float
The component MTTF
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3)
>>> voter.mttf
8333.33333333333
"""
t = Symbol('t', positive=True)
return self.reliability(t).integrate((t, 0, oo))
@property
def mttr(self):
r""" Compute the Mean-Time-To-Repair of the voter
The MTTR is defined as :
:math:`MTTR = \int_{0}^{\infty} 1 - M(t)dt`
Returns
-------
out : float
The component MTTR
Examples
--------
>>> motor = Component('M', 1e-4, 3e-2)
>>> voter = Voter(motor, 2, 3, mu=1e-3)
>>> voter.mttr
1000.57547188695
"""
t = Symbol('t', positive=True)
return (1 - self.maintainability(t)).integrate((t, 0, oo))