Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'oldstyle_element_set'
authorFabien Chaix <chaix@ics.forth.gr>
Wed, 24 Feb 2016 12:05:57 +0000 (14:05 +0200)
committerFabien Chaix <chaix@ics.forth.gr>
Wed, 24 Feb 2016 12:05:57 +0000 (14:05 +0200)
Fixed corner cases with concurrency and concurrency_share>1
Fixed a bug in lmm_on_disabled_var()
Added more flexibility to maxmin_bench to stress better SURF maxmin

1  2 
src/include/surf/maxmin.h
src/surf/maxmin.cpp
src/surf/maxmin_private.hpp
src/surf/network_cm02.cpp
teshsuite/surf/maxmin_bench/maxmin_bench.c

@@@ -217,7 -217,15 +217,15 @@@ XBT_PUBLIC(double) lmm_constraint_get_u
   */
  XBT_PUBLIC(void) lmm_constraint_concurrency_limit_set(lmm_constraint_t cnst, int concurrency_limit);
  
+ /**
+  * @brief Gets the concurrency limit for this constraint
+  * 
+  * @param cnst A constraint
+  * @return The concurrency limit used by this constraint
+  */
+ XBT_PUBLIC(int) lmm_constraint_concurrency_limit_get(lmm_constraint_t cnst);
  
+                            
  /**
   * @brief Reset the concurrency maximum for a given variable (we will update the maximum to reflect constraint evolution).
   *
@@@ -235,7 -243,7 +243,7 @@@ XBT_PUBLIC(void) lmm_constraint_concurr
   */
  XBT_PUBLIC(int) lmm_constraint_concurrency_maximum_get(lmm_constraint_t cnst);
  
 -                           
 +           
  /**
   * @brief Create a new Linear MaxMin variable
   * 
@@@ -474,6 -482,13 +482,13 @@@ XBT_PUBLIC(void) lmm_update_constraint_
   */
  XBT_PUBLIC(int) lmm_constraint_used(lmm_system_t sys, lmm_constraint_t cnst);
  
+ /**
+  * @brief Print the lmm system
+  * 
+  * @param sys The lmm system to print
+  */
+ XBT_PUBLIC(void) lmm_print(lmm_system_t sys);
+                            
  /**
   * @brief Solve the lmm system
   * 
diff --combined src/surf/maxmin.cpp
@@@ -46,15 -46,32 +46,32 @@@ static int lmm_concurrency_slack(lmm_co
  static int lmm_cnstrs_min_concurrency_slack(lmm_variable_t var);
  
  static void lmm_check_concurrency(lmm_system_t sys);
-   
- inline void lmm_decrease_concurrency(lmm_constraint_t cnstr){
-   xbt_assert(cnstr->concurrency_current>0);
-   cnstr->concurrency_current--;
+ inline int lmm_element_concurrency(lmm_element_t elem) {
+   //Ignore element with weight less than one (e.g. cross-traffic)
+   return (elem->value>=1)?1:0;
+   //There are other alternatives, but they will change the behaviour of the model..
+   //So do not use it unless you want to make a new model.
+   //If you do, remember to change the variables concurrency share to reflect it.
+   //Potential examples are:
+   //return (elem->weight>0)?1:0;//Include element as soon  as weight is non-zero
+   //return (int)ceil(elem->weight);//Include element as the rounded-up integer value of the element weight
+ }
+ inline void lmm_decrease_concurrency(lmm_element_t elem) {
+   xbt_assert(elem->constraint->concurrency_current>=lmm_element_concurrency(elem));
+   elem->constraint->concurrency_current-=lmm_element_concurrency(elem);
  }
  
- inline void lmm_increase_concurrency(lmm_constraint_t cnstr){
-   if(++cnstr->concurrency_current > cnstr->concurrency_maximum)
-     cnstr->concurrency_maximum=cnstr->concurrency_current;
+ inline void lmm_increase_concurrency(lmm_element_t elem) {
+   elem->constraint->concurrency_current+= lmm_element_concurrency(elem);
+   lmm_constraint_t cnstr=elem->constraint;
+   
+   if(cnstr->concurrency_current > cnstr->concurrency_maximum)
+     cnstr->concurrency_maximum= cnstr->concurrency_current;
    xbt_assert(cnstr->concurrency_limit<0 || cnstr->concurrency_current<=cnstr->concurrency_limit,"Concurrency limit overflow!");
  }
  
@@@ -126,27 -143,25 +143,38 @@@ static XBT_INLINE void lmm_variable_rem
    XBT_IN("(sys=%p, var=%p)", sys, var);
    sys->modified = 1;
  
 -  //TODOLATER Can do better than that by leaving only the variable in only one element_set, call lmm_update_modified_set, and then remove it..
 +  //TODOLATER Can do better than that by leaving only the variable in only one enabled_element_set, call lmm_update_modified_set, and then remove it..
    if(var->cnsts_number)
        lmm_update_modified_set(sys, var->cnsts[0].constraint);
  
    for (i = 0; i < var->cnsts_number; i++) {
      elem = &var->cnsts[i];
      if(var->weight>0)
-       lmm_decrease_concurrency(elem->constraint);
 -      lmm_decrease_concurrency(elem);
 -    xbt_swag_remove(elem, &(elem->constraint->element_set));
++    lmm_decrease_concurrency(elem);
 +    xbt_swag_remove(elem, &(elem->constraint->enabled_element_set));
 +    xbt_swag_remove(elem, &(elem->constraint->disabled_element_set));
      xbt_swag_remove(elem, &(elem->constraint->active_element_set));
 -    nelements=xbt_swag_size(&(elem->constraint->element_set));
 +    nelements=xbt_swag_size(&(elem->constraint->enabled_element_set)) +
 +              xbt_swag_size(&(elem->constraint->disabled_element_set));
      if (!nelements)
        make_constraint_inactive(sys, elem->constraint);
--  //Check if we can enable new variables going through the constraints where var was.
      else
        lmm_on_disabled_var(sys,elem->constraint);
    }
--
++  
++  //Check if we can enable new variables going through the constraints where var was.
++  //Do it after removing all elements, so he first disabled variables get priority over those with smaller
++  //requirement
++  for (i = 0; i < var->cnsts_number; i++) {
++    elem = &var->cnsts[i];
++    if(xbt_swag_size(&(elem->constraint->disabled_element_set)))
++      lmm_on_disabled_var(sys,elem->constraint);  
++  }
++  
    var->cnsts_number = 0;
++
++  lmm_check_concurrency(sys);
++    
    XBT_OUT();
  }
  
@@@ -160,6 -175,8 +188,6 @@@ static void lmm_var_free(lmm_system_t s
  static XBT_INLINE void lmm_cnst_free(lmm_system_t sys,
                                       lmm_constraint_t cnst)
  {
 -/*   xbt_assert(xbt_swag_size(&(cnst->element_set)), */
 -/*         "This list should be empty!"); */
    make_constraint_inactive(sys, cnst);
    free(cnst);
  }
@@@ -173,10 -190,8 +201,10 @@@ lmm_constraint_t lmm_constraint_new(lmm
    cnst = xbt_new0(s_lmm_constraint_t, 1);
    cnst->id = id;
    cnst->id_int = Global_const_debug_id++;
 -  xbt_swag_init(&(cnst->element_set),
 -                xbt_swag_offset(elem, element_set_hookup));
 +  xbt_swag_init(&(cnst->enabled_element_set),
 +                xbt_swag_offset(elem, enabled_element_set_hookup));
 +  xbt_swag_init(&(cnst->disabled_element_set),
 +                xbt_swag_offset(elem, disabled_element_set_hookup));
    xbt_swag_init(&(cnst->active_element_set),
                  xbt_swag_offset(elem, active_element_set_hookup));
  
    return cnst;
  }
  
+ int lmm_constraint_concurrency_limit_get(lmm_constraint_t cnst)
+ {
+  return cnst->concurrency_limit;
+ }
  void lmm_constraint_concurrency_limit_set(lmm_constraint_t cnst, int concurrency_limit)
  {
+   xbt_assert(concurrency_limit<0 || cnst->concurrency_maximum<=concurrency_limit,"New concurrency limit should be larger than observed concurrency maximum. Maybe you want to call  lmm_constraint_concurrency_maximum_reset() to reset the maximum?");
    cnst->concurrency_limit = concurrency_limit;
  }
  
@@@ -204,6 -225,7 +238,7 @@@ void lmm_constraint_concurrency_maximum
  
  int lmm_constraint_concurrency_maximum_get(lmm_constraint_t cnst)
  {
+  xbt_assert(cnst->concurrency_limit<0 || cnst->concurrency_maximum<=cnst->concurrency_limit,"Very bad: maximum observed concurrency is higher than limit. This is a bug of SURF, please report it.");
    return cnst->concurrency_maximum;
  }
  
@@@ -227,8 -249,7 +262,8 @@@ XBT_INLINE void lmm_constraint_free(lmm
                                      lmm_constraint_t cnst)
  {
    xbt_assert(!xbt_swag_size(&(cnst->active_element_set)),"Removing constraint but it still has active elements");
 -  xbt_assert(!xbt_swag_size(&(cnst->element_set)),"Removing constraint but it still has elements");
 +  xbt_assert(!xbt_swag_size(&(cnst->enabled_element_set)),"Removing constraint but it still has enabled elements");
 +  xbt_assert(!xbt_swag_size(&(cnst->disabled_element_set)),"Removing constraint but it still has disabled elements");
    remove_constraint(sys, cnst);
    lmm_cnst_free(sys, cnst);
  }
