Convert to Flat Normal Form (cpmpy.transformations.flatten_model)
Flattening a model (or individual constraints) into ‘flat normal form’.
In flat normal form, constraints belong to one of three families with all arguments either constants, variables, list of constants or list of variables, and some binary constraints have a canonical order of variables.
Furthermore, it is ‘negated normal’ meaning that the ~ (negation operator) only appears before a Boolean variable (in CPMpy, absorbed in a ‘NegBoolView’), and it is ‘negation normal’ meaning that the - (negative operator) only appears before a constant, that is a - b :: a + -1*b :: wsum([1,-1],[a,b])
The three families of possible constraints are:
Base constraints: (no nesting)
Boolean variable |
|
|
Boolean operators |
|
|
Boolean implication |
|
|
Boolean equality |
|
|
Global constraint (Boolean) |
|
Comparison constraints: (up to one nesting on one side)
Numeric equality |
|
|
Numeric disequality |
|
|
Numeric inequality (>=,>,<,<=) |
|
Numexpr:
Operator (non-Boolean) with all args Var/constant |
|
|
Global constraint (non-Boolean) |
|
wsum:
Todo
wsum([Const],[Var]) represents sum([Const]*[Var]) # TODO: not implemented yet
Reify/imply constraint: (up to two nestings on one side)
Reification (double implication) |
|
|
Implication |
|
Boolexpr:
Boolean operators |
|
|
Boolean equality |
|
|
Global constraint (Boolean) |
|
|
Comparison constraint (see above) |
Reification of a comparison is the most complex case as it can allow up to 3 levels of nesting in total, e.g.:
(wsum([1,2,3],[IV1,IV2,IV3]) > 5) == BV
(IV1 == IV2) == BV
(BV1 == BV2) == BV3
Objective: (up to one nesting)
Type |
Example |
Notes |
|---|---|---|
Satisfaction problem |
|
|
Decision variable |
|
|
Linear |
|
|
The output after calling flatten_model() or flatten_constraint() will ONLY contain expressions
of the form specified above.
The flattening does not promise to do common subexpression elimination or to automatically group
commutative expressions (and, or, sum, wsum, …) but such optimisations should be added later.
Todo
TODO: update behind_the_scenes.rst doc with the new ‘flat normal form’ TODO: small optimisations, e.g. and/or chaining (potentially after negation), see test_flatten
- cpmpy.transformations.flatten_model.flatten_constraint(expr, csemap=None)[source]
input is any expression; except is_num(), pure _NumVarImpl, or Operator/GlobalConstraint with not is_bool()
output: see definition of ‘flat normal form’ above.
it will return ‘Exception’ if something is not supported
Todo
TODO, what built-in python error is best? RE TODO: we now have custom NotImpl/NotSupported
- cpmpy.transformations.flatten_model.flatten_model(orig_model)[source]
Receives model, returns new model where every constraint is in ‘flat normal form’
- cpmpy.transformations.flatten_model.flatten_objective(expr, supported=frozenset({'sum', 'wsum'}), csemap=None)[source]
Decision variable: Var
- Linear:
sum([Var])
(CPMpy class ‘Operator’, name ‘sum’)
wsum([Const],[Var])
(CPMpy class ‘Operator’, name ‘wsum’)
- cpmpy.transformations.flatten_model.get_or_make_var(expr, csemap=None)[source]
Must return a variable, and list of flat normal constraints Determines whether this is a Boolean or Integer variable and returns the equivalent of: (var, normalize(expr) == var)
- cpmpy.transformations.flatten_model.get_or_make_var_or_list(expr, csemap=None)[source]
Like get_or_make_var() but also accepts and recursively transforms lists Used to convert arguments of globals
- cpmpy.transformations.flatten_model.normalized_boolexpr(expr, csemap=None)[source]
input is any Boolean (is_bool()) expression output are all ‘flat normal form’ Boolean expressions that can be ‘reified’, meaning that
subexpr == BoolVar subexpr -> BoolVar
are valid output expressions.
Currently, this is the case for subexpr:
Boolean operators
and([Var]),or([Var])Boolean equality
Var == VarGlobal constraint (Boolean)
global([Var]*)Comparison constraint (see elsewhere)
- Result:
(base_expr, base_cons) with:
base_expr: same as ‘expr’, but all arguments are variables
base_cons: list of flat normal constraints
- cpmpy.transformations.flatten_model.normalized_numexpr(expr, csemap=None)[source]
all ‘flat normal form’ numeric expressions…
Currently, this is the case for:
- Operator (non-Boolean) with all args Var/constant (examples: +,*,/,mod,wsum)
(CPMpy class ‘Operator’, not is_bool())
- Global constraint (non-Boolean) (examples: Max,Min,Element)
(CPMpy class ‘GlobalConstraint’, not is_bool()))
- Result:
(base_expr, base_cons) with:
base_expr: same as ‘expr’, but all arguments are variables
base_cons: list of flat normal constraints