Chọn kết hợp các số nguyên một cách hiệu quả


8

Giả sử chúng ta có một ma trận 5x5, chứa đầy 0.

myMatrix <- matrix(rep(0, 25), ncol = 5)

Bây giờ, hãy chọn một bộ ba số nguyên từ 1 đến 5.

triplet <- c(1,2,3)

Đối với tất cả các kết hợp của bộ ba này, bây giờ chúng ta thêm 1 trong ma trận, với chức năng này:

addCombinationsToMatrix <- function(.matrix, .triplet){
    indexesToChange <- as.matrix(expand.grid(.triplet, .triplet))
    .matrix[indexesToChange] <- .matrix[indexesToChange] + 1
    .matrix
}

Sử dụng chức năng, chúng tôi đi từ

myMatrix

     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0

đến

myMatrix <- addCombinationsToMatrix(myMatrix, triplet)
myMatrix

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    0    0
[2,]    1    1    1    0    0
[3,]    1    1    1    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0

Nếu chúng tôi chọn một bộ ba khác, chúng tôi chuyển sang

nextTriplet <- 2:4
myMatrix <- addCombinationsToMatrix(myMatrix, nextTriplet)
myMatrix

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    1    1    0    0
[2,]    1    2    2    1    0
[3,]    1    2    2    1    0
[4,]    0    1    1    1    0
[5,]    0    0    0    0    0

Vì vậy, các kết hợp cột hàng biểu thị tần suất hai số nguyên được hiển thị cùng nhau trong một bộ ba: 3 và 4 đã được hiển thị cùng nhau một lần, 2 và 3 đã được hiển thị cùng nhau hai lần.

Câu hỏi : Làm thế nào một người có thể chọn bộ ba, sao cho mọi kết hợp (1-2, 1-3, 1-4 ...) được chọn ít nhất một lần và số lượng bộ ba được giảm thiểu.

Tôi đang tìm kiếm một thuật toán ở đây chọn bộ ba tiếp theo.

Lý tưởng nhất là nó có thể được mở rộng đến

  • ma trận lớn tùy ý (10 x 10, 100x100 ...)
  • các vectơ lớn tùy ý (bộ tứ, bộ ngũ, n-tuplets)
  • một số lần tùy ý một sự kết hợp phải được chọn ít nhất

Thí dụ:

myMatrix
myMatrix <- addCombinationsToMatrix(myMatrix, 1:3)
myMatrix
myMatrix <- addCombinationsToMatrix(myMatrix, 3:5)
myMatrix
myMatrix <- addCombinationsToMatrix(myMatrix, c(1,4,5))
myMatrix
myMatrix <- addCombinationsToMatrix(myMatrix, c(2,4,5))
myMatrix

EDIT : Chỉ cần chắc chắn: câu trả lời không nhất thiết phải là Rmã. Nó có thể là một số ngôn ngữ khác cũng như hoặc thậm chí mã giả.

EDIT 2 : Điều này xảy ra với tôi bây giờ, rằng có nhiều cách đo lường hiệu quả khác nhau. Tôi thực sự có nghĩa là, thuật toán nên mất càng ít lần lặp càng tốt. Thuật toán nhanh cũng rất tuyệt, nhưng không phải là mục tiêu chính ở đây.

Câu trả lời:


6

Câu hỏi tuyệt vời! Điều này xuất hiện trong thiết kế khảo sát, trong đó bạn muốn có một vài phiên bản khảo sát khác nhau, mỗi phiên bản chỉ chứa một tập hợp các câu hỏi, nhưng bạn muốn mỗi cặp (hoặc t-tuple) câu hỏi được hỏi ít nhất một lần.

Điều này được gọi là thiết kế che phủ , và là một biến thể của vấn đề bao gồm thiết lập cổ điển . Như bạn có thể đọc trong bài đăng Trao đổi ngăn xếp toán học xuất sắc về chủ đề này, mọi người sử dụng ký hiệu C (v, k, t) cho biết số lượng tập hợp phần tử k tối thiểu bạn cần rút ra (k = 3 trong trường hợp của bạn) từ một v -element set (v = 5 trong trường hợp của bạn) sao cho mọi tập hợp phần tử t trong toàn bộ tập hợp (t = 2 trong trường hợp của bạn) được chứa trong một trong các tập hợp con đã chọn của bạn. Mọi người đã đánh giá chức năng này cho nhiều bộ dữ liệu (v, k, t) khác nhau; xem, ví dụ: https://ljcr.dmgordon.org/cover/table.html . Chúng ta có thể đọc từ bảng đó rằng C (5, 3, 2) = 4, với thiết kế như sau:

  1  2  3
  1  4  5
  2  3  4
  2  3  5

