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