识别哪个近旁号码对应于哪个输入

时间:2019-04-01 09:30:08

标签: python list identification

上下文:我有一个奇怪的问题:让我们考虑2个元组,其中一个是另一个大小为N-1的子集。

node = (40, 50, 60, 80)
adj_node = (40, 50, 60)

如您所见,我将这些组合称为网络图中的节点。前缀adj_代表adjacent。该算法正在为图形着色,即它为每个节点找到一个替代值。后缀alt_代表alternative

在容差范围内,nodeadj_node都提供了一种替代方法。此函数的目的是计算两个替代方案之间的偏差。

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,在相邻的node_alternative中变为42。 替代品可能未订购。即node_alt可能是(48, 39, 87, 59)。 公差带可以重叠,例如。对于605559都在公差带内。

该代码的问题部分:我试图实现的步骤是我所说的识别步骤:找出哪个替代值对应于哪个输入值。为此,我计算了两个值之间的距离,并返回替代值所在的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)

5554的公差带中都包含5060。 输出为(如果节点为(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)

5559包含在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: []}

如果有人对如何改进此代码以及如何在每种情况下获得正确的输出有任何想法,我将很高兴听到它:)我觉得我的识别过程笨拙且效率低下... >

1 个答案:

答案 0 :(得分:0)

当前代码可产生正确的输出:这是一团糟,效率低下...

def traceback(tuple_node, tuple_node_alt):
    """
    Compute which value from tuple_node_alt comes from which value from tuple_node.
    tuple_node is the input
    tuple_node_alt is the "output"
    """
    # Compute the tolerances based on the node
    tolerances = [0.1 if f <= 100 else 0.2 for f in tuple_node]

    # Traceback
    distance = dict()
    alt_identification = dict()
    for k, x in enumerate(tuple_node):
        distance[k] = [abs(elt-1) for elt in [alt_x/x for alt_x in tuple_node_alt]]
        alt_identification[x] = list(np.where([elt <= tolerances[k]+0.00001 for elt in distance[k]])[0])

    len_values = {key: len(val) for key, val in alt_identification.items()}

    if all([x <= 1 for x in len_values.values()]):
        return alt_identification
    else:
        for key, value in alt_identification.items():
            if len(value) <= 1:
                continue
            else:
                other_values = [val for k, val in alt_identification.items() if k != key]
                if value in other_values:
                   continue
                else:
                    for val in other_values:
                        set1 = set(value)
                        intersec = set1.intersection(set(val))
                        if len(intersec) == 0:
                            continue
                        else:
                            alt_identification[key] = [v for v in value if v not in intersec]

    return alt_identification