@@ -324,23 +324,21 @@ pub fn solve_optimal(model: highs::Model) -> Result<highs::SolvedModel, ModelErr
324324 }
325325}
326326
327- /// Sanity check for input prices.
328- ///
329- /// Input prices should only be provided for commodities for which there will be no commodity
330- /// balance constraint.
331- fn check_input_prices ( input_prices : & CommodityPrices , markets : & [ MarketID ] ) {
332- let markets_set: HashSet < _ > = markets. iter ( ) . collect ( ) ;
333- let has_prices_for_market_subset = input_prices. keys ( ) . any ( |( commodity_id, region_id, _) | {
334- let market_for_commodity_region = MarketID {
335- commodity_id : commodity_id. clone ( ) ,
336- region_id : region_id. clone ( ) ,
337- } ;
338- markets_set. contains ( & market_for_commodity_region)
339- } ) ;
340- assert ! (
341- !has_prices_for_market_subset,
342- "Input prices were included for commodities that are being modelled, which is not allowed."
343- ) ;
327+ /// Select prices for commodities not being balanced
328+ fn select_input_prices (
329+ input_prices : & CommodityPrices ,
330+ markets_to_balance : & [ MarketID ] ,
331+ ) -> CommodityPrices {
332+ let commodity_regions_set: HashSet < ( & CommodityID , & RegionID ) > = markets_to_balance
333+ . iter ( )
334+ . map ( |m| ( & m. commodity_id , & m. region_id ) )
335+ . collect ( ) ;
336+ input_prices
337+ . iter ( )
338+ . filter ( |( commodity_id, region_id, _, _) | {
339+ !commodity_regions_set. contains ( & ( commodity_id, region_id) )
340+ } )
341+ . collect ( )
344342}
345343
346344/// Provides the interface for running the dispatch optimisation.
@@ -438,18 +436,25 @@ impl<'model, 'run> DispatchRun<'model, 'run> {
438436 } else {
439437 self . markets_to_balance
440438 } ;
441- if let Some ( input_prices) = self . input_prices {
442- check_input_prices ( input_prices, markets_to_balance) ;
443- }
439+
440+ // Select prices for commodities not being balanced
441+ let input_prices_owned = self
442+ . input_prices
443+ . map ( |prices| select_input_prices ( prices, markets_to_balance) ) ;
444+ let input_prices = input_prices_owned. as_ref ( ) ;
444445
445446 // Try running dispatch. If it fails because the model is infeasible, it is likely that this
446447 // is due to unmet demand, in this case, we rerun dispatch including with unmet demand
447448 // variables for all markets so we can report the offending markets to users
448- match self . run_internal ( markets_to_balance, self . markets_to_allow_unmet_demand ) {
449+ match self . run_internal (
450+ markets_to_balance,
451+ self . markets_to_allow_unmet_demand ,
452+ input_prices,
453+ ) {
449454 Ok ( solution) => Ok ( solution) ,
450455 Err ( ModelError :: NonOptimal ( HighsModelStatus :: Infeasible ) ) => {
451456 let markets = self
452- . get_markets_with_unmet_demand ( markets_to_balance)
457+ . get_markets_with_unmet_demand ( markets_to_balance, input_prices )
453458 . expect ( "Failed to run dispatch to calculate unmet demand" ) ;
454459
455460 ensure ! (
@@ -472,9 +477,10 @@ impl<'model, 'run> DispatchRun<'model, 'run> {
472477 pub fn get_markets_with_unmet_demand (
473478 & self ,
474479 markets_to_balance : & [ MarketID ] ,
480+ input_prices : Option < & CommodityPrices > ,
475481 ) -> Result < IndexSet < MarketID > > {
476482 // Run dispatch including unmet demand variables for all markets being balanced
477- let solution = self . run_internal ( markets_to_balance, markets_to_balance) ?;
483+ let solution = self . run_internal ( markets_to_balance, markets_to_balance, input_prices ) ?;
478484
479485 // Collect markets with unmet demand
480486 Ok ( solution. get_markets_with_unmet_demand ( ) )
@@ -485,13 +491,14 @@ impl<'model, 'run> DispatchRun<'model, 'run> {
485491 & self ,
486492 markets_to_balance : & [ MarketID ] ,
487493 markets_to_allow_unmet_demand : & [ MarketID ] ,
494+ input_prices : Option < & CommodityPrices > ,
488495 ) -> Result < Solution < ' model > , ModelError > {
489496 // Set up problem
490497 let mut problem = Problem :: default ( ) ;
491498 let mut variables = VariableMap :: new_with_asset_vars (
492499 & mut problem,
493500 self . model ,
494- self . input_prices ,
501+ input_prices,
495502 self . existing_assets ,
496503 self . candidate_assets ,
497504 self . year ,
0 commit comments