Đầu tiên và quan trọng nhất, vấn đề này là NP-hard, vì vậy tất cả các thuật toán chính xác đã biết sẽ mở rộng theo cấp số nhân trong các đầu vào v, k và t. Vì vậy, trong khi bạn có thể giải quyết các trường hợp nhỏ chính xác bằng cách liệt kê hoặc một số phương pháp chính xác thông minh hơn (ví dụ lập trình số nguyên), bạn có thể sẽ cần phải sử dụng các phương pháp heuristic vì kích thước bài toán rất lớn.

Một khả năng theo hướng này là bao gồm từ vựng, như được đề xuất trong https://arxiv.org/pdf/math/9502238.pdf (bạn sẽ lưu ý rằng nhiều giải pháp trên trang web được liên kết ở trên liệt kê "lex cover" là phương pháp của xây dựng). Về cơ bản, bạn liệt kê ra tất cả các k-tuple có thể theo thứ tự từ điển:

123
124
125
134
135
145
234
235
245
345

Sau đó, bạn tham lam thêm k-tuple bao gồm các t-tuple chưa được phát hiện trước đó, phá vỡ các mối quan hệ bằng cách sử dụng thứ tự từ điển.

Đây là cách thuật toán hoạt động trong trường hợp của chúng tôi:

  1. Lúc đầu, mỗi 3 tuple bao gồm 3 tuple khác nhau, vì vậy chúng tôi thêm vào 123vì nó là từ vựng sớm nhất.

  2. Sau khi thực hiện điều này, 2-tuples của 12, 1323đã được bao phủ, trong khi tất cả còn lại 2-tuples không được. Một số 3 tuple bao gồm 3 tuple nữa, vd 145245. Chúng tôi chọn 145, vì nó là thứ tự từ điển đầu tiên, bao gồm 14, 4515.

  3. Bây giờ chúng tôi có 4 còn phát hiện 2 bộ dữ liệu - 24, 25, 34, và 35. Không có 3-tuple bao gồm 3 trong số này, nhưng một số bìa 2, ví dụ 234345. Chúng tôi chọn 234là từ vựng sớm nhất.

  4. Chúng tôi có hai tuple 2 chưa được phát hiện - 2535. Chúng tôi chọn 235là 3 tuple duy nhất bao gồm cả hai.

Chúng tôi kết thúc với giải pháp chính xác được hiển thị ở trên. Điều quan trọng, đây chỉ là một phương pháp heuristic - nó không đảm bảo rằng 4 là số lượng nhỏ nhất của 3 bộ dữ liệu cần thiết để bao gồm tất cả các cặp trong một bộ có 5 phần tử. Trong trường hợp này, giới hạn dưới của Schönheim (một tài liệu tham khảo được cung cấp trong bài viết được liên kết ở trên) thuyết phục chúng tôi rằng, trên thực tế, C (5, 3, 2) không thể nhỏ hơn 4. Chúng tôi kết luận rằng giải pháp từ bao phủ từ điển là Trong thực tế tối ưu.

Bạn sẽ cần một tinh chỉnh để bao gồm mỗi t-tup một số lần nhất định r. Một điều hiển nhiên là chỉ cần lặp lại mỗi bộ dữ liệu để được bảo hiểm "r" lần, và sau đó chạy lex cover như bình thường (ví dụ, trong bước đầu tiên trên mỗi bộ 3 sẽ bao gồm 9 2 tuple với r = 3). Tất nhiên điều này vẫn là một heuristic cho vấn đề tổng thể của bạn do sử dụng lex cover.


2
Ai, đây là một câu trả lời tốt đáng kinh ngạc. Cảm ơn bạn rất nhiều. Về cơ bản nó giải thích câu hỏi tốt hơn câu hỏi đã làm. Điều này thực sự là giác ngộ.
Georgery

2

Đây là một tùy chọn sử dụng data.tableđể theo dõi số lượng ma trận và RcppAlgosđể tạo các kết hợp:

library(RcppAlgos)
library(data.table)

M <- 100 #5 #10 #100
sz <- 5 #3 #4 5 
minpick <- 3 #1 #2
d <- integer(M)

system.time({
    universe <- as.data.table(comboGeneral(M, 2L, nThreads=4L))[, count := 0L]
    ntuples <- 0
    while (universe[, any(count < minpick)]) {
        v <- universe[order(count), head(unique(c(V1[1L:2L], V2[1L:2L])), sz)]
        universe[as.data.table(comboGeneral(v, 2L, nThreads=4L)), on=.NATURAL, count := count + 1L]
        ntuples = ntuples + 1L
    }
    ntuples
})
#   user  system elapsed 
#  26.82    9.81   28.75 

