我想计算一个k行和2 ^ k列的矩阵(S),以满足以下两个条件:
1) all of whose elements are either 1 or -1 ,
2) each column of S is a vector of dimension k and columns are distinct.
如何使用R?感谢。
答案 0 :(得分:8)
您可以使用expand.grid
,它会创建输入向量的所有组合:
k <- 3
t(expand.grid(rep(list(c(1,-1)), k)))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#Var1 1 -1 1 -1 1 -1 1 -1
#Var2 1 1 -1 -1 1 1 -1 -1
#Var3 1 1 1 1 -1 -1 -1 -1
答案 1 :(得分:3)
这是我的解决方案(递归):
from itertools import product
lst = [['alpha'],['beta','gamma'],['delta','peta','lambda']]
for res in product(*lst):
print(res)
>> ('alpha', 'beta', 'delta')
('alpha', 'beta', 'peta')
('alpha', 'beta', 'lambda')
('alpha', 'gamma', 'delta')
('alpha', 'gamma', 'peta')
('alpha', 'gamma', 'lambda')
由于递归,这种解决方案效率低下 (但递归非常好。)
Mk <- function(k) {
if (k==1) return(matrix(c(1,-1), 1, 2))
cbind(rbind(1, Mk(k-1)), rbind(-1, Mk(k-1)))
}
Mk(3)
#> Mk(3)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 1 1 1 -1 -1 -1 -1
#[2,] 1 1 -1 -1 1 1 -1 -1
#[3,] 1 -1 1 -1 1 -1 1 -1
library(microbenchmark)
k <- 3
Mk <- function(k) {
if (k==1) return(matrix(c(1,-1), 1, 2))
cbind(rbind(1, Mk(k-1)), rbind(-1, Mk(k-1)))
}
microbenchmark(
expa=t(expand.grid(rep(list(c(1,-1)), k))),
recu=Mk(k)
)
#Unit: microseconds
# expr min lq mean median uq max neval
# expa 271.977 288.359 317.30903 294.872 326.254 871.983 100
# recu 41.449 45.001 53.24341 48.949 58.422 140.134 100
答案 2 :(得分:0)
当只有2种可能的结果时,我会想到比特。
OneOrMinusOne <- function(x, dig) {
i <- 0L
string <- numeric(dig)-1L
while (x > 0) {
string[dig - i] <- ifelse(x%%2L==0L,-1L,1L)
x <- x %/% 2L
i <- i + 1L
}
string
}
sapply(0:(2^3 - 1), function(x) OneOrMinusOne(x,3))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] -1 -1 -1 -1 1 1 1 1
[2,] -1 -1 1 1 -1 -1 1 1
[3,] -1 1 -1 1 -1 1 -1 1
虽然这很自然,但它并不像Roland上面那样使用expand.grid
那么有效。
这个问题非常有趣,因为您可以考虑多少种方法。我已经提到了从0到(2 n - 1)的数字的二进制表示的连接,但是,还有更多。
<强> 1。几何(获得图像here)
当k = 3
恰好是以原点为中心的立方体顶点的坐标时,OP正在寻找的答案。对于较大的k
,答案是相似的(即答案将是kth
维hypercube的顶点坐标。在数学上,这可以通过具有半径sqrt(k)
的超球面和具有长度= 2的边的超立方体的交点来描述,两者都以原点为中心。对于k = 3
,这将转化为以下等式:
x 2 + y 2 + z 2 = 3 其中(x,y,z)是积分值(即1或-1)
<强> 2。抽象代数
我们可以将解决方案视为isomorphic到{2}整数模2 k + 1 。您可能想知道为什么k+1
。好吧,恰好Multiplicative group给了我们这些类型的组的顺序,因此我们有:
phi(2 k + 1 )= 2 k + 1 *(1 - 1/2)= 2 k
每个元素都是它自己的反转元素,元素rep(1, k)
作为标识,并在乘法时关闭(元素乘法(例如(1,-1,1)*( - 1,-1) ,1)=(-1,1,1)))。
如果你真的想对群论理解,可以将解决方案集更全面地描述为Euler's totient function。这实际上可能有效地生成解决方案,因为您实际上只需要几个向量来完整地描述解决方案集。例如,对于k = 3
,仅从3个向量开始,我们可以生成整个解集。
myL <- list(c(-1,-1,1),c(-1,1,-1),c(-1,1,1)) ## generating set
myL[[4]] <- myL[[1]]*myL[[2]]
myL[[5]] <- myL[[1]]*myL[[3]]
myL[[6]] <- myL[[1]]*myL[[2]]*myL[[3]]
myL[[7]] <- myL[[2]]*myL[[3]]
myL[[8]] <- myL[[1]]^2
do.call(cbind, myL)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] -1 -1 -1 1 1 -1 1 1
[2,] -1 1 1 -1 -1 -1 1 1
[3,] 1 -1 1 -1 1 -1 -1 1
我没有证明这一点,但是对于我尝试过的每个例子,任何k
的一般解决方案似乎完全由k
个不同的向量集合描述((-1, 1,... 1),(1,-1,1,...,1),(1,1,-1,1,...,1),...,(1,... ,1,-1))。
无论如何,这很有趣。