Skip to content

Add random vector sampling method to MGA - #162

Open
bsergi wants to merge 59 commits into
mainfrom
bs/mga_rv
Open

Add random vector sampling method to MGA#162
bsergi wants to merge 59 commits into
mainfrom
bs/mga_rv

Conversation

@bsergi

@bsergi bsergi commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds a new capability to the existing MGA method to support random vector sampling across subcategories of the variables being explored.

Technical details

The current MGA method applies the minimization (or maximization) to the sum of a variable across all modeled regions (e.g., total U.S. solar capacity or fossil generation). The random vector method assigns randomly-sampled weights to the regional quantities applied before the summation. This technique allows for exploring the regional distribution of capacity and generation results in the near-optimal space.

As an illustration, the plot below shows the range of natural gas capacity by region (using the 54-zones) from 100 runs with the MGA random vector method with a 1% cost threshold. The MGA max/min squares indicate the results from the previous, nationwide-method; the original min/max approach is better suited for getting a wider range of total capacity, whereas the new method is better geared toward understanding uncertainty at a regional level.

image

Implementation notes

  • The weights are generated by themain_mga_rv function in mcs_sampler.py, with the number of samples (runs) controlled by GSw_MGA_RV_runs.
  • Regional weights are drawn from a support of {-1,1} with equal probability; including both negative and positive values allows for exploring minimization in one region and maximization in another.
    • The method in mcs_sampler.py can support linear sampling from [-1,1] using a uniform distribution. Initial tests suggested this didn't yield as much of a signal so we haven't implemented a switch to control this.
    • The regionality at which unique weights are sampled is controlled by GSw_MGA_RV_region and can be any level in the hierarchy file.
  • Currently this method is only supported for GSw_MGA_Objective = (capacity or generation), with weights generated by region and technology group (i_subtech).
    • If GSw_MGA_SubObjective is an aggregated tech category (e.g., gentech), unique weights will be sampled for the different i_subtech groups within the larger category.
  • Weights are read in by b_inputs.gms and applied to the MGA objective function in d_mga.gms.

Additional changes

Added a run using the random vector method to cases_test.csv.

Switches added/removed/changed

  • GSw_MGA_RV_runs: number of random weight vectors to draw; corresponds to the number of ReEDS runs.
  • GSw_MGA_RV_region`: level of regionality at which to sample the random weights.

Relevant sources or documentation

The random vector method has been used in previous MGA studies (examples here and here

Validation, testing, and comparison report(s)

Will run reference case tests once the HPC is back in service. Will also link a slide deck with some results using this method.

Checklist for author

Details to double-check

  • Charge code provided to reviewers
  • Included comparison reports for appropriate test cases
  • Documentation updated if necessary
  • If input data added/modified:
    • Dollar year recorded and converted to 2004$ for GAMS
    • Timeseries are in Central Time
    • Units are specified
    • Preprocessing steps have been documented and committed to ReEDS_Input_Processing
    • New large data files handled with .h5 instead of .csv
    • If new parameters are added to d_objective.gms, they are included in objective_function_params.yaml for completeness checking
    • If spatially resolved inputs are modified, the following visualizations for each file are included in the PR description (time-averaged if the inputs are time-resolved):
      • Map of absolute values before
      • Map of absolute values after
      • Map of differences: (after - before) or (after / before)
    • If entries are added/removed/changed in the EIA-NEMS unit database:
      • Changes have been committed to ReEDS_Input_Processing
      • hourlize/resource.py was rerun to regenerate the existing/prescribed VRE capacity data
  • Code formatting standardized
  • Reusable functions used where possible instead of copy/pasted code

General information to guide review

  • Zero impact on results of default case
  • No large data file(s) added/modified
  • No substantive impact on runtime for full-US reference case
  • No substantive impact on folder size for full-US reference case
  • No change to process flow (runreeds.py, reeds/core/solve/solve.py)
  • No change to code organization
  • No change to package requirements (environment.yml or Project.toml)

Did you use LLM tools (chatbot or copilot) in the preparation of this PR? If so, describe how

Tag points of contact here if you would like additional review of the relevant parts of the model

Comment thread reeds/inputs.py Outdated
@bsergi
bsergi marked this pull request as ready for review July 27, 2026 20:54
@bsergi
bsergi requested a review from patrickbrown4 July 27, 2026 20:54
@bsergi
bsergi requested a review from atpham88 July 27, 2026 20:54

@patrickbrown4 patrickbrown4 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.

Looks great! The only critical comment is in d_mga.gms; all the rest are minor cleanups. Approving now but should still confirm zero change before merging.

Comment thread reeds/input_processing/runfiles.csv Outdated
Comment thread reeds/inputs.py Outdated
Comment thread reeds/inputs.py
Comment on lines +286 to +292
if int(dfcases[c].MCS_runs) > 0:
mcs_sampler.general_mcs_dist_validation(reeds.io.reeds_path, mcs_dist_path, sw)
numruns = int(dfcases[c].MCS_runs)
run_type = 'MC'
else:
numruns = int(dfcases[c].GSw_MGA_RV_runs)
run_type = 'R'

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.

MCS and RV are mutually incompatible, right (at least in the current implementation, which is totally ok)? If so, should probably add a check to runreeds.check_compatibility() that raises an exception if MCS_runs and GSw_MGA_RV_runs are both nonzero.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yea that's right. We talked about eventually enabling both, but that might warrant a different approach to the run labeling that I didn't tackle. I'll add a compability check.

Comment thread reeds/input_processing/mcs_sampler.py Outdated
Comment thread reeds/input_processing/mcs_sampler.py Outdated
Comment thread docs/source/user_guide.md Outdated
Comment thread docs/source/user_guide.md Outdated
By default the MGA min/max is applied to the sum of the variable across all regions being modeled.
The MGA approach also supports an option to randomly sample of a vector of weights to apply to the regional values of the variable being optimized.
This method can be useful to characterizing the uncertainty in the regional distribution of the results.
Weights are sampled as discrete values from a support of {-1,1} to allow for simultaneous minimization and maximization.

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.

Just to check, is "support" the right word here? (I'm unfamiliar with this usage but also don't know much stats)

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.

Can we just say "weights are sampled as discrete values between {-1,1}"? Also we still have the option to sample linearly also right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Support just means where the distribution has non-zero density. It's probably not that useful to include here so I'll put something simpler to avoid the jargon (An, I think your suggestion works).

On the linear weights, the python function supports it but there's no switch to control this so it isn't exposed to the user. It's not that much additional code so I figured we could leave it in and if we change our minds about using it in the future we could either add a switch or just toggle the function argument default for a specific set of runs.

Comment thread docs/source/user_guide.md Outdated
Comment thread reeds/core/setup/b_inputs.gms Outdated
Comment thread reeds/core/setup/d_mga.gms Outdated
Comment thread reeds/core/setup/b_inputs.gms Outdated

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.

Would you move these employment factors to copy_files.py as we discussed in my PR? I'm happy to help do this here as well if needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ah I forgot I said I was going to do that in this one--thanks for the reminder!

Comment thread cases.csv
Comment thread cases.csv Outdated
Comment thread docs/source/user_guide.md Outdated
By default the MGA min/max is applied to the sum of the variable across all regions being modeled.
The MGA approach also supports an option to randomly sample of a vector of weights to apply to the regional values of the variable being optimized.
This method can be useful to characterizing the uncertainty in the regional distribution of the results.
Weights are sampled as discrete values from a support of {-1,1} to allow for simultaneous minimization and maximization.

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.

Can we just say "weights are sampled as discrete values between {-1,1}"? Also we still have the option to sample linearly also right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants