Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Removing bugs and changing verbosity.
[simgrid.git] / src / surf / maxmin.c
index bdee4b2..b91599c 100644 (file)
@@ -11,6 +11,7 @@
 #include "xbt/mallocator.h"
 #include "maxmin_private.h"
 #include <stdlib.h>
+#include <math.h>
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_maxmin, surf,
                                "Logging specific to SURF (maxmin)");
 
@@ -86,7 +87,6 @@ static void lmm_var_free(lmm_system_t sys, lmm_variable_t var)
 {
 
   lmm_variable_disable(sys, var);
-  memset(var->cnsts,0,var->cnsts_size*sizeof(s_lmm_element_t));
   free(var->cnsts);
   xbt_mallocator_release(sys->variable_mallocator, var);
 }
@@ -174,6 +174,13 @@ lmm_variable_t lmm_variable_new(lmm_system_t sys, void *id,
   var->weight = weight;
   var->bound = bound;
   var->value = 0.0;
+  var->df    = 0.0;
+
+  var->func_f    = func_f_def;
+  var->func_fp   = func_fp_def;
+  var->func_fpi  = func_fpi_def;
+  var->func_fpip = func_fpip_def;
+
   if(weight) xbt_swag_insert_at_head(var,&(sys->variable_set));
   else xbt_swag_insert_at_tail(var,&(sys->variable_set));
   XBT_OUT;
@@ -325,7 +332,8 @@ static void saturated_variable_set_update(lmm_system_t sys)
   }
 }
 
-static void lmm_print(lmm_system_t sys)
+void lmm_print(lmm_system_t sys)
+
 {
   lmm_constraint_t cnst = NULL;
   lmm_element_t elem = NULL;
@@ -363,7 +371,7 @@ static void lmm_print(lmm_system_t sys)
     strcat(trace_buf, print_buf);
     xbt_swag_foreach(elem, elem_list) {
       sprintf(print_buf,"%f.'%p'(%f) + ",elem->value, 
-             elem->variable,elem->variable->weight);
+             elem->variable,elem->variable->value);
       trace_buf = xbt_realloc(trace_buf,strlen(trace_buf)+strlen(print_buf)+1);
       strcat(trace_buf, print_buf);
       sum += elem->value * elem->variable->value;
@@ -371,17 +379,23 @@ static void lmm_print(lmm_system_t sys)
     sprintf(print_buf,"0 <= %f ('%p')",cnst->bound,cnst);
     trace_buf = xbt_realloc(trace_buf,strlen(trace_buf)+strlen(print_buf)+1);
     strcat(trace_buf, print_buf);
+
+    if(!cnst->shared) {
+      sprintf(print_buf," [MAX-Constraint]");
+      trace_buf = xbt_realloc(trace_buf,strlen(trace_buf)+strlen(print_buf)+1);
+      strcat(trace_buf, print_buf);
+    }
     DEBUG1("%s",trace_buf);
     trace_buf[0]='\000';
-    xbt_assert2((sum<=cnst->bound), "Incorrect value (%f is not smaller than %f)",
-               sum,cnst->bound);
+    xbt_assert3(!double_positive(sum-cnst->bound), "Incorrect value (%f is not smaller than %f): %g",
+               sum,cnst->bound,sum-cnst->bound);
   }
 
   /* Printing Result */
   xbt_swag_foreach(var, var_list) {
     if(var->bound>0) {
       DEBUG4("'%p'(%f) : %f (<=%f)",var,var->weight,var->value, var->bound);
-      xbt_assert0((var->value<=var->bound), "Incorrect value");
+      xbt_assert0(!double_positive(var->value-var->bound), "Incorrect value");
     }
     else 
       DEBUG3("'%p'(%f) : %f",var,var->weight,var->value);
@@ -410,9 +424,9 @@ void lmm_solve(lmm_system_t sys)
     var->value = 0.0;
   }
 
