- The Quantitative Supply Chain Manifesto
- The Lokad test of supply chain performance
- An overview of quantitative supply chain
- Generalized probabilistic forecasting
- Decision-driven optimization
- Economic drivers
- Data preparation
- The Supply Chain Scientist
- Timeline of a typical project
- Project deliverables
- Assessing success
- Antipatterns in supply chain

- Inventory forecasting
- Prioritized ordering report
- Old forecasting input file format
- Old forecasting output file format
- Choosing the service levels
- Managing your inventory settings
- The old Excel forecast report
- Using tags to improve accuracy
- Oddities in classic forecasts
- Oddities in quantile forecasts
- Stock-out's bias on quantile forecasts
- Daily, weekly and monthly aggregations

Home » Resources » Here

Distributions in Envision are practical because they are supported by an entire algebra of distributions. However, in order to generate inventory decisions, it is usually required to transform those distributions back into a

`extend.distrib()`

function can be used for this purpose.`Id`

which identifies the item`Min`

, the lower inclusive boundary of the histogram bucket`Max`

, the higher inclusive boundary of the histogram bucket`Value`

, the value associated with the histogram bucket

For a given item, the grid may contain a series of buckets that represent the entire histogram of the distribution. If the distribution is a

Grids are not as flexible as distributions. In order to achieve the required level of performance, it is frequently not possible to maintain buckets having a width of 1. For this reason, larger buckets are used instead in order to keep the memory requirements of the grid manageable within Lokad. Non-unit buckets complicate calculations that are carried out on grids. Also, by design, grids have

On the other hand, grids are plain

`extend.distrib()`

turns a vector of distributions into a table, as illustrated by the following syntax:
table T = extend.distrib(D) T.Probability = int(D, T.Min, T.Max) show table "Distribution details" with Id T.Min T.Max T.ProbabilityThe argument

`D`

is expected to be a vector of distributions, as typically produced by Lokad's probabilistic forecasting engine. Table `T`

is typed as an extension of the originating table - the implicit `Items`

table in the script above. Table `T`

is populated with three fields:`T.Min`

: the inclusive integral lower boundary of the segment`T.Max`

: the inclusive integral higher boundary of the segment`T.Probability`

: the sum of the distribution over the inclusive range

Despite its name, the

`Probability`

field actually refers to the sum of the distribution over the bucket range, which is returned. Note that this field is not populated by `extend.distrib()`

. In case this field is required, it must be created specifically, as in line 2.For relatively compact distributions, segments have a length of 1, and hence

`T.Min == T.Max`

. However, if the distribution spreads over higher values, segments of length equal to 1 would end up generating possibly millions of lines, which becomes unmanageable. Hence, when dealing with such large-valued distributions, Envision auto-aggregates these distributions around larger segments. Algorithms are therefore fine-tuned to keep the size of the generated tables manageable.By design,

`extend.distrib()`

always singles out the zero segment. As a result, the [0;0] segment always gets its own line in the generated table. This behavior is indeed helpful in many business situations, where zero demand represents an edge case - such as infinite stock cover - which requires some dedicated logic.Then, three additional overloads for

`extend.distrib()`

are provided in order to gain more control over the specific granularity of the generated table.table T = extend.distrib(D, S)The first argument

`D`

is as defined above. The second argument `S`

is expected to be an integral number. When this second argument is present, the generated table always includes two lines dedicated to the two segments [0;0] and [1;S]. Additional segments are auto-generated starting from S+1 as detailed above. When left unspecified, the default value for this argument is zero.In practice, argument

`S`

is frequently defined as the sum of the stock available plus the stock on order. When reordering, only those demand probabilities that exceed the current stock level should be considered.table T = extend.distrib(D, S, M)The arguments

`D`

and `S`

are as defined above. The third argument `M`

is expected to be an integral number. It represents the desired segment length. Thus, the table includes the list of segments [0;0], [1;S], [S+1;S+M] [S+M+1;S+2M] … If `M`

is zero, then the function falls back on auto-sizing the segments.In practice, forcing segments whose length is equal to 1 would possibly lead to performance issues as the size of the table can be arbitrarily large. Thus, Envision has the possibility to fall back on a

`M`

instead. Using a multiple ensures that the As a rule of thumb, we suggest not to use this specific overload unless lot multipliers are involved, and when they

`M`

at zero for any item that does not have a specific lot multiplier.table T = extend.distrib(D, S, M, R)The arguments

`D`

, `S`

and `M`

are as defined above. The fourth argument `R`

is expected to be a non-negative integral number. It represents the desired `T.Max`

is greater or equal to `R`

. When left unspecified, the default value for this argument is zero.In practice, this argument is used to cope with large minimum order quantity (MOQ) constraints that can only be satisfied if the generated distributions are reaching far enough to

As a rule of thumb, we suggest not to use this overload unless there are specific MOQs to be reached, and when this is the case, it is suggested to keep

`R`

as small as possible. A small `R`

value does not prevent table `T`

from reaching higher values, it only ensures that larger values are reached.