Linear Parts

Unlike other discrete choice tools (notably Biogeme), which allow for the creation of a variety of arbitrary non-linear functions, Larch relies heavily on linear functions.

class larch.core.LinearComponent(data="", param="", multiplier=1.0, category=None)

A combination of a parameter and data.

This class represents a single term of a linear function, i.e. a parameter multiplied by some data. The data may be a single column of raw data from a data Fountain, or it may be some prescribed function of raw data (e.g. logarithm of cost, or cost divided by income); the principal requirement is that the data function contains only data and no parameters to be estimated, other than the single linear coefficient.

Parameters:
  • param (str or ParameterRef) – The name of, or reference to, a parameter.
  • data (str or DataRef) – The name of, or reference to, some data. This may be a raw column in a data Fountain, or an expression that can be evaluated, including a number expressed as a string. To express a constant (i.e. a parameter with no data) give 1.0.
  • multiplier (float) – A convenient method to multiply the data by a constant, which can be given as a float instead of a string.
  • category (None or int or string or tuple) – Some LinearComponent’s apply only to certain things.
data

The data associated with this LinearComponent, expressed as a DataRef. You can assign a numerical value or a plain str to this attribute as well.

param

The parameter associated with this LinearComponent, expressed as a ParameterRef. You can assign a plain str that names a parameter to this attribute as well. Parameter names are case-sensitive.

In addition to creating a LinearComponent using the regular constructor, you can also create these objects by multiplying a ParameterRef and a DataRef. For example:

>>> from larch.roles import P,X
>>> P.TotalCost * X.totcost
LinearComponent(data='totcost', param='TotalCost')
class larch.core.LinearFunction

This class is a specialize list of LinearComponent, which are summed across during evaluation.

Instead of creating a LinearFunction through a constructor, it is better to create one simply by adding multiple LinearComponent objects:

>>> from larch.roles import P,X
>>> u1 = P.TotalCost * X.totcost
>>> u2 = P.InVehTime * X.ivt
>>> u1 + u2
<LinearFunction with length 2>
  = LinearComponent(data='totcost', param='TotalCost')
  + LinearComponent(data='ivt', param='InVehTime')
>>> lf = u1 + u2
>>> lf += P.OutOfVehTime * X.ovt
>>> lf
<LinearFunction with length 3>
  = LinearComponent(data='totcost', param='TotalCost')
  + LinearComponent(data='ivt', param='InVehTime')
  + LinearComponent(data='ovt', param='OutOfVehTime')

You can also add a ParameterRef by itself to a LinearFunction,

>>> lf += P.SomeConstant
>>> lf
<LinearFunction with length 4>
  = LinearComponent(data='totcost', param='TotalCost')
  + LinearComponent(data='ivt', param='InVehTime')
  + LinearComponent(data='ovt', param='OutOfVehTime')
  + LinearComponent(data='1', param='SomeConstant')

Although not just data by itself:

>>> lf += X.PlainData
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NotImplementedError: Wrong number or type of arguments...

Several pre-selected multiple-term functions are available in larch.util.piecewise.

larch.util.piecewise.log_and_linear_function(basevar, baseparam=None)

Create a two term LinearFunction for log plus linear.

The resulting function looks like \({ \beta }_1 X + { \beta }_2 \log ( 1 + X )\).

Parameters:
  • basevar (str) – The variable to use as the base variable.
  • baseparam (str or None) – The base parameter name. If not given, basevar is used.
Returns:

The two term linear function.

Return type:

LinearFunction

Examples

>>> from larch.util.piecewise import log_and_linear_function
>>> f = log_and_linear_function('Aaa')
>>> print(f)
  = P('Aaa') * X('Aaa')
  + P('logAaaP1') * X('log1p(Aaa)')
>>> f2 = log_and_linear_function('Aaa','Bbb')
>>> print(f2)
  = P('Bbb') * X('Aaa')
  + P('logBbbP1') * X('log1p(Aaa)')
larch.util.piecewise.polynomial_linear_function(basevar, powers, baseparam=None, invertpower=False, scaling=1)

Create a polynomial LinearFunction.

The resulting function looks like \({ \beta }_1 X^{n_1} + { \beta }_2 X^{n_2} + { \beta }_3 X^{n_3} + ...\).

Note that the function is polynomial only in the data, and the powers are given explicitly. The resulting function is still a linear-in-parameters function of data (and transformed data), and not actually a non-linear function of parameters that will be estimated.

Parameters:
  • basevar (str) – The variable to use as the base variable.
  • powers (iterable of numbers) – The powers of the polynomial. Can be integer or floats. Explicitly include 1 to include a linear component.
  • baseparam (str or None) – The base parameter name. If not given, basevar is used.
  • invertpower (bool) – If True, the inverse (i.e., 1/N) of the powers is used.
  • scaling (float) – A scaling term. The basevar is divided by this term before the power is taken, which can help prevent high power terms becoming unreasonably large.
Returns:

The polynomial linear function.

Return type:

LinearFunction

Examples

>>> from larch.util.piecewise import polynomial_linear_function
>>> f = polynomial_linear_function('Aaa', [1,2,3])
>>> print(f)
  = P('Aaa') * X('Aaa')
  + P('Aaa_2') * X('(Aaa)**2')
  + P('Aaa_3') * X('(Aaa)**3')
>>> f2 = polynomial_linear_function('Aaa', [1,2,3], invertpower=True)
>>> print(f2)
  = P('Aaa') * X('Aaa')
  + P('Aaa_2') * X('(Aaa)**(1/2)')
  + P('Aaa_3') * X('(Aaa)**(1/3)')
larch.util.piecewise.gross_piecewise_linear_function(basevar, breaks, smoothness=1, baseparam=None)

Smoothed piecewise linear function with gross breakpoints.

class larch.core.LinearBundle

A LinearBundle represents a bundle of linear terms that, when combined, form a complete linear relationship from data to a modeled factor.

ca

The ca attribute is a single LinearFunction that can be applied for all alternatives. Depending on the data source used, the data used in this function might need to be exclusively from the idca Format data (e.g. for DB), or it could be a combination of idca Format and idco Format data (e.g. for DT)

co

The co attribute is a mapping (like a dict), where the keys are alternative codes and the values are LinearFunction of idco Format data for each alternative. If an alternative is omitted, the implied value of the LinearFunction is zero.

As a convenince, the LinearBundle object also provides __getitem__ and __setitem__ functions that pass through to the co attribute.