Skip to content

Commit 07b7c16

Browse files
FBumannclaude
andcommitted
refac: inline _add_dpwl_sos2_core into _add_disjunctive, remove dead code
Remove _add_pwl_sos2_core and _add_pwl_incremental_core which were never called, and inline the single-caller _add_dpwl_sos2_core. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent afa1d8e commit 07b7c16

1 file changed

Lines changed: 43 additions & 68 deletions

File tree

linopy/piecewise.py

Lines changed: 43 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -576,72 +576,6 @@ def _compute_combined_mask(
576576
return ~(x_points.isnull() | y_points.isnull())
577577

578578

579-
def _add_dpwl_sos2_core(
580-
model: Model,
581-
name: str,
582-
x_expr: LinearExpression,
583-
target_expr: LinearExpression,
584-
x_points: DataArray,
585-
y_points: DataArray,
586-
lambda_mask: DataArray | None,
587-
active: LinearExpression | None = None,
588-
) -> Constraint:
589-
"""
590-
Core disjunctive SOS2 formulation with separate x/y points.
591-
592-
When ``active`` is provided, the segment selection becomes
593-
``sum(z_k) == active`` instead of ``== 1``, forcing all segment
594-
binaries, lambdas, and thus x and y to zero when ``active=0``.
595-
"""
596-
binary_name = f"{name}{PWL_BINARY_SUFFIX}"
597-
select_name = f"{name}{PWL_SELECT_SUFFIX}"
598-
lambda_name = f"{name}{PWL_LAMBDA_SUFFIX}"
599-
convex_name = f"{name}{PWL_CONVEX_SUFFIX}"
600-
x_link_name = f"{name}{PWL_X_LINK_SUFFIX}"
601-
y_link_name = f"{name}{PWL_Y_LINK_SUFFIX}"
602-
603-
extra = _extra_coords(x_points, BREAKPOINT_DIM, SEGMENT_DIM)
604-
lambda_coords = extra + [
605-
pd.Index(x_points.coords[SEGMENT_DIM].values, name=SEGMENT_DIM),
606-
pd.Index(x_points.coords[BREAKPOINT_DIM].values, name=BREAKPOINT_DIM),
607-
]
608-
binary_coords = extra + [
609-
pd.Index(x_points.coords[SEGMENT_DIM].values, name=SEGMENT_DIM),
610-
]
611-
612-
binary_mask = (
613-
lambda_mask.any(dim=BREAKPOINT_DIM) if lambda_mask is not None else None
614-
)
615-
616-
binary_var = model.add_variables(
617-
binary=True, coords=binary_coords, name=binary_name, mask=binary_mask
618-
)
619-
620-
# Segment selection: sum(z_k) == 1 or sum(z_k) == active
621-
rhs = active if active is not None else 1
622-
select_con = model.add_constraints(
623-
binary_var.sum(dim=SEGMENT_DIM) == rhs, name=select_name
624-
)
625-
626-
lambda_var = model.add_variables(
627-
lower=0, upper=1, coords=lambda_coords, name=lambda_name, mask=lambda_mask
628-
)
629-
630-
model.add_sos_constraints(lambda_var, sos_type=2, sos_dim=BREAKPOINT_DIM)
631-
632-
model.add_constraints(
633-
lambda_var.sum(dim=BREAKPOINT_DIM) == binary_var, name=convex_name
634-
)
635-
636-
x_weighted = (lambda_var * x_points).sum(dim=[SEGMENT_DIM, BREAKPOINT_DIM])
637-
model.add_constraints(x_expr == x_weighted, name=x_link_name)
638-
639-
y_weighted = (lambda_var * y_points).sum(dim=[SEGMENT_DIM, BREAKPOINT_DIM])
640-
model.add_constraints(target_expr == y_weighted, name=y_link_name)
641-
642-
return select_con
643-
644-
645579
# ---------------------------------------------------------------------------
646580
# Main entry point
647581
# ---------------------------------------------------------------------------
@@ -983,6 +917,47 @@ def _add_disjunctive(
983917
"NaN values must only appear at the end of the breakpoint sequence."
984918
)
985919

986-
return _add_dpwl_sos2_core(
987-
model, name, x_expr, y_expr, x_points, y_points, mask, active
920+
binary_name = f"{name}{PWL_BINARY_SUFFIX}"
921+
select_name = f"{name}{PWL_SELECT_SUFFIX}"
922+
lambda_name = f"{name}{PWL_LAMBDA_SUFFIX}"
923+
convex_name = f"{name}{PWL_CONVEX_SUFFIX}"
924+
x_link_name = f"{name}{PWL_X_LINK_SUFFIX}"
925+
y_link_name = f"{name}{PWL_Y_LINK_SUFFIX}"
926+
927+
extra = _extra_coords(x_points, BREAKPOINT_DIM, SEGMENT_DIM)
928+
lambda_coords = extra + [
929+
pd.Index(x_points.coords[SEGMENT_DIM].values, name=SEGMENT_DIM),
930+
pd.Index(x_points.coords[BREAKPOINT_DIM].values, name=BREAKPOINT_DIM),
931+
]
932+
binary_coords = extra + [
933+
pd.Index(x_points.coords[SEGMENT_DIM].values, name=SEGMENT_DIM),
934+
]
935+
936+
binary_mask = mask.any(dim=BREAKPOINT_DIM) if mask is not None else None
937+
938+
binary_var = model.add_variables(
939+
binary=True, coords=binary_coords, name=binary_name, mask=binary_mask
940+
)
941+
942+
rhs = active if active is not None else 1
943+
select_con = model.add_constraints(
944+
binary_var.sum(dim=SEGMENT_DIM) == rhs, name=select_name
945+
)
946+
947+
lambda_var = model.add_variables(
948+
lower=0, upper=1, coords=lambda_coords, name=lambda_name, mask=mask
988949
)
950+
951+
model.add_sos_constraints(lambda_var, sos_type=2, sos_dim=BREAKPOINT_DIM)
952+
953+
model.add_constraints(
954+
lambda_var.sum(dim=BREAKPOINT_DIM) == binary_var, name=convex_name
955+
)
956+
957+
x_weighted = (lambda_var * x_points).sum(dim=[SEGMENT_DIM, BREAKPOINT_DIM])
958+
model.add_constraints(x_expr == x_weighted, name=x_link_name)
959+
960+
y_weighted = (lambda_var * y_points).sum(dim=[SEGMENT_DIM, BREAKPOINT_DIM])
961+
model.add_constraints(y_expr == y_weighted, name=y_link_name)
962+
963+
return select_con

0 commit comments

Comments
 (0)