Skip to content

Enforce total capacity limit constraint in investment - #1496

Draft
AdrianDAlessandro wants to merge 6 commits into
mainfrom
total_limit_rough
Draft

Enforce total capacity limit constraint in investment#1496
AdrianDAlessandro wants to merge 6 commits into
mainfrom
total_limit_rough

Conversation

@AdrianDAlessandro

@AdrianDAlessandro AdrianDAlessandro commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Description

This is an attempt at enforcing the total capacity limit constraint in the investment. It still needs some tests, but there are some components I wanted to ask about first.

I had made the total capacity limits mapped by ProcessID, but was going to ask about the function in which I do that (market.rs::collect_total_limits), because I believe it is looping over duplicate processes and just overwriting the HashMap unnecessarily. However, I have just seen #1495 - which I believe answers that question, but will require me to bring this branch up to date with it and then change my implementation.

For now, two questions:

  1. Am I correct about the above PR requiring me to refactor?
  2. Despite the refactor, is this doing the right thing?

Fixes #1493

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

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.17647% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.28%. Comparing base (a332ac1) to head (a132876).

Files with missing lines Patch % Lines
src/simulation/investment.rs 60.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1496      +/-   ##
==========================================
- Coverage   90.29%   90.28%   -0.01%     
==========================================
  Files          60       60              
  Lines        8645     8700      +55     
  Branches     8645     8700      +55     
==========================================
+ Hits         7806     7855      +49     
- Misses        525      531       +6     
  Partials      314      314              

☔ View full report in Codecov by Harness.
📢 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

Copy link
Copy Markdown
Collaborator

For now, two questions:

  1. Am I correct about the above PR requiring me to refactor?
  2. Despite the refactor, is this doing the right thing?

Yes and yes! Sorry, should have alerted you more to #1495 as it was intended to make your life easier not harder!

Comment on lines 571 to 601
if best_asset.is_candidate() {
// Candidate assets: remove capacity from the investment limit, if applicable.
if let Some(remaining_capacity) = remaining_candidate_capacities.get_mut(&best_asset) {
if let Some(remaining_capacity) = remaining_addition_limit.get_mut(&best_asset) {
*remaining_capacity -= best_asset.total_capacity();

// If there's not enough capacity remaining to install any more units, remove the
// asset from the investment options.
if *remaining_capacity < best_asset.total_capacity() {
let old_idx = opt_assets
.iter()
.position(|asset| *asset == best_asset)
.unwrap();
opt_assets.swap_remove(old_idx);
remaining_candidate_capacities.remove(&best_asset);
remaining_addition_limit.remove(&best_asset);
}
}
} else {
// Commissioned assets: we've appraised a single unit, so remove one unit from the
// remaining units count for this asset.
let remaining = remaining_units.get_mut(&best_asset).unwrap();
*remaining = remaining.saturating_sub(1);

// If all units have been selected, remove the asset from the investment options.
if *remaining == 0 {
let old_idx = opt_assets
.iter()
.position(|asset| *asset == best_asset)
.unwrap();
opt_assets.swap_remove(old_idx);
remaining_units.remove(&best_asset);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it's possible this part could fail if the asset has already been removed from the asset options by the total capacity limit (trying to remove the same option twice). You'll need to rework this function a bit to account for this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm not entirely sure what you mean, specifically. But... the more I look at this function, the more I don't understand it and think it doesn't do what it's supposed to do. In the case where the asset drops the remaining capacity to zero, that asset shouldn't be included in the final set of assets used, but it looks like it doesn't behave that way. From what I can tell of this, the asset is added to the list of best assets, but prevented from being added again? Which doesn't really make any sense.

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.

Implement total capacity limit constraint

2 participants