List of functions

The primary purpose of functions is to extend the capabilities of Envision whenever the basic language syntax would not be sufficient. Below, we list the functions supported by Envision.

Function syntax

The general syntax for functions is:

x = fun(arg1, arg2, arg3, ..., argN) by [Group] sort [Order]

fun will be replaced by the name of the function and arg1, arg2, arg3, ..., argN will be replaced by the arguments passed to the function. All functions operate on vectors.

Only certain functions support the extra options by and sort. While the syntax is similar to the syntax of the aggregators, those functions are not aggregators. The by option is optional, and when it is omitted, it is equivalent to by 1. Both Group and Order support tuples of vectors, that is, multiple vectors delimited by commas. For example:

R = rank() by [A, B] sort [1]

Mathematical functions

Text functions

Calendar functions

Ranking functions

Graph functions

Algebra of ranvars

In the following, given an integer-valued random variable $X: \mathbb{\Omega} \to \mathbb{Z}$, its associated probability distribution $\mathbf{P}(X = k)$ will be referred to as a ranvar. Additional information on the algebra of ranvars is provided in the algebra of ranvars section.

Parametric ranvars

Parametric ranvars can be generated through functions which take a number as an argument - the parameter.

Non-parametric ranvars

Indicators on ranvars

Numeric indicators about ranvars can also be obtained in Envision. If X and Y are independent random variables, with ranvars (probability distributions) R and S respectively, and a and b are integers,

Transformations of ranvars

A ranvar can also be transformed into another ranvar (the total mass of 1 being conserved by the transformation). If X and Y are independent random variables, with ranvars R and S respectively, and a and b are integers,

Algebra of zedfuncs

In Envision, a zedfunc is defined as a function $Z: \mathbb{Z} \to \mathbb{R}$. As an example, stockrwd.m() and pricebrk() return a zedfunc.

Parametric zedfuncs

Zedfuncs can be generated through functions which take a parameter as an argument.

Transformations of zedfuncs

If Z is a zedfunc,

Table creation functions

New tables can be created from existing tables or ranvars:

table T = extend.range(Orders.42)
T.Quantity = Orders.Quantity // implicit extension
show table "T" with T.N, T.Quantity

Advanced functions

cumsub(G.Item, G.Stock, G.Quantity, G.Rank)

Takes 4 vectors belonging to a grid table with:

The function cumsub() explores all bundles by increasing rank, keeping track of the remaining stock for each item. Initially, this stock is defined by the G.Stock vector. For each bundle, the function determines whether there is enough remaining stock to purchase all grid lines in that bundle, based on whether the stock exceeds G.Quantity. If that is the case, then the function decrements the stock for each item, and writes to each grid line the remaining stock for that item. If there is not enough stock to serve the entire bundle - usually because one of the items has run out - then the function does not update the remain stocks and stores for each grid line the value -(S+1) (where S is the remaining stock for that item at that point), to indicate both that the grid line is not purchased (test if G.S < 0) and whether it was that specific line that caused the bundle not to be purchased (test if G.Quantity + G.S + 1 > 0) and by how much (G.Missing = G.Quantity + G.S + 1).

forex(value, Origin, Destination, date)

Returns the amount expressed in the currency Origin into the equivalent amount in the currency Destination according to the historical rates at the specified date. The currencies should be encoded with their canonical three-letter codes. Lokad supports about 30 currencies leveraging the data provided by the European Central Bank. Rates are updated on a daily basis. See also isCurrency() to test the validity of your currency code.

hash(value)

Returns a pseudo-injective hash value between 0 and 2^24-1. This function is typically used to randomly shuffle a dataset by hashing the content of a column, and then sorting against the hashed values.

isCurrency(currencyCode)

Returns true if the text entry passed as an argument is a currency code recognized by the forex() function.

mkuid(X, offset)

Returns a unique number, with unicity maintained across Envision runs. This function is intended to uniquely identify results calculated by Lokad. For example, it can be used to generate a unique purchase order number to be incremented whenever the Envision script is re-executed.

The vector X is ignored, but the UID (unique identifier) is generated as a scalar in the table associated to X. The offset is an optional scalar that represents the starting suffix for for the UID. The generated strings are numbers in the format PPPPPPPAAA, with P as a page number (does not start with 0) that is always strictly increasing, and A as an incremented counter that starts at offset (or 0 if no offset parameter is provided). P has at least 7 digits, A has at least 3.

