Вы можете присвоить ранг каждому узлу (при условии, что у вас есть график, для которого это имеет смысл ) ...
vdf = data.table(p = sort(unique(unlist(df[, c("p1", "p2")]))))
i = 0L
vdf[, r := 0L]
while (any(vdf[r == i, p] %in% df$p1)){
vdf[r == i, r := r + !df[.(p), on=.(p1), p %in% setdiff(p1, p2)]]
i = i + 1L
}
p r
1: x0 0
2: x1 1
3: x2 1
4: x3 2
5: x4 3
Если есть уникальное первое событие, x0
, тогда благодаря @Roland вот более простой способ:
library(igraph)
vdf[, r := as.vector(distances(graph_from_data_frame(df), "x0"))]
Затем для каждого ранга, имеющего более одного узла, возьмите все перестановки (здесь, заимствуя из Генерация всех различных перестановоксписок в R ) ...
wdf = vdf[, do.call(cbind, lapply(split(.I, r), function(x) as.data.table(
gtools::permutations(length(x), length(x), x)
)))]
0.V1 1.V1 1.V2 2.V1 3.V1
1: 1 2 3 4 5
2: 1 3 2 4 5
Значения в wdf
являются номерами строк (см. ?.I
) из vdf
, поэтому ...
mdf = melt(wdf[, g := .I], id = "g", value.name = "w")[order(g, variable)]
vdf[mdf$w, .(p, g = mdf$g, r)][, seq := rowid(g)][]
p g r seq
1: x0 1 0 1
2: x1 1 1 2
3: x2 1 1 3
4: x3 1 2 4
5: x4 1 3 5
6: x0 2 0 1
7: x2 2 1 2
8: x1 2 1 3
9: x3 2 2 4
10: x4 2 3 5
Итак, g
- это «группа», упомянутая в ОП;r
- ранг;seq
- это последовательность внутри группы (полезна для явной сортировки таблицы).
Комментарий. Я бы остановился после присвоения атрибута rank / глубиныкаждый узел в vdf
.Вся информация о возможных последовательностях событий находится здесь, но перечисление их (как в выходных данных OP) может быть очень дорогостоящим, с точки зрения вычислительного времени и пространства, и поэтому его следует по возможности избегать.
Число перестановок для событий x
с одинаковым рангом равно factorial(length(x))
, поэтому, например, если x
имеет длину 10, возвращаемая матрица имеет размеры dim(gtools::permutations(10, 10))
= 3628800 x 10. Мой компьютер зависает при попытке вычислить его.