@@@ -261,10 -282,8 +296,10 @@@ lmm_variable_t lmm_variable_new(lmm_sys
    var->id_int = Global_debug_id++;
    var->cnsts = (s_lmm_element_t *) xbt_realloc(var->cnsts, number_of_constraints * sizeof(s_lmm_element_t));
    for (i = 0; i < number_of_constraints; i++) {
 -    var->cnsts[i].element_set_hookup.next = NULL;
 -    var->cnsts[i].element_set_hookup.prev = NULL;
 +    var->cnsts[i].enabled_element_set_hookup.next = NULL;
 +    var->cnsts[i].enabled_element_set_hookup.prev = NULL;
 +    var->cnsts[i].disabled_element_set_hookup.next = NULL;
 +    var->cnsts[i].disabled_element_set_hookup.prev = NULL;
      var->cnsts[i].active_element_set_hookup.next = NULL;
      var->cnsts[i].active_element_set_hookup.prev = NULL;
      var->cnsts[i].constraint = NULL;
@@@ -351,10 -370,10 +386,10 @@@ void lmm_shrink(lmm_system_t sys, lmm_c
     */
    lmm_update_modified_set(sys, cnst);
    //Useful in case var was already removed from the constraint
 -  lmm_update_modified_set(sys, var->cnsts[0].constraint); // will look up element_set of this constraint, and then each var in the element_set, and each var->cnsts[i].
 +  lmm_update_modified_set(sys, var->cnsts[0].constraint); // will look up enabled_element_set of this constraint, and then each var in the enabled_element_set, and each var->cnsts[i].
  
 -  if(xbt_swag_remove(elem, &(elem->constraint->element_set)) && var->weight>0)
 +  if(xbt_swag_remove(elem, &(elem->constraint->enabled_element_set)))
-     lmm_decrease_concurrency(elem->constraint);
+     lmm_decrease_concurrency(elem);
  
    xbt_swag_remove(elem, &(elem->constraint->active_element_set));
    elem->constraint = NULL;
    var->cnsts_number -= 1;
  
    //No variable in this constraint -> make it inactive
 -  if (xbt_swag_size(&(cnst->element_set)) == 0)
 +  if (xbt_swag_size(&(cnst->enabled_element_set))+xbt_swag_size(&(cnst->disabled_element_set)) == 0)
      make_constraint_inactive(sys, cnst);
    else {
      //Check maxconcurrency to see if we can enable new variables
@@@ -379,11 -398,11 +414,24 @@@ void lmm_expand(lmm_system_t sys, lmm_c
  {
    lmm_element_t elem = NULL;
    double weight;
--  int i;
++  int i,current_share;
++  
    
    sys->modified = 1;
  
--  if(var->weight>0 && lmm_concurrency_slack(cnst)==0){
++  //Check if this variable already has an active element in this constraint
++  //If it does, substract it from the required slack
++  current_share=0;
++  if(var->concurrency_share>1){
++    for( i=0; i<var->cnsts_number;i++){
++      if(var->cnsts[i].constraint==cnst && xbt_swag_belongs(&var->cnsts[i],&(var->cnsts[i].constraint->enabled_element_set)))
++      current_share+=lmm_element_concurrency(&(var->cnsts[i]));
++    }
++  }
++
++  //Check if we need to disable the variable 
++  if(var->weight>0 && var->concurrency_share-current_share>lmm_concurrency_slack(cnst))
++   {
      weight=var->weight;
      lmm_disable_var(sys,var);
      for (i = 0; i < var->cnsts_number; i++)
  
    
    if (var->weight){
 -    xbt_swag_insert_at_head(elem, &(elem->constraint->element_set));
 +    xbt_swag_insert_at_head(elem, &(elem->constraint->enabled_element_set));
-     lmm_increase_concurrency(elem->constraint);
+     lmm_increase_concurrency(elem);
    }
    else
 -    xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set));
 +    xbt_swag_insert_at_tail(elem, &(elem->constraint->disabled_element_set));
  
    if(!sys->selective_update_active) {
      make_constraint_active(sys, cnst);
  void lmm_expand_add(lmm_system_t sys, lmm_constraint_t cnst,
                      lmm_variable_t var, double value)
  {
--  int i;
++  int i,j;
++  double weight;
    sys->modified = 1;
--
++  
    lmm_check_concurrency(sys);
  
++  //BEWARE: In case you have multiple elements in one constraint, this will always
++  //add value to the first element.
    for (i = 0; i < var->cnsts_number; i++)
      if (var->cnsts[i].constraint == cnst)
        break;
  
    if (i < var->cnsts_number) {
++    if (var->weight)
++      lmm_decrease_concurrency(&var->cnsts[i]);
++
      if (cnst->sharing_policy)
        var->cnsts[i].value += value;
      else
        var->cnsts[i].value = MAX(var->cnsts[i].value, value);
++
++    //We need to check that increasing value of the element does not cross the concurrency limit
++    if (var->weight){
++      if(lmm_concurrency_slack(cnst)<lmm_element_concurrency(&var->cnsts[i])){
++      weight=var->weight;
++      lmm_disable_var(sys,var);
++      for (j = 0; j < var->cnsts_number; j++)
++        lmm_on_disabled_var(sys,var->cnsts[j].constraint);
++      var->staged_weight=weight;
++      xbt_assert(!var->weight);
++      }
++      lmm_increase_concurrency(&var->cnsts[i]);
++    }
++    
      lmm_update_modified_set(sys, cnst);
    } else
      lmm_expand(sys, cnst, var, value);
@@@ -476,23 -495,10 +544,23 @@@ lmm_variable_t lmm_get_var_from_cnst(lm
                                       lmm_constraint_t cnst,
                                       lmm_element_t * elem)
  {
 -  if (!(*elem))
 -    *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->element_set));
 -  else
 -    *elem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->element_set.offset);
 +  
 +  if (!(*elem)) {
 +    //That is the first call, pick the first element among enabled_element_set (or disabled_element_set if enabled_element_set is empty)
 +    *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->enabled_element_set));
 +    if (!(*elem))
 +      *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->disabled_element_set));
 +  }  else {
 +    //elem is not null, so we carry on
 +    if(xbt_swag_belongs(*elem,&(cnst->enabled_element_set))){
 +      //Look at enabled_element_set, and jump to disabled_element_set when finished
 +      *elem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->enabled_element_set.offset);
 +      if (!(*elem))
 +  *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->disabled_element_set));
 +    } else {
 +      *elem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->disabled_element_set.offset);      
 +    }
 +  }
    if (*elem)
      return (*elem)->variable;
    else
@@@ -508,10 -514,8 +576,10 @@@ lmm_variable_t lmm_get_var_from_cnst_sa
                                       int * numelem)
  {
    if (!(*elem)){
 -    *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->element_set));
 -    *numelem = xbt_swag_size(&(cnst->element_set))-1;
 +    *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->enabled_element_set));
 +    *numelem = xbt_swag_size(&(cnst->enabled_element_set))+xbt_swag_size(&(cnst->disabled_element_set))-1;
 +    if (!(*elem))
 +      *elem = (lmm_element_t) xbt_swag_getFirst(&(cnst->disabled_element_set));
    }else{
      *elem = *nextelem;
      if(*numelem>0){
        return NULL;
    }
    if (*elem){
 -    *nextelem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->element_set.offset);
 +    //elem is not null, so we carry on
 +    if(xbt_swag_belongs(*elem,&(cnst->enabled_element_set))){
 +      //Look at enabled_element_set, and jump to disabled_element_set when finished
 +      *nextelem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->enabled_element_set.offset);
 +      if (!(*nextelem))
 +  *nextelem = (lmm_element_t) xbt_swag_getFirst(&(cnst->disabled_element_set));
 +    } else {
 +      *nextelem = (lmm_element_t) xbt_swag_getNext(*elem, cnst->disabled_element_set.offset);      
 +    }
      return (*elem)->variable;
    }else
      return NULL;
