- Added
wild,wild_low, andwild_highoptions tolargest_count()evaluation. These allow specifying outcomes as wild, combining with any outcomes, outcomes that they are lower than, and outcomes that they are higher than respectively. standard_poolrenamed tod_pool, leaving a deprecation warning.
Major modifications to map(repeat) Markov process flow.
- Now requires Python >= 3.12 (from 3.10).
Rerollsplit into separateRerollandRestartsymbols with different meanings inmap(repeat)andAgain.- In
map(repeat),Rerollrerolls only the current stage, whileRestartrestarts the entire process. - With
again_count,Rerollrerolls any dice over the limit until they don't rollAgain, whileRestartrestarts the entire process. - With
again_depth,Rerollrerolls the last depth if going over the limit, whileRestartcannot be used withagain_depth.
- In
Breakoutcome wrapper that can be returned from a function sent tomap(repeat)in order to immediately terminate the Markov process.map(repeat)now defaults torepeat=None;repeatis now explicitly incompatible withAgain.- Remove separate
time_limitparameter tomap();repeatnow always returns early if fully absorbed. again_endcan now be used withagain_count..weightless()method for multiset generators that sets the quantity for all possible multisets to 1.- New
product_of_counts()multiset evaluation. - More specific overloads for
map,tupleize,vectorize. - Rename
commonize_denominator()toharmonize_denominator()and add optional weight parameter. - Fix immediate absorption case for
map(repeat='inf').
- Change
max_pair_lowest()andmax_pair_highest()tomax_pair_keep()andmax_pair_drop(). - Add remaining operators to the
max_pairmethods. - Rename
reroll_to_pool(mode)options from 'highest' to 'high'. - Allow
max_timeargument to be omitted fromtime_to_sumif all outcomes are positive. - Allow lexicographic comparison between
Vectors of different length. - Prevent unevaluated expressions from being returned from a
@multiset_function.
- Breaking change:
difference(but not other operations) now haskeep_negative_countsparameter again, which defaults toFalse.
- Experimental
sort_pair_keep_while()andsort_pair_drop_while()multiset ops.
- Breaking change:
any()multiset evaluation renamed and inverted toempty(). - Breaking change:
sort_match()renamed tosort_pair(),maximum_match_highest()renamed tomax_pair_highest()and similar forminimum_match_highest(). - Add
extraparameter tosort_pair. - Rename several
whichandtargetparameters tooutcomes. - Make
max_rerollsanddepthparameters ofreroll_to_pool()keyword-only, and add default outcomes to reroll. - Experimental
leximin()andleximax()multiset evaluations. - Experimental
versus_any()andversus_all()multiset operations.
- Fix internal
starinmap_and_time(). - Experimental
mean_time_to_absorb().
- Add
staroption formultiset_function. - Add
kwargsoption formapand similar functions. - Skip optimization for multideal.
- Fix
Vectorcomparisons so that they properly serve the dual purpose of element-wise comparison and truth value comparison. - Fix multideal null pops.
- Experimental
Deck.deal_groups().
- Fix default
next_state_keyidentification.
- Adjusted behavior of
MultisetEvaluatorcaching between calls toevaluate()depending on the value ofnext_state_key.- By default,
next_state_keywill only cache if the evaluator is called directly (i.e. not inside a@multiset_function). - If a full
next_state_keyis given, it will cache inside@multiset_function, provided the other contents agree. - The special value
NoCachewill disable caching.
- By default,
- Support argumentless evaluations.
- Some typing fixes.
Major rewrite of multiset handling. Things will be more unstable than usual for a while.
MultisetEvaluator.next_state()now has an explicit parameter with the order in which outcomes are seen.- Optional
MultisetEvaluator.initial_state()method. MultisetEvaluator.initial_state()andfinal_state()now get the following parameters:- The order in which outcomes are / were seen.
- All outcomes that will be / were seen.
- The sizes of the input multisets, if inferrable with counts being non-negative.
- Non-multiset keyword arguments that were passed to
evaluate().
ascendinganddescendingvariants ofnext_stateno longer exist.- Instead,
raise UnsupportedOrder()if you don't like the current order. The other order will automatically be tried. - This can be done in
initial_state()(recommended),next_state(), orfinal_outcome().
- Instead,
- Multiset operator order is now always attached to the evaluator side rather than the generator side.
- Unless the operator modifies the generator in-place, but in this case both orders will certainly be supported.
MultisetEvaluatorcan optionally provide a key for persistent caching.- Some existing expressions and evaluators now take advantage of inferred multiset sizes.
- In particular,
keep()andsorted_match().
- In particular,
MultisetExpression.count()renamed tosize().@multiset_functionnow implements late binding like a standard Python method. (Though I still recommend using only pure functions.)@multiset_functionnow accepts variadic arguments.@multiset_functionnow accepts non-multiset keyword arguments.@multiset_functionnow works with joint evaluations where some sub-evaluations don't contain parameters.- Hopefully better
@multiset_functionperformance. Alignmentclass is retired.- Deprecated
depth=Noneis removed fromDie.reroll(). - Multiset generators now always produce a single count value, with
MultiDealnow producing tuple-valued counts rather than taking up multiple argument slots. - Multiset computations now try to infer multiset sizes if the counts are non-negative. This improves the applicability of
keepandsort_matchexpressions. - Cartesian products (e.g.
tupleize) now returnRerollif any argument isReroll.
- Add
Population.append()and.remove()methods. - Improve
Vectorperformance. - Adjusted typing of mixture expressions.
- Experimental
Walleniusnoncentral hypergeometric.
- Fix joint evaluations and
@multiset_functioninteraction withnext_state_ascendingandnext_state_descending.
- Overhauled multiset expressions. This allows expressions that are given to an evaluator to have the evaluation persistently cached. This makes the caching behavior more consistent: a single expression will be cached in the final evaluator (e.g.
(a - b).unique().sum()would be cached in thesumevaluator), and@multiset_functioncreates an evaluator like any other. Unfortunately, this did come at some performance cost for@multiset_function. I have some ideas on how to claw back some of the performance but I haven't decided whether it's worth the complexity. - Instead of specifying
order()for an evaluator, you can now implementnext_state_ascending()and/ornext_state_descending(). Alignmentnow has a denominator of 1.keep(),isdisjoint(),sort_match(), andmaximum_match()operations now treat negative incoming counts as zero rather than raising an error.- Add
Population.group_by()method to split a population into a "covering" set of conditional probabilities.Population.group_by[]can also be used to group by index or slice.
- Move
split()fromDieto the basePopulationclass. - Straight-related multiset operations can now choose between prioritizing low and high outcomes.
- Store original names of
@multiset_functionparameters.
- Deprecate
depth=Nonein favor ofdepth='inf'. - Add experimental
format_inverse()option that formats probabilities as "1 in N".
- Add
pointwise_max,pointwise_minarguments to take pointwise maximum or minimum of CDFs. - Add
Die.time_to_sum()method. - Fix identification of absorbing states in the presence of
extra_argsinmap_and_time(). - Add
time_limitparameter tomap(). repeatparameter now uses'inf'to request the absorbing distribution rather thanNone.
- Breaking change: outcomes with zero quantities are removed when constructing
DieandDeck.- Functions and methods relating to zero-quantities are removed:
align(),align_range(),Population.has_zero_quantities(),Die.trim(),Die.set_range(),Die.set_outcomes(). - You can use
consecutive()orsorted_union()to get an appropriate superset of sets of outcomes.
- Functions and methods relating to zero-quantities are removed:
- Breaking change:
MultisetEvaluator.alignment()is renamed toMultisetEvaluator.extra_outcomes().MultisetEvaluator.range_alignment()is renamed toMultisetEvaluator.consecutive().- The
Alignmentclass is no longer public.
- Breaking change:
Deck.multiply_counts()andPopulation.scale_quantities()are replaced/renamed toPopulation.multiply_quantities()etc. - Add
Deck.sequence()andDie.sequence()method. - Add
Population.pad_to_denominator()method. - Move
zero()andzero_outcome()fromDietoPopulation. @operator now sums left-to-right.- Remove old
compairevaluation. min_outcome()andmax_outcome()free functions can now be called using a single iterable argument.- Forward algorithm now has a persistent cache.
- Add skip optimization for single deals with keep tuples.
- Pools now only skip dice, not outcomes. This is a bit slower in some cases but provides more consistent iteration order.
- Add shared evaluator instances for some built-in evaluator for caching.
- Simplify determination of outcome order for multiset evaluations.
- Simplify implementation of generator unbinding.
- Fix
extra_argsexpansion formap_and_time.
- Providing only a
dropargument tolowest()orhighest()will now keep all other elements rather than just the first non-dropped element. depthargument toDie.reroll()is now mandatory.tupleoutcomes are now auto-tupleized again duringDieconstruction.- Add
Die.stochastic_round()method. - Add
Die.reroll_to_pool()method. - Add
Die.keep()method. This works asMultisetGenerator.keep()with an implicit sum. - Add
percentoption toPopulation.probability. - Add new
again_countmode for handlingAgain, which limits the total number of dice. - Improved ability to
keepfrom both ends for certain types of multiset expressions. - Rename
funcparameters tofunction. MultisetExpression.order()is now public.- Improved sorting for
Symbols; now compares counts in alphabetical order. - Experimental
sort_match,maximum_match_highest,maximum_match_lowestexpressions.sort_matchreplaces thecompairevaluations. - Experimental
all_straights_reduce_countsandargsortmultiset evaluations. - Breaking change:
nearest,quantity,quantities,probability,probabilities,keep_countsno longer have separate variants for each comparison; instead, they now take a comparison argument.quantitiesandprobabilitiesnow accept a comparison argument but no longer accept a list of outcomes.
- Rename
keep_countstokeep_counts_ge. Addle,lt,gt,eq, andnevariants. - Add
count_subsetevaluation that counts how many times the right side is contained in the left. - Add
ImplicitConversionErroras subclass ofTypeError. - Add binary multiset operators to
Deck. - Add
modulo_counts/%operation on multisets. - Rebind generators and evaluate when fully bound non-generator expressions are given to an evaluator.
- Fix
Symbolsintersection. - Fix argument order in
__rfloordiv__.
- Fix
Symbolsoperator priority withPopulation,AgainExpression. - Added experimental
map_to_poolandexplode_to_poolmethods. - Split
compairintocompare_ltetc. - Constructing a mixture of dice now effectively uses the old
lcm_jointmethod, which reduces the denominator more aggressively.
- Experimental
Symbolsclass representing a multiset of characters. marginalsnow forwards__getattr__to outcomes, as long as the attribute name doesn't begin with an underscore.- Operators on expressions now keep negative counts by default. The
keep_negative_countsargument is retired. - Add unary
-forMultisetExpression. MultisetExpression.isdisjoint()now raises an error for negative counts.- Small performance optimization for
Vector. Population.marginalsis no longer aSequence, since the mixins don't make sense.Mappings are now properly excluded fromPopulation.common_outcome_length.- Fixed quoting in
reprfor populations.
- Add
z(n), which produces a die that runs from 0 ton - 1inclusive. - Add
Population.to_one_hot(), which converts the die or deck to a one-hot representation. - Add
Die.mean_time_to_sum(), which computes the mean number of rolls until the cumulative sum is greater or equal to the target.
- Fix non-fully-bound case of
MultisetEvaluator.evaluate(). - Add
defaultargument tolowest(), highest(), middle(). - Add
Population.entropy().
mean(),variance(), etc. now return an exactfractions.Fractionwhen possible. (Note thatFractions only support float-style formatting from Python 3.12.)- Rename
disjoint_uniontoadditive_union. - Add
keep_negative_countskeyword argument to+, -, &, |binary operators for multiset expressions (defaultFalse). - Symmetric difference (
^) for multiset expressions is now a straight absolute difference of counts. - Add unary
+operator for multiset expressions, which is the same askeep_counts(0).
Improve some error messages.
Fix a bug in MultisetExpression.keep_outcomes() and drop_outcomes() regarding unbinding variables.
MultisetExpression.map_counts()now accepts multiple arguments.MultisetExpression.keep_outcomes()anddrop_outcomes()now accept an expression as an argument.MultisetExpression.highest_outcome_and_count()now returns the min outcome if no outcomes have positive count.
highest,lowest, andmiddlecan now take a single iterable argument.- Add
all_straightsevaluation. all_countsandall_straightsnow output sizes in descending order.- Harmonize method and free function versions of
map. Both now allow extra arguments and repeat. - Rename
filter_countstokeep_counts. expandevaluator now allows order to be set.- Experimental
compairevaluation.
- Add HTML and BBCode options for population formatting.
- Renamed
applytomapand the decorator version tomap_function. - The above now uses
guess_star. - Add default of 1 die for
Die.pool().
Fix mathematical bug in Die.reroll for limited depth.
Retired implicit elementwise operations on tuples. This is now handled by a new explicit Vector container.
cartesian_product() is replaced by two new functions: tupleize() and vectorize().
These compute the Cartesian product and produce a tuple or Vector respectively (or a die/deck thereof).
The Again symbol is now used without parentheses. The name of the underlying type is now AgainExpression.
die.zero() now multiplies all outcomes by 0 to determine the zero-outcome rather than using the default constructor.
This allows it to work with Vector's elementwise operations while still producing the expected result for
tuples, strings, etc.
Retired the linear algorithm for comparators for Die. While the quadratic algorithm is slower, it allows for non-bool outputs.
die.tuple_len() renamed to common_outcome_length. Now applies to all sized outcome types.
- Counts type
Qsis now invariant with more detailed typing inDeal.
Incremented two versions because I messed up the last version number.
commonize_denominatorvisible at top level.
- Rename
from_cumulative_quantitiestofrom_cumulativeand allow die inputs. - Mark
multiset_functionexperimental again and note more caveats in the docstring.
- Add missing variants of
nearestandquantitiesmethods. - Add optional
outcomesargument toquantitiesandprobabilitiesmethods.
mapand similar functions will attempt to guessstar.- Changed
positive_onlyparameter toexpression.all_countstofilter. - Changed implementation of bound generators to unbind expressions rather than dynamically splitting.
- Retired
apply_sortedand variants. - Add
outcome_functiondecorator similar toapply. - Add
map_countsexpression. Rerollin tuple outcomes and joint evaluations causes the whole thing to be rerolled.
- Tuple outcomes can now be compared with single outcomes.
- Add
.keep, .highest, lowest, .middlevariants ofapply_sorted. - Recommend
multiset_functionbe used as a decorator, addupdate_wrapper. - Add
keep_outcomes, drop_outcomesmethods to expressions. - Add
anyevaluation to expresions.
Comparisons on dice with tuple outcomes are now performed elementwise.
Testing GitHub workflows.
Expanded multiset processing with multiset expressions.
OutcomeCountGenerator,OutcomeCountEvaluatorrenamed toMultisetGenerator,MultisetEvaluator.multiset_functionis an easy way to create joint evaluators.Poolindexing is now relative rather than absolute.- Renamed
pool.sorted_roll_countstopool.keepandpool.keep_tuple. Dieversions ofsum_highestetc. renamed to justhighest; these always return dice.MultisetExpression(including generators likePool) havehighest()returning an expression.Dieoperators now does mixed vector-scalar binary operations by broadcasting the scalar.- Add
middle()methods. - Remove
*generatorsargument fromevaluator.order(),evaluator.final_outcome(). *generatorsargument ofevaluator.alignmentreplaced with the union of all generator outcomes.- Removed suits.
- Stop using
__class_getitem__, which is intended for typing only.
Reworked built-in generators and evaluators.
- Generators now support multiset operations. These include:
- Multiset comparisons (
<, <=, >, >=, ==, !=, isdisjoint), which produceDie[bool]. - Multiset operators (
+,-,|,&,^) which produce wrapped generators. - A suite of chainable count adjustments, including
multiply_counts,divide_counts,filter_counts, andunique.
- Multiset comparisons (
- Rename
median_lefttomedian_lowetc. - Generators and evaluators are now paramterized by count type as well.
- Move concrete evaluators to a submodule.
- Fixed weighting bug in
__matmul__when the left die has an outcome of 0. - Retired the names
standardandbernoulli. These will be justdandcoinrespectively. applynow acceptsPoolarguments, which will haveexpand()called on them.- Reinstate automatic Cartesian product in
Populationconstruction. if_elsenow runs in two stages.
- Incremental sorting for
all_matching_setsto reduce state space. lowest()andhighest()now actually visible.- Improved checking for tuple outcome sortability and types.
Prepend sum_ to OutcomeCountGenerator versions of highest and lowest.
Expanded typing, particularly in terms of parameterizing types.
DieandDeckconstructors now expect exactly one nesting level, e.g. a Sequence of outcomes.- Removed
Die.bool(). **kwargsreplaced with explcitagain_depth,again_end. RemovedOutcomeCountEvaluator.final_kwargs().- Split
include_stepsversion ofDie.map()into amap_and_timemethod. - Split
include_outcomeversion ofbest_matching_setandbest_straightinto separate methods. - Rename
keep_highestandhighesttosum_highest; add justhighestfor taking the single highest. - Same for
lowest. - Added
cartesian_product(), took this functionality out of theDieconstructor for now. - Added
OutcomeCountGenerator.all_matching_sets().
Die.sub()renamed toDie.map().Die.map()can now include the number of steps taken until absorption.Die.reroll_until()renamed toDie.filter().wildsarguments marked experimental, pending decision on how ordering should affect them.- Only tuples get separate columns in tables and not
strorbytes. - Non-recursive algorithm for
Again()handling.
- Nested lists are now allowed in the
Die()constructor. - Single outcomes can be sent to the
Die()constructor without wrapping them in a list. - Same for sending a die to the
Pool()constructor. - Add
Die.probabilities_lt(),Die.probabilities_gt()methods. - Add
wildsargument tocontains_subset()andintersection_size()methods. - Removed
extra_diceargument fromDie.sub(). - Added
sub()method toDeck, though with less features than theDieversion. sum()method of generators now has asuboption that maps outcomes before summing.expand()method of generators now has auniqueoption that counts duplicates only once.- Forwarding of
kwargstoDie()replaced with explicit arguments. - Add comparators to
Again. - Experimental absorbing Markov chain analysis for
Die.sub(depth=None).
- Added
one_hotfunction. - Added experimental suit generator that wraps a generator and produces counts for all suits for each value.
- Retired
denominator_method. - Renamed
max_depthparameters to justdepth. - Binary operators delegate to
Again's behavior. - Only single outcomes implicity convert to
Die. marginalsis now a Sequence, and can be iterated over, unpacked, etc.Die.sub()now expands extra die arguments into their outcomes.
Fix contains_again checking of sequences.
New feature: Again(), a placeholder that allows to roll again with some modification.
**kwargsare forwarded to the constructor of the yielded or returned die forsub,if_else,reduce,accumulate,apply,apply_sorted.- Add optional
final_kwargsmethod to evaluators. - Rename
max_depthparameter ofsub()torepeat.
- Rename
Die.reduce()toDie.simplify()to avoid confusion with the free functionreduce(). - Rename
OutcomeCountEvaluator.direction()toorder()and add explicitly namedOrderenums. - Add
is_in,count, andcount_inmethods to dice. - Add built-in evaluators as convenience functions of
OutcomeCountGenerator.
- Fixes to
max_depth=Nonecase ofsub(). - This is now marked experimental.
- Pass
starparameter tosub()to recursive calls.
sub()withmax_depth=Nonenow handles "monotonic" transitions with finite states. Full absorbing Markov chain calculation still under consideration.sub()no longer accept sequence input.- Some minor formatting fixes.
- Standardize outcome count of
bernoulli/coinand comparators. standard_poolnow accepts adictargument.post_roll_countsrenamed again tosorted_roll_counts.apply_sortedcan be subscripted to set thesorted_roll_counts.- Pools are no longer resizable after creation.
Die.pool()now has mandatory argument, now accepts a sequence argument to setsorted_roll_counts.
More renaming, experimental sample() methods.
- Both
DieandDecknow havequantitiesrather thanweight,dups, etc. - Many
Diemethods moved to base class and are now available toDeck. - "Eval" is now the full word "Evaluator".
- Parameter and method names are no longer prefixed with "num_".
reduce_weightsrenamed back toreduce.Decks can be formatted likeDie.- Allow formatting 0-1 probability.
- Experimental
sample()methods forOutcomeCountGeneratorandOutcomeCountEvaluator.
Development of deck API.
- Separate
Dealclass fromDeck, roughly analogous toPoolvs.Die. Dealcan now output multiple hands. The counts for each hand are provided in order toeval.next_state.comb_rownow uses iterative rather than recursive memoization. This will prevent some stack overflows.Pools are not permitted to be constructed using a rawDieorDeckargument.reduceargument ofDie.equals()renamed toreduce_weights.
Significant API changes, experimental deck support.
- Experimental
Deckclass. API still very unstable. Pools,Decks, and internal Alignment now have a common base classOutcomeCountGen.EvalPoolrenamed toOutcomeCountEval.DieandDeckare now properMappings withkeys,values, anditems.- The above view types can also be accessed like sequences.
- A
Dieis now always considered notequal()to non-Die. die[]now works like a dict. Usemarginals[]to marginalize dimensions.Die,Pool, andDecknow take a single sequence or mapping argument rather than a variable number of arguments.Die,Pool, andDecknow all have the same name for the second argument:times.count_dicerenamed topost_roll_counts. No longer acceptsNone, use[:]instead.- Linear algorithm for comparators on
Die. - Improvements to internal
Countclass. - Add
clear_pool_cachefunction. - Forward
*extra_argsforreroll, reroll_until, explode.
Added type hints. Now requires Python 3.10 or later.
Other changes:
- Add
apply_sorted()method. - Add
Die.set_range(). standard()/d()argument is now positional-only.
Reinstate alternate internal EvalPool algorithm, which provides better performance in some cases.
- Added a new
EvalPool.alignment()method. This allows to specify an iterable of outcomes that should always be seen bynext_stateeven if they have zero count. - The free function
d()is now simply an alias forstandard(). - Removed
Die.d(). - The
@operator now casts the right side to aDielike other operators. - Some internal changes to
EvalPoolalgorithm.
The data of a die resulting from == or != is lazily evaluated.
This saves computation in case the caller is only interested in the truth value.
EvalPool favors the cached direction more.
Major reworking of pool construction.
- Public constructor is now just
Pool(*dice). - In particular, no more
truncate_minortruncate_maxarguments. - Pools can be of arbitrary dice, though non-truncative sets of dice will have lower performance. There is some performance penalty overall.
apply()called with no arguments now callsfunconce with no arguments.
- Removed
Die.keep(). UseDie.pool(...).sum(). highest/lowestreturns empty die if any of the input dice are empty.
- Free-function form of
lowest,highestnow selects between algorithms for better performance and generality. - Removed
die.lowest,die.highest`. die.min_outcome,die.max_outcomeno longer take arguments beyondself.- No more (public)
repeat_and_sum, as this is redundant with@anddie.keep(). - No more public
die.keep_lowest_single(),die.keep_highest_single(). count_dicearguments are now keyword-only.die.zero()no longer reduces weights to 1.- Update PyPi classifiers.
- Removed
min_outcomeparameter from die construction. - Operations on tuple outcomes are now performed recursively, to match the fact that die expansion on construction is recursive.
- Renamed
Die.reduce()toDie.reduce_weights(). - Added
reduce()andaccumulate()functions analogous to the functions of the same name from functools/itertools. - Add CSV output.
- Renamed
Die.markdown()toDie.format_markdown(). - Added
starparameter tosub,explode,reroll,reroll_untilmethods. If set, this unpacks outcomes before giving them to the supplied function. - Added experimental
JointEvalclass for performing two evals on the same roll of a pool.
- Operators other than
[]are performed element-wise on tuples. - Rename
DicePoolto justPool. Merge the old factory function into the constructor.
- Fix denominator_method='reduce' in die creation.
- Fix outcomes consisting of empty tuple
(). apply()with no dice produces an empty die.
Retired the EmptyDie / ScalarDie / VectorDie distinction.
- There is now only one
Dieclass; it behaves similarly to howScalarDieused to. - There is no more
ndim. - The
[]operator now forwards to the outcome, acting similar to whatVectorDie.dim[]used to do. - Removed
PoolEval.bind_dice(). It was cute, but I'm not convinced it was worth spending API on.
- This will probably be the last version with a
VectorDiedistinction. - Dice cannot have negative weights.
VectorDiecannot be nested inside tuple outcomes.
- Die and dict arguments to
Die()are now expanded, including when nested. - Add
Die.if_else()method, which acts as a ternary conditional operator on outcomes. - Dice are now hashable.
==and!=return dice with truth values based on whether the two dice have identical outcomes and weights. ndimnow uses singletonsicepool.Scalarandicepool.Empty.
EvalPool.eval()can now be provided with single rolls of a pool. This can be a dict-like mapping individual die outcomes to counts or a sequence of individual die outcomes.EvalPool.next_state()can not expect that the outcomes it sees are consecutive, though they are guaranteed to be seen in monotonic order.FindBestRun()no longer assumes consecutive outcomes.- Added
DicePool.sample(). - Added
die.truncate(). min_outcomes,max_outcomes(for pool definitions) renamed totruncate_min,truncate_max.- Removed
die.getitem(). DicePoolis no longer iterable, since there isn't an intuitive, unambiguous way of doing so.align_range()now only operates on scalar outcomes.
- Renamed from
hdrollertoicepool. - Primary repository is now https://github.com/HighDiceRoller/icepool.
- Only
tuples becomeVectorDie. - Weights of 10^30 or above are not shown in tables by default.
- Add
max_depthparameter tosub(). If set toNonethis seeks a fixed point. - Add
'reduce'option fordenominator_methodparameters. - Cache results of
repeat_and_sum().
- Add
ndimkeyword argument tod(). - Removed
hitting_time()method; it seems too niche to commit to. - Several arguments are now keyword-only.
- Fix to
reroll_until()for vector dice.
- Add
VectorDie.all()andVectorDie.any(). - More fixes to
ndimcalculation.
EmptyDie(a die with no outcomes) is now its own class.mix()along with its weights argument is folded into theDie()factory.- Fixes to
ndimcalculation. apply(), EvalPool.final_outcome()can now return dice,hdroller.Reroll, etc.- Center
Ellipsiswhen indexing a pool can now work on undersized pools, rather than being an error. - Fix
lcm_weighteddenominator method. len(die)is now the same asdie.num_outcomes()again.- Slicing a die now refers to (sorted) outcome indexes.
- Dimension slicing is now
VectorDie.dim[select].
Die()now takes a variable number of arguments. A sequence provided as a single argument will be treated as a single outcome equal to that sequence. To have one outcome per item in the sequence, the sequence must be unpacked into multiple arguments.min_outcomeandndimargs toDie()are now keyword-only.- Non-integers are now allowed for
count_dice. Use at your own risk. - The third argument to a
count_diceslice, if provided, changes the size of the pool. - Up to one
Ellipsis(...) may now be used incount_dice. This allows the tuple option to adapt to differently-sized pools. VectorDieoutcomes are now unpacked when providing them to callable arguments inreroll(),explode(),split().if_else()is now a method ofScalarDierather than a free function.- Fixed the invert operator.
- Rerolls in pools,
mix(), andsub()are now triggered by a sentinel valuehdroller.Reroll(rather thanNone). - Single-
intindexes forcount_diceand pool[]operator now produce a die rather than a pool, in analogy to sequence indexing. However, note that this is absolute relative to the whole pool rather than relative to any previous indexing. EvalPoolcan now iterate in both directions even if one ofmax_outcomesormin_outcomesis given, though at lower efficiency in the disfavored direction.- Default such direction changed back to ascending.
- Re-implemented
clip(). - The minimum outcome of
highest()is equal to the highest minimum outcome among all input dice and likewise forlowest(). This will prevent introducing zero-weight outcomes where they did not exist before.
- Pool
max_outcomesormin_outcomesoutside the range of the fundamental die is now an error. - Pools no longer automatically shrink the die to fit
max_outcomesormin_outcomes. This is to guarantee a predictable iteration order. - Improved
str(die)formatting. VectorDieoutcomes are automatically converted to tuples.ScalarDienow hasndim='scalar'rather thanndim=False.- Add
standard_pool()function for easy creation of standard pools. - Removed
reroll_lt(), etc. as they weren't enough faster thanreroll(func)to justify spending extra space.
- Removed
initial_state()in favor of usingNoneas the initial state. - Added simple
pool.eval()method. Nonenow rerolls inEvalPool.- Fix
trunc,floor,ceil. - Various improvements to pool algorithm.
- Add some thresholding methods for dice.
- Max/min renamed to highest/lowest.
- Improve empty die handling.
- Improved
VectorDiestring formatting. - Disabled
reverse().
- Faster algorithm for keeping the single highest/lowest.
- Fix
from_sweights().
- Fix
max()andmin()casting to dice.
- Capitalize
Die()andPool()factory methods. PoolEvalrenamed toEvalPool.- Implemented
min_outcomesfor pools. Direction is now determined byEvalPool. - Allow dice with zero weights or zero outcomes.
BaseDiesubclasses are nowScalarDieandVectorDie.==and!=compare outcomes again. Dice are no longer hashable by the standardhash().- Rewored
Pool()arguments. - Added several methods.
- Fix
weights_le()etc. set_outcomes()is now public.
min_outcome(),max_outcome()now accept multiple dice.- Fix slice range going below zero.
num_diceis now an optional parameter forkeep*()andpool(). Exactly one out ofnum_dice,min_outcomes, andmax_outcomesshould be provided.- Removed right-side cast for
@operator, as it leads to confusion with either other operator casting ord()casting. - Replaced key-value sequence option for
die()with a sequence of weight-1 outcomes. - Add
has_zero_weights()method to dice. align(),align_range()are now public.
- Remove numpy install dependency.
- Use the
@operator andd()instead of*for "roll the die on the left, then roll that many dice on the right and sum". *operator now multiplies.- Add
/operator. - Add
median_left(), median_right(), ppf(), ppf_left(), ppf_right(), sample(), cmp(), sign().
No longer numpy-based. Major changes:
- API completely reworked.
- Weights are Python
ints. This decreases performance but produces all exact results. - New
MultiDieclass representing multivariate distributions. PoolScorerclasses merged to a singlePoolEvalclass.
This will most likely be the last numpy-based version.
- Pool scorers skip zero-weight outcomes.
- Removed
__bool__since zero-weight dice are no longer allowed.
- Pool scorers can now return
Nonestates, which drops the state from evaluation, effectively performing a full reroll. - Operations that result in no remaining weight (e.g. rerolling all outcomes) now return None.
- Dice can no longer be constructed with zero total weight.
- The
Die()constructor now auto-trims. Die._align()is now private and no longer makes all the dice the same weight.- Fixed
Die.explode()weighting. - Cleaned up unused functions.
- Optimize
Pool.pops()by immediately removing all the dice if there are no left in the mask. Die.rerollnow tracks weights properly.
- Implemented new keep/pool algorithms, which make heavy use of caching. The
keep*()function signatures changed. Dieis now hashable.- Empty
Dieis now an error. - Removed weight normalization.
- Added
%and//operators toDie. - Renamed
ccdftosffollowingscipy's naming.
best_setnow queries thescore_functo determine possible outcomes, which allows more flexibility.
Die.align()andDie.trim()are now public.- Optimize
keep()algorithm by skipping to results after passing the last kept die. - Add
best_set()method for computing sets of matching dice.
The major change in this version is a new roll-and-keep algorithm. This can keep arbitrary indexes, as well as supporting dissimilar dice as long as they share a common "prefix" of weights.
Initial version.