Model specification

The specification schema, the operator-overloaded DSL that lowers to it, and the compiler that binds a spec to a network.

Schema

Declarative, serializable model specification.

A ModelSpec describes a linear-in-parameters utility as an ordered list of Term objects. Each term contributes to one parameter’s design column, and the utility is \(Z\beta\) with one coefficient per distinct parameter name.

A term’s regressor is built from named link attributes (a product of several gives an interaction), an optional elementwise transform, an optional scale, and an optional segmentation indicator on a per-variant covariate. All parts transform the data; the parameter enters linearly.

class micropurc.spec.schema.Segment(covariate, op, threshold)[source]

Bases: object

Indicator gate 1[covariate op threshold] on a per-variant covariate.

Variables:
  • covariate (str) – Name of the per-variant covariate to test.

  • op (str) – Comparison, one of OPS.

  • threshold (float) – Right-hand side of the comparison.

Parameters:
covariate: str
op: str
threshold: float
to_dict()[source]

Return a plain-dict representation.

Return type:

dict[str, Any]

class micropurc.spec.schema.Term(parameter, attributes, transform='identity', power=1.0, segment=None, scale=1.0)[source]

Bases: object

One additive utility term mapped to a single parameter.

Variables:
  • parameter (str) – Name of the coefficient \(\beta\). Terms sharing a name sum into the same design column.

  • attributes (tuple[str, ...]) – Named attributes multiplied together (interaction).

  • transform (str) – Elementwise transform applied to the attribute product.

  • power (float) – Exponent used when transform == "power".

  • segment (micropurc.spec.schema.Segment | None) – Optional covariate indicator gating the term.

  • scale (float) – Constant multiplier applied to the regressor.

Parameters:
parameter: str
attributes: tuple[str, ...]
transform: str = 'identity'
power: float = 1.0
segment: Segment | None = None
scale: float = 1.0
to_dict()[source]

Return a plain-dict representation, omitting fields left at default.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Build a term from its dict representation.

Parameters:

d (dict[str, Any])

Return type:

Term

class micropurc.spec.schema.ModelSpec(terms=<factory>)[source]

Bases: object

An ordered collection of utility terms.

Variables:

terms (list[micropurc.spec.schema.Term]) – The terms, in the order they were declared.

Parameters:

terms (list[Term])

terms: list[Term]
parameters()[source]

Distinct parameter names in order of first appearance.

This order fixes the design’s column order, so it also fixes the order of the estimated coefficients.

Return type:

list[str]

covariates()[source]

Distinct segmentation covariate names, in order of first appearance.

Return type:

list[str]

to_dict()[source]

Return a plain-dict representation.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Build a spec from its dict representation.

Parameters:

d (dict[str, Any])

Return type:

ModelSpec

to_json(indent=2)[source]

Serialize to a JSON string.

Parameters:

indent (int)

Return type:

str

classmethod from_json(source)[source]

Load a spec from a JSON string or a file path.

A Path is always read from disk. A str is read from disk when it names an existing file and parsed as JSON text otherwise, so a document containing a newline is always treated as text.

Parameters:

source (str | Path)

Return type:

ModelSpec

DSL

Symbolic builders for model specifications.

A small operator-overloaded DSL that lowers to ModelSpec. Example:

U = (beta("time") * attr("travel_time")
     + beta("fee_low") * attr("fee") * seg("group", "==", 0)
     + beta("logdist") * log(attr("length")))
spec = U.to_spec()

Each summand is beta(name) * <attribute expression> [* seg(...)], optionally scaled by a constant. Attribute expressions may be a product of attributes (interaction) and may carry a scalar transform (log, power, standardize).

class micropurc.spec.dsl.AttrExpr(name, transform='identity', power=1.0)[source]

Bases: object

A named attribute, optionally with an elementwise transform.

Variables:
  • name (str) – Attribute name, resolved against the network at compile time.

  • transform (str) – One of the transforms the schema accepts.

  • power (float) – Exponent used when transform == "power".

Parameters:
name: str
transform: str = 'identity'
power: float = 1.0
class micropurc.spec.dsl.Beta(name)[source]

Bases: object

A parameter placeholder; multiply by an attribute expression to form a term.

Parameters:

name (str)

name: str
class micropurc.spec.dsl.ProductExpr(factors)[source]

Bases: object

A product (interaction) of attribute expressions.

Parameters:

factors (tuple[AttrExpr, ...])

factors: tuple[AttrExpr, ...]
class micropurc.spec.dsl.TermExpr(parameter, attributes=(), segment=None, scale=1.0)[source]

Bases: object

