///|
/// Failure-mode-and-effects-analysis item.
pub struct RiskItem {
name : String
severity : Int
occurrence : Int
detection : Int
risk_priority_number : Int
recommended_action : String
}
///|
pub fn risk_item(
name~ : String,
severity~ : Int,
occurrence~ : Int,
detection~ : Int,
recommended_action~ : String,
) -> RiskItem {
if severity < 1 ||
severity > 10 ||
occurrence < 1 ||
occurrence > 10 ||
detection < 1 ||
detection > 10 {
abort("FMEA scores must be in 1..10")
}
{
name,
severity,
occurrence,
detection,
risk_priority_number: severity * occurrence * detection,
recommended_action,
}
}
///|
pub fn rank_risks(items : Array[RiskItem]) -> Array[RiskItem] {
let result = items.copy()
result.sort_by((left, right) => {
if left.risk_priority_number > right.risk_priority_number {
-1
} else if left.risk_priority_number < right.risk_priority_number {
1
} else {
0
}
})
result
}
///|
pub fn risk_matrix_score(
severity : Int,
occurrence : Int,
detection : Int,
) -> Int {
severity * occurrence * detection
}
///|
pub fn risk_level(priority_number : Int) -> String {
if priority_number >= 300 {
"high"
} else if priority_number >= 100 {
"medium"
} else {
"low"
}
}
///|
pub struct FaultTreeResult {
top_event_probability : Double
minimal_cut_sets : Array[Array[Int]]
dominant_component : Int?
}
///|
pub fn fault_tree_result(
top_event_probability~ : Double,
minimal_cut_sets~ : Array[Array[Int]],
dominant_component~ : Int?,
) -> FaultTreeResult {
{ top_event_probability, minimal_cut_sets, dominant_component }
}
///|
pub fn fault_tree_or(events : Array[Double]) -> FaultTreeResult {
let probability = parallel_reliability(events.map(value => 1.0 - value))
let cuts = Array::makei(events.length(), i => [i])
let mut dominant = 0
for i in 1.. events[dominant] {
dominant = i
}
}
fault_tree_result(
top_event_probability=probability,
minimal_cut_sets=cuts,
dominant_component=Some(dominant),
)
}
///|
pub fn fault_tree_and(events : Array[Double]) -> FaultTreeResult {
let probability = series_reliability(events)
let cut : Array[Int] = []
for i in 0.. Double {
let mut result = 1.0
for index in cut {
result *= component_failure_probabilities[index]
}
result
}
///|
pub fn risk_reduction(original : RiskItem, improved_detection : Int) -> Double {
let new_detection = improved_detection.max(1).min(10)
1.0 -
(original.severity * original.occurrence * new_detection).to_double() /
original.risk_priority_number.to_double()
}
///|
pub fn safety_integrity_level(pfd : Double) -> String {
if pfd <= 1.0e-5 {
"SIL4"
} else if pfd <= 1.0e-4 {
"SIL3"
} else if pfd <= 1.0e-3 {
"SIL2"
} else if pfd <= 1.0e-2 {
"SIL1"
} else {
"below-SIL"
}
}