Logo AND Algorithmique Numérique Distribuée

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