Skip to content

Commit 2e177d5

Browse files
committed
Implement easy suggestions
1 parent 5b26fac commit 2e177d5

1 file changed

Lines changed: 31 additions & 36 deletions

File tree

src/simulation/prices.rs

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl WeightedAverageAccumulator {
3838
/// Solve the weighted average.
3939
///
4040
/// Returns `None` if the denominator is zero (or close to zero)
41-
fn finalise(&self) -> Option<MoneyPerFlow> {
41+
fn finalise(self) -> Option<MoneyPerFlow> {
4242
(self.denominator > Dimensionless::EPSILON).then(|| self.numerator / self.denominator)
4343
}
4444
}
@@ -62,7 +62,7 @@ impl WeightedAverageBackupAccumulator {
6262
/// Solve the weighted average, falling back to backup weights if needed.
6363
///
6464
/// Returns `None` if both denominators are zero (or close to zero).
65-
fn finalise(&self) -> Option<MoneyPerFlow> {
65+
fn finalise(self) -> Option<MoneyPerFlow> {
6666
self.primary.finalise().or_else(|| self.backup.finalise())
6767
}
6868
}
@@ -388,15 +388,13 @@ where
388388
scarcity_prices
389389
}
390390

391-
/// Expand a map of prices for commodity/region/time slice selections to a map of prices for
392-
/// commodity/region/time slices by applying the same price to all time slices within each
393-
/// selection.
394-
fn expand_selection_prices(
391+
/// Extend an existing commodity/region/time-slice price map by applying each
392+
/// selection-level price to all time slices within that selection.
393+
fn extend_selection_prices(
394+
prices: &mut IndexMap<(CommodityID, RegionID, TimeSliceID), MoneyPerFlow>,
395395
group_prices: &IndexMap<(CommodityID, RegionID, TimeSliceSelection), MoneyPerFlow>,
396396
time_slice_info: &TimeSliceInfo,
397-
) -> IndexMap<(CommodityID, RegionID, TimeSliceID), MoneyPerFlow> {
398-
let mut prices = IndexMap::new();
399-
397+
) {
400398
for ((commodity_id, region_id, selection), &selection_price) in group_prices {
401399
for (time_slice_id, _) in selection.iter(time_slice_info) {
402400
let key = (
@@ -408,8 +406,6 @@ fn expand_selection_prices(
408406
assert!(!existing, "Key {key:?} already exists in the map");
409407
}
410408
}
411-
412-
prices
413409
}
414410

415411
/// Calculate marginal cost prices for a set of commodities.
@@ -530,7 +526,7 @@ where
530526
.filter_map(|(key, per_asset)| {
531527
per_asset
532528
.into_values()
533-
.filter_map(|inner| inner.finalise())
529+
.filter_map(WeightedAverageBackupAccumulator::finalise)
534530
.reduce(|current, value| current.max(value))
535531
.map(|v| (key, v))
536532
})
@@ -584,22 +580,21 @@ where
584580
}
585581

586582
// For each group, finalise per-candidate weighted averages then take the min across candidates
587-
let cand_group_prices: IndexMap<_, MoneyPerFlow> = cand_accum
588-
.into_iter()
589-
.filter_map(|(key, per_candidate)| {
590-
per_candidate
591-
.into_values()
592-
.filter_map(|inner| inner.finalise())
593-
.reduce(|current, value| current.min(value))
594-
.map(|v| (key, v))
595-
})
596-
.collect();
583+
let cand_group_prices = cand_accum.into_iter().filter_map(|(key, per_candidate)| {
584+
per_candidate
585+
.into_values()
586+
.filter_map(WeightedAverageAccumulator::finalise)
587+
.reduce(|current, value| current.min(value))
588+
.map(|v| (key, v))
589+
});
597590

598591
// Merge existing and candidate group prices, then expand to individual time slices
599592
let mut all_group_prices = group_prices;
600593
all_group_prices.extend(cand_group_prices);
601594

602-
expand_selection_prices(&all_group_prices, time_slice_info)
595+
let mut prices = IndexMap::new();
596+
extend_selection_prices(&mut prices, &all_group_prices, time_slice_info);
597+
prices
603598
}
604599

605600
/// Calculate annual activities for each asset by summing across all time slices
@@ -760,7 +755,7 @@ where
760755
.filter_map(|(key, per_asset)| {
761756
per_asset
762757
.into_values()
763-
.filter_map(|inner| inner.finalise())
758+
.filter_map(WeightedAverageBackupAccumulator::finalise)
764759
.reduce(|current, value| current.max(value))
765760
.map(|v| (key, v))
766761
})
@@ -827,22 +822,21 @@ where
827822
}
828823

829824
// For each group, finalise per-candidate weighted averages then reduce to the min across candidates
830-
let cand_group_prices: IndexMap<_, MoneyPerFlow> = cand_accum
831-
.into_iter()
832-
.filter_map(|(key, per_candidate)| {
833-
per_candidate
834-
.into_values()
835-
.filter_map(|inner| inner.finalise())
836-
.reduce(|current, value| current.min(value))
837-
.map(|v| (key, v))
838-
})
839-
.collect();
825+
let cand_group_prices = cand_accum.into_iter().filter_map(|(key, per_candidate)| {
826+
per_candidate
827+
.into_values()
828+
.filter_map(WeightedAverageAccumulator::finalise)
829+
.reduce(|current, value| current.min(value))
830+
.map(|v| (key, v))
831+
});
840832

841833
// Merge existing and candidate group prices, then expand to individual time slices
842834
let mut all_group_prices = group_prices;
843835
all_group_prices.extend(cand_group_prices);
844836

845-
expand_selection_prices(&all_group_prices, time_slice_info)
837+
let mut prices = IndexMap::new();
838+
extend_selection_prices(&mut prices, &all_group_prices, time_slice_info);
839+
prices
846840
}
847841

848842
#[cfg(test)]
@@ -862,6 +856,7 @@ mod tests {
862856
Activity, Capacity, Dimensionless, FlowPerActivity, MoneyPerActivity, MoneyPerCapacity,
863857
MoneyPerCapacityPerYear, MoneyPerFlow,
864858
};
859+
use float_cmp::assert_approx_eq;
865860
use indexmap::{IndexMap, IndexSet};
866861
use rstest::rstest;
867862
use std::collections::{HashMap, HashSet};
@@ -1157,7 +1152,7 @@ mod tests {
11571152
accum.add(MoneyPerFlow(200.0), Dimensionless(2.0));
11581153
// (100*1 + 200*2) / (1+2) = 500/3 ≈ 166.667
11591154
let result = accum.finalise().unwrap();
1160-
assert!((result - MoneyPerFlow(500.0 / 3.0)).abs() < MoneyPerFlow::EPSILON);
1155+
assert_approx_eq!(MoneyPerFlow, result, MoneyPerFlow(500.0 / 3.0));
11611156
}
11621157

11631158
#[test]

0 commit comments

Comments
 (0)