R: Генерация всех перестановок N весов в кратных P - PullRequest
3 голосов
/ 31 июля 2011

Мне нужно создать функцию (в R), которая:
- дано N возможных переменных для присвоения весов;
- создает все возможные перестановки весов (суммирование до 100%);
- при условии ограничения, что весовые коэффициенты должны быть кратны P (обычно 1%)

Очевидно, что N и P имеют обратную связь, т. Е. Я не могу указать N = 7 и P = 0,4. Однако я хотел бы иметь возможность указывать только целочисленные решения, т.е. P = 0,01.

Извините, если это хорошо известная проблема - я не математик, и я искал, используя известные мне термины, но не нашел ничего достаточно близкого.

Я бы опубликовал код, который я написал, но ... он не впечатляет и не проницателен.

Спасибо за любую помощь!

Ответы [ 2 ]

5 голосов
/ 01 августа 2011

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

Так как вы хотите, чтобы веса добавляли до 1, вам нужно, чтобы 1 / p было целым числом, которое в следующем коде равно sumparts; это не зависит от количества весов. Как только у вас есть композиции, вы можете умножить их на p, то есть разделить на n, чтобы получить ваши веса.

R имеет пакет partitions для создания таких композиций или ограниченных разделов. Следующий код должен быть понятен: каждый столбец в матрице представляет собой набор весов. Я взял семь весов и р = 0,1 или 10%, и запретил веса 0: это дает 84 возможности; допустимые веса 0 означают 8008 возможностей. При p = 0,01 или 1% было бы 1,120,529,256 возможностей без весов 0 и 1,705,904,746 с. Если порядок не имеет значения, используйте restrictedparts вместо compositions.

> library(partitions)
> numparts <- 7  # number of weights
> sumparts <- 10  # reciprocal of p
> weights <- compositions(n=sumparts, m=numparts, include.zero=FALSE)/sumparts
> weights

[1,] 0.4 0.3 0.2 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1
[2,] 0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2
[4,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.3 0.2 0.1
[2,] 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.3
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[4,] 0.4 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[5,] 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.4 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.3
[2,] 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.3 0.4 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2

[1,] 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[2,] 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[3,] 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2
[7,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2

[1,] 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1
[2,] 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.3 0.1 0.1 0.1 0.1 0.1 0.2 0.1
[7,] 0.2 0.3 0.3 0.3 0.3 0.3 0.3 0.4
2 голосов
/ 01 августа 2011

РЕДАКТИРОВАТЬ: функция обновлена, так как она дала некоторые результаты дважды.

Вы можете попробовать эту функцию, основываясь на рекурсивных вычислениях.Это даст вам все возможные комбинации, независимо от порядка.Я сделал это таким образом, так как в противном случае вы получите несколько строк со всеми возможными перестановками.

Расчет основан на целых числах.Минимальный вес P устанавливается равным 1, и Pint становится числом единиц веса, которые можно разделить.max.W будет максимальным количеством единиц, которое может быть задано одной переменной.

Алгоритм работает следующим образом:

  • , если N = 2, тогда сделать всевозможные комбинации для данного минимального и максимального веса.

  • , если N> 2, применить этот алгоритм для N = 1 к потолку (максимальный вес / N), с максимальным весом, указанным кактекущий максимальный вес +1 минус N, а минимальный вес - N.

Это дает вам все возможные комбинации целых чисел.Умножение на P дает исходные веса.

Или в функции:

myfunc <- function(N,P){
  if(100%%(P*100) !=0){
    stop("100% cannot be divided in portions of P")
  }
  Pint <- 100/(P*100)
  max.W <- Pint- N + 1

  combs <- function(n,max.w,min){
    mw <- max.w + 1

    if(n==2){

      w <- seq.int(min,floor((mw)/2))
      out <- cbind(w,mw-w)

    } else if (n > 2){

      x <- lapply(1:ceiling(max.w/n),function(i){

        newcombs <- combs(n-1,mw-i,i)
        cbind(newcombs,rep(i,nrow(newcombs)))

      })

      out <- do.call("rbind",x)
    }
    colnames(out) <-rownames(out) <- NULL
    out
  }  
  res <- combs(N,max.W)
  apply(res,1,sort)*P
}

Это дает комбинации в столбцах матрицы:

> Y <- myfunc(3,0.1)
> Y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]  0.1  0.1  0.1  0.1  0.2  0.2  0.2  0.3
[2,]  0.1  0.2  0.3  0.4  0.2  0.3  0.4  0.3
[3,]  0.8  0.7  0.6  0.5  0.6  0.5  0.4  0.4

Будьте осторожны!с заданным вами тестовым сценарием (7 переменных, переходы 0,01) вы будете очень долго вычислять огромное количество возможностей.При N = 7 и P = 0,04 у вас уже есть 3555 возможных комбинаций.С N = 0,2 это становится 336,443 возможностями.И вы должны учитывать каждую возможную перестановку этих комбинаций, если это то, что вы ищете.

...