moptipyapps.utils package

Some shared utilities.

Submodules

moptipyapps.utils.sampling module

Some utilities for random sampling.

The goal that we follow with class Distribution is to have clearly defined integer-producing random distributions. We want to be able to say exactly how to generate some random numbers.

A distribution can be sampled using the method sample(). Each distribution has a mean value, which either may be an exact value or an approximate result, that can be obtained via mean(). Sometimes, distributions can be simplified, which is supported by simplify().

>>> from moptipy.utils.nputils import rand_generator
>>> from statistics import mean
>>> rnd = rand_generator(0)
>>> const = Const(12.3)
>>> const
Const(v=12.3)
>>> const.mean()
12.3
>>> const.sample(rnd)
12.3
>>> normal = Normal(1, 2.0)
>>> normal
Normal(mu=1, sd=2)
>>> x = [normal.sample(rnd) for _ in range(200)]
>>> x[:20]
[1.2514604421867865, 0.7357902734173962, 2.280845300886564, 1.2098002343060794, -0.07133874632222192, 1.7231901098189695, 3.6080000902602745, 2.8941619262584846, -0.4074704716139852, -1.530842942092105, -0.24654892507470438, 1.0826519586944872, -3.6500615492776687, 0.5624166721349085, -1.4918218945061303, -0.4645347094069032, -0.08851796571461978, 0.3673996872616909, 1.8232610727482657, 3.085026738885355]
>>> mean(x) / normal.mean()
1.0305262793198813
>>> exponential = Exponential(3)
>>> x = [exponential.sample(rnd) for _ in range(200)]
>>> x[:20]
[1.3203895772033505, 1.152983246827425, 4.527545171626064, 5.080441711712409, 0.6498200242245252, 3.408652958826374, 2.842677620245357, 2.1132194336022, 3.5838508479713393, 1.2223825336486978, 2.8454397976498504, 0.8653980789905962, 0.19572166348792452, 3.2506725793229854, 0.9426446058446336, 3.246902386754473, 10.294412603282666, 5.275683923067543, 0.49517363091492944, 0.2982336402218482]
>>> mean(x) / exponential.mean()
1.088857332669081
>>> gamma = Gamma(3.0, 0.26)
>>> gamma
Gamma(k=3, theta=0.26)
>>> x = [gamma.sample(rnd) for _ in range(200)]
>>> x[:20]
[1.1617763743292708, 1.305755109480284, 0.7627948403389954, 1.2735522637897285, 0.7742951665621697, 1.074233520618276, 0.6324661100546898, 1.4627037699922791, 0.5739033567160827, 0.5555065636904546, 0.629236234283296, 0.3666171387296996, 0.3780976936750937, 0.9511433672028858, 1.2607313263258062, 1.4442096466925938, 0.48758642085808085, 1.247724803721524, 1.9359140456080306, 1.3935246884396764]
>>> mean(x) / gamma.mean()
0.962254253258444
>>> Gamma.from_alpha_beta(2, 0.5)
Erlang(k=2, theta=2)
>>> Gamma.from_alpha_beta(2.5, 0.5)
Gamma(k=2.5, theta=2)
>>> Erlang.from_alpha_beta(2, 0.5)
Erlang(k=2, theta=2)
>>> erlang = Erlang(1.0, 0.26)
>>> erlang
Erlang(k=1, theta=0.26)
>>> x = [erlang.sample(rnd) for _ in range(200)]
>>> x[:20]
[0.29911329228981776, 0.3630768060267626, 0.14111385731543394, 0.0745673280234536, 0.029950507989979877, 0.04741877104350835, 0.38599089026561223, 0.047919114170390194, 0.06921557868837301, 0.4066084140331242, 0.07170887998378667, 0.022061870233843223, 0.04904717644388396, 0.32082097064821674, 0.001884448999141546, 0.6687964040577958, 0.060598863807579915, 0.21491377996577304, 0.23088301776258766, 0.23667780086315618]
>>> mean(x) / erlang.mean()
0.9212193955320179
>>> uniform = Uniform(10.5, 17)
>>> uniform
Uniform(low=10.5, high=17)
>>> x = [uniform.sample(rnd) for _ in range(200)]
>>> x[:20]
[11.235929257903324, 13.89459856391694, 14.196833332199233, 13.871456027849515, 14.485310406702393, 16.20468251006836, 13.7773314921396, 12.964459911549145, 12.167722566772781, 12.49450317595701, 14.145245846833722, 15.669920217581366, 13.367286694558258, 10.764955127505994, 11.723004274328007, 11.089239517262232, 12.666732191193558, 14.948448277461127, 14.339645757381653, 14.803829334728565]
>>> mean(x) / uniform.mean()
0.9968578545459643
>>> choice = Choice((Const(2), gamma, normal))
>>> choice
Choice(ch=(Const(v=2), Gamma(k=3, theta=0.26), Normal(mu=1, sd=2)))
>>> x = [choice.sample(rnd) for _ in range(200)]
>>> x[:20]
[0.5499364190576, -0.10428920251005325, 2, 2, 0.44263544084840273, 0.6088189450771303, 2, 2, 2, 2, -0.32003290715104904, 2, 0.6165299227577784, 1.0445083345086352, 2, 2, 2, -0.5970322857539738, -1.6672705710198277, 2]
>>> mean(x) / choice.mean()
0.9849730453309948
>>> lower = AtLeast(2, normal)
>>> lower
AtLeast(lb=2, d=Normal(mu=1, sd=2))
>>> x = [lower.sample(rnd) for _ in range(200)]
>>> x[:20]
[2.9715155848474772, 3.407503493034132, 2.59634461519561, 2.0472458472897714, 3.9865670827840334, 2.015117730344058, 2.0316584714999935, 5.36625737470408, 3.042848158343226, 3.390407444638451, 4.5503184215686, 3.7682459882073007, 2.0539760253651305, 2.134886147372958, 2.500182239395479, 2.891402111997337, 2.7393826524907228, 2.3449577842364766, 2.9043074694017195, 4.7173482582723825]
>>> mean(x) / lower.mean()
1.0178179732075965
>>> interval = In(1, 10, gamma)
>>> interval
In(lb=1, ub=10, d=Gamma(k=3, theta=0.26))
>>> x = [interval.sample(rnd) for _ in range(200)]
>>> x[:20]
[1.3488423972739083, 1.0929631399361601, 1.681162621901135, 1.655614926246918, 1.041948891842002, 2.0773395958990175, 1.3338891374921853, 1.2478964188175743, 1.9417070894505217, 1.3990572178987266, 1.1216118870312337, 1.0641160239253207, 2.131253600219639, 1.0337453883221577, 1.396499618416345, 1.9865175145136038, 1.2555473269031396, 1.4412027583435465, 1.320740351247919, 1.0407411942999665]
>>> mean(x) / interval.mean()
1.0256329849020747
>>> erlang2 = Gamma.from_k_and_mean(3, 10)
>>> erlang2
Erlang(k=3, theta=3.3333333333333335)
>>> erlang2.mean()
10
>>> x = [erlang2.sample(rnd) for _ in range(200)]
>>> x[:20]
[10.087506399523226, 12.928131914870168, 12.330250639007767, 5.305123692562998, 21.085037136404374, 6.6603691824173135, 2.961302890492059, 9.810557147180853, 8.051620919921454, 8.750329405836668, 3.9511445189935763, 5.570300668751883, 16.70132947692463, 7.831425379483914, 11.154757962484842, 8.78943102381046, 8.395847820234795, 16.42251602814587, 17.1628992966332, 9.684008648356015]
>>> mean(x) / erlang2.mean()
1.022444624140316
>>> AtLeast.greater_than_zero(Gamma(1, 0.5))
AtLeast(lb=5e-324, d=Exponential(eta=1))
>>> AtLeast.greater_than_zero(Gamma(2, 0.5))
Erlang(k=2, theta=0.5)
>>> AtLeast.greater_than_zero(Gamma(2.5, 0.5))
Gamma(k=2.5, theta=0.5)
class moptipyapps.utils.sampling.AtLeast(lb, d)[source]

