Components Wear
mlumina.components_wear
Симуляция износа и отказов графа взаимозависимых компонентов (по докстрингам и примерам — модель ориентирована на автомобильные узлы, но структура графа предметно-независима). Два класса: ComponentsGraph (описание графа и симуляции для многих объектов) и ComponentsObject (один конкретный экземпляр системы и его текущий износ).
⚠️ Известный баг:
ComponentsObject.update_wear()иComponentsObject.predict_fix()не работают — см. известные проблемы ниже.get_probabilities(), а также все методыComponentsGraph(simulate_objects*) — рабочие.
Граф компонентов
Граф описывается словарём: узлы (nodes) — группы взаимозаменяемых компонентов, каждый со своей функцией вероятности отказа; рёбра (edges) — зависимость износа одного узла от состояния другого.
{
"A": {
"edges": { "B": { "bend": 0.4, "koef": 2.3 } },
"nodes": {
"A1": {"func": "weibull_failure_prob", "a": 1.0, "maximum": 100000},
"A2": {"func": "weibull_failure_prob", "a": 1.5, "maximum": 100000}
}
},
"B": {
"edges": {},
"nodes": {
"B1": {"func": "weibull_failure_prob", "a": 1.0, "maximum": 100000}
}
}
}
"func"— ключ вmlumina.components_wear.functions.utils_functions_mapping(сейчас единственная зарегистрированная функция —"weibull_failure_prob", вычисляет CDF распределения Вейбулла по параметрамa(форма) иmaximum(износ, при котором вероятность отказа ≈ 0.999)).edges[parent]={"bend": ..., "koef": ...}— до достижения родителем износаbend * maximumдочерний узел изнашивается с обычной скоростью (коэффициент 1); после достижения родителем своегоmaximum— со скоростьюkoef; между этими точками — линейная интерполяция.
import json
from mlumina.components_wear import ComponentsGraph
with open("examples/components_wear/data/graph.json", encoding="utf-8") as f:
graph_dict = json.load(f)
graph = ComponentsGraph(graph_dict)
Симуляция парка объектов
df = graph.simulate_objects(n_objects=100, total_wearout=100_000, step=1000, seed=42, fix_coeff=1.0)
Для каждого из n_objects объектов случайно выбирается по одному компоненту из каждого узла (начальный износ — усечённое экспоненциальное распределение), затем пошагово (step) наращивается износ с учётом зависимостей, на каждом шаге проверяется отказ (по вероятности из func) и «тихий» ремонт (та же вероятность, умноженная на fix_coeff). Возвращает pandas.DataFrame с колонками failed_node, wear, all_parts — по одной строке на каждый зафиксированный отказ.
simulate_objects_ray(...) — та же логика, но каждый объект симулируется в отдельной Ray-задаче (@ray.remote). Требует ray.init() заранее, иначе RuntimeError.
simulate_objects_bn(...) — экспериментальный вариант: вероятность отказа считается как 0.6 * P_weibull + 0.4 * P_bn, где P_bn — упрощённая байесовская оценка на основе дискретизации износа в 5 бинов (b0…b4) для узла и его непосредственного родителя. Возвращает те же колонки плюс prob_weibull, prob_bn, prob_combined.
create_random_object() -> ComponentsObject — генерирует один случайный объект (без симуляции износа во времени).
Объект системы (ComponentsObject)
from mlumina.components_wear import ComponentsObject
obj = ComponentsObject([["A1", 0], ["B1", 0]]) # [[имя_компонента, начальный_износ], ...]
probs = obj.get_probabilities(graph) # {component_name: вероятность_отказа_в_%}
get_probabilities(graph) — рабочий метод: по каждому компоненту находит его функцию отказа в графе и считает вероятность (в процентах) от текущего износа.
Известная поломка update_wear и predict_fix
ComponentsObject.update_wear(graph, step=1000) (src/mlumina/components_wear/components_object.py:163) и ComponentsObject.predict_fix(...) (там же, строка 272) вызывают self._get_wear_dict(). В классе определён метод _get__dict() (строка 74, с двойным подчёркиванием — похоже на опечатку), а не _get_wear_dict(). Метода _get_wear_dict в классе нет — оба вызова гарантированно падают с AttributeError: 'ComponentsObject' object has no attribute '_get_wear_dict'.
Это воспроизводится и в штатном примере examples/components_wear/example.py:33 (component_object.update_wear(graph, 10000)), т.е. пример из репозитория в текущем виде не отрабатывает до конца.
Если нужно пользоваться этими методами — до исправления в коде их можно обойти монки-патчем:
from mlumina.components_wear.components_object import ComponentsObject
ComponentsObject._get_wear_dict = ComponentsObject._get__dict
Функции отказа (functions.py)
from mlumina.components_wear.functions import weibull, utils_functions_mapping
weibull(wear, a, maximum) -> float — CDF Вейбулла, масштаб подобран так, что weibull(maximum, a, maximum) ≈ 0.999. utils_functions_mapping = {"weibull_failure_prob": weibull} — реестр функций, на который ссылаются графы по строковому ключу "func". Чтобы добавить свою функцию отказа, нужно дополнить этот словарь (единой точки регистрации "снаружи" пакета сейчас нет — граф всегда резолвит "func" через этот фиксированный маппинг).
No comments to display
No comments to display