Skip to content

Commit

Permalink
zero-quantity outcomes are pruned from Die/Deck construction
Browse files Browse the repository at this point in the history
  • Loading branch information
HighDiceRoller committed Sep 12, 2024
1 parent fbd4808 commit 113e994
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 6 deletions.
10 changes: 9 additions & 1 deletion src/icepool/creation_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,12 @@ def merge_weights_lcm(subdatas: Sequence[Mapping[T, int]],
data: MutableMapping[Any, int] = defaultdict(int)
for subdata, subdata_denominator, w in zip(subdatas, subdata_denominators,
weights):
factor = denominator_lcm * w // subdata_denominator if subdata_denominator else 0
if subdata_denominator == 0 or w == 0:
continue
factor = denominator_lcm * w // subdata_denominator
for outcome, weight in subdata.items():
if weight == 0:
continue
data[outcome] += weight * factor
return data

Expand All @@ -122,7 +126,11 @@ def merge_duplicates(subdatas: Sequence[Mapping[T, int]],

data: MutableMapping[Any, int] = defaultdict(int)
for subdata, subdup in zip(subdatas, duplicates):
if subdup == 0:
continue
for outcome, dup in subdata.items():
if dup == 0:
continue
data[outcome] += dup * subdup

return data
5 changes: 5 additions & 0 deletions src/icepool/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,16 @@ def from_rv(rv, outcomes: Sequence[float], denominator: int,
def from_rv(rv, outcomes: Sequence[int] | Sequence[float], denominator: int,
**kwargs) -> 'icepool.Die[int] | icepool.Die[float]':
"""Constructs a `Die` from a rv object (as `scipy.stats`).
This is done using the CDF.
Args:
rv: A rv object (as `scipy.stats`).
outcomes: An iterable of `int`s or `float`s that will be the outcomes
of the resulting `Die`.
If the distribution is discrete, outcomes must be `int`s.
Some outcomes may be omitted if their probability is too small
compared to the denominator.
denominator: The denominator of the resulting `Die` will be set to this.
**kwargs: These will be forwarded to `rv.cdf()`.
"""
Expand Down
3 changes: 3 additions & 0 deletions src/icepool/population/deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def __new__(cls,
times: Sequence[int] | int = 1) -> 'Deck[T_co]':
"""Constructor for a `Deck`.
All quantities must be non-negative. Outcomes with zero quantity will be
omitted.
Args:
outcomes: The cards of the `Deck`. This can be one of the following:
* A `Sequence` of outcomes. Duplicates will contribute
Expand Down
3 changes: 2 additions & 1 deletion src/icepool/population/die.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def __new__(
* Use a dict: `Die({1:1, 2:1, 3:1, 4:1, 5:1, 6:1})`
* Give the faces as a sequence: `Die([1, 2, 3, 4, 5, 6])`
All quantities must be non-negative, though they can be zero.
All quantities must be non-negative. Outcomes with zero quantity will be
omitted.
Several methods and functions foward **kwargs to this constructor.
However, these only affect the construction of the returned or yielded
Expand Down
2 changes: 1 addition & 1 deletion tests/comparator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def test_cmp_len():
assert len(icepool.d6.cmp(0)) == 1
assert len(icepool.d6.cmp(7)) == 1
assert len(icepool.Die([1]).cmp(1)) == 1
assert len(icepool.Die({-1: 0, 0: 0, 1: 0}).cmp(0)) == 3
assert len(icepool.Die({-1: 0, 0: 0, 1: 0}).cmp(0)) == 0


def test_quantity_le():
Expand Down
2 changes: 1 addition & 1 deletion tests/evaluator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_sum_descending_keep_highest():

def test_zero_weight_outcomes():
result = icepool.Die(range(5), times=[0, 1, 0, 1, 0]).highest(3, 2)
assert len(result) == 9
assert len(result) == 3


def sum_dice_func(state, outcome, count):
Expand Down
4 changes: 2 additions & 2 deletions tests/from_cumulative_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ def test_from_rv_norm():
1000000,
loc=die.mean(),
scale=die.standard_deviation())
assert die.probabilities('<=') == pytest.approx(
norm_die.probabilities('<='), abs=1e-3)
assert [die.probability('<=', x) for x in range(600)] == pytest.approx(
[norm_die.probability('<=', x) for x in range(600)], abs=1e-3)

0 comments on commit 113e994

Please sign in to comment.