可视化 link 攻击的最佳方式是什么

What's the best way to visualize link attacks

我有如下图所示的 Networkx 图 (image source)

我执行边缘攻击并观察结果子图节点处值的变化。

例如, 如果我攻击边 (a,2):边 (a, 2) 和 (2, 1) 将被删除。稍微解释一下,当边 (a, 2) 受到攻击时,节点 2 的度数将小于 2。因此连接到节点 2 的边也将被删除。

上述攻击产生了一个子图

每次边被攻击时,观察到的标记为e的终端节点的值随时间变化。假设我执行了 5(attack = 5)次攻击,我有一个 time x attack 矩阵(time=25,attack=5)存储节点 e.

的时间序列数据

我想就如何可视化这些攻击对节点 e 值随时间变化的影响提出建议。 编辑:

What information do you want to be able to see or identify from your visualizations?

我想看看在 e 观察到的时程值对哪条边沿的攻击影响最大。我们可以将其想象成一个交通网络,节点处的值反映了已达到 location/node 的产品数量。从源节点b,货物被运送到目标节点e。所做的观察是边被攻击后节点值的变化,没有观察到边值。

请找出用于攻击边的代码

import networkx as nx
import matplotlib.pyplot as plt


def attack(G):
    print(G.edges())

    for i, edge in enumerate(G.edges()):
        no_attack = [(6, 9), (3, 16)]
        if edge not in no_attack:
            data = {}
            print(f'attacking edge {edge}')

            H = G.copy()

            # attack an edge
            H.remove_edges_from(ebunch=[edge])

            n = len(G.nodes)
            retain_node_ids = [9, 3]
            H.add_edges_from([(u, v) for u in retain_node_ids for v in (n+1, n+2)])

            # remove nodes with degree < 2
            H = nx.k_core(H, k=2)
            H.remove_nodes_from([n + 1, n + 2])
            # graph_utils_py.draw_graph3d(H, fig=2, show=True)

            # H = nx.convert_node_labels_to_integers(H, first_label=1, ordering='default', label_attribute=None)

            # delete connected nodes and edges
            diff_nodes = set(G.nodes()).difference(H.nodes())
            diff_edges = {e for e in G.edges() for n in diff_nodes if n in e}

            print(f"deleting connected nodes {diff_nodes} ...")
            print(f"deleting connected edges {diff_edges} ...")

            data['diff_nodes'] = list(diff_nodes)
            data['diff_edges'] = list(diff_edges)
            data['edge'] = edge


if __name__ == '__main__':
    n = 20
    G = nx.gnm_random_graph(n=20, m=30, seed=1)
    # nx.draw(G, with_labels=True)
    # plt.show()

    retain_node_ids = [11, 4]
    G.add_edges_from([(u, v) for u in retain_node_ids for v in (n, n + 1)])

    G = nx.k_core(G, k=2)
    G.remove_nodes_from([n, n + 1])
    # nx.draw(G, with_labels=True)
    # plt.show()

    G = nx.convert_node_labels_to_integers(G, first_label=1, ordering='default', label_attribute=None)
    nx.draw(G, with_labels=True)
    plt.show()

    attack(G)

编辑2: 下面发布的答案建议通过改变不透明度和设置不同的配色方案来可视化边缘攻击。不幸的是,这没有帮助。必须为每次攻击创建不同的图像。我仍在寻找其他建议。

EDIT3:进一步澄清我想要可视化的内容以保持简单。

我正在寻找如下所示的交互式图表。

可以单击被攻击的边,LHS 图将显示在目标节点处进行的观察。虚线是由于对给定边(存储在变量 edge 中)的攻击而受影响的边(存储在代码中的变量 diff_edges 中)。

如果在攻击 link 后受影响的边缘有重叠,我们可以将其显示为具有相应颜色映射的多条线。交互式图表将帮助用户挑选边缘攻击来比较节点 e 处的观察结果。可以通过改变不透明度/线条样式/颜色来显示被攻击的边缘。

EDIT4:下面发布的答案有帮助。但是当受影响的边缘重叠时会出现问题。

例如, 攻击(H, (6, 4), 颜色='red') 攻击(H, (5, 4), color='yellow')

给予

颜色重叠,很难想象。如果我们可以将受影响的边缘彼此相邻地绘制,而不重叠,如上面在 edit3 中发布的图像所示,那将会很好。

解决方案

在删除节点之前,将箭头添加到指向节点 e 的边上,要删除的节点和边为绿色,然后是红色,然后重复。还可以合并 Alpha 来表示 min-max 距离以及它们如何随着图形的修改而变化。

参考资料

NetworkX 有向图示例:https://networkx.github.io/documentation/stable/auto_examples/drawing/plot_directed.html

NetworkX draw_networkx_edges 个参数(包括箭头、颜色和 alpha):https://networkx.github.io/documentation/stable/reference/generated/networkx.drawing.nx_pylab.draw_networkx_edges.html

Sankey Chart 会有帮助吗?

桑基图是一种可视化,用于描述从一组值到另一组值的流动。下面的代码片段来自 Google 个图表,作为图形流可视化外观的示例。

<html>
<body>
 <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

<div id="sankey_multiple" style="width: 900px; height: 300px;"></div>