A utility term under construction: a parameter, attribute factors, a segment.

Variables:
Parameters:
parameter: str
attributes: tuple[AttrExpr, ...] = ()
segment: Segment | None = None
scale: float = 1.0
to_spec()[source]

Lower a single-term utility to a ModelSpec.

Return type:

ModelSpec

to_term()[source]

Lower to a schema Term.

A term needs at least one attribute. A transform is carried over only from a single-attribute term, since an interaction leaves the target of the transform ambiguous.

Return type:

Term

class micropurc.spec.dsl.Utility(terms)[source]

Bases: object

A sum of terms; lower it to a ModelSpec.

Variables:

terms (list[micropurc.spec.dsl.TermExpr]) – The summands, in declaration order.

Parameters:

terms (list[TermExpr])

terms: list[TermExpr]
to_spec()[source]

Lower to a ModelSpec.

Return type:

ModelSpec

micropurc.spec.dsl.beta(name)[source]

A parameter placeholder named name.

Parameters:

name (str)

Return type:

Beta

micropurc.spec.dsl.attr(name)[source]

A named link attribute.

Parameters:

name (str)

Return type:

AttrExpr

micropurc.spec.dsl.seg(covariate, op, threshold)[source]

A covariate indicator 1[covariate op threshold].

Parameters:
Return type:

Segment

micropurc.spec.dsl.log(a)[source]

Natural-log transform of an attribute.

Parameters:

a (AttrExpr)

Return type:

AttrExpr

micropurc.spec.dsl.power(a, p)[source]

Raise an attribute to the power p.

Parameters:
Return type:

AttrExpr

micropurc.spec.dsl.standardize(a)[source]

Standardize an attribute to zero mean and unit variance.

The moments are taken over every entry of the attribute, pooling the attribute-variant axis when there is one.

Parameters:

a (AttrExpr)

Return type:

AttrExpr

Compiler

Compile a ModelSpec into a design matrix.

The compiler binds attribute names to data and evaluates each term into the design. Attribute values may be static (columns of network.Z) or vary across an attribute-variant axis (supplied via variant_attrs, e.g. a time-of-day-dependent link time); segmented terms additionally gate on per-variant covariates.

Without variant structure the design is a single matrix Z of shape (L, K). With attribute variance and/or segmentation it is a stack of per-variant matrices z_variants of shape (n_variants, L, K) selected by trip_variant, or a lazy design (materialize=False). K is the number of distinct parameters.

class micropurc.spec.compile.CompiledDesign(parameters, Z=None, z_variants=None, trip_variant=None, lazy=None)[source]

Bases: object

A compiled design ready for estimation.

Exactly one of Z (no variant structure), z_variants (variant structure, materialized), or lazy (materialize=False) is set.

Variables:
  • parameters (list[str]) – Ordered parameter names; column k of the design is the regressor for parameters[k].

  • Z (numpy.ndarray | None) – Design matrix, shape (L, K) when there is no variant structure.

  • z_variants (numpy.ndarray | None) – Per-variant designs, shape (n_variants, L, K).

  • trip_variant (numpy.ndarray | None) – Variant index per trip, shape (N,).

  • lazy (micropurc.core.lazy_design.LazyDesign | None) – Lazy design, set when materialize=False.

Parameters:
parameters: list[str]
Z: ndarray | None = None
z_variants: ndarray | None = None
trip_variant: ndarray | None = None
lazy: LazyDesign | None = None
micropurc.spec.compile.compile_design(spec, network, *, variant_covariates=None, covariate_names=None, trip_variant=None, variant_attrs=None, variant_attr_index=None, materialize=True)[source]

Compile a model specification against a network.

Parameters:
  • spec (ModelSpec) – The model specification.

  • network (Network) – Network supplying named static link attributes.

  • variant_covariates (ndarray | None) – Per-variant covariate values, shape (n_variants, C). Required if the spec has segmented terms.

  • covariate_names (list[str] | None) – Names of the covariate columns, length C.

  • trip_variant (ndarray | None) – Variant index per trip, shape (N,). Required whenever the design is variant-specific.

  • variant_attrs (dict[str, ndarray] | None) – Optional mapping name -> array (n_attr_var, L) of attributes whose values vary across an attribute-variant axis.

  • variant_attr_index (ndarray | None) – Attribute-variant row per variant, shape (n_variants,). Required if variant_attrs is given.

  • materialize (bool) – If True, build explicit design matrices; if False, build a LazyDesign.

Returns:

The compiled design.

Raises:

ValueError – If the variant structure inputs required by the spec are missing or mutually inconsistent.

Return type:

CompiledDesign