diff options
Diffstat (limited to 'ext/dsent/model/Model.cc')
-rw-r--r-- | ext/dsent/model/Model.cc | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/ext/dsent/model/Model.cc b/ext/dsent/model/Model.cc new file mode 100644 index 000000000..5a7bfe391 --- /dev/null +++ b/ext/dsent/model/Model.cc @@ -0,0 +1,698 @@ +#include "model/Model.h" + +#include <vector> + +#include "util/Result.h" + +namespace DSENT +{ + using std::vector; + using LibUtil::deletePtrMap; + using LibUtil::clonePtrMap; + + Model::SubModel::SubModel(Model* model_, double num_models_) + : m_model_(model_), m_num_models_(num_models_) + {} + + Model::SubModel::~SubModel() + { + delete m_model_; + } + + Model* Model::SubModel::getModel() + { + return m_model_; + } + + const Model* Model::SubModel::getModel() const + { + return m_model_; + } + + double Model::SubModel::getNumModels() const + { + return m_num_models_; + } + + Model::SubModel* Model::SubModel::clone() const + { + return new SubModel(*this); + } + + Model::SubModel::SubModel(const SubModel& sub_model_) + { + m_model_ = sub_model_.m_model_->clone(); + m_num_models_ = sub_model_.m_num_models_; + } + + const char Model::TYPE_SEPARATOR[] = ">>"; + const char Model::HIERARCHY_SEPARATOR[] = "->"; + const char Model::SUBFIELD_SEPARATOR[] = ":"; + const char Model::DETAIL_SEPARATOR[] = "@"; + + Model::Model(const String& instance_name_, const TechModel* tech_model_) + : m_instance_name_(instance_name_), m_tech_model_(tech_model_), + m_constructed_(false), m_updated_(false), m_evaluated_(false) + { + m_property_names_ = new vector<String>; + m_parameter_names_ = new vector<String>; + m_parameters_ = new ParameterMap(); + m_properties_ = new PropertyMap(); + m_generated_properties_ = new PropertyMap(); + m_sub_instances_ = new Map<SubModel*>(); + m_event_map_ = new Map<Result*>(); + m_area_map_ = new Map<Result*>(); + m_ndd_power_map_ = new Map<Result*>(); + } + + Model::~Model() + { + // Clear parameter names + delete m_parameter_names_; + // Clear property name + delete m_property_names_; + + // Clear parameters + delete m_parameters_; + m_parameters_ = NULL; + // Clear input properties + delete m_properties_; + m_properties_ = NULL; + + // Clear generated properties + delete m_generated_properties_; + m_generated_properties_ = NULL; + + // Clear sub models + deletePtrMap<SubModel>(m_sub_instances_); + m_sub_instances_ = NULL; + + // Clear all results + deletePtrMap<Result>(m_event_map_); + m_event_map_ = NULL; + deletePtrMap<Result>(m_area_map_); + m_area_map_ = NULL; + deletePtrMap<Result>(m_ndd_power_map_); + m_ndd_power_map_ = NULL; + } + + void Model::setInstanceName(const String& instance_name_) + { + m_instance_name_ = instance_name_; + return; + } + + const String& Model::getInstanceName() const + { + return m_instance_name_; + } + + void Model::setIsTopModel(bool is_top_model_) + { + m_is_top_model_ = is_top_model_; + return; + } + + bool Model::getIsTopModel() const + { + return m_is_top_model_; + } + + //------------------------------------------------------------------------- + // Parameters and properties checks + //------------------------------------------------------------------------- + void Model::addParameterName(const String& parameter_name_) + { + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + + " -> Cannot add additional parameters names after model is constructed!"); + m_parameter_names_->push_back(parameter_name_); + + return; + } + + void Model::addParameterName(const String& parameter_name_, const String& parameter_default_) + { + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + + " -> Cannot add additional parameters names after model is constructed!"); + m_parameter_names_->push_back(parameter_name_); + setParameter(parameter_name_, parameter_default_); + return; + } + + const vector<String>* Model::getParameterNames() const + { + return m_parameter_names_; + } + + void Model::addPropertyName(const String& property_name_) + { + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + + " -> Cannot add additional property names after model is constructed!"); + m_property_names_->push_back(property_name_); + return; + } + + void Model::addPropertyName(const String& property_name_, const String& property_default_) + { + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + + " -> Cannot add additional property names after model is constructed!"); + m_property_names_->push_back(property_name_); + setProperty(property_name_, property_default_); + return; + } + + const vector<String>* Model::getPropertyNames() const + { + return m_property_names_; + } + + void Model::checkParameters() const + { + String missing_parameters = ""; + + for(int i = 0; i < (int)m_parameter_names_->size(); ++i) + { + const String& parameter_name = m_parameter_names_->at(i); + if (!m_parameters_->keyExist(parameter_name)) + missing_parameters += " " + parameter_name + "\n"; + } + + ASSERT(missing_parameters.size() == 0, "[Error] " + m_instance_name_ + + " -> Missing parameters:\n" + missing_parameters); + return; + } + + void Model::checkProperties() const + { + String missing_properties = ""; + + for(int i = 0; i < (int)m_property_names_->size(); ++i) + { + const String& property_name = m_property_names_->at(i); + if (!m_properties_->keyExist(property_name)) + missing_properties += " " + property_name + "\n"; + } + + ASSERT(missing_properties.size() == 0, "[Error] " + m_instance_name_ + + " -> Missing properties:\n" + missing_properties); + return; + } + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Parameters Manipulation + //------------------------------------------------------------------------- + const ParameterMap* Model::getParameters() const + { + return m_parameters_; + } + + const String Model::getParameter(const String& parameter_name_) const + { + return m_parameters_->get(parameter_name_); + } + + void Model::setParameter(const String& parameter_name_, const String& parameter_value_) + { + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + + " -> Cannot set parameters after model is constructed!"); + m_parameters_->set(parameter_name_, parameter_value_); + } + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + // Properties Manipulation + //------------------------------------------------------------------------- + const PropertyMap* Model::getProperties() const + { + return m_properties_; + } + + const String Model::getProperty(const String& property_name_) const + { + return m_properties_->get(property_name_); + } + + void Model::setProperty(const String& property_name_, const String& property_value_) + { + // If any properties changed, reset updated and evaluated flags + m_updated_ = false; + m_evaluated_ = false; + m_properties_->set(property_name_, property_value_); + } + //------------------------------------------------------------------------- + + PropertyMap* Model::getGenProperties() + { + return m_generated_properties_; + } + + const PropertyMap* Model::getGenProperties() const + { + return m_generated_properties_; + } + + void Model::addSubInstances(Model* sub_instance_, double num_sub_instances_) + { + // Get instance name + const String& sub_instance_name = sub_instance_->getInstanceName(); + + // Check if the instance exists + if(m_sub_instances_->keyExist(sub_instance_name)) + { + const String& error_msg = "[Error] " + m_instance_name_ + + " -> Instance exists (" + sub_instance_name + ")"; + throw Exception(error_msg); + } + + // Check if the num_sub_instances_ is a positive number + ASSERT((num_sub_instances_ >= 0), "[Error] " + m_instance_name_ + + " -> Invalid number of instance (" + String(num_sub_instances_) + ")"); + + // Add the instance + m_sub_instances_->set(sub_instance_name, new SubModel(sub_instance_, num_sub_instances_)); + return; + } + + Model* Model::getSubInstance(const String& sub_instance_name_) + { + // Throw an Exception if the instance already exists + if(!m_sub_instances_->keyExist(sub_instance_name_)) + { + const String& error_msg = "[Error] " + m_instance_name_ + + " -> Instance not exists (" + sub_instance_name_ + ")"; + throw Exception(error_msg); + } + + return m_sub_instances_->get(sub_instance_name_)->getModel(); + } + + const Model* Model::getSubInstance(const String& sub_instance_name_) const + { + // Throw an Exception if the instance does not exist + if(!m_sub_instances_->keyExist(sub_instance_name_)) + { + const String& error_msg = "[Error] " + m_instance_name_ + + " -> Instance not exists (" + sub_instance_name_ + ")"; + throw Exception(error_msg); + } + + return m_sub_instances_->get(sub_instance_name_)->getModel(); + } + + bool Model::hasSubInstance(const String& sub_instance_name_) const + { + return m_sub_instances_->keyExist(sub_instance_name_); + } + + void Model::addAreaResult(Result* area_) + { + const String& area_name = area_->getName(); + + // Throw an Exception if the area already exists + if(m_area_map_->keyExist(area_name)) + { + const String& error_msg = "Internal error: area (" + area_name + + ") exists"; + throw Exception(error_msg); + } + + // Add the area + m_area_map_->set(area_name, area_); + return; + } + + Result* Model::getAreaResult(const String& area_name_) + { + return m_area_map_->get(area_name_); + } + + const Result* Model::getAreaResult(const String& area_name_) const + { + return m_area_map_->get(area_name_); + } + + bool Model::hasAreaResult(const String& area_name_) const + { + return m_area_map_->keyExist(area_name_); + } + + void Model::addNddPowerResult(Result* ndd_power_) + { + const String& ndd_power_name = ndd_power_->getName(); + + // Throw an Exception if the ndd_power already exists + if(m_ndd_power_map_->keyExist(ndd_power_name)) + { + const String& error_msg = "Internal error: ndd_power (" + ndd_power_name + + ") exists"; + throw Exception(error_msg); + } + + // Add the ndd_power + m_ndd_power_map_->set(ndd_power_name, ndd_power_); + return; + } + + Result* Model::getNddPowerResult(const String& ndd_power_name_) + { + return m_ndd_power_map_->get(ndd_power_name_); + } + + const Result* Model::getNddPowerResult(const String& ndd_power_name_) const + { + return m_ndd_power_map_->get(ndd_power_name_); + } + + bool Model::hasNddPowerResult(const String& ndd_power_name_) const + { + return m_ndd_power_map_->keyExist(ndd_power_name_); + } + + void Model::addEventResult(Result* event_) + { + const String& event_name = event_->getName(); + + // Throw an Exception if the event already exists + if(m_event_map_->keyExist(event_name)) + { + const String& error_msg = "Internal error: event (" + event_name + + ") exists"; + throw Exception(error_msg); + } + + // Add the event + m_event_map_->set(event_name, event_); + return; + } + + Result* Model::getEventResult(const String& event_name_) + { + return m_event_map_->get(event_name_); + } + + const Result* Model::getEventResult(const String& event_name_) const + { + return m_event_map_->get(event_name_); + } + + bool Model::hasEventResult(const String& event_name_) const + { + return m_event_map_->keyExist(event_name_); + } + + const TechModel* Model::getTechModel() const + { + return m_tech_model_; + } + + const void* Model::parseQuery(const String& query_type_, const String& query_hier_, const String& query_sub_field_) + { + // Break query by hierarchy separator + vector<String> hier_split = query_hier_.splitByString(HIERARCHY_SEPARATOR); + + // Check if the query_hier matches the instance name + ASSERT((hier_split[0] == m_instance_name_), "[Error] " + + m_instance_name_ + " -> Mismatch in instance name (" + + hier_split[0] + ")"); + + // If there is no more hierarchy separator, this process the query + if(hier_split.size() == 1) + { + // Query the model + return processQuery(query_type_, query_sub_field_); + } + else + { + // Reconstruct the query + String temp_query_hier = hier_split[1]; + for(int i = 2; i < (int)hier_split.size(); ++i) + { + temp_query_hier += HIERARCHY_SEPARATOR + hier_split[i]; + } + + // Get sub instance's name + const String& temp_sub_instance_name = hier_split[1]; + ASSERT(m_sub_instances_->keyExist(temp_sub_instance_name), "[Error] " + + m_instance_name_ + " -> No sub-instances queried (" + + temp_sub_instance_name + ")"); + + return m_sub_instances_->get(temp_sub_instance_name)->getModel()->parseQuery(query_type_, temp_query_hier, query_sub_field_); + } + } + + const void* Model::processQuery(const String& query_type_, const String& query_sub_field_) + { + if(query_type_ == "Property") + { + return getProperties(); + } + else if(query_type_ == "Parameter") + { + return getParameters(); + } + else if(query_type_.contain("Hier")) + { + return this; + } + else if(query_type_ == "Area") + { + return queryArea(query_sub_field_); + } + else if(query_type_ == "NddPower") + { + return queryNddPower(query_sub_field_); + } + else if(query_type_ == "Energy") + { + return queryEventEnergyCost(query_sub_field_); + } + else + { + const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; + throw Exception(error_msg); + return NULL; + } + } + + const Result* Model::queryArea(const String& area_name_) const + { + ASSERT(m_area_map_->keyExist(area_name_), "[Error] " + m_instance_name_ + + " -> Unknown queried area name (" + area_name_ + ")"); + return m_area_map_->get(area_name_); + } + + const Result* Model::queryNddPower(const String& ndd_power_name_) + { + ASSERT(m_ndd_power_map_->keyExist(ndd_power_name_), "[Error] " + m_instance_name_ + + " -> Unknown queried ndd power name (" + ndd_power_name_ + ")"); + + use("Idle"); + return m_ndd_power_map_->get(ndd_power_name_); + } + + const Result* Model::queryEventEnergyCost(const String& event_name_) + { + ASSERT(m_event_map_->keyExist(event_name_), "[Error] " + m_instance_name_ + + " -> Unknown queried event name (" + event_name_ + ")"); + + use(event_name_); + return m_event_map_->get(event_name_); + } + + // Update checks whether the model needs updating, whether all properties have been specified, + // and calls updateModel if update is necessary + void Model::construct() + { + // Model should not be constructed yet + ASSERT(!m_constructed_, "[Error] " + getInstanceName() + " -> Cannot construct an already contructed model!"); + // Check if whether all needed parameters are defined + checkParameters(); + constructModel(); + m_constructed_ = true; + m_updated_ = false; + m_evaluated_ = false; + return; + } + + // Update checks whether the model needs updating, whether all properties have been specified, + // and calls updateModel if update is necessary + void Model::update() + { + // Model should be constructed + ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot update an unconstructed model!"); + // If the model needs updating (due to property change) + // an update is necessary + if (!m_updated_) + { + // Check if all properties needed exist + checkProperties(); + updateModel(); + m_updated_ = true; + m_evaluated_ = false; + } + return; + } + + // Evaluate checks whether the model needs to be evaluated. + void Model::evaluate() + { + // Model should be constructed + ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot evaluate an unconstructed model!"); + // Model should be updated + ASSERT(m_updated_, "[Error] " + getInstanceName() + " -> Cannot evaluate without first updating!"); + // If the model needs evaluating + if (!m_evaluated_) + { + evaluateModel(); + m_evaluated_ = true; + } + + return; + } + + void Model::use(const String& event_name_) + { + useModel(event_name_); + return; + } + + void Model::use() + { + useModel(); + return; + } + + // By default, update model will iterate through all sub-instances and do updateModel on them + void Model::updateModel() + { + Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); + Map<SubModel*>::Iterator end = m_sub_instances_->end(); + while (iter != end) + { + iter->second->getModel()->update(); + iter++; + } + return; + } + + // By default, update model will iterate through all sub-instances and do updateModel on them + void Model::evaluateModel() + { + Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); + Map<SubModel*>::Iterator end = m_sub_instances_->end(); + while (iter != end) + { + iter->second->getModel()->evaluate(); + iter++; + } + return; + } + + void Model::useModel(const String& /* event_name_ */) + {} + + void Model::useModel() + {} + + void Model::printHierarchy(const String& query_type_, const String& query_sub_field_, const String& prepend_str_, int detail_level_, ostream& ost_) const + { + if(query_type_ == "InstHier") + { + ost_ << prepend_str_ << getInstanceName() << endl; + printInstHierarchy(prepend_str_, detail_level_, ost_); + //if(detail_level_ > 0) + //{ + //for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) + //{ + //const Model* sub_model = (it->second)->getModel(); + //String temp_prepend_str = prepend_str_ + " "; + //sub_model->printHierarchy(query_type_, query_sub_field_, temp_prepend_str, detail_level_ - 1, ost_); + //} + //} + } + else + { + const Map<Result*>* result_map; + + if(query_type_ == "AreaHier") + { + result_map = m_area_map_; + } + else if(query_type_ == "NddPowerHier") + { + result_map = m_ndd_power_map_; + } + else if(query_type_ == "EventHier") + { + result_map = m_event_map_; + } + else + { + const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; + throw Exception(error_msg); + return; + } + + if(query_sub_field_ == "") + { + for(Map<Result*>::ConstIterator it = result_map->begin(); it != result_map->end(); ++it) + { + const Result* result = it->second; + ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; + result->printHierarchy(prepend_str_, detail_level_, ost_); + } + } + else + { + const Result* result = result_map->get(query_sub_field_); + ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; + result->printHierarchy(prepend_str_, detail_level_, ost_); + } + } + return; + } + + void Model::printInstHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const + { + if(detail_level_ > 0) + { + for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) + { + const Model* sub_model = it->second->getModel(); + String temp_prepend_str = prepend_str_ + " "; + + ost_ << prepend_str_ << " |--" << sub_model->getInstanceName() << endl; + sub_model->printInstHierarchy(temp_prepend_str, detail_level_ - 1, ost_); + } + } + return; + } + + Model* Model::clone() const + { + throw Exception(getInstanceName() + " -> Cannot be cloned!"); + } + + Model::Model(const Model& model_) + { + // Copy instance's name + m_instance_name_ = model_.m_instance_name_; + + // Clone properties + m_properties_ = model_.m_properties_->clone(); + + // Clone instances + m_sub_instances_ = clonePtrMap(model_.m_sub_instances_); + + // Clone events, area, ndd_power + m_event_map_ = clonePtrMap(model_.m_event_map_); + m_area_map_ = clonePtrMap(model_.m_area_map_); + m_ndd_power_map_ = clonePtrMap(model_.m_ndd_power_map_); + + // Copy tech model pointer + m_tech_model_ = model_.m_tech_model_; + } + +} // namespace DSENT + |