setdest2.cc

Go to the documentation of this file.
00001 /*
00002  * a simplified version of setdest which bypass the computation of route length.
00003  */
00004 
00005 extern "C" {
00006 #include <assert.h>
00007 #include <fcntl.h>
00008 #include <math.h>
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <sys/time.h>
00013 #include <sys/types.h>
00014 #include <sys/uio.h>
00015 #include <unistd.h>
00016 #if !defined(sun) && !defined(__CYGWIN__)
00017 #include <err.h>
00018 #endif
00019 };
00020 #include "../../../rng.h"
00021 
00022 #include "setdest.h"
00023 
00024 
00025 // #define      DEBUG
00026 #define     SANITY_CHECKS
00027 //#define       SHOW_SYMMETRIC_PAIRS
00028 
00029 
00030 #define GOD_FORMAT  "$ns_ at %.12f \"$god_ set-dist %d %d %d\"\n"
00031 #define GOD_FORMAT2 "$god_ set-dist %d %d %d\n"
00032 #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n"
00033 #define NODE_FORMAT2    "$node_(%d) setdest %.12f %.12f %.12f\n"
00034 #define NODE_FORMAT3    "$node_(%d) set %c_ %.12f\n"
00035 
00036 #define     INFINITY    0x00ffffff
00037 #define     min(x,y)    ((x) < (y) ? (x) : (y))
00038 #define     max(x,y)    ((x) > (y) ? (x) : (y))
00039 #define     ROUND_ERROR 1e-9
00040 
00041 static int count = 0;
00042 
00043 /* ======================================================================
00044    Function Prototypes
00045    ====================================================================== */
00046 void        usage(char**);
00047 void        init(void);
00048 double      uniform(void);
00049 
00050 void        dumpall(void);
00051 void        ComputeW(void);
00052 void        floyd_warshall(void);
00053 
00054 void        show_diffs(void);
00055 void        show_routes(void);
00056 void        show_counters(void);
00057 
00058 
00059 /* ======================================================================
00060    Global Variables
00061    ====================================================================== */
00062 const double    RANGE = 250.0;      // transmitter range in meters
00063 double      TIME = 0.0;     // my clock;
00064 double      MAXTIME = 0.0;      // duration of simulation
00065 
00066 double      MAXX = 0.0;
00067 double      MAXY = 0.0;
00068 double      MAXSPEED = 0.0;
00069 double      PAUSE = 0.0;
00070 u_int32_t   NODES = 0;
00071 u_int32_t   RouteChangeCount = 0;
00072 u_int32_t       LinkChangeCount = 0;
00073 u_int32_t   DestUnreachableCount = 0;
00074 
00075 Node        *NodeList = 0;
00076 u_int32_t   *D1 = 0;
00077 u_int32_t   *D2 = 0;
00078 
00079 
00080 /* ======================================================================
00081    Random Number Generation
00082    ====================================================================== */
00083 #define M       2147483647L
00084 #define INVERSE_M   ((double)4.656612875e-10)
00085 
00086 char random_state[32];
00087 RNG *rng;
00088 
00089 double
00090 uniform()
00091 {
00092         count++;
00093         return rng->uniform_double() ;
00094 } 
00095 
00096 
00097 /* ======================================================================
00098    Misc Functions...
00099    ====================================================================== */
00100 void
00101 usage(char **argv)
00102 {
00103     fprintf(stderr,
00104         "\nusage: %s\t-n <nodes> -p <pause time> -s <max speed>\n",
00105         argv[0]);
00106     fprintf(stderr,
00107         "\t\t-t <simulation time> -x <max X> -y <max Y>\n\n");
00108 }
00109 
00110 void
00111 init()
00112 {
00113     /*
00114      * Initialized the Random Number Generation
00115      */
00116 "
00117     /*"
00118      * Allocate memory for globals
00119      */
00120     NodeList = new Node[NODES];
00121     if(NodeList == 0) {
00122         perror("new");
00123         exit(1);
00124     }
00125 
00126     D1 = new u_int32_t[NODES * NODES];
00127     if(D1 == 0) {
00128         perror("new");
00129         exit(1);
00130     }
00131     memset(D1, '\xff', sizeof(u_int32_t) * NODES * NODES);
00132 
00133     D2 = new u_int32_t[NODES * NODES];
00134     if(D2 == 0) {
00135         perror("new");
00136         exit(1);
00137     }
00138     memset(D2, '\xff', sizeof(u_int32_t) * NODES * NODES);
00139 }
00140 
00141 extern "C" char *optarg;
00142 
00143 int
00144 main(int argc, char **argv)
00145 {
00146     char ch;
00147 
00148     while ((ch = getopt(argc, argv, "n:p:s:t:x:y:i:o:")) != EOF) {       
00149 
00150         switch (ch) { 
00151 
00152         case 'n':
00153             NODES = atoi(optarg);
00154             break;
00155 
00156         case 'p':
00157             PAUSE = atof(optarg);
00158             break;
00159 
00160         case 's':
00161             MAXSPEED = atof(optarg);
00162             break;
00163 
00164         case 't':
00165             MAXTIME = atof(optarg);
00166             break;
00167 
00168         case 'x':
00169             MAXX = atof(optarg);
00170             break;
00171 
00172         case 'y':
00173             MAXY = atof(optarg);
00174             break;
00175 
00176         default:
00177             usage(argv);
00178             exit(1);
00179         }
00180     }
00181 
00182     if(MAXX == 0.0 || MAXY == 0.0 || NODES == 0 || MAXTIME == 0.0) {
00183         usage(argv);
00184         exit(1);
00185     }
00186 
00187     fprintf(stdout, "#\n# nodes: %d, pause: %.2f, max speed: %.2f  max x = %.2f, max y: %.2f\n#\n",
00188         NODES , PAUSE, MAXSPEED, MAXX, MAXY);
00189 
00190     // The more portable solution for random number generation
00191     rng = new RNG;
00192     rng->set_seed(RNG::HEURISTIC_SEED_SOURCE); 
00193 
00194     init();
00195 
00196     while(TIME <= MAXTIME) {
00197         double nexttime = 0.0;
00198         u_int32_t i;
00199 
00200         for(i = 0; i < NODES; i++) {
00201             NodeList[i].Update();
00202         }
00203 /*
00204         for(i = 0; i < NODES; i++) {
00205             NodeList[i].UpdateNeighbors();
00206         }
00207 */
00208         for(i = 0; i < NODES; i++) {
00209             Node *n = &NodeList[i];
00210     
00211             if(n->time_transition > 0.0) {
00212                 if(nexttime == 0.0)
00213                     nexttime = n->time_transition;
00214                 else
00215                     nexttime = min(nexttime, n->time_transition);
00216             }
00217 
00218             if(n->time_arrival > 0.0) {
00219                 if(nexttime == 0.0)
00220                     nexttime = n->time_arrival;
00221                 else
00222                     nexttime = min(nexttime, n->time_arrival);
00223             }
00224         }
00225 
00226         // floyd_warshall();
00227 
00228 #ifdef DEBUG
00229         show_routes();
00230 #endif
00231 
00232         // show_diffs();
00233 
00234 #ifdef DEBUG
00235         dumpall();
00236 #endif
00237 
00238         assert(nexttime > TIME + ROUND_ERROR);
00239         TIME = nexttime;
00240     }
00241 
00242     show_counters();
00243 
00244     int of;
00245     if ((of = open(".rand_state",O_WRONLY | O_TRUNC | O_CREAT, 0777)) < 0) {
00246       fprintf(stderr, "open rand state\n");
00247       exit(-1);
00248       }
00249     for (unsigned int i = 0; i < sizeof(random_state); i++)
00250           random_state[i] = 0xff & (int) (uniform() * 256);
00251     if (write(of,random_state, sizeof(random_state)) < 0) {
00252       fprintf(stderr, "writing rand state\n");
00253       exit(-1);
00254       }
00255     close(of);
00256 }
00257 
00258 
00259 /* ======================================================================
00260    Node Class Functions
00261    ====================================================================== */
00262 u_int32_t Node::NodeIndex = 0;
00263 
00264 Node::Node()
00265 {
00266     u_int32_t i;
00267 
00268     index = NodeIndex++;
00269 
00270     //if(index == 0)
00271     //  return;
00272 
00273     route_changes = 0;
00274         link_changes = 0;
00275 
00276         /*
00277          * For the first PAUSE seconds of the simulation, all nodes
00278          * are stationary.
00279          */
00280     time_arrival = TIME + PAUSE;
00281     time_update = TIME;
00282     time_transition = 0.0;
00283 
00284     position.X = position.Y = position.Z = 0.0;
00285     destination.X = destination.Y = destination.Z = 0.0;
00286     direction.X = direction.Y = direction.Z = 0.0;
00287     speed = 0.0;
00288 
00289     RandomPosition();
00290 
00291     fprintf(stdout, NODE_FORMAT3, index, 'X', position.X);
00292     fprintf(stdout, NODE_FORMAT3, index, 'Y', position.Y);
00293     fprintf(stdout, NODE_FORMAT3, index, 'Z', position.Z);
00294 
00295     neighbor = new Neighbor[NODES];
00296     if(neighbor == 0) {
00297         perror("new");
00298         exit(1);
00299     }
00300 
00301     for(i = 0; i < NODES; i++) {
00302         neighbor[i].index = i;
00303         neighbor[i].reachable = (index == i) ? 1 : 0;
00304         neighbor[i].time_transition = 0.0;
00305     }
00306 }
00307 
00308 
00309 
00310 void
00311 Node::RandomPosition()
00312 {
00313         position.X = uniform() * MAXX;
00314         position.Y = uniform() * MAXY;
00315     position.Z = 0.0;
00316 }
00317 
00318 
00319 void
00320 Node::RandomDestination()
00321 {
00322         destination.X = uniform() * MAXX;
00323         destination.Y = uniform() * MAXY;
00324     destination.Z = 0.0;
00325     assert(destination != position);
00326 }
00327 
00328 void
00329 Node::RandomSpeed()
00330 {
00331         speed = uniform() * MAXSPEED;
00332 
00333     assert(speed != 0.0);
00334 }
00335 
00336 
00337 void
00338 Node::Update()
00339 {
00340     position += (speed * (TIME - time_update)) * direction;
00341 
00342     if(TIME == time_arrival) {
00343         vector v;
00344 
00345         if(speed == 0.0 || PAUSE == 0.0) {
00346 
00347                         RandomDestination();
00348             RandomSpeed();
00349 
00350             v = destination - position;
00351             direction = v / v.length();
00352             time_arrival = TIME + v.length() / speed;
00353         }
00354         else {
00355 
00356             destination = position;
00357             speed = 0.0;
00358 
00359             time_arrival = TIME + PAUSE;
00360         }
00361 
00362         fprintf(stdout, NODE_FORMAT,
00363             TIME, index, destination.X, destination.Y, speed);
00364     
00365     }
00366 
00367     time_update = TIME;
00368     time_transition = 0.0;
00369 }
00370 
00371 
00372 void
00373 Node::UpdateNeighbors()
00374 {
00375     static Node *n2;
00376     static Neighbor *m1, *m2;
00377     static vector D, B, v1, v2;
00378     static double a, b, c, t1, t2, Q;
00379     static u_int32_t i, reachable;
00380 
00381     v1 = speed * direction;
00382 
00383     /*
00384      *  Only need to go from INDEX --> N for each one since links
00385      *  are symmetric.
00386      */
00387     for(i = index+1; i < NODES; i++) {
00388 
00389         m1 = &neighbor[i];
00390         n2 = &NodeList[i];
00391         m2 = &n2->neighbor[index];
00392 
00393         assert(i == m1->index);
00394         assert(m1->index == n2->index);
00395         assert(index == m2->index);
00396                 assert(m1->reachable == m2->reachable);
00397 
00398                 reachable = m1->reachable;
00399 
00400         /* ==================================================
00401            Determine Reachability
00402            ================================================== */
00403         {   vector d = position - n2->position;
00404 
00405             if(d.length() < RANGE) {
00406 #ifdef SANITY_CHECKS
00407                 if(TIME > 0.0 && m1->reachable == 0)
00408                     assert(RANGE - d.length() < ROUND_ERROR);
00409 #endif
00410                 m1->reachable = m2->reachable = 1;
00411             }
00412             // Boundary condition handled below.
00413             else {
00414 #ifdef SANITY_CHECKS
00415                 if(TIME > 0.0 && m1->reachable == 1)
00416                     assert(d.length() - RANGE < ROUND_ERROR);
00417 #endif
00418                 m1->reachable = m2->reachable = 0;
00419             }
00420 #ifdef DEBUG
00421                         fprintf(stdout, "# %.6f (%d, %d) %.2fm\n",
00422                                 TIME, index, m1->index, d.length());
00423 #endif
00424         }
00425 
00426         /* ==================================================
00427            Determine Next Event Time
00428            ================================================== */
00429         v2 = n2->speed * n2->direction;
00430 
00431         D = v2 - v1;
00432         B = n2->position - position;
00433 
00434         a = (D.X * D.X) + (D.Y * D.Y) + (D.Z * D.Z);
00435         b = 2 * ((D.X * B.X) + (D.Y * B.Y) + (D.Z * B.Z));
00436         c = (B.X * B.X) + (B.Y * B.Y) + (B.Z * B.Z) - (RANGE * RANGE);
00437 
00438         if(a == 0.0) {
00439             /*
00440              *  No Finite Solution
00441              */
00442             m1->time_transition= 0.0;
00443             m2->time_transition= 0.0;
00444             goto  next;
00445         }
00446 
00447         Q = b * b - 4 * a * c;
00448         if(Q < 0.0) {
00449             /*
00450              *  No real roots.
00451              */
00452             m1->time_transition = 0.0;
00453             m2->time_transition = 0.0;
00454             goto next;
00455         }
00456         Q = sqrt(Q);
00457 
00458         t1 = (-b + Q) / (2 * a);
00459         t2 = (-b - Q) / (2 * a);
00460 
00461         // Stupid Rounding/Boundary Cases
00462         if(t1 > 0.0 && t1 < ROUND_ERROR) t1 = 0.0;
00463         if(t1 < 0.0 && -t1 < ROUND_ERROR) t1 = 0.0;
00464         if(t2 > 0.0 && t2 < ROUND_ERROR) t2 = 0.0;
00465         if(t2 < 0.0 && -t2 < ROUND_ERROR) t2 = 0.0;
00466 
00467         if(t1 < 0.0 && t2 < 0.0) {
00468             /*
00469              *  No "future" time solution.
00470              */
00471             m1->time_transition = 0.0;
00472             m2->time_transition = 0.0;
00473             goto next;
00474         }
00475 
00476         /*
00477          * Boundary conditions.
00478          */
00479         if((t1 == 0.0 && t2 > 0.0) || (t2 == 0.0 && t1 > 0.0)) {
00480             m1->reachable = m2->reachable = 1;
00481             m1->time_transition = m2->time_transition = TIME + max(t1, t2);
00482         }
00483         else if((t1 == 0.0 && t2 < 0.0) || (t2 == 0.0 && t1 < 0.0)) {
00484             m1->reachable = m2->reachable = 0;
00485             m1->time_transition = m2->time_transition = 0.0;
00486         }
00487 
00488         /*
00489          * Non-boundary conditions.
00490          */
00491         else if(t1 > 0.0 && t2 > 0.0) {
00492             m1->time_transition = TIME + min(t1, t2);
00493             m2->time_transition = TIME + min(t1, t2);
00494         }
00495         else if(t1 > 0.0) {
00496             m1->time_transition = TIME + t1;
00497             m2->time_transition = TIME + t1;
00498         }
00499         else {
00500             m1->time_transition = TIME + t2;
00501             m2->time_transition = TIME + t2;
00502         }
00503 
00504         /* ==================================================
00505            Update the transition times for both NODEs.
00506            ================================================== */
00507         if(time_transition == 0.0 || (m1->time_transition &&
00508            time_transition > m1->time_transition)) {
00509             time_transition = m1->time_transition;
00510         }
00511         if(n2->time_transition == 0.0 || (m2->time_transition &&
00512            n2->time_transition > m2->time_transition)) {
00513             n2->time_transition = m2->time_transition;
00514         }
00515         next:
00516                 if(reachable != m1->reachable && TIME > 0.0) {
00517                         LinkChangeCount++;
00518                         link_changes++;
00519                         n2->link_changes++;
00520                 }
00521     }
00522 }
00523 
00524 void
00525 Node::Dump()
00526 {
00527     Neighbor *m;
00528     u_int32_t i;
00529 
00530     fprintf(stdout,
00531         "Node: %d\tpos: (%.2f, %.2f, %.2f) dst: (%.2f, %.2f, %.2f)\n",
00532         index, position.X, position.Y, position.Z,
00533         destination.X, destination.Y, destination.Z);
00534     fprintf(stdout, "\tdir: (%.2f, %.2f, %.2f) speed: %.2f\n",
00535         direction.X, direction.Y, direction.Z, speed);
00536     fprintf(stdout, "\tArrival: %.2f, Update: %.2f, Transition: %.2f\n",
00537         time_arrival, time_update, time_transition);
00538 
00539     for(i = 0; i < NODES; i++) {
00540         m = &neighbor[i];
00541         fprintf(stdout, "\tNeighbor: %d (%x), Reachable: %d, Transition Time: %.2f\n",
00542             m->index, (int) m, m->reachable, m->time_transition);
00543     }
00544 }
00545 
00546 
00547 /* ======================================================================
00548    Dijkstra's Shortest Path Algoritm
00549    ====================================================================== */
00550 void dumpall()
00551 {
00552     u_int32_t i;
00553 
00554     fprintf(stdout, "\nTime: %.2f\n", TIME);
00555 
00556     for(i = 0; i < NODES; i++) {
00557         NodeList[i].Dump();
00558     }
00559 }
00560 
00561 void
00562 ComputeW()
00563 {
00564     u_int32_t i, j;
00565     u_int32_t *W = D2;
00566 
00567     memset(W, '\xff', sizeof(int) * NODES * NODES);
00568 
00569     for(i = 0; i < NODES; i++) {
00570         for(j = i; j < NODES; j++) {
00571             Neighbor *m = &NodeList[i].neighbor[j];
00572             if(i == j)
00573                 W[i*NODES + j] = W[j*NODES + i] = 0;
00574             else
00575                 W[i*NODES + j] = W[j*NODES + i] = m->reachable ? 1 : INFINITY;  
00576         }
00577     }
00578 }
00579 
00580 void
00581 floyd_warshall()
00582 {
00583     u_int32_t i, j, k;
00584 
00585     ComputeW(); // the connectivity matrix
00586 
00587     for(i = 0; i < NODES; i++) {
00588         for(j = 0; j < NODES; j++) {
00589             for(k = 0; k < NODES; k++) {
00590                 D2[j*NODES + k] = min(D2[j*NODES + k], D2[j*NODES + i] + D2[i*NODES + k]);
00591             }
00592         }
00593     }
00594 
00595 #ifdef SANITY_CHECKS
00596     for(i = 0; i < NODES; i++)
00597         for(j = 0; j < NODES; j++) {
00598             assert(D2[i*NODES + j] == D2[j*NODES + i]);
00599             assert(D2[i*NODES + j] <= INFINITY);
00600         }
00601 #endif
00602 }
00603 
00604 
00605 /*
00606  *  Write the actual GOD entries to a TCL script.
00607  */
00608 void
00609 show_diffs()
00610 {
00611     u_int32_t i, j;
00612 
00613     for(i = 0; i < NODES; i++) {
00614         for(j = i + 1; j < NODES; j++) {
00615             if(D1[i*NODES + j] != D2[i*NODES + j]) {
00616 
00617                 if(D2[i*NODES + j] == INFINITY)
00618                     DestUnreachableCount++;
00619 
00620                                 if(TIME > 0.0) {
00621                                         RouteChangeCount++;
00622                                         NodeList[i].route_changes++;
00623                                         NodeList[j].route_changes++;
00624                                 }
00625 
00626                 if(TIME == 0.0) {
00627                     fprintf(stdout, GOD_FORMAT2,
00628                         i, j, D2[i*NODES + j]);
00629 #ifdef SHOW_SYMMETRIC_PAIRS
00630                     fprintf(stdout, GOD_FORMAT2,
00631                         j, i, D2[j*NODES + i]);
00632 #endif
00633                 }
00634                 else {
00635                     fprintf(stdout, GOD_FORMAT, 
00636                         TIME, i, j, D2[i*NODES + j]);
00637 #ifdef SHOW_SYMMETRIC_PAIRS
00638                     fprintf(stdout, GOD_FORMAT, 
00639                         TIME, j, i, D2[j*NODES + i]);
00640 #endif
00641                 }
00642             }
00643         }
00644     }
00645 
00646     memcpy(D1, D2, sizeof(int) * NODES * NODES);
00647 }
00648 
00649 
00650 void
00651 show_routes()
00652 {
00653     u_int32_t i, j;
00654 
00655     fprintf(stdout, "#\n# TIME: %.12f\n#\n", TIME);
00656     for(i = 0; i < NODES; i++) {
00657         fprintf(stdout, "# %2d) ", i);
00658         for(j = 0; j < NODES; j++)
00659             fprintf(stdout, "%3d ", D2[i*NODES + j] & 0xff);
00660         fprintf(stdout, "\n");
00661     }
00662     fprintf(stdout, "#\n");
00663 }
00664 
00665 void
00666 show_counters()
00667 {
00668     u_int32_t i;
00669 
00670     fprintf(stdout, "#\n# Destination Unreachables: %d\n#\n",
00671         DestUnreachableCount);
00672     fprintf(stdout, "# Route Changes: %d\n#\n", RouteChangeCount);
00673         fprintf(stdout, "# Link Changes: %d\n#\n", LinkChangeCount);
00674         fprintf(stdout, "# Node | Route Changes | Link Changes\n");
00675     for(i = 0; i < NODES; i++)
00676         fprintf(stdout, "# %4d |          %4d |         %4d\n",
00677                         i, NodeList[i].route_changes,
00678                         NodeList[i].link_changes);
00679     fprintf(stdout, "#\n");
00680 }
00681 

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