-
-  /* Compute Usage and store the variables that reach the maximum */
-
+  /* 
+   * Compute Usage and store the variables that reach the maximum.
+   */
   cnst_list = &(sys->active_constraint_set);
   DEBUG1("Active constraints : %d", xbt_swag_size(cnst_list));
   xbt_swag_foreach(cnst, cnst_list) {
@@ -420,21 +434,22 @@ void lmm_solve(lmm_system_t sys)
     cnst->remaining = cnst->bound;
     cnst->usage = 0;
     elem_list = &(cnst->element_set);
+    cnst->usage = 0.0;
     xbt_swag_foreach(elem, elem_list) {
       if(elem->variable->weight <=0) break;
       if ((elem->value > 0)) {
        if(cnst->shared)
          cnst->usage += elem->value / elem->variable->weight;
        else 
-         cnst->usage = 1;
+         if(cnst->usage<elem->value / elem->variable->weight)
+           cnst->usage = elem->value / elem->variable->weight;
+       DEBUG2("Constraint Usage %p : %f",cnst,cnst->usage);
        make_elem_active(elem);
       }
     }
-
     /* Saturated constraints update */
     saturated_constraint_set_update(sys, cnst, &min_usage);
   }
-
   saturated_variable_set_update(sys);
 
   /* Saturated variables update */
@@ -459,6 +474,8 @@ void lmm_solve(lmm_system_t sys)
       int i;
 
       var->value = min_usage / var->weight;
+      DEBUG5("Min usage: %f, Var(%p)->weight: %f, Var(%p)->value: %f ",min_usage,var,var->weight,var,var->value);
+
 
       /* Update usage */
 
@@ -466,10 +483,23 @@ void lmm_solve(lmm_system_t sys)
        elem = &var->cnsts[i];
        cnst = elem->constraint;
        if(cnst->shared) {
-         cnst->remaining -= elem->value * var->value;
-         cnst->usage -= elem->value / var->weight;
+         double_update(&(cnst->remaining), elem->value * var->value);
+         double_update(&(cnst->usage), elem->value / var->weight);
+         make_elem_inactive(elem);
+       } else { /* FIXME one day: We recompute usage.... :( */
+         cnst->usage = 0.0;
+         make_elem_inactive(elem);
+         xbt_swag_foreach(elem, elem_list) {
+           if(elem->variable->weight <=0) break;
+           if(elem->variable->value > 0) break;
+           if ((elem->value > 0)) {
+             if(cnst->usage<elem->value / elem->variable->weight)
+               cnst->usage = elem->value / elem->variable->weight;
+             DEBUG2("Constraint Usage %p : %f",cnst,cnst->usage);
+             make_elem_active(elem);
+           }
+         } 
        }
-       make_elem_inactive(elem);
       }
       xbt_swag_remove(var, var_list);
     }
@@ -505,6 +535,18 @@ void lmm_update(lmm_system_t sys, lmm_constraint_t cnst,
     }
 }
 
+/** \brief Attribute the value bound to var->bound.
+ * 
+ *  \param sys the lmm_system_t
+ *  \param var the lmm_variable_t
+ *  \param bound the new bound to associate with var
+ * 
+ *  Makes var->bound equal to bound. Whenever this function is called 
+ *  a change is  signed in the system. To
+ *  avoid false system changing detection it is a good idea to test 
+ *  (bound != 0) before calling it.
+ *
+ */
 void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var,
                               double bound)
 {
@@ -512,6 +554,25 @@ void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var,
   var->bound = bound;
 }
 
