Skip to content

Circularity MILP - #1557

Draft
tsmbland wants to merge 10 commits into
graph_docsfrom
circularity_milp
Draft

tsmbland wants to merge 10 commits into
graph_docsfrom
circularity_milp

Conversation

@tsmbland

@tsmbland tsmbland commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Similar to #1547, but doesn't require/allow users to manually mark feedback processes. These are detected based on which commodities end up out of order in the MILP result, with an added constraint to make sure that the system remains valid once feedback processes are removed (necessary for the second investment pass). I imagine this PR is the one we'll merge over #1547, if this two-pass approach proves useful, but that other PR is useful for testing different feedback_process configurations.

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change to fix an issue)
  • New feature (non-breaking change to add functionality)
  • Refactoring (non-breaking, non-functional change to improve maintainability)
  • Optimization (non-breaking change to speed up the code)
  • Breaking change (whatever its nature)
  • Documentation (improve or add documentation)

Key checklist

  • All tests pass: $ cargo test
  • The documentation builds and looks OK: $ cargo doc
  • Update release notes for the latest release if this PR adds a new feature or fixes a bug
    present in the previous release

Further checks

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works

@tsmbland
tsmbland force-pushed the circularity_milp branch 2 times, most recently from 19f051d to b798205 Compare October 27, 2026 14:04

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.30.

Benchmark suite Current: 948f1b7 Previous: 6a19604 Ratio
select_best_assets_parallel/01 13564670.46875 ns 9132896.765151516 ns 1.49
select_best_assets_parallel/05 38101280.5 ns 26819628.777777776 ns 1.42
select_best_assets_parallel/10 64754173 ns 45113674.75 ns 1.44
select_best_assets_parallel/15 94518125.75 ns 65351435.33333333 ns 1.45
select_best_assets_parallel/20 124836132.25 ns 85097739.5 ns 1.47
select_best_assets_sequential/01 13319748.961538462 ns 9107675.635526314 ns 1.46
select_best_assets_sequential/05 64110279.33333333 ns 43859325.75 ns 1.46
select_best_assets_sequential/10 127960637.5 ns 87553632.5 ns 1.46
select_best_assets_sequential/15 192535830.5 ns 131658938.5 ns 1.46
select_best_assets_sequential/20 259066737 ns 175652280.5 ns 1.47

This comment was automatically generated by workflow using github-action-benchmark.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved feedback-ordering, demand-accounting and input-handling bugs can cause infeasible portfolios, unnecessary investment and model-loading panics.

5 open issues
What changed in this PR

This PR replaces MUSE2’s flexible-capacity cycle balancing with a two-pass investment algorithm that detects feedback processes automatically, unlike the manual configuration approach in #1547.

Changes:

  • Adds supply-preservation constraints to cycle ordering and automatic feedback exclusion during the second investment pass.
  • Passes explicit demand maps into dispatch and removes capacity_margin.
  • Combines regional commodity graphs into yearly graphs and updates circularity regression expectations.
File Description
tests/​data/​circularity/​commodity_prices.csv Updates expected circularity prices.
tests/​data/​circularity/​assets.csv Updates expected selected assets.
tests/​data/​circularity/​asset_capacities.csv Updates expected capacities and tranche counts.
tests/​data/​circularity_npv/​commodity_prices.csv Updates expected NPV scenario prices.
tests/​data/​circularity_npv/​assets.csv Updates NPV scenario asset selections.
tests/​data/​circularity_npv/​asset_capacities.csv Updates NPV scenario capacities.
tests/​cli.rs Checks the yearly graph filename.
src/​simulation/​optimisation/​constraints.rs Uses explicit demands and removes flexible-capacity constraints.
src/​simulation/​optimisation.rs Accepts demand maps and removes capacity decision variables.
src/​simulation/​market.rs Implements feedback detection and two-pass investment.
src/​simulation/​investment.rs Supplies dispatch demands and introduces demand flooring.
src/​simulation.rs Passes preset demands to final dispatch.
src/​model/​parameters.rs Removes capacity_margin.
src/​input.rs Loads yearly graphs and propagates ordering errors.
src/​graph/​validate.rs Validates region-aware nodes and edges.
src/​graph/​investment.rs Adds external-supply tracking and cycle-order constraints.
src/​graph.rs Builds and exports one region-aware graph per year.
schemas/​input/​model.yaml Removes the capacity-margin schema entry.
benches/​assets.rs Adapts benchmark dispatch to explicit demands.

Review effort: Balanced

Comment thread src/graph/investment.rs
fn find_sourced_markets(graph: &CommoditiesGraph) -> HashSet<MarketSet> {
graph
.edge_references()
.filter(|e| matches!(graph[e.source()], GraphNode::Source))
Comment thread src/graph/investment.rs
Comment on lines +337 to +342
// Make sure the SCC has at least one external incoming edge - panic if not as this should
// not happen
assert!(
has_external_incoming.contains(&true),
"SCC {scc_display} has no inputs"
);
Comment thread src/graph/investment.rs
Comment on lines +424 to +425
let required = if has_external_incoming[i] { 0.0 } else { 1.0 };
problem.add_row(required.., incoming_terms);
Comment on lines +188 to +190
if *value < Flow(0.0) {
*value = Flow(0.0);
}
Comment thread src/simulation/market.rs
Comment on lines +267 to +269
if !process.active_for_year(year) {
continue;
}
@tsmbland
tsmbland changed the base branch from main to graph_multi_region October 29, 2026 09:33
@tsmbland
tsmbland changed the base branch from graph_multi_region to graph_docs November 2, 2026 15:52

This branch has not been deployed

No deployments
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.

2 participants