简单解决第一个问题
这是第一个问题的简单解决方案。
模拟u_1
, ..., u_n
之间-1
and 1
。
然后设置x_1 = (u_1-u_n)/2
, x_2 = (u_2-u_1)/2
, x_3 = (u_3-u_2)/2
, ..., x_n = (u_n-u_{n-1})/2
.
n <- 10L
u <- runif(n, -1, 1)
x <- c(u[1L]-u[n], diff(u)) / 2
sum(x)
summary(x)
推广到任意总和
现在,如何生成n
随机数x_1
, ..., x_n
位于之间-1
and 1
和给定的数字s
(之间-n
and n
)?
像以前一样进行,但减去s/n
to the u_i
并添加s/n
to the x_i
:
s <- 3
n <- 10L
u <- runif(n, -1, 1) - s/n
x <- c(u[1L]-u[n], diff(u))/2 + s/n
sum(x)
summary(x)
泛化到任意范围?
现在,如何生成n
随机数x_1
, ..., x_n
位于两个给定数字之间a
and b
和给定的数字s
(之间n*a
and n*b
)?
前面的方法可以推广到这种情况a = -b
:
a <- -4; b <- 4; s <- 10
n <- 10L
u <- runif(n, -(b-a)/2, (b-a)/2) - s/n
x <- c(u[1L]-u[n], diff(u))/2 + s/n
sum(x)
summary(x)
最后是DRS算法
The 狄利克雷重缩放算法解决任意数字对的最后一个问题a < b
.
此外,模拟向量(x_1, ..., x_n)
有均匀分布 on the (n-1)
维流形{sum x_i = s}
, a <= x_i <= b
.
这是一个 R 实现,改编自 Roger Stafford 编写的 Matlab 实现(代码中给出的参考)。
# adapted from Roger Stafford's Matlab implementation
# Roger Stafford (2023). Random Vectors with Fixed Sum (https://www.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum), MATLAB Central File Exchange. Retrieved March 23, 2023.
DRS <- function(n, s, a, b) {
n <- as.integer(n)
if(s < n*a || s > n*b || a >= b) {
stop("Invalid parameters.")
}
# Rescale to a unit cube: 0 <= x(i) <= 1
s <- (s - n*a) / (b - a)
# Construct the transition probability table, t.
# t(i,j) will be used only in the region where j <= i + 1.
k <- max(min(as.integer(floor(s)), n-1L), 0L) # Must have 0 <= k <= n-1
s <- max(min(s, k+1L), k) # Must have k <= s <= k+1
s1 <- s - (k:(k-n+1L)) # s1 will never be negative
s2 <- ((k+n):(k+1L)) - s # s2 will never be negative
w <- matrix(0, nrow = n, ncol = n+1L)
w[1L, 2L] <- .Machine$double.xmax # Scale for full 'double' range
t <- matrix(0, nrow = n-1L, ncol = n)
tiny <- .Machine$double.eps # The smallest positive 'double'
for(i in 2L:n) {
tmp1 <- w[i-1L, 2L:(i+1L)] * s1[1L:i] / i
tmp2 <- w[i-1L, 1L:i] * s2[(n-i+1L):n] / i
w[i, 2L:(i+1L)] <- tmp1 + tmp2
tmp3 <- w[i, 2L:(i+1L)] + tiny # In case tmp1 & tmp2 are both 0,
tmp4 <- as.double(s2[(n-i+1L):n] > s1[1L:i]) # then t is 0 on left & 1 on right
t[i-1L, 1L:i] <- (tmp2 / tmp3) * tmp4 + (1 - tmp1 / tmp3) * (1 - tmp4)
}
# Derive the polytope volume v from the appropriate element in the bottom row of w.
v <- n^(3/2) * (w[n, k+2L] / .Machine$double.xmax) * (b - a)^(n - 1L)
# Now construct the vector x.
x <- numeric(n)
rt <- runif(n - 1L) # For random selection of simplex type
rs <- runif(n - 1L) # For random location within a simplex
j <- k + 1L # For indexing in the t table
sm <- 0 # Start with sum zero
pr <- 1 # Start with product 1
for(i in (n-1L):1L) { # Work backwards in the t table
e <- as.double(rt[n-i] <= t[i, j]) # Use rt to choose a transition
sx <- rs[n-i] ^ (1L/i) # Use rs to compute next simplex coordinate
sm <- sm + (1 - sx) * pr * s / (i + 1L) # Update sum
pr <- sx * pr # Update product
x[n-i] <- sm + pr * e # Calculate x using simplex coordinates
s <- s - e
j <- j - e # Transition adjustment
}
x[n] <- sm + pr * s # Compute the last x
# Randomly permute the order in x and rescale
p <- order(runif(n)) # it is a random permutation
a + (b - a) * x[p]
}
Example:
x <- DRS(n = 10L, s = 14, a = 1, b = 2)
sum(x)
summary(x)
EDIT
有问题:这是notDRS - 请参阅给定链接中的幻灯片。 DRS 更普遍地允许不同的界限x_i
.
EDIT
我刚刚发现这个方法是在R包中实现的代理人.