def constrained_random(size, proposal, constraint):
    """
    Generate samples from a random distribution, with constraints

    Parameters
    ----------
    size : int
        Number of samples to draw

    proposal : func
        Function which takes size as input,
        and returns that many random samples

    constraint : func
        Function which takes an array as input,
        and returns a True/False array indicating
        whether each point is allowed

    Returns
    -------
    size draws from the proposal function, all of which pass the
    constraint test
    """
    result = proposal(size)
    bad = ~constraint(result)
    while bad.any():
        result[bad] = proposal(bad.sum())
        bad = ~constraint(result)
    return result