setdest.cc

Go to the documentation of this file.
00001 /*
00002  *
00003  * The original code of setdest was included in ns-2.1b8a.
00004  * This file is the modified version by J. Yoon <jkyoon@eecs.umich.edu>,
00005  *  Department of EECS, University of Michigan, Ann Arbor. 
00006  *
00007  * (1) Input parameters
00008  *  <Original version>
00009  *      => -M maximum speed (minimum speed is zero as a default)
00010  *      => -p pause time (constant) 
00011  *      => -n number of nodes
00012  *      => -x x dimension of space
00013  *      => -y y dimension of space
00014  *
00015  *  <Modified version>
00016  *      => -s speed type (uniform, normal)
00017  *      => -m minimum speed > 0 
00018  *      => -M maximum speed
00019  *      => -P pause type (constant, uniform)
00020  *      => -p pause time (a median if uniform is chosen)
00021  *      => -n number of nodes
00022  *      => -x x dimension of space
00023  *      => -y y dimension of space
00024  *
00025  * (2) In case of modified version, the steady-state speed distribution is applied to 
00026  *  the first trip to eliminate any speed decay. If pause is not zero, the first 
00027  *  trip could be either a move or a pause depending on the probabilty that the 
00028  *  first trip is a pause. After the first trip regardless of whether it is 
00029  *  a move or a pause, all subsequent speeds are determined from the given speed 
00030  *  distribution (e.g., uniform or normal).
00031  *
00032  * (3) Refer to and use scenario-generating scripts (make-scen.csh for original version, 
00033  *  make-scen-steadystate.csh for modified version).
00034  *
00035  *
00036  */
00037 
00038 
00039 
00040 extern "C" {
00041 #include <assert.h>
00042 #include <fcntl.h>
00043 #include <math.h>
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <sys/time.h>
00048 #include <sys/types.h>
00049 #include <sys/uio.h>
00050 #include <unistd.h>
00051 #if !defined(sun)
00052 #include <err.h>
00053 #endif
00054 };
00055 #include "../../../tools/rng.h"
00056 
00057 #include "setdest.h"
00058 
00059 
00060 // #define      DEBUG
00061 #define     SANITY_CHECKS
00062 //#define       SHOW_SYMMETRIC_PAIRS
00063 
00064 
00065 #define GOD_FORMAT  "$ns_ at %.12f \"$god_ set-dist %d %d %d\"\n"
00066 #define GOD_FORMAT2 "$god_ set-dist %d %d %d\n"
00067 #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n"
00068 #define NODE_FORMAT2    "$node_(%d) setdest %.12f %.12f %.12f\n"
00069 #define NODE_FORMAT3    "$node_(%d) set %c_ %.12f\n"
00070 
00071 #define     RTG_INFINITY    0x00ffffff
00072 #ifndef min
00073 #define     min(x,y)    ((x) < (y) ? (x) : (y))
00074 #define     max(x,y)    ((x) > (y) ? (x) : (y))
00075 #endif
00076 #define     ROUND_ERROR 1e-9
00077 #ifndef PI
00078 #define     PI      3.1415926   
00079 #endif
00080 
00081 
00082 static int count = 0;
00083 
00084 /* ======================================================================
00085    Function Prototypes
00086    ====================================================================== */
00087 void        usage(char**);
00088 void        init(void);
00089 double      uniform(void);
00090 
00091 void        dumpall(void);
00092 void        ComputeW(void);
00093 void        floyd_warshall(void);
00094 
00095 void        show_diffs(void);
00096 void        show_routes(void);
00097 void        show_counters(void);
00098 
00099 
00100 /* ======================================================================
00101    Global Variables
00102    ====================================================================== */
00103 const double    RANGE = 250.0;  // transmitter range in meters
00104 double      TIME = 0.0;         // my clock;
00105 double      MAXTIME = 0.0;      // duration of simulation
00106 
00107 double      MAXX = 0.0;         // width of space
00108 double      MAXY = 0.0;         // height of space
00109 double      PAUSE = 0.0;        // pause time
00110 double      MAXSPEED = 0.0;     // max speed
00111 double      MINSPEED = 0.0;     // min speed 
00112 double      SS_AVGSPEED = 0.0;  // steady-state avg speed 
00113 double      KAPPA = 0.0;        // normalizing constant 
00114 double      MEAN = 0.0;         // mean for normal speed
00115 double      SIGMA = 0.0;        // std for normal speed
00116 double      EXP_1_V = 0.0;      // expactation of 1/V
00117 double      EXP_R = 0.0;        // expectation of travel distance R
00118 double      PDFMAX = 0.0;       // max of pdf for rejection technique
00119 u_int32_t   SPEEDTYPE = 1;      // speed type (default = uniform)
00120 u_int32_t   PAUSETYPE = 1;      // pause type (default = constant)
00121 u_int32_t   VERSION = 1;        // setdest version (default = original by CMU) 
00122 u_int32_t   NODES = 0;          // number of nodes
00123 u_int32_t   RouteChangeCount = 0;
00124 u_int32_t   LinkChangeCount = 0;
00125 u_int32_t   DestUnreachableCount = 0;
00126 
00127 
00128 Node        *NodeList = 0;
00129 u_int32_t   *D1 = 0;
00130 u_int32_t   *D2 = 0;
00131 
00132 
00133 /* ======================================================================
00134    Random Number Generation
00135    ====================================================================== */
00136 #define M       2147483647L
00137 #define INVERSE_M   ((double)4.656612875e-10)
00138 
00139 char random_state[32];
00140 RNG *rng;
00141 
00142 double
00143 uniform()
00144 {
00145         count++;
00146         return rng->uniform_double() ;
00147 }
00148 
00149 
00150 /* ======================================================================
00151    Misc Functions...
00152    ====================================================================== */
00153 
00154 
00155 /* compute the expectation of travel distance E[R] in a rectangle */
00156 void
00157 compute_EXP_R()
00158 {
00159     #define csc(x)      (1.0/sin(x))        // csc function
00160     #define sec(x)      (1.0/cos(x))        // sec function
00161     #define sin2(x)     (sin(x)*sin(x))     // sin^2
00162     #define sin3(x)     (sin2(x)*sin(x))    // sin^3
00163     #define cos2(x)     (cos(x)*cos(x))     // cos^2
00164     #define cos3(x)     (cos2(x)*cos(x))    // cos^3
00165 
00166     double x = MAXX, y = MAXY;          // max x and max y
00167     double x2 = x*x, x3 = x*x*x;            // x^2 and x^3
00168     double y2 = y*y, y3 = y*y*y;            // y^2 and y^3
00169 
00170     double term1 = sin(atan2(y,x)) / 2.0 / cos2(atan2(y,x));
00171     double term2 = 0.5 * log( sec(atan2(y,x)) + y/x );
00172     double term3 = -1.0 * x3 / y2 / 60.0 / cos3(atan2(y,x)) + 1.0/60.0 * x3 / y2;
00173     double term4 = (term1 + term2) * x2 / 12.0 / y + term3;
00174 
00175     double term5 = -1.0 * cos(atan2(y,x)) / 2.0 / sin2(atan2(y,x));
00176     double term6 = 0.5 * log( csc(atan2(y,x)) - x/y );
00177     double term7 = -1.0 * y3 / x2 / 60.0 / sin3(atan2(y,x)) + 1.0/60.0 * y3 / x2;
00178     double term8 = -1.0 * (term5 + term6) * y2 / 12.0 / x + term7;
00179 
00180     EXP_R = (4 * (term4 + term8));          // E[R]
00181 }
00182 
00183 void
00184 usage(char **argv)
00185 {
00186     fprintf(stderr, "\nusage:\n");
00187     fprintf(stderr,
00188         "\n<original 1999 CMU version (version 1)>\n %s\t-v <1> -n <nodes> -p <pause time> -M <max speed>\n",
00189         argv[0]);
00190     fprintf(stderr,
00191         "\t\t-t <simulation time> -x <max X> -y <max Y>\n");
00192     fprintf(stderr,
00193         "\nOR\n<modified 2003 U.Michigan version (version 2)>\n %s\t-v <2> -n <nodes> -s <speed type> -m <min speed> -M <max speed>\n",
00194         argv[0]);
00195     fprintf(stderr,
00196         "\t\t-t <simulation time> -P <pause type> -p <pause time> -x <max X> -y <max Y>\n");
00197     fprintf(stderr,
00198         "\t\t(Refer to the script files make-scen.csh and make-scen-steadystate.csh for detail.) \n\n");
00199 }
00200 
00201 void
00202 init()
00203 {
00204     /*
00205      * Initialized the Random Number Generation
00206      */
00207     /* 
00208     This part of init() is commented out and is replaced by more
00209     portable RNG (random number generator class of ns) functions.   
00210 
00211     struct timeval tp;
00212     int fd, seed, bytes;
00213 
00214     if((fd = open("/dev/random", O_RDONLY)) < 0) {
00215         perror("open");
00216         exit(1);
00217     }
00218     if((bytes = read(fd, random_state, sizeof(random_state))) < 0) {
00219         perror("read");
00220         exit(1);
00221     }
00222     close(fd);
00223 
00224     fprintf(stderr, "*** read %d bytes from /dev/random\n", bytes);
00225 
00226     if(bytes != sizeof(random_state)) {
00227       fprintf(stderr,"Not enough randomness. Reading `.rand_state'\n");
00228       if((fd = open(".rand_state", O_RDONLY)) < 0) {
00229         perror("open .rand_state");
00230         exit(1);
00231       }
00232       if((bytes = read(fd, random_state, sizeof(random_state))) < 0) {
00233         perror("reading .rand_state");
00234         exit(1);
00235       }
00236       close(fd);
00237     }
00238 
00239          if(gettimeofday(&tp, 0) < 0) {
00240         perror("gettimeofday");
00241         exit(1);
00242     }
00243     seed = (tp.tv_sec  >> 12 ) ^ tp.tv_usec;
00244         (void) initstate(seed, random_state, bytes & 0xf8);*/
00245 
00246     /*
00247      * Allocate memory for globals
00248      */
00249     NodeList = new Node[NODES];
00250     if(NodeList == 0) {
00251         perror("new");
00252         exit(1);
00253     }
00254 
00255     D1 = new u_int32_t[NODES * NODES];
00256     if(D1 == 0) {
00257         perror("new");
00258         exit(1);
00259     }
00260     memset(D1, '\xff', sizeof(u_int32_t) * NODES * NODES);
00261 
00262     D2 = new u_int32_t[NODES * NODES];
00263     if(D2 == 0) {
00264         perror("new");
00265         exit(1);
00266     }
00267     memset(D2, '\xff', sizeof(u_int32_t) * NODES * NODES);
00268 }
00269 
00270 extern "C" char *optarg;
00271 
00272 int
00273 main(int argc, char **argv)
00274 {
00275     char ch;
00276 
00277     while ((ch = getopt(argc, argv, "v:n:s:m:M:t:P:p:x:y:i:o:")) != EOF) {       
00278 
00279         switch (ch) { 
00280         
00281         case 'v':
00282           VERSION = atoi(optarg);
00283           break;
00284 
00285         case 'n':
00286           NODES = atoi(optarg);
00287           break;
00288 
00289         case 's':
00290             SPEEDTYPE = atoi(optarg);   
00291             break;
00292 
00293         case 'm':
00294             MINSPEED = atof(optarg);    
00295             break;
00296 
00297         case 'M':
00298             MAXSPEED = atof(optarg);
00299             break;
00300 
00301         case 't':
00302             MAXTIME = atof(optarg);
00303             break;
00304 
00305         case 'P':
00306             PAUSETYPE = atoi(optarg);   
00307             break;
00308 
00309         case 'p':
00310             PAUSE = atof(optarg);
00311             break;
00312 
00313         case 'x':
00314             MAXX = atof(optarg);
00315             break;
00316 
00317         case 'y':
00318             MAXY = atof(optarg);
00319             break;
00320 
00321         default:
00322             usage(argv);
00323             exit(1);
00324         }
00325     }
00326 
00327     if(MAXX == 0.0 || MAXY == 0.0 || NODES == 0 || MAXTIME == 0.0) {
00328         usage(argv);
00329         exit(1);
00330     }
00331     
00332     /* specify the version */
00333     if (VERSION != 1 && VERSION != 2) {
00334       printf("Please specify the setdest version you want to use. For original 1999 CMU version use 1; For modified 2003 U.Michigan version use 2\n");
00335       exit(1);
00336     }
00337 
00338     if (VERSION == 2 && MINSPEED <= 0) {
00339       usage(argv);
00340       exit(1);
00341     } else if (VERSION == 1 && MINSPEED > 0) {
00342       usage(argv);
00343       exit(1);
00344     }
00345 
00346 
00347     // The more portable solution for random number generation
00348     rng = new RNG;
00349     rng->set_seed(RNG::HEURISTIC_SEED_SOURCE); 
00350 
00351 
00352 
00353     /****************************************************************************************
00354      * Steady-state avg speed and distribution depending on the initial distirbutions given
00355      ****************************************************************************************/
00356     
00357     /* original setdest */  
00358     if (VERSION == 1) { 
00359         fprintf(stdout, "#\n# nodes: %d, pause: %.2f, max speed: %.2f, max x: %.2f, max y: %.2f\n#\n",
00360             NODES, PAUSE, MAXSPEED, MAXX, MAXY);
00361     }   
00362 
00363     /* modified version */
00364     else if (VERSION == 2) {
00365         /* compute the expectation of travel distance in a rectangle */
00366         compute_EXP_R();
00367 
00368         /* uniform speed from min to max */
00369         if (SPEEDTYPE == 1) {
00370             EXP_1_V = log(MAXSPEED/MINSPEED) / (MAXSPEED - MINSPEED);   // E[1/V]
00371             SS_AVGSPEED = EXP_R / (EXP_1_V*EXP_R + PAUSE);              // steady-state average speed
00372             PDFMAX = 1/MINSPEED*EXP_R / (EXP_1_V*EXP_R + PAUSE) / (MAXSPEED-MINSPEED);  // max of pdf for rejection technique
00373         }
00374         
00375         /* normal speed clipped from min to max */
00376         else if (SPEEDTYPE == 2) {
00377             int bin_no = 10000;                                 // the number of bins for summation
00378             double delta = (MAXSPEED - MINSPEED)/bin_no;        // width of each bin 
00379             int i;
00380             double acc_k, acc_e, square, temp_v;
00381 
00382             MEAN = (MAXSPEED + MINSPEED)/2.0;                   // means for normal dist.
00383             SIGMA = (MAXSPEED - MINSPEED)/4.0;                  // std for normal dist.
00384             /* computing a normalizing constant KAPPA, E[1/V], and pdf max */
00385             KAPPA = 0.0;
00386             EXP_1_V = 0.0;
00387             PDFMAX = 0.0;
00388 
00389             /* numerical integrals */
00390             for (i=0; i<bin_no; ++i) {
00391                 temp_v = MINSPEED + i*delta;        // ith v from min speed
00392                 square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
00393 
00394                 acc_k = 1.0/sqrt(2.0*PI*SIGMA*SIGMA)*exp(-0.5*square);
00395                 KAPPA += (acc_k*delta);             // summing up the area of rectangle
00396 
00397                 acc_e = 1.0/temp_v/sqrt(2.0*PI*SIGMA*SIGMA)*exp(-0.5*square);
00398                 EXP_1_V += (acc_e*delta);           // summing up for the denominator of pdf
00399     
00400                 /* find a max of pdf */
00401                 if (PDFMAX < acc_e) PDFMAX = acc_e;
00402             }
00403             EXP_1_V /= KAPPA;                       // normalizing
00404             SS_AVGSPEED = EXP_R / (EXP_1_V*EXP_R + PAUSE);          // steady-state average speed
00405             PDFMAX = EXP_R*PDFMAX/KAPPA / (EXP_1_V*EXP_R + PAUSE);  // max of pdf for rejection technique
00406         }
00407         /* other types of speed for future use */
00408         else
00409             ;
00410     
00411         fprintf(stdout, "#\n# nodes: %d, speed type: %d, min speed: %.2f, max speed: %.2f\n# avg speed: %.2f, pause type: %d, pause: %.2f, max x: %.2f, max y: %.2f\n#\n",
00412             NODES , SPEEDTYPE, MINSPEED, MAXSPEED, SS_AVGSPEED, PAUSETYPE, PAUSE, MAXX, MAXY);
00413     }   
00414 
00415 
00416     init();
00417 
00418     while(TIME <= MAXTIME) {
00419         double nexttime = 0.0;
00420         u_int32_t i;
00421 
00422         for(i = 0; i < NODES; i++) {
00423             NodeList[i].Update();
00424         }
00425 
00426         for(i = 0; i < NODES; i++) {
00427             NodeList[i].UpdateNeighbors();
00428         }
00429 
00430         for(i = 0; i < NODES; i++) {
00431             Node *n = &NodeList[i];
00432     
00433             if(n->time_transition > 0.0) {
00434                 if(nexttime == 0.0)
00435                     nexttime = n->time_transition;
00436                 else
00437                     nexttime = min(nexttime, n->time_transition);
00438             }
00439 
00440             if(n->time_arrival > 0.0) {
00441                 if(nexttime == 0.0)
00442                     nexttime = n->time_arrival;
00443                 else
00444                     nexttime = min(nexttime, n->time_arrival);
00445             }
00446 
00447         }
00448 
00449         floyd_warshall();
00450 
00451 #ifdef DEBUG
00452         show_routes();
00453 #endif
00454 
00455         show_diffs();
00456 
00457 #ifdef DEBUG
00458         dumpall();
00459 #endif
00460 
00461         assert(nexttime > TIME + ROUND_ERROR);
00462         TIME = nexttime;
00463     }
00464 
00465     show_counters();
00466 
00467     int of;
00468     if ((of = open(".rand_state",O_WRONLY | O_TRUNC | O_CREAT, 0777)) < 0) {
00469       fprintf(stderr, "open rand state\n");
00470       exit(-1);
00471       }
00472     for (unsigned int i = 0; i < sizeof(random_state); i++)
00473           random_state[i] = 0xff & (int) (uniform() * 256);
00474     if (write(of,random_state, sizeof(random_state)) < 0) {
00475       fprintf(stderr, "writing rand state\n");
00476       exit(-1);
00477       }
00478     close(of);
00479 
00480 
00481 }
00482 
00483 
00484 /* ======================================================================
00485    Node Class Functions
00486    ====================================================================== */
00487 u_int32_t Node::NodeIndex = 0;
00488 
00489 Node::Node()
00490 {
00491     u_int32_t i;
00492 
00493     index = NodeIndex++;
00494 
00495     //if(index == 0)
00496     //  return;
00497 
00498     route_changes = 0;
00499     link_changes = 0;
00500 
00501 
00502 
00503     /*******************************************************************************
00504      * Determine if the first trip is a pause or a move with the steady-state pdf
00505      *******************************************************************************/
00506 
00507     /* original version */
00508     if (VERSION == 1) {
00509             time_arrival = TIME + PAUSE;            // constant pause
00510     }
00511 
00512     /* modified version */ 
00513     else if (VERSION == 2) {
00514         /* probability that the first trip would be a pause */
00515         double prob_pause = PAUSE / (EXP_1_V*EXP_R + PAUSE);
00516     
00517         /* the first trip is a pause */
00518         if (prob_pause > uniform()) {
00519             /* constant pause */
00520             if (PAUSETYPE == 1) {
00521                 time_arrival = TIME + PAUSE;                // constant pause
00522             }
00523             /* uniform pause */
00524             else if (PAUSETYPE == 2) {
00525                 time_arrival = TIME + 2*PAUSE*uniform();    // uniform pause [0, 2*PAUSE]
00526             }
00527                 
00528             first_trip = 0;                     // indicating the first trip is a pause 
00529         }
00530         /* the first trip is a move based on the steady-state pdf */
00531         else {
00532             time_arrival = TIME;
00533             first_trip = 1;                     // indicating the first trip is a move 
00534         }
00535     }
00536 
00537 
00538     time_update = TIME;
00539     time_transition = 0.0;
00540 
00541     position.X = position.Y = position.Z = 0.0;
00542     destination.X = destination.Y = destination.Z = 0.0;
00543     direction.X = direction.Y = direction.Z = 0.0;
00544     speed = 0.0;
00545 
00546     RandomPosition();
00547 
00548     fprintf(stdout, NODE_FORMAT3, index, 'X', position.X);
00549     fprintf(stdout, NODE_FORMAT3, index, 'Y', position.Y);
00550     fprintf(stdout, NODE_FORMAT3, index, 'Z', position.Z);
00551 
00552     neighbor = new Neighbor[NODES];
00553     if(neighbor == 0) {
00554         perror("new");
00555         exit(1);
00556     }
00557 
00558     for(i = 0; i < NODES; i++) {
00559         neighbor[i].index = i;
00560         neighbor[i].reachable = (index == i) ? 1 : 0;
00561         neighbor[i].time_transition = 0.0;
00562     }
00563 }
00564 
00565 
00566 
00567 void
00568 Node::RandomPosition()
00569 {
00570     position.X = uniform() * MAXX;
00571     position.Y = uniform() * MAXY;
00572     position.Z = 0.0;
00573 }
00574 
00575 
00576 void
00577 Node::RandomDestination()
00578 {
00579     destination.X = uniform() * MAXX;
00580     destination.Y = uniform() * MAXY;
00581     destination.Z = 0.0;
00582     assert(destination != position);
00583 }
00584 
00585 
00586 /****************************************************************************************** 
00587  * Speeds are chosen based on the given type and distribution
00588  ******************************************************************************************/
00589 void
00590 Node::RandomSpeed()
00591 {
00592     /* original version */
00593     if (VERSION == 1) {
00594         speed = uniform() * MAXSPEED;
00595         assert(speed != 0.0);
00596     }
00597 
00598     /* modified version */
00599     else if (VERSION == 2) {
00600         /* uniform speed */
00601         if (SPEEDTYPE == 1) {
00602             /* using steady-state distribution for the first trip */
00603             if (first_trip == 1) {
00604                 /* pick a speed by rejection technique */
00605                 double temp_v, temp_fv;
00606     
00607                 do {
00608                     temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
00609                     temp_fv = uniform() * PDFMAX;
00610                 } while (temp_fv > 1/temp_v*EXP_R / (EXP_1_V*EXP_R + PAUSE) / (MAXSPEED-MINSPEED));
00611      
00612                 speed = temp_v;
00613                 first_trip = 0;     // reset first_trip flag    
00614             }
00615             /* using the original distribution from the second trip on */
00616             else {
00617                 speed = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
00618                 assert(speed != 0.0);
00619             }
00620         }
00621         /* normal speed */
00622         else if (SPEEDTYPE == 2) {
00623             /* using steady-state distribution for the first trip */
00624             if (first_trip == 1) {
00625                 double temp_v, temp_fv, square, fv;
00626     
00627                 /* rejection technique */
00628                 do {
00629                     temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
00630                     temp_fv = uniform() * PDFMAX;
00631                     square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
00632                     fv = 1/KAPPA/sqrt(2.0*PI*SIGMA*SIGMA) * exp(-0.5*square);
00633                 } while (temp_fv > 1.0/temp_v*fv*EXP_R / (EXP_1_V*EXP_R + PAUSE));
00634      
00635                 speed = temp_v;
00636                 first_trip = 0;
00637             }
00638             /* using the original distribution from the second trip on */
00639             else {
00640                 double temp_v, temp_fv, square;
00641                 double max_normal = 1.0/KAPPA/sqrt(2.0*PI*SIGMA*SIGMA);     // max of normal distribution
00642     
00643                 /* rejection technique */
00644                 do {
00645                     temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
00646                     temp_fv = uniform() * max_normal;
00647                     square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
00648                 } while (temp_fv > max_normal * exp(-0.5*square));
00649      
00650                 speed = temp_v;
00651                 assert(speed != 0.0);
00652             }
00653         }
00654         /* other types of speed for future use */
00655         else
00656             ;
00657     }
00658 }
00659 
00660 
00661 void
00662 Node::Update()
00663 {
00664     position += (speed * (TIME - time_update)) * direction;
00665 
00666     if(TIME == time_arrival) {
00667         vector v;
00668 
00669         if(speed == 0.0 || PAUSE == 0.0) {
00670 
00671             RandomDestination();
00672             RandomSpeed();
00673 
00674             v = destination - position;
00675             direction = v / v.length();
00676             time_arrival = TIME + v.length() / speed;
00677         }
00678         else {
00679 
00680             destination = position;
00681             speed = 0.0;
00682 
00683             /* original version */
00684             if (VERSION == 1) {
00685                 time_arrival = TIME + PAUSE;
00686             }
00687             /* modified version */
00688             else if (VERSION == 2) {
00689                 /* constant pause */
00690                 if (PAUSETYPE == 1) {
00691                     time_arrival = TIME + PAUSE;
00692                 }
00693                 /* uniform pause */
00694                 else if (PAUSETYPE == 2) {
00695                     time_arrival = TIME + 2*PAUSE*uniform();
00696                 }
00697             }
00698         }
00699 
00700         fprintf(stdout, NODE_FORMAT,
00701             TIME, index, destination.X, destination.Y, speed);
00702     
00703     }
00704 
00705     time_update = TIME;
00706     time_transition = 0.0;
00707 }
00708 
00709 
00710 void
00711 Node::UpdateNeighbors()
00712 {
00713     static Node *n2;
00714     static Neighbor *m1, *m2;
00715     static vector D, B, v1, v2;
00716     static double a, b, c, t1, t2, Q;
00717     static u_int32_t i, reachable;
00718 
00719     v1 = speed * direction;
00720 
00721     /*
00722      *  Only need to go from INDEX --> N for each one since links
00723      *  are symmetric.
00724      */
00725     for(i = index+1; i < NODES; i++) {
00726 
00727         m1 = &neighbor[i];
00728         n2 = &NodeList[i];
00729         m2 = &n2->neighbor[index];
00730 
00731         assert(i == m1->index);
00732         assert(m1->index == n2->index);
00733         assert(index == m2->index);
00734                 assert(m1->reachable == m2->reachable);
00735 
00736                 reachable = m1->reachable;
00737 
00738         /* ==================================================
00739            Determine Reachability
00740            ================================================== */
00741         {   vector d = position - n2->position;
00742 
00743             if(d.length() < RANGE) {
00744 #ifdef SANITY_CHECKS
00745                 if(TIME > 0.0 && m1->reachable == 0)
00746                     assert(RANGE - d.length() < ROUND_ERROR);
00747 #endif
00748                 m1->reachable = m2->reachable = 1;
00749             }
00750             // Boundary condition handled below.
00751             else {
00752 #ifdef SANITY_CHECKS
00753                 if(TIME > 0.0 && m1->reachable == 1)
00754                     assert(d.length() - RANGE < ROUND_ERROR);
00755 #endif
00756                 m1->reachable = m2->reachable = 0;
00757             }
00758 #ifdef DEBUG
00759                         fprintf(stdout, "# %.6f (%d, %d) %.2fm\n",
00760                                 TIME, index, m1->index, d.length());
00761 #endif
00762         }
00763 
00764         /* ==================================================
00765            Determine Next Event Time
00766            ================================================== */
00767         v2 = n2->speed * n2->direction;
00768 
00769         D = v2 - v1;
00770         B = n2->position - position;
00771 
00772         a = (D.X * D.X) + (D.Y * D.Y) + (D.Z * D.Z);
00773         b = 2 * ((D.X * B.X) + (D.Y * B.Y) + (D.Z * B.Z));
00774         c = (B.X * B.X) + (B.Y * B.Y) + (B.Z * B.Z) - (RANGE * RANGE);
00775 
00776         if(a == 0.0) {
00777             /*
00778              *  No Finite Solution
00779              */
00780             m1->time_transition= 0.0;
00781             m2->time_transition= 0.0;
00782             goto  next;
00783         }
00784 
00785         Q = b * b - 4 * a * c;
00786         if(Q < 0.0) {
00787             /*
00788              *  No real roots.
00789              */
00790             m1->time_transition = 0.0;
00791             m2->time_transition = 0.0;
00792             goto next;
00793         }
00794         Q = sqrt(Q);
00795 
00796         t1 = (-b + Q) / (2 * a);
00797         t2 = (-b - Q) / (2 * a);
00798 
00799         // Stupid Rounding/Boundary Cases
00800         if(t1 > 0.0 && t1 < ROUND_ERROR) t1 = 0.0;
00801         if(t1 < 0.0 && -t1 < ROUND_ERROR) t1 = 0.0;
00802         if(t2 > 0.0 && t2 < ROUND_ERROR) t2 = 0.0;
00803         if(t2 < 0.0 && -t2 < ROUND_ERROR) t2 = 0.0;
00804 
00805         if(t1 < 0.0 && t2 < 0.0) {
00806             /*
00807              *  No "future" time solution.
00808              */
00809             m1->time_transition = 0.0;
00810             m2->time_transition = 0.0;
00811             goto next;
00812         }
00813 
00814         /*
00815          * Boundary conditions.
00816          */
00817         if((t1 == 0.0 && t2 > 0.0) || (t2 == 0.0 && t1 > 0.0)) {
00818             m1->reachable = m2->reachable = 1;
00819             m1->time_transition = m2->time_transition = TIME + max(t1, t2);
00820         }
00821         else if((t1 == 0.0 && t2 < 0.0) || (t2 == 0.0 && t1 < 0.0)) {
00822             m1->reachable = m2->reachable = 0;
00823             m1->time_transition = m2->time_transition = 0.0;
00824         }
00825 
00826         /*
00827          * Non-boundary conditions.
00828          */
00829         else if(t1 > 0.0 && t2 > 0.0) {
00830             m1->time_transition = TIME + min(t1, t2);
00831             m2->time_transition = TIME + min(t1, t2);
00832         }
00833         else if(t1 > 0.0) {
00834             m1->time_transition = TIME + t1;
00835             m2->time_transition = TIME + t1;
00836         }
00837         else {
00838             m1->time_transition = TIME + t2;
00839             m2->time_transition = TIME + t2;
00840         }
00841 
00842         /* ==================================================
00843            Update the transition times for both NODEs.
00844            ================================================== */
00845         if(time_transition == 0.0 || (m1->time_transition &&
00846            time_transition > m1->time_transition)) {
00847             time_transition = m1->time_transition;
00848         }
00849         if(n2->time_transition == 0.0 || (m2->time_transition &&
00850            n2->time_transition > m2->time_transition)) {
00851             n2->time_transition = m2->time_transition;
00852         }
00853         next:
00854                 if(reachable != m1->reachable && TIME > 0.0) {
00855                         LinkChangeCount++;
00856                         link_changes++;
00857                         n2->link_changes++;
00858                 }
00859     }
00860 }
00861 
00862 void
00863 Node::Dump()
00864 {
00865     Neighbor *m;
00866     u_int32_t i;
00867 
00868     fprintf(stdout,
00869         "Node: %d\tpos: (%.2f, %.2f, %.2f) dst: (%.2f, %.2f, %.2f)\n",
00870         index, position.X, position.Y, position.Z,
00871         destination.X, destination.Y, destination.Z);
00872     fprintf(stdout, "\tdir: (%.2f, %.2f, %.2f) speed: %.2f\n",
00873         direction.X, direction.Y, direction.Z, speed);
00874     fprintf(stdout, "\tArrival: %.2f, Update: %.2f, Transition: %.2f\n",
00875         time_arrival, time_update, time_transition);
00876 
00877     for(i = 0; i < NODES; i++) {
00878         m = &neighbor[i];
00879         fprintf(stdout, "\tNeighbor: %d (%lx), Reachable: %d, Transition Time: %.2f\n",
00880             m->index, (long) m, m->reachable, m->time_transition);
00881     }
00882 }
00883 
00884 
00885 /* ======================================================================
00886    Dijkstra's Shortest Path Algoritm
00887    ====================================================================== */
00888 void dumpall()
00889 {
00890     u_int32_t i;
00891 
00892     fprintf(stdout, "\nTime: %.2f\n", TIME);
00893 
00894     for(i = 0; i < NODES; i++) {
00895         NodeList[i].Dump();
00896     }
00897 }
00898 
00899 void
00900 ComputeW()
00901 {
00902     u_int32_t i, j;
00903     u_int32_t *W = D2;
00904 
00905     memset(W, '\xff', sizeof(int) * NODES * NODES);
00906 
00907     for(i = 0; i < NODES; i++) {
00908         for(j = i; j < NODES; j++) {
00909             Neighbor *m = &NodeList[i].neighbor[j];
00910             if(i == j)
00911                 W[i*NODES + j] = W[j*NODES + i] = 0;
00912             else
00913                 W[i*NODES + j] = W[j*NODES + i] = m->reachable ? 1 : RTG_INFINITY;  
00914         }
00915     }
00916 }
00917 
00918 void
00919 floyd_warshall()
00920 {
00921     u_int32_t i, j, k;
00922 
00923     ComputeW(); // the connectivity matrix
00924 
00925     for(i = 0; i < NODES; i++) {
00926         for(j = 0; j < NODES; j++) {
00927             for(k = 0; k < NODES; k++) {
00928                 D2[j*NODES + k] = min(D2[j*NODES + k], D2[j*NODES + i] + D2[i*NODES + k]);
00929             }
00930         }
00931     }
00932 
00933 #ifdef SANITY_CHECKS
00934     for(i = 0; i < NODES; i++)
00935         for(j = 0; j < NODES; j++) {
00936             assert(D2[i*NODES + j] == D2[j*NODES + i]);
00937             assert(D2[i*NODES + j] <= RTG_INFINITY);
00938         }
00939 #endif
00940 }
00941 
00942 
00943 /*
00944  *  Write the actual GOD entries to a TCL script.
00945  */
00946 void
00947 show_diffs()
00948 {
00949     u_int32_t i, j;
00950 
00951     for(i = 0; i < NODES; i++) {
00952         for(j = i + 1; j < NODES; j++) {
00953             if(D1[i*NODES + j] != D2[i*NODES + j]) {
00954 
00955                 if(D2[i*NODES + j] == RTG_INFINITY)
00956                     DestUnreachableCount++;
00957 
00958                                 if(TIME > 0.0) {
00959                                         RouteChangeCount++;
00960                                         NodeList[i].route_changes++;
00961                                         NodeList[j].route_changes++;
00962                                 }
00963 
00964                 if(TIME == 0.0) {
00965                     fprintf(stdout, GOD_FORMAT2,
00966                         i, j, D2[i*NODES + j]);
00967 #ifdef SHOW_SYMMETRIC_PAIRS
00968                     fprintf(stdout, GOD_FORMAT2,
00969                         j, i, D2[j*NODES + i]);
00970 #endif
00971                 }
00972                 else {
00973                     fprintf(stdout, GOD_FORMAT, 
00974                         TIME, i, j, D2[i*NODES + j]);
00975 #ifdef SHOW_SYMMETRIC_PAIRS
00976                     fprintf(stdout, GOD_FORMAT, 
00977                         TIME, j, i, D2[j*NODES + i]);
00978 #endif
00979                 }
00980             }
00981         }
00982     }
00983 
00984     memcpy(D1, D2, sizeof(int) * NODES * NODES);
00985 }
00986 
00987 
00988 void
00989 show_routes()
00990 {
00991     u_int32_t i, j;
00992 
00993     fprintf(stdout, "#\n# TIME: %.12f\n#\n", TIME);
00994     for(i = 0; i < NODES; i++) {
00995         fprintf(stdout, "# %2d) ", i);
00996         for(j = 0; j < NODES; j++)
00997             fprintf(stdout, "%3d ", D2[i*NODES + j] & 0xff);
00998         fprintf(stdout, "\n");
00999     }
01000     fprintf(stdout, "#\n");
01001 }
01002 
01003 void
01004 show_counters()
01005 {
01006     u_int32_t i;
01007 
01008     fprintf(stdout, "#\n# Destination Unreachables: %d\n#\n",
01009         DestUnreachableCount);
01010     fprintf(stdout, "# Route Changes: %d\n#\n", RouteChangeCount);
01011         fprintf(stdout, "# Link Changes: %d\n#\n", LinkChangeCount);
01012         fprintf(stdout, "# Node | Route Changes | Link Changes\n");
01013     for(i = 0; i < NODES; i++)
01014         fprintf(stdout, "# %4d |          %4d |         %4d\n",
01015                         i, NodeList[i].route_changes,
01016                         NodeList[i].link_changes);
01017     fprintf(stdout, "#\n");
01018 }
01019 

Generated on Tue Mar 6 16:47:51 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6