Implementation of fast biased sampling of discrete values [0, ..., n]
For a concise explanation see https://www.keithschwarz.com/darts-dice-coins/
Parameters:
Name |
Type |
Description |
Default |
weights
|
typing.Union[numpy.array, list]
|
relative weights of the n events, where weights[i] is the relative
statistical weight of event i. The weights do not need to be
normalized.
For an array with length n, generated random values
will be from range(n).
|
required
|
Examples:
Create a VoseAliasSampling instance
>>> from pathpy.processes import VoseAliasSampling
>>> sampler = VoseAliasSampling([1,1,2])
Fast biased sampling in O(1)
>>> [ sampler.sample() for i in range(10) ]
[ 0 2 0 1 2 1 2 1 2 0 2 2 ]
Source code in src/pathpyG/processes/sampling.py
| class VoseAliasSampling:
"""
Implementation of fast biased sampling of discrete values [0, ..., n]
For a concise explanation see https://www.keithschwarz.com/darts-dice-coins/
Args:
weights: relative weights of the n events, where weights[i] is the relative
statistical weight of event i. The weights do not need to be
normalized.
For an array with length n, generated random values
will be from range(n).
Examples:
Create a VoseAliasSampling instance
>>> from pathpy.processes import VoseAliasSampling
>>> sampler = VoseAliasSampling([1,1,2])
Fast biased sampling in O(1)
>>> [ sampler.sample() for i in range(10) ]
[ 0 2 0 1 2 1 2 1 2 0 2 2 ]
"""
def __init__(self, weights: Union[np.array, list]) -> None:
"""
Initializes probability and alias tables
"""
self.n = len(weights)
self.probs = dict()
self.scaled_probs = dict()
self.aliases = dict()
small = list()
large = list()
for i in range(1, self.n + 1):
self.probs[i] = weights[i - 1]
self.scaled_probs[i] = self.n * weights[i - 1]
if self.scaled_probs[i] > 1:
large.append(i)
elif self.scaled_probs[i] <= 1:
small.append(i)
while small and large:
l = small.pop()
g = large.pop()
self.probs[l] = self.scaled_probs[l]
self.aliases[l] = g
self.scaled_probs[g] = self.scaled_probs[l] + self.scaled_probs[g] - 1
if self.scaled_probs[g] < 1:
small.append(g)
else:
large.append(g)
while large:
g = large.pop()
self.probs[g] = 1
while small:
l = small.pop()
self.probs[l] = 1
def sample(self) -> int:
"""
Biased sampling of discrete value in O(1)
Returns: integer value from range(n), where n is the length
of the weight array used to create the instance.
"""
i = np.random.randint(1, self.n + 1)
x = np.random.rand()
if x < self.probs[i]:
return i - 1
else:
return self.aliases[i] - 1
|
__init__
Initializes probability and alias tables
Source code in src/pathpyG/processes/sampling.py
| def __init__(self, weights: Union[np.array, list]) -> None:
"""
Initializes probability and alias tables
"""
self.n = len(weights)
self.probs = dict()
self.scaled_probs = dict()
self.aliases = dict()
small = list()
large = list()
for i in range(1, self.n + 1):
self.probs[i] = weights[i - 1]
self.scaled_probs[i] = self.n * weights[i - 1]
if self.scaled_probs[i] > 1:
large.append(i)
elif self.scaled_probs[i] <= 1:
small.append(i)
while small and large:
l = small.pop()
g = large.pop()
self.probs[l] = self.scaled_probs[l]
self.aliases[l] = g
self.scaled_probs[g] = self.scaled_probs[l] + self.scaled_probs[g] - 1
if self.scaled_probs[g] < 1:
small.append(g)
else:
large.append(g)
while large:
g = large.pop()
self.probs[g] = 1
while small:
l = small.pop()
self.probs[l] = 1
|
sample
Biased sampling of discrete value in O(1)
integer value from range(n), where n is the length
Type |
Description |
int
|
of the weight array used to create the instance.
|
Source code in src/pathpyG/processes/sampling.py
| def sample(self) -> int:
"""
Biased sampling of discrete value in O(1)
Returns: integer value from range(n), where n is the length
of the weight array used to create the instance.
"""
i = np.random.randint(1, self.n + 1)
x = np.random.rand()
if x < self.probs[i]:
return i - 1
else:
return self.aliases[i] - 1
|