dlsun / symbulate

A symbolic algebra for specifying simulations.
MIT License
34 stars 18 forks source link

Beta: add xmin and xmax parameters for intervals other than (0,1) #65

Open kevindavisross opened 6 years ago

hayate0304 commented 6 years ago

I don't understand this issue. Does this mean I have to change self.xlim = (0,1) to something else. image

kevindavisross commented 6 years ago

Uniform(0,1) takes values in (0,1), while Uniform(a,b) takes values in (a,b). The usual definition of the beta takes values in (0,1), but you can also define on other intervals (xmin,xmax). I think the easiest way is with rescaling. If U is Uniform (0,1) then a+(b-a)U is Uniform (a,b). Define beta similarly: if X is Beta on (0,1) then xmin+(xmax-xmim)X is Beta on (xmin,xmax). See the code for Cauchy, where I think we handled general location and scale parameters with a similar rescaling idea.

hayate0304 commented 6 years ago

Can you check out this code? I add 1 parameter 'rescale' for when a user want to define Beta on (a,b) rather than (0,1). If you don't like it, I can change to xmin, xmax parameters, but then the user needs to specify 4 parameters, and I feel like (a,b) is the same as (xmin, xmax) at that time. I'm still unclear on that case. Moreover, I used np.random.beta(1e-4, 1) because the function doesn't take 0. I don't know why, even numpy v1.14 says it takes non-negative but it just doesn't work for me. ` def init(self, a, b, rescale=False, scale=None):

    if 0 < a:
        self.a = a
    else:
        raise Exception("a must be positive")

    if 0 < b:
        self.b = b
    else:
        raise Exception("b must be positive")

    self.rescale = rescale

    params = {
        "a" : a,
        "b" : b
        }
    super().__init__(params, stats.beta, False)
    self.xlim = (0, 1) # Beta distributions are not defined for x < 0 and x > 1

def draw(self):
    """A function that takes no arguments and
        returns a single draw from the Beta distribution."""

    if self.rescale:
        return (self.a + (self.b - self.a)*np.random.beta(1e-4, 1))
    else:
        return np.random.beta(self.a, self.b)`
kevindavisross commented 6 years ago

No, this won't work. You are confusing the shape parameters of the Beta with the parameters that define the range of possible values. The Beta distribution on (0,1) has two shape parameters, which are commonly denoted alpha (abbreviated a) and beta (abbreviated b). The requirements are that both a>0 and b>0.

Do NOT confuse the shape parameters with the parameters that define the range of possible values, xmin and xmax. (xmin and xmax play a role similar to a and b in Uniform(a,b), NOT the role of a and b in Beta(a,b).) Perhaps it would be less confusing in code to rename a as alpha and b as beta, but that would require changes in many places.

You do need two parameters, xmin and xmax, not just their difference. Beta with xmin=3, xmax=5 does not have the same range of possible values as xmin=13, xmax=15.

Your distribution will need 4 parameters: Beta(a, b, xmin, xmax), default for xmin=0, for xmax=1. The key line will be

self.xmin + (self.xmax - self.xmin)*np.random.beta(self.a, self.b)