linopy.model.Model.add_piecewise_formulation

linopy.model.Model.add_piecewise_formulation#

Model.add_piecewise_formulation(*pairs, method='auto', active=None, name=None)#

Add piecewise linear constraints.

Each positional argument is a (expression, breakpoints) tuple, or (expression, breakpoints, sign) to mark that expression as bounded by the piecewise curve rather than pinned to it. All expressions are linked through shared interpolation weights so that every operating point lies on the same piece of the piecewise curve.

Example — 2 variables (joint equality, the default):

m.add_piecewise_formulation(
    (power, [0, 30, 60, 100]),
    (fuel,  [0, 36, 84, 170]),
)

Example — 3 variables, CHP plant (joint equality):

m.add_piecewise_formulation(
    (power, [0, 30, 60, 100]),
    (fuel,  [0, 40, 85, 160]),
    (heat,  [0, 25, 55, 95]),
)

Per-tuple sign — inequality bounds:

Add "<=" or ">=" as a third tuple element to mark a single expression as bounded by the curve instead of pinned to it. The remaining tuples are still forced to equality (input on the curve). Reads directly as the relation it encodes:

# fuel <= f(power) — concave curve, bounded above
m.add_piecewise_formulation(
    (fuel, y_pts, "<="),
    (power, x_pts),
)

# cost >= g(load) — convex curve, bounded below
m.add_piecewise_formulation(
    (cost, y_pts, ">="),
    (load, x_pts),
)

For 2-variable inequality on convex/concave curves, method="auto" automatically selects a pure-LP tangent-line formulation (no auxiliary variables). Non-convex curves fall back to SOS2/incremental with the sign applied to the bounded tuple’s link constraint.

Restrictions on per-tuple sign:

  • At most one tuple may carry a non-equality sign. All other tuples default to "==".

  • With 3 or more tuples, all signs must be "==".

Multi-bounded and N≥3-inequality use cases aren’t supported yet. If you have a concrete use case, please open an issue at PyPSA/linopy#issues so we can scope it properly.

Parameters:
  • *pairs (tuple of (expression, breakpoints) or (expression, breakpoints, sign)) – Each pair links an expression (Variable or LinearExpression) to its breakpoint values. An optional third element "<=" or ">=" marks that expression as bounded by the curve; if omitted, the expression is pinned ("=="). At least two pairs are required; at most one may carry a non-equality sign; with 3+ pairs all signs must be "==".

  • method ({"auto", "sos2", "incremental", "lp"}, default "auto") – Formulation method. "lp" uses tangent lines (pure LP, no variables) and requires exactly one tuple with "<=" or ">=" plus a matching-curvature curve with exactly two tuples. "auto" picks "lp" when applicable, otherwise "incremental" (monotonic breakpoints) or "sos2".

  • active (Variable or LinearExpression, optional) – Binary variable that gates the piecewise function. When active=0, all auxiliary variables are forced to zero. Not supported with method="lp".

    With all-equality tuples (the default), the output is then pinned to 0. With a bounded tuple ("<=" / ">="), deactivation only pushes the signed bound to 0 (the output is ≤ 0 or ≥ 0 respectively) — the complementary bound still comes from the output variable’s own lower/upper. In the common case where the output is naturally non-negative (fuel, cost, heat, …), just set lower=0 on that variable: combined with the y 0 constraint from deactivation, this forces y = 0 automatically. For outputs that genuinely need both signs you must add the complementary bound yourself (e.g., a big-M coupling y with active).

  • name (str, optional) – Base name for generated variables/constraints.

Returns:

PiecewiseFormulation

Warns:

EvolvingAPIWarningadd_piecewise_formulation is a newly-added API; details such as the per-tuple sign convention and active + non-equality sign semantics may be refined based on user feedback. Silence with warnings.filterwarnings("ignore", category=linopy.EvolvingAPIWarning).