0

Suppose that I want to create a list consisting of thousands of elements (float numbers). I want to set a minimum threshold among all of the items. So in each step, I want to append an element (float number) to the list and I want to check if the added number has the minimum difference with all of the elements.

something like this: I have a list of numbers (1.2, 2.7, 0.7, 4.9) and I want to add a new element. it should check if the randomly generated number has a minimum threshold with all of the elements and if it does not have generate another number and check the threshold again.

I would appreciate if you can give me a hint.

SNS
  • 13
  • 2
  • 1
    Can you make this minimum threshold idea a bit more explicit please? – Celius Stingher Jan 20 '20 at 11:25
  • 1
    i want to generate 1000 random numbers and I want to check if the generated numbers have at least a minimum difference. for example: if the threshold is 0.5 and my list is (1.2, 1.9) then if I append a random number equal 1.4 then this should not be added to the list because 1.4 - 1.2 = 0.2 and it is less than 0.5 as the threshold. it should generate another number. for example this time 2.6. this number has the minimum threshold with the elements of the list: 2.6 - 1.9 > 0.5 and also 2.6 - 1.2 > 0.5 – SNS Jan 20 '20 at 11:30
  • 1
    OK, but do you want to **generate 1000 numbers** and filter out some of them (possibly leaving the resulting list much shorter than 1000) or do you want to generate new random numbers until your list contains 1000 "good" numbers? There is a difference, y'know… – Błotosmętek Jan 20 '20 at 11:33
  • Actually I want to have 1000 good numbers. So maybe I need to generate so many more numbers (maybe thousands!) randomly and check them regularly if they satisfy the minimum threshold with each element. – SNS Jan 20 '20 at 11:37

1 Answers1

2

You could do something like this:

import random

def generate_list_min_threshold(size=1000, threshold=0.01, min_value=-10, max_value=10, seed=1):
    random.seed(seed)
    ret = []
    while len(ret) < size:
        candidate = random.uniform(min_value,max_value)  # changed based on comment from Błotosmętek
        if all(abs(candidate-value) > threshold for value in ret):
            ret.append(candidate)
    return ret

Obviously this tries uniformly sampling values in [min_value, max_value] and there might not even be a valid number to add (depending on the threshold configuration). For better performance, you might want to look into consideration the conditional distribution, given your current elements in the list.

Additional suggestion to break up the probability masses and sample only valid candidates by recursion:

def sample_min_threshold(size=10000, min_value=-10000, max_value=10000, threshold=0.01):
    if size == 0:
        return []

    if (max_value-min_value)/threshold < size:
        raise ValueError("No valid configuration.", size, (max_value-min_value)/threshold)

    value = random.uniform(min_value, max_value)
    mass_left = (value-min_value)/(max_value-min_value)
    mass_right = 1 - mass_left

    n_left = math.floor(mass_left*size)
    n_right = math.floor(mass_right*size)

    return (sample_min_threshold(size=n_left, min_value=min_value, max_value=value-threshold) + 
            [value] + 
            sample_min_threshold(size=n_right, min_value=value+threshold, max_value=max_value))

edit: Added check for whether there is a valid configuration to explore.

sim
  • 1,227
  • 14
  • 20