如何在给定条件下订购一组变量。
如果给我:
A < B, B < C, and C < A. This is impossible.
A < B, C < B, and A < C. The order, from least to greatest, is A, C, B.
我更喜欢R,如果我可以给出c("A<B", "C<B", "A<C")
这样的方法字符串,那么该方法会返回c("A","C", "B")
鉴于任何数量的变量,我如何根据这些条件将它们从最小到最高排名?如果情况不可能,请在代码中加入中断。谢谢。
答案 0 :(得分:1)
这适用于您的示例( - 但未检查边缘情况),它使用dag&#39; s(有向非循环图)具有自然顺序的想法。您的示例就是这种情况。语句中的一个不可能的场景会导致图中出现一个循环,因此我们可以使用它来抛出错误。
如果您的所有陈述都是严格的
,则此方法有效library(igraph)
f <- function(X) {
d <- do.call("rbind", strsplit(X , "<"))
g <- graph.data.frame(d)
if(is.dag(g))
V(g)$name[topological.sort(g)]
else
stop("Graph has cycles")
}
f(c("A<B", "C<B", "A<C"))
f(c("C<B", "A<C", "A<B"))
f(c("A<B", "B<C", "C<A"))
关于代码:
# this splits the string into two columns
# interpreted as from -> to by graph
do.call("rbind", strsplit(X , "<"))
# generate graph from edges (d)
g <- graph.data.frame(d)
is.dag(g) # checks if the graph is acyclic
# if there are no cycles return the vertice names in topological order
V(g)$name[topological.sort(g)]
修改强>
包括顶点等效的情况限制了上述的使用。但我们仍然可以使用图形方法(虽然它不那么自然而不是 R方式) - 通过描述具有双向边的相等顶点。如果完全指定了模型/语句(它应该是),我们有一个完整的图形,我们可以使用这样的事实:如果两个顶点相等,它们应该具有比它们更大的相同顶点集,并且相同的顶点比它们小 - 否则抛出错误。
因此,我们使用parents
和children
的概念,并在等效顶点(A&lt; B&lt; =&gt;父&lt; child)之间进行比较。
该函数的第一部分是针对语句严格小于或大于的情况。第二部分比较了具有等价语句的节点的父节点和子节点。
f <- function(X) {
l <- do.call("rbind", strsplit(X[grepl("<", X)] , "<"))
if(!any(grepl("==", X))) {
g <- graph.data.frame(l)
if(is.dag(g))
V(g)$name[topological.sort(g)]
else
stop("Impossible")
}
else {
e <- do.call("rbind", strsplit(X[grepl("==", X)] , "=="))
g <- graph.data.frame(rbind(l, e, e[,2:1]))
par <- function(g)
setNames(lapply(neighborhood(g, 1, mode="in"),
function(i) sort(V(g)$name[i])), V(g)$name)
ch <- function(g)
setNames(lapply(neighborhood(g, 1, mode="out"),
function(i) sort(V(g)$name[i])), V(g)$name)
pareq <- apply(e, 1,
function(i)
identical(par(g)[[i[1]]], par(g)[[i[2]]]))
cheq <- apply(e, 1,
function(i)
identical(ch(g)[[i[1]]], ch(g)[[i[2]]]))
if(all(pareq & cheq)) {
g <- graph.data.frame(rbind(l,e))
V(g)$name[topological.sort(g)]
}
else
stop("Impossible")
}
}
几个例子
f(X = c("C<B", "A<C", "A<B"))
f(X = c("C==B", "C==A", "A<B"))
f(X = c("C==B", "C<A", "A<B"))
f(X = c("B==C", "C<A", "B<A"))
我没有检查过所有边缘情况或更大的图表,但它应该给你一个想法让你开始(如果你想这样做)
答案 1 :(得分:1)
这是另一种为元素定义自定义顺序运算符然后调用内置方法sort
的方法。
rules <- c("A<B", "C<B", "A<C")
vec <- c("A", "B", "C", "A")
class(vec) <- 'letters'
`[.letters` <- function(x, i) {
x <- unclass(x)
e <- x[i]
class(e) <- 'letters'
e
}
`==.letters` <- function(x, y) unclass(x) == unclass(y)
`>.letters` <- function(x, y) paste(y, x, sep='<') %in% rules
sort(vec)
# [1] "A" "A" "C" "B"
此策略由this answer建议,但我在这里使用的方法更简单。