Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I randomly choose values from a complex interval instance? #43

Closed
cannolis opened this issue Oct 14, 2020 · 5 comments
Closed
Labels
question Issue is a question

Comments

@cannolis
Copy link

now I need to get some random values from a interval instance, is there some simple methods to achieve this?
if there is, I would appreciate it very much !

@AlexandreDecan AlexandreDecan added the question Issue is a question label Oct 14, 2020
@AlexandreDecan
Copy link
Owner

AlexandreDecan commented Oct 14, 2020

Hello,

Which kind of intervals are you using? I mean: are they based on numerical values, dates, etc.? Also, depending on the type, these intervals can be continuous (e.g. floats) or pseudo-discrete (e.g. dates), leading to a different problem ;)

[Edited: Also, I guess that you want each value to have the exact same probability to be taken?]

@cannolis
Copy link
Author

Hi @AlexandreDecan,
Just as you said, these intervals are mainly based on numerical values, and I want to get random values in same probability.
Although there is some method to get values from a range in model "random", but the boundary is hard to handle with the interval instance.

@AlexandreDecan
Copy link
Owner

AlexandreDecan commented Oct 14, 2020

Hi,

A very naive, pretty inefficient, way to do this would be to generate a random value and check if it is contained in the interval. Let's assume that your interval is interval, and that it is lower and upper bounded (i.e. its bounds are distinct from P.inf and -P.inf). Then the code could be:

while True:
  x = random.uniform(interval.lower, interval.upper)
  if x in interval: 
    break

By the way, this could be very inefficient, especially if there are many "gaps" in your interval.

Another way, more efficient, would be to work with atomic intervals (i.e. intervals that have no "gap"). The first step is to select one of them, then to generate a value between its bounds. Obviously, not all atomic intervals should have the same weights, since some of them are "smaller" than some other ones.

weights = [x.upper - x.lower for x in interval]
atomic = random.choices(interval, weights=weights, k=1)[0]
while True:
  x = random.uniform(atomic.lower, atomic.upper)
  if x in atomic:
    break

The while loop is still needed, since we are generating a number between atomic.lower and atomic.upper and that one of them could be P.OPEN (i.e. should not be selected). This loop is however far more efficient than the one of the first example, as it will only be executed more than once if x == atomic.lower and atomic.left == P.OPEN or x == atomic.upper and atomic.right == P.OPEN.

Notice that I have not tested these snippets yet :-)

@cannolis
Copy link
Author

Thank you very much!
I think the methods you mentioned can really help me with the problem, and I truly appreciate your timely help ;)

@AlexandreDecan
Copy link
Owner

You're welcome! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Issue is a question
Projects
None yet
Development

No branches or pull requests

2 participants