4 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_maxmin, surf,
5 "Logging specific to SURF (maxmin)");
7 static int Global_debug_id = 1;
8 static int Global_const_debug_id = 1;
10 Solver::Solver(int selectiveUpdate)
16 m_selectiveUpdateActive = selectiveUpdate;
19 XBT_DEBUG("Setting selective_update_active flag to %d\n",
20 this->m_selectiveUpdateActive);
22 /*xbt_swag_init(&(l->variable_set),
23 xbt_swag_offset(var, variable_set_hookup));
24 xbt_swag_init(&(l->constraint_set),
25 xbt_swag_offset(cnst, constraint_set_hookup));
27 xbt_swag_init(&(l->active_constraint_set),
28 xbt_swag_offset(cnst, active_constraint_set_hookup));
30 xbt_swag_init(&(l->modified_constraint_set),
31 xbt_swag_offset(cnst, modified_constraint_set_hookup));
32 xbt_swag_init(&(l->saturated_variable_set),
33 xbt_swag_offset(var, saturated_variable_set_hookup));
34 xbt_swag_init(&(l->saturated_constraint_set),
35 xbt_swag_offset(cnst, saturated_constraint_set_hookup));
37 l->variable_mallocator = xbt_mallocator_new(65536,
38 lmm_variable_mallocator_new_f,
39 lmm_variable_mallocator_free_f,
40 lmm_variable_mallocator_reset_f);*/
43 ConstraintPtr Solver::createConstraint(void *id, double bound)
45 ConstraintPtr cnst = m_constraintAllocator.construct(id, bound);
46 m_constraintSet.push_back(cnst);
50 void Solver::destroyConstraint(Constraint* cnst)
52 m_constraintAllocator.destroy(cnst);
56 VariablePtr Solver::createVariable(void *id, double weight, double bound)
58 void *mem = m_variableAllocator.malloc();
59 VariablePtr var = new (mem) Variable(id, weight, bound, m_visitedCounter - 1);
60 var->m_visited = m_visitedCounter - 1;
62 m_variableSet.insert(m_variableSet.begin(), var);
64 m_variableSet.push_back(var);
68 void Solver::destroyVariable(Variable* var)
70 m_variableAllocator.destroy(var);
73 void Solver::destroyElement(Element* elem)
75 m_elementAllocator.destroy(elem);
78 void Solver::expand(ConstraintPtr cnst, VariablePtr var, double value)
82 ElementPtr elem = m_elementAllocator.construct(cnst, var, value);
83 var->m_cnsts.push_back(elem);
86 cnst->m_elementSet.insert(cnst->m_elementSet.begin(), elem);
88 cnst->m_elementSet.push_back(elem);
89 if(!m_selectiveUpdateActive) {
90 activateConstraint(cnst);
91 } else if(value>0 || var->m_weight >0) {
92 activateConstraint(cnst);
93 updateModifiedSet(cnst);
94 if (var->m_cnsts.size() > 1)
95 updateModifiedSet(var->m_cnsts.front()->p_constraint);
99 void Solver::expandAdd(ConstraintPtr cnst, VariablePtr var, double value)
103 std::vector<ElementPtr>::iterator it;
104 for (it=var->m_cnsts.begin(); it!=var->m_cnsts.end(); ++it )
105 if ((*it)->p_constraint == cnst)
108 if (it != var->m_cnsts.end()) {
109 if (cnst->isShared())
110 (*it)->m_value += value;
112 (*it)->m_value = MAX((*it)->m_value, value);
113 updateModifiedSet(cnst);
115 expand(cnst, var, value);
118 void Solver::elementSetValue(ConstraintPtr cnst, VariablePtr var, double value)
120 std::vector<ElementPtr>::iterator it;
121 for (it=var->m_cnsts.begin(); it!=var->m_cnsts.end(); ++it ) {
122 ElementPtr elem = (*it);
123 if (elem->p_constraint == cnst) {
124 elem->m_value = value;
126 updateModifiedSet(cnst);
129 if (it==var->m_cnsts.end()) {
135 ConstraintPtr Variable::getCnst(int num)
137 if (num < m_cnsts.size())
138 return m_cnsts.at(num)->p_constraint;
146 double Variable::getCnstWeight(int num)
148 if (num < m_cnsts.size())
149 return (m_cnsts.at(num)->m_value);
155 int Variable::getNumberOfCnst()
157 return m_cnsts.size();
160 VariablePtr Constraint::getVar(ElementPtr elem)
162 vector<ElementPtr>::iterator it;
164 elem = m_elementSet.front();
166 elem = *(++find(m_elementSet.begin(), m_elementSet.end(), elem));
168 return elem->p_variable;
176 void* Constraint::id()
188 void Solver::saturatedConstraintSetUpdate(double usage,
189 ConstraintLightPtr cnstLight,
190 vector<ConstraintLightPtr> saturatedConstraintSet,
193 xbt_assert(usage > 0,"Impossible");
195 if (*minUsage < 0 || *minUsage > usage) {
197 saturatedConstraintSet.clear();
198 saturatedConstraintSet.push_back(cnstLight);
199 XBT_HERE(" min_usage=%f (cnst->remaining / cnst->usage =%f)", *minUsage, usage);
200 } else if (*minUsage == usage) {
201 saturatedConstraintSet.push_back(cnstLight);
206 void Solver::saturatedVariableSetUpdate(vector<ConstraintLightPtr> cnstLightList,
207 vector<ConstraintLightPtr> saturatedCnstSet)
209 ConstraintLight* cnst = NULL;
210 Element* elem = NULL;
211 vector<ElementPtr>* elem_list;
212 std::vector<ConstraintLightPtr>::iterator it;
213 std::vector<ElementPtr>::iterator elemIt;
214 for (it=saturatedCnstSet.begin(); it!=saturatedCnstSet.end(); ++it) {
216 elem_list = &(cnst->p_cnst->m_activeElementSet);
217 for (elemIt=elem_list->begin(); elemIt!=elem_list->end(); ++elemIt) {
219 if (elem->p_variable->m_weight <= 0)
221 if (elem->m_value >0)
222 m_saturatedVariableSet.push_back(elem->p_variable);
227 void Element::activate()
229 p_constraint->m_activeElementSet.push_back(this);
232 void Element::inactivate()
234 std::vector<ElementPtr>::iterator it;
235 vector<ElementPtr> elemSet = p_constraint->m_activeElementSet;
236 it = find(elemSet.begin(), elemSet.end(), this);
237 if (it != elemSet.end())
241 void Solver::activateConstraint(ConstraintPtr cnst)
243 m_activeConstraintSet.push_back(cnst);
246 void Solver::inactivateConstraint(ConstraintPtr cnst)
248 std::vector<ConstraintPtr>::iterator it;
249 it = find(m_activeConstraintSet.begin(), m_activeConstraintSet.end(), cnst);
250 if (it != m_activeConstraintSet.end())
251 m_activeConstraintSet.erase(it);
252 m_modifiedConstraintSet.erase(std::find(m_modifiedConstraintSet.begin(), m_modifiedConstraintSet.end(), cnst));
256 void vector_remove_first(vector<T> vec, T obj) {
257 typename vector<T>::iterator it;
258 for (it=vec.begin(); it != vec.end(); ++it) {
259 if ((*it) == (obj)) {
273 Variable* var = NULL;
274 Constraint* cnst = NULL;
275 Element* elem = NULL;
276 vector<ConstraintPtr>* cnstList = NULL;
277 std::vector<ConstraintPtr>::iterator cnstIt;
278 vector<VariablePtr>* varList = NULL;
279 std::vector<VariablePtr>::iterator varIt;
280 vector<ElementPtr>* elemList = NULL;
281 std::vector<ElementPtr>::iterator elemIt;
282 vector<ElementPtr>* elemListB = NULL;
283 std::vector<ElementPtr>::iterator elemItB;
284 double minUsage = -1;
285 double minBound = -1;
290 XBT_IN("(sys=%p)", this);
293 * Compute Usage and store the variables that reach the maximum.
295 cnstList = m_selectiveUpdateActive ? &m_modifiedConstraintSet :
296 &m_activeConstraintSet;
298 XBT_DEBUG("Active constraintsSolver : %d", cnstList->size());
299 /* Init: Only modified code portions */
301 for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
302 elemList = &((*cnstIt)->m_elementSet);
303 for (elemIt=elemList->begin(); elemIt!=elemList->end(); ++elemIt) {
304 var = ((*elemIt)->p_variable);
305 if (var->m_weight <= 0.0)
311 vector<ConstraintLightPtr> cnstLightList;
312 std::vector<ConstraintLightPtr>::iterator cnstLightIt;
314 vector<ConstraintLightPtr> saturatedConstraintSet;
315 saturatedConstraintSet.reserve(5);
317 for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
320 if (cnst->m_remaining == 0)
323 elemList = &(cnst->m_elementSet);
324 for (elemIt=elemList->begin(); elemIt!=elemList->end(); ++elemIt) {
325 /* 0-weighted elements (ie, sleep actions) are at the end of the swag and we don't want to consider them */
327 if (elem->p_variable->m_weight <= 0)
329 if ((elem->m_value > 0)) {
331 cnst->m_usage += elem->m_value / elem->p_variable->m_weight;
332 else if (cnst->m_usage < elem->m_value / elem->p_variable->m_weight)
333 cnst->m_usage = elem->m_value / elem->p_variable->m_weight;
336 if (m_keepTrack.size()) //TODO: check good semantic
337 m_keepTrack.push_back(elem->p_variable->p_id);
340 XBT_DEBUG("Constraint Usage '%d' : %f", cnst->m_idInt, cnst->m_usage);
341 /* Saturated constraints update */
342 if(cnst->m_usage > 0) {
343 ConstraintLightPtr cnstLight (new ConstraintLight((*cnstIt), cnst->m_remaining / cnst->m_usage));
344 cnst->p_cnstLight = cnstLight;
345 saturatedConstraintSetUpdate(cnstLight->m_remainingOverUsage, cnstLight, saturatedConstraintSet, &minUsage);
346 cnstLightList.push_back(cnstLight);
350 saturatedVariableSetUpdate(cnstLightList, saturatedConstraintSet);
352 /* Saturated variables update */
354 /* Fix the variables that have to be */
355 varList = &m_saturatedVariableSet;
357 for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
359 if (var->m_weight <= 0.0) {
362 /* First check if some of these variables have reach their upper
363 bound and update min_usage accordingly. */
365 ("var=%d, var->bound=%f, var->weight=%f, min_usage=%f, var->bound*var->weight=%f",
366 var->m_idInt, var->m_bound, var->m_weight, minUsage,
367 var->m_bound * var->m_weight);
369 if ((var->m_bound > 0) && (var->m_bound * var->m_weight < minUsage)) {
371 minBound = var->m_bound;
373 minBound = MIN(minBound, var->m_bound);
374 XBT_DEBUG("Updated min_bound=%f", minBound);
378 while (varList->size()>0) {
379 var = varList->front();
383 var->m_value = minUsage / var->m_weight;
385 if (minBound == var->m_bound)
386 var->m_value = var->m_bound;
388 vector_remove_first(*varList, varList->front());
392 XBT_DEBUG("Min usage: %f, Var(%d)->weight: %f, Var(%d)->value: %f ",
393 minUsage, var->m_idInt, var->m_weight, var->m_idInt, var->m_value);
397 for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) {
399 cnst = elem->p_constraint;
400 if (cnst->m_shared) {
401 double_update(&(cnst->m_remaining), elem->m_value * var->m_value);
402 double_update(&(cnst->m_usage), elem->m_value / var->m_weight);
403 if(cnst->m_usage<=0 || cnst->m_remaining<=0) {
404 if (cnst->p_cnstLight) {
405 // TODO: reformat message
406 XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ",
407 elemIt - var->m_cnsts.begin(), var->m_cnsts.size(), cnst, cnst->p_cnstLight, &cnstLightList);
408 vector_remove_first(cnstLightList, cnst->p_cnstLight);
409 cnst->p_cnstLight = ConstraintLightPtr();
412 cnst->p_cnstLight->m_remainingOverUsage = cnst->m_remaining / cnst->m_usage;
418 elemListB = &(cnst->m_elementSet);
419 for (elemItB=elemListB->begin(); elemItB!=elemListB->end(); ++elemItB) {
421 if (elem->p_variable->m_weight <= 0 || elem->p_variable->m_value > 0)
423 if (elem->m_value > 0)
424 cnst->m_usage = MAX(cnst->m_usage, elem->m_value / elem->p_variable->m_weight);
426 if (cnst->m_usage<=0 || cnst->m_remaining<=0) {
427 if(cnst->p_cnstLight) {
428 vector_remove_first(cnstLightList, cnst->p_cnstLight);
429 // TODO: reformat message
430 XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ",
431 elemIt - var->m_cnsts.begin(), var->m_cnsts.size(), cnst, cnst->p_cnstLight, &cnstLightList);
432 cnst->p_cnstLight = ConstraintLightPtr();
435 cnst->p_cnstLight->m_remainingOverUsage = cnst->m_remaining / cnst->m_usage;
439 vector_remove_first(*varList, varList->front());
442 /* Find out which variables reach the maximum */
445 m_saturatedConstraintSet.clear();
447 for (cnstLightIt=cnstLightList.begin(); cnstLightIt!=cnstLightList.end(); ++cnstLightIt)
448 saturatedConstraintSetUpdate((*cnstLightIt)->m_remainingOverUsage,
450 saturatedConstraintSet,
452 saturatedVariableSetUpdate(cnstLightList, saturatedConstraintSet);
454 } while (cnstLightList.size() > 0);
458 if (m_selectiveUpdateActive)
459 removeAllModifiedSet();
462 if (m_selectiveUpdateActive)
463 removeAllModifiedSet();
465 if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
469 /*TODO: xbt_free(saturated_constraint_set->data);
470 xbt_free(saturated_constraint_set);
471 xbt_free(cnst_light_tab);*/
475 /* Not a O(1) function */
477 void Solver::update(ConstraintPtr cnst, VariablePtr var, double value)
479 std::vector<ElementPtr>::iterator it;
480 for (it=var->m_cnsts.begin(); it!=var->m_cnsts.end(); ++it )
481 if ((*it)->p_constraint == cnst) {
482 (*it)->m_value = value;
484 updateModifiedSet(cnst);
489 /** \brief Attribute the value bound to var->bound.
491 * \param sys the lmm_system_t
492 * \param var the lmm_variable_t
493 * \param bound the new bound to associate with var
495 * Makes var->bound equal to bound. Whenever this function is called
496 * a change is signed in the system. To
497 * avoid false system changing detection it is a good idea to test
498 * (bound != 0) before calling it.
501 void Solver::updateVariableBound(VariablePtr var, double bound)
504 var->m_bound = bound;
506 if (var->m_cnsts.size() > 0)
507 updateModifiedSet(var->m_cnsts.front()->p_constraint);
510 void Solver::updateVariableWeight(VariablePtr var, double weight)
514 if (weight == var->m_weight)
516 XBT_IN("(sys=%p, var=%p, weight=%f)", this, var, weight);
518 var->m_weight = weight;
519 vector_remove_first(m_variableSet, var);
520 if (weight) // TODO: use swap instead
521 m_variableSet.insert(m_variableSet.begin(), var);
523 m_variableSet.push_back(var);
525 vector<ElementPtr> elemList;
526 vector<ElementPtr>::iterator it;
527 for (it=var->m_cnsts.begin(); it!=var->m_cnsts.end(); ++it ) {
528 elemList = (*it)->p_constraint->m_elementSet;
529 vector_remove_first(elemList, (*it));
531 elemList.insert(elemList.begin(), *it);
533 elemList.push_back(*it);
534 if (it == var->m_cnsts.begin())
535 updateModifiedSet((*it)->p_constraint);
543 double Variable::getWeight()
547 void Solver::updateConstraintBound(ConstraintPtr cnst, double bound)
550 updateModifiedSet(cnst);
551 cnst->m_bound = bound;
555 bool Solver::constraintUsed(ConstraintPtr cnst)
557 return std::find(m_activeConstraintSet.begin(),
558 m_activeConstraintSet.end(), cnst)!=m_activeConstraintSet.end();
562 ConstraintPtr Solver::getFirstActiveConstraint()
564 return m_activeConstraintSet.front();
568 ConstraintPtr Solver::getNextActiveConstraint(ConstraintPtr cnst)
570 return *(++std::find(m_activeConstraintSet.begin(), m_activeConstraintSet.end(), cnst));
573 #ifdef HAVE_LATENCY_BOUND_TRACKING
575 bool Variable::isLimitedByLatency()
577 return (double_equals(m_bound, m_value));
581 /** \brief Update the constraint set propagating recursively to
582 * other constraints so the system should not be entirely computed.
584 * \param sys the lmm_system_t
585 * \param cnst the lmm_constraint_t affected by the change
587 * A recursive algorithm to optimize the system recalculation selecting only
588 * constraints that have changed. Each constraint change is propagated
589 * to the list of constraints for each variable.
592 void Solver::updateModifiedSetRec(ConstraintPtr cnst)
594 std::vector<ElementPtr>::iterator elemIt;
595 for (elemIt=cnst->m_elementSet.begin(); elemIt!=cnst->m_elementSet.end(); ++elemIt) {
596 VariablePtr var = (*elemIt)->p_variable;
597 vector<ElementPtr> cnsts = var->m_cnsts;
598 std::vector<ElementPtr>::iterator cnstIt;
599 for (cnstIt=cnsts.begin(); var->m_visited != m_visitedCounter
600 && cnstIt!=cnsts.end(); ++cnstIt){
601 if ((*cnstIt)->p_constraint != cnst
602 && std::find(m_modifiedConstraintSet.begin(),
603 m_modifiedConstraintSet.end(), (*cnstIt)->p_constraint)
604 == m_modifiedConstraintSet.end()) {
605 m_modifiedConstraintSet.push_back((*cnstIt)->p_constraint);
606 updateModifiedSetRec((*cnstIt)->p_constraint);
609 var->m_visited = m_visitedCounter;
614 void Solver::updateModifiedSet(ConstraintPtr cnst)
616 /* nothing to do if selective update isn't active */
617 if (m_selectiveUpdateActive
618 && std::find(m_modifiedConstraintSet.begin(),
619 m_modifiedConstraintSet.end(), cnst)
620 == m_modifiedConstraintSet.end()) {
621 m_modifiedConstraintSet.push_back(cnst);
622 updateModifiedSetRec(cnst);
626 /** \brief Remove all constraints of the modified_constraint_set.
628 * \param sys the lmm_system_t
631 void Solver::removeAllModifiedSet()
633 if (++m_visitedCounter == 1) {
634 /* the counter wrapped around, reset each variable->visited */
635 std::vector<VariablePtr>::iterator it;
636 for (it=m_variableSet.begin(); it!=m_variableSet.end(); ++it)
637 (*it)->m_visited = 0;
639 m_modifiedConstraintSet.clear();
642 inline void Solver::disableVariable(VariablePtr var)
649 XBT_IN("(sys=%p, var=%p)", this, var);
652 std::vector<ElementPtr>::iterator varIt, elemIt;
653 for (varIt=var->m_cnsts.begin(); varIt!=var->m_cnsts.end(); ) {
654 vector<ElementPtr> elemSet = (*varIt)->p_constraint->m_elementSet;
655 elemSet.erase(std::find(elemSet.begin(), elemSet.end(), *varIt));
656 vector<ElementPtr> activeElemSet = (*varIt)->p_constraint->m_activeElementSet;
657 activeElemSet.erase(std::find(activeElemSet.begin(), activeElemSet.end(), *varIt));
658 if (elemSet.empty()) {
659 inactivateConstraint((*varIt)->p_constraint);
660 var->m_cnsts.erase(varIt);
667 updateModifiedSet(var->m_cnsts.front()->p_constraint);
668 var->m_cnsts.clear();
673 Constraint::Constraint(void *id, double bound):
674 p_id(id), m_idInt(1), m_bound(bound), m_usage(0), m_shared(1),
675 m_elementsZeroWeight(0)
677 m_idInt = Global_const_debug_id++;
680 void Constraint::addElement(ElementPtr elem)
682 m_elementSet.push_back(elem);
683 if (elem->p_variable->m_weight<0)
684 std::swap(m_elementSet[m_elementSet.size()-1], m_elementSet[m_elementsZeroWeight++]);
687 void Constraint::shared() {
691 bool Constraint::isShared() {
695 Variable::Variable(void *id, double weight, double bound, int visited)
700 XBT_IN("(sys=%p, id=%p, weight=%f, bound=%f, num_cons =%d)",
701 0, id, weight, bound, 0);
704 m_idInt = Global_debug_id++;
706 // TODO: optimize cache
711 m_visited = visited;//sys->visited_counter - 1;
714 //m_func_f = func_f_def;
715 //m_func_fp = func_fp_def;
716 //m_func_fpi = func_fpi_def;
719 XBT_OUT(" returns %p", this);
722 double Variable::value()
727 double Variable::bound()
732 Element::Element(ConstraintPtr cnst, VariablePtr var, double value):
733 p_constraint(cnst), p_variable(var), m_value(value)