计算有向图中的累积流量

时间:2021-06-14 16:36:03

标签: python r graph networkx igraph

Directed Graph

我有一个以“L”点结束的有向图。当我在“L”点对所有传入的度数求和时,我得到了值:13。但我想根据给定的图修改图形(见图)。在图中,传入的度数将分布在以下节点中。例如,点“F”的传入度数为 2,因此“F”的值为 2。但在点“K”和“G”的情况下,值将是 0.5 和 0.5,因为“的值” H”分为两部分。点“J”的值将是来自上层节点(即 G、E、F)的传入值的总和。

需要 R 或 python 中的解决方案。

这是我使用的示例代码...

library(igraph)
library(dplyr)
g1<- graph (edges = c("A","E", "E","I", "I","L", "E","J", "J","L", 
"B","F", "C","F", "F","J", "D","H", "H","K", "H","G", "G","J", "K","L"), 
directed = T)
cum_deg <- data.frame(name=names(V(g1))) %>%
        mutate(deg_1=degree(g1, mode="in")) %>%
        mutate(cum_degree = rowSums 
        ((!is.infinite(distances(g1,mode="in"))) %*% diag (deg_1)))

        > cum_deg
         name deg_1 cum_degree
         A     0          0
         B     0          0
         C     0          0
         D     0          0
         E     1          1
         F     2          2
         G     1          2
         H     1          1
         I     1          2
         J     3          8
         K     1          2
         L     3         13

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是使用 all_simple_paths 来“拆分”图形,然后使用累积权重聚合路径,例如,

# all source vertices
vs <- V(g1)[degree(g1, mode = "in") == 0]
# all sink vertices
vt <- V(g1)[degree(g1, mode = "out") == 0]
# cumulative weights along each simple path
df <- do.call(
    rbind,
    lapply(
        unlist(sapply(
            vs,
            function(x) all_simple_paths(g1, x, vt)
        ),
        recursive = FALSE
        ),
        function(s) {
            stack(
                replace(
                    cumprod(
                        replace(
                            1 / degree(g1, s, mode = "out"),
                            length(s),
                            1
                        )
                    ),
                    1,
                    0
                )
            )
        }
    )
)
# aggregate weights
out <- rev(stack(xtabs(df)[order(names(V(g1)))]))

给予

> out
   ind values
1    A    0.0
2    B    0.0
3    C    0.0
4    D    0.0
5    E    1.0
6    F    2.0
7    G    0.5
8    H    1.0
9    I    0.5
10   J    3.0
11   K    0.5
12   L    4.0

答案 1 :(得分:1)

Python 中另一种可能的解决方案是基于 sinktank 节点的初步计算,即分别没有传入/传出边的节点。

使用 igraph,您可以在图 g 上进行操作:

sink=g.vs.select(_indegree=0)["name"]
tank=g.vs.select(_outdegree=0)["name"]

然后初始化一个变量 ready_nodes,它将包含在每次迭代中计算出的流的节点,并将其初始化为每个汇节点的 flow=1:

ready_nodes = {sink[i]: 1 for i in range(0, len(sink))}

您可以递归调用以下函数:

def get_score(node_name:str, ready_nodes:list):
    if node_name in ready_nodes:
        return ready_nodes[node_name]
    else:
        curr_node = g.vs.find(node_name)
                
        # get neighbor nodes
        neighbors_idx = g.neighbors(curr_node, mode="in")
        neighbors_names = g.vs[neighbors_idx]["name"]
        display(f"The neighbors of {node_name} are {neighbors_names}")

        this_node_score = 0
        for j in range(0, len(neighbors_names)):
            this_node_score += get_score(neighbors_names[j], ready_nodes)

        # divide the score by the number of outgoing edges if this node is not a tank node
        if curr_node.outdegree() > 0:
            this_node_score /= curr_node.outdegree()

        display(f'The outgoing flow from node {curr_node["name"]} is: {this_node_score}')
        ready_nodes[node_name] = this_node_score
        return this_node_score

从此for循环:

for i in range(0, len(tank)):
    t_name = tank[i]
    
    display(f"The flow to {t_name} is {get_score(t_name, ready_nodes)}")

把事情做好。

The neighbors of L are ['I', 'J', 'K']
The neighbors of I are ['E']
The neighbors of E are ['A']
The outgoing flow from node E is: 0.5
The outgoing flow from node I is: 0.5
The neighbors of J are ['E', 'F', 'G']
The neighbors of F are ['B', 'C']
The outgoing flow from node F is: 2.0
The neighbors of G are ['H']
The neighbors of H are ['D']
The outgoing flow from node H is: 0.5
The outgoing flow from node G is: 0.5
The outgoing flow from node J is: 3.0
The neighbors of K are ['H']
The outgoing flow from node K is: 0.5
The outgoing flow from node L is: 4.0
The flow to L is 4.0

您可以在此协作实验室中浏览解决方案 sheet

相关问题