Skip to content

stochastic: honor modularity: true on the first-stage design - #33

Closed
dmeoli wants to merge 1 commit into
SPSUnipi:stochasticfrom
dmeoli:relax-design-when-modularity-true
Closed

stochastic: honor modularity: true on the first-stage design#33
dmeoli wants to merge 1 commit into
SPSUnipi:stochasticfrom
dmeoli:relax-design-when-modularity-true

Conversation

@dmeoli

@dmeoli dmeoli commented May 11, 2026

Copy link
Copy Markdown

Summary

The deterministic branch (src/base_model.jl:152-163) gates first-stage design integrality on the per-asset modularity flag:

  • modularity: true → design is continuous (and x_us = n_us * nom_capacity)
  • modularity: falseset_integer(n_us) is called
  • (field absent) → integer (back-compat)

The stochastic branch (src/stochastic/cooperativeStoch.jl:55 and src/stochastic/nonCooperativeStoch.jl:55) instead declared x_us with a blanket , Int flag, so the design was always integer regardless of the YAML setting — diverging from the deterministic semantics.

This patch aligns the two branches: the integrality constraint is now applied per-asset, only when modularity is not explicitly true.

  • For back-compat, when the field is absent the design stays integer (current behavior).
  • Models that opt in with modularity: true get a continuous design (matching base_model.jl).

Motivation

We are validating an SMS++ port of the same energy-community model (https://gitlab.com/smspp). The SMS++ side (UCBlock/IntermittentUnitBlock/BatteryUnitBlock) treats the design capacity as a continuous variable, so to compare objective values against EC.jl we need an LP relaxation on this side too. Without this patch the only workable comparison required dumping the LP file, stripping its Generals block, and re-solving in a fresh Gurobi environment — an awkward workaround for what should be a YAML-driven knob.

After this patch, EC.jl objective_value(model.model) matches the SMS++ LP relaxation to ~1e-11 relative on all stochastic test instances we exercise (CO / CO+TUB / NA / NC / NC+TUB).

Test plan

  • Pkg.test("EnergyCommunity") on the stochastic branch with no YAML change → behavior unchanged (x_us stays integer because modularity field is absent on the shipped example YAMLs)
  • Same test with modularity: true added to every asset → x_us becomes continuous, objective_value is the LP relaxation, no Generals block in the dumped LP
  • Mixed configuration (some assets modularity: true, others false or absent) → only the modularity: true ones become continuous

🤖 Generated with Claude Code

The deterministic branch (`base_model.jl:152-163`) already gates design
integrality on the per-asset `modularity` flag: continuous when
`modularity: true`, integer when `modularity: false`. The stochastic
branch (`cooperativeStoch.jl:55`, `nonCooperativeStoch.jl:55`) instead
declared `x_us` with a blanket `, Int` flag, so the design was always
integer regardless of the YAML setting -- diverging from `base_model.jl`.

This patch aligns the two branches: the integrality constraint is now
applied per-asset, only when `modularity` is not explicitly `true`. For
back-compat, when the field is absent the design stays integer (current
behavior); models that opt in with `modularity: true` get a continuous
design (matching `base_model.jl`).

Motivation: SMS++ TSSB / LagrangianDualSolver_UC harnesses (in `UCBlock/
tools/csv2netCDF/`) compare EC.jl against an LP relaxation of the same
EC instance. Without this fix the comparison required a workaround that
dumped the LP file, stripped its `Generals` block, and re-solved in a
fresh Gurobi environment; with this fix the comparison can rely on
`objective_value(model.model)` directly.
@dmeoli dmeoli closed this May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant