我有一个以“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
答案 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 中另一种可能的解决方案是基于 sink 和 tank 节点的初步计算,即分别没有传入/传出边的节点。
使用 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