@@@ -610,7 -606,7 +678,7 @@@ void lmm_print(lmm_system_t sys
        xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
    strcat(trace_buf, print_buf);
    xbt_swag_foreach(_var, var_list) {
 -      var = (lmm_variable_t)_var;
 +  var = (lmm_variable_t)_var;
      sprintf(print_buf, "'%d'(%f) ", var->id_int, var->weight);
      trace_buf = (char*)
          xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
    /* Printing Constraints */
    cnst_list = &(sys->active_constraint_set);
    xbt_swag_foreach(_cnst, cnst_list) {
 -      cnst = (lmm_constraint_t)_cnst;
 +  cnst = (lmm_constraint_t)_cnst;
      sum = 0.0;
 -    elem_list = &(cnst->element_set);
 +    //Show  the enabled variables
 +    elem_list = &(cnst->enabled_element_set);
      sprintf(print_buf, "\t");
      trace_buf = (char*)
          xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
                        strlen(trace_buf) + strlen(print_buf) + 1);
        strcat(trace_buf, print_buf);
        if(cnst->sharing_policy)
 -        sum += elem->value * elem->variable->value;
 +        sum += elem->value * elem->variable->value;
 +      else 
 +        sum = MAX(sum,elem->value * elem->variable->value);
 +    }
 +    //TODO: Adding disabled elements only for test compatibility, but do we really want them to be printed?
 +    elem_list = &(cnst->disabled_element_set);
 +    xbt_swag_foreach(_elem, elem_list) {
 +      elem = (lmm_element_t)_elem;
 +      sprintf(print_buf, "%f.'%d'(%f) %s ", elem->value,
 +              elem->variable->id_int, elem->variable->value,(cnst->sharing_policy)?"+":",");
 +      trace_buf = (char*)
 +          xbt_realloc(trace_buf,
 +                      strlen(trace_buf) + strlen(print_buf) + 1);
 +      strcat(trace_buf, print_buf);
 +      if(cnst->sharing_policy)
 +        sum += elem->value * elem->variable->value;
        else 
 -        sum = MAX(sum,elem->value * elem->variable->value);
 +        sum = MAX(sum,elem->value * elem->variable->value);
      }
 +    
      sprintf(print_buf, "0) <= %f ('%d')", cnst->bound, cnst->id_int);
      trace_buf = (char*)
          xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1);
    XBT_DEBUG("Variables");
    /* Printing Result */
    xbt_swag_foreach(_var, var_list) {
 -      var = (lmm_variable_t)_var;
 +  var = (lmm_variable_t)_var;
      if (var->bound > 0) {
        XBT_DEBUG("'%d'(%f) : %f (<=%f)", var->id_int, var->weight, var->value,
               var->bound);
@@@ -734,12 -713,13 +802,12 @@@ void lmm_solve(lmm_system_t sys
    XBT_DEBUG("Active constraints : %d", xbt_swag_size(cnst_list));
    /* Init: Only modified code portions: reset the value of active variables */
    xbt_swag_foreach(_cnst, cnst_list) {
 -      cnst = (lmm_constraint_t)_cnst;
 -    elem_list = &(cnst->element_set);
 +  cnst = (lmm_constraint_t)_cnst;
 +    elem_list = &(cnst->enabled_element_set);
      //XBT_DEBUG("Variable set : %d", xbt_swag_size(elem_list));
      xbt_swag_foreach(_elem, elem_list) {
        var = ((lmm_element_t)_elem)->variable;
 -      if (var->weight <= 0.0)
 -        break;
 +      xbt_assert(var->weight > 0.0);
        var->value = 0.0;
      }
    }
    saturated_constraint_set->data = xbt_new0(int, saturated_constraint_set->size);
  
    xbt_swag_foreach_safe(_cnst, _cnst_next, cnst_list) {
 -      cnst = (lmm_constraint_t)_cnst;
 +  cnst = (lmm_constraint_t)_cnst;
      /* INIT: Collect constraints that actually need to be saturated (i.e remaining  and usage are strictly positive) into cnst_light_tab. */
      cnst->remaining = cnst->bound;
      if (!double_positive(cnst->remaining, cnst->bound*sg_maxmin_precision))
        continue;
      cnst->usage = 0;
 -    elem_list = &(cnst->element_set);
 +    elem_list = &(cnst->enabled_element_set);
      xbt_swag_foreach(_elem, elem_list) {
        elem = (lmm_element_t)_elem;
 -      /* 0-weighted elements (ie, sleep actions) are at the end of the swag and we don't want to consider them */
 -      if (elem->variable->weight <= 0)
 -        break;
 +      xbt_assert(elem->variable->weight > 0);
        if ((elem->value > 0)) {
          if (cnst->sharing_policy)
            cnst->usage += elem->value / elem->variable->weight;
        int i;
  
        if (min_bound < 0) {
 -      //If no variable could reach its bound, deal iteratively the constraints usage ( at worst one constraint is saturated at each cycle) 
 +  //If no variable could reach its bound, deal iteratively the constraints usage ( at worst one constraint is saturated at each cycle) 
          var->value = min_usage / var->weight;
          XBT_DEBUG("Setting %p (%d) value to %f\n", var, var->id_int, var->value);
        } else {
 -      //If there exist a variable that can reach its bound, only update it (and other with the same bound) for now.
 -          if (double_equals(min_bound, var->bound*var->weight, sg_maxmin_precision)){
 +  //If there exist a variable that can reach its bound, only update it (and other with the same bound) for now.
 +      if (double_equals(min_bound, var->bound*var->weight, sg_maxmin_precision)){
            var->value = var->bound;
            XBT_DEBUG("Setting %p (%d) value to %f\n", var, var->id_int, var->value);
          }
          else {
 -        // Variables which bound is different are not considered for this cycle, but they will be afterwards.  
 +    // Variables which bound is different are not considered for this cycle, but they will be afterwards.  
            XBT_DEBUG("Do not consider %p (%d) \n", var, var->id_int);
            xbt_swag_remove(var, var_list);
            continue;
          elem = &var->cnsts[i];
          cnst = elem->constraint;
          if (cnst->sharing_policy) {
 -        //Remember: shared constraints require that sum(elem->value * var->value) < cnst->bound
 +    //Remember: shared constraints require that sum(elem->value * var->value) < cnst->bound
            double_update(&(cnst->remaining),  elem->value * var->value, cnst->bound*sg_maxmin_precision);
            double_update(&(cnst->usage), elem->value / var->weight, sg_maxmin_precision);
 -        //If the constraint is saturated, remove it from the set of active constraints (light_tab)
 +    //If the constraint is saturated, remove it from the set of active constraints (light_tab)
            if(!double_positive(cnst->usage,sg_maxmin_precision) || !double_positive(cnst->remaining,cnst->bound*sg_maxmin_precision)) {
              if (cnst->cnst_light) {
                int index = (cnst->cnst_light-cnst_light_tab);
                XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p usage: %f remaining: %f bound: %f  ",
 -                      index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab, cnst->usage, cnst->remaining, cnst->bound);
 +      index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab, cnst->usage, cnst->remaining, cnst->bound);
                cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1];
                cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index];
                cnst_light_num--;
            }
            make_elem_inactive(elem);
          } else {
 -        //Remember: non-shared constraints only require that max(elem->value * var->value) < cnst->bound
 +    //Remember: non-shared constraints only require that max(elem->value * var->value) < cnst->bound
            cnst->usage = 0.0;
            make_elem_inactive(elem);
 -          elem_list = &(cnst->element_set);
 +          elem_list = &(cnst->enabled_element_set);
            xbt_swag_foreach(_elem, elem_list) {
 -              elem = (lmm_element_t)_elem;
 -              if (elem->variable->weight <= 0) break; //Found an inactive variable -> no more active variables
 -            if (elem->variable->value > 0) continue;
 -            if (elem->value > 0)
 -              cnst->usage = MAX(cnst->usage, elem->value / elem->variable->weight);
 +      elem = (lmm_element_t)_elem;
 +      xbt_assert(elem->variable->weight > 0);
 +      if (elem->variable->value > 0) continue;
 +      if (elem->value > 0)
 +        cnst->usage = MAX(cnst->usage, elem->value / elem->variable->weight);
            }
 -        //If the constraint is saturated, remove it from the set of active constraints (light_tab)
 +    //If the constraint is saturated, remove it from the set of active constraints (light_tab)
            if(!double_positive(cnst->usage,sg_maxmin_precision) || !double_positive(cnst->remaining,cnst->bound*sg_maxmin_precision)) {
              if(cnst->cnst_light) {
                int index = (cnst->cnst_light-cnst_light_tab);
                XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p usage: %f remaining: %f bound: %f  ",
 -                      index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab, cnst->usage, cnst->remaining, cnst->bound);
 +      index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab, cnst->usage, cnst->remaining, cnst->bound);
                cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1];
                cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index];
                cnst_light_num--;
            pos,
            saturated_constraint_set,
            &min_usage);
 -      }
 +  }
  
      saturated_variable_set_update(  cnst_light_tab,
                                      saturated_constraint_set,
      lmm_print(sys);
    }
  
++  lmm_check_concurrency(sys);
++  
    xbt_free(saturated_constraint_set->data);
    xbt_free(saturated_constraint_set);
    xbt_free(cnst_light_tab);
@@@ -957,13 -939,28 +1027,11 @@@ void lmm_update_variable_bound(lmm_syst
  
  int lmm_concurrency_slack(lmm_constraint_t cnstr){
  
-   xbt_assert(xbt_swag_size(&(cnstr->enabled_element_set))==cnstr->concurrency_current,"concurrency_current is not up to date!");
 -  int slack;
 -  int concurrency=0;
 -  void* _elem;
 -  lmm_element_t elem;
--
    //FIXME MARTIN: Replace by infinite value std::numeric_limits<int>::(max)(), or something better within Simgrid?
    if(cnstr->concurrency_limit<0)
      return 666;
  
 -  if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
 -    xbt_swag_foreach(_elem, &(cnstr->element_set)) {
 -      elem = (lmm_element_t)_elem;
 -      concurrency+=lmm_element_concurrency(elem);
 -    }
 -      
 -    slack=cnstr->concurrency_limit-concurrency;
 -    xbt_assert(slack>=0,"concurrency slack should not be negative!");
 -    return slack;
 -  }
 -
 -  return  cnstr->concurrency_limit - cnstr->concurrency_current;
 -  
 +  return  cnstr->concurrency_limit - cnstr->concurrency_current;  
  }
  
  /** \brief Measure the minimum concurrency slack across all constraints where var is involved
@@@ -1018,14 -1015,14 +1086,16 @@@ void lmm_enable_var(lmm_system_t sys, l
    xbt_swag_insert_at_head(var, &(sys->variable_set));
    for (i = 0; i < var->cnsts_number; i++) {
      elem = &var->cnsts[i];
 -    xbt_swag_remove(elem, &(elem->constraint->element_set));
 -    xbt_swag_insert_at_head(elem, &(elem->constraint->element_set));
 +    xbt_swag_remove(elem, &(elem->constraint->disabled_element_set));
 +    xbt_swag_insert_at_head(elem, &(elem->constraint->enabled_element_set));
-     lmm_increase_concurrency(elem->constraint);
+     lmm_increase_concurrency(elem);
    }
    if (var->cnsts_number)
      lmm_update_modified_set(sys, var->cnsts[0].constraint);
  
--  lmm_check_concurrency(sys);
++  //When used within lmm_on_disabled_var, we would get an assertion fail, because transiently there can be variables that are staged and could be activated.
++  //Anyway, caller functions all call lmm_check_concurrency() in the end. 
++  //  lmm_check_concurrency(sys);
  }
  
  void lmm_disable_var(lmm_system_t sys, lmm_variable_t var){
      lmm_update_modified_set(sys, var->cnsts[0].constraint);
    for (i = 0; i < var->cnsts_number; i++) {
      elem = &var->cnsts[i];
 -    xbt_swag_remove(elem, &(elem->constraint->element_set));
 -    xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set));
 +    xbt_swag_remove(elem, &(elem->constraint->enabled_element_set));
 +    xbt_swag_insert_at_tail(elem, &(elem->constraint->disabled_element_set));
  
      xbt_swag_remove(elem, &(elem->constraint->active_element_set));
  
-     lmm_decrease_concurrency(elem->constraint);
+     lmm_decrease_concurrency(elem);
    }
  
    var->weight=0.0;
   * Assuming that the variable has already been removed from non-zero weights
   * Can we find a staged variable to add?
   * If yes, check that none of the constraints that this variable is involved in is at the limit of its concurrency
 - * And then add it to active variables
 + * And then add it to enabled variables
   */
  void lmm_on_disabled_var(lmm_system_t sys, lmm_constraint_t cnstr){
  
    lmm_element_t elem;
++  lmm_element_t nextelem;
++  int numelem;
++  
    if(cnstr->concurrency_limit<0)
      return;
--  
-   int concurrency=cnstr->concurrency_current;
-   xbt_swag_foreach(elem, &(cnstr->disabled_element_set)) {
 -  int concurrency=0;
 -  xbt_swag_foreach(elem, &(cnstr->element_set)) {
 -
 -    //active variables are checked to see if we already reached the maximum (SHOULD NOT HAPPEN BECAUSE WE SHOULD HAVE JUST DEACTIVATED ONE)
 -    if (elem->variable->weight > 0){
 -      concurrency+=lmm_element_concurrency(elem);
 -      xbt_assert(elem->variable->staged_weight==0.0,"Staged weight should have been reset");
 -    } else if (elem->variable->staged_weight>0 )
++
++  numelem=xbt_swag_size(&(cnstr->disabled_element_set));
++  if(!numelem)
++    return;
++
++  elem= (lmm_element_t) xbt_swag_getFirst(&(cnstr->disabled_element_set));
++
++  //Cannot use xbt_swag_foreach, because lmm_enable_var will modify disabled_element_set.. within the loop
++  while(numelem-- && elem ){
++
++    nextelem = (lmm_element_t) xbt_swag_getNext(elem, cnstr->disabled_element_set.offset);      
 +
 +    if (elem->variable->staged_weight>0 )
        {
-   //Found a staged variable
-   //TODOLATER: Add random timing function to model reservation protocol fuzziness? Then how to make sure that staged variables will eventually be called?
-   if(lmm_can_enable_var(elem->variable)){
-     lmm_enable_var(sys,elem->variable);
-     concurrency++;
-   }        
+       //Found a staged variable
+       //TODOLATER: Add random timing function to model reservation protocol fuzziness? Then how to make sure that staged variables will eventually be called?
+       if(lmm_can_enable_var(elem->variable)){
+         lmm_enable_var(sys,elem->variable);
 -        concurrency+=lmm_element_concurrency(elem);
 -      }             
++      }        
        }
  
--    xbt_assert(concurrency<=cnstr->concurrency_limit,"Concurrency overflow!");
--    if(concurrency==cnstr->concurrency_limit)
++    xbt_assert(cnstr->concurrency_current<=cnstr->concurrency_limit,"Concurrency overflow!");
++    if(cnstr->concurrency_current==cnstr->concurrency_limit)
        break;
++
++    elem = nextelem;
    }
  
--  lmm_check_concurrency(sys);
++  //We could get an assertion fail, because transiently there can be variables that are staged and could be activated.
++  //And we need to go through all constraints of the disabled var before getting back a coherent state.
++  //Anyway, caller functions all call lmm_check_concurrency() in the end. 
++  //  lmm_check_concurrency(sys);
  
  }
  
   * @return Returns whether a change was made
   */
  void lmm_update_variable_weight(lmm_system_t sys, lmm_variable_t var,
 -                             double weight)
 +             double weight)
  {
    int minslack;
    
    if (enabling_var){
      var->staged_weight = weight;
      minslack=lmm_cnstrs_min_concurrency_slack(var);
--    if(minslack==0){      
--      XBT_DEBUG("Staging var (instead of enabling) because min concurrency slack %i, with weight %f", minslack, weight);
++    if(minslack<var->concurrency_share){      
++      XBT_DEBUG("Staging var (instead of enabling) because min concurrency slack %i, with weight %f and concurrency share %i", minslack, weight, var->concurrency_share);
        return;
      }
      XBT_DEBUG("Enabling var with min concurrency slack %i", minslack);
@@@ -1166,7 -1167,7 +1251,7 @@@ XBT_INLINE lmm_constraint_t lmm_get_nex
  }
  
  #ifdef HAVE_LATENCY_BOUND_TRACKING
 -XBT_INLINE int lmm_is_variable_limited_by_latency(lmm_variable_t var)
 +XBT_PUBLIC(int) lmm_is_variable_limited_by_latency(lmm_variable_t var)
  {
    return (double_equals(var->bound, var->value, var->bound*sg_maxmin_precision));
  }
@@@ -1190,10 -1191,13 +1275,10 @@@ static void lmm_update_modified_set_rec
  
    //TODOLATER: Why lmm_modified_set has been changed in git version 2392B5157...? Looks equivalent logically and less obvious..
    
 -  xbt_swag_foreach(_elem, &cnst->element_set) {
 +  xbt_swag_foreach(_elem, &cnst->enabled_element_set) {
      lmm_variable_t var = ((lmm_element_t)_elem)->variable;
      s_lmm_element_t *cnsts = var->cnsts;
      int i;
 -    /* No need to update variables that are not active (because we made sure that also variables in the process of being disabled are still in the active element set of the original constraint given as argument) */
 -    if(var->weight<=0) 
 -      break;
      for (i = 0; var->visited != sys->visited_counter
               && i < var->cnsts_number ; i++) {
        if (cnsts[i].constraint != cnst
@@@ -1232,10 -1236,10 +1317,10 @@@ static void lmm_remove_all_modified_set
    //To be clean, when visited counter has wrapped around, we force these var->visited values so that variables that were in the modified a long (long long) time ago are not wrongly skipped here, which would lead to very nasty bugs (i.e. not readibily reproducible, and requiring a lot of run time before happening).  
    if (++sys->visited_counter == 1) {
      /* the counter wrapped around, reset each variable->visited */
 -      void *_var;
 +  void *_var;
      xbt_swag_foreach(_var, &sys->variable_set)
        ((lmm_variable_t)_var)->visited = 0;
--  }
++  } 
    xbt_swag_reset(&sys->modified_constraint_set);
  }
  
   */
  double lmm_constraint_get_usage(lmm_constraint_t cnst) {
     double usage = 0.0;
 -   xbt_swag_t elem_list = &(cnst->element_set);
 +   xbt_swag_t elem_list = &(cnst->enabled_element_set);
     void *_elem;
     lmm_element_t elem = NULL;
  
     xbt_swag_foreach(_elem, elem_list) {
 -       elem = (lmm_element_t)_elem;
 -     /* 0-weighted elements (ie, sleep actions) are at the end of the swag and we don't want to consider them */
 -     if (elem->variable->weight <= 0)
 -       break;
 +   elem = (lmm_element_t)_elem;
       if ((elem->value > 0)) {
         if (cnst->sharing_policy)
           usage += elem->value * elem->variable->value;
  void lmm_check_concurrency(lmm_system_t sys){
    void* _cnst;
    void* _elem;
++  void* _var;
    lmm_element_t elem;
    lmm_constraint_t cnst;
++  lmm_variable_t var;
    int concurrency;
--
++  int i,belong_to_enabled,belong_to_disabled,belong_to_active;
++  
    //These checks are very expensive, so do them only if we want to debug SURF LMM
    if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
    
      xbt_swag_foreach(_cnst, &(sys->constraint_set)) {
        cnst = (lmm_constraint_t) _cnst;
        concurrency=0;
-      
 -      if(cnst->concurrency_limit<0)
 -      continue;
 -      xbt_swag_foreach(_elem, &(cnst->element_set)) {
 +      xbt_swag_foreach(_elem, &(cnst->enabled_element_set)) {
-   elem = (lmm_element_t)_elem;
-   xbt_assert(elem->variable->weight > 0);
-     concurrency++;
+       elem = (lmm_element_t)_elem;
 -      if (elem->variable->weight > 0) 
 -        concurrency+=lmm_element_concurrency(elem);
 -      else {
 -        //We should have staged variables only if conccurency is reached in some constraint
 -        xbt_assert(cnst->concurrency_limit<0 || elem->variable->staged_weight==0 || lmm_cnstrs_min_concurrency_slack(elem->variable) < elem->variable->concurrency_share,"should not have staged variable!");
 -          }
++      xbt_assert(elem->variable->weight > 0);
++      concurrency+=lmm_element_concurrency(elem);
 +      }
++      
 +      xbt_swag_foreach(_elem, &(cnst->disabled_element_set)) {
 +  elem = (lmm_element_t)_elem;
-   //We should have staged variables only if conccurency is reached in some constraint
++  //We should have staged variables only if concurrency is reached in some constraint
 +  xbt_assert(cnst->concurrency_limit<0 || elem->variable->staged_weight==0 || lmm_cnstrs_min_concurrency_slack(elem->variable) < elem->variable->concurrency_share,"should not have staged variable!");
        }
 +      
        xbt_assert(cnst->concurrency_limit<0 || cnst->concurrency_limit >= concurrency,"concurrency check failed!");
        xbt_assert(cnst->concurrency_current == concurrency, "concurrency_current is out-of-date!");
-       xbt_assert(cnst->concurrency_current == xbt_swag_size(&(cnst->enabled_element_set)), "concurrency_current is out-of-date (2) !");
      }
  
++
++    //Check that for each variable, all corresponding elements are in the same state (i.e. same element sets)
++    xbt_swag_foreach(_var, &(sys->variable_set)) {
++      var= (lmm_variable_t) _var;
++
++      if(!var->cnsts_number)
++      continue;
++
++      elem = &var->cnsts[0];
++      belong_to_enabled=xbt_swag_belongs(elem,&(elem->constraint->enabled_element_set));
++      belong_to_disabled=xbt_swag_belongs(elem,&(elem->constraint->disabled_element_set));
++      belong_to_active=xbt_swag_belongs(elem,&(elem->constraint->active_element_set));
++
++      for (i = 1; i < var->cnsts_number; i++) {
++      elem = &var->cnsts[i];
++      xbt_assert(belong_to_enabled==xbt_swag_belongs(elem,&(elem->constraint->enabled_element_set)),
++                 "Variable inconsistency (1): enabled_element_set");
++      xbt_assert(belong_to_disabled==xbt_swag_belongs(elem,&(elem->constraint->disabled_element_set)),
++         "Variable inconsistency (2): disabled_element_set");
++      xbt_assert(belong_to_active==xbt_swag_belongs(elem,&(elem->constraint->active_element_set)),
++                 "Variable inconsistency (3): active_element_set");
++      }
++      
++    }
    }
  }
   * @brief LMM element
   * Elements can be seen as glue between constraint objects and variable objects.
   * Basically, each variable will have a set of elements, one for each constraint where it is involved.
 - * Then, it is used to list all variables involved in constraint through constraint's element_set lists, or vice-versa list all constraints for a given variable.  
 + * Then, it is used to list all variables involved in constraint through constraint's xxx_element_set lists, or vice-versa list all constraints for a given variable.  
   */
  typedef struct lmm_element {
    /* hookup to constraint */
 -  s_xbt_swag_hookup_t element_set_hookup;
 +  s_xbt_swag_hookup_t enabled_element_set_hookup;
 +  s_xbt_swag_hookup_t disabled_element_set_hookup;
    s_xbt_swag_hookup_t active_element_set_hookup;
  
    lmm_constraint_t constraint;
@@@ -45,6 -44,7 +45,6 @@@ typedef struct lmm_constraint_light 
   * \li Enabled elements which variable's weight is non-zero. They are utilized in some LMM functions.
   * \li Active elements which variable's weight is non-zero (i.e. it is enabled) AND its element value is non-zero. LMM_solve iterates over active elements during resolution, dynamically making them active or unactive. 
   * 
 - * Also note that we maintain element_set such that all enabled elements (i.e. var->weight>0) come before disabled elements.
   */
  typedef struct lmm_constraint {
    /* hookup to system */
@@@ -53,8 -53,9 +53,8 @@@
    s_xbt_swag_hookup_t modified_constraint_set_hookup;
    s_xbt_swag_hookup_t saturated_constraint_set_hookup;
  
 -  //TODO we could split element_set in, say, enabled_element_set and disabled_element_set depending on var->weight
 -  //Could make code more readable and should not pose implementation issues (only lmm_print does not stop at the end of enabled elements
 -  s_xbt_swag_t element_set;     /* a list of lmm_element_t */
 +  s_xbt_swag_t enabled_element_set;     /* a list of lmm_element_t */
 +  s_xbt_swag_t disabled_element_set;     /* a list of lmm_element_t */
    s_xbt_swag_t active_element_set;      /* a list of lmm_element_t */
    double remaining;
    double usage;
@@@ -140,7 -141,7 +140,7 @@@ typedef struct lmm_system 
   * 
   * @param sys A lmm system
   */
- XBT_PRIVATE void lmm_print(lmm_system_t sys);
//XBT_PRIVATE void lmm_print(lmm_system_t sys);
  
  extern XBT_PRIVATE double (*func_f_def) (lmm_variable_t, double);
  extern XBT_PRIVATE double (*func_fp_def) (lmm_variable_t, double);
@@@ -9,6 -9,7 +9,6 @@@
  #include "network_cm02.hpp"
  #include "maxmin_private.hpp"
  #include "simgrid/sg_config.h"
 -#include "src/surf/platform.hpp"
  
  XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_network);
  
@@@ -20,6 -21,23 +20,6 @@@ double sg_weight_S_parameter = 0.0
  double sg_tcp_gamma = 0.0;
  int sg_network_crosstraffic = 0;
  
 -/*************
 - * CallBacks *
 - *************/
 -
 -void net_define_callbacks(void)
 -{
 -  /* Figuring out the network links */
 -  simgrid::surf::on_link.connect(netlink_parse_init);
 -  simgrid::surf::on_postparse.connect([]() {
 -    surf_network_model->addTraces();
 -  });
 -}
 -
 -/*********
 - * Model *
 - *********/
 -
  /************************************************************************/
  /* New model based on optimizations discussed during Pedro Velho's thesis*/
  /************************************************************************/
@@@ -39,13 -57,16 +39,13 @@@ void surf_network_model_init_LegrandVel
    if (surf_network_model)
      return;
  
 +  simgrid::surf::on_link.connect(netlink_parse_init);
    surf_network_model = new simgrid::surf::NetworkCm02Model();
 -  net_define_callbacks();
 -  simgrid::surf::Model *model = surf_network_model;
 -  xbt_dynar_push(all_existing_models, &model);
 -
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",
 -                            13.01);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor",
 -                            0.97);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 20537);
 +  xbt_dynar_push(all_existing_models, &surf_network_model);
 +
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",      13.01);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor",     0.97);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S",         20537);
  }
  
  /***************************************************************************/
@@@ -65,13 -86,13 +65,13 @@@ void surf_network_model_init_CM02(void
    if (surf_network_model)
      return;
  
 +  simgrid::surf::on_link.connect(netlink_parse_init);
    surf_network_model = new simgrid::surf::NetworkCm02Model();
    xbt_dynar_push(all_existing_models, &surf_network_model);
 -  net_define_callbacks();
  
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 1.0);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",   1.0);
    xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", 1.0);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 0.0);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S",         0.0);
  }
  
  /***************************************************************************/
@@@ -89,16 -110,15 +89,16 @@@ void surf_network_model_init_Reno(void
    if (surf_network_model)
      return;
  
 +  simgrid::surf::on_link.connect(netlink_parse_init);
    surf_network_model = new simgrid::surf::NetworkCm02Model();
    xbt_dynar_push(all_existing_models, &surf_network_model);
 -  net_define_callbacks();
 +
    lmm_set_default_protocol_function(func_reno_f, func_reno_fp, func_reno_fpi);
    surf_network_model->f_networkSolve = lagrange_solve;
  
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", 0.92);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",     10.4);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor",    0.92);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S",         8775);
  }
  
  
@@@ -107,16 -127,15 +107,16 @@@ void surf_network_model_init_Reno2(void
    if (surf_network_model)
      return;
  
 +  simgrid::surf::on_link.connect(netlink_parse_init);
    surf_network_model = new simgrid::surf::NetworkCm02Model();
    xbt_dynar_push(all_existing_models, &surf_network_model);
 -  net_define_callbacks();
 +
    lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp, func_reno2_fpi);
    surf_network_model->f_networkSolve = lagrange_solve;
  
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", 0.92);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",    10.4);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor",   0.92);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S",        8775);
  }
  
  void surf_network_model_init_Vegas(void)
    if (surf_network_model)
      return;
  
 +  simgrid::surf::on_link.connect(netlink_parse_init);
    surf_network_model = new simgrid::surf::NetworkCm02Model();
    xbt_dynar_push(all_existing_models, &surf_network_model);
 -  net_define_callbacks();
 +
    lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp, func_vegas_fpi);
    surf_network_model->f_networkSolve = lagrange_solve;
  
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", 0.92);
 -  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor",    10.4);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor",   0.92);
 +  xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S",        8775);
  }
  
  namespace simgrid {
  namespace surf {
  
  NetworkCm02Model::NetworkCm02Model()
 -      :NetworkModel()
 +  :NetworkModel()
  {
    char *optim = xbt_cfg_get_string(_sg_cfg_set, "network/optim");
 -  int select =
 -      xbt_cfg_get_boolean(_sg_cfg_set, "network/maxmin_selective_update");
 +  int select = xbt_cfg_get_boolean(_sg_cfg_set, "network/maxmin_selective_update");
  
    if (!strcmp(optim, "Full")) {
      p_updateMechanism = UM_FULL;
    } else if (!strcmp(optim, "Lazy")) {
      p_updateMechanism = UM_LAZY;
      m_selectiveUpdate = 1;
 -    xbt_assert((select == 1)
 -               ||
 -               (xbt_cfg_is_default_value
 -                (_sg_cfg_set, "network/maxmin_selective_update")),
 +    xbt_assert((select == 1) || (xbt_cfg_is_default_value(_sg_cfg_set, "network/maxmin_selective_update")),
                 "Disabling selective update while using the lazy update mechanism is dumb!");
    } else {
      xbt_die("Unsupported optimization (%s) for this model", optim);
    }
  
    if (!p_maxminSystem)
 -      p_maxminSystem = lmm_system_new(m_selectiveUpdate);
 +    p_maxminSystem = lmm_system_new(m_selectiveUpdate);
  
    routing_model_create(createLink("__loopback__",
 -                                    498000000, NULL, 0.000015, NULL,
 -                                    1 /*SURF_RESOURCE_ON*/, NULL,
 -                                    SURF_LINK_FATPIPE, NULL));
 +                                498000000, NULL, 0.000015, NULL,
 +                                1 /*SURF_RESOURCE_ON*/, NULL,
 +                                SURF_LINK_FATPIPE, NULL));
  
    if (p_updateMechanism == UM_LAZY) {
 -      p_actionHeap = xbt_heap_new(8, NULL);
 -      xbt_heap_set_update_callback(p_actionHeap, surf_action_lmm_update_index_heap);
 -      p_modifiedSet = new ActionLmmList();
 -      p_maxminSystem->keep_track = p_modifiedSet;
 +  p_actionHeap = xbt_heap_new(8, NULL);
 +  xbt_heap_set_update_callback(p_actionHeap, surf_action_lmm_update_index_heap);
 +  p_modifiedSet = new ActionLmmList();
 +  p_maxminSystem->keep_track = p_modifiedSet;
    }
  }
  
  Link* NetworkCm02Model::createLink(const char *name,
 -                                 double bw_initial,
 -                                 tmgr_trace_t bw_trace,
 -                                 double lat_initial,
 -                                 tmgr_trace_t lat_trace,
 -                                 int initiallyOn,
 -                                 tmgr_trace_t state_trace,
 -                                 e_surf_link_sharing_policy_t policy,
 -                                 xbt_dict_t properties)
 +    double bw_initial, tmgr_trace_t bw_trace,
 +    double lat_initial, tmgr_trace_t lat_trace,
 +    int initiallyOn, tmgr_trace_t state_trace,
 +    e_surf_link_sharing_policy_t policy, xbt_dict_t properties)
  {
    xbt_assert(NULL == Link::byName(name),
               "Link '%s' declared several times in the platform",
               name);
  
 -  Link* link = new NetworkCm02Link(this, name, properties, p_maxminSystem, sg_bandwidth_factor * bw_initial, future_evt_set,
 -                                           initiallyOn, state_trace, bw_initial, bw_trace, lat_initial, lat_trace, policy);
 +  Link* link = new NetworkCm02Link(this, name, properties, p_maxminSystem, sg_bandwidth_factor * bw_initial,
 +                     initiallyOn, state_trace, bw_initial, bw_trace, lat_initial, lat_trace, policy);
    Link::onCreation(link);
    return link;
  }