Bases: Distribution

A distribution that is lower-bounded.

>>> AtLeast(5, Const(7))
AtLeast(lb=5, d=Const(v=7))
>>> AtLeast(5, AtLeast(8, Const(17)))
AtLeast(lb=8, d=Const(v=17))
>>> AtLeast(8, AtLeast(5, Const(17)))
AtLeast(lb=8, d=Const(v=17))
d: Distribution

the inner distribution to sample from

classmethod greater_than_zero(d)[source]

Ensure that all samples are greater than zero.

Parameters:

d (int | float | Distribution) – the original distribution

Return type:

Distribution

Returns:

a distribution which is always greater than zero

lb: int | float

the inclusive lower bound

sample(random)[source]

Sample from the lower-bounded distribution.

Parameters:

random (Generator) – the random number generator

Return type:

int | float

Returns:

the result

simplify()[source]

Try to simplify this distribution.

Return type:

Distribution

Returns:

a simplified version of this distribution

>>> AtLeast(1, Uniform(3, 4)).simplify()
Uniform(low=3, high=4)
>>> AtLeast(3.5, Uniform(3, 4)).simplify()
Uniform(low=3.5, high=4)
class moptipyapps.utils.sampling.Choice(ch)[source]

Bases: Distribution

A class representing a uniform choice.

