next up previous contents index
Next: Profiles of the and Up: T. Zurek: Optimisation of Previous: Timestamps for Q

Manipulation of Interval Lengths

          

This is the C source code for a function change_lengths (change) that changes the average interval length by the value given in change.

/*************************************/
/*****  change_lengths (change)  *****/
/*************************************/
/* 
   Changes the average length of the intervals by the 
   value given in "change". The interval starpoints
   are stored in ts[0..N-1] and the corresponding
   endpoints in te[0..N-1].
   The function randomly picks an interval and adds
   or subtracts chronons in order to achieve the new
   average length.
*/

void change_lengths (int change)  {

/* 
   Global variables or macros:
   ---------------------------
   N              = total number of intervals
   ts[0..N-1]     = intervals startpoints
   te[0..N-1]     = intervals endpoints
   tmax           = maximum value for a ts[] or a te[]
   MAX_IDLE       = max. number of loop runs that can be idle
   total_length   = sum of all intervals' lengths
   average_length = current average length of the intervals

   Local variables:
   ----------------
   i          = index of interval whose length will be changed 
   useless    = counter for the number of intervals with ts >= te
   idle       = number of subsequent idle loop passes
   difference = interval i's length = te[i] - ts[i]
   direction  = +1  if average length is to be increased
              = -1  if average length is to be decreased
   to_change  = number of chronons that remain to be 
                added or subtracted
   abs_change = abs(change) = change * direction
   end        = 0   if ts[i] is to be moved to the left or right
              = 1   if te[i] is to be moved to the left or right
*/
     
   unsigned i, useless, idle, difference, abs_change;
   int      end = 1;
   long     to_change;
   short    direction;  


   /* Are chronons added or subtracted */

   if (change >= 0)
     direction = 1;
   else
     direction = -1;


   /* determine the absolute value of "change" */

   abs_change = change * direction;


   /* total amount of chronons to add / to substract */

   to_change = change * N;


   /* determine new total length */

   total_length = total_length + to_change;


   /* initialise random generator */

   srand(seed);


   /* initialise "idle" */

   idle = 0;


   /* main loop that subsequently adds or substracts chronons */

   while ((to_change > 0) && (idle < MAX_IDLE)) {

      /* find a suitable interval */

      do {
        i = rand() % N;
      } while ((ts[i]==0) && (te[i]==tmax));


      /* will start- or endpoint be changed? */

      end = rand() % 2;


      /* increase lengths */

      if (direction == 1) {           

        idle++;

        if ((end == 0) && (ts[i] > 0)) {
          ts[i]--;
          to_change--;
          idle = 0;
        }

        if ((end == 1) && (te[i] < tmax)) {
            te[i]++;
            to_change--;
            idle = 0;
          }
      }

      /* decrease lengths */

      else {
        
        /* search for another interval if the current one
           comprises no chronon, i.e. it is a timepoint.
           The search is stopped when the number of useless
           intervals matches the total number of intervals. */
           
        useless = 0;

        while ((ts[i] == te[i]) && (useless < N)) {
          i = (i+1) % N;
          useless++;
        }

        /* If no suitable interval is found then leave the loop */

        if (useless >= N)
          idle = MAX_IDLE;

        /* If the interval i is suitable then ... */

        if (ts[i] < te[i]) {

          difference = te[i] - ts[i];

          /* decrease length as much as possible */

          if (difference <= abs_change) {
            if (end)
              te[i] = ts[i];
            else
              ts[i] = te[i];
            to_change = to_change + difference;
          }
          else if ((difference > abs_change) && 
                   (to_change  < (2*change))  )   {
            if (!end)
              ts[i]     = ts[i] + abs_change;
            else
              te[i]     = te[i] - abs_change;
            to_change = to_change + abs_change;
          }
          else {
            if (!end)
              ts[i]++;
            else
              te[i]--;
            to_change++;
          }
        }
      }

   }

   if (to_change != 0) {
     fprintf(stderr,"--- Warning ---\n");
     fprintf(stderr,"Too many idle attempts!\n");
     fprintf(stderr,"Abandoned change loop.\n");
     total_length = total_length - to_change;
   }
   
   /* determine new average length */
      
   average_length = total_length / N;

   
   return;
}



Thomas Zurek