m <- matrix(0L, nrow=M, ncol=M)
m[as.matrix(universe[, V1:V2])] <- universe$count
m + t(m) + diag(d)

Nó là một thuật toán tham lam, do đó, tôi không chắc liệu điều này có dẫn đến số lượng bộ dữ liệu tối thiểu hay không.


Hừm, nó không hoạt động với tôi. Tôi nhận được lỗi này: Error in eval(onsub, parent.frame(2L), parent.frame(2L)) : object '.NATURAL' not found
Georgery

bạn cần data.table phiên bản> = 1.12.4 xem mục 10 trong bản phát hành đó trên github.com/Rdatitable/data.table/blob/master/NEWS.md
chin gió12

2

Vì câu hỏi này yêu cầu các cách tiếp cận thuật toán để bao trùm các thiết kế, tôi sẽ cung cấp một câu trả lời chính xác (còn gọi là thiết kế tốt nhất có thể) bằng lập trình số nguyên trong R. Với mỗi k-tuple mà bạn đang xem xét (k = 3 cho bạn, vì bạn đang chọn bộ ba), hãy xác định biến quyết định lấy giá trị 1 nếu bạn đưa nó vào thiết kế của bạn và 0 nếu không. Vì vậy, trong trường hợp của bạn, bạn sẽ xác định x_123 để cho biết nếu tuple (1,2,3) được chọn, x_345 cho (3,4,5), v.v.

Mục tiêu của mô hình tối ưu hóa là giảm thiểu số lượng bộ dữ liệu được chọn, hay còn gọi là tổng của tất cả các biến quyết định của bạn. Tuy nhiên, với mỗi t-tuple (t = 2 trong trường hợp của bạn), bạn cần bao gồm một biến quyết định có chứa t-tuple đó. Điều này mang lại một ràng buộc cho mọi tuple. Ví dụ, chúng ta sẽ có x_123+x_124+x_125 >= 1các ràng buộc yêu cầu cặp 12phải ở trong một số bộ được chọn.

Điều này mang lại mô hình tối ưu hóa sau:

min  x_123+x_124+...+x_345
s.t. x_123+x_124+x_125 >= 1  # constraint for 12
     x_123+x_134+x_135 >= 1  # constraint for 13
     ...
     x_145+x_245+x_345 >= 1  # constraint for 45
     x_ijk binary for all i, j, k

Bạn có thể mở rộng điều này để yêu cầu lặp lại r của mỗi tuple bằng cách thay đổi phía bên phải của mọi bất đẳng thức thành "r" và yêu cầu tất cả các biến là số nguyên thay vì nhị phân.

Điều này rất dễ giải quyết với một gói như lpSolvetrong R:

library(lpSolve)
C <- function(v, k, tt, r) {
  k.tuples <- combn(v, k)
  t.tuples <- combn(v, tt)
  mod <- lp(direction="min",
            objective.in=rep(1, ncol(k.tuples)),
            const.mat=t(apply(t.tuples, 2, function(x) {
              apply(k.tuples, 2, function(y) as.numeric(sum(x %in% y) == tt))
            })),
            const.dir=rep(">=", ncol(t.tuples)),
            const.rhs=rep(r, ncol(t.tuples)),
            all.int=TRUE)
  k.tuples[,rep(seq_len(ncol(k.tuples)), round(mod$solution))]
}
C(5, 3, 2, 1)
#      [,1] [,2] [,3] [,4]
# [1,]    1    1    1    3
# [2,]    2    2    2    4
# [3,]    3    4    5    5
C(5, 3, 2, 3)
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]    1    1    1    1    1    1    2    2    2     3
# [2,]    2    2    2    3    3    4    3    3    4     4
# [3,]    3    4    5    4    5    5    4    5    5     5

Mặc dù điều này giải quyết chính xác vấn đề của bạn, nhưng nó sẽ không mở rộng tốt cho các kích thước vấn đề lớn. Điều này là do vấn đề là NP-hard - không có thuật toán chính xác nào được biết sẽ mở rộng tốt. Nếu bạn cần giải quyết các trường hợp vấn đề lớn, thì các phương pháp phỏng đoán được đề xuất trong các câu trả lời khác ở đây là cách tốt nhất của bạn. Hoặc bạn có thể giải quyết với lập trình số nguyên (như chúng tôi làm ở đây) và đặt thời gian chờ; sau đó bạn sẽ làm việc với giải pháp tốt nhất được tìm thấy trong thời gian chờ của bạn, đó là một giải pháp heuristic cho vấn đề tổng thể.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.