生成具有最小距离的随机 x 和 y 坐标
generating random x and y coordinates with a minimum distance
R 中有没有办法生成随机坐标,它们之间的距离最小?
例如我想避免什么
x <- c(0,3.9,4.1,8)
y <- c(1,4.1,3.9,7)
plot(x~y)
我不确定你在问什么。
如果你想要这里的随机坐标。
c(
runif(1,max=y[1],min=x[1]),
runif(1,max=y[2],min=x[2]),
runif(1,min=y[3],max=x[3]),
runif(1,min=y[4],max=x[4])
)
你可以使用拒绝树苗https://en.wikipedia.org/wiki/Rejection_sampling
原理很简单:重新采样直到数据验证条件。
> set.seed(1)
>
> x <- rnorm(2)
> y <- rnorm(2)
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 6.565578
> while((x[1]-x[2])^2+(y[1]-y[2])^2 > 1) {
+ x <- rnorm(2)
+ y <- rnorm(2)
+ }
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 0.9733252
>
好的,这个怎么样?您只需无限制地生成随机数对,然后删除太接近的一次。这可能是一个很好的开始:
minimumDistancePairs <- function(x, y, minDistance){
i <- 1
repeat{
distance <- sqrt((x-x[i])^2 + (y-y[i])^2) < minDistance # pythagorean theorem
distance[i] <- FALSE # distance to oneself is always zero
if(any(distance)) { # if too close to any other point
x <- x[-i] # remove element from x
y <- y[-i] # and remove element from y
} else { # otherwise...
i = i + 1 # repeat the procedure with the next element
}
if (i > length(x)) break
}
data.frame(x,y)
}
minimumDistancePairs(
c(0,3.9,4.1,8)
, c(1,4.1,3.9,7)
, 1
)
会导致
x y
1 0.0 1.0
2 4.1 3.9
3 8.0 7.0
但请注意,这些不再是随机数(无论您如何解决问题)。
以下是一种天真的命中注定的方法,对于某些参数选择(问题中未指定)效果很好。如果性能成为问题,您可以尝试使用具有 GPU 加速距离矩阵计算的包 gpuR。
rand.separated <- function(n,x0,x1,y0,y1,d,trials = 1000){
for(i in 1:trials){
nums <- cbind(runif(n,x0,x1),runif(n,y0,y1))
if(min(dist(nums)) >= d) return(nums)
}
return(NA) #no luck
}
这会在 [x0,x1]x[y0,y1]
中重复抽取大小为 n
的样本,如果不满足则将样本丢弃。作为安全措施,trials
防止无限循环。如果解决方案很难找到或 n
很大,您可能需要增加或减少 trials
.
例如:
> set.seed(2018)
> nums <- rand.separated(25,0,10,0,10,0.2)
> plot(nums)
几乎立即运行并产生:
这是随机几何学的经典问题。 space 中的完全随机点,其中落在不相交区域中的点数彼此独立,对应于齐次泊松点过程(在这种情况下,在 R^2 中,但几乎可以在任何 space 中).
一个重要的特征是点的总数必须是随机的,然后才能独立于不相交区域中的点数。
对于泊松过程,点可以任意靠近。如果您通过对泊松过程进行采样来定义一个过程,直到您没有任何太靠近的点,您就有了所谓的 Gibbs Hardcore 过程。这在文献中已经进行了大量研究,并且有不同的方法来模拟它。 R 包 spatstat
具有执行此操作的功能。 rHardcore
是一个完美的采样器,但是如果你想要高强度的点和大的硬核距离,它可能不会在有限的时间内终止......分布可以作为马尔可夫链的极限获得并且 rmh.default
让你 运行 一个以给定吉布斯模型作为不变分布的马尔可夫链。这在有限的时间内完成,但只给出了近似分布的实现。
在rmh.default
中,您还可以模拟固定点数的条件。请注意,当您在有限的盒子中采样时,给定的硬核半径可以容纳的点数当然有一个上限,并且您越接近此限制,从分布中正确采样的问题就越大。
示例:
library(spatstat)
beta <- 100; R = 0.1
win <- square(1) # Unit square for simulation
X1 <- rHardcore(beta, R, W = win) # Exact sampling -- beware it may run forever for some par.!
plot(X1, main = paste("Exact sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X1) # Observed min. nearest neighbour dist.
#> [1] 0.102402
近似模拟
model <- rmhmodel(cif="hardcore", par = list(beta=beta, hc=R), w = win)
X2 <- rmh(model)
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X2, main = paste("Approx. sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X2) # Observed min. nearest neighbour dist.
#> [1] 0.1005433
以点数为条件的近似模拟
X3 <- rmh(model, control = rmhcontrol(p=1), start = list(n.start = 42))
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X3, main = paste("Approx. sim. given n =", 42))
minnndist(X3) # Observed min. nearest neighbour dist.
#> [1] 0.1018068
R 中有没有办法生成随机坐标,它们之间的距离最小?
例如我想避免什么
x <- c(0,3.9,4.1,8)
y <- c(1,4.1,3.9,7)
plot(x~y)
我不确定你在问什么。
如果你想要这里的随机坐标。
c(
runif(1,max=y[1],min=x[1]),
runif(1,max=y[2],min=x[2]),
runif(1,min=y[3],max=x[3]),
runif(1,min=y[4],max=x[4])
)
你可以使用拒绝树苗https://en.wikipedia.org/wiki/Rejection_sampling
原理很简单:重新采样直到数据验证条件。
> set.seed(1)
>
> x <- rnorm(2)
> y <- rnorm(2)
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 6.565578
> while((x[1]-x[2])^2+(y[1]-y[2])^2 > 1) {
+ x <- rnorm(2)
+ y <- rnorm(2)
+ }
> (x[1]-x[2])^2+(y[1]-y[2])^2
[1] 0.9733252
>
好的,这个怎么样?您只需无限制地生成随机数对,然后删除太接近的一次。这可能是一个很好的开始:
minimumDistancePairs <- function(x, y, minDistance){
i <- 1
repeat{
distance <- sqrt((x-x[i])^2 + (y-y[i])^2) < minDistance # pythagorean theorem
distance[i] <- FALSE # distance to oneself is always zero
if(any(distance)) { # if too close to any other point
x <- x[-i] # remove element from x
y <- y[-i] # and remove element from y
} else { # otherwise...
i = i + 1 # repeat the procedure with the next element
}
if (i > length(x)) break
}
data.frame(x,y)
}
minimumDistancePairs(
c(0,3.9,4.1,8)
, c(1,4.1,3.9,7)
, 1
)
会导致
x y
1 0.0 1.0
2 4.1 3.9
3 8.0 7.0
但请注意,这些不再是随机数(无论您如何解决问题)。
以下是一种天真的命中注定的方法,对于某些参数选择(问题中未指定)效果很好。如果性能成为问题,您可以尝试使用具有 GPU 加速距离矩阵计算的包 gpuR。
rand.separated <- function(n,x0,x1,y0,y1,d,trials = 1000){
for(i in 1:trials){
nums <- cbind(runif(n,x0,x1),runif(n,y0,y1))
if(min(dist(nums)) >= d) return(nums)
}
return(NA) #no luck
}
这会在 [x0,x1]x[y0,y1]
中重复抽取大小为 n
的样本,如果不满足则将样本丢弃。作为安全措施,trials
防止无限循环。如果解决方案很难找到或 n
很大,您可能需要增加或减少 trials
.
例如:
> set.seed(2018)
> nums <- rand.separated(25,0,10,0,10,0.2)
> plot(nums)
几乎立即运行并产生:
这是随机几何学的经典问题。 space 中的完全随机点,其中落在不相交区域中的点数彼此独立,对应于齐次泊松点过程(在这种情况下,在 R^2 中,但几乎可以在任何 space 中).
一个重要的特征是点的总数必须是随机的,然后才能独立于不相交区域中的点数。
对于泊松过程,点可以任意靠近。如果您通过对泊松过程进行采样来定义一个过程,直到您没有任何太靠近的点,您就有了所谓的 Gibbs Hardcore 过程。这在文献中已经进行了大量研究,并且有不同的方法来模拟它。 R 包 spatstat
具有执行此操作的功能。 rHardcore
是一个完美的采样器,但是如果你想要高强度的点和大的硬核距离,它可能不会在有限的时间内终止......分布可以作为马尔可夫链的极限获得并且 rmh.default
让你 运行 一个以给定吉布斯模型作为不变分布的马尔可夫链。这在有限的时间内完成,但只给出了近似分布的实现。
在rmh.default
中,您还可以模拟固定点数的条件。请注意,当您在有限的盒子中采样时,给定的硬核半径可以容纳的点数当然有一个上限,并且您越接近此限制,从分布中正确采样的问题就越大。
示例:
library(spatstat)
beta <- 100; R = 0.1
win <- square(1) # Unit square for simulation
X1 <- rHardcore(beta, R, W = win) # Exact sampling -- beware it may run forever for some par.!
plot(X1, main = paste("Exact sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X1) # Observed min. nearest neighbour dist.
#> [1] 0.102402
近似模拟
model <- rmhmodel(cif="hardcore", par = list(beta=beta, hc=R), w = win)
X2 <- rmh(model)
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X2, main = paste("Approx. sim. of hardcore model; beta =", beta, "and R =", R))
minnndist(X2) # Observed min. nearest neighbour dist.
#> [1] 0.1005433
以点数为条件的近似模拟
X3 <- rmh(model, control = rmhcontrol(p=1), start = list(n.start = 42))
#> Checking arguments..determining simulation windows...Starting simulation.
#> Initial state...Ready to simulate. Generating proposal points...Running Metropolis-Hastings.
plot(X3, main = paste("Approx. sim. given n =", 42))
minnndist(X3) # Observed min. nearest neighbour dist.
#> [1] 0.1018068