110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology 210448Snilay@cs.wisc.edu * 310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy 410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal 510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights 610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is 810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions: 910448Snilay@cs.wisc.edu * 1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in 1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software. 1210448Snilay@cs.wisc.edu * 1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1910448Snilay@cs.wisc.edu * THE SOFTWARE. 2010448Snilay@cs.wisc.edu */ 2110448Snilay@cs.wisc.edu 2210447Snilay@cs.wisc.edu#include "model/Model.h" 2310447Snilay@cs.wisc.edu 2410447Snilay@cs.wisc.edu#include <vector> 2510447Snilay@cs.wisc.edu 2610447Snilay@cs.wisc.edu#include "util/Result.h" 2710447Snilay@cs.wisc.edu 2810447Snilay@cs.wisc.edunamespace DSENT 2910447Snilay@cs.wisc.edu{ 3010447Snilay@cs.wisc.edu using std::vector; 3110447Snilay@cs.wisc.edu using LibUtil::deletePtrMap; 3210447Snilay@cs.wisc.edu using LibUtil::clonePtrMap; 3310447Snilay@cs.wisc.edu 3410447Snilay@cs.wisc.edu Model::SubModel::SubModel(Model* model_, double num_models_) 3510447Snilay@cs.wisc.edu : m_model_(model_), m_num_models_(num_models_) 3610447Snilay@cs.wisc.edu {} 3710447Snilay@cs.wisc.edu 3810447Snilay@cs.wisc.edu Model::SubModel::~SubModel() 3910447Snilay@cs.wisc.edu { 4010447Snilay@cs.wisc.edu delete m_model_; 4110447Snilay@cs.wisc.edu } 4210447Snilay@cs.wisc.edu 4310447Snilay@cs.wisc.edu Model* Model::SubModel::getModel() 4410447Snilay@cs.wisc.edu { 4510447Snilay@cs.wisc.edu return m_model_; 4610447Snilay@cs.wisc.edu } 4710447Snilay@cs.wisc.edu 4810447Snilay@cs.wisc.edu const Model* Model::SubModel::getModel() const 4910447Snilay@cs.wisc.edu { 5010447Snilay@cs.wisc.edu return m_model_; 5110447Snilay@cs.wisc.edu } 5210447Snilay@cs.wisc.edu 5310447Snilay@cs.wisc.edu double Model::SubModel::getNumModels() const 5410447Snilay@cs.wisc.edu { 5510447Snilay@cs.wisc.edu return m_num_models_; 5610447Snilay@cs.wisc.edu } 5710447Snilay@cs.wisc.edu 5810447Snilay@cs.wisc.edu Model::SubModel* Model::SubModel::clone() const 5910447Snilay@cs.wisc.edu { 6010447Snilay@cs.wisc.edu return new SubModel(*this); 6110447Snilay@cs.wisc.edu } 6210447Snilay@cs.wisc.edu 6310447Snilay@cs.wisc.edu Model::SubModel::SubModel(const SubModel& sub_model_) 6410447Snilay@cs.wisc.edu { 6510447Snilay@cs.wisc.edu m_model_ = sub_model_.m_model_->clone(); 6610447Snilay@cs.wisc.edu m_num_models_ = sub_model_.m_num_models_; 6710447Snilay@cs.wisc.edu } 6810447Snilay@cs.wisc.edu 6910447Snilay@cs.wisc.edu const char Model::TYPE_SEPARATOR[] = ">>"; 7010447Snilay@cs.wisc.edu const char Model::HIERARCHY_SEPARATOR[] = "->"; 7110447Snilay@cs.wisc.edu const char Model::SUBFIELD_SEPARATOR[] = ":"; 7210447Snilay@cs.wisc.edu const char Model::DETAIL_SEPARATOR[] = "@"; 7310447Snilay@cs.wisc.edu 7410447Snilay@cs.wisc.edu Model::Model(const String& instance_name_, const TechModel* tech_model_) 7510447Snilay@cs.wisc.edu : m_instance_name_(instance_name_), m_tech_model_(tech_model_), 7610447Snilay@cs.wisc.edu m_constructed_(false), m_updated_(false), m_evaluated_(false) 7710447Snilay@cs.wisc.edu { 7810447Snilay@cs.wisc.edu m_property_names_ = new vector<String>; 7910447Snilay@cs.wisc.edu m_parameter_names_ = new vector<String>; 8010447Snilay@cs.wisc.edu m_parameters_ = new ParameterMap(); 8110447Snilay@cs.wisc.edu m_properties_ = new PropertyMap(); 8210447Snilay@cs.wisc.edu m_generated_properties_ = new PropertyMap(); 8310447Snilay@cs.wisc.edu m_sub_instances_ = new Map<SubModel*>(); 8410447Snilay@cs.wisc.edu m_event_map_ = new Map<Result*>(); 8510447Snilay@cs.wisc.edu m_area_map_ = new Map<Result*>(); 8610447Snilay@cs.wisc.edu m_ndd_power_map_ = new Map<Result*>(); 8710447Snilay@cs.wisc.edu } 8810447Snilay@cs.wisc.edu 8910447Snilay@cs.wisc.edu Model::~Model() 9010447Snilay@cs.wisc.edu { 9110447Snilay@cs.wisc.edu // Clear parameter names 9210447Snilay@cs.wisc.edu delete m_parameter_names_; 9310447Snilay@cs.wisc.edu // Clear property name 9410447Snilay@cs.wisc.edu delete m_property_names_; 9510447Snilay@cs.wisc.edu 9610447Snilay@cs.wisc.edu // Clear parameters 9710447Snilay@cs.wisc.edu delete m_parameters_; 9810447Snilay@cs.wisc.edu m_parameters_ = NULL; 9910447Snilay@cs.wisc.edu // Clear input properties 10010447Snilay@cs.wisc.edu delete m_properties_; 10110447Snilay@cs.wisc.edu m_properties_ = NULL; 10210447Snilay@cs.wisc.edu 10310447Snilay@cs.wisc.edu // Clear generated properties 10410447Snilay@cs.wisc.edu delete m_generated_properties_; 10510447Snilay@cs.wisc.edu m_generated_properties_ = NULL; 10610447Snilay@cs.wisc.edu 10710447Snilay@cs.wisc.edu // Clear sub models 10810447Snilay@cs.wisc.edu deletePtrMap<SubModel>(m_sub_instances_); 10910447Snilay@cs.wisc.edu m_sub_instances_ = NULL; 11010447Snilay@cs.wisc.edu 11110447Snilay@cs.wisc.edu // Clear all results 11210447Snilay@cs.wisc.edu deletePtrMap<Result>(m_event_map_); 11310447Snilay@cs.wisc.edu m_event_map_ = NULL; 11410447Snilay@cs.wisc.edu deletePtrMap<Result>(m_area_map_); 11510447Snilay@cs.wisc.edu m_area_map_ = NULL; 11610447Snilay@cs.wisc.edu deletePtrMap<Result>(m_ndd_power_map_); 11710447Snilay@cs.wisc.edu m_ndd_power_map_ = NULL; 11810447Snilay@cs.wisc.edu } 11910447Snilay@cs.wisc.edu 12010447Snilay@cs.wisc.edu void Model::setInstanceName(const String& instance_name_) 12110447Snilay@cs.wisc.edu { 12210447Snilay@cs.wisc.edu m_instance_name_ = instance_name_; 12310447Snilay@cs.wisc.edu return; 12410447Snilay@cs.wisc.edu } 12510447Snilay@cs.wisc.edu 12610447Snilay@cs.wisc.edu const String& Model::getInstanceName() const 12710447Snilay@cs.wisc.edu { 12810447Snilay@cs.wisc.edu return m_instance_name_; 12910447Snilay@cs.wisc.edu } 13010447Snilay@cs.wisc.edu 13110447Snilay@cs.wisc.edu void Model::setIsTopModel(bool is_top_model_) 13210447Snilay@cs.wisc.edu { 13310447Snilay@cs.wisc.edu m_is_top_model_ = is_top_model_; 13410447Snilay@cs.wisc.edu return; 13510447Snilay@cs.wisc.edu } 13610447Snilay@cs.wisc.edu 13710447Snilay@cs.wisc.edu bool Model::getIsTopModel() const 13810447Snilay@cs.wisc.edu { 13910447Snilay@cs.wisc.edu return m_is_top_model_; 14010447Snilay@cs.wisc.edu } 14110447Snilay@cs.wisc.edu 14210447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 14310447Snilay@cs.wisc.edu // Parameters and properties checks 14410447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 14510447Snilay@cs.wisc.edu void Model::addParameterName(const String& parameter_name_) 14610447Snilay@cs.wisc.edu { 14710447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 14810447Snilay@cs.wisc.edu " -> Cannot add additional parameters names after model is constructed!"); 14910447Snilay@cs.wisc.edu m_parameter_names_->push_back(parameter_name_); 15010447Snilay@cs.wisc.edu 15110447Snilay@cs.wisc.edu return; 15210447Snilay@cs.wisc.edu } 15310447Snilay@cs.wisc.edu 15410447Snilay@cs.wisc.edu void Model::addParameterName(const String& parameter_name_, const String& parameter_default_) 15510447Snilay@cs.wisc.edu { 15610447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 15710447Snilay@cs.wisc.edu " -> Cannot add additional parameters names after model is constructed!"); 15810447Snilay@cs.wisc.edu m_parameter_names_->push_back(parameter_name_); 15910447Snilay@cs.wisc.edu setParameter(parameter_name_, parameter_default_); 16010447Snilay@cs.wisc.edu return; 16110447Snilay@cs.wisc.edu } 16210447Snilay@cs.wisc.edu 16310447Snilay@cs.wisc.edu const vector<String>* Model::getParameterNames() const 16410447Snilay@cs.wisc.edu { 16510447Snilay@cs.wisc.edu return m_parameter_names_; 16610447Snilay@cs.wisc.edu } 16710447Snilay@cs.wisc.edu 16810447Snilay@cs.wisc.edu void Model::addPropertyName(const String& property_name_) 16910447Snilay@cs.wisc.edu { 17010447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 17110447Snilay@cs.wisc.edu " -> Cannot add additional property names after model is constructed!"); 17210447Snilay@cs.wisc.edu m_property_names_->push_back(property_name_); 17310447Snilay@cs.wisc.edu return; 17410447Snilay@cs.wisc.edu } 17510447Snilay@cs.wisc.edu 17610447Snilay@cs.wisc.edu void Model::addPropertyName(const String& property_name_, const String& property_default_) 17710447Snilay@cs.wisc.edu { 17810447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 17910447Snilay@cs.wisc.edu " -> Cannot add additional property names after model is constructed!"); 18010447Snilay@cs.wisc.edu m_property_names_->push_back(property_name_); 18110447Snilay@cs.wisc.edu setProperty(property_name_, property_default_); 18210447Snilay@cs.wisc.edu return; 18310447Snilay@cs.wisc.edu } 18410447Snilay@cs.wisc.edu 18510447Snilay@cs.wisc.edu const vector<String>* Model::getPropertyNames() const 18610447Snilay@cs.wisc.edu { 18710447Snilay@cs.wisc.edu return m_property_names_; 18810447Snilay@cs.wisc.edu } 18910447Snilay@cs.wisc.edu 19010447Snilay@cs.wisc.edu void Model::checkParameters() const 19110447Snilay@cs.wisc.edu { 19210447Snilay@cs.wisc.edu String missing_parameters = ""; 19310447Snilay@cs.wisc.edu 19410447Snilay@cs.wisc.edu for(int i = 0; i < (int)m_parameter_names_->size(); ++i) 19510447Snilay@cs.wisc.edu { 19610447Snilay@cs.wisc.edu const String& parameter_name = m_parameter_names_->at(i); 19710447Snilay@cs.wisc.edu if (!m_parameters_->keyExist(parameter_name)) 19810447Snilay@cs.wisc.edu missing_parameters += " " + parameter_name + "\n"; 19910447Snilay@cs.wisc.edu } 20010447Snilay@cs.wisc.edu 20110447Snilay@cs.wisc.edu ASSERT(missing_parameters.size() == 0, "[Error] " + m_instance_name_ + 20210447Snilay@cs.wisc.edu " -> Missing parameters:\n" + missing_parameters); 20310447Snilay@cs.wisc.edu return; 20410447Snilay@cs.wisc.edu } 20510447Snilay@cs.wisc.edu 20610447Snilay@cs.wisc.edu void Model::checkProperties() const 20710447Snilay@cs.wisc.edu { 20810447Snilay@cs.wisc.edu String missing_properties = ""; 20910447Snilay@cs.wisc.edu 21010447Snilay@cs.wisc.edu for(int i = 0; i < (int)m_property_names_->size(); ++i) 21110447Snilay@cs.wisc.edu { 21210447Snilay@cs.wisc.edu const String& property_name = m_property_names_->at(i); 21310447Snilay@cs.wisc.edu if (!m_properties_->keyExist(property_name)) 21410447Snilay@cs.wisc.edu missing_properties += " " + property_name + "\n"; 21510447Snilay@cs.wisc.edu } 21610447Snilay@cs.wisc.edu 21710447Snilay@cs.wisc.edu ASSERT(missing_properties.size() == 0, "[Error] " + m_instance_name_ + 21810447Snilay@cs.wisc.edu " -> Missing properties:\n" + missing_properties); 21910447Snilay@cs.wisc.edu return; 22010447Snilay@cs.wisc.edu } 22110447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 22210447Snilay@cs.wisc.edu 22310447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 22410447Snilay@cs.wisc.edu // Parameters Manipulation 22510447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 22610447Snilay@cs.wisc.edu const ParameterMap* Model::getParameters() const 22710447Snilay@cs.wisc.edu { 22810447Snilay@cs.wisc.edu return m_parameters_; 22910447Snilay@cs.wisc.edu } 23010447Snilay@cs.wisc.edu 23110447Snilay@cs.wisc.edu const String Model::getParameter(const String& parameter_name_) const 23210447Snilay@cs.wisc.edu { 23310447Snilay@cs.wisc.edu return m_parameters_->get(parameter_name_); 23410447Snilay@cs.wisc.edu } 23510447Snilay@cs.wisc.edu 23610447Snilay@cs.wisc.edu void Model::setParameter(const String& parameter_name_, const String& parameter_value_) 23710447Snilay@cs.wisc.edu { 23810447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 23910447Snilay@cs.wisc.edu " -> Cannot set parameters after model is constructed!"); 24010447Snilay@cs.wisc.edu m_parameters_->set(parameter_name_, parameter_value_); 24110447Snilay@cs.wisc.edu } 24210447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 24310447Snilay@cs.wisc.edu 24410447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 24510447Snilay@cs.wisc.edu // Properties Manipulation 24610447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 24710447Snilay@cs.wisc.edu const PropertyMap* Model::getProperties() const 24810447Snilay@cs.wisc.edu { 24910447Snilay@cs.wisc.edu return m_properties_; 25010447Snilay@cs.wisc.edu } 25110447Snilay@cs.wisc.edu 25210447Snilay@cs.wisc.edu const String Model::getProperty(const String& property_name_) const 25310447Snilay@cs.wisc.edu { 25410447Snilay@cs.wisc.edu return m_properties_->get(property_name_); 25510447Snilay@cs.wisc.edu } 25610447Snilay@cs.wisc.edu 25710447Snilay@cs.wisc.edu void Model::setProperty(const String& property_name_, const String& property_value_) 25810447Snilay@cs.wisc.edu { 25910447Snilay@cs.wisc.edu // If any properties changed, reset updated and evaluated flags 26010447Snilay@cs.wisc.edu m_updated_ = false; 26110447Snilay@cs.wisc.edu m_evaluated_ = false; 26210447Snilay@cs.wisc.edu m_properties_->set(property_name_, property_value_); 26310447Snilay@cs.wisc.edu } 26410447Snilay@cs.wisc.edu //------------------------------------------------------------------------- 26510447Snilay@cs.wisc.edu 26610447Snilay@cs.wisc.edu PropertyMap* Model::getGenProperties() 26710447Snilay@cs.wisc.edu { 26810447Snilay@cs.wisc.edu return m_generated_properties_; 26910447Snilay@cs.wisc.edu } 27010447Snilay@cs.wisc.edu 27110447Snilay@cs.wisc.edu const PropertyMap* Model::getGenProperties() const 27210447Snilay@cs.wisc.edu { 27310447Snilay@cs.wisc.edu return m_generated_properties_; 27410447Snilay@cs.wisc.edu } 27510447Snilay@cs.wisc.edu 27610447Snilay@cs.wisc.edu void Model::addSubInstances(Model* sub_instance_, double num_sub_instances_) 27710447Snilay@cs.wisc.edu { 27810447Snilay@cs.wisc.edu // Get instance name 27910447Snilay@cs.wisc.edu const String& sub_instance_name = sub_instance_->getInstanceName(); 28010447Snilay@cs.wisc.edu 28110447Snilay@cs.wisc.edu // Check if the instance exists 28210447Snilay@cs.wisc.edu if(m_sub_instances_->keyExist(sub_instance_name)) 28310447Snilay@cs.wisc.edu { 28410447Snilay@cs.wisc.edu const String& error_msg = "[Error] " + m_instance_name_ + 28510447Snilay@cs.wisc.edu " -> Instance exists (" + sub_instance_name + ")"; 28610447Snilay@cs.wisc.edu throw Exception(error_msg); 28710447Snilay@cs.wisc.edu } 28810447Snilay@cs.wisc.edu 28910447Snilay@cs.wisc.edu // Check if the num_sub_instances_ is a positive number 29010447Snilay@cs.wisc.edu ASSERT((num_sub_instances_ >= 0), "[Error] " + m_instance_name_ + 29110447Snilay@cs.wisc.edu " -> Invalid number of instance (" + String(num_sub_instances_) + ")"); 29210447Snilay@cs.wisc.edu 29310447Snilay@cs.wisc.edu // Add the instance 29410447Snilay@cs.wisc.edu m_sub_instances_->set(sub_instance_name, new SubModel(sub_instance_, num_sub_instances_)); 29510447Snilay@cs.wisc.edu return; 29610447Snilay@cs.wisc.edu } 29710447Snilay@cs.wisc.edu 29810447Snilay@cs.wisc.edu Model* Model::getSubInstance(const String& sub_instance_name_) 29910447Snilay@cs.wisc.edu { 30010447Snilay@cs.wisc.edu // Throw an Exception if the instance already exists 30110447Snilay@cs.wisc.edu if(!m_sub_instances_->keyExist(sub_instance_name_)) 30210447Snilay@cs.wisc.edu { 30310447Snilay@cs.wisc.edu const String& error_msg = "[Error] " + m_instance_name_ + 30410447Snilay@cs.wisc.edu " -> Instance not exists (" + sub_instance_name_ + ")"; 30510447Snilay@cs.wisc.edu throw Exception(error_msg); 30610447Snilay@cs.wisc.edu } 30710447Snilay@cs.wisc.edu 30810447Snilay@cs.wisc.edu return m_sub_instances_->get(sub_instance_name_)->getModel(); 30910447Snilay@cs.wisc.edu } 31010447Snilay@cs.wisc.edu 31110447Snilay@cs.wisc.edu const Model* Model::getSubInstance(const String& sub_instance_name_) const 31210447Snilay@cs.wisc.edu { 31310447Snilay@cs.wisc.edu // Throw an Exception if the instance does not exist 31410447Snilay@cs.wisc.edu if(!m_sub_instances_->keyExist(sub_instance_name_)) 31510447Snilay@cs.wisc.edu { 31610447Snilay@cs.wisc.edu const String& error_msg = "[Error] " + m_instance_name_ + 31710447Snilay@cs.wisc.edu " -> Instance not exists (" + sub_instance_name_ + ")"; 31810447Snilay@cs.wisc.edu throw Exception(error_msg); 31910447Snilay@cs.wisc.edu } 32010447Snilay@cs.wisc.edu 32110447Snilay@cs.wisc.edu return m_sub_instances_->get(sub_instance_name_)->getModel(); 32210447Snilay@cs.wisc.edu } 32310447Snilay@cs.wisc.edu 32410447Snilay@cs.wisc.edu bool Model::hasSubInstance(const String& sub_instance_name_) const 32510447Snilay@cs.wisc.edu { 32610447Snilay@cs.wisc.edu return m_sub_instances_->keyExist(sub_instance_name_); 32710447Snilay@cs.wisc.edu } 32810447Snilay@cs.wisc.edu 32910447Snilay@cs.wisc.edu void Model::addAreaResult(Result* area_) 33010447Snilay@cs.wisc.edu { 33110447Snilay@cs.wisc.edu const String& area_name = area_->getName(); 33210447Snilay@cs.wisc.edu 33310447Snilay@cs.wisc.edu // Throw an Exception if the area already exists 33410447Snilay@cs.wisc.edu if(m_area_map_->keyExist(area_name)) 33510447Snilay@cs.wisc.edu { 33610447Snilay@cs.wisc.edu const String& error_msg = "Internal error: area (" + area_name + 33710447Snilay@cs.wisc.edu ") exists"; 33810447Snilay@cs.wisc.edu throw Exception(error_msg); 33910447Snilay@cs.wisc.edu } 34010447Snilay@cs.wisc.edu 34110447Snilay@cs.wisc.edu // Add the area 34210447Snilay@cs.wisc.edu m_area_map_->set(area_name, area_); 34310447Snilay@cs.wisc.edu return; 34410447Snilay@cs.wisc.edu } 34510447Snilay@cs.wisc.edu 34610447Snilay@cs.wisc.edu Result* Model::getAreaResult(const String& area_name_) 34710447Snilay@cs.wisc.edu { 34810447Snilay@cs.wisc.edu return m_area_map_->get(area_name_); 34910447Snilay@cs.wisc.edu } 35010447Snilay@cs.wisc.edu 35110447Snilay@cs.wisc.edu const Result* Model::getAreaResult(const String& area_name_) const 35210447Snilay@cs.wisc.edu { 35310447Snilay@cs.wisc.edu return m_area_map_->get(area_name_); 35410447Snilay@cs.wisc.edu } 35510447Snilay@cs.wisc.edu 35610447Snilay@cs.wisc.edu bool Model::hasAreaResult(const String& area_name_) const 35710447Snilay@cs.wisc.edu { 35810447Snilay@cs.wisc.edu return m_area_map_->keyExist(area_name_); 35910447Snilay@cs.wisc.edu } 36010447Snilay@cs.wisc.edu 36110447Snilay@cs.wisc.edu void Model::addNddPowerResult(Result* ndd_power_) 36210447Snilay@cs.wisc.edu { 36310447Snilay@cs.wisc.edu const String& ndd_power_name = ndd_power_->getName(); 36410447Snilay@cs.wisc.edu 36510447Snilay@cs.wisc.edu // Throw an Exception if the ndd_power already exists 36610447Snilay@cs.wisc.edu if(m_ndd_power_map_->keyExist(ndd_power_name)) 36710447Snilay@cs.wisc.edu { 36810447Snilay@cs.wisc.edu const String& error_msg = "Internal error: ndd_power (" + ndd_power_name + 36910447Snilay@cs.wisc.edu ") exists"; 37010447Snilay@cs.wisc.edu throw Exception(error_msg); 37110447Snilay@cs.wisc.edu } 37210447Snilay@cs.wisc.edu 37310447Snilay@cs.wisc.edu // Add the ndd_power 37410447Snilay@cs.wisc.edu m_ndd_power_map_->set(ndd_power_name, ndd_power_); 37510447Snilay@cs.wisc.edu return; 37610447Snilay@cs.wisc.edu } 37710447Snilay@cs.wisc.edu 37810447Snilay@cs.wisc.edu Result* Model::getNddPowerResult(const String& ndd_power_name_) 37910447Snilay@cs.wisc.edu { 38010447Snilay@cs.wisc.edu return m_ndd_power_map_->get(ndd_power_name_); 38110447Snilay@cs.wisc.edu } 38210447Snilay@cs.wisc.edu 38310447Snilay@cs.wisc.edu const Result* Model::getNddPowerResult(const String& ndd_power_name_) const 38410447Snilay@cs.wisc.edu { 38510447Snilay@cs.wisc.edu return m_ndd_power_map_->get(ndd_power_name_); 38610447Snilay@cs.wisc.edu } 38710447Snilay@cs.wisc.edu 38810447Snilay@cs.wisc.edu bool Model::hasNddPowerResult(const String& ndd_power_name_) const 38910447Snilay@cs.wisc.edu { 39010447Snilay@cs.wisc.edu return m_ndd_power_map_->keyExist(ndd_power_name_); 39110447Snilay@cs.wisc.edu } 39210447Snilay@cs.wisc.edu 39310447Snilay@cs.wisc.edu void Model::addEventResult(Result* event_) 39410447Snilay@cs.wisc.edu { 39510447Snilay@cs.wisc.edu const String& event_name = event_->getName(); 39610447Snilay@cs.wisc.edu 39710447Snilay@cs.wisc.edu // Throw an Exception if the event already exists 39810447Snilay@cs.wisc.edu if(m_event_map_->keyExist(event_name)) 39910447Snilay@cs.wisc.edu { 40010447Snilay@cs.wisc.edu const String& error_msg = "Internal error: event (" + event_name + 40110447Snilay@cs.wisc.edu ") exists"; 40210447Snilay@cs.wisc.edu throw Exception(error_msg); 40310447Snilay@cs.wisc.edu } 40410447Snilay@cs.wisc.edu 40510447Snilay@cs.wisc.edu // Add the event 40610447Snilay@cs.wisc.edu m_event_map_->set(event_name, event_); 40710447Snilay@cs.wisc.edu return; 40810447Snilay@cs.wisc.edu } 40910447Snilay@cs.wisc.edu 41010447Snilay@cs.wisc.edu Result* Model::getEventResult(const String& event_name_) 41110447Snilay@cs.wisc.edu { 41210447Snilay@cs.wisc.edu return m_event_map_->get(event_name_); 41310447Snilay@cs.wisc.edu } 41410447Snilay@cs.wisc.edu 41510447Snilay@cs.wisc.edu const Result* Model::getEventResult(const String& event_name_) const 41610447Snilay@cs.wisc.edu { 41710447Snilay@cs.wisc.edu return m_event_map_->get(event_name_); 41810447Snilay@cs.wisc.edu } 41910447Snilay@cs.wisc.edu 42010447Snilay@cs.wisc.edu bool Model::hasEventResult(const String& event_name_) const 42110447Snilay@cs.wisc.edu { 42210447Snilay@cs.wisc.edu return m_event_map_->keyExist(event_name_); 42310447Snilay@cs.wisc.edu } 42410447Snilay@cs.wisc.edu 42510447Snilay@cs.wisc.edu const TechModel* Model::getTechModel() const 42610447Snilay@cs.wisc.edu { 42710447Snilay@cs.wisc.edu return m_tech_model_; 42810447Snilay@cs.wisc.edu } 42910447Snilay@cs.wisc.edu 43010447Snilay@cs.wisc.edu const void* Model::parseQuery(const String& query_type_, const String& query_hier_, const String& query_sub_field_) 43110447Snilay@cs.wisc.edu { 43210447Snilay@cs.wisc.edu // Break query by hierarchy separator 43310447Snilay@cs.wisc.edu vector<String> hier_split = query_hier_.splitByString(HIERARCHY_SEPARATOR); 43410447Snilay@cs.wisc.edu 43510447Snilay@cs.wisc.edu // Check if the query_hier matches the instance name 43610447Snilay@cs.wisc.edu ASSERT((hier_split[0] == m_instance_name_), "[Error] " + 43710447Snilay@cs.wisc.edu m_instance_name_ + " -> Mismatch in instance name (" + 43810447Snilay@cs.wisc.edu hier_split[0] + ")"); 43910447Snilay@cs.wisc.edu 44010447Snilay@cs.wisc.edu // If there is no more hierarchy separator, this process the query 44110447Snilay@cs.wisc.edu if(hier_split.size() == 1) 44210447Snilay@cs.wisc.edu { 44310447Snilay@cs.wisc.edu // Query the model 44410447Snilay@cs.wisc.edu return processQuery(query_type_, query_sub_field_); 44510447Snilay@cs.wisc.edu } 44610447Snilay@cs.wisc.edu else 44710447Snilay@cs.wisc.edu { 44810447Snilay@cs.wisc.edu // Reconstruct the query 44910447Snilay@cs.wisc.edu String temp_query_hier = hier_split[1]; 45010447Snilay@cs.wisc.edu for(int i = 2; i < (int)hier_split.size(); ++i) 45110447Snilay@cs.wisc.edu { 45210447Snilay@cs.wisc.edu temp_query_hier += HIERARCHY_SEPARATOR + hier_split[i]; 45310447Snilay@cs.wisc.edu } 45410447Snilay@cs.wisc.edu 45510447Snilay@cs.wisc.edu // Get sub instance's name 45610447Snilay@cs.wisc.edu const String& temp_sub_instance_name = hier_split[1]; 45710447Snilay@cs.wisc.edu ASSERT(m_sub_instances_->keyExist(temp_sub_instance_name), "[Error] " + 45810447Snilay@cs.wisc.edu m_instance_name_ + " -> No sub-instances queried (" + 45910447Snilay@cs.wisc.edu temp_sub_instance_name + ")"); 46010447Snilay@cs.wisc.edu 46110447Snilay@cs.wisc.edu return m_sub_instances_->get(temp_sub_instance_name)->getModel()->parseQuery(query_type_, temp_query_hier, query_sub_field_); 46210447Snilay@cs.wisc.edu } 46310447Snilay@cs.wisc.edu } 46410447Snilay@cs.wisc.edu 46510447Snilay@cs.wisc.edu const void* Model::processQuery(const String& query_type_, const String& query_sub_field_) 46610447Snilay@cs.wisc.edu { 46710447Snilay@cs.wisc.edu if(query_type_ == "Property") 46810447Snilay@cs.wisc.edu { 46910447Snilay@cs.wisc.edu return getProperties(); 47010447Snilay@cs.wisc.edu } 47110447Snilay@cs.wisc.edu else if(query_type_ == "Parameter") 47210447Snilay@cs.wisc.edu { 47310447Snilay@cs.wisc.edu return getParameters(); 47410447Snilay@cs.wisc.edu } 47510447Snilay@cs.wisc.edu else if(query_type_.contain("Hier")) 47610447Snilay@cs.wisc.edu { 47710447Snilay@cs.wisc.edu return this; 47810447Snilay@cs.wisc.edu } 47910447Snilay@cs.wisc.edu else if(query_type_ == "Area") 48010447Snilay@cs.wisc.edu { 48110447Snilay@cs.wisc.edu return queryArea(query_sub_field_); 48210447Snilay@cs.wisc.edu } 48310447Snilay@cs.wisc.edu else if(query_type_ == "NddPower") 48410447Snilay@cs.wisc.edu { 48510447Snilay@cs.wisc.edu return queryNddPower(query_sub_field_); 48610447Snilay@cs.wisc.edu } 48710447Snilay@cs.wisc.edu else if(query_type_ == "Energy") 48810447Snilay@cs.wisc.edu { 48910447Snilay@cs.wisc.edu return queryEventEnergyCost(query_sub_field_); 49010447Snilay@cs.wisc.edu } 49110447Snilay@cs.wisc.edu else 49210447Snilay@cs.wisc.edu { 49310447Snilay@cs.wisc.edu const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 49410447Snilay@cs.wisc.edu throw Exception(error_msg); 49510447Snilay@cs.wisc.edu return NULL; 49610447Snilay@cs.wisc.edu } 49710447Snilay@cs.wisc.edu } 49810447Snilay@cs.wisc.edu 49910447Snilay@cs.wisc.edu const Result* Model::queryArea(const String& area_name_) const 50010447Snilay@cs.wisc.edu { 50110447Snilay@cs.wisc.edu ASSERT(m_area_map_->keyExist(area_name_), "[Error] " + m_instance_name_ + 50210447Snilay@cs.wisc.edu " -> Unknown queried area name (" + area_name_ + ")"); 50310447Snilay@cs.wisc.edu return m_area_map_->get(area_name_); 50410447Snilay@cs.wisc.edu } 50510447Snilay@cs.wisc.edu 50610447Snilay@cs.wisc.edu const Result* Model::queryNddPower(const String& ndd_power_name_) 50710447Snilay@cs.wisc.edu { 50810447Snilay@cs.wisc.edu ASSERT(m_ndd_power_map_->keyExist(ndd_power_name_), "[Error] " + m_instance_name_ + 50910447Snilay@cs.wisc.edu " -> Unknown queried ndd power name (" + ndd_power_name_ + ")"); 51010447Snilay@cs.wisc.edu 51110447Snilay@cs.wisc.edu use("Idle"); 51210447Snilay@cs.wisc.edu return m_ndd_power_map_->get(ndd_power_name_); 51310447Snilay@cs.wisc.edu } 51410447Snilay@cs.wisc.edu 51510447Snilay@cs.wisc.edu const Result* Model::queryEventEnergyCost(const String& event_name_) 51610447Snilay@cs.wisc.edu { 51710447Snilay@cs.wisc.edu ASSERT(m_event_map_->keyExist(event_name_), "[Error] " + m_instance_name_ + 51810447Snilay@cs.wisc.edu " -> Unknown queried event name (" + event_name_ + ")"); 51910447Snilay@cs.wisc.edu 52010447Snilay@cs.wisc.edu use(event_name_); 52110447Snilay@cs.wisc.edu return m_event_map_->get(event_name_); 52210447Snilay@cs.wisc.edu } 52310447Snilay@cs.wisc.edu 52410447Snilay@cs.wisc.edu // Update checks whether the model needs updating, whether all properties have been specified, 52510447Snilay@cs.wisc.edu // and calls updateModel if update is necessary 52610447Snilay@cs.wisc.edu void Model::construct() 52710447Snilay@cs.wisc.edu { 52810447Snilay@cs.wisc.edu // Model should not be constructed yet 52910447Snilay@cs.wisc.edu ASSERT(!m_constructed_, "[Error] " + getInstanceName() + " -> Cannot construct an already contructed model!"); 53010447Snilay@cs.wisc.edu // Check if whether all needed parameters are defined 53110447Snilay@cs.wisc.edu checkParameters(); 53210447Snilay@cs.wisc.edu constructModel(); 53310447Snilay@cs.wisc.edu m_constructed_ = true; 53410447Snilay@cs.wisc.edu m_updated_ = false; 53510447Snilay@cs.wisc.edu m_evaluated_ = false; 53610447Snilay@cs.wisc.edu return; 53710447Snilay@cs.wisc.edu } 53810447Snilay@cs.wisc.edu 53910447Snilay@cs.wisc.edu // Update checks whether the model needs updating, whether all properties have been specified, 54010447Snilay@cs.wisc.edu // and calls updateModel if update is necessary 54110447Snilay@cs.wisc.edu void Model::update() 54210447Snilay@cs.wisc.edu { 54310447Snilay@cs.wisc.edu // Model should be constructed 54410447Snilay@cs.wisc.edu ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot update an unconstructed model!"); 54510447Snilay@cs.wisc.edu // If the model needs updating (due to property change) 54610447Snilay@cs.wisc.edu // an update is necessary 54710447Snilay@cs.wisc.edu if (!m_updated_) 54810447Snilay@cs.wisc.edu { 54910447Snilay@cs.wisc.edu // Check if all properties needed exist 55010447Snilay@cs.wisc.edu checkProperties(); 55110447Snilay@cs.wisc.edu updateModel(); 55210447Snilay@cs.wisc.edu m_updated_ = true; 55310447Snilay@cs.wisc.edu m_evaluated_ = false; 55410447Snilay@cs.wisc.edu } 55510447Snilay@cs.wisc.edu return; 55610447Snilay@cs.wisc.edu } 55710447Snilay@cs.wisc.edu 55810447Snilay@cs.wisc.edu // Evaluate checks whether the model needs to be evaluated. 55910447Snilay@cs.wisc.edu void Model::evaluate() 56010447Snilay@cs.wisc.edu { 56110447Snilay@cs.wisc.edu // Model should be constructed 56210447Snilay@cs.wisc.edu ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot evaluate an unconstructed model!"); 56310447Snilay@cs.wisc.edu // Model should be updated 56410447Snilay@cs.wisc.edu ASSERT(m_updated_, "[Error] " + getInstanceName() + " -> Cannot evaluate without first updating!"); 56510447Snilay@cs.wisc.edu // If the model needs evaluating 56610447Snilay@cs.wisc.edu if (!m_evaluated_) 56710447Snilay@cs.wisc.edu { 56810447Snilay@cs.wisc.edu evaluateModel(); 56910447Snilay@cs.wisc.edu m_evaluated_ = true; 57010447Snilay@cs.wisc.edu } 57110447Snilay@cs.wisc.edu 57210447Snilay@cs.wisc.edu return; 57310447Snilay@cs.wisc.edu } 57410447Snilay@cs.wisc.edu 57510447Snilay@cs.wisc.edu void Model::use(const String& event_name_) 57610447Snilay@cs.wisc.edu { 57710447Snilay@cs.wisc.edu useModel(event_name_); 57810447Snilay@cs.wisc.edu return; 57910447Snilay@cs.wisc.edu } 58010447Snilay@cs.wisc.edu 58110447Snilay@cs.wisc.edu void Model::use() 58210447Snilay@cs.wisc.edu { 58310447Snilay@cs.wisc.edu useModel(); 58410447Snilay@cs.wisc.edu return; 58510447Snilay@cs.wisc.edu } 58610447Snilay@cs.wisc.edu 58710447Snilay@cs.wisc.edu // By default, update model will iterate through all sub-instances and do updateModel on them 58810447Snilay@cs.wisc.edu void Model::updateModel() 58910447Snilay@cs.wisc.edu { 59010447Snilay@cs.wisc.edu Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 59110447Snilay@cs.wisc.edu Map<SubModel*>::Iterator end = m_sub_instances_->end(); 59210447Snilay@cs.wisc.edu while (iter != end) 59310447Snilay@cs.wisc.edu { 59410447Snilay@cs.wisc.edu iter->second->getModel()->update(); 59510447Snilay@cs.wisc.edu iter++; 59610447Snilay@cs.wisc.edu } 59710447Snilay@cs.wisc.edu return; 59810447Snilay@cs.wisc.edu } 59910447Snilay@cs.wisc.edu 60010447Snilay@cs.wisc.edu // By default, update model will iterate through all sub-instances and do updateModel on them 60110447Snilay@cs.wisc.edu void Model::evaluateModel() 60210447Snilay@cs.wisc.edu { 60310447Snilay@cs.wisc.edu Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 60410447Snilay@cs.wisc.edu Map<SubModel*>::Iterator end = m_sub_instances_->end(); 60510447Snilay@cs.wisc.edu while (iter != end) 60610447Snilay@cs.wisc.edu { 60710447Snilay@cs.wisc.edu iter->second->getModel()->evaluate(); 60810447Snilay@cs.wisc.edu iter++; 60910447Snilay@cs.wisc.edu } 61010447Snilay@cs.wisc.edu return; 61110447Snilay@cs.wisc.edu } 61210447Snilay@cs.wisc.edu 61310447Snilay@cs.wisc.edu void Model::useModel(const String& /* event_name_ */) 61410447Snilay@cs.wisc.edu {} 61510447Snilay@cs.wisc.edu 61610447Snilay@cs.wisc.edu void Model::useModel() 61710447Snilay@cs.wisc.edu {} 61810447Snilay@cs.wisc.edu 61910447Snilay@cs.wisc.edu void Model::printHierarchy(const String& query_type_, const String& query_sub_field_, const String& prepend_str_, int detail_level_, ostream& ost_) const 62010447Snilay@cs.wisc.edu { 62110447Snilay@cs.wisc.edu if(query_type_ == "InstHier") 62210447Snilay@cs.wisc.edu { 62310447Snilay@cs.wisc.edu ost_ << prepend_str_ << getInstanceName() << endl; 62410447Snilay@cs.wisc.edu printInstHierarchy(prepend_str_, detail_level_, ost_); 62510447Snilay@cs.wisc.edu //if(detail_level_ > 0) 62610447Snilay@cs.wisc.edu //{ 62710447Snilay@cs.wisc.edu //for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 62810447Snilay@cs.wisc.edu //{ 62910447Snilay@cs.wisc.edu //const Model* sub_model = (it->second)->getModel(); 63010447Snilay@cs.wisc.edu //String temp_prepend_str = prepend_str_ + " "; 63110447Snilay@cs.wisc.edu //sub_model->printHierarchy(query_type_, query_sub_field_, temp_prepend_str, detail_level_ - 1, ost_); 63210447Snilay@cs.wisc.edu //} 63310447Snilay@cs.wisc.edu //} 63410447Snilay@cs.wisc.edu } 63510447Snilay@cs.wisc.edu else 63610447Snilay@cs.wisc.edu { 63710447Snilay@cs.wisc.edu const Map<Result*>* result_map; 63810447Snilay@cs.wisc.edu 63910447Snilay@cs.wisc.edu if(query_type_ == "AreaHier") 64010447Snilay@cs.wisc.edu { 64110447Snilay@cs.wisc.edu result_map = m_area_map_; 64210447Snilay@cs.wisc.edu } 64310447Snilay@cs.wisc.edu else if(query_type_ == "NddPowerHier") 64410447Snilay@cs.wisc.edu { 64510447Snilay@cs.wisc.edu result_map = m_ndd_power_map_; 64610447Snilay@cs.wisc.edu } 64710447Snilay@cs.wisc.edu else if(query_type_ == "EventHier") 64810447Snilay@cs.wisc.edu { 64910447Snilay@cs.wisc.edu result_map = m_event_map_; 65010447Snilay@cs.wisc.edu } 65110447Snilay@cs.wisc.edu else 65210447Snilay@cs.wisc.edu { 65310447Snilay@cs.wisc.edu const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 65410447Snilay@cs.wisc.edu throw Exception(error_msg); 65510447Snilay@cs.wisc.edu return; 65610447Snilay@cs.wisc.edu } 65710447Snilay@cs.wisc.edu 65810447Snilay@cs.wisc.edu if(query_sub_field_ == "") 65910447Snilay@cs.wisc.edu { 66010447Snilay@cs.wisc.edu for(Map<Result*>::ConstIterator it = result_map->begin(); it != result_map->end(); ++it) 66110447Snilay@cs.wisc.edu { 66210447Snilay@cs.wisc.edu const Result* result = it->second; 66310447Snilay@cs.wisc.edu ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 66410447Snilay@cs.wisc.edu result->printHierarchy(prepend_str_, detail_level_, ost_); 66510447Snilay@cs.wisc.edu } 66610447Snilay@cs.wisc.edu } 66710447Snilay@cs.wisc.edu else 66810447Snilay@cs.wisc.edu { 66910447Snilay@cs.wisc.edu const Result* result = result_map->get(query_sub_field_); 67010447Snilay@cs.wisc.edu ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 67110447Snilay@cs.wisc.edu result->printHierarchy(prepend_str_, detail_level_, ost_); 67210447Snilay@cs.wisc.edu } 67310447Snilay@cs.wisc.edu } 67410447Snilay@cs.wisc.edu return; 67510447Snilay@cs.wisc.edu } 67610447Snilay@cs.wisc.edu 67710447Snilay@cs.wisc.edu void Model::printInstHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const 67810447Snilay@cs.wisc.edu { 67910447Snilay@cs.wisc.edu if(detail_level_ > 0) 68010447Snilay@cs.wisc.edu { 68110447Snilay@cs.wisc.edu for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 68210447Snilay@cs.wisc.edu { 68310447Snilay@cs.wisc.edu const Model* sub_model = it->second->getModel(); 68410447Snilay@cs.wisc.edu String temp_prepend_str = prepend_str_ + " "; 68510447Snilay@cs.wisc.edu 68610447Snilay@cs.wisc.edu ost_ << prepend_str_ << " |--" << sub_model->getInstanceName() << endl; 68710447Snilay@cs.wisc.edu sub_model->printInstHierarchy(temp_prepend_str, detail_level_ - 1, ost_); 68810447Snilay@cs.wisc.edu } 68910447Snilay@cs.wisc.edu } 69010447Snilay@cs.wisc.edu return; 69110447Snilay@cs.wisc.edu } 69210447Snilay@cs.wisc.edu 69310447Snilay@cs.wisc.edu Model* Model::clone() const 69410447Snilay@cs.wisc.edu { 69510447Snilay@cs.wisc.edu throw Exception(getInstanceName() + " -> Cannot be cloned!"); 69610447Snilay@cs.wisc.edu } 69710447Snilay@cs.wisc.edu 69810447Snilay@cs.wisc.edu Model::Model(const Model& model_) 69910447Snilay@cs.wisc.edu { 70010447Snilay@cs.wisc.edu // Copy instance's name 70110447Snilay@cs.wisc.edu m_instance_name_ = model_.m_instance_name_; 70210447Snilay@cs.wisc.edu 70310447Snilay@cs.wisc.edu // Clone properties 70410447Snilay@cs.wisc.edu m_properties_ = model_.m_properties_->clone(); 70510447Snilay@cs.wisc.edu 70610447Snilay@cs.wisc.edu // Clone instances 70710447Snilay@cs.wisc.edu m_sub_instances_ = clonePtrMap(model_.m_sub_instances_); 70810447Snilay@cs.wisc.edu 70910447Snilay@cs.wisc.edu // Clone events, area, ndd_power 71010447Snilay@cs.wisc.edu m_event_map_ = clonePtrMap(model_.m_event_map_); 71110447Snilay@cs.wisc.edu m_area_map_ = clonePtrMap(model_.m_area_map_); 71210447Snilay@cs.wisc.edu m_ndd_power_map_ = clonePtrMap(model_.m_ndd_power_map_); 71310447Snilay@cs.wisc.edu 71410447Snilay@cs.wisc.edu // Copy tech model pointer 71510447Snilay@cs.wisc.edu m_tech_model_ = model_.m_tech_model_; 71610447Snilay@cs.wisc.edu } 71710447Snilay@cs.wisc.edu 71810447Snilay@cs.wisc.edu} // namespace DSENT 71910447Snilay@cs.wisc.edu 720