Reputation: 242
I want to sample two integers x and y at random from an interval [1,N] such that |x-y| >= D, for some D < N. The code below (written in R) is what I have been using but it is terribly inefficient. Are there better methods for this sort of sampling? Thanks in adv.
N <- 100; D <- 10;
i <- sample(1:N, 2)
while ( abs( i[1] - i[2] ) < D ){
i <- sort(sample(1:N, 2))
}
Upvotes: 1
Views: 214
Reputation: 10349
I guess the key is to realize that y is dependent on x (or the other way around). Here's the algorithm that should work in at most three steps:
1. sample x from [1:N]
2. sample y from [1:(x-D)] if (x-D) >= 1
sample y from [x + D:N] if (x+D) <= N
3. If both conditions for y are met, choose one of the generated y uniform at random
The idea is that once x was sampled, y needs to be in the range [1:(x-D)] or [x+D:N] in order to satisfy |x-y| >= D.
Examples:
N=100; D=10
a) x is close to N
1. x is sampled from 1:N as 95
2. to satisfy |x-y| >= D, y can be at most 85, so the range to sample y is [1:85]
b) x is close to 1
1. x is sampled from 1:N as 9
2. y must be at least 19, so the range to sample y is [19:N]
c) x is close to 50
1. x is sampled from 1:N as 45
2. y must be either at most 35, or at least 55, so the ranges to sample from are [1:35] and [55:N]
Upvotes: 1
Reputation: 2094
I would approach this by first randomly sampling a difference between the numbers is greater than or equal to D
. In other words, we want to sample numbers between D
and N-1
with replacement.
difference <- sample(D:(N-1), 20, replace = TRUE)
Now all we need to do is select our lower number by selecting a number between 1
and N - difference
. We can do this using vapply
.
lowerval <- vapply(N - difference, sample, numeric(1), 1)
Finally we get the upper value by adding the difference to the lower value.
upperval <- lowerval + difference
Upvotes: 0