Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9be12ea769be94e5555b39280b7a53acc6e17d0d
[simgrid.git] / src / surf / fair_bottleneck.c
1 /*      $Id$ */
2
3 /* Copyright (c) 2007 Arnaud Legrand. All rights reserved.               */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8
9 #include "xbt/sysdep.h"
10 #include "xbt/log.h"
11 #include "maxmin_private.h"
12 #include <stdlib.h>
13 #include <math.h>
14
15 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_maxmin);
16 #define SHOW_EXPR_G(expr) DEBUG1(#expr " = %g",expr);
17 #define SHOW_EXPR_D(expr) DEBUG1(#expr " = %d",expr);
18 #define SHOW_EXPR_P(expr) DEBUG1(#expr " = %p",expr);
19
20 void bottleneck_solve(lmm_system_t sys)
21 {
22   lmm_variable_t var = NULL;
23   lmm_variable_t var_to_update = NULL;
24   lmm_constraint_t cnst = NULL;
25   lmm_constraint_t useless_cnst = NULL;
26   s_lmm_constraint_t s_cnst;
27   lmm_constraint_t cnst_next = NULL;
28   lmm_element_t elem = NULL;
29   xbt_swag_t cnst_list = NULL;
30   xbt_swag_t var_list = NULL;
31   xbt_swag_t elem_list = NULL;
32   double min_usage = -1;
33   int i;
34
35   static s_xbt_swag_t cnst_to_update;
36
37   if (!(sys->modified))
38     return;
39
40   /* Init */
41   xbt_swag_init(&(cnst_to_update),
42                 xbt_swag_offset(s_cnst, saturated_constraint_set_hookup));
43
44   var_list = &(sys->variable_set);
45   DEBUG1("Variable set : %d", xbt_swag_size(var_list));
46   xbt_swag_foreach(var, var_list) {
47     int nb=0;
48     var->value = 0.0;
49     for (i = 0; i < var->cnsts_number; i++) {
50       if(var->cnsts[i].value==0.0) nb++;
51     }
52     if((nb==var->cnsts_number) && (var->weight>0.0))
53       var->value = 1.0;
54   }
55
56   cnst_list = &(sys->active_constraint_set);
57   DEBUG1("Active constraints : %d", xbt_swag_size(cnst_list));
58   xbt_swag_foreach(cnst, cnst_list) {
59     xbt_swag_insert(cnst, &(sys->saturated_constraint_set));
60   }
61   cnst_list = &(sys->saturated_constraint_set);
62   xbt_swag_foreach(cnst, cnst_list) {
63     cnst->remaining = cnst->bound;
64     cnst->usage = 0.0;
65   }
66
67   DEBUG0("Fair bottleneck Initialized");
68
69   /* 
70    * Compute Usage and store the variables that reach the maximum.
71    */
72   while (1) {
73 /*     if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { */
74 /*       DEBUG0("Fair bottleneck done"); */
75 /*       lmm_print(sys); */
76 /*     } */
77     DEBUG1("******* Constraints to process: %d *******", xbt_swag_size(cnst_list));
78     min_usage = -1;
79     xbt_swag_foreach_safe(cnst, cnst_next, cnst_list) {
80       int nb = 0;
81       double max_elem = 0.0;
82       DEBUG1("Processing cnst %p ", cnst);
83       elem_list = &(cnst->element_set);
84       cnst->usage = 0.0;
85       xbt_swag_foreach(elem, elem_list) {
86         if (elem->variable->weight <= 0)
87           break;
88         if ((elem->value > 0)) {
89           nb++;
90           if (max_elem > 0)
91             max_elem =
92                 MAX(max_elem, elem->value / elem->variable->weight);
93           else
94             max_elem = elem->value / elem->variable->weight;
95         }
96         //      make_elem_active(elem);
97       }
98       DEBUG2("\tmax_elem : %g with %d variables",  max_elem,nb);
99       if(nb>0 && !cnst->shared)
100         nb = 1;
101       cnst->usage = max_elem * nb;
102       DEBUG3("\tConstraint Usage %p : %f with %d variables", cnst, cnst->usage,nb);
103       if(!nb) {
104         xbt_swag_remove(cnst, cnst_list);
105         continue;
106       }
107
108       /* Saturated constraints update */
109       if (min_usage < 0 || min_usage > cnst->remaining / cnst->usage) {
110         DEBUG3("Update min_usage (%g) with cnst %p -> %g",min_usage, cnst,
111                cnst->remaining / cnst->usage);
112
113         min_usage = cnst->remaining / cnst->usage;
114         while ((useless_cnst = xbt_swag_extract(&(cnst_to_update)))) {
115           xbt_swag_insert_at_head(useless_cnst, cnst_list);
116         }
117         xbt_swag_remove(cnst, cnst_list);
118         xbt_swag_insert(cnst, &(cnst_to_update));
119       } else if (min_usage == cnst->remaining / cnst->usage) {
120         DEBUG2("Keep   min_usage (%g) with cnst %p",min_usage, cnst);
121         xbt_swag_remove(cnst, cnst_list);
122         xbt_swag_insert(cnst, &(cnst_to_update));
123       } else {
124         DEBUG1("\tmin_usage: %f. No update",min_usage);
125       }
126     }
127
128     if (!xbt_swag_size(&cnst_to_update))
129       break;
130
131     var_list = &(sys->variable_set);
132     var_to_update = NULL;
133     xbt_swag_foreach(var, var_list) {
134       if(!var->value  && var->bound>0 && 
135          var->bound<min_usage) {
136         var_to_update = var;
137         min_usage = var->bound;
138       }
139     }
140     if(var_to_update) {
141       DEBUG2("\tUpdating var %p (%g)",var,var->value);
142       var->value = var->bound;
143       
144       for (i = 0; i < var->cnsts_number; i++) {
145         lmm_element_t elm = &var->cnsts[i];
146         cnst = elm->constraint;
147         DEBUG1("\t\tUpdating cnst %p",cnst);
148         double_update(&(cnst->remaining), elm->value * var->value);
149         double_update(&(cnst->usage), elm->value / var->weight);
150         //              make_elem_inactive(elm);
151       }
152       while ((cnst = xbt_swag_extract(&cnst_to_update))) {
153         xbt_swag_insert(cnst, cnst_list);
154       }
155       continue;
156     }
157
158     while ((cnst_next = xbt_swag_extract(&cnst_to_update))) {
159       int nb = 0;
160       double remaining = cnst_next->remaining;
161       elem_list = &(cnst_next->element_set);
162       xbt_swag_foreach(elem, elem_list) {
163         if (elem->variable->weight <= 0)
164           break;
165         if ((elem->value > 0))
166           nb++;
167       }
168       if(nb>0 && !(cnst_next->shared))
169         nb = 1;
170
171       DEBUG1("Updating for cnst %p",cnst_next);
172
173       xbt_swag_foreach(elem, elem_list) {
174         if (elem->value <= 0) continue;
175
176         var = elem->variable;
177
178         if (var->weight <= 0)
179           break;
180         if (var->value == 0.0) {
181           DEBUG2("\tUpdating var %p (%g)",var,var->value);
182           var->value = var->weight * remaining / (nb * elem->value);
183
184           /* Update usage */
185
186           for (i = 0; i < var->cnsts_number; i++) {
187             lmm_element_t elm = &var->cnsts[i];
188             cnst = elm->constraint;
189             DEBUG1("\t\tUpdating cnst %p",cnst);
190             double_update(&(cnst->remaining), elm->value * var->value);
191             double_update(&(cnst->usage), elm->value / var->weight);
192             //              make_elem_inactive(elm);
193           }
194         }
195       }
196     }
197   }
198
199   sys->modified = 0;
200   if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
201     DEBUG0("Fair bottleneck done");
202     lmm_print(sys);
203   }
204 }