use rand::rngs::StdRng;
use crate::containers::{Bag, Mail, MailItem, ModelSimResults, Msg, Outputs, Value};
use crate::dynamic::Dynamic;
use crate::model::Model;
use crate::simulator::Simulator;
use crate::time::Time;
use std::cell::RefCell;
pub use std::{
collections::{BTreeMap, HashSet},
rc::Rc,
};
#[derive(Clone, Debug)]
pub struct SimModel {
pub full_name: String,
pub dynamic: Box<dyn Dynamic>,
pub structure: Option<Structure>,
}
impl SimModel {
pub fn new(full_name: String, model: Model, rng: &Rc<RefCell<StdRng>>, iteration: u64) -> Self {
let Model {
dynamic,
sumbodels,
input_couplings,
internal_couplings,
output_couplings,
..
} = model;
let mut external_input_couplings: BTreeMap<String, BTreeMap<String, Vec<String>>> =
Default::default();
for (self_in_port, submodel, submodel_in_port) in input_couplings {
if !external_input_couplings.contains_key(&self_in_port) {
external_input_couplings.insert(self_in_port.clone(), Default::default());
}
let submodels_and_ports = external_input_couplings.get_mut(&self_in_port).unwrap();
if !submodels_and_ports.contains_key(&submodel) {
submodels_and_ports.insert(submodel.clone(), Default::default());
}
let submodels_ports = submodels_and_ports.get_mut(&submodel).unwrap();
if !submodels_ports.contains(&submodel_in_port) {
submodels_ports.push(submodel_in_port);
}
}
let mut self_internal_couplings: BTreeMap<
String,
BTreeMap<String, BTreeMap<String, Vec<String>>>,
> = Default::default();
for (
source_submodel,
source_submodel_out_port,
destination_model,
destination_model_out_port,
) in internal_couplings
{
if !self_internal_couplings.contains_key(&source_submodel) {
self_internal_couplings.insert(source_submodel.clone(), Default::default());
}
let submodels_and_its_couplings =
self_internal_couplings.get_mut(&source_submodel).unwrap();
if !submodels_and_its_couplings.contains_key(&source_submodel_out_port) {
submodels_and_its_couplings
.insert(source_submodel_out_port.clone(), Default::default());
}
let submodels_and_ports = submodels_and_its_couplings
.get_mut(&source_submodel_out_port)
.unwrap();
if !submodels_and_ports.contains_key(&destination_model) {
submodels_and_ports.insert(destination_model.clone(), Default::default());
}
let destination_submodels_ports =
submodels_and_ports.get_mut(&destination_model).unwrap();
if !destination_submodels_ports.contains(&destination_model_out_port) {
destination_submodels_ports.push(destination_model_out_port);
}
}
let mut external_output_couplings: BTreeMap<String, BTreeMap<String, Vec<String>>> =
Default::default();
for (submodel, submodel_out_port, self_out_port) in output_couplings {
if !external_output_couplings.contains_key(&submodel) {
external_output_couplings.insert(submodel.clone(), Default::default());
}
let submodel_out_and_self_out_ports =
external_output_couplings.get_mut(&submodel).unwrap();
if !submodel_out_and_self_out_ports.contains_key(&submodel_out_port) {
submodel_out_and_self_out_ports
.insert(submodel_out_port.clone(), Default::default());
}
let self_out_ports = submodel_out_and_self_out_ports
.get_mut(&submodel_out_port)
.unwrap();
if !self_out_ports.contains(&self_out_port) {
self_out_ports.push(self_out_port);
}
}
let sub_simulators: BTreeMap<String, Simulator> = sumbodels
.into_iter()
.map({
|(sub_sim_model_name, sub_model)| {
let sub_sim_model_full_name = format!("{}/{}", &full_name, sub_sim_model_name);
let sub_simulator = Simulator::new(
sub_sim_model_full_name.clone(),
sub_model,
rng.clone(),
iteration,
);
(sub_sim_model_name, sub_simulator)
}
})
.collect();
let structure = if !sub_simulators.is_empty() {
Some(Structure {
sub_simulators,
external_input_couplings,
internal_couplings: self_internal_couplings,
external_output_couplings,
})
} else {
None
};
Self {
full_name,
dynamic,
structure,
}
}
pub(crate) fn full_name(&self) -> &str {
&self.full_name
}
pub(crate) fn has_submodels(&self) -> bool {
self.structure.is_some()
}
pub(crate) fn sub_simulators(&mut self) -> Option<&mut BTreeMap<String, Simulator>> {
self.structure
.as_mut()
.and_then(|Structure { sub_simulators, .. }| Some(sub_simulators))
}
pub(crate) fn external_input_couplings(
&self,
) -> Option<&BTreeMap<String, BTreeMap<String, Vec<String>>>> {
self.structure.as_ref().and_then(
|Structure {
external_input_couplings,
..
}| Some(external_input_couplings),
)
}
pub(crate) fn internal_couplings(
&self,
) -> Option<&BTreeMap<String, BTreeMap<String, BTreeMap<String, Vec<String>>>>> {
self.structure.as_ref().and_then(
|Structure {
internal_couplings, ..
}| Some(internal_couplings),
)
}
pub(crate) fn external_output_couplings(
&self,
) -> Option<&BTreeMap<String, BTreeMap<String, Vec<String>>>> {
self.structure.as_ref().and_then(
|Structure {
external_output_couplings,
..
}| Some(external_output_couplings),
)
}
pub(crate) fn get_subsimulator(&mut self, simulator_name: &str) -> Option<&mut Simulator> {
self.structure
.as_mut()
.and_then(|Structure { sub_simulators, .. }| sub_simulators.get_mut(simulator_name))
}
pub(crate) fn get_y_bag_from_mail(&self, mail: &Mail) -> Bag {
let eoc = self.external_output_couplings().unwrap();
let mut bag: Bag = Bag::new();
for MailItem { model_name, y_bag } in mail.iter() {
for Msg { port, value } in y_bag {
if let Some(mdl) = eoc.get(model_name) {
if let Some(out_prt) = mdl.get(port) {
for out_port in out_prt.iter() {
let port = out_port.clone();
let value = value.clone();
bag.push(Msg { port, value });
}
}
}
}
}
bag
}
pub(crate) fn init(&mut self, init_time: Time, rng: &mut StdRng) {
self.dynamic.init(init_time, rng);
}
pub(crate) fn time_advance(&self, rng: &mut StdRng) -> Time {
self.dynamic.time_advance(rng)
}
pub(crate) fn state(&self) -> Value {
self.dynamic.state()
}
pub(crate) fn output(&self, sim_time: Time) -> Bag {
let mut outputs = Outputs::new();
self.dynamic.output(sim_time, &mut outputs);
let Outputs { bag } = outputs;
bag
}
pub(crate) fn internal_transition(&mut self, sim_time: Time, rng: &mut StdRng) {
self.dynamic.internal_transition(sim_time, rng);
}
pub(crate) fn external_transition(
&mut self,
sim_time: Time,
elapsed: Time,
x_bag: &Bag,
rng: &mut StdRng,
) {
self.dynamic
.external_transition(sim_time, elapsed, x_bag, rng)
}
pub(crate) fn external_mail_transition(
&mut self,
sim_time: Time,
elapsed: Time,
mail: &Mail,
rng: &mut StdRng,
) {
self.dynamic
.external_mail_transition(sim_time, elapsed, mail, rng)
}
pub(crate) fn confluent_transition(&mut self, sim_time: Time, x_bag: &Bag, rng: &mut StdRng) {
self.dynamic.confluent_transition(sim_time, x_bag, rng);
}
pub(crate) fn finish(&mut self, sim_time: Time) -> BTreeMap<String, ModelSimResults> {
self.dynamic.finish(sim_time);
let mut results: BTreeMap<String, ModelSimResults> = BTreeMap::new();
if let Some(sub_simulators) = self.sub_simulators() {
sub_simulators.iter_mut().for_each(|(_, sub_simulator)| {
results.append(&mut sub_simulator.finish(sim_time));
});
}
results
}
}
#[derive(Clone, Debug)]
pub struct Structure {
pub sub_simulators: BTreeMap<String, Simulator>,
pub external_input_couplings: BTreeMap<String, BTreeMap<String, Vec<String>>>,
pub internal_couplings: BTreeMap<String, BTreeMap<String, BTreeMap<String, Vec<String>>>>,
pub external_output_couplings: BTreeMap<String, BTreeMap<String, Vec<String>>>,
}
#[cfg(test)]
mod tests {
#[test]
fn test_1() {}
}