roundSeqPreservingSum

maelzel.distribute.roundSeqPreservingSum(seq, maxdelta=1, maxsolutions=1, ensureDirection=True)[source]

Round sequence preserving its integer sum

Find for each element in seq. an integer within the range x-maxdelta : x+maxdelta so that the sum of these integers is the same as the rounded sum of seq.

Note

This function is implemented using contraint programming. The search space grows very quickly as the seq grows so it can take a long time for large sequences.

Parameters:
  • seq (list[float]) – a list of numbers

  • maxdelta – the max. deviation the integer can have from the original item

  • maxsolutions – the max. number of solutions to generate before finding the best from those solutions. All solutions generated comply with the constraints given; the returned solutions as the one which follows the original seq. as closest

  • ensureDirection – if True, ensure that for any two numbers a and b, if a < b then a_rounded <= b_rounded (and similarly if a > b)

Return type:

list[int]

Returns:

a list of integers representing the original seq. If there are no solutions an empty list is returned

Example

>>> from maelzel import distribute
>>> from emlib.iterlib import pairwise
>>> import matplotlib.pyplot as plt
>>> parts = distribute.partitionExpon(40, 5, exp=3)
>>> parts
array([ 6.0952381 ,  6.19047619,  6.85714286,  8.66666667, 12.19047619])
>>> round(sum(parts))
40
>>> intparts = distribute.roundSeqPreservingSum(parts, maxsolutions=10)
>>> intparts, sum(intparts)
[6, 6, 7, 8, 13], 40