Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Expressions

Expressions are used in the problem definition (PD) within the following constraint fields:

  • exprFrom: The starting point for iteration in a constraint sum of type iterateVar.
  • exprTo: The ending point for iteration in a constraint sum of type iterateVar.
  • exprMain: The calculation that is added to the solution score or a resultVar if defined.

Expressions are used to calculate a value and return it. They have no features for looping or control or functional decomposition - they are purely and simply expressions.

Expression Variables

By default, the following variables (constants actually) are available to all expressions:

  • R: The R (resource count) dimension of the atom array.
  • T: The T (time count) dimension of the atom array.
  • S: The S (state count) dimension of the atom array.

Variables declared in the following places can also appear in expressions:

  • iterVars: Variables declared in the iterVars of a constraint sum.
  • resultVar: Result variable declared in a child constraint sum.
  • constants: Any constant define in the constants section of the PD.
  • array: Any name of any array object in the PD.

Expression Operators

The following standard operators are supported in expressions. They are grouped in order of precedence:

  • !, NOT: Not operators. (From 0 to 1 and vice versa.) These are the only unary operators.
  • *, /, %: Multiple, divide, modulo divide.
  • +, -: Add, subtract.
  • <, <=, >, >=, =, !=: Inequality operators. The result of these operators is either 1 or 0.
  • AND, OR: Boolean operators. The result of these operators is either 1 or 0.

Example:

53 / 100 * (2 + 1) > 1.55

Answer:

1.0

Expression Functions

There are several built-in functions and dynamically named array accessors that are supported in expressions. These fall into three categories:

  1. Functions that access the atom array: A and X.
  2. Inequality functions: IQ and EQ.
  3. Array accessor functions named by the array itself.

Expression Functions: Atom Array

As described in the Concepts section of this guide, the atom array can be accessed, or "viewed", as either atoms or bits. In addition, in cases where the atom array is composed of a single column or row, there are short hand functions for not having to specify the 1 dimension.

The following functions are used to access the atom array as atoms:

  • A(r, t): returns the atom state at resource r, time t.
  • Ar(r): assuming there is only a single time column (T = 1), then this will return the atom state at A(r, 0)
  • At(t): assuming there is only a single resource row (R = 1), then this will return the atom state at A(0, t)
  • ANY(r, t): returns 1 or 0 (true or false) if there is a non-zero state at atom r, t. This is used for atom matrices with zero states.

The following functions are used to access the atom array as bits:

  • X(r, t, s): returns 0 or 1 depending on whether bit s of the atom at r, t is set (i.e., the atom state is equal to s).
  • Xr(r, s): assuming there is only a single time column (T = 1), then this will return the bit state at X(r, 0, s)
  • Xt(t, s): assuming there is only a single resource row (R = 1), then this will return the bit state at X(0, t, s)

Expression Functions: Inequality

The two inequality functions are extremely important to the solver. These are fundamentally different than the inequality operators in that they are used by the solver for more than just expression functions - they are used to identify inequalities for multivariable models. Also, while an inequality operator simply returns a 1 or 0 given a condition, the inequality functions return how unequal the variables being compared are, and thus implement the "unconstrained constraint" described in the concepts section.

The two fundamental inequality functions are EQ and IQ (for equality and inequality, respectively) however technically EQ could be represented with an IQ as will be shown shortly. These functions more closely match the declaration in a constraint description. For example, a constraint description that states "variable v must be between 2 and 10" would be captured with a IQ(2, v, 10) expression.

EQ and IQ return a value that is typically multiplied by the penaltyVar defined on the constraint. However, there are cases where the penalty value might be different if the function result is less than vs. greater than the comparison value. In these cases, two additional inequality functions, EQP and IQP are provided that take two additional parameters - the penalty if less than, and the penalty if greater than. In this case, the constraint would not have a penaltyVar as the penalty is defined in the inequality.

  • EQ(v, n): Compares whether n and v are equal. Equality would return 0 while not equal would return the absolute value of the difference. Formally, this would be represented as:

    \( v = n\)

    Therefore, if a constraint description states that some variable must be equal to a value, then this should be defined using the EQ function.

  • IQ(n, v, m): Checks whether v is within (inclusively) the range n to m, in which case 0 is returned, while outside the range would return the distance outside the range. Formally, this would be represented as:

    \( n \le v \le m\)

    Note that either n or m (but not both) can be the infinity symbol ~. For example, the expression IQ(~, v, m) would formally be:

    \( v \le m \)

    Or, the expression IQ(n, v, ~) would be;

    \( v \ge n \)

    In addition, IQ could implement EQ with an expression IQ(n, v, n), but this is for illustrative purposes only.

  • EQP(v, n, pu, po): Same as EQ but has two additional parameters to define the penalty under vs. over, respectively.

  • IQP(n, v, m, pu, po): Same as IQ but has two additional parameters to define the penalty under vs. over, respectively.

Expression Functions: Array Accessors

Arrays are accessed by their name and appear just like functions. In addition, their optional ldimFields can be used as the last parameter. For example, given the array definition below:

  {
    "array": {
      "name": "shift_on_req",
      "file": "array_shift_on_req.json",
      "ldimFields": [
        "shift_on",
        "shift_on_weight"
      ]
    }
  }

And given the follow sample array that this definition refers to:

[
    [
        [
            0.0,
            0.0
        ],
        [
            0.0,
            0.0
        ]
    ]
]

An expression that accesses the array values could be:

(A(r, t) != shift_on_req(r, t, shift_on)) * shift_on_req(r, t, shift_on_weight)

Note that the last parameter of the array accessor refers to one of the ldimFields. In this case, this array is in essence a 2D index into a set of records that each contain two fields.