Ранжирование переменных, порядок

1

Как заказать набор переменных с заданными условиями.

Если мне дадут:

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")

Учитывая любое количество переменных, как я могу ранжировать их от наименьшего до наибольшего, исходя из этих условий? Пожалуйста, включите разрыв кода, если сценарий невозможен. Спасибо.

  • 2
    О, если вы собираетесь отказаться от голосования, пожалуйста, скажите, пожалуйста, почему, чтобы я мог отредактировать свой вопрос так, чтобы он соответствовал SO стандартам. Просто голосование вниз не поможет мне, кому-либо еще, или этому сайту в целом.
  • 1
    Это вопрос Java или R? (Я не голосовал против)
Показать ещё 5 комментариев
Теги:
graph

2 ответа

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"

Эта стратегия была предложена этим ответом, но метод, который я здесь использую, проще.

  • 0
    Кажется, что это работает, но не определяет, когда это невозможно.
1

Это работает для вашего примера (но не проверяется для случая кромки). В нем используется идея, что dag (направленные ациклические графики) имеют естественный порядок. Это относится к вашему примеру. Невозможный сценарий в операторах приведет к циклу в графе, поэтому мы можем использовать его для выброса ошибки.

Это работает, если все ваши заявления строги

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 <B <=> parent <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"))

Я не проверял это для всех случаев краев или больших графиков, но он должен дать представление о том, чтобы вы начали (если вы хотите идти этим путем)

  • 0
    Ух ты какое решение! Я еще не понимаю все методы (я прочитаю некоторую документацию!), Но наличие такого уникального пакета и то, что вы связали мой вопрос с этой функцией, весьма примечательно. Отличный ответ. Я чувствую, что мой вопрос довольно элементарен, но если подумать, он может быть более сложным, чем кажется на первый взгляд.
  • 0
    Ой, подождите, только один вопрос. Что если у меня есть значения, которые равны, это все еще будет работать? @ user20650
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню