Skip to content

Allow cost-based pricing for circular markets#1322

Open
tsmbland wants to merge 12 commits into
select_assets_for_cycle_fixfrom
circularities_pricing
Open

Allow cost-based pricing for circular markets#1322
tsmbland wants to merge 12 commits into
select_assets_for_cycle_fixfrom
circularities_pricing

Conversation

@tsmbland
Copy link
Copy Markdown
Collaborator

@tsmbland tsmbland commented Jun 1, 2026

Description

See #1318 for full context. Adam suggested a solution of iterating over the commodities in cycles just once, in the reverse of the investment order. This will inevitably lead to some price inconsistency between commodities, but prevents the risk of price spiralling that could happen if we iterate multiple times.

The implementation here does exactly this (one pass through the commodities in the reverse of the investment order), although I've left the code flexible enough that we can experiment with iterating multiple times (via a hard-coded variable in the code, rather than an input parameter).

I've run for the "circularity" example (using the default "full_average" pricing strategy) and it works nicely. (Hydrogen prices are atmittedly very high in the first year, but I think that's down to #1325)

Main changes:

  • Removed a check in compress_cycles that was disallowing circular markets to use cost-based pricing strategies
  • A few simplifications to the surrounding code as this no longer needs to return a Result
  • Restructured the price calculation algorithm to recurse over InvestmentSets, similar to the investment algorithm just in reverse order. For InvestmentSet::Cycle, this calls the new price_cycle function.
  • Modified CommodityPrices::insert and CommodityPrices::extend_selection_prices to allow for price overwriting. This was necessary since prices for circular markets need to be updated multiple times (even if just running for one iteration, since we seed with shadow prices beforehand), and this was the easiest way to do it (slightly lazy - I can change if we really need this check in other contexts, but it didn't seem hugely important to me)

Other notes:

  • Diffs to some other model results - just changing the order of rows
  • price_markets, while set up to solve multiple markets in batch, is in practice only ever called on one market at a time. There are potentially some performance gains that could be had by solving independent markets in batch (particularly within the same layer), but this didn't work with the recursive approach of price_investment_set.If we don't want to go down the route of solving markets in batch then we could simplify price_markets and some other functions. I'll leave it for now though.
  • I haven't tried this yet with more complex cycles. Will give it a go and report back.
  • I'm thinking it might worth rebranding InvestmentSet into something a bit more generic is we're now using this outside the context of investments.

Fixes #1168

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 1, 2026

Codecov Report

❌ Patch coverage is 94.15205% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.63%. Comparing base (58c7f76) to head (c994f8c).

Files with missing lines Patch % Lines
src/simulation/prices.rs 93.82% 7 Missing and 3 partials ⚠️
Additional details and impacted files
@@                       Coverage Diff                       @@
##           select_assets_for_cycle_fix    #1322      +/-   ##
===============================================================
+ Coverage                        89.52%   89.63%   +0.11%     
===============================================================
  Files                               58       58              
  Lines                             8542     8609      +67     
  Branches                          8542     8609      +67     
===============================================================
+ Hits                              7647     7717      +70     
  Misses                             580      580              
+ Partials                           315      312       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tsmbland tsmbland changed the title Circularities pricing Allow cost-based pricing for circular markets Jun 1, 2026
@tsmbland tsmbland requested a review from Copilot June 1, 2026 14:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Enables cost-based (marginal/full) pricing strategies for models with circular commodity dependencies by removing the prior validation restriction and introducing cycle-aware pricing logic.

Changes:

  • Remove the validation-time restriction that prevented cost-based pricing strategies in InvestmentSet::Cycle.
  • Refactor price calculation to handle InvestmentSet variants explicitly, adding a price_cycle pathway and allowing price overwrites during cycle iteration.
  • Update circularity example/regression datasets to reflect the new pricing behavior.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/data/circularity/commodity_prices.csv Updated expected commodity price outputs for circularity regression scenario.
tests/data/circularity/commodity_flows.csv Updated expected flow outputs for circularity regression scenario.
tests/data/circularity/assets.csv Updated expected assets snapshot for circularity regression scenario.
tests/data/circularity/asset_capacities.csv Updated expected asset capacities snapshot for circularity regression scenario.
src/simulation/prices.rs Adds cycle-aware pricing path and allows overwriting prices to support iterative updates.
src/input.rs Adjusts model loading to accommodate non-Result investment-order solving.
src/graph/investment.rs Removes pricing-strategy restriction in SCC compression and simplifies APIs to return non-Result.
examples/circularity/commodities.csv Updates example commodities to use default (cost-based) pricing rather than shadow pricing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/simulation/prices.rs Outdated
Comment thread src/simulation/prices.rs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Comment thread src/simulation/prices.rs
@tsmbland tsmbland force-pushed the circularities_pricing branch from 015bb12 to c994f8c Compare June 2, 2026 10:37
@tsmbland tsmbland changed the base branch from main to select_assets_for_cycle_fix June 2, 2026 10:38
@tsmbland tsmbland marked this pull request as ready for review June 3, 2026 08:30
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.

Cannot use "marginal" or "full" pricing strategies for markets with circularities

2 participants