Skip to main content

Overview

Constants and Lookup Tables are how you separate a model’s parameters from its logic. Instead of hardcoding values inside expressions, you name them, store them in one place, and reference them from anywhere. Change the named value once, and every expression that references it updates automatically. This matters for three reasons:
  1. Tuning — adjust model parameters without hunting through expressions. Change BASE_PROCESSING_TIME from 60 to 75 and every relevant component follows.
  2. Readabilityshift_efficiency_factor is easier to understand than 0.87 sprinkled across expressions.
  3. Non-technical access — operators and analysts who shouldn’t modify expressions can still tune the model by changing constant values.
Both Constants and Lookup Tables are factory-scoped: they’re shared across every model in the factory. Define them once, reference anywhere.

Constants

A Constant is a named value with a specific type: number, string, or boolean. Each constant has:
  • Name — how expressions reference it (e.g., BASE_CYCLE_TIME)
  • Description — what it represents and what units
  • Typenumber, string, or boolean
  • Value — the actual data
Reference a constant by its name in any expression:
BASE_CYCLE_TIME * shift_efficiency_factor

When to Use a Constant

  • Any value that appears in multiple places. If you find yourself typing 0.87 in several expressions, extract it to a constant.
  • Any value you might want to change between runs or sweep in an experiment. Constants are first-class parameters that experiments can vary systematically.
  • Any value a non-technical stakeholder might need to adjust. Analysts can tune a constant without knowing the expression language.

Managing Constants

Constants are defined in the Library of the Data section, alongside Entities and Lookup Tables. Add, edit, or delete constants there — changes propagate to every model that references them.

Lookup Tables

A Lookup Table is a named key-value table. Query it with LOOKUP(table_name, key) in any expression:
LOOKUP(cycle_times, ENTITY_TYPE)
Each table has a name and a set of rows. Keys are strings; values are numeric or string. If a key isn’t found, LOOKUP returns a type-specific zero (0 for numeric, "" for text, FALSE for boolean) — see Multi-Dimensional Lookups below for details and the default:= override.

When to Use a Lookup Table

  • Values that vary by a categorical attribute. Processing time by product type, yield rate by material, priority weight by customer tier — all natural lookups.
  • Routing and proportional splits. Different entities route differently; store the routing rules in a table rather than deeply nested IF expressions.
  • Data-driven configuration. When the “configuration” of a model is really a set of numbers tied to categories, a lookup table is clearer than encoding the same information across many fields.

Multi-Dimensional Lookups

Lookup tables are multi-dimensional by default — a table can have multiple key columns, and a lookup specifies a value for each. This is how you represent data that varies across two or more axes at once, like “processing time by (product type, station)” or “yield rate by (shift, material class).”
LOOKUP(cycle_times_by_station, ENTITY_TYPE, station_name)
Provide one argument per key column, in the order the table defines them. If no row matches, the lookup returns a type-specific zero: 0 for a numeric-valued table, "" for a text-valued table, FALSE for a boolean-valued table. (LOOKUP doesn’t return null.) Fallback with default:=. Use the default:= keyword argument to specify what to return on no match, instead of the type-specific zero:
LOOKUP(yield_rates, ENTITY_TYPE, shift, default:=0.95)
The default:= keyword argument handles fallbacks directly — no need to wrap the lookup in an IF(). This is the cleanest way to express “the typical value for this attribute, with a sensible fallback when the combination isn’t in the table.” Partial matches. Always provide one argument per key column — no wildcards, no partial matches. A three-column table queried with two keys is an invalid call and the lookup falls through to the default (or the type-specific zero if no default is provided).

Constants vs. Lookup Tables — Which to Use?

  • Single value used in many places → Constant
  • Value that depends on a categorical attribute (type, class, tier) → Lookup Table
  • Needs to be swept in an experiment → Constant (experiments treat constants as parameter axes)
  • Large reference dataset → Lookup Table
It’s common to use both: a constant for a global factor, a lookup for per-type rates, combined in one expression.

Patterns

Processing time by product:
LOOKUP(cycle_times, ENTITY_TYPE) * BASE_PROCESSING_FACTOR
Conditional cost or surcharge:
IF(priority == "rush",
   LOOKUP(rush_surcharges, ENTITY_TYPE),
   LOOKUP(standard_rates, ENTITY_TYPE))
Tunable shift dynamics:
IF(SIM_TIME < SHIFT_1_END,
   BASE_RATE * SHIFT_1_EFFICIENCY,
   BASE_RATE * SHIFT_2_EFFICIENCY)