Контекст: У меня немного странная проблема: давайте рассмотрим 2 кортежа, один из которых является подмножеством другого размера N-1.
node = (40, 50, 60, 80)
adj_node = (40, 50, 60)
КакВы можете видеть, я называю эти комбинации как узлы сетевого графа.Префикс adj_
означает adjacent
.Алгоритм раскрашивает график, то есть находит альтернативное значение для каждого узла.Суффикс alt_
будет означать alternative
.
И для node
, и для adj_node
предусмотрена 1 альтернатива в пределах допустимого диапазона.Цель этой функции - вычислить отклонение между обеими альтернативами.
def compute_deviation_between_node_alternative_and_adj_node_alternative(node,
node_alt, adj_node, adj_node_alt):
"""
4 tuples in input, the node, the node alternative, the adjacent node, and
the adjacent node alternatives.
"""
# Compute
return deviation
Рассмотрим следующий вход:
node = (40, 50, 60, 80)
node_alt = (39, 48, 59, 87)
adj_node = (40, 50, 60)
adj_node_alt = (42, 55, 59)
Каждое значение из узла или из adj_node заменяется наальтернативное значение в пределах диапазона допуска +/- 10%.Таким образом, 40
становится 39
в альтернативном узле и 42
в соседнем альтернативном узле.Альтернативы не могут быть заказаны.то есть node_alt
могло бы быть (48, 39, 87, 59)
.Диапазон допуска может перекрываться, например, для 60
, оба значения 55
и 59
находятся в пределах диапазона допуска.
Проблемная часть кода: Шаг, который я пытаюсь выполнитьреализовать - это то, что я назвал этапом идентификации: выяснить, какое альтернативное значение соответствует какому входному значению.Для этого я вычисляю расстояние между значениями и возвращаю id (или idx), на котором находится альтернативное значение.
tolerances = [0.1 if x <= 100 else 0.2 for x in node]
distance = dict()
alt_identification = dict()
for k, x in enumerate(node):
distance[k] = [abs(elt-1) for elt in [alt_x/x for alt_x in node_alt]]
alt_identification[x] = list(np.where([elt <= tolerances[k]+0.00001 for elt in distance[k]])[0])
В приведенном выше примере выводом является:
alt_identification
Out[67]: {40: [0], 50: [1], 60: [2], 80: [3]}
То же самое делается для альтернативы смежного узла.
distance = dict()
adj_alt_identification = dict()
for k, x in enumerate(node):
distance[k] = [abs(elt-1) for elt in [alt_x/x for alt_x in adj_node_alt]]
adj_alt_identification[x] = list(np.where([elt <= tolerances[k]+0.00001 for elt in distance[k]])[0])
Вывод:
adj_alt_identification
Out[66]: {40: [0], 50: [1], 60: [1, 2], 80: []}
Проблема: У меня есть разные сценарии, которые могут возникнуть.
Сценарий 1: каждому значению присвоено одно альтернативное значение.Например, это относится к node
, где вывод равен {40: [0], 50: [1], 60: [2], 80: [3]}
.
Сценарий 2: Некоторые из входных значений идентифицируются как 2 или более различных возможных альтернативных значений.Это может произойти из-за перекрытия диапазона допуска.Например,
adj_node = (40, 50, 60)
adj_node_alt = (42, 55, 54)
Оба 55
и 54
включены в диапазон допуска от 50
и 60
.Вывод будет (если узел (40, 50, 60, 80)
):
adj_alt_identification Out [66]: {40: [0], 50: [1, 2], 60: [1, 2], 80: []}
Сценарий 3: Это имеет место в предыдущем примере для adj_alt
:
adj_node = (40, 50, 60)
adj_node_alt = (42, 55, 59)
55
и 59
включены в диапазон допуска 60
.Только 55
входит в диапазон допуска 50
.
Токовый выход:
adj_alt_identification
Out[66]: {40: [0], 50: [1], 60: [1, 2], 80: []}
Корректный выход будет означать, что 60
не может принять значение55
, поскольку оно уже занято 50
.Таким образом, выходные данные должны быть:
adj_alt_identification
Out[66]: {40: [0], 50: [1], 60: [2], 80: []}
Если у кого-то есть идеи о том, как улучшить этот код и как получить правильный вывод в каждом сценарии, я бы с удовольствием услышал об этом :) Я чувствуюкак мой процесс идентификации является неуклюжим и неэффективным ...