@@@ -198,9 -224,11 +198,9 @@@ void NetworkCm02Model::updateActionsSta
      XBT_DEBUG("Something happened to action %p", action);
      if (TRACE_is_enabled()) {
        int n = lmm_get_number_of_cnst_from_var(p_maxminSystem, action->getVariable());
 -      int i;
 -      for (i = 0; i < n; i++){
 -        lmm_constraint_t constraint = lmm_get_cnst_from_var(p_maxminSystem,
 -                                                            action->getVariable(),
 -                                                            i);
 +
 +      for (int i = 0; i < n; i++){
 +        lmm_constraint_t constraint = lmm_get_cnst_from_var(p_maxminSystem, action->getVariable(), i);
          NetworkCm02Link *link = static_cast<NetworkCm02Link*>(lmm_constraint_id(constraint));
          TRACE_surf_link_set_utilization(link->getName(),
                                          action->getCategory(),
@@@ -245,7 -273,7 +245,7 @@@ void NetworkCm02Model::updateActionsSta
  
    for(ActionList::iterator it(running_actions->begin()), itNext=it, itend(running_actions->end())
       ; it != itend ; it=itNext) {
 -      ++itNext;
 +  ++itNext;
  
      action = static_cast<NetworkCm02Action*> (&*it);
      XBT_DEBUG("Something happened to action %p", action);
        }
        if (TRACE_is_enabled()) {
          int n = lmm_get_number_of_cnst_from_var(p_maxminSystem, action->getVariable());
 -        int i;
 -        for (i = 0; i < n; i++){
 -          lmm_constraint_t constraint = lmm_get_cnst_from_var(p_maxminSystem,
 -                                                            action->getVariable(),
 -                                                            i);
 +        for (int i = 0; i < n; i++){
 +          lmm_constraint_t constraint = lmm_get_cnst_from_var(p_maxminSystem, action->getVariable(), i);
 +
            NetworkCm02Link* link = static_cast<NetworkCm02Link*>(lmm_constraint_id(constraint));
            TRACE_surf_link_set_utilization(link->getName(),
                                          action->getCategory(),
                                          now - action->getLastUpdate());
          }
        }
 -      if (!lmm_get_number_of_cnst_from_var
 -          (p_maxminSystem, action->getVariable())) {
 +      if (!lmm_get_number_of_cnst_from_var (p_maxminSystem, action->getVariable())) {
          /* There is actually no link used, hence an infinite bandwidth.
           * This happens often when using models like vivaldi.
           * In such case, just make sure that the action completes immediately.
        action->gapRemove();
      }
    }
 -  return;
  }
  
  Action *NetworkCm02Model::communicate(NetCard *src, NetCard *dst,
  
    xbt_dynar_t route = xbt_dynar_new(sizeof(NetCard*), NULL);
  
 -  XBT_IN("(%s,%s,%g,%g)", src->getName(), dst->getName(), size, rate);
 +  XBT_IN("(%s,%s,%g,%g)", src->name(), dst->name(), size, rate);
  
    routing_platf->getRouteAndLatency(src, dst, &route, &latency);
    xbt_assert(!xbt_dynar_is_empty(route) || latency,
               "You're trying to send data from %s to %s but there is no connecting path between these two hosts.",
 -             src->getName(), dst->getName());
 +             src->name(), dst->name());
  
    xbt_dynar_foreach(route, i, _link) {
 -      link = static_cast<NetworkCm02Link*>(_link);
 +  link = static_cast<NetworkCm02Link*>(_link);
      if (link->isOff()) {
        failed = 1;
        break;
      }
    }
    if (sg_network_crosstraffic == 1) {
 -        routing_platf->getRouteAndLatency(dst, src, &back_route, NULL);
 +    routing_platf->getRouteAndLatency(dst, src, &back_route, NULL);
      xbt_dynar_foreach(back_route, i, _link) {
        link = static_cast<NetworkCm02Link*>(_link);
        if (link->isOff()) {
      }
    }
    xbt_dynar_foreach(route, i, _link) {
 -      link = static_cast<NetworkCm02Link*>(_link);
 +    link = static_cast<NetworkCm02Link*>(_link);
      double bb = bandwidthFactor(size) * link->getBandwidth();
      bandwidth_bound =
          (bandwidth_bound < 0.0) ? bb : std::min(bandwidth_bound, bb);
      link = *static_cast<NetworkCm02Link **>(xbt_dynar_get_ptr(route, 0));
      gapAppend(size, link, action);
      XBT_DEBUG("Comm %p: %s -> %s gap=%f (lat=%f)",
 -              action, src->getName(), dst->getName(), action->m_senderGap,
 +              action, src->name(), dst->name(), action->m_senderGap,
                action->m_latency);
    }
  
    }
  
    xbt_dynar_foreach(route, i, _link) {
 -      link = static_cast<NetworkCm02Link*>(_link);
 +    link = static_cast<NetworkCm02Link*>(_link);
      lmm_expand(p_maxminSystem, link->getConstraint(), action->getVariable(), 1.0);
    }
  
        link = static_cast<NetworkCm02Link*>(_link);
        lmm_expand(p_maxminSystem, link->getConstraint(), action->getVariable(), .05);
      }
--    lmm_variable_concurrency_share_set(action->getVariable(),2);
++    //Change concurrency_share here, if you want that cross-traffic is included in the SURF concurrency
++    //(You would also have to change lmm_element_concurrency())
++    //lmm_variable_concurrency_share_set(action->getVariable(),2);
    }
  
    xbt_dynar_free(&route);
    return action;
  }
  
 -void NetworkCm02Model::addTraces(){
 -  xbt_dict_cursor_t cursor = NULL;
 -  char *trace_name, *elm;
 -
 -  static int called = 0;
 -  if (called)
 -    return;
 -  called = 1;
 -
 -  /* connect all traces relative to network */
 -  xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
 -    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 -    NetworkCm02Link *link = static_cast<NetworkCm02Link*>( Link::byName(elm) );
 -
 -    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
 -               trace_name, elm);
 -    xbt_assert(trace,
 -               "Cannot connect trace %s to link %s: trace undefined",
 -               trace_name, elm);
 -
 -    link->p_stateEvent = future_evt_set->add_trace(trace, 0.0, link);
 -  }
 -
 -  xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
 -    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 -    NetworkCm02Link *link = static_cast<NetworkCm02Link*>( Link::byName(elm) );
 -
 -    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
 -               trace_name, elm);
 -    xbt_assert(trace,
 -               "Cannot connect trace %s to link %s: trace undefined",
 -               trace_name, elm);
 -
 -    link->p_speed.event = future_evt_set->add_trace(trace, 0.0, link);
 -  }
 -
 -  xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
 -    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 -    NetworkCm02Link *link = static_cast<NetworkCm02Link*>(Link::byName(elm));;
 -
 -    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
 -               trace_name, elm);
 -    xbt_assert(trace,
 -               "Cannot connect trace %s to link %s: trace undefined",
 -               trace_name, elm);
 -
 -    link->p_latEvent = future_evt_set->add_trace(trace, 0.0, link);
 -  }
 -}
 -
  /************
   * Resource *
   ************/
  NetworkCm02Link::NetworkCm02Link(NetworkCm02Model *model, const char *name, xbt_dict_t props,
 -                                 lmm_system_t system,
 -                                 double constraint_value,
 -                                 sg_future_evt_set_t fes,
 -                                 int initiallyOn,
 -                                 tmgr_trace_t state_trace,
 -                                 double metric_peak,
 -                                 tmgr_trace_t metric_trace,
 -                                 double lat_initial,
 -                                 tmgr_trace_t lat_trace,
 -                                 e_surf_link_sharing_policy_t policy)
 -: Link(model, name, props, lmm_constraint_new(system, this, constraint_value), fes, state_trace)
 +    lmm_system_t system,
 +    double constraint_value,
 +    int initiallyOn, tmgr_trace_t state_trace,
 +    double bw_peak, tmgr_trace_t bw_trace,
 +    double lat_initial, tmgr_trace_t lat_trace,
 +    e_surf_link_sharing_policy_t policy)
 +: Link(model, name, props, lmm_constraint_new(system, this, constraint_value), state_trace)
  {
    if (initiallyOn)
      turnOn();
    else
      turnOff();
  
 -  p_speed.scale = 1.0;
 -  p_speed.peak = metric_peak;
 -  if (metric_trace)
 -    p_speed.event = fes->add_trace(metric_trace, 0.0, this);
 +  m_bandwidth.scale = 1.0;
 +  m_bandwidth.peak = bw_peak;
 +  if (bw_trace)
 +    m_bandwidth.event = future_evt_set->add_trace(bw_trace, 0.0, this);
    else
 -    p_speed.event = NULL;
 +    m_bandwidth.event = NULL;
  
 -  m_latCurrent = lat_initial;
 +  m_latency.scale = 1.0;
 +  m_latency.peak = lat_initial;
    if (lat_trace)
 -      p_latEvent = fes->add_trace(lat_trace, 0.0, this);
 +    m_latency.event = future_evt_set->add_trace(lat_trace, 0.0, this);
  
    if (policy == SURF_LINK_FATPIPE)
 -      lmm_constraint_shared(getConstraint());
 +    lmm_constraint_shared(getConstraint());
  }
  
  
  
 -void NetworkCm02Link::updateState(tmgr_trace_iterator_t triggered,
 -                                      double value, double date)
 +void NetworkCm02Link::apply_event(tmgr_trace_iterator_t triggered, double value)
  {
  
    /* Find out which of my iterators was triggered, and react accordingly */
 -  if (triggered == p_speed.event) {
 -    updateBandwidth(value, date);
 -    tmgr_trace_event_unref(&p_speed.event);
 -  } else if (triggered == p_latEvent) {
 -    updateLatency(value, date);
 -    tmgr_trace_event_unref(&p_latEvent);
 -  } else if (triggered == p_stateEvent) {
 +  if (triggered == m_bandwidth.event) {
 +    updateBandwidth(value);
 +    tmgr_trace_event_unref(&m_bandwidth.event);
 +
 +  } else if (triggered == m_latency.event) {
 +    updateLatency(value);
 +    tmgr_trace_event_unref(&m_latency.event);
 +
 +  } else if (triggered == m_stateEvent) {
      if (value > 0)
        turnOn();
      else {
        lmm_variable_t var = NULL;
        lmm_element_t elem = NULL;
 +      double now = surf_get_clock();
  
        turnOff();
        while ((var = lmm_get_var_from_cnst(getModel()->getMaxminSystem(), getConstraint(), &elem))) {
  
          if (action->getState() == SURF_ACTION_RUNNING ||
              action->getState() == SURF_ACTION_READY) {
 -          action->setFinishTime(date);
 +          action->setFinishTime(now);
            action->setState(SURF_ACTION_FAILED);
          }
        }
      }
 -    tmgr_trace_event_unref(&p_stateEvent);
 +    tmgr_trace_event_unref(&m_stateEvent);
    } else {
      xbt_die("Unknown event!\n");
    }
  
 -  XBT_DEBUG
 -      ("There was a resource state event, need to update actions related to the constraint (%p)",
 +  XBT_DEBUG("There was a resource state event, need to update actions related to the constraint (%p)",
         getConstraint());
  }
  
 -void NetworkCm02Link::updateBandwidth(double value, double date){
 -  double delta = sg_weight_S_parameter / value - sg_weight_S_parameter /
 -                 (p_speed.peak * p_speed.scale);
 -  lmm_variable_t var = NULL;
 -  lmm_element_t elem = NULL;
 -  lmm_element_t nextelem = NULL;
 -  int numelem = 0;
 +void NetworkCm02Link::updateBandwidth(double value) {
  
 -  NetworkCm02Action *action = NULL;
 +  m_bandwidth.peak = value;
 +
 +  lmm_update_constraint_bound(getModel()->getMaxminSystem(), getConstraint(),
 +      sg_bandwidth_factor * (m_bandwidth.peak * m_bandwidth.scale));
 +  TRACE_surf_link_set_bandwidth(surf_get_clock(), getName(), sg_bandwidth_factor * m_bandwidth.peak * m_bandwidth.scale);
  
 -  p_speed.peak = value;
 -  lmm_update_constraint_bound(getModel()->getMaxminSystem(),
 -                              getConstraint(),
 -                              sg_bandwidth_factor *
 -                              (p_speed.peak * p_speed.scale));
 -  TRACE_surf_link_set_bandwidth(date, getName(), sg_bandwidth_factor * p_speed.peak * p_speed.scale);
    if (sg_weight_S_parameter > 0) {
 +    double delta = sg_weight_S_parameter / value - sg_weight_S_parameter / (m_bandwidth.peak * m_bandwidth.scale);
 +
 +    lmm_variable_t var;
 +    lmm_element_t elem = NULL, nextelem = NULL;
 +    int numelem = 0;
      while ((var = lmm_get_var_from_cnst_safe(getModel()->getMaxminSystem(), getConstraint(), &elem, &nextelem, &numelem))) {
 -      action = (NetworkCm02Action*) lmm_variable_id(var);
 +      NetworkCm02Action *action = (NetworkCm02Action*) lmm_variable_id(var);
        action->m_weight += delta;
        if (!action->isSuspended())
          lmm_update_variable_weight(getModel()->getMaxminSystem(), action->getVariable(), action->m_weight);
    }
  }
  
 -void NetworkCm02Link::updateLatency(double value, double date){
 -  double delta = value - m_latCurrent;
 +void NetworkCm02Link::updateLatency(double value){
 +  double delta = value - m_latency.peak;
    lmm_variable_t var = NULL;
    lmm_element_t elem = NULL;
    lmm_element_t nextelem = NULL;
    int numelem = 0;
 -  NetworkCm02Action *action = NULL;
  
 -  m_latCurrent = value;
 +  m_latency.peak = value;
 +
    while ((var = lmm_get_var_from_cnst_safe(getModel()->getMaxminSystem(), getConstraint(), &elem, &nextelem, &numelem))) {
 -    action = (NetworkCm02Action*) lmm_variable_id(var);
 +    NetworkCm02Action *action = (NetworkCm02Action*) lmm_variable_id(var);
      action->m_latCurrent += delta;
      action->m_weight += delta;
      if (action->m_rate < 0)
        if (action->m_rate < sg_tcp_gamma / (2.0 * action->m_latCurrent)) {
          XBT_INFO("Flow is limited BYBANDWIDTH");
        } else {
 -        XBT_INFO("Flow is limited BYLATENCY, latency of flow is %f",
 -                 action->m_latCurrent);
 +        XBT_INFO("Flow is limited BYLATENCY, latency of flow is %f", action->m_latCurrent);
        }
      }
      if (!action->isSuspended())
@@@ -28,33 -28,44 +28,47 @@@ int int_random(int max
    return (int) (((max * 1.0) * rand()) / (RAND_MAX + 1.0));
  }
  
- void test(int nb_cnst, int nb_var, int nb_elem);
- void test(int nb_cnst, int nb_var, int nb_elem)
 -void test(int nb_cnst, int nb_var, int nb_elem, int pw_base_limit, int pw_max_limit, float rate_no_limit, int max_share);
 -void test(int nb_cnst, int nb_var, int nb_elem, int pw_base_limit, int pw_max_limit, float rate_no_limit, int max_share)
++void test(int nb_cnst, int nb_var, int nb_elem, int pw_base_limit, int pw_max_limit, float rate_no_limit, int max_share, int testmode);
++void test(int nb_cnst, int nb_var, int nb_elem, int pw_base_limit, int pw_max_limit, float rate_no_limit, int max_share, int testmode)
  {
    lmm_system_t Sys = NULL;
    lmm_constraint_t *cnst = xbt_new0(lmm_constraint_t, nb_cnst);
    lmm_variable_t *var = xbt_new0(lmm_variable_t, nb_var);
    int *used = xbt_new0(int, nb_cnst);
-   int i, j, k;
+   int i, j, k,l;
++  int concurrency_share;
+   
    Sys = lmm_system_new(1);
  
    for (i = 0; i < nb_cnst; i++) {
      cnst[i] = lmm_constraint_new(Sys, NULL, float_random(10.0));
+     if(rate_no_limit>float_random(1.0))
+       //Look at what happens when there is no concurrency limit 
+       l=-1;
+     else
+       //Badly logarithmically random concurrency limit in [2^pw_base_limit+1,2^pw_base_limit+2^pw_max_limit]
+       l=(1<<pw_base_limit)+(1<<int_random(pw_max_limit));
+  
+     lmm_constraint_concurrency_limit_set(cnst[i],l );
    }
+   
    for (i = 0; i < nb_var; i++) {
      var[i] = lmm_variable_new(Sys, NULL, 1.0, -1.0, nb_elem);
 -    lmm_variable_concurrency_share_set(var[i],1+int_random(max_share));
+     //Have a few variables with a concurrency share of two (e.g. cross-traffic in some cases)
++    concurrency_share=1+int_random(max_share);
++    lmm_variable_concurrency_share_set(var[i],concurrency_share);
+       
      for (j = 0; j < nb_cnst; j++)
        used[j] = 0;
      for (j = 0; j < nb_elem; j++) {
        k = int_random(nb_cnst);
--      if (used[k]) {
++      if (used[k]>=concurrency_share) {
          j--;
          continue;
        }
--      lmm_expand(Sys, cnst[k], var[i], float_random(1.0));
--      used[k] = 1;
++      lmm_expand(Sys, cnst[k], var[i], float_random(1.5));
++      lmm_expand_add(Sys, cnst[k], var[i], float_random(1.5));
++      used[k]++;
      }
    }
  
    lmm_solve(Sys);
    date = xbt_os_time() * 1000000 - date;
  
 -  printf("Max concurrency:\n");
 -  l=0;
 -  for (i = 0; i < nb_cnst; i++) {
 -    j=lmm_constraint_concurrency_maximum_get(cnst[i]);
 -    k=lmm_constraint_concurrency_limit_get(cnst[i]);
 -    xbt_assert(k<0 || j<=k);
 -    if(j>l)
 -      l=j;
 -    printf("(%i):%i/%i ",i,j,k);
 -    lmm_constraint_concurrency_maximum_reset(cnst[i]);
 -    xbt_assert(!lmm_constraint_concurrency_maximum_get(cnst[i]));
 -    if(i%10==9)
 -       printf("\n");    
 -  }
 -  printf("\nTotal maximum concurrency is %i\n",l);
++  if(testmode){
++    printf("Max concurrency:\n");
++    l=0;
++    for (i = 0; i < nb_cnst; i++) {
++      j=lmm_constraint_concurrency_maximum_get(cnst[i]);
++      k=lmm_constraint_concurrency_limit_get(cnst[i]);
++      xbt_assert(k<0 || j<=k);
++      if(j>l)
++      l=j;
++      printf("(%i):%i/%i ",i,j,k);
++      lmm_constraint_concurrency_maximum_reset(cnst[i]);
++      xbt_assert(!lmm_constraint_concurrency_maximum_get(cnst[i]));
++      if(i%10==9)
++      printf("\n");    
++    }
++    printf("\nTotal maximum concurrency is %i\n",l);
 -  lmm_print(Sys);
++    lmm_print(Sys);
++  }
+   
    for (i = 0; i < nb_var; i++)
      lmm_variable_free(Sys, var[i]);
    lmm_system_free(Sys);
    free(cnst);
    free(var);
    free(used);
+   
  }
  
++int TestClasses [][4]=
++  //Nbcnst Nbvar Baselimit Maxlimit 
++  {{  10  ,10    ,1        ,2 }, //small
++   {  100 ,100   ,3        ,6 }, //medium
++   {  2000,2000  ,5        ,8 }, //big
++   { 20000,20000 ,7        ,10}  //huge
++  }; 
++
  int main(int argc, char **argv)
  {
--  int nb_cnst = 2000;
--  int nb_var = 2000;
-   int nb_elem = 80;
 -  int nb_elem; 
 -  int pw_base_limit=5; 
 -  int pw_max_limit=8;
++  int nb_cnst, nb_var,nb_elem,pw_base_limit,pw_max_limit,max_share;
+   float rate_no_limit=0.2;
 -  int max_share=1<<(pw_base_limit/2+1);
++  float acc_date=0,acc_date2=0;
++  int testclass,testmode,testcount;
++  int i;
++  
++  if(argc<3) {
++    printf("Syntax: <small|medium|big|huge> <count> [test]\n");
++    return -1;
++  }
++
++  //what class?
++  if(!strcmp(argv[1],"small"))
++      testclass=0;
++  else if(!strcmp(argv[1],"medium"))
++      testclass=1;
++  else if(!strcmp(argv[1],"big"))
++      testclass=2;
++  else if(!strcmp(argv[1],"huge"))
++      testclass=3;
++  else {
++    printf("Unknown class \"%s\", aborting!\n",argv[1]);
++    return -2;
++  }
++
++  //How many times?
++  testcount=atoi(argv[2]);
+   
++  //Show me everything!
++  testmode=(argc>=4 && strcmp(argv[3],"test")==0);
++
++  if(testmode)
++    xbt_log_control_set("surf/maxmin.threshold:DEBUG surf.threshold:DEBUG");
++
++  nb_cnst= TestClasses[testclass][0];
++  nb_var= TestClasses[testclass][1];
++  pw_base_limit= TestClasses[testclass][2];
++  pw_max_limit= TestClasses[testclass][3];
++  max_share=2; //1<<(pw_base_limit/2+1);
++
+   //If you want to test concurrency, you need nb_elem >> 2^pw_base_limit:
+   nb_elem= (1<<pw_base_limit)+(1<<(8*pw_max_limit/10));
+   //Otherwise, just set it to a constant value (and set rate_no_limit to 1.0):
+   //nb_elem=200
 -  
++
    xbt_init(&argc, argv);
--  date = xbt_os_time() * 1000000;
-   test(nb_cnst, nb_var, nb_elem);
 -  test(nb_cnst, nb_var, nb_elem, pw_base_limit, pw_max_limit, rate_no_limit,max_share);    
--  printf("One shot execution time for a total of %d constraints, "
-          "%d variables with %d active constraint each : %g microsecondes \n",
 -         "%d variables with %d active constraint each : %g microseconds \n",
--         nb_cnst, nb_var, nb_elem, date);
++  
++  for(i=0;i<testcount;i++){
++    test(nb_cnst, nb_var, nb_elem, pw_base_limit, pw_max_limit, rate_no_limit,max_share,testmode);
++    acc_date+=date;
++    acc_date2+=date*date;
++  }
++
++  float mean_date= acc_date/(float)testcount;  
++  float stdev_date= sqrt(acc_date2/(float)testcount-mean_date*mean_date);
++    
++  printf("%ix One shot execution time for a total of %d constraints, "
++         "%d variables with %d active constraint each, concurrency in [%i,%i] and max concurrency share %i: %g +- %g  microseconds \n",
++       testcount,nb_cnst, nb_var, nb_elem, (1<<pw_base_limit), (1<<pw_base_limit)+(1<<pw_max_limit), max_share, mean_date, stdev_date);
    return 0;
  }