Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add function xbt_dynar_compare
[simgrid.git] / src / surf / maxmin.c
1 /* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7
8 #include "xbt/sysdep.h"
9 #include "xbt/log.h"
10 #include "xbt/mallocator.h"
11 #include "maxmin_private.h"
12 #include <stdlib.h>
13 #include <stdio.h>              /* sprintf */
14 #include <math.h>
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_maxmin, surf,
16                                 "Logging specific to SURF (maxmin)");
17
18 static void *lmm_variable_mallocator_new_f(void);
19 static void lmm_variable_mallocator_free_f(void *var);
20 static void lmm_variable_mallocator_reset_f(void *var);
21 static void lmm_update_modified_set(lmm_system_t sys,
22                                     lmm_constraint_t cnst);
23 static void lmm_remove_all_modified_set(lmm_system_t sys);
24 int sg_maxmin_selective_update = 1;
25 static int Global_debug_id = 1;
26 static int Global_const_debug_id = 1;
27 lmm_system_t lmm_system_new(void)
28 {
29   lmm_system_t l = NULL;
30   s_lmm_variable_t var;
31   s_lmm_constraint_t cnst;
32
33   l = xbt_new0(s_lmm_system_t, 1);
34
35   l->modified = 0;
36   l->selective_update_active = sg_maxmin_selective_update;
37
38   DEBUG1("Setting selective_update_active flag to %d\n",
39          l->selective_update_active);
40
41   xbt_swag_init(&(l->variable_set),
42                 xbt_swag_offset(var, variable_set_hookup));
43   xbt_swag_init(&(l->constraint_set),
44                 xbt_swag_offset(cnst, constraint_set_hookup));
45
46   xbt_swag_init(&(l->active_constraint_set),
47                 xbt_swag_offset(cnst, active_constraint_set_hookup));
48
49   xbt_swag_init(&(l->modified_constraint_set),
50                 xbt_swag_offset(cnst, modified_constraint_set_hookup));
51   xbt_swag_init(&(l->saturated_variable_set),
52                 xbt_swag_offset(var, saturated_variable_set_hookup));
53   xbt_swag_init(&(l->saturated_constraint_set),
54                 xbt_swag_offset(cnst, saturated_constraint_set_hookup));
55
56   l->variable_mallocator = xbt_mallocator_new(64,
57                                               lmm_variable_mallocator_new_f,
58                                               lmm_variable_mallocator_free_f,
59                                               lmm_variable_mallocator_reset_f);
60
61   return l;
62 }
63
64 void lmm_system_free(lmm_system_t sys)
65 {
66   lmm_variable_t var = NULL;
67   lmm_constraint_t cnst = NULL;
68
69   while ((var = extract_variable(sys))) {
70     WARN2
71         ("Variable %p (%d) still in LMM system when freing it: this may be a bug",
72          var, var->id_int);
73     lmm_var_free(sys, var);
74   }
75
76   while ((cnst = extract_constraint(sys)))
77     lmm_cnst_free(sys, cnst);
78
79   xbt_mallocator_free(sys->variable_mallocator);
80   free(sys);
81 }
82
83 XBT_INLINE void lmm_variable_disable(lmm_system_t sys, lmm_variable_t var)
84 {
85   int i;
86   lmm_element_t elem = NULL;
87
88   XBT_IN2("(sys=%p, var=%p)", sys, var);
89   sys->modified = 1;
90
91   for (i = 0; i < var->cnsts_number; i++) {
92     elem = &var->cnsts[i];
93     xbt_swag_remove(elem, &(elem->constraint->element_set));
94     xbt_swag_remove(elem, &(elem->constraint->active_element_set));
95     if (!xbt_swag_size(&(elem->constraint->element_set)))
96       make_constraint_inactive(sys, elem->constraint);
97     else
98       lmm_update_modified_set(sys, elem->constraint);
99   }
100   var->cnsts_number = 0;
101   XBT_OUT;
102 }
103
104 static void lmm_var_free(lmm_system_t sys, lmm_variable_t var)
105 {
106
107   lmm_variable_disable(sys, var);
108   free(var->cnsts);
109   xbt_mallocator_release(sys->variable_mallocator, var);
110 }
111
112 static XBT_INLINE void lmm_cnst_free(lmm_system_t sys,
113                                      lmm_constraint_t cnst)
114 {
115 /*   xbt_assert0(xbt_swag_size(&(cnst->element_set)), */
116 /*            "This list should be empty!"); */
117   remove_active_constraint(sys, cnst);
118   free(cnst);
119 }
120
121 lmm_constraint_t lmm_constraint_new(lmm_system_t sys, void *id,
122                                     double bound_value)
123 {
124   lmm_constraint_t cnst = NULL;
125   s_lmm_element_t elem;
126
127   cnst = xbt_new0(s_lmm_constraint_t, 1);
128   cnst->id = id;
129   cnst->id_int = Global_const_debug_id++;
130   xbt_swag_init(&(cnst->element_set),
131                 xbt_swag_offset(elem, element_set_hookup));
132   xbt_swag_init(&(cnst->active_element_set),
133                 xbt_swag_offset(elem, active_element_set_hookup));
134
135   cnst->bound = bound_value;
136   cnst->usage = 0;
137   cnst->shared = 1;
138   insert_constraint(sys, cnst);
139
140   return cnst;
141 }
142
143 XBT_INLINE void lmm_constraint_shared(lmm_constraint_t cnst)
144 {
145   cnst->shared = 0;
146 }
147
148 XBT_INLINE int lmm_constraint_is_shared(lmm_constraint_t cnst)
149 {
150   return (cnst->shared);
151 }
152
153 XBT_INLINE void lmm_constraint_free(lmm_system_t sys,
154                                     lmm_constraint_t cnst)
155 {
156   remove_constraint(sys, cnst);
157   lmm_cnst_free(sys, cnst);
158 }
159
160 static void *lmm_variable_mallocator_new_f(void)
161 {
162   return xbt_new(s_lmm_variable_t, 1);
163 }
164
165 static void lmm_variable_mallocator_free_f(void *var)
166 {
167   xbt_free(var);
168 }
169
170 static void lmm_variable_mallocator_reset_f(void *var)
171 {
172   /* memset to zero like calloc */
173   memset(var, 0, sizeof(s_lmm_variable_t));
174 }
175
176 lmm_variable_t lmm_variable_new(lmm_system_t sys, void *id,
177                                 double weight,
178                                 double bound, int number_of_constraints)
179 {
180   lmm_variable_t var = NULL;
181   int i;
182
183   XBT_IN5("(sys=%p, id=%p, weight=%f, bound=%f, num_cons =%d)",
184           sys, id, weight, bound, number_of_constraints);
185
186   var = xbt_mallocator_get(sys->variable_mallocator);
187   var->id = id;
188   var->id_int = Global_debug_id++;
189   var->cnsts = xbt_new0(s_lmm_element_t, number_of_constraints);
190   for (i = 0; i < number_of_constraints; i++) {
191     /* Should be useless because of the 
192        calloc but it seems to help valgrind... */
193     var->cnsts[i].element_set_hookup.next = NULL;
194     var->cnsts[i].element_set_hookup.prev = NULL;
195     var->cnsts[i].active_element_set_hookup.next = NULL;
196     var->cnsts[i].active_element_set_hookup.prev = NULL;
197     var->cnsts[i].constraint = NULL;
198     var->cnsts[i].variable = NULL;
199     var->cnsts[i].value = 0.0;
200   }
201   var->cnsts_size = number_of_constraints;
202   var->cnsts_number = 0;        /* Should be useless because of the 
203                                    calloc but it seems to help valgrind... */
204   var->weight = weight;
205   var->bound = bound;
206   var->value = 0.0;
207
208
209   var->func_f = func_f_def;
210   var->func_fp = func_fp_def;
211   var->func_fpi = func_fpi_def;
212
213   if (weight)
214     xbt_swag_insert_at_head(var, &(sys->variable_set));
215   else
216     xbt_swag_insert_at_tail(var, &(sys->variable_set));
217   XBT_OUT;
218   return var;
219 }
220
221 void lmm_variable_free(lmm_system_t sys, lmm_variable_t var)
222 {
223   remove_variable(sys, var);
224   lmm_var_free(sys, var);
225 }
226
227 XBT_INLINE double lmm_variable_getvalue(lmm_variable_t var)
228 {
229   return (var->value);
230 }
231
232 XBT_INLINE double lmm_variable_getbound(lmm_variable_t var)
233 {
234   return (var->bound);
235 }
236
237 void lmm_expand(lmm_system_t sys, lmm_constraint_t cnst,
238                 lmm_variable_t var, double value)
239 {
240   lmm_element_t elem = NULL;
241
242   sys->modified = 1;
243
244   xbt_assert0(var->cnsts_number < var->cnsts_size, "Too much constraints");
245
246   elem = &(var->cnsts[var->cnsts_number++]);
247
248   elem->value = value;
249   elem->constraint = cnst;
250   elem->variable = var;
251
252   if (var->weight)
253     xbt_swag_insert_at_head(elem, &(elem->constraint->element_set));
254   else
255     xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set));
256
257   make_constraint_active(sys, cnst);
258   lmm_update_modified_set(sys, cnst);
259 }
260
261 void lmm_expand_add(lmm_system_t sys, lmm_constraint_t cnst,
262                     lmm_variable_t var, double value)
263 {
264   int i;
265   sys->modified = 1;
266
267   for (i = 0; i < var->cnsts_number; i++)
268     if (var->cnsts[i].constraint == cnst)
269       break;
270
271   if (i < var->cnsts_number) {
272     if (cnst->shared)
273       var->cnsts[i].value += value;
274     else
275       var->cnsts[i].value = MAX(var->cnsts[i].value, value);
276     lmm_update_modified_set(sys, cnst);
277   } else
278     lmm_expand(sys, cnst, var, value);
279 }
280
281 void lmm_elem_set_value(lmm_system_t sys, lmm_constraint_t cnst,
282                         lmm_variable_t var, double value)
283 {
284   int i;
285
286   for (i = 0; i < var->cnsts_number; i++)
287     if (var->cnsts[i].constraint == cnst)
288       break;
289
290   if (i < var->cnsts_number) {
291     var->cnsts[i].value = value;
292     sys->modified = 1;
293     lmm_update_modified_set(sys, cnst);
294   } else
295     DIE_IMPOSSIBLE;
296 }
297
298 XBT_INLINE lmm_constraint_t lmm_get_cnst_from_var(lmm_system_t sys,
299                                                   lmm_variable_t var,
300                                                   int num)
301 {
302   if (num < var->cnsts_number)
303     return (var->cnsts[num].constraint);
304   else
305     return NULL;
306 }
307
308 XBT_INLINE int lmm_get_number_of_cnst_from_var(lmm_system_t sys,
309                                                lmm_variable_t var)
310 {
311   return (var->cnsts_number);
312 }
313
314 lmm_variable_t lmm_get_var_from_cnst(lmm_system_t sys,
315                                      lmm_constraint_t cnst,
316                                      lmm_element_t * elem)
317 {
318   if (!(*elem))
319     *elem = xbt_swag_getFirst(&(cnst->element_set));
320   else
321     *elem = xbt_swag_getNext(*elem, cnst->element_set.offset);
322   if (*elem)
323     return (*elem)->variable;
324   else
325     return NULL;
326 }
327
328 XBT_INLINE void *lmm_constraint_id(lmm_constraint_t cnst)
329 {
330   return cnst->id;
331 }
332
333 XBT_INLINE void *lmm_variable_id(lmm_variable_t var)
334 {
335   return var->id;
336 }
337
338 static XBT_INLINE void saturated_constraint_set_update(lmm_system_t sys,
339                                                        lmm_constraint_t
340                                                        cnst,
341                                                        double *min_usage)
342 {
343   lmm_constraint_t useless_cnst = NULL;
344
345   XBT_IN3("sys=%p, cnst=%p, min_usage=%f", sys, cnst, *min_usage);
346   if (cnst->usage <= 0) {
347     XBT_OUT;
348     return;
349   }
350   if (cnst->remaining <= 0) {
351     XBT_OUT;
352     return;
353   }
354   if ((*min_usage < 0) || (*min_usage > cnst->remaining / cnst->usage)) {
355     *min_usage = cnst->remaining / cnst->usage;
356     LOG3(xbt_log_priority_trace,
357          "min_usage=%f (cnst->remaining=%f, cnst->usage=%f)", *min_usage,
358          cnst->remaining, cnst->usage);
359     while ((useless_cnst =
360             xbt_swag_getFirst(&(sys->saturated_constraint_set))))
361       xbt_swag_remove(useless_cnst, &(sys->saturated_constraint_set));
362
363     xbt_swag_insert(cnst, &(sys->saturated_constraint_set));
364   } else if (*min_usage == cnst->remaining / cnst->usage) {
365     xbt_swag_insert(cnst, &(sys->saturated_constraint_set));
366   }
367   XBT_OUT;
368 }
369
370 static XBT_INLINE void saturated_variable_set_update(lmm_system_t sys)
371 {
372   lmm_constraint_t cnst = NULL;
373   xbt_swag_t cnst_list = NULL;
374   lmm_element_t elem = NULL;
375   xbt_swag_t elem_list = NULL;
376
377   cnst_list = &(sys->saturated_constraint_set);
378   while ((cnst = xbt_swag_getFirst(cnst_list))) {
379     elem_list = &(cnst->active_element_set);
380     xbt_swag_foreach(elem, elem_list) {
381       if (elem->variable->weight <= 0)
382         break;
383       if ((elem->value > 0))
384         xbt_swag_insert(elem->variable, &(sys->saturated_variable_set));
385     }
386     xbt_swag_remove(cnst, cnst_list);
387   }
388 }
389
390 void lmm_print(lmm_system_t sys)
391 {
392   lmm_constraint_t cnst = NULL;
393   lmm_element_t elem = NULL;
394   lmm_variable_t var = NULL;
395   xbt_swag_t cnst_list = NULL;
396   xbt_swag_t var_list = NULL;
397   xbt_swag_t elem_list = NULL;
398   char print_buf[1024];
399   char *trace_buf = xbt_malloc0(sizeof(char));
400   double sum = 0.0;
401
402   /* Printing Objective */
403   var_list = &(sys->variable_set);
404   sprintf(print_buf, "MAX-MIN ( ");
405   trace_buf =
406       xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
407   strcat(trace_buf, print_buf);
408   xbt_swag_foreach(var, var_list) {
409     sprintf(print_buf, "'%d'(%f) ", var->id_int, var->weight);
410     trace_buf =
411         xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
412     strcat(trace_buf, print_buf);
413   }
414   sprintf(print_buf, ")");
415   trace_buf =
416       xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
417   strcat(trace_buf, print_buf);
418   fprintf(stderr, "%s", trace_buf);
419   //DEBUG1("%20s", trace_buf); FIXME
420   trace_buf[0] = '\000';
421
422   DEBUG0("Constraints");
423   /* Printing Constraints */
424   cnst_list = &(sys->active_constraint_set);
425   xbt_swag_foreach(cnst, cnst_list) {
426     sum = 0.0;
427     elem_list = &(cnst->element_set);
428     sprintf(print_buf, "\t");
429     trace_buf =
430         xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
431     strcat(trace_buf, print_buf);
432     xbt_swag_foreach(elem, elem_list) {
433       sprintf(print_buf, "%f.'%d'(%f) + ", elem->value,
434               elem->variable->id_int, elem->variable->value);
435       trace_buf =
436           xbt_realloc(trace_buf,
437                       strlen(trace_buf) + strlen(print_buf) + 1);
438       strcat(trace_buf, print_buf);
439       sum += elem->value * elem->variable->value;
440     }
441     sprintf(print_buf, "0 <= %f ('%d')", cnst->bound, cnst->id_int);
442     trace_buf =
443         xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
444     strcat(trace_buf, print_buf);
445
446     if (!cnst->shared) {
447       sprintf(print_buf, " [MAX-Constraint]");
448       trace_buf =
449           xbt_realloc(trace_buf,
450                       strlen(trace_buf) + strlen(print_buf) + 1);
451       strcat(trace_buf, print_buf);
452     }
453     //   DEBUG1("%s", trace_buf);
454     fprintf(stderr, "%s", trace_buf);
455     trace_buf[0] = '\000';
456     xbt_assert3(!double_positive(sum - cnst->bound),
457                 "Incorrect value (%f is not smaller than %f): %g",
458                 sum, cnst->bound, sum - cnst->bound);
459   }
460
461   DEBUG0("Variables");
462   /* Printing Result */
463   xbt_swag_foreach(var, var_list) {
464     if (var->bound > 0) {
465       DEBUG4("'%d'(%f) : %f (<=%f)", var->id_int, var->weight, var->value,
466              var->bound);
467       xbt_assert2(!double_positive(var->value - var->bound),
468                   "Incorrect value (%f is not smaller than %f",
469                   var->value, var->bound);
470     } else {
471       DEBUG3("'%d'(%f) : %f", var->id_int, var->weight, var->value);
472     }
473   }
474
475   free(trace_buf);
476 }
477
478 void lmm_solve(lmm_system_t sys)
479 {
480   lmm_variable_t var = NULL;
481   lmm_constraint_t cnst = NULL;
482   lmm_element_t elem = NULL;
483   xbt_swag_t cnst_list = NULL;
484   xbt_swag_t var_list = NULL;
485   xbt_swag_t elem_list = NULL;
486   double min_usage = -1;
487   double min_bound = -1;
488
489   if (!(sys->modified))
490     return;
491
492   /*
493    * Compute Usage and store the variables that reach the maximum.
494    */
495   cnst_list =
496       sys->
497       selective_update_active ? &(sys->modified_constraint_set) :
498       &(sys->active_constraint_set);
499
500   DEBUG1("Active constraints : %d", xbt_swag_size(cnst_list));
501   /* Init: Only modified code portions */
502   xbt_swag_foreach(cnst, cnst_list) {
503     elem_list = &(cnst->element_set);
504     //DEBUG1("Variable set : %d", xbt_swag_size(elem_list));
505     xbt_swag_foreach(elem, elem_list) {
506       var = elem->variable;
507       if (var->weight <= 0.0)
508         break;
509       var->value = 0.0;
510     }
511   }
512
513   DEBUG1("Active constraints : %d", xbt_swag_size(cnst_list));
514   xbt_swag_foreach(cnst, cnst_list) {
515     /* INIT */
516     cnst->remaining = cnst->bound;
517     if (cnst->remaining == 0)
518       continue;
519     cnst->usage = 0;
520     elem_list = &(cnst->element_set);
521     xbt_swag_foreach(elem, elem_list) {
522       /* 0-weighted elements (ie, sleep actions) are at the end of the swag and we don't want to consider them */
523       if (elem->variable->weight <= 0)
524         break;
525       if ((elem->value > 0)) {
526         if (cnst->shared)
527           cnst->usage += elem->value / elem->variable->weight;
528         else if (cnst->usage < elem->value / elem->variable->weight)
529           cnst->usage = elem->value / elem->variable->weight;
530
531         make_elem_active(elem);
532       }
533     }
534     DEBUG2("Constraint Usage %d : %f", cnst->id_int, cnst->usage);
535     /* Saturated constraints update */
536     saturated_constraint_set_update(sys, cnst, &min_usage);
537   }
538   saturated_variable_set_update(sys);
539
540   /* Saturated variables update */
541
542   do {
543     /* Fix the variables that have to be */
544     var_list = &(sys->saturated_variable_set);
545
546     xbt_swag_foreach(var, var_list) {
547       if (var->weight <= 0.0)
548         DIE_IMPOSSIBLE;
549       /* First check if some of these variables have reach their upper
550          bound and update min_usage accordingly. */
551       DEBUG5
552           ("var=%d, var->bound=%f, var->weight=%f, min_usage=%f, var->bound*var->weight=%f",
553            var->id_int, var->bound, var->weight, min_usage,
554            var->bound * var->weight);
555       if ((var->bound > 0) && (var->bound * var->weight < min_usage)) {
556         if (min_bound < 0)
557           min_bound = var->bound;
558         else
559           min_bound = MIN(min_bound, var->bound);
560         DEBUG1("Updated min_bound=%f", min_bound);
561       }
562     }
563
564
565     while ((var = xbt_swag_getFirst(var_list))) {
566       int i;
567
568       if (min_bound < 0) {
569         var->value = min_usage / var->weight;
570       } else {
571         if (min_bound == var->bound)
572           var->value = var->bound;
573         else {
574           xbt_swag_remove(var, var_list);
575           continue;
576         }
577       }
578       DEBUG5("Min usage: %f, Var(%d)->weight: %f, Var(%d)->value: %f ",
579              min_usage, var->id_int, var->weight, var->id_int, var->value);
580
581
582       /* Update usage */
583
584       for (i = 0; i < var->cnsts_number; i++) {
585         elem = &var->cnsts[i];
586         cnst = elem->constraint;
587         if (cnst->shared) {
588           double_update(&(cnst->remaining), elem->value * var->value);
589           double_update(&(cnst->usage), elem->value / var->weight);
590           make_elem_inactive(elem);
591         } else {                /* FIXME one day: We recompute usage.... :( */
592           cnst->usage = 0.0;
593           make_elem_inactive(elem);
594           elem_list = &(cnst->element_set);
595           xbt_swag_foreach(elem, elem_list) {
596             if (elem->variable->weight <= 0)
597               break;
598             if (elem->variable->value > 0)
599               break;
600             if ((elem->value > 0)) {
601               cnst->usage =
602                   MAX(cnst->usage, elem->value / elem->variable->weight);
603               DEBUG2("Constraint Usage %d : %f", cnst->id_int,
604                      cnst->usage);
605               make_elem_active(elem);
606             }
607           }
608         }
609       }
610       xbt_swag_remove(var, var_list);
611     }
612
613     /* Find out which variables reach the maximum */
614     cnst_list =
615         sys->selective_update_active ? &(sys->modified_constraint_set) :
616         &(sys->active_constraint_set);
617     min_usage = -1;
618     min_bound = -1;
619     xbt_swag_foreach(cnst, cnst_list) {
620       saturated_constraint_set_update(sys, cnst, &min_usage);
621     }
622     saturated_variable_set_update(sys);
623
624   } while (xbt_swag_size(&(sys->saturated_variable_set)));
625
626   sys->modified = 0;
627   if (sys->selective_update_active)
628     lmm_remove_all_modified_set(sys);
629
630   if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
631     lmm_print(sys);
632   }
633 }
634
635 /* Not a O(1) function */
636
637 void lmm_update(lmm_system_t sys, lmm_constraint_t cnst,
638                 lmm_variable_t var, double value)
639 {
640   int i;
641
642   for (i = 0; i < var->cnsts_number; i++)
643     if (var->cnsts[i].constraint == cnst) {
644       var->cnsts[i].value = value;
645       sys->modified = 1;
646       lmm_update_modified_set(sys, cnst);
647       return;
648     }
649 }
650
651 /** \brief Attribute the value bound to var->bound.
652  * 
653  *  \param sys the lmm_system_t
654  *  \param var the lmm_variable_t
655  *  \param bound the new bound to associate with var
656  * 
657  *  Makes var->bound equal to bound. Whenever this function is called 
658  *  a change is  signed in the system. To
659  *  avoid false system changing detection it is a good idea to test 
660  *  (bound != 0) before calling it.
661  *
662  */
663 void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var,
664                                double bound)
665 {
666   int i;
667
668   sys->modified = 1;
669   var->bound = bound;
670
671   for (i = 0; i < var->cnsts_number; i++)
672     lmm_update_modified_set(sys, var->cnsts[i].constraint);
673
674 }
675
676
677 void lmm_update_variable_weight(lmm_system_t sys, lmm_variable_t var,
678                                 double weight)
679 {
680   int i;
681   lmm_element_t elem;
682
683   if (weight == var->weight)
684     return;
685   XBT_IN3("(sys=%p, var=%p, weight=%f)", sys, var, weight);
686   sys->modified = 1;
687   var->weight = weight;
688   xbt_swag_remove(var, &(sys->variable_set));
689   if (weight)
690     xbt_swag_insert_at_head(var, &(sys->variable_set));
691   else
692     xbt_swag_insert_at_tail(var, &(sys->variable_set));
693
694   for (i = 0; i < var->cnsts_number; i++) {
695     elem = &var->cnsts[i];
696     xbt_swag_remove(elem, &(elem->constraint->element_set));
697     if (weight)
698       xbt_swag_insert_at_head(elem, &(elem->constraint->element_set));
699     else
700       xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set));
701
702     lmm_update_modified_set(sys, elem->constraint);
703   }
704   if (!weight)
705     var->value = 0.0;
706
707   XBT_OUT;
708 }
709
710 XBT_INLINE double lmm_get_variable_weight(lmm_variable_t var)
711 {
712   return var->weight;
713 }
714
715 XBT_INLINE void lmm_update_constraint_bound(lmm_system_t sys,
716                                             lmm_constraint_t cnst,
717                                             double bound)
718 {
719   sys->modified = 1;
720   lmm_update_modified_set(sys, cnst);
721   cnst->bound = bound;
722 }
723
724 XBT_INLINE int lmm_constraint_used(lmm_system_t sys, lmm_constraint_t cnst)
725 {
726   return xbt_swag_belongs(cnst, &(sys->active_constraint_set));
727 }
728
729 XBT_INLINE lmm_constraint_t lmm_get_first_active_constraint(lmm_system_t
730                                                             sys)
731 {
732   return xbt_swag_getFirst(&(sys->active_constraint_set));
733 }
734
735 XBT_INLINE lmm_constraint_t lmm_get_next_active_constraint(lmm_system_t
736                                                            sys,
737                                                            lmm_constraint_t
738                                                            cnst)
739 {
740   return xbt_swag_getNext(cnst, (sys->active_constraint_set).offset);
741 }
742
743 #ifdef HAVE_LATENCY_BOUND_TRACKING
744 XBT_INLINE int lmm_is_variable_limited_by_latency(lmm_variable_t var)
745 {
746   return (double_equals(var->bound, var->value));
747 }
748 #endif
749
750
751 /** \brief Update the constraint set propagating recursively to
752  *  other constraints so the system should not be entirely computed.
753  *
754  *  \param sys the lmm_system_t
755  *  \param cnst the lmm_constraint_t affected by the change
756  *
757  *  A recursive algorithm to optimize the system recalculation selecting only
758  *  constraints that have changed. Each constraint change is propagated
759  *  to the list of constraints for each variable.
760  */
761 static void lmm_update_modified_set(lmm_system_t sys,
762                                     lmm_constraint_t cnst)
763 {
764   lmm_element_t elem = NULL;
765   lmm_variable_t var = NULL;
766   xbt_swag_t elem_list = NULL;
767   int i;
768
769   /* return if selective update isn't active */
770   if (!sys->selective_update_active)
771     return;
772
773   //DEBUG1("Updating modified constraint set with constraint %d", cnst->id_int);
774
775   if (xbt_swag_belongs(cnst, &(sys->modified_constraint_set)))
776     return;
777
778   //DEBUG1("Inserting into modified constraint set %d", cnst->id_int);
779
780   /* add to modified set */
781   xbt_swag_insert(cnst, &(sys->modified_constraint_set));
782
783   elem_list = &(cnst->element_set);
784   xbt_swag_foreach(elem, elem_list) {
785     var = elem->variable;
786     for (i = 0; i < var->cnsts_number; i++)
787       if (cnst != var->cnsts[i].constraint) {
788         //DEBUG2("Updating modified %d calling for %d", cnst->id_int, var->cnsts[i].constraint->id_int);
789         lmm_update_modified_set(sys, var->cnsts[i].constraint);
790       }
791   }
792 }
793
794 /** \brief Remove all constraints of the modified_constraint_set.
795  *
796  *  \param sys the lmm_system_t
797  */
798 static void lmm_remove_all_modified_set(lmm_system_t sys)
799 {
800   lmm_element_t elem = NULL;
801   lmm_element_t elem_next = NULL;
802   xbt_swag_t elem_list = NULL;
803
804   elem_list = &(sys->modified_constraint_set);
805   xbt_swag_foreach_safe(elem, elem_next, elem_list) {
806     xbt_swag_remove(elem, elem_list);
807   }
808 }