+/** \brief Add the value delta to var->df (the sum of latencies).
+ * 
+ *  \param sys the lmm_system_t associated
+ *  \param var the lmm_variable_t which need to updated
+ *  \param delta the variation of the latency
+ * 
+ *  Add the value delta to var->df (the sum of latencys associated to the
+ *  flow). Whenever this function is called a change is  signed in the system. To
+ *  avoid false system changing detection it is a good idea to test 
+ *  (delta != 0) before calling it.
+ *
+ */
+void lmm_update_variable_latency(lmm_system_t sys, lmm_variable_t var,
+                              double delta)
+{
+  sys->modified = 1;
+  var->df += delta;
+}
+
 void lmm_update_variable_weight(lmm_system_t sys, lmm_variable_t var,
                                double weight)
 {
@@ -562,3 +623,115 @@ lmm_constraint_t lmm_get_next_active_constraint(lmm_system_t sys, lmm_constraint
   return xbt_swag_getNext(cnst,(sys->active_constraint_set).offset);
 }
 
+
+
+/** \brief Attribute the value bound to var->bound.
+ * 
+ *  \param func_f    default function f associated with the chosen protocol flavor
+ *  \param func_fp   partial differential of f (f prime, f')
+ *  \param func_fpi  inverse of the partial differential of f (f prime inverse, (f')^{-1})
+ *  \param func_fpip partial differential of the inverse of the partial differential of f (f prime inverse prime, ((f')^{-1})')
+ * 
+ *  Set default functions to the ones passed as parameters. This is a polimorfism in C pure, enjoy the roots of programming.
+ *
+ */
+void lmm_set_default_protocol_functions(double (* func_f)    (lmm_variable_t var, double x),
+                                       double (* func_fp)   (lmm_variable_t var, double x),
+                                       double (* func_fpi)  (lmm_variable_t var, double x),
+                                       double (* func_fpip) (lmm_variable_t var, double x))
+                                       
+{
+  func_f_def    = func_f;
+  func_fp_def   = func_fp;
+  func_fpi_def  = func_fpi;
+  func_fpip_def = func_fpip;
+}
+
+
+/*
+ * NOTE for Reno: all functions consider the network
+ * coeficient (alpha) equal to 1.
+ */
+
+/*
+ * For Vegas f: $\alpha_f d_f \log\left(x_f\right)$
+ */
+double func_vegas_f(lmm_variable_t var, double x){
+  return var->df * log(x);
+}
+
+/*
+ * For Vegas fp: $\frac{\alpha D_f}{x}$
+ */
+double func_vegas_fp(lmm_variable_t var, double x){
+  //avoid a disaster value - c'est du bricolage mais ca marche
+/*   if(x == 0) x = 10e-8; */
+  return var->df/x;
+}
+
+/*
+ * For Vegas fpi: $\frac{\alpha D_f}{x}$
+ */
+double func_vegas_fpi(lmm_variable_t var, double x){
+  //avoid a disaster value - c'est du bricolage mais ca marche
+/*   if(x == 0) x = 10e-8; */
+  return var->df/x;
+}
+
+/*
+ * For Vegas fpip: $-\frac{\alpha D_f}{x^2}$
+ */
+double func_vegas_fpip(lmm_variable_t var, double x){
+  //avoid a disaster value - c'est du bricolage mais ca marche
+/*   if(x == 0) x = 10e-8; */
+  return -( var->df/(x*x) ) ;
+}
+
+
+/*
+ * For Reno f: $\frac{\sqrt{\frac{3}{2}}}{D_f} \arctan\left(\sqrt{\frac{3}{2}}x_f D_f\right)$
+ */
+double func_reno_f(lmm_variable_t var, double x){
+  xbt_assert0(var->df>0.0,"Don't call me with stupid values!");
+  // \sqrt{3/2} = 0.8164965808
+  return (0.8164965808 / var->df) * atan( (0.8164965808 / var->df)*x );
+}
+
+/*
+ * For Reno fp: $\frac{3}{3 {D_f}^2 x^2 + 2}$
+ */
+double func_reno_fp(lmm_variable_t var, double x){
+  return 3 / (3*var->df*var->df*x*x + 2);
+}
+
+/*
+ * For Reno fpi: $\sqrt{\frac{1}{{D_f}^2 x} - \frac{2}{3{D_f}^2}}$
+ */
+double func_reno_fpi(lmm_variable_t var, double x){
+  double res_fpi; 
+
+  xbt_assert0(var->df>0.0,"Don't call me with stupid values!");
+  xbt_assert0(x>0.0,"Don't call me with stupid values!");
+
+  res_fpi = 1/(var->df*var->df*x) - 2/(3*var->df*var->df);
+  if(res_fpi<=0.0) return 0.0;
+  xbt_assert0(res_fpi>0.0,"Don't call me with stupid values!");
+  return sqrt(res_fpi);
+}
+
+/*
+ * For Reno fpip:  $-\frac{1}{2 {D_f}^2 x^2\sqrt{\frac{1}{{D_f}^2 x} - \frac{2}{3{D_f}^2}}}$
+ */
+double func_reno_fpip(lmm_variable_t var, double x){
+  double res_fpip; 
+  double critical_test;
+
+  xbt_assert0(var->df>0.0,"Don't call me with stupid values!");
+  xbt_assert0(x>0.0,"Don't call me with stupid values!");
+
+  res_fpip = 1/(var->df*var->df*x) - 2/(3*var->df*var->df);
+  xbt_assert0(res_fpip>0.0,"Don't call me with stupid values!");
+  critical_test = (2*var->df*var->df*x*x*sqrt(res_fpip));
+
+  return -(1.0/critical_test);
+}