>>> Choice((Uniform(1, 2), Uniform(3, 4))).simplify()
Choice(ch=(Uniform(low=1, high=2), Uniform(low=3, high=4)))
>>> Choice((Uniform(1, 2), Uniform(1.0, 2))).simplify()
Uniform(low=1, high=2)
>>> Choice((Uniform(1, 2), Choice(
...     (Const(1), Uniform(1, 2))))).simplify()
Choice(ch=(Uniform(low=1, high=2), IntConst(v=1), Uniform(low=1, high=2)))
ch: tuple[Distribution, ...]

the choices

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample from the uniform distribution.

Parameters:

random (Generator) – the random number generator

Return type:

int | float

Returns:

the result

simplify()[source]

Try to simplify this distribution.

Return type:

Distribution

Returns:

a simplified version of this distribution

class moptipyapps.utils.sampling.Const(v)[source]

Bases: Distribution

A constant value.

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample the constant integer.

Parameters:

random (Generator) – the random number generator

Return type:

int | float

Returns:

the integer

simplify()[source]

Simplify this constat.

Return type:

Distribution

Returns:

the simplified constant

>>> Const(1.5).simplify()
Const(v=1.5)
>>> Const(1.0).simplify()
IntConst(v=1)
v: int | float

the constant value

class moptipyapps.utils.sampling.Distribution[source]

Bases: object

A base class for distributions.

mean()[source]

Get the mean or approximate mean of the distribution.

Some distribution overwrite this method to produce an exact computed expected value or mean. This default implementation just computes the arithmetic mean of 10’000 samples of the distribution. This serves as baseline approximation for any case where a closed form mathematical definition of the expected value is not available.

Return type:

int | float

Returns:

the mean or approximated mean

sample(random)[source]

Sample a random number following this distribution generator.

Each call to this function returns exactly one number.

Parameters:

random (Generator) – the random number generator

Return type:

int | float

Returns:

the number

simplify()[source]

Try to simplify this distribution.

Some distributions can trivially be simplified. For example, if you have applied a range limit (In) to a constant distribution (class:Const), then this can be simplified to just the constant. If such simplification is possible, this method returns the simplified distribution. Otherwise, it just returns the distribution itself.

Return type:

Distribution

Returns:

a simplified version of this distribution

class moptipyapps.utils.sampling.Erlang(k, theta)[source]

Bases: Gamma

The Erlang distribution.

class moptipyapps.utils.sampling.Exponential(eta)[source]

Bases: Distribution

A class representing an exponential distribution.

eta: int | float

the exponential distribution parameter

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample from the Exponential distribution.

Parameters:

random (Generator) – the random number generator

Return type:

float

Returns:

the result

class moptipyapps.utils.sampling.Gamma(k, theta)[source]

Bases: Distribution

A class representing a Gamma distribution.

Here, k is the shape and theta is the scale parameter. If you use a parameterization with alpha and beta, you need to create the distribution using from_alpha_beta() instead. The reason is that shape = 1/beta, see https://www.statlect.com/probability-distributions/gamma-distribution.

classmethod from_alpha_beta(alpha, beta)[source]

Create a Gamma distribution from alpha and beta.

Parameters:
  • alpha (int | float) – the alpha parameter

  • beta (int | float) – the beta parameter

Return type:

Distribution

Returns:

the distribution

classmethod from_k_and_mean(k, mean)[source]

Create the Gamma distribution from the value of k and a mean.

Parameters:
Return type:

Distribution

Returns:

the distribution

k: int | float

the shape parameter

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample from the Gamma distribution.

Parameters:

random (Generator) – the random number generator

Return type:

float

Returns:

the result

simplify()[source]

Try to simplify this distribution.

A Gamma distribution may simplify to either an Erlang or an Exponential distribution, depending on its parameters. If the k is 1, then it is actually an Exponential distribution. If k is an integer, then the distribution is an Erlang distribution.

  1. https://www.statisticshowto.com/gamma-distribution

  2. https://www.statisticshowto.com/erlang-distribution

