Search code examples
pythonarraysnumpymeshlinspace

Non-evenly spaced np.array with more points near the boundary


I have an interval, say (0, 9) and I have to generate points between them such that they are denser at the both the boundaries. I know the number of points, say n_x. alpha decides the "denseness" of the system such that points are evenly spaced if alpha = 1.

The cross product of n_x and n_y is supposed to look like this:

[enter image description here

So far the closest I've been to this is by using np.geomspace, but it's only dense near the left-hand side of the domain,

In [55]: np.geomspace(1,10,15) - 1
Out[55]: 
array([0.        , 0.17876863, 0.38949549, 0.63789371, 0.93069773,
       1.27584593, 1.6826958 , 2.16227766, 2.72759372, 3.39397056,
       4.17947468, 5.1054023 , 6.19685673, 7.48342898, 9.        ])

I also tried dividing the domain into two parts, (0,4), (5,10) but that did not help either (since geomspace gives more points only at the LHS of the domain).

In [29]: np.geomspace(5,10, 15)
Out[29]: 
array([ 5.        ,  5.25378319,  5.52044757,  5.80064693,  6.09506827,
        6.40443345,  6.72950096,  7.07106781,  7.42997145,  7.80709182,
        8.20335356,  8.61972821,  9.05723664,  9.51695153, 10.        ])

Apart from that, I am a bit confused about which mathematical function can I use to generate such an array.


Solution

  • You can use cumulative beta functions and map to your range.

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.stats import beta
    
    def denseboundspace(size=30, start=0, end=9, alpha=.5):
        x = np.linspace(0, 1, size)
        return start + beta.cdf(x, 2.-alpha, 2.-alpha) * (end-start)
    
    n_x = denseboundspace()
    #[0.         0.09681662 0.27092155 0.49228501 0.74944966 1.03538131
    # 1.34503326 1.67445822 2.02038968 2.38001283 2.75082572 3.13054817
    # 3.51705806 3.9083439  4.30246751 4.69753249 5.0916561  5.48294194
    # 5.86945183 6.24917428 6.61998717 6.97961032 7.32554178 7.65496674
    # 7.96461869 8.25055034 8.50771499 8.72907845 8.90318338 9.        ]
    
    plt.vlines(n_x, 0,2);
    

    beta(1.5, 1.5)

    n_x = denseboundspace(size=13, start=1.2, end=7.8, alpha=1.0)
    #[1.2  1.75 2.3  2.85 3.4  3.95 4.5  5.05 5.6  6.15 6.7  7.25 7.8 ]
    
    plt.vlines(n_x, 0,2);
    

    beta(1,1)

    The spread is continuously controlled by the alpha parameter.

    alpha0to1