Search code examples
pythonlistrandomthreshold

Set a minimum threshold among the elements of a list in python


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.


Solution

  • 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.