<script type="text/javascript">
  google.charts.load("current", {packages:["sankey"]});
  google.charts.setOnLoadCallback(drawChart);
   function drawChart() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'From');
    data.addColumn('string', 'To');
    data.addColumn('number', 'Weight');
    data.addRows([
       [ 'Brazil', 'Portugal', 5 ],
       [ 'Brazil', 'France', 1 ],
       [ 'Brazil', 'Spain', 1 ],
       [ 'Brazil', 'England', 1 ],
       [ 'Canada', 'Portugal', 1 ],
       [ 'Canada', 'France', 5 ],
       [ 'Canada', 'England', 1 ],
       [ 'Mexico', 'Portugal', 1 ],
       [ 'Mexico', 'France', 1 ],
       [ 'Mexico', 'Spain', 5 ],
       [ 'Mexico', 'England', 1 ],
       [ 'USA', 'Portugal', 1 ],
       [ 'USA', 'France', 1 ],
       [ 'USA', 'Spain', 1 ],
       [ 'USA', 'England', 5 ],
       [ 'Portugal', 'Angola', 2 ],
       [ 'Portugal', 'Senegal', 1 ],
       [ 'Portugal', 'Morocco', 1 ],
       [ 'Portugal', 'South Africa', 3 ],
       [ 'France', 'Angola', 1 ],
       [ 'France', 'Senegal', 3 ],
       [ 'France', 'Mali', 3 ],
       [ 'France', 'Morocco', 3 ],
       [ 'France', 'South Africa', 1 ],
       [ 'Spain', 'Senegal', 1 ],
       [ 'Spain', 'Morocco', 3 ],
       [ 'Spain', 'South Africa', 1 ],
       [ 'England', 'Angola', 1 ],
       [ 'England', 'Senegal', 1 ],
       [ 'England', 'Morocco', 2 ],
       [ 'England', 'South Africa', 7 ],
       [ 'South Africa', 'China', 5 ],
       [ 'South Africa', 'India', 1 ],
       [ 'South Africa', 'Japan', 3 ],
       [ 'Angola', 'China', 5 ],
       [ 'Angola', 'India', 1 ],
       [ 'Angola', 'Japan', 3 ],
       [ 'Senegal', 'China', 5 ],
       [ 'Senegal', 'India', 1 ],
       [ 'Senegal', 'Japan', 3 ],
       [ 'Mali', 'China', 5 ],
       [ 'Mali', 'India', 1 ],
       [ 'Mali', 'Japan', 3 ],
       [ 'Morocco', 'China', 5 ],
       [ 'Morocco', 'India', 1 ],
       [ 'Morocco', 'Japan', 3 ]
    ]);

    // Set chart options
    var options = {
      width: 600,
    };

    // Instantiate and draw our chart, passing in some options.
    var chart = new google.visualization.Sankey(document.getElementById('sankey_multiple'));
    chart.draw(data, options);
   }
</script>
</body>
</html>

如果您正在寻找 python 图书馆,请查看 Sankey diagrams in Plotly

你可以先移除被攻击的边,看看它是否使另一个相邻节点退役(受影响的边),然后在找到正确的边后,你用特定于该攻击的颜色绘制它们。这里我用实线画了主攻,用虚线画了受影响的。

import matplotlib.pyplot as plt
import networkx as nx


H = nx.gnm_random_graph(n=8, m=9, seed=5)  # generate a random graph
H.add_edges_from([('In', 1), (5, 'Out')])  # adding input/output nodes
pos = nx.spring_layout(H, iterations=400)  # find good positions for nodes

edges = []
impacted_edges = []


def attack(G, edge, color):
    G.remove_edge(*edge)  # first remove the edge

    # check if another could be also impacted
    if G.degree[edge[0]] == 1:
        neighbor = [n for n in G.neighbors(edge[0])][0]
        impacted_edge = (edge[0], neighbor, color)

    elif G.degree[edge[1]] == 1:
        neighbor = [n for n in G.neighbors(edge[1])][0]
        impacted_edge = (edge[1], neighbor, color)

    else:
        impacted_edge = None

    if impacted_edge:
        impacted_edges.append(impacted_edge)

    edges.append((edge[0], edge[1], color))
    nx.draw_networkx_edges(
        H,
        edgelist=[edge],
        pos=pos,
        edge_color=color,
        style='solid',
        label=f'Attack {edge[0]}-{edge[1]}',
        width=4
    )
    G.add_edge(*edge)

# attack some edges
attack(H, (6, 4), color='red')
attack(H, (3, 6), color='blue')
attack(H, (1, 2), color='green')
attack(H, (5, 4), color='purple')

ax = plt.gca()
for edge in impacted_edges:
    ax.annotate('',
                xy=pos[edge[0]],
                xytext=pos[edge[1]],
                zorder=1,
                arrowprops=dict(
                    color=edge[2],
                    arrowstyle='-',
                    connectionstyle='arc3,rad=0.2',
                    lw=4,
                    linestyle='--'
                )
                )

H.remove_edges_from([(e[0], e[1]) for e in impacted_edges])
H.remove_edges_from([(e[0], e[1]) for e in edges])

nx.draw(H, pos, node_size=700, with_labels=True, node_color='gray', edge_color='gray')

plt.legend()
plt.show()

希望你能在这个答案中找到你想要的。