00001 extern "C" {
00002 #include <assert.h>
00003 #include <fcntl.h>
00004 #include <math.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <sys/time.h>
00009 #include <sys/types.h>
00010 #include <sys/uio.h>
00011 #include <unistd.h>
00012
00013 };
00014 #include "../../../tools/rng.h"
00015 #include "setdest.h"
00016
00017
00018 #define SANITY_CHECKS
00019
00020
00021
00022 #define GOD_FORMAT "$ns_ at %.12f \"$god_ set-dist %d %d %d\"\n"
00023 #define GOD_FORMAT2 "$god_ set-dist %d %d %d\n"
00024 #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n"
00025 #define NODE_FORMAT2 "$node_(%d) setdest %.12f %.12f %.12f\n"
00026 #define NODE_FORMAT3 "$node_(%d) set %c_ %.12f\n"
00027
00028 #undef INFINITY
00029 #define INFINITY 0x00ffffff
00030 #define min(x,y) ((x) < (y) ? (x) : (y))
00031 #define max(x,y) ((x) > (y) ? (x) : (y))
00032 #define ROUND_ERROR 1e-9
00033
00034 static int count = 0;
00035
00036
00037
00038
00039 void usage(char**);
00040 void init(void);
00041 double uniform(void);
00042
00043 void dumpall(void);
00044 void ComputeW(void);
00045 void floyd_warshall(void);
00046
00047 void show_diffs(void);
00048 void show_routes(void);
00049 void show_counters(void);
00050
00051
00052
00053
00054
00055 double RANGE = 250.0;
00056 double TIME = 0.0;
00057 double MAXTIME = 0.0;
00058
00059 double MAXX = 0.0;
00060 double MAXY = 0.0;
00061 double MAXSPEED = 0.0;
00062 double PAUSE = 0.0;
00063 u_int32_t NODES = 0;
00064 u_int32_t RouteChangeCount = 0;
00065 u_int32_t LinkChangeCount = 0;
00066 u_int32_t DestUnreachableCount = 0;
00067
00068 Node *NodeList = 0;
00069 u_int32_t *D1 = 0;
00070 u_int32_t *D2 = 0;
00071
00072 FILE *in_file;
00073 FILE *out_file;
00074
00075
00076
00077
00078
00079 #define M 2147483647L
00080 #define INVERSE_M ((double)4.656612875e-10)
00081
00082 char random_state[32];
00083 RNG *rng;
00084
00085 double
00086 uniform()
00087 {
00088 count++;
00089 return rng->uniform_double();
00090 }
00091
00092
00093
00094
00095
00096 void
00097 usage(char **argv)
00098 {
00099 fprintf(stderr,
00100 "\nusage: %s\t[-n <nodes>] \n",
00101 argv[0]);
00102 fprintf(stderr,
00103 "\t\t[-t <simulation time>]\n");
00104 fprintf(stderr,
00105 "\t\t-i <input_file> -o <output file>\n");
00106 fprintf(stderr,
00107 "\t\t #nodes, max time, and range read from scenario file if possible\n\n");
00108
00109 }
00110
00111 void
00112 init()
00113 {
00114
00115
00116
00117
00118
00119
00120
00121 NodeList = new Node[NODES];
00122 if(NodeList == 0) {
00123 perror("new");
00124 exit(1);
00125 }
00126
00127 D1 = new u_int32_t[NODES * NODES];
00128 if(D1 == 0) {
00129 perror("new");
00130 exit(1);
00131 }
00132 memset(D1, '\xff', sizeof(u_int32_t) * NODES * NODES);
00133
00134 D2 = new u_int32_t[NODES * NODES];
00135 if(D2 == 0) {
00136 perror("new");
00137 exit(1);
00138 }
00139 memset(D2, '\xff', sizeof(u_int32_t) * NODES * NODES);
00140 }
00141
00142 void
00143 OpenAndReadHeader(char *in_filename, char *out_filename)
00144
00145
00146 {
00147 char buf[256];
00148
00149 in_file = fopen(in_filename,"r");
00150 out_file = fopen(out_filename,"w");
00151
00152 if (NULL == in_file)
00153 fprintf(stderr, "*** can't open inputfile %s",in_filename);
00154 if (NULL == out_file)
00155 fprintf(stderr,"can't open outputfile %s",out_filename);
00156
00157 while (!feof(in_file)) {
00158
00159 *buf = fgetc(in_file);
00160 ungetc(*buf,in_file);
00161 if (*buf != '#') break;
00162
00163 fgets(buf, sizeof(buf), in_file);
00164
00165
00166 sscanf(buf, "# nodes: %d, max time: %lf", &NODES, &MAXTIME);
00167 sscanf(buf, "# nominal range: %lf", &RANGE);
00168
00169 fprintf(out_file, "%s", buf);
00170 }
00171 NODES += 1;
00172 fflush(out_file);
00173 }
00174
00175 void
00176 ReadInMovementPattern()
00177 {
00178 char buf[256];
00179 u_int n;
00180 double x,y,z,t,s;
00181 struct setdest *setdest;
00182
00183 while (!feof(in_file)) {
00184
00185 fgets(buf, sizeof(buf), in_file);
00186 fprintf(out_file, "%s", buf);
00187 if (*buf == '#') continue;
00188 if (*buf == '\n') continue;
00189
00190
00191 if (2 == sscanf(buf,"$node_(%d) set Z_ %lf", &n, &z))
00192 {
00193 assert(n < NODES);
00194 NodeList[n].position.Z = z;
00195 }
00196 else if (2 == sscanf(buf,"$node_(%d) set X_ %lf", &n, &x))
00197 {
00198 assert(n < NODES);
00199 NodeList[n].position.X = x;
00200 }
00201 else if (2 == sscanf(buf,"$node_(%d) set Y_ %lf", &n, &y))
00202 {
00203 assert(n < NODES);
00204 NodeList[n].position.Y = y;
00205 }
00206 else if (5 == sscanf(buf,"$ns_ at %lf \"$node_(%d) setdest %lf %lf %lf\"",
00207 &t, &n, &x, &y, &s))
00208 {
00209 assert(n < NODES);
00210 assert(t <= MAXTIME);
00211 setdest = (struct setdest *)malloc(sizeof(*setdest));
00212 assert(setdest);
00213 setdest->X = x; setdest->Y = y; setdest->Z = 0;
00214 setdest->time = t;
00215 setdest->speed = s;
00216 if (NodeList[n].traj.lh_first
00217 && t > NodeList[n].traj.lh_first->time)
00218 {
00219 printf("setdest's must be in anti-chronological order in input file!\n");
00220 printf("failed on node %d\n",n);
00221 exit(-1);
00222 }
00223 LIST_INSERT_HEAD(&NodeList[n].traj,setdest,traj);
00224 }
00225 else
00226 {
00227 printf("unparsable line: '%s'", buf);
00228 continue;
00229 }
00230 }
00231 fflush(out_file);
00232 }
00233
00234 extern "C" char *optarg;
00235 int
00236 main(int argc, char **argv)
00237 {
00238 char ch;
00239 char *in_filename = NULL;
00240 char *out_filename = NULL;
00241
00242 while ((ch = getopt(argc, argv, "n:t:i:o:")) != EOF) {
00243
00244 switch (ch) {
00245
00246 case 'n':
00247 NODES = atoi(optarg) + 1;
00248 break;
00249
00250 case 't':
00251 MAXTIME = atof(optarg);
00252 break;
00253
00254 case 'i':
00255 in_filename = optarg;
00256 break;
00257
00258 case 'o':
00259 out_filename = optarg;
00260 break;
00261
00262 default:
00263 usage(argv);
00264 exit(1);
00265 }
00266 }
00267
00268 if (NULL == in_filename || NULL == out_filename) {
00269 usage(argv);
00270 exit(1);
00271 }
00272
00273 OpenAndReadHeader(in_filename, out_filename);
00274
00275 if(NODES == 0 || MAXTIME == 0.0) {
00276 usage(argv);
00277 exit(1);
00278 }
00279
00280 rng = new RNG;
00281 rng->set_seed(RNG::HEURISTIC_SEED_SOURCE);
00282 init();
00283
00284 ReadInMovementPattern();
00285
00286 while(TIME <= MAXTIME) {
00287 double nexttime = 0.0;
00288 u_int32_t i;
00289
00290 for(i = 1; i < NODES; i++) {
00291 NodeList[i].Update();
00292 }
00293
00294 for(i = 1; i < NODES; i++) {
00295 NodeList[i].UpdateNeighbors();
00296 }
00297
00298 for(i = 1; i < NODES; i++) {
00299 Node *n = &NodeList[i];
00300
00301 if(n->time_transition > 0.0) {
00302 if(nexttime == 0.0)
00303 nexttime = n->time_transition;
00304 else
00305 nexttime = min(nexttime, n->time_transition);
00306 }
00307
00308 if(n->time_arrival > 0.0) {
00309 if(nexttime == 0.0)
00310 nexttime = n->time_arrival;
00311 else
00312 nexttime = min(nexttime, n->time_arrival);
00313 }
00314 }
00315
00316 floyd_warshall();
00317
00318 #ifdef DEBUG
00319 show_routes();
00320 #endif
00321
00322 show_diffs();
00323
00324 #ifdef DEBUG
00325 dumpall();
00326 #endif
00327
00328 if (nexttime <= TIME + ROUND_ERROR)
00329 TIME = MAXTIME + 1;
00330 else
00331 TIME = nexttime;
00332 #ifdef OLD
00333 assert(nexttime > TIME + ROUND_ERROR);
00334 TIME = nexttime;
00335 #endif
00336
00337 }
00338
00339 show_counters();
00340
00341 int of;
00342 if ((of = open(".rand_state",O_WRONLY | O_TRUNC | O_CREAT, 0777)) < 0)
00343 fprintf(stderr,"open rand state");
00344 for (unsigned int i = 0; i < sizeof(random_state); i++)
00345 random_state[i] = 0xff & (int) (uniform() * 256);
00346 if (write(of,random_state, sizeof(random_state)) < 0)
00347 fprintf(stderr,"writing rand state");
00348 close(of);
00349 }
00350
00351
00352
00353
00354
00355 u_int32_t Node::NodeIndex = 0;
00356
00357 Node::Node()
00358 {
00359 u_int32_t i;
00360
00361 index = NodeIndex++;
00362
00363 if(index == 0)
00364 return;
00365
00366 route_changes = 0;
00367 link_changes = 0;
00368
00369
00370
00371
00372
00373 time_arrival = TIME;
00374 time_update = TIME;
00375 time_transition = 0.0;
00376
00377 position.X = position.Y = position.Z = 0.0;
00378 destination.X = destination.Y = destination.Z = 0.0;
00379 direction.X = direction.Y = direction.Z = 0.0;
00380 speed = 0.0;
00381
00382 neighbor = new Neighbor[NODES];
00383 if(neighbor == 0) {
00384 perror("new");
00385 exit(1);
00386 }
00387
00388 LIST_INIT(&traj);
00389
00390 for(i = 1; i < NODES; i++) {
00391 neighbor[i].index = i;
00392 neighbor[i].reachable = (index == i) ? 1 : 0;
00393 neighbor[i].time_transition = 0.0;
00394 }
00395 }
00396
00397
00398
00399 void
00400 Node::RandomPosition()
00401 {
00402 position.X = uniform() * MAXX;
00403 position.Y = uniform() * MAXY;
00404 position.Z = 0.0;
00405 }
00406
00407
00408 void
00409 Node::RandomDestination()
00410 {
00411 destination.X = uniform() * MAXX;
00412 destination.Y = uniform() * MAXY;
00413 destination.Z = 0.0;
00414 assert(destination != position);
00415 }
00416
00417 void
00418 Node::RandomSpeed()
00419 {
00420 speed = uniform() * MAXSPEED;
00421
00422 assert(speed != 0.0);
00423 }
00424
00425
00426 void
00427 Node::Update()
00428 {
00429 struct setdest *setdest = traj.lh_first;
00430
00431 position += (speed * (TIME - time_update)) * direction;
00432
00433 if(TIME == time_arrival) {
00434
00435 if (NULL == setdest)
00436 {
00437 destination = position;
00438 direction.X = direction.Y = direction.Z = 0.0;
00439 speed = 0.0;
00440 time_arrival = MAXTIME + 1;
00441 }
00442 else
00443 {
00444 vector v;
00445 destination.X = setdest->X;
00446 destination.Y = setdest->Y;
00447 speed = setdest->speed;
00448 if (0.0 == speed)
00449 {
00450 if (LIST_NEXT(setdest,traj))
00451 time_arrival = LIST_NEXT(setdest,traj)->time;
00452 else
00453 time_arrival = MAXTIME + 1;
00454 }
00455 else
00456 {
00457 v = destination - position;
00458 direction = v / v.length();
00459 time_arrival = TIME + v.length() / speed;
00460 }
00461 LIST_REMOVE(setdest,traj);
00462 free(setdest);
00463 }
00464 }
00465
00466 time_update = TIME;
00467 time_transition = 0.0;
00468 }
00469
00470
00471 void
00472 Node::UpdateNeighbors()
00473 {
00474 static Node *n2;
00475 static Neighbor *m1, *m2;
00476 static vector D, B, v1, v2;
00477 static double a, b, c, t1, t2, Q;
00478 static u_int32_t i, reachable;
00479
00480 v1 = speed * direction;
00481
00482
00483
00484
00485
00486 for(i = index+1; i < NODES; i++) {
00487
00488 m1 = &neighbor[i];
00489 n2 = &NodeList[i];
00490 m2 = &n2->neighbor[index];
00491
00492 assert(i == m1->index);
00493 assert(m1->index == n2->index);
00494 assert(index == m2->index);
00495 assert(m1->reachable == m2->reachable);
00496
00497 reachable = m1->reachable;
00498
00499
00500
00501
00502 { vector d = position - n2->position;
00503
00504 if(d.length() < RANGE) {
00505 #ifdef SANITY_CHECKS
00506 if(TIME > 0.0 && m1->reachable == 0)
00507 assert(RANGE - d.length() < ROUND_ERROR);
00508 #endif
00509 m1->reachable = m2->reachable = 1;
00510 }
00511
00512 else {
00513 #ifdef SANITY_CHECKS
00514 if(TIME > 0.0 && m1->reachable == 1)
00515 assert(d.length() - RANGE < ROUND_ERROR);
00516 #endif
00517 m1->reachable = m2->reachable = 0;
00518 }
00519 #ifdef DEBUG
00520 fprintf(stdout, "# %.6f (%d, %d) %.2fm\n",
00521 TIME, index, m1->index, d.length());
00522 #endif
00523 }
00524
00525
00526
00527
00528 v2 = n2->speed * n2->direction;
00529
00530 D = v2 - v1;
00531 B = n2->position - position;
00532
00533 a = (D.X * D.X) + (D.Y * D.Y) + (D.Z * D.Z);
00534 b = 2 * ((D.X * B.X) + (D.Y * B.Y) + (D.Z * B.Z));
00535 c = (B.X * B.X) + (B.Y * B.Y) + (B.Z * B.Z) - (RANGE * RANGE);
00536
00537 if(a == 0.0) {
00538
00539
00540
00541 m1->time_transition= 0.0;
00542 m2->time_transition= 0.0;
00543 goto next;
00544 }
00545
00546 Q = b * b - 4 * a * c;
00547 if(Q < 0.0) {
00548
00549
00550
00551 m1->time_transition = 0.0;
00552 m2->time_transition = 0.0;
00553 goto next;
00554 }
00555 Q = sqrt(Q);
00556
00557 t1 = (-b + Q) / (2 * a);
00558 t2 = (-b - Q) / (2 * a);
00559
00560
00561 if(t1 > 0.0 && t1 < ROUND_ERROR) t1 = 0.0;
00562 if(t1 < 0.0 && -t1 < ROUND_ERROR) t1 = 0.0;
00563 if(t2 > 0.0 && t2 < ROUND_ERROR) t2 = 0.0;
00564 if(t2 < 0.0 && -t2 < ROUND_ERROR) t2 = 0.0;
00565
00566 if(t1 < 0.0 && t2 < 0.0) {
00567
00568
00569
00570 m1->time_transition = 0.0;
00571 m2->time_transition = 0.0;
00572 goto next;
00573 }
00574
00575
00576
00577
00578 if((t1 == 0.0 && t2 > 0.0) || (t2 == 0.0 && t1 > 0.0)) {
00579 m1->reachable = m2->reachable = 1;
00580 m1->time_transition = m2->time_transition = TIME + max(t1, t2);
00581 }
00582 else if((t1 == 0.0 && t2 < 0.0) || (t2 == 0.0 && t1 < 0.0)) {
00583 m1->reachable = m2->reachable = 0;
00584 m1->time_transition = m2->time_transition = 0.0;
00585 }
00586
00587
00588
00589
00590 else if(t1 > 0.0 && t2 > 0.0) {
00591 m1->time_transition = TIME + min(t1, t2);
00592 m2->time_transition = TIME + min(t1, t2);
00593 }
00594 else if(t1 > 0.0) {
00595 m1->time_transition = TIME + t1;
00596 m2->time_transition = TIME + t1;
00597 }
00598 else {
00599 m1->time_transition = TIME + t2;
00600 m2->time_transition = TIME + t2;
00601 }
00602
00603
00604
00605
00606 if(time_transition == 0.0 || (m1->time_transition &&
00607 time_transition > m1->time_transition)) {
00608 time_transition = m1->time_transition;
00609 }
00610 if(n2->time_transition == 0.0 || (m2->time_transition &&
00611 n2->time_transition > m2->time_transition)) {
00612 n2->time_transition = m2->time_transition;
00613 }
00614 next:
00615 if(reachable != m1->reachable && TIME > 0.0) {
00616 LinkChangeCount++;
00617 link_changes++;
00618 n2->link_changes++;
00619 }
00620 }
00621 }
00622
00623 void
00624 Node::Dump()
00625 {
00626 Neighbor *m;
00627 u_int32_t i;
00628
00629 fprintf(stdout,
00630 "Node: %d\tpos: (%.2f, %.2f, %.2f) dst: (%.2f, %.2f, %.2f)\n",
00631 index, position.X, position.Y, position.Z,
00632 destination.X, destination.Y, destination.Z);
00633 fprintf(stdout, "\tdir: (%.2f, %.2f, %.2f) speed: %.2f\n",
00634 direction.X, direction.Y, direction.Z, speed);
00635 fprintf(stdout, "\tArrival: %.2f, Update: %.2f, Transition: %.2f\n",
00636 time_arrival, time_update, time_transition);
00637
00638 for(i = 1; i < NODES; i++) {
00639 m = &neighbor[i];
00640 fprintf(stdout, "\tNeighbor: %d (%x), Reachable: %d, Transition Time: %.2f\n",
00641 m->index, (int) m, m->reachable, m->time_transition);
00642 }
00643 }
00644
00645
00646
00647
00648
00649 void dumpall()
00650 {
00651 u_int32_t i;
00652
00653 fprintf(stdout, "\nTime: %.2f\n", TIME);
00654
00655 for(i = 1; i < NODES; i++) {
00656 NodeList[i].Dump();
00657 }
00658 }
00659
00660 void
00661 ComputeW()
00662 {
00663 u_int32_t i, j;
00664 u_int32_t *W = D2;
00665
00666 memset(W, '\xff', sizeof(int) * NODES * NODES);
00667
00668 for(i = 1; i < NODES; i++) {
00669 for(j = i; j < NODES; j++) {
00670 Neighbor *m = &NodeList[i].neighbor[j];
00671 if(i == j)
00672 W[i*NODES + j] = W[j*NODES + i] = 0;
00673 else
00674 W[i*NODES + j] = W[j*NODES + i] = m->reachable ? 1 : INFINITY;
00675 }
00676 }
00677 }
00678
00679 void
00680 floyd_warshall()
00681 {
00682 u_int32_t i, j, k;
00683
00684 ComputeW();
00685
00686 for(i = 1; i < NODES; i++) {
00687 for(j = 1; j < NODES; j++) {
00688 for(k = 1; k < NODES; k++) {
00689 D2[j*NODES + k] = min(D2[j*NODES + k], D2[j*NODES + i] + D2[i*NODES + k]);
00690 }
00691 }
00692 }
00693
00694 #ifdef SANITY_CHECKS
00695 for(i = 1; i < NODES; i++)
00696 for(j = 1; j < NODES; j++) {
00697 assert(D2[i*NODES + j] == D2[j*NODES + i]);
00698 assert(D2[i*NODES + j] <= INFINITY);
00699 }
00700 #endif
00701 }
00702
00703
00704
00705
00706
00707 void
00708 show_diffs()
00709 {
00710 u_int32_t i, j;
00711
00712 for(i = 1; i < NODES; i++) {
00713 for(j = i + 1; j < NODES; j++) {
00714 if(D1[i*NODES + j] != D2[i*NODES + j]) {
00715
00716 if(D2[i*NODES + j] == INFINITY)
00717 DestUnreachableCount++;
00718
00719 if(TIME > 0.0) {
00720 RouteChangeCount++;
00721 NodeList[i].route_changes++;
00722 NodeList[j].route_changes++;
00723 }
00724
00725 if(TIME == 0.0) {
00726 fprintf(out_file, GOD_FORMAT2,
00727 i, j, D2[i*NODES + j]);
00728 #ifdef SHOW_SYMMETRIC_PAIRS
00729 fprintf(out_file, GOD_FORMAT2,
00730 j, i, D2[j*NODES + i]);
00731 #endif
00732 }
00733 else {
00734 fprintf(out_file, GOD_FORMAT,
00735 TIME, i, j, D2[i*NODES + j]);
00736 #ifdef SHOW_SYMMETRIC_PAIRS
00737 fprintf(out_file, GOD_FORMAT,
00738 TIME, j, i, D2[j*NODES + i]);
00739 #endif
00740 }
00741 }
00742 }
00743 }
00744
00745 memcpy(D1, D2, sizeof(int) * NODES * NODES);
00746 }
00747
00748
00749 void
00750 show_routes()
00751 {
00752 u_int32_t i, j;
00753
00754 fprintf(stdout, "#\n# TIME: %.12f\n#\n", TIME);
00755 for(i = 1; i < NODES; i++) {
00756 fprintf(stdout, "# %2d) ", i);
00757 for(j = 1; j < NODES; j++)
00758 fprintf(stdout, "%3d ", D2[i*NODES + j] & 0xff);
00759 fprintf(stdout, "\n");
00760 }
00761 fprintf(stdout, "#\n");
00762 }
00763
00764 void
00765 show_counters()
00766 {
00767 u_int32_t i;
00768
00769 fprintf(out_file, "#\n# Destination Unreachables: %d\n#\n",
00770 DestUnreachableCount);
00771 fprintf(out_file, "# Route Changes: %d\n#\n", RouteChangeCount);
00772 fprintf(out_file, "# Link Changes: %d\n#\n", LinkChangeCount);
00773 fprintf(out_file, "# Node | Route Changes | Link Changes\n");
00774 for(i = 1; i < NODES; i++)
00775 fprintf(out_file, "# %4d | %4d | %4d\n",
00776 i, NodeList[i].route_changes,
00777 NodeList[i].link_changes);
00778 fprintf(out_file, "#\n");
00779 }
00780