1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21 22#include "model/Model.h" 23 24#include <vector> 25 26#include "util/Result.h" 27 28namespace DSENT 29{ 30 using std::vector; 31 using LibUtil::deletePtrMap; 32 using LibUtil::clonePtrMap; 33 34 Model::SubModel::SubModel(Model* model_, double num_models_) 35 : m_model_(model_), m_num_models_(num_models_) 36 {} 37 38 Model::SubModel::~SubModel() 39 { 40 delete m_model_; 41 } 42 43 Model* Model::SubModel::getModel() 44 { 45 return m_model_; 46 } 47 48 const Model* Model::SubModel::getModel() const 49 { 50 return m_model_; 51 } 52 53 double Model::SubModel::getNumModels() const 54 { 55 return m_num_models_; 56 } 57 58 Model::SubModel* Model::SubModel::clone() const 59 { 60 return new SubModel(*this); 61 } 62 63 Model::SubModel::SubModel(const SubModel& sub_model_) 64 { 65 m_model_ = sub_model_.m_model_->clone(); 66 m_num_models_ = sub_model_.m_num_models_; 67 } 68 69 const char Model::TYPE_SEPARATOR[] = ">>"; 70 const char Model::HIERARCHY_SEPARATOR[] = "->"; 71 const char Model::SUBFIELD_SEPARATOR[] = ":"; 72 const char Model::DETAIL_SEPARATOR[] = "@"; 73 74 Model::Model(const String& instance_name_, const TechModel* tech_model_) 75 : m_instance_name_(instance_name_), m_tech_model_(tech_model_), 76 m_constructed_(false), m_updated_(false), m_evaluated_(false) 77 { 78 m_property_names_ = new vector<String>; 79 m_parameter_names_ = new vector<String>; 80 m_parameters_ = new ParameterMap(); 81 m_properties_ = new PropertyMap(); 82 m_generated_properties_ = new PropertyMap(); 83 m_sub_instances_ = new Map<SubModel*>(); 84 m_event_map_ = new Map<Result*>(); 85 m_area_map_ = new Map<Result*>(); 86 m_ndd_power_map_ = new Map<Result*>(); 87 } 88 89 Model::~Model() 90 { 91 // Clear parameter names 92 delete m_parameter_names_; 93 // Clear property name 94 delete m_property_names_; 95 96 // Clear parameters 97 delete m_parameters_; 98 m_parameters_ = NULL; 99 // Clear input properties 100 delete m_properties_; 101 m_properties_ = NULL; 102 103 // Clear generated properties 104 delete m_generated_properties_; 105 m_generated_properties_ = NULL; 106 107 // Clear sub models 108 deletePtrMap<SubModel>(m_sub_instances_); 109 m_sub_instances_ = NULL; 110 111 // Clear all results 112 deletePtrMap<Result>(m_event_map_); 113 m_event_map_ = NULL; 114 deletePtrMap<Result>(m_area_map_); 115 m_area_map_ = NULL; 116 deletePtrMap<Result>(m_ndd_power_map_); 117 m_ndd_power_map_ = NULL; 118 } 119 120 void Model::setInstanceName(const String& instance_name_) 121 { 122 m_instance_name_ = instance_name_; 123 return; 124 } 125 126 const String& Model::getInstanceName() const 127 { 128 return m_instance_name_; 129 } 130 131 void Model::setIsTopModel(bool is_top_model_) 132 { 133 m_is_top_model_ = is_top_model_; 134 return; 135 } 136 137 bool Model::getIsTopModel() const 138 { 139 return m_is_top_model_; 140 } 141 142 //------------------------------------------------------------------------- 143 // Parameters and properties checks 144 //------------------------------------------------------------------------- 145 void Model::addParameterName(const String& parameter_name_) 146 { 147 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 148 " -> Cannot add additional parameters names after model is constructed!"); 149 m_parameter_names_->push_back(parameter_name_); 150 151 return; 152 } 153 154 void Model::addParameterName(const String& parameter_name_, const String& parameter_default_) 155 { 156 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 157 " -> Cannot add additional parameters names after model is constructed!"); 158 m_parameter_names_->push_back(parameter_name_); 159 setParameter(parameter_name_, parameter_default_); 160 return; 161 } 162 163 const vector<String>* Model::getParameterNames() const 164 { 165 return m_parameter_names_; 166 } 167 168 void Model::addPropertyName(const String& property_name_) 169 { 170 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 171 " -> Cannot add additional property names after model is constructed!"); 172 m_property_names_->push_back(property_name_); 173 return; 174 } 175 176 void Model::addPropertyName(const String& property_name_, const String& property_default_) 177 { 178 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 179 " -> Cannot add additional property names after model is constructed!"); 180 m_property_names_->push_back(property_name_); 181 setProperty(property_name_, property_default_); 182 return; 183 } 184 185 const vector<String>* Model::getPropertyNames() const 186 { 187 return m_property_names_; 188 } 189 190 void Model::checkParameters() const 191 { 192 String missing_parameters = ""; 193 194 for(int i = 0; i < (int)m_parameter_names_->size(); ++i) 195 { 196 const String& parameter_name = m_parameter_names_->at(i); 197 if (!m_parameters_->keyExist(parameter_name)) 198 missing_parameters += " " + parameter_name + "\n"; 199 } 200 201 ASSERT(missing_parameters.size() == 0, "[Error] " + m_instance_name_ + 202 " -> Missing parameters:\n" + missing_parameters); 203 return; 204 } 205 206 void Model::checkProperties() const 207 { 208 String missing_properties = ""; 209 210 for(int i = 0; i < (int)m_property_names_->size(); ++i) 211 { 212 const String& property_name = m_property_names_->at(i); 213 if (!m_properties_->keyExist(property_name)) 214 missing_properties += " " + property_name + "\n"; 215 } 216 217 ASSERT(missing_properties.size() == 0, "[Error] " + m_instance_name_ + 218 " -> Missing properties:\n" + missing_properties); 219 return; 220 } 221 //------------------------------------------------------------------------- 222 223 //------------------------------------------------------------------------- 224 // Parameters Manipulation 225 //------------------------------------------------------------------------- 226 const ParameterMap* Model::getParameters() const 227 { 228 return m_parameters_; 229 } 230 231 const String Model::getParameter(const String& parameter_name_) const 232 { 233 return m_parameters_->get(parameter_name_); 234 } 235 236 void Model::setParameter(const String& parameter_name_, const String& parameter_value_) 237 { 238 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 239 " -> Cannot set parameters after model is constructed!"); 240 m_parameters_->set(parameter_name_, parameter_value_); 241 } 242 //------------------------------------------------------------------------- 243 244 //------------------------------------------------------------------------- 245 // Properties Manipulation 246 //------------------------------------------------------------------------- 247 const PropertyMap* Model::getProperties() const 248 { 249 return m_properties_; 250 } 251 252 const String Model::getProperty(const String& property_name_) const 253 { 254 return m_properties_->get(property_name_); 255 } 256 257 void Model::setProperty(const String& property_name_, const String& property_value_) 258 { 259 // If any properties changed, reset updated and evaluated flags 260 m_updated_ = false; 261 m_evaluated_ = false; 262 m_properties_->set(property_name_, property_value_); 263 } 264 //------------------------------------------------------------------------- 265 266 PropertyMap* Model::getGenProperties() 267 { 268 return m_generated_properties_; 269 } 270 271 const PropertyMap* Model::getGenProperties() const 272 { 273 return m_generated_properties_; 274 } 275 276 void Model::addSubInstances(Model* sub_instance_, double num_sub_instances_) 277 { 278 // Get instance name 279 const String& sub_instance_name = sub_instance_->getInstanceName(); 280 281 // Check if the instance exists 282 if(m_sub_instances_->keyExist(sub_instance_name)) 283 { 284 const String& error_msg = "[Error] " + m_instance_name_ + 285 " -> Instance exists (" + sub_instance_name + ")"; 286 throw Exception(error_msg); 287 } 288 289 // Check if the num_sub_instances_ is a positive number 290 ASSERT((num_sub_instances_ >= 0), "[Error] " + m_instance_name_ + 291 " -> Invalid number of instance (" + String(num_sub_instances_) + ")"); 292 293 // Add the instance 294 m_sub_instances_->set(sub_instance_name, new SubModel(sub_instance_, num_sub_instances_)); 295 return; 296 } 297 298 Model* Model::getSubInstance(const String& sub_instance_name_) 299 { 300 // Throw an Exception if the instance already exists 301 if(!m_sub_instances_->keyExist(sub_instance_name_)) 302 { 303 const String& error_msg = "[Error] " + m_instance_name_ + 304 " -> Instance not exists (" + sub_instance_name_ + ")"; 305 throw Exception(error_msg); 306 } 307 308 return m_sub_instances_->get(sub_instance_name_)->getModel(); 309 } 310 311 const Model* Model::getSubInstance(const String& sub_instance_name_) const 312 { 313 // Throw an Exception if the instance does not exist 314 if(!m_sub_instances_->keyExist(sub_instance_name_)) 315 { 316 const String& error_msg = "[Error] " + m_instance_name_ + 317 " -> Instance not exists (" + sub_instance_name_ + ")"; 318 throw Exception(error_msg); 319 } 320 321 return m_sub_instances_->get(sub_instance_name_)->getModel(); 322 } 323 324 bool Model::hasSubInstance(const String& sub_instance_name_) const 325 { 326 return m_sub_instances_->keyExist(sub_instance_name_); 327 } 328 329 void Model::addAreaResult(Result* area_) 330 { 331 const String& area_name = area_->getName(); 332 333 // Throw an Exception if the area already exists 334 if(m_area_map_->keyExist(area_name)) 335 { 336 const String& error_msg = "Internal error: area (" + area_name + 337 ") exists"; 338 throw Exception(error_msg); 339 } 340 341 // Add the area 342 m_area_map_->set(area_name, area_); 343 return; 344 } 345 346 Result* Model::getAreaResult(const String& area_name_) 347 { 348 return m_area_map_->get(area_name_); 349 } 350 351 const Result* Model::getAreaResult(const String& area_name_) const 352 { 353 return m_area_map_->get(area_name_); 354 } 355 356 bool Model::hasAreaResult(const String& area_name_) const 357 { 358 return m_area_map_->keyExist(area_name_); 359 } 360 361 void Model::addNddPowerResult(Result* ndd_power_) 362 { 363 const String& ndd_power_name = ndd_power_->getName(); 364 365 // Throw an Exception if the ndd_power already exists 366 if(m_ndd_power_map_->keyExist(ndd_power_name)) 367 { 368 const String& error_msg = "Internal error: ndd_power (" + ndd_power_name + 369 ") exists"; 370 throw Exception(error_msg); 371 } 372 373 // Add the ndd_power 374 m_ndd_power_map_->set(ndd_power_name, ndd_power_); 375 return; 376 } 377 378 Result* Model::getNddPowerResult(const String& ndd_power_name_) 379 { 380 return m_ndd_power_map_->get(ndd_power_name_); 381 } 382 383 const Result* Model::getNddPowerResult(const String& ndd_power_name_) const 384 { 385 return m_ndd_power_map_->get(ndd_power_name_); 386 } 387 388 bool Model::hasNddPowerResult(const String& ndd_power_name_) const 389 { 390 return m_ndd_power_map_->keyExist(ndd_power_name_); 391 } 392 393 void Model::addEventResult(Result* event_) 394 { 395 const String& event_name = event_->getName(); 396 397 // Throw an Exception if the event already exists 398 if(m_event_map_->keyExist(event_name)) 399 { 400 const String& error_msg = "Internal error: event (" + event_name + 401 ") exists"; 402 throw Exception(error_msg); 403 } 404 405 // Add the event 406 m_event_map_->set(event_name, event_); 407 return; 408 } 409 410 Result* Model::getEventResult(const String& event_name_) 411 { 412 return m_event_map_->get(event_name_); 413 } 414 415 const Result* Model::getEventResult(const String& event_name_) const 416 { 417 return m_event_map_->get(event_name_); 418 } 419 420 bool Model::hasEventResult(const String& event_name_) const 421 { 422 return m_event_map_->keyExist(event_name_); 423 } 424 425 const TechModel* Model::getTechModel() const 426 { 427 return m_tech_model_; 428 } 429 430 const void* Model::parseQuery(const String& query_type_, const String& query_hier_, const String& query_sub_field_) 431 { 432 // Break query by hierarchy separator 433 vector<String> hier_split = query_hier_.splitByString(HIERARCHY_SEPARATOR); 434 435 // Check if the query_hier matches the instance name 436 ASSERT((hier_split[0] == m_instance_name_), "[Error] " + 437 m_instance_name_ + " -> Mismatch in instance name (" + 438 hier_split[0] + ")"); 439 440 // If there is no more hierarchy separator, this process the query 441 if(hier_split.size() == 1) 442 { 443 // Query the model 444 return processQuery(query_type_, query_sub_field_); 445 } 446 else 447 { 448 // Reconstruct the query 449 String temp_query_hier = hier_split[1]; 450 for(int i = 2; i < (int)hier_split.size(); ++i) 451 { 452 temp_query_hier += HIERARCHY_SEPARATOR + hier_split[i]; 453 } 454 455 // Get sub instance's name 456 const String& temp_sub_instance_name = hier_split[1]; 457 ASSERT(m_sub_instances_->keyExist(temp_sub_instance_name), "[Error] " + 458 m_instance_name_ + " -> No sub-instances queried (" + 459 temp_sub_instance_name + ")"); 460 461 return m_sub_instances_->get(temp_sub_instance_name)->getModel()->parseQuery(query_type_, temp_query_hier, query_sub_field_); 462 } 463 } 464 465 const void* Model::processQuery(const String& query_type_, const String& query_sub_field_) 466 { 467 if(query_type_ == "Property") 468 { 469 return getProperties(); 470 } 471 else if(query_type_ == "Parameter") 472 { 473 return getParameters(); 474 } 475 else if(query_type_.contain("Hier")) 476 { 477 return this; 478 } 479 else if(query_type_ == "Area") 480 { 481 return queryArea(query_sub_field_); 482 } 483 else if(query_type_ == "NddPower") 484 { 485 return queryNddPower(query_sub_field_); 486 } 487 else if(query_type_ == "Energy") 488 { 489 return queryEventEnergyCost(query_sub_field_); 490 } 491 else 492 { 493 const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 494 throw Exception(error_msg); 495 return NULL; 496 } 497 } 498 499 const Result* Model::queryArea(const String& area_name_) const 500 { 501 ASSERT(m_area_map_->keyExist(area_name_), "[Error] " + m_instance_name_ + 502 " -> Unknown queried area name (" + area_name_ + ")"); 503 return m_area_map_->get(area_name_); 504 } 505 506 const Result* Model::queryNddPower(const String& ndd_power_name_) 507 { 508 ASSERT(m_ndd_power_map_->keyExist(ndd_power_name_), "[Error] " + m_instance_name_ + 509 " -> Unknown queried ndd power name (" + ndd_power_name_ + ")"); 510 511 use("Idle"); 512 return m_ndd_power_map_->get(ndd_power_name_); 513 } 514 515 const Result* Model::queryEventEnergyCost(const String& event_name_) 516 { 517 ASSERT(m_event_map_->keyExist(event_name_), "[Error] " + m_instance_name_ + 518 " -> Unknown queried event name (" + event_name_ + ")"); 519 520 use(event_name_); 521 return m_event_map_->get(event_name_); 522 } 523 524 // Update checks whether the model needs updating, whether all properties have been specified, 525 // and calls updateModel if update is necessary 526 void Model::construct() 527 { 528 // Model should not be constructed yet 529 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + " -> Cannot construct an already contructed model!"); 530 // Check if whether all needed parameters are defined 531 checkParameters(); 532 constructModel(); 533 m_constructed_ = true; 534 m_updated_ = false; 535 m_evaluated_ = false; 536 return; 537 } 538 539 // Update checks whether the model needs updating, whether all properties have been specified, 540 // and calls updateModel if update is necessary 541 void Model::update() 542 { 543 // Model should be constructed 544 ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot update an unconstructed model!"); 545 // If the model needs updating (due to property change) 546 // an update is necessary 547 if (!m_updated_) 548 { 549 // Check if all properties needed exist 550 checkProperties(); 551 updateModel(); 552 m_updated_ = true; 553 m_evaluated_ = false; 554 } 555 return; 556 } 557 558 // Evaluate checks whether the model needs to be evaluated. 559 void Model::evaluate() 560 { 561 // Model should be constructed 562 ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot evaluate an unconstructed model!"); 563 // Model should be updated 564 ASSERT(m_updated_, "[Error] " + getInstanceName() + " -> Cannot evaluate without first updating!"); 565 // If the model needs evaluating 566 if (!m_evaluated_) 567 { 568 evaluateModel(); 569 m_evaluated_ = true; 570 } 571 572 return; 573 } 574 575 void Model::use(const String& event_name_) 576 { 577 useModel(event_name_); 578 return; 579 } 580 581 void Model::use() 582 { 583 useModel(); 584 return; 585 } 586 587 // By default, update model will iterate through all sub-instances and do updateModel on them 588 void Model::updateModel() 589 { 590 Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 591 Map<SubModel*>::Iterator end = m_sub_instances_->end(); 592 while (iter != end) 593 { 594 iter->second->getModel()->update(); 595 iter++; 596 } 597 return; 598 } 599 600 // By default, update model will iterate through all sub-instances and do updateModel on them 601 void Model::evaluateModel() 602 { 603 Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 604 Map<SubModel*>::Iterator end = m_sub_instances_->end(); 605 while (iter != end) 606 { 607 iter->second->getModel()->evaluate(); 608 iter++; 609 } 610 return; 611 } 612 613 void Model::useModel(const String& /* event_name_ */) 614 {} 615 616 void Model::useModel() 617 {} 618 619 void Model::printHierarchy(const String& query_type_, const String& query_sub_field_, const String& prepend_str_, int detail_level_, ostream& ost_) const 620 { 621 if(query_type_ == "InstHier") 622 { 623 ost_ << prepend_str_ << getInstanceName() << endl; 624 printInstHierarchy(prepend_str_, detail_level_, ost_); 625 //if(detail_level_ > 0) 626 //{ 627 //for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 628 //{ 629 //const Model* sub_model = (it->second)->getModel(); 630 //String temp_prepend_str = prepend_str_ + " "; 631 //sub_model->printHierarchy(query_type_, query_sub_field_, temp_prepend_str, detail_level_ - 1, ost_); 632 //} 633 //} 634 } 635 else 636 { 637 const Map<Result*>* result_map; 638 639 if(query_type_ == "AreaHier") 640 { 641 result_map = m_area_map_; 642 } 643 else if(query_type_ == "NddPowerHier") 644 { 645 result_map = m_ndd_power_map_; 646 } 647 else if(query_type_ == "EventHier") 648 { 649 result_map = m_event_map_; 650 } 651 else 652 { 653 const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 654 throw Exception(error_msg); 655 return; 656 } 657 658 if(query_sub_field_ == "") 659 { 660 for(Map<Result*>::ConstIterator it = result_map->begin(); it != result_map->end(); ++it) 661 { 662 const Result* result = it->second; 663 ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 664 result->printHierarchy(prepend_str_, detail_level_, ost_); 665 } 666 } 667 else 668 { 669 const Result* result = result_map->get(query_sub_field_); 670 ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 671 result->printHierarchy(prepend_str_, detail_level_, ost_); 672 } 673 } 674 return; 675 } 676 677 void Model::printInstHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const 678 { 679 if(detail_level_ > 0) 680 { 681 for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 682 { 683 const Model* sub_model = it->second->getModel(); 684 String temp_prepend_str = prepend_str_ + " "; 685 686 ost_ << prepend_str_ << " |--" << sub_model->getInstanceName() << endl; 687 sub_model->printInstHierarchy(temp_prepend_str, detail_level_ - 1, ost_); 688 } 689 } 690 return; 691 } 692 693 Model* Model::clone() const 694 { 695 throw Exception(getInstanceName() + " -> Cannot be cloned!"); 696 } 697 698 Model::Model(const Model& model_) 699 { 700 // Copy instance's name 701 m_instance_name_ = model_.m_instance_name_; 702 703 // Clone properties 704 m_properties_ = model_.m_properties_->clone(); 705 706 // Clone instances 707 m_sub_instances_ = clonePtrMap(model_.m_sub_instances_); 708 709 // Clone events, area, ndd_power 710 m_event_map_ = clonePtrMap(model_.m_event_map_); 711 m_area_map_ = clonePtrMap(model_.m_area_map_); 712 m_ndd_power_map_ = clonePtrMap(model_.m_ndd_power_map_); 713 714 // Copy tech model pointer 715 m_tech_model_ = model_.m_tech_model_; 716 } 717 718} // namespace DSENT 719 720