Return type:

Distribution

Returns:

a simplified version of this distribution

theta: int | float

the scale parameter

class moptipyapps.utils.sampling.In(lb, ub, d)[source]

Bases: Distribution

A distribution that is lower and upper-bounded.

>>> In(1, 10, Const(6))
In(lb=1, ub=10, d=Const(v=6))
>>> In(1, 10, In(5, 12, Const(6)))
In(lb=5, ub=10, d=Const(v=6))
>>> In(1, 10, AtLeast(6, Const(6)))
In(lb=6, ub=10, d=Const(v=6))
d: Distribution

the inner distribution to sample from

lb: int | float

the inclusive lower bound

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample from the lower-bounded distribution.

Parameters:

random (Generator) – the random number generator

Return type:

int | float

Returns:

the result

simplify()[source]

Simplify this distribution.

Return type:

Distribution

Returns:

the simplified distribution

>>> In(-3, 4, Const(3)).simplify()
Const(v=3)
>>> ii = In(-10, 10, Uniform(3, 20))
>>> ii
In(lb=3, ub=10, d=Uniform(low=3, high=10))
>>> ii.simplify()
Uniform(low=3, high=10)
ub: int | float

the exclusive upper bound

class moptipyapps.utils.sampling.IntConst(v)[source]

Bases: IntDistribution, Const

An integer constant.

mean()[source]

Get the arithmetic mean.

Return type:

int

sample(random)[source]

Get the integer constant value.

Return type:

int

class moptipyapps.utils.sampling.IntDistribution[source]

Bases: Distribution

A base class for integer distributions.

sample(random)[source]

Sample a random number following this integer distribution generator.

Each call to this function returns exactly one number.

Parameters:

random (Generator) – the random number generator

Return type:

int

Returns:

the number, which always will be integer

simplify()[source]

Try to simplify this integer distribution.

Return type:

IntDistribution

Returns:

a simplified version of this integer distribution

class moptipyapps.utils.sampling.Normal(mu, sd)[source]

Bases: Distribution

A class representing a normal distribution.

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

mu: int | float

the expected value and center of the distribution

sample(random)[source]

Sample from the normal distribution.

Parameters:

random (Generator) – the random number generator

Return type:

float

Returns:

the result

sd: int | float

the standard deviation of the distribution

class moptipyapps.utils.sampling.Uniform(low, high)[source]

Bases: Distribution

A class representing a uniform distribution.

high: int | float

the highest permitted value

low: int | float

the lowest permitted value

mean()[source]

Get the mean of this distribution.

Return type:

int | float

Returns:

the mean

sample(random)[source]

Sample from the uniform distribution.

Parameters:

random (Generator) – the random number generator

Return type:

float

Returns:

the result

moptipyapps.utils.sampling.distribution(d)[source]

Get the distribution from the parameter.

Parameters:

d (int | float | Distribution) – the integer value or distribution

Return type:

Distribution

Returns:

the canonicalized distribution

>>> distribution(7)
IntConst(v=7)
>>> distribution(3.4)
Const(v=3.4)
>>> distribution(Choice((Const(4.0), )))
IntConst(v=4)

moptipyapps.utils.shared module

Some shared variables and constants.

moptipyapps.utils.shared.SCOPE_INSTANCE: Final[str] = 'inst'

the instance scope

moptipyapps.utils.shared.moptipyapps_argparser(file, description, epilog)[source]

Create an argument parser with default settings.

Parameters:
  • file (str) – the __file__ special variable of the calling script

  • description (str) – the description string

  • epilog (str) – the epilogue string

Return type:

ArgumentParser

Returns:

the argument parser

>>> ap = moptipyapps_argparser(
...     __file__, "This is a test program.", "This is a test.")
>>> isinstance(ap, argparse.ArgumentParser)
True
>>> "Copyright" in ap.epilog
True

Print the standard csv footer for moptipyapps.

Parameters:
  • _ – the setup object, ignored

  • additional (str | None, default: None) – any additional output string

Return type:

Iterable[str]

Returns:

the comments

>>> for s in motipyapps_footer_bottom_comments(None, "bla"):
...     print(s[:49])
This data has been generated with moptipyapps ver
bla
You can find moptipyapps at https://thomasweise.g
>>> for s in motipyapps_footer_bottom_comments(None, None):
...     print(s[:49])
This data has been generated with moptipyapps ver
You can find moptipyapps at https://thomasweise.g