setdest.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:25k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  *
  3.  * The original code of setdest was included in ns-2.1b8a.
  4.  * This file is the modified version by J. Yoon <jkyoon@eecs.umich.edu>,
  5.  * Department of EECS, University of Michigan, Ann Arbor. 
  6.  *
  7.  * (1) Input parameters
  8.  * <Original version>
  9.  * => -M maximum speed (minimum speed is zero as a default)
  10.  * => -p pause time (constant) 
  11.  * => -n number of nodes
  12.  * => -x x dimension of space
  13.  * => -y y dimension of space
  14.  *
  15.  * <Modified version>
  16.  * => -s speed type (uniform, normal)
  17.  * => -m minimum speed > 0 
  18.  * => -M maximum speed
  19.  * => -P pause type (constant, uniform)
  20.  * => -p pause time (a median if uniform is chosen)
  21.  * => -n number of nodes
  22.  * => -x x dimension of space
  23.  * => -y y dimension of space
  24.  *
  25.  * (2) In case of modified version, the steady-state speed distribution is applied to 
  26.  * the first trip to eliminate any speed decay. If pause is not zero, the first 
  27.  * trip could be either a move or a pause depending on the probabilty that the 
  28.  * first trip is a pause. After the first trip regardless of whether it is 
  29.  * a move or a pause, all subsequent speeds are determined from the given speed 
  30.  * distribution (e.g., uniform or normal).
  31.  *
  32.  * (3) Refer to and use scenario-generating scripts (make-scen.csh for original version, 
  33.  * make-scen-steadystate.csh for modified version).
  34.  *
  35.  *
  36.  */
  37. extern "C" {
  38. #include <assert.h>
  39. #include <fcntl.h>
  40. #include <math.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <sys/time.h>
  45. #include <sys/types.h>
  46. #include <sys/uio.h>
  47. #include <unistd.h>
  48. #if !defined(sun)
  49. #include <err.h>
  50. #endif
  51. };
  52. #include "../../../tools/rng.h"
  53. #include "setdest.h"
  54. // #define DEBUG
  55. #define SANITY_CHECKS
  56. //#define SHOW_SYMMETRIC_PAIRS
  57. #define GOD_FORMAT "$ns_ at %.12f "$god_ set-dist %d %d %d"n"
  58. #define GOD_FORMAT2 "$god_ set-dist %d %d %dn"
  59. #define NODE_FORMAT "$ns_ at %.12f "$node_(%d) setdest %.12f %.12f %.12f"n"
  60. #define NODE_FORMAT2 "$node_(%d) setdest %.12f %.12f %.12fn"
  61. #define NODE_FORMAT3 "$node_(%d) set %c_ %.12fn"
  62. #define RTG_INFINITY 0x00ffffff
  63. #ifndef min
  64. #define min(x,y) ((x) < (y) ? (x) : (y))
  65. #define max(x,y) ((x) > (y) ? (x) : (y))
  66. #endif
  67. #define ROUND_ERROR 1e-9
  68. #ifndef PI
  69. #define  PI   3.1415926
  70. #endif
  71. static int count = 0;
  72. /* ======================================================================
  73.    Function Prototypes
  74.    ====================================================================== */
  75. void usage(char**);
  76. void init(void);
  77. double uniform(void);
  78. void dumpall(void);
  79. void ComputeW(void);
  80. void floyd_warshall(void);
  81. void show_diffs(void);
  82. void show_routes(void);
  83. void show_counters(void);
  84. /* ======================================================================
  85.    Global Variables
  86.    ====================================================================== */
  87. const double RANGE = 250.0; // transmitter range in meters
  88. double TIME = 0.0; // my clock;
  89. double MAXTIME = 0.0; // duration of simulation
  90. double MAXX = 0.0; // width of space
  91. double MAXY = 0.0; // height of space
  92. double PAUSE = 0.0; // pause time
  93. double MAXSPEED = 0.0; // max speed
  94. double MINSPEED = 0.0; // min speed 
  95. double SS_AVGSPEED = 0.0; // steady-state avg speed 
  96. double  KAPPA = 0.0; // normalizing constant 
  97. double  MEAN = 0.0; // mean for normal speed
  98. double  SIGMA = 0.0; // std for normal speed
  99. double  EXP_1_V = 0.0; // expactation of 1/V
  100. double  EXP_R = 0.0; // expectation of travel distance R
  101. double  PDFMAX = 0.0; // max of pdf for rejection technique
  102. u_int32_t SPEEDTYPE = 1; // speed type (default = uniform)
  103. u_int32_t PAUSETYPE = 1; // pause type (default = constant)
  104. u_int32_t VERSION = 1; // setdest version (default = original by CMU) 
  105. u_int32_t NODES = 0; // number of nodes
  106. u_int32_t RouteChangeCount = 0;
  107. u_int32_t LinkChangeCount = 0;
  108. u_int32_t DestUnreachableCount = 0;
  109. Node *NodeList = 0;
  110. u_int32_t *D1 = 0;
  111. u_int32_t *D2 = 0;
  112. /* ======================================================================
  113.    Random Number Generation
  114.    ====================================================================== */
  115. #define M 2147483647L
  116. #define INVERSE_M ((double)4.656612875e-10)
  117. char random_state[32];
  118. RNG *rng;
  119. double
  120. uniform()
  121. {
  122.         count++;
  123.         return rng->uniform_double() ;
  124. }
  125. /* ======================================================================
  126.    Misc Functions...
  127.    ====================================================================== */
  128. /* compute the expectation of travel distance E[R] in a rectangle */
  129. void
  130. compute_EXP_R()
  131. {
  132. #define csc(x)  (1.0/sin(x)) // csc function
  133. #define sec(x) (1.0/cos(x)) // sec function
  134. #define sin2(x) (sin(x)*sin(x)) // sin^2
  135. #define sin3(x) (sin2(x)*sin(x)) // sin^3
  136. #define cos2(x) (cos(x)*cos(x)) // cos^2
  137. #define cos3(x) (cos2(x)*cos(x)) // cos^3
  138. double x = MAXX, y = MAXY; // max x and max y
  139. double x2 = x*x, x3 = x*x*x; // x^2 and x^3
  140. double y2 = y*y, y3 = y*y*y; // y^2 and y^3
  141. double term1 = sin(atan2(y,x)) / 2.0 / cos2(atan2(y,x));
  142. double term2 = 0.5 * log( sec(atan2(y,x)) + y/x );
  143. double term3 = -1.0 * x3 / y2 / 60.0 / cos3(atan2(y,x)) + 1.0/60.0 * x3 / y2;
  144. double term4 = (term1 + term2) * x2 / 12.0 / y + term3;
  145. double term5 = -1.0 * cos(atan2(y,x)) / 2.0 / sin2(atan2(y,x));
  146. double term6 = 0.5 * log( csc(atan2(y,x)) - x/y );
  147. double term7 = -1.0 * y3 / x2 / 60.0 / sin3(atan2(y,x)) + 1.0/60.0 * y3 / x2;
  148. double term8 = -1.0 * (term5 + term6) * y2 / 12.0 / x + term7;
  149. EXP_R = (4 * (term4 + term8));  // E[R]
  150. }
  151. void
  152. usage(char **argv)
  153. {
  154. fprintf(stderr, "nusage:n");
  155. fprintf(stderr,
  156. "n<original 1999 CMU version (version 1)>n %st-v <1> -n <nodes> -p <pause time> -M <max speed>n",
  157. argv[0]);
  158. fprintf(stderr,
  159. "tt-t <simulation time> -x <max X> -y <max Y>n");
  160. fprintf(stderr,
  161. "nORn<modified 2003 U.Michigan version (version 2)>n %st-v <2> -n <nodes> -s <speed type> -m <min speed> -M <max speed>n",
  162. argv[0]);
  163. fprintf(stderr,
  164. "tt-t <simulation time> -P <pause type> -p <pause time> -x <max X> -y <max Y>n");
  165. fprintf(stderr,
  166. "tt(Refer to the script files make-scen.csh and make-scen-steadystate.csh for detail.) nn");
  167. }
  168. void
  169. init()
  170. {
  171. /*
  172.  * Initialized the Random Number Generation
  173.  */
  174. /* 
  175. This part of init() is commented out and is replaced by more
  176. portable RNG (random number generator class of ns) functions.
  177. struct timeval tp;
  178. int fd, seed, bytes;
  179. if((fd = open("/dev/random", O_RDONLY)) < 0) {
  180. perror("open");
  181. exit(1);
  182. }
  183. if((bytes = read(fd, random_state, sizeof(random_state))) < 0) {
  184. perror("read");
  185. exit(1);
  186. }
  187. close(fd);
  188. fprintf(stderr, "*** read %d bytes from /dev/randomn", bytes);
  189. if(bytes != sizeof(random_state)) {
  190.   fprintf(stderr,"Not enough randomness. Reading `.rand_state'n");
  191.   if((fd = open(".rand_state", O_RDONLY)) < 0) {
  192.     perror("open .rand_state");
  193.     exit(1);
  194.   }
  195.   if((bytes = read(fd, random_state, sizeof(random_state))) < 0) {
  196.     perror("reading .rand_state");
  197.     exit(1);
  198.   }
  199.   close(fd);
  200. }
  201.          if(gettimeofday(&tp, 0) < 0) {
  202. perror("gettimeofday");
  203. exit(1);
  204. }
  205. seed = (tp.tv_sec  >> 12 ) ^ tp.tv_usec;
  206.         (void) initstate(seed, random_state, bytes & 0xf8);*/
  207. /*
  208.  * Allocate memory for globals
  209.  */
  210. NodeList = new Node[NODES];
  211. if(NodeList == 0) {
  212. perror("new");
  213. exit(1);
  214. }
  215. D1 = new u_int32_t[NODES * NODES];
  216. if(D1 == 0) {
  217. perror("new");
  218. exit(1);
  219. }
  220. memset(D1, 'xff', sizeof(u_int32_t) * NODES * NODES);
  221. D2 = new u_int32_t[NODES * NODES];
  222. if(D2 == 0) {
  223. perror("new");
  224. exit(1);
  225. }
  226. memset(D2, 'xff', sizeof(u_int32_t) * NODES * NODES);
  227. }
  228. extern "C" char *optarg;
  229. int
  230. main(int argc, char **argv)
  231. {
  232. char ch;
  233. while ((ch = getopt(argc, argv, "v:n:s:m:M:t:P:p:x:y:i:o:")) != EOF) {       
  234. switch (ch) { 
  235. case 'v':
  236.   VERSION = atoi(optarg);
  237.   break;
  238. case 'n':
  239.   NODES = atoi(optarg);
  240.   break;
  241. case 's':
  242. SPEEDTYPE = atoi(optarg);
  243. break;
  244. case 'm':
  245. MINSPEED = atof(optarg);
  246. break;
  247. case 'M':
  248. MAXSPEED = atof(optarg);
  249. break;
  250. case 't':
  251. MAXTIME = atof(optarg);
  252. break;
  253. case 'P':
  254. PAUSETYPE = atoi(optarg);
  255. break;
  256. case 'p':
  257. PAUSE = atof(optarg);
  258. break;
  259. case 'x':
  260. MAXX = atof(optarg);
  261. break;
  262. case 'y':
  263. MAXY = atof(optarg);
  264. break;
  265. default:
  266. usage(argv);
  267. exit(1);
  268. }
  269. }
  270. if(MAXX == 0.0 || MAXY == 0.0 || NODES == 0 || MAXTIME == 0.0) {
  271. usage(argv);
  272. exit(1);
  273. }
  274. /* specify the version */
  275. if (VERSION != 1 && VERSION != 2) {
  276.   printf("Please specify the setdest version you want to use. For original 1999 CMU version use 1; For modified 2003 U.Michigan version use 2n");
  277.   exit(1);
  278. }
  279. if (VERSION == 2 && MINSPEED <= 0) {
  280.   usage(argv);
  281.   exit(1);
  282. } else if (VERSION == 1 && MINSPEED > 0) {
  283.   usage(argv);
  284.   exit(1);
  285. }
  286. // The more portable solution for random number generation
  287. rng = new RNG;
  288. rng->set_seed(RNG::HEURISTIC_SEED_SOURCE); 
  289. /****************************************************************************************
  290.    * Steady-state avg speed and distribution depending on the initial distirbutions given
  291.  ****************************************************************************************/
  292. /* original setdest */
  293. if (VERSION == 1) {
  294. fprintf(stdout, "#n# nodes: %d, pause: %.2f, max speed: %.2f, max x: %.2f, max y: %.2fn#n",
  295. NODES, PAUSE, MAXSPEED, MAXX, MAXY);
  296. }
  297. /* modified version */
  298. else if (VERSION == 2) {
  299. /* compute the expectation of travel distance in a rectangle */
  300. compute_EXP_R();
  301. /* uniform speed from min to max */
  302. if (SPEEDTYPE == 1) {
  303. EXP_1_V = log(MAXSPEED/MINSPEED) / (MAXSPEED - MINSPEED); // E[1/V]
  304. SS_AVGSPEED = EXP_R / (EXP_1_V*EXP_R + PAUSE); // steady-state average speed
  305. PDFMAX = 1/MINSPEED*EXP_R / (EXP_1_V*EXP_R + PAUSE) / (MAXSPEED-MINSPEED); // max of pdf for rejection technique
  306. }
  307. /* normal speed clipped from min to max */
  308. else if (SPEEDTYPE == 2) {
  309. int bin_no = 10000; // the number of bins for summation
  310. double delta = (MAXSPEED - MINSPEED)/bin_no;  // width of each bin 
  311. int i;
  312. double acc_k, acc_e, square, temp_v;
  313. MEAN = (MAXSPEED + MINSPEED)/2.0; // means for normal dist.
  314. SIGMA = (MAXSPEED - MINSPEED)/4.0; // std for normal dist.
  315. /* computing a normalizing constant KAPPA, E[1/V], and pdf max */
  316. KAPPA = 0.0;
  317. EXP_1_V = 0.0;
  318. PDFMAX = 0.0;
  319. /* numerical integrals */
  320. for (i=0; i<bin_no; ++i) {
  321. temp_v = MINSPEED + i*delta; // ith v from min speed
  322. square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
  323. acc_k = 1.0/sqrt(2.0*PI*SIGMA*SIGMA)*exp(-0.5*square);
  324. KAPPA += (acc_k*delta); // summing up the area of rectangle
  325. acc_e = 1.0/temp_v/sqrt(2.0*PI*SIGMA*SIGMA)*exp(-0.5*square);
  326. EXP_1_V += (acc_e*delta); // summing up for the denominator of pdf
  327. /* find a max of pdf */
  328. if (PDFMAX < acc_e) PDFMAX = acc_e;
  329. }
  330. EXP_1_V /= KAPPA; // normalizing
  331. SS_AVGSPEED = EXP_R / (EXP_1_V*EXP_R + PAUSE); // steady-state average speed
  332. PDFMAX = EXP_R*PDFMAX/KAPPA / (EXP_1_V*EXP_R + PAUSE); // max of pdf for rejection technique
  333. }
  334. /* other types of speed for future use */
  335. else
  336. ;
  337. fprintf(stdout, "#n# nodes: %d, speed type: %d, min speed: %.2f, max speed: %.2fn# avg speed: %.2f, pause type: %d, pause: %.2f, max x: %.2f, max y: %.2fn#n",
  338. NODES , SPEEDTYPE, MINSPEED, MAXSPEED, SS_AVGSPEED, PAUSETYPE, PAUSE, MAXX, MAXY);
  339. init();
  340. while(TIME <= MAXTIME) {
  341. double nexttime = 0.0;
  342. u_int32_t i;
  343. for(i = 0; i < NODES; i++) {
  344. NodeList[i].Update();
  345. }
  346. for(i = 0; i < NODES; i++) {
  347. NodeList[i].UpdateNeighbors();
  348. }
  349. for(i = 0; i < NODES; i++) {
  350. Node *n = &NodeList[i];
  351. if(n->time_transition > 0.0) {
  352. if(nexttime == 0.0)
  353. nexttime = n->time_transition;
  354. else
  355. nexttime = min(nexttime, n->time_transition);
  356. }
  357. if(n->time_arrival > 0.0) {
  358. if(nexttime == 0.0)
  359. nexttime = n->time_arrival;
  360. else
  361. nexttime = min(nexttime, n->time_arrival);
  362. }
  363. }
  364. floyd_warshall();
  365. #ifdef DEBUG
  366. show_routes();
  367. #endif
  368.   show_diffs();
  369. #ifdef DEBUG
  370. dumpall();
  371. #endif
  372. assert(nexttime > TIME + ROUND_ERROR);
  373. TIME = nexttime;
  374. }
  375. show_counters();
  376. int of;
  377. if ((of = open(".rand_state",O_WRONLY | O_TRUNC | O_CREAT, 0777)) < 0) {
  378.   fprintf(stderr, "open rand staten");
  379.   exit(-1);
  380.   }
  381. for (unsigned int i = 0; i < sizeof(random_state); i++)
  382.           random_state[i] = 0xff & (int) (uniform() * 256);
  383. if (write(of,random_state, sizeof(random_state)) < 0) {
  384.   fprintf(stderr, "writing rand staten");
  385.   exit(-1);
  386.   }
  387. close(of);
  388. }
  389. /* ======================================================================
  390.    Node Class Functions
  391.    ====================================================================== */
  392. u_int32_t Node::NodeIndex = 0;
  393. Node::Node()
  394. {
  395. u_int32_t i;
  396. index = NodeIndex++;
  397. //if(index == 0)
  398. // return;
  399. route_changes = 0;
  400.     link_changes = 0;
  401.     /*******************************************************************************
  402.  * Determine if the first trip is a pause or a move with the steady-state pdf
  403.      *******************************************************************************/
  404. /* original version */
  405. if (VERSION == 1) {
  406. time_arrival = TIME + PAUSE; // constant pause
  407. }
  408. /* modified version */ 
  409. else if (VERSION == 2) {
  410. /* probability that the first trip would be a pause */
  411. double prob_pause = PAUSE / (EXP_1_V*EXP_R + PAUSE);
  412. /* the first trip is a pause */
  413. if (prob_pause > uniform()) {
  414. /* constant pause */
  415. if (PAUSETYPE == 1) {
  416. time_arrival = TIME + PAUSE; // constant pause
  417. }
  418. /* uniform pause */
  419. else if (PAUSETYPE == 2) {
  420. time_arrival = TIME + 2*PAUSE*uniform(); // uniform pause [0, 2*PAUSE]
  421. }
  422. first_trip = 0; // indicating the first trip is a pause 
  423. }
  424. /* the first trip is a move based on the steady-state pdf */
  425. else {
  426. time_arrival = TIME;
  427. first_trip = 1; // indicating the first trip is a move 
  428. }
  429. }
  430. time_update = TIME;
  431. time_transition = 0.0;
  432. position.X = position.Y = position.Z = 0.0;
  433. destination.X = destination.Y = destination.Z = 0.0;
  434. direction.X = direction.Y = direction.Z = 0.0;
  435. speed = 0.0;
  436. RandomPosition();
  437. fprintf(stdout, NODE_FORMAT3, index, 'X', position.X);
  438. fprintf(stdout, NODE_FORMAT3, index, 'Y', position.Y);
  439. fprintf(stdout, NODE_FORMAT3, index, 'Z', position.Z);
  440. neighbor = new Neighbor[NODES];
  441. if(neighbor == 0) {
  442. perror("new");
  443. exit(1);
  444. }
  445. for(i = 0; i < NODES; i++) {
  446. neighbor[i].index = i;
  447. neighbor[i].reachable = (index == i) ? 1 : 0;
  448. neighbor[i].time_transition = 0.0;
  449. }
  450. }
  451. void
  452. Node::RandomPosition()
  453. {
  454.     position.X = uniform() * MAXX;
  455.     position.Y = uniform() * MAXY;
  456. position.Z = 0.0;
  457. }
  458. void
  459. Node::RandomDestination()
  460. {
  461.     destination.X = uniform() * MAXX;
  462.     destination.Y = uniform() * MAXY;
  463. destination.Z = 0.0;
  464. assert(destination != position);
  465. }
  466. /****************************************************************************************** 
  467.  * Speeds are chosen based on the given type and distribution
  468.  ******************************************************************************************/
  469. void
  470. Node::RandomSpeed()
  471. {
  472. /* original version */
  473. if (VERSION == 1) {
  474.         speed = uniform() * MAXSPEED;
  475. assert(speed != 0.0);
  476. }
  477. /* modified version */
  478. else if (VERSION == 2) {
  479. /* uniform speed */
  480. if (SPEEDTYPE == 1) {
  481. /* using steady-state distribution for the first trip */
  482. if (first_trip == 1) {
  483. /* pick a speed by rejection technique */
  484. double temp_v, temp_fv;
  485. do {
  486.            temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
  487. temp_fv = uniform() * PDFMAX;
  488. } while (temp_fv > 1/temp_v*EXP_R / (EXP_1_V*EXP_R + PAUSE) / (MAXSPEED-MINSPEED));
  489.  
  490. speed = temp_v;
  491. first_trip = 0; // reset first_trip flag 
  492. }
  493. /* using the original distribution from the second trip on */
  494. else {
  495.          speed = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
  496. assert(speed != 0.0);
  497. }
  498. }
  499. /* normal speed */
  500. else if (SPEEDTYPE == 2) {
  501. /* using steady-state distribution for the first trip */
  502. if (first_trip == 1) {
  503. double temp_v, temp_fv, square, fv;
  504. /* rejection technique */
  505. do {
  506.            temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
  507. temp_fv = uniform() * PDFMAX;
  508. square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
  509. fv = 1/KAPPA/sqrt(2.0*PI*SIGMA*SIGMA) * exp(-0.5*square);
  510. } while (temp_fv > 1.0/temp_v*fv*EXP_R / (EXP_1_V*EXP_R + PAUSE));
  511.  
  512. speed = temp_v;
  513. first_trip = 0;
  514. }
  515. /* using the original distribution from the second trip on */
  516. else {
  517. double temp_v, temp_fv, square;
  518. double max_normal = 1.0/KAPPA/sqrt(2.0*PI*SIGMA*SIGMA); // max of normal distribution
  519. /* rejection technique */
  520. do {
  521.           temp_v = uniform() * (MAXSPEED - MINSPEED) + MINSPEED;
  522. temp_fv = uniform() * max_normal;
  523. square = (temp_v - MEAN)*(temp_v - MEAN)/SIGMA/SIGMA;
  524. } while (temp_fv > max_normal * exp(-0.5*square));
  525.  
  526. speed = temp_v;
  527. assert(speed != 0.0);
  528. }
  529. }
  530. /* other types of speed for future use */
  531. else
  532. ;
  533. }
  534. }
  535. void
  536. Node::Update()
  537. {
  538. position += (speed * (TIME - time_update)) * direction;
  539. if(TIME == time_arrival) {
  540. vector v;
  541. if(speed == 0.0 || PAUSE == 0.0) {
  542.             RandomDestination();
  543. RandomSpeed();
  544. v = destination - position;
  545. direction = v / v.length();
  546. time_arrival = TIME + v.length() / speed;
  547. }
  548. else {
  549. destination = position;
  550. speed = 0.0;
  551. /* original version */
  552. if (VERSION == 1) {
  553. time_arrival = TIME + PAUSE;
  554. }
  555. /* modified version */
  556. else if (VERSION == 2) {
  557. /* constant pause */
  558. if (PAUSETYPE == 1) {
  559. time_arrival = TIME + PAUSE;
  560. }
  561. /* uniform pause */
  562. else if (PAUSETYPE == 2) {
  563. time_arrival = TIME + 2*PAUSE*uniform();
  564. }
  565. }
  566. }
  567. fprintf(stdout, NODE_FORMAT,
  568. TIME, index, destination.X, destination.Y, speed);
  569. }
  570. time_update = TIME;
  571. time_transition = 0.0;
  572. }
  573. void
  574. Node::UpdateNeighbors()
  575. {
  576. static Node *n2;
  577. static Neighbor *m1, *m2;
  578. static vector D, B, v1, v2;
  579. static double a, b, c, t1, t2, Q;
  580. static u_int32_t i, reachable;
  581. v1 = speed * direction;
  582. /*
  583.  *  Only need to go from INDEX --> N for each one since links
  584.  *  are symmetric.
  585.  */
  586. for(i = index+1; i < NODES; i++) {
  587. m1 = &neighbor[i];
  588. n2 = &NodeList[i];
  589. m2 = &n2->neighbor[index];
  590. assert(i == m1->index);
  591. assert(m1->index == n2->index);
  592. assert(index == m2->index);
  593.                 assert(m1->reachable == m2->reachable);
  594.                 reachable = m1->reachable;
  595. /* ==================================================
  596.    Determine Reachability
  597.    ================================================== */
  598. { vector d = position - n2->position;
  599. if(d.length() < RANGE) {
  600. #ifdef SANITY_CHECKS
  601. if(TIME > 0.0 && m1->reachable == 0)
  602. assert(RANGE - d.length() < ROUND_ERROR);
  603. #endif
  604. m1->reachable = m2->reachable = 1;
  605. }
  606. // Boundary condition handled below.
  607. else {
  608. #ifdef SANITY_CHECKS
  609. if(TIME > 0.0 && m1->reachable == 1)
  610. assert(d.length() - RANGE < ROUND_ERROR);
  611. #endif
  612. m1->reachable = m2->reachable = 0;
  613. }
  614. #ifdef DEBUG
  615.                         fprintf(stdout, "# %.6f (%d, %d) %.2fmn",
  616.                                 TIME, index, m1->index, d.length());
  617. #endif
  618. }
  619. /* ==================================================
  620.    Determine Next Event Time
  621.    ================================================== */
  622. v2 = n2->speed * n2->direction;
  623. D = v2 - v1;
  624. B = n2->position - position;
  625. a = (D.X * D.X) + (D.Y * D.Y) + (D.Z * D.Z);
  626. b = 2 * ((D.X * B.X) + (D.Y * B.Y) + (D.Z * B.Z));
  627. c = (B.X * B.X) + (B.Y * B.Y) + (B.Z * B.Z) - (RANGE * RANGE);
  628. if(a == 0.0) {
  629. /*
  630.  *  No Finite Solution
  631.  */
  632. m1->time_transition= 0.0;
  633. m2->time_transition= 0.0;
  634. goto  next;
  635. }
  636. Q = b * b - 4 * a * c;
  637. if(Q < 0.0) {
  638. /*
  639.  *  No real roots.
  640.  */
  641. m1->time_transition = 0.0;
  642. m2->time_transition = 0.0;
  643. goto next;
  644. }
  645. Q = sqrt(Q);
  646. t1 = (-b + Q) / (2 * a);
  647. t2 = (-b - Q) / (2 * a);
  648. // Stupid Rounding/Boundary Cases
  649. if(t1 > 0.0 && t1 < ROUND_ERROR) t1 = 0.0;
  650. if(t1 < 0.0 && -t1 < ROUND_ERROR) t1 = 0.0;
  651. if(t2 > 0.0 && t2 < ROUND_ERROR) t2 = 0.0;
  652. if(t2 < 0.0 && -t2 < ROUND_ERROR) t2 = 0.0;
  653. if(t1 < 0.0 && t2 < 0.0) {
  654. /*
  655.  *  No "future" time solution.
  656.  */
  657. m1->time_transition = 0.0;
  658. m2->time_transition = 0.0;
  659. goto next;
  660. }
  661. /*
  662.  * Boundary conditions.
  663.  */
  664. if((t1 == 0.0 && t2 > 0.0) || (t2 == 0.0 && t1 > 0.0)) {
  665. m1->reachable = m2->reachable = 1;
  666. m1->time_transition = m2->time_transition = TIME + max(t1, t2);
  667. }
  668. else if((t1 == 0.0 && t2 < 0.0) || (t2 == 0.0 && t1 < 0.0)) {
  669. m1->reachable = m2->reachable = 0;
  670. m1->time_transition = m2->time_transition = 0.0;
  671. }
  672. /*
  673.  * Non-boundary conditions.
  674.  */
  675. else if(t1 > 0.0 && t2 > 0.0) {
  676. m1->time_transition = TIME + min(t1, t2);
  677. m2->time_transition = TIME + min(t1, t2);
  678. }
  679. else if(t1 > 0.0) {
  680. m1->time_transition = TIME + t1;
  681. m2->time_transition = TIME + t1;
  682. }
  683. else {
  684. m1->time_transition = TIME + t2;
  685. m2->time_transition = TIME + t2;
  686. }
  687. /* ==================================================
  688.    Update the transition times for both NODEs.
  689.    ================================================== */
  690. if(time_transition == 0.0 || (m1->time_transition &&
  691.    time_transition > m1->time_transition)) {
  692. time_transition = m1->time_transition;
  693. }
  694. if(n2->time_transition == 0.0 || (m2->time_transition &&
  695.    n2->time_transition > m2->time_transition)) {
  696. n2->time_transition = m2->time_transition;
  697. }
  698.         next:
  699.                 if(reachable != m1->reachable && TIME > 0.0) {
  700.                         LinkChangeCount++;
  701.                         link_changes++;
  702.                         n2->link_changes++;
  703.                 }
  704. }
  705. }
  706. void
  707. Node::Dump()
  708. {
  709. Neighbor *m;
  710. u_int32_t i;
  711. fprintf(stdout,
  712. "Node: %dtpos: (%.2f, %.2f, %.2f) dst: (%.2f, %.2f, %.2f)n",
  713. index, position.X, position.Y, position.Z,
  714. destination.X, destination.Y, destination.Z);
  715. fprintf(stdout, "tdir: (%.2f, %.2f, %.2f) speed: %.2fn",
  716. direction.X, direction.Y, direction.Z, speed);
  717. fprintf(stdout, "tArrival: %.2f, Update: %.2f, Transition: %.2fn",
  718. time_arrival, time_update, time_transition);
  719. for(i = 0; i < NODES; i++) {
  720. m = &neighbor[i];
  721. fprintf(stdout, "tNeighbor: %d (%lx), Reachable: %d, Transition Time: %.2fn",
  722. m->index, (long) m, m->reachable, m->time_transition);
  723. }
  724. }
  725. /* ======================================================================
  726.    Dijkstra's Shortest Path Algoritm
  727.    ====================================================================== */
  728. void dumpall()
  729. {
  730. u_int32_t i;
  731. fprintf(stdout, "nTime: %.2fn", TIME);
  732. for(i = 0; i < NODES; i++) {
  733. NodeList[i].Dump();
  734. }
  735. }
  736. void
  737. ComputeW()
  738. {
  739. u_int32_t i, j;
  740. u_int32_t *W = D2;
  741. memset(W, 'xff', sizeof(int) * NODES * NODES);
  742. for(i = 0; i < NODES; i++) {
  743. for(j = i; j < NODES; j++) {
  744. Neighbor *m = &NodeList[i].neighbor[j];
  745. if(i == j)
  746. W[i*NODES + j] = W[j*NODES + i] = 0;
  747. else
  748. W[i*NODES + j] = W[j*NODES + i] = m->reachable ? 1 : RTG_INFINITY;
  749. }
  750. }
  751. }
  752. void
  753. floyd_warshall()
  754. {
  755. u_int32_t i, j, k;
  756. ComputeW(); // the connectivity matrix
  757. for(i = 0; i < NODES; i++) {
  758. for(j = 0; j < NODES; j++) {
  759. for(k = 0; k < NODES; k++) {
  760. D2[j*NODES + k] = min(D2[j*NODES + k], D2[j*NODES + i] + D2[i*NODES + k]);
  761. }
  762. }
  763. }
  764. #ifdef SANITY_CHECKS
  765. for(i = 0; i < NODES; i++)
  766. for(j = 0; j < NODES; j++) {
  767. assert(D2[i*NODES + j] == D2[j*NODES + i]);
  768. assert(D2[i*NODES + j] <= RTG_INFINITY);
  769. }
  770. #endif
  771. }
  772. /*
  773.  *  Write the actual GOD entries to a TCL script.
  774.  */
  775. void
  776. show_diffs()
  777. {
  778. u_int32_t i, j;
  779. for(i = 0; i < NODES; i++) {
  780. for(j = i + 1; j < NODES; j++) {
  781. if(D1[i*NODES + j] != D2[i*NODES + j]) {
  782. if(D2[i*NODES + j] == RTG_INFINITY)
  783. DestUnreachableCount++;
  784.                                 if(TIME > 0.0) {
  785.                                         RouteChangeCount++;
  786.                                         NodeList[i].route_changes++;
  787.                                         NodeList[j].route_changes++;
  788.                                 }
  789. if(TIME == 0.0) {
  790. fprintf(stdout, GOD_FORMAT2,
  791. i, j, D2[i*NODES + j]);
  792. #ifdef SHOW_SYMMETRIC_PAIRS
  793. fprintf(stdout, GOD_FORMAT2,
  794. j, i, D2[j*NODES + i]);
  795. #endif
  796. }
  797. else {
  798. fprintf(stdout, GOD_FORMAT, 
  799. TIME, i, j, D2[i*NODES + j]);
  800. #ifdef SHOW_SYMMETRIC_PAIRS
  801. fprintf(stdout, GOD_FORMAT, 
  802. TIME, j, i, D2[j*NODES + i]);
  803. #endif
  804. }
  805. }
  806. }
  807. }
  808. memcpy(D1, D2, sizeof(int) * NODES * NODES);
  809. }
  810. void
  811. show_routes()
  812. {
  813. u_int32_t i, j;
  814. fprintf(stdout, "#n# TIME: %.12fn#n", TIME);
  815. for(i = 0; i < NODES; i++) {
  816. fprintf(stdout, "# %2d) ", i);
  817. for(j = 0; j < NODES; j++)
  818. fprintf(stdout, "%3d ", D2[i*NODES + j] & 0xff);
  819. fprintf(stdout, "n");
  820. }
  821. fprintf(stdout, "#n");
  822. }
  823. void
  824. show_counters()
  825. {
  826. u_int32_t i;
  827. fprintf(stdout, "#n# Destination Unreachables: %dn#n",
  828. DestUnreachableCount);
  829. fprintf(stdout, "# Route Changes: %dn#n", RouteChangeCount);
  830.         fprintf(stdout, "# Link Changes: %dn#n", LinkChangeCount);
  831.         fprintf(stdout, "# Node | Route Changes | Link Changesn");
  832. for(i = 0; i < NODES; i++)
  833. fprintf(stdout, "# %4d |          %4d |         %4dn",
  834.                         i, NodeList[i].route_changes,
  835.                         NodeList[i].link_changes);
  836. fprintf(stdout, "#n");
  837. }