0

I am trying to create a loop in Python with numpy that will give me a variable "times" with 5 numbers generated randomly between 0 and 20. However, I want there to be one condition: that none of the differences between two adjacent elements in that list are less than 1. What is the best way to achieve this? I tried with the last two lines of code, but this is most likely wrong.

for j in range(1,6):

    times = np.random.rand(1, 5) * 20
    times.sort()
    print times

    da = np.diff(times) 

    if da.sum < 1: break

For instance, for one iteration, this would not be good:

4.25230915 4.36463992 10.35915732 12.39446368 18.46893283

But something like this would be perfect:

1.47166904 6.85610453 10.81431629 12.10176092 15.53569052

2 Answers 2

2

Since you are using numpy, you might as well use the built-in functions for uniform random numbers.

def uniform_min_range(a, b, n, min_dist):
    while True:
        x = np.random.uniform(a, b, size=n)
        np.sort(x)
        if np.all(np.diff(x) >= min_dist):
            return x

It uses the same trial-and-error approach as the previous answer, so depending on the parameters the time to find a solution can be large.

Sign up to request clarification or add additional context in comments.

4 Comments

A numpy translation of the other answer is a definite plus
Thank you Hannes, it works perfectly and the numbers look great! I made x a global inside the function and the printed x outside, after passing the arguments.
No, please don't do that unless you really need to. Which you most likely don't :) Instead call it as times = uniform_min_range(0, 20, 5, 1.0) and then print times.
Done! Thanks so much Hannes!
0

Use a hit and miss approach to guarantee uniform distribution. Here is a straight-Python implementation which should be tweakable for numpy:

import random

def randSpacedPoints(n,a,b,minDist):
    #draws n random numbers in [a,b]
    # with property that their distance apart is >= minDist
    #uses a hit-miss approach

    while True:
        nums = [a + (b-a)*random.random() for i in range(n)]
        nums.sort()
        if all(nums[i] + minDist < nums[i+1] for i in range(n-1)):
            return nums

For example,

>>> randSpacedPoints(5,0,20,1)
[0.6681336968970486, 6.882374558960349, 9.73325447748434, 11.774594560239493, 16.009157676493903]

If there is no feasible solution this will hang in an infinite loop (so you might want to add a safety parameter which controls the number of trials).

8 Comments

There seems to be a problem with the limits imgur.com/j4iPNph It's probably because no misses can occur for (-1, 0) and (20, 21). Practically may not be important but I wanted to add as a note.
Thank you John! Unfortunately, since I am new to Python, I am still trying to wrap my head around your solution. I am copy pasting your code into my editor. I figured I should define the variables n, a, b, minDist in between the import and the def. But I don't the numbers. I get just a "** Load Time: 0.00 seconds"
@ayhan The numbers themselves are not uniform. The constraints force the numbers to be biased towards the end points. The uniformity I referred to is that the vector is chosen uniformly from among all such vectors.
@JohnColeman You are correct, I mixed up two different concepts.
@Spica. Glad you got it to work, though from a programming point of view, adding a print statement inside a function like that makes it less usable as a function. It is better design to have the calling code print the result.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.