summaryrefslogtreecommitdiff
path: root/opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py
diff options
context:
space:
mode:
authorRadu Nicolae <rnicolae04@gmail.com>2025-06-16 18:01:07 +0200
committerGitHub <noreply@github.com>2025-06-16 18:01:07 +0200
commit0df3d9ced743ac3385dd710c7133a6cf369b051c (patch)
treeeff5d6d67c275643e229731ba08c5fe7dc4ccd0a /opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py
parentc7e303ad1b5217e2ff24cee9538ac841d6149706 (diff)
integrated M3SA, updated with tests and CpuPowerModels
Diffstat (limited to 'opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py')
-rw-r--r--opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py214
1 files changed, 0 insertions, 214 deletions
diff --git a/opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py b/opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py
deleted file mode 100644
index 49930d25..00000000
--- a/opendc-experiments/opendc-experiments-m3sa/src/main/python/models/MetaModel.py
+++ /dev/null
@@ -1,214 +0,0 @@
-import numpy as np
-import os
-import pandas as pd
-
-from .Model import Model
-
-
-class MetaModel:
- """
- A class that aggregates results from multiple simulation models based on user-defined functions, producing
- consolidated outputs for analysis.
-
- Attributes:
- multi_model (MultiModel): The container of models whose results are aggregated.
- meta_model (Model): Model instance that stores aggregated results.
- meta_function (function): Function used to calculate aggregated data.
- min_raw_model_len (int): Minimum length of raw data arrays across all models.
- min_processed_model_len (int): Minimum length of processed data arrays across all models.
- number_of_models (int): Number of models being aggregated.
- function_map (dict): Mapping of aggregation function names to function implementations.
- """
-
- META_MODEL_ID = -101
-
- def __init__(self, multimodel, meta_function=None):
- """
- Initializes the Metamodel with a MultiModel instance and prepares aggregation functions based on configuration.
-
- :param multimodel: MultiModel instance containing the models to aggregate.
- :raise ValueError: If metamodel functionality is not enabled in the configuration.
- """
- if not multimodel.user_input.get('metamodel', False):
- raise ValueError("Metamodel is not enabled in the config file")
-
- self.function_map = {
- 'mean': self.mean,
- 'median': self.median,
- 'meta_equation1': self.meta_equation1,
- }
-
- self.multi_model = multimodel
- self.meta_model = Model(
- raw_sim_data=[],
- id=self.META_MODEL_ID,
- path=self.multi_model.output_folder_path
- )
-
- if meta_function is not None:
- self.meta_function = meta_function
- else:
- self.meta_function = self.function_map.get(multimodel.user_input['meta_function'], self.mean)
-
- self.min_raw_model_len = min([len(model.raw_sim_data) for model in self.multi_model.models])
- self.min_processed_model_len = min([len(model.processed_sim_data) for model in self.multi_model.models])
- self.number_of_models = len(self.multi_model.models)
- self.compute()
- self.output()
-
- def output(self):
- """
- Generates outputs by plotting the aggregated results and exporting the metamodel data to a file.
- :return: None
- :side effect: Outputs data to files and generates plots.
- """
- self.plot()
- self.output_metamodel()
-
- def compute(self):
- """
- Computes aggregated data based on the specified plot type from the configuration.
- :raise ValueError: If an unsupported plot type is specified in the configuration.
- """
- if self.multi_model.plot_type == 'time_series':
- self.compute_time_series()
- elif self.multi_model.plot_type == 'cumulative':
- self.compute_cumulative()
- elif self.multi_model.plot_type == 'cumulative_time_series':
- self.compute_cumulative_time_series()
- else:
- raise ValueError("Invalid plot type in config file")
-
- def plot(self):
- """
- Plots the aggregated data according to the specified plot type from the configuration.
- :raise ValueError: If an unsupported plot type is specified.
- """
- if self.multi_model.plot_type == 'time_series':
- self.plot_time_series()
- elif self.multi_model.plot_type == 'cumulative':
- self.plot_cumulative()
- elif self.multi_model.plot_type == 'cumulative_time_series':
- self.plot_cumulative_time_series()
-
- else:
- raise ValueError("Invalid plot type in config file")
-
- def compute_time_series(self):
- """
- Aggregates time series data across models using the specified aggregation function.
- :return: None
- :side effect: Updates the meta_model's processed data with aggregated results.
- """
- for i in range(0, self.min_processed_model_len):
- data_entries = []
- for j in range(self.number_of_models):
- data_entries.append(self.multi_model.models[j].processed_sim_data[i])
- self.meta_model.processed_sim_data.append(self.meta_function(data_entries))
- self.meta_model.raw_sim_data = self.meta_model.processed_sim_data
-
- def plot_time_series(self):
- """
- Generates a time series plot of the aggregated data.
- :return: None
- :side effect: Displays a time series plot using the multi_model's plotting capabilities.
- """
- self.multi_model.models.append(self.meta_model)
- self.multi_model.generate_plot()
-
- def compute_cumulative(self):
- """
- Aggregates cumulative data entries across all models.
- :return: None
- :side effect: Updates the meta_model's cumulative data with aggregated results.
- """
-
- for i in range(0, self.min_raw_model_len):
- data_entries = []
- for j in range(self.number_of_models):
- sim_data = self.multi_model.models[j].raw_sim_data
- ith_element = sim_data[i]
- data_entries.append(ith_element)
- self.meta_model.cumulated += self.mean(data_entries)
- self.meta_model.cumulated = round(self.meta_model.cumulated, 2)
-
- def plot_cumulative(self):
- """
- Generates a cumulative plot of the aggregated data.
- :return: None
- :side effect: Displays a cumulative plot using the multi_model's plotting capabilities.
- """
- self.multi_model.models.append(self.meta_model)
- self.multi_model.generate_plot()
-
- def compute_cumulative_time_series(self):
- """
- Aggregates cumulative time series data entries across models using the specified aggregation function.
- :return: None
- :side effect: Updates the meta_model's processed data with cumulative aggregated results.
- """
- for i in range(0, self.min_processed_model_len):
- data_entries = []
- for j in range(self.number_of_models):
- data_entries.append(self.multi_model.models[j].processed_sim_data[i])
- self.meta_model.processed_sim_data.append(self.meta_function(data_entries))
-
- def plot_cumulative_time_series(self):
- """
- Generates a cumulative time series plot of the aggregated data.
- :return: None
- :side effect: Displays a cumulative time series plot using the multi_model's plotting capabilities.
- """
- self.multi_model.models.append(self.meta_model)
- self.multi_model.generate_plot()
-
- def output_metamodel(self):
- """
- Exports the processed sim data of the metamodel to a parquet file for further analysis or record keeping.
- :return: None
- :side effect: Writes data to a parquet file at the specified directory path.
- """
- directory_path = os.path.join(self.multi_model.output_folder_path, "raw-output/metamodel/seed=0")
- os.makedirs(directory_path, exist_ok=True)
- current_path = os.path.join(directory_path, f"{self.multi_model.metric}.parquet")
- df = pd.DataFrame({'processed_sim_data': self.meta_model.processed_sim_data})
- df.to_parquet(current_path, index=False)
-
- def mean(self, chunks):
- """
- Calculates the mean of a list of numerical data.
-
- :param chunks (list): The data over which to calculate the mean.
- :return: float: The mean of the provided data.
- """
- return np.mean(chunks)
-
- def median(self, chunks):
- """
- Calculates the median of a list of numerical data.
-
- :param chunks (list): The data over which to calculate the median.
- :return: float: The median of the provided data.
- """
- return np.median(chunks)
-
- def meta_equation1(self, chunks):
- """
- Calculates a weighted mean where the weights are inversely proportional to the absolute difference from the median value.
- :param chunks (list): Data chunks from which to calculate the weighted mean.
- :return: float: The calculated weighted mean.
- """
-
- """Attempt 1"""
- # median_val = np.median(chunks)
- # proximity_weights = 1 / (1 + np.abs(chunks - median_val)) # Avoid division by zero
- # weighted_mean = np.sum(proximity_weights * chunks) / np.sum(proximity_weights)
- # return weighted_mean
-
- """Attempt 2 Inter-Quartile Mean (same accuracy as mean)"""
- # sorted_preds = np.sort(chunks, axis=0)
- # Q1 = int(np.floor(0.25 * len(sorted_preds)))
- # Q3 = int(np.floor(0.75 * len(sorted_preds)))
- #
- # iqm = np.mean(sorted_preds[Q1:Q3], axis=0)
- # return iqm