The UIDs offer three properties.

  1. All UIDs can be parsed as numbers, and those numbers will be different. Keep in mind, however, that UIDs have at least 10 digits, and likely more if each call needs to generate more than 1000.
  2. A UID generated at time T is strictly inferior (in alphabetical order) to a UID generated at time T’ > T.
  3. If all calls generate similar numbers of UIDs (less than 999, or between 1000 and 9999, etc.) then the previous property is also true for the numeric order between UIDs.

solve.moq(…)

An advanced numeric solver for the general MOQ problem (minimal order quantities).

pricebrk(D, P, Prices.MinQ, Prices.P, Stock, StockP)

Returns the zedfunc (i.e. a function $Z: \mathbb{Z} \to \mathbb{R}$) vector of the marginal purchase unit price. See Supplier Price Breaks.

priopack(V, MaxV, JT, B) by [Group] sort [Order]

A simple variant of the bin packing algorithm intended to be used with a purchase prioritization list. Unlike the classic bin packing algorithm, not only do we seek to optimize the bin capacities, but the ordering of the units will also be preserved as much as possible.

ranvar.segment(…)

This call-function is intended to convert time-series into probability distributions (ranvar) by collecting observations over moving windows.

D = ranvar.segment(
  start: Items.Start // first date (inclusive) for each item
  end: Items.End // end date (inclusive) for each item
  step: Items.Step // number, increments in day in-between observation
  horizon: Items.Horizon // number, the length in day of period for each item
  date: Orders.Date  // date for each event
  quantity: Orders.Quantity) // quantity for each event

This function computes, for each item, the ranvar of the sum of event quantities over periods of horizon length, that are entirely between the first and last date for that item. For example, for a start date on Jan 1st, end date on Jan 7th, a horizon of 3 days, and a single event of quantity 5 on Jan 2nd, the observed periods are:

And so the resulting ranvar is 60% Q = 0, 40% Q = 5.

ranvar.periodicr(…)

This is a more general version of ranvar.segment, where the horizon is a ranvar of lengths (e.g. the probability distribution of lead times) and events at the extrema or at the middle of the chosen time interval are equally taken into account:

D = ranvar.periodicr(
  start: Items.Start // first date (inclusive) for each item
  end: Items.End // end date (inclusive) for each item
  horizon: Items.LeadTime // ranvar of lengths in day
  date: Orders.Date  // date for each event
  quantity: Orders.Quantity) // quantity for each event

Indeed, ranvar.periodicr considers an infinite repetition of the input data and sums the event quantities over periods of all possible lengths contained in the horizon ranvar. As a consequence, if we consider the example above and we imagine an additional event of quantity 2 on Jan 7th, ranvar.periodicr with dirac(3) as the horizon would observe the following:

and return the ranvar ~28% Q = 0, ~28% Q = 2, ~28% Q = 5, ~14% Q = 7. For comparison, ranvar.segment with horizon 3 and step 1 would ignore the last two lines of the above list and return 40% Q = 0, 20% Q = 2, 40% Q = 5.

forest.regress(…)

Gives access to a random forest regression algorithm. A training dataset (Example) and an evaluation dataset (Sample) must be provided. These two tables contain the same series of column attributes, for a different set of Id. In addition, the Example table contains a further column called Label, which represents the desired output of the regression function. The Example table shall thus be conceived as a Sample with a Label.

The function syntax is the following:

Sample.Label = forest.regress(
  training: Example.A, Example.B, Example.C // number/Boolean/text
  trainingBow : Example.D // plain text, optional
  label: Example.Label // number
  evaluation: Sample.A, Sample.B, Sample.C // number/Boolean/text
  evaluationBow: Sample.D) // plain text, optional

This call-function returns for each Id a ranvar (probability distribution) representing the quantity Label. Up to 16 different attributes are supported as training and evaluation entries. Of these, 8 at most can be number vectors and 8 at most can be Boolean or text vectors representing categories. Optionally, a text vector of words can be provided as trainingBow and evaluationBow: here the text string is treated as a bag-of-words, and analysed in terms of words occurrences.

smudge(values, present) by [Group] sort [Order]

Takes an incomplete vector of values and a Boolean vector that determines where the valid values are present. It returns a full vector of valid values, which has been completed by spreading valid values into the non-valid ones. More precisely, the output vector is built by looking at every line, group by group (if there is a Group argument) and following the ascending Order, and replacing any non-valid value by the last value that has been seen, or by a default value if no valid value has yet been seen in the group.

stockrwd.m(D, AM), stockrwd.s(D), stockrwd.c(D, AC)

The stock reward functions. These functions are used to build prioritized ordering policy out of the probabilistic forecasts produced by Lokad.