powers_rs/
scenario.rs

1use rand::prelude::*;
2use rand_distr;
3use rand_xoshiro;
4
5pub struct NodeNoiseGenerator<
6    L: rand_distr::Distribution<f64>,
7    I: rand_distr::Distribution<f64>,
8> {
9    pub load_distributions: Vec<L>, // indexed by hydro_id
10    pub inflow_distributions: Vec<I>, // indexed by hydro_id
11    pub num_branchings: usize,
12    pub num_load_entities: usize,
13    pub num_inflow_entities: usize,
14}
15
16pub struct NoiseGenerator<
17    L: rand_distr::Distribution<f64>,
18    I: rand_distr::Distribution<f64>,
19> {
20    pub node_generators: Vec<NodeNoiseGenerator<L, I>>,
21}
22
23impl<L: rand_distr::Distribution<f64>, I: rand_distr::Distribution<f64>>
24    NoiseGenerator<L, I>
25{
26    pub fn new() -> Self {
27        Self {
28            node_generators: vec![],
29        }
30    }
31
32    pub fn add_node_generator(
33        &mut self,
34        load_distributions: Vec<L>,
35        inflow_distributions: Vec<I>,
36        num_branchings: usize,
37    ) {
38        let num_load_entities = load_distributions.len();
39        let num_inflow_entities = inflow_distributions.len();
40        self.node_generators.push(NodeNoiseGenerator::<L, I> {
41            load_distributions,
42            inflow_distributions,
43            num_branchings,
44            num_load_entities,
45            num_inflow_entities,
46        });
47    }
48
49    pub fn get_node_generator(
50        &mut self,
51        id: usize,
52    ) -> Option<&NodeNoiseGenerator<L, I>> {
53        self.node_generators.get(id)
54    }
55
56    /// Generates an SAA from a set of distributions
57    ///
58    /// `seed` must be an u64
59    ///
60    /// ## Example
61    ///
62    /// ```
63    /// let mu = 3.6;
64    /// let sigma = 0.6928;
65    /// let num_entities = 2;
66    /// let mut scenario_generator = powers_rs::scenario::NoiseGenerator::new();
67    /// let num_stages = 1;
68    /// let num_branchings = 10;
69    /// scenario_generator.add_node_generator(
70    ///     vec![rand_distr::Normal::new(mu, sigma).unwrap(); num_entities],
71    ///     vec![rand_distr::LogNormal::new(mu, sigma).unwrap(); num_entities],
72    ///     num_branchings);
73    /// let saa = scenario_generator.generate(0);
74    /// assert_eq!(saa.get_noises_by_stage_and_branching(0, 0).unwrap().num_load_entities, num_entities);
75    /// assert_eq!(saa.get_noises_by_stage_and_branching(0, 0).unwrap().num_inflow_entities, num_entities);
76    /// assert_eq!(saa.get_noises_by_stage_and_branching(0, 0).unwrap().get_load_noises().len(), num_entities);
77    /// assert_eq!(saa.get_noises_by_stage_and_branching(0, 0).unwrap().get_inflow_noises().len(), num_entities);
78    ///
79    /// ```
80    pub fn generate(&self, seed: u64) -> SAA {
81        let mut rng = rand_xoshiro::Xoshiro256Plus::seed_from_u64(seed);
82
83        let mut saa = SAA::new(&self);
84        for (stage_id, stage_generator) in
85            self.node_generators.iter().enumerate()
86        {
87            // here, 'noises' is indexed by [entity][branching]
88            let load_noises: Vec<Vec<f64>> = stage_generator
89                .load_distributions
90                .iter()
91                .map(|entity_generator| {
92                    entity_generator
93                        .sample_iter(&mut rng)
94                        .take(stage_generator.num_branchings)
95                        .collect()
96                })
97                .collect();
98            let inflow_noises: Vec<Vec<f64>> = stage_generator
99                .inflow_distributions
100                .iter()
101                .map(|entity_generator| {
102                    entity_generator
103                        .sample_iter(&mut rng)
104                        .take(stage_generator.num_branchings)
105                        .collect()
106                })
107                .collect();
108
109            saa.set_noises_by_stage(
110                stage_id,
111                stage_generator.num_branchings,
112                stage_generator.num_load_entities,
113                stage_generator.num_inflow_entities,
114                load_noises,
115                inflow_noises,
116            );
117        }
118
119        saa
120    }
121}
122
123#[derive(Debug, Clone)]
124pub struct SampledBranchingNoises {
125    pub load_noises: Vec<f64>,
126    pub inflow_noises: Vec<f64>,
127    pub num_load_entities: usize,
128    pub num_inflow_entities: usize,
129}
130
131impl SampledBranchingNoises {
132    pub fn new(num_load_entities: usize, num_inflow_entities: usize) -> Self {
133        Self {
134            load_noises: Vec::<f64>::with_capacity(num_load_entities),
135            inflow_noises: Vec::<f64>::with_capacity(num_inflow_entities),
136            num_load_entities,
137            num_inflow_entities,
138        }
139    }
140
141    pub fn get_load_noises(&self) -> &[f64] {
142        return self.load_noises.as_slice();
143    }
144
145    pub fn get_inflow_noises(&self) -> &[f64] {
146        return self.inflow_noises.as_slice();
147    }
148
149    pub fn set_load_noises(&mut self, noises: &[f64]) {
150        self.load_noises.extend_from_slice(noises);
151    }
152
153    pub fn set_inflow_noises(&mut self, noises: &[f64]) {
154        self.inflow_noises.extend_from_slice(noises);
155    }
156}
157
158#[derive(Debug, Clone)]
159pub struct SampledNodeBranchings {
160    pub num_branchings: usize,
161    pub branching_noises: Vec<SampledBranchingNoises>,
162}
163
164impl SampledNodeBranchings {
165    pub fn new<
166        L: rand_distr::Distribution<f64>,
167        I: rand_distr::Distribution<f64>,
168    >(
169        stage_generator: &NodeNoiseGenerator<L, I>,
170    ) -> Self {
171        let num_load_entities = stage_generator.num_load_entities;
172        let num_inflow_entities = stage_generator.num_inflow_entities;
173        Self {
174            num_branchings: stage_generator.num_branchings,
175            branching_noises: vec![
176                SampledBranchingNoises::new(
177                    num_load_entities,
178                    num_inflow_entities
179                );
180                stage_generator.num_branchings
181            ],
182        }
183    }
184
185    pub fn get_noises_by_branching(
186        &self,
187        branching_id: usize,
188    ) -> Option<&SampledBranchingNoises> {
189        return self.branching_noises.get(branching_id);
190    }
191
192    pub fn set_noises_by_branching(
193        &mut self,
194        branching_id: usize,
195        load_noises: &[f64],
196        inflow_noises: &[f64],
197    ) {
198        self.branching_noises
199            .get_mut(branching_id)
200            .unwrap()
201            .set_load_noises(load_noises);
202        self.branching_noises
203            .get_mut(branching_id)
204            .unwrap()
205            .set_inflow_noises(inflow_noises);
206    }
207}
208
209#[derive(Debug)]
210pub struct SAA {
211    pub branching_samples: Vec<SampledNodeBranchings>,
212    pub index_samplers: Vec<rand_distr::Uniform<usize>>,
213}
214
215impl SAA {
216    pub fn new<
217        L: rand_distr::Distribution<f64>,
218        I: rand_distr::Distribution<f64>,
219    >(
220        scenario_generator: &NoiseGenerator<L, I>,
221    ) -> Self {
222        let branching_samples: Vec<SampledNodeBranchings> = scenario_generator
223            .node_generators
224            .iter()
225            .map(|g| SampledNodeBranchings::new(g))
226            .collect();
227        let index_samplers = scenario_generator
228            .node_generators
229            .iter()
230            .map(|g| {
231                rand_distr::Uniform::<usize>::try_from(0..g.num_branchings)
232                    .unwrap()
233            })
234            .collect();
235        Self {
236            branching_samples,
237            index_samplers,
238        }
239    }
240
241    pub fn get_branching_count_at_stage(
242        &self,
243        stage_id: usize,
244    ) -> Option<usize> {
245        return Some(self.branching_samples.get(stage_id)?.num_branchings);
246    }
247
248    pub fn get_noises_by_stage_and_branching(
249        &self,
250        stage_id: usize,
251        branching_id: usize,
252    ) -> Option<&SampledBranchingNoises> {
253        return self
254            .branching_samples
255            .get(stage_id)?
256            .get_noises_by_branching(branching_id);
257    }
258
259    pub fn sample_scenario(
260        &self,
261        rng: &mut rand_xoshiro::Xoshiro256Plus,
262    ) -> Vec<&SampledBranchingNoises> {
263        let branching_indices: Vec<usize> =
264            self.index_samplers.iter().map(|d| d.sample(rng)).collect();
265
266        branching_indices
267            .iter()
268            .enumerate()
269            .map(|(id, branching_id)| {
270                self.get_noises_by_stage_and_branching(id, *branching_id)
271                    .unwrap()
272            })
273            .collect()
274    }
275
276    pub fn set_noises_by_stage(
277        &mut self,
278        stage_id: usize,
279        num_branchings: usize,
280        num_load_entities: usize,
281        num_inflow_entities: usize,
282        load_noises: Vec<Vec<f64>>,
283        inflow_noises: Vec<Vec<f64>>,
284    ) {
285        for branching_id in 0..num_branchings {
286            let mut branching_load_noises =
287                Vec::<f64>::with_capacity(num_load_entities);
288            for entitiy_id in 0..num_load_entities {
289                branching_load_noises.push(
290                    *load_noises
291                        .get(entitiy_id)
292                        .unwrap()
293                        .get(branching_id)
294                        .unwrap(),
295                );
296            }
297            let mut branching_inflow_noises =
298                Vec::<f64>::with_capacity(num_inflow_entities);
299            for entitiy_id in 0..num_inflow_entities {
300                branching_inflow_noises.push(
301                    *inflow_noises
302                        .get(entitiy_id)
303                        .unwrap()
304                        .get(branching_id)
305                        .unwrap(),
306                );
307            }
308            self.branching_samples
309                .get_mut(stage_id)
310                .unwrap()
311                .set_noises_by_branching(
312                    branching_id,
313                    branching_load_noises.as_slice(),
314                    branching_inflow_noises.as_slice(),
315                );
316        }
317    }
318}
319
320#[cfg(test)]
321mod tests {
322
323    use super::*;
324
325    #[test]
326    fn test_generate_saa() {
327        let mu = 3.6;
328        let sigma = 0.6928;
329        let num_entities = 2;
330        let mut scenario_generator = NoiseGenerator::new();
331        let num_branchings = 10;
332        scenario_generator.add_node_generator(
333            vec![rand_distr::Normal::new(10.0, 0.0).unwrap(); num_entities],
334            vec![rand_distr::LogNormal::new(mu, sigma).unwrap(); num_entities],
335            num_branchings,
336        );
337        let saa = scenario_generator.generate(0);
338        assert!(saa.get_noises_by_stage_and_branching(0, 0).is_some())
339    }
340}