prodigy.distribution.linear_guards

Exact normalisation of linear guards (normalize_guard()).

A comparison whose sides are built from variables, constants, +, multiplication by a constant and division by a constant is linear. It is compared exactly over the rationals, e.g. 1/2*x < 2 holds if and only if x < 4. As everywhere, / is rational division, so x/2 <= 1 means x <= 2 and not floor division. The comparison is rewritten into an equivalent guard with natural numbers only:

  • with one variable it becomes x < n, x <= n, x = n, x > n or x >= n for a natural number n, or true or false (x = 3/2 never holds), which every engine can filter even on infinite distributions;

  • with several variables and a constant that is not a natural number or a division, both sides are multiplied by the least common denominator, e.g. 1/2*x + 1/3*y < 1 becomes 3*x + 2*y < 6;

  • without variables it becomes true or false.

Subtraction is not linear here, as x - y on natural numbers is truncated at 0 by some engines. A guard with a constant that is not a natural number but that is not linear (e.g. x*y < 1/2 or x % 2 = 1/2) is rejected on every engine, as its value depends on how an engine treats non-natural intermediate results.

LinearForm

A linear combination of variables; the key “” holds the constant.

alias of Dict[str, Fraction]

normalize_guard(condition, variables)[source]

An equivalent guard with natural numbers only if condition is a linear comparison (see the module documentation), or None if there is nothing to normalise.

Raises a ValueError if condition is a comparison with a constant that is not a natural number but not linear.

Parameters:
  • condition (VarExpr | BoolLitExpr | NatLitExpr | RealLitExpr | UnopExpr | BinopExpr | CategoricalExpr | SubstExpr | TickExpr | FunctionCallExpr | InferExpr | SampleExpr)

  • variables (Set[str])

Return type:

VarExpr | BoolLitExpr | NatLitExpr | RealLitExpr | UnopExpr | BinopExpr | CategoricalExpr | SubstExpr | TickExpr | FunctionCallExpr | InferExpr | SampleExpr | None