annotate emd.c @ 258:d12364d8b9ea adding-emd

added cmdline stubs for distance switch and skeleton methods for EMD
author map01bf
date Fri, 25 Apr 2008 17:40:19 +0000
parents bfd34e8c84fb
children
rev   line source
map01bf@255 1 /*
map01bf@255 2 emd.c
map01bf@255 3
map01bf@255 4 Last update: 3/14/98
map01bf@255 5
map01bf@255 6 An implementation of the Earth Movers Distance.
map01bf@255 7 Based of the solution for the Transportation problem as described in
map01bf@255 8 "Introduction to Mathematical Programming" by F. S. Hillier and
map01bf@255 9 G. J. Lieberman, McGraw-Hill, 1990.
map01bf@255 10
map01bf@255 11 Copyright (C) 1998 Yossi Rubner
map01bf@255 12 Computer Science Department, Stanford University
map01bf@255 13 E-Mail: rubner@cs.stanford.edu URL: http://vision.stanford.edu/~rubner
map01bf@255 14 */
map01bf@255 15
map01bf@255 16 #include <stdio.h>
map01bf@255 17 #include <stdlib.h>
map01bf@255 18 #include <math.h>
map01bf@255 19
map01bf@255 20 #include "emd.h"
map01bf@255 21
map01bf@255 22 #define DEBUG_LEVEL 0
map01bf@255 23 /*
map01bf@255 24 DEBUG_LEVEL:
map01bf@255 25 0 = NO MESSAGES
map01bf@255 26 1 = PRINT THE NUMBER OF ITERATIONS AND THE FINAL RESULT
map01bf@255 27 2 = PRINT THE RESULT AFTER EVERY ITERATION
map01bf@255 28 3 = PRINT ALSO THE FLOW AFTER EVERY ITERATION
map01bf@255 29 4 = PRINT A LOT OF INFORMATION (PROBABLY USEFUL ONLY FOR THE AUTHOR)
map01bf@255 30 */
map01bf@255 31
map01bf@255 32
map01bf@255 33 #define MAX_SIG_SIZE1 (MAX_SIG_SIZE+1) /* FOR THE POSIBLE DUMMY FEATURE */
map01bf@255 34
map01bf@255 35 /* NEW TYPES DEFINITION */
map01bf@255 36
map01bf@255 37 /* node1_t IS USED FOR SINGLE-LINKED LISTS */
map01bf@255 38 typedef struct node1_t {
map01bf@255 39 int i;
map01bf@255 40 double val;
map01bf@255 41 struct node1_t *Next;
map01bf@255 42 } node1_t;
map01bf@255 43
map01bf@255 44 /* node1_t IS USED FOR DOUBLE-LINKED LISTS */
map01bf@255 45 typedef struct node2_t {
map01bf@255 46 int i, j;
map01bf@255 47 double val;
map01bf@255 48 struct node2_t *NextC; /* NEXT COLUMN */
map01bf@255 49 struct node2_t *NextR; /* NEXT ROW */
map01bf@255 50 } node2_t;
map01bf@255 51
map01bf@255 52
map01bf@255 53
map01bf@255 54 /* GLOBAL VARIABLE DECLARATION */
map01bf@255 55 static int _n1, _n2; /* SIGNATURES SIZES */
map01bf@255 56 static float _C[MAX_SIG_SIZE1][MAX_SIG_SIZE1];/* THE COST MATRIX */
map01bf@255 57 static node2_t _X[MAX_SIG_SIZE1*2]; /* THE BASIC VARIABLES VECTOR */
map01bf@255 58 /* VARIABLES TO HANDLE _X EFFICIENTLY */
map01bf@255 59 static node2_t *_EndX, *_EnterX;
map01bf@255 60 static char _IsX[MAX_SIG_SIZE1][MAX_SIG_SIZE1];
map01bf@255 61 static node2_t *_RowsX[MAX_SIG_SIZE1], *_ColsX[MAX_SIG_SIZE1];
map01bf@255 62 static double _maxW;
map01bf@255 63 static float _maxC;
map01bf@255 64
map01bf@255 65 /* DECLARATION OF FUNCTIONS */
map01bf@255 66 static float init(signature_t *Signature1, signature_t *Signature2,
map01bf@255 67 float (*Dist)(feature_t *, feature_t *));
map01bf@255 68 static void findBasicVariables(node1_t *U, node1_t *V);
map01bf@255 69 static int isOptimal(node1_t *U, node1_t *V);
map01bf@255 70 static int findLoop(node2_t **Loop);
map01bf@255 71 static void newSol();
map01bf@255 72 static void russel(double *S, double *D);
map01bf@255 73 static void addBasicVariable(int minI, int minJ, double *S, double *D,
map01bf@255 74 node1_t *PrevUMinI, node1_t *PrevVMinJ,
map01bf@255 75 node1_t *UHead);
map01bf@255 76 #if DEBUG_LEVEL > 0
map01bf@255 77 static void printSolution();
map01bf@255 78 #endif
map01bf@255 79
map01bf@255 80
map01bf@255 81 /******************************************************************************
map01bf@255 82 float emd(signature_t *Signature1, signature_t *Signature2,
map01bf@255 83 float (*Dist)(feature_t *, feature_t *), flow_t *Flow, int *FlowSize)
map01bf@255 84
map01bf@255 85 where
map01bf@255 86
map01bf@255 87 Signature1, Signature2 Pointers to signatures that their distance we want
map01bf@255 88 to compute.
map01bf@255 89 Dist Pointer to the ground distance. i.e. the function that computes
map01bf@255 90 the distance between two features.
map01bf@255 91 Flow (Optional) Pointer to a vector of flow_t (defined in emd.h)
map01bf@255 92 where the resulting flow will be stored. Flow must have n1+n2-1
map01bf@255 93 elements, where n1 and n2 are the sizes of the two signatures
map01bf@255 94 respectively.
map01bf@255 95 If NULL, the flow is not returned.
map01bf@255 96 FlowSize (Optional) Pointer to an integer where the number of elements in
map01bf@255 97 Flow will be stored
map01bf@255 98
map01bf@255 99 ******************************************************************************/
map01bf@255 100
map01bf@255 101 float emd(signature_t *Signature1, signature_t *Signature2,
map01bf@255 102 float (*Dist)(feature_t *, feature_t *),
map01bf@255 103 flow_t *Flow, int *FlowSize)
map01bf@255 104 {
map01bf@255 105 int itr;
map01bf@255 106 double totalCost;
map01bf@255 107 float w;
map01bf@255 108 node2_t *XP;
map01bf@255 109 flow_t *FlowP;
map01bf@255 110 node1_t U[MAX_SIG_SIZE1], V[MAX_SIG_SIZE1];
map01bf@255 111
map01bf@255 112 w = init(Signature1, Signature2, Dist);
map01bf@255 113
map01bf@255 114 #if DEBUG_LEVEL > 1
map01bf@255 115 printf("\nINITIAL SOLUTION:\n");
map01bf@255 116 printSolution();
map01bf@255 117 #endif
map01bf@255 118
map01bf@255 119 if (_n1 > 1 && _n2 > 1) /* IF _n1 = 1 OR _n2 = 1 THEN WE ARE DONE */
map01bf@255 120 {
map01bf@255 121 for (itr = 1; itr < MAX_ITERATIONS; itr++)
map01bf@255 122 {
map01bf@255 123 /* FIND BASIC VARIABLES */
map01bf@255 124 findBasicVariables(U, V);
map01bf@255 125
map01bf@255 126 /* CHECK FOR OPTIMALITY */
map01bf@255 127 if (isOptimal(U, V))
map01bf@255 128 break;
map01bf@255 129
map01bf@255 130 /* IMPROVE SOLUTION */
map01bf@255 131 newSol();
map01bf@255 132
map01bf@255 133 #if DEBUG_LEVEL > 1
map01bf@255 134 printf("\nITERATION # %d \n", itr);
map01bf@255 135 printSolution();
map01bf@255 136 #endif
map01bf@255 137 }
map01bf@255 138
map01bf@255 139 if (itr == MAX_ITERATIONS)
map01bf@255 140 fprintf(stderr, "emd: Maximum number of iterations has been reached (%d)\n",
map01bf@255 141 MAX_ITERATIONS);
map01bf@255 142 }
map01bf@255 143
map01bf@255 144 /* COMPUTE THE TOTAL FLOW */
map01bf@255 145 totalCost = 0;
map01bf@255 146 if (Flow != NULL)
map01bf@255 147 FlowP = Flow;
map01bf@255 148 for(XP=_X; XP < _EndX; XP++)
map01bf@255 149 {
map01bf@255 150 if (XP == _EnterX) /* _EnterX IS THE EMPTY SLOT */
map01bf@255 151 continue;
map01bf@255 152 if (XP->i == Signature1->n || XP->j == Signature2->n) /* DUMMY FEATURE */
map01bf@255 153 continue;
map01bf@255 154
map01bf@255 155 if (XP->val == 0) /* ZERO FLOW */
map01bf@255 156 continue;
map01bf@255 157
map01bf@255 158 totalCost += (double)XP->val * _C[XP->i][XP->j];
map01bf@255 159 if (Flow != NULL)
map01bf@255 160 {
map01bf@255 161 FlowP->from = XP->i;
map01bf@255 162 FlowP->to = XP->j;
map01bf@255 163 FlowP->amount = XP->val;
map01bf@255 164 FlowP++;
map01bf@255 165 }
map01bf@255 166 }
map01bf@255 167 if (Flow != NULL)
map01bf@255 168 *FlowSize = FlowP-Flow;
map01bf@255 169
map01bf@255 170 #if DEBUG_LEVEL > 0
map01bf@255 171 printf("\n*** OPTIMAL SOLUTION (%d ITERATIONS): %f ***\n", itr, totalCost);
map01bf@255 172 #endif
map01bf@255 173
map01bf@255 174 /* RETURN THE NORMALIZED COST == EMD */
map01bf@255 175 return (float)(totalCost / w);
map01bf@255 176 }
map01bf@255 177
map01bf@255 178
map01bf@255 179
map01bf@255 180
map01bf@255 181
map01bf@255 182 /**********************
map01bf@255 183 init
map01bf@255 184 **********************/
map01bf@255 185 static float init(signature_t *Signature1, signature_t *Signature2,
map01bf@255 186 float (*Dist)(feature_t *, feature_t *))
map01bf@255 187 {
map01bf@255 188 int i, j;
map01bf@255 189 double sSum, dSum, diff;
map01bf@255 190 feature_t *P1, *P2;
map01bf@255 191 double S[MAX_SIG_SIZE1], D[MAX_SIG_SIZE1];
map01bf@255 192
map01bf@255 193 _n1 = Signature1->n;
map01bf@255 194 _n2 = Signature2->n;
map01bf@255 195
map01bf@255 196 if (_n1 > MAX_SIG_SIZE || _n2 > MAX_SIG_SIZE)
map01bf@255 197 {
map01bf@255 198 fprintf(stderr, "emd: Signature size is limited to %d\n", MAX_SIG_SIZE);
map01bf@255 199 exit(1);
map01bf@255 200 }
map01bf@255 201
map01bf@255 202 /* COMPUTE THE DISTANCE MATRIX */
map01bf@255 203 _maxC = 0;
map01bf@255 204 for(i=0, P1=Signature1->Features; i < _n1; i++, P1++)
map01bf@255 205 for(j=0, P2=Signature2->Features; j < _n2; j++, P2++)
map01bf@255 206 {
map01bf@255 207 _C[i][j] = Dist(P1, P2);
map01bf@255 208 if (_C[i][j] > _maxC)
map01bf@255 209 _maxC = _C[i][j];
map01bf@255 210 }
map01bf@255 211
map01bf@255 212 /* SUM UP THE SUPPLY AND DEMAND */
map01bf@255 213 sSum = 0.0;
map01bf@255 214 for(i=0; i < _n1; i++)
map01bf@255 215 {
map01bf@255 216 S[i] = Signature1->Weights[i];
map01bf@255 217 sSum += Signature1->Weights[i];
map01bf@255 218 _RowsX[i] = NULL;
map01bf@255 219 }
map01bf@255 220 dSum = 0.0;
map01bf@255 221 for(j=0; j < _n2; j++)
map01bf@255 222 {
map01bf@255 223 D[j] = Signature2->Weights[j];
map01bf@255 224 dSum += Signature2->Weights[j];
map01bf@255 225 _ColsX[j] = NULL;
map01bf@255 226 }
map01bf@255 227
map01bf@255 228 /* IF SUPPLY DIFFERENT THAN THE DEMAND, ADD A ZERO-COST DUMMY CLUSTER */
map01bf@255 229 diff = sSum - dSum;
map01bf@255 230 if (fabs(diff) >= EPSILON * sSum)
map01bf@255 231 {
map01bf@255 232 if (diff < 0.0)
map01bf@255 233 {
map01bf@255 234 for (j=0; j < _n2; j++)
map01bf@255 235 _C[_n1][j] = 0;
map01bf@255 236 S[_n1] = -diff;
map01bf@255 237 _RowsX[_n1] = NULL;
map01bf@255 238 _n1++;
map01bf@255 239 }
map01bf@255 240 else
map01bf@255 241 {
map01bf@255 242 for (i=0; i < _n1; i++)
map01bf@255 243 _C[i][_n2] = 0;
map01bf@255 244 D[_n2] = diff;
map01bf@255 245 _ColsX[_n2] = NULL;
map01bf@255 246 _n2++;
map01bf@255 247 }
map01bf@255 248 }
map01bf@255 249
map01bf@255 250 /* INITIALIZE THE BASIC VARIABLE STRUCTURES */
map01bf@255 251 for (i=0; i < _n1; i++)
map01bf@255 252 for (j=0; j < _n2; j++)
map01bf@255 253 _IsX[i][j] = 0;
map01bf@255 254 _EndX = _X;
map01bf@255 255
map01bf@255 256 _maxW = sSum > dSum ? sSum : dSum;
map01bf@255 257
map01bf@255 258 /* FIND INITIAL SOLUTION */
map01bf@255 259 russel(S, D);
map01bf@255 260
map01bf@255 261 _EnterX = _EndX++; /* AN EMPTY SLOT (ONLY _n1+_n2-1 BASIC VARIABLES) */
map01bf@255 262
map01bf@255 263 return sSum > dSum ? dSum : sSum;
map01bf@255 264 }
map01bf@255 265
map01bf@255 266
map01bf@255 267 /**********************
map01bf@255 268 findBasicVariables
map01bf@255 269 **********************/
map01bf@255 270 static void findBasicVariables(node1_t *U, node1_t *V)
map01bf@255 271 {
map01bf@255 272 int i, j, found;
map01bf@255 273 int UfoundNum, VfoundNum;
map01bf@255 274 node1_t u0Head, u1Head, *CurU, *PrevU;
map01bf@255 275 node1_t v0Head, v1Head, *CurV, *PrevV;
map01bf@255 276
map01bf@255 277 /* INITIALIZE THE ROWS LIST (U) AND THE COLUMNS LIST (V) */
map01bf@255 278 u0Head.Next = CurU = U;
map01bf@255 279 for (i=0; i < _n1; i++)
map01bf@255 280 {
map01bf@255 281 CurU->i = i;
map01bf@255 282 CurU->Next = CurU+1;
map01bf@255 283 CurU++;
map01bf@255 284 }
map01bf@255 285 (--CurU)->Next = NULL;
map01bf@255 286 u1Head.Next = NULL;
map01bf@255 287
map01bf@255 288 CurV = V+1;
map01bf@255 289 v0Head.Next = _n2 > 1 ? V+1 : NULL;
map01bf@255 290 for (j=1; j < _n2; j++)
map01bf@255 291 {
map01bf@255 292 CurV->i = j;
map01bf@255 293 CurV->Next = CurV+1;
map01bf@255 294 CurV++;
map01bf@255 295 }
map01bf@255 296 (--CurV)->Next = NULL;
map01bf@255 297 v1Head.Next = NULL;
map01bf@255 298
map01bf@255 299 /* THERE ARE _n1+_n2 VARIABLES BUT ONLY _n1+_n2-1 INDEPENDENT EQUATIONS,
map01bf@255 300 SO SET V[0]=0 */
map01bf@255 301 V[0].i = 0;
map01bf@255 302 V[0].val = 0;
map01bf@255 303 v1Head.Next = V;
map01bf@255 304 v1Head.Next->Next = NULL;
map01bf@255 305
map01bf@255 306 /* LOOP UNTIL ALL VARIABLES ARE FOUND */
map01bf@255 307 UfoundNum=VfoundNum=0;
map01bf@255 308 while (UfoundNum < _n1 || VfoundNum < _n2)
map01bf@255 309 {
map01bf@255 310
map01bf@255 311 #if DEBUG_LEVEL > 3
map01bf@255 312 printf("UfoundNum=%d/%d,VfoundNum=%d/%d\n",UfoundNum,_n1,VfoundNum,_n2);
map01bf@255 313 printf("U0=");
map01bf@255 314 for(CurU = u0Head.Next; CurU != NULL; CurU = CurU->Next)
map01bf@255 315 printf("[%d]",CurU-U);
map01bf@255 316 printf("\n");
map01bf@255 317 printf("U1=");
map01bf@255 318 for(CurU = u1Head.Next; CurU != NULL; CurU = CurU->Next)
map01bf@255 319 printf("[%d]",CurU-U);
map01bf@255 320 printf("\n");
map01bf@255 321 printf("V0=");
map01bf@255 322 for(CurV = v0Head.Next; CurV != NULL; CurV = CurV->Next)
map01bf@255 323 printf("[%d]",CurV-V);
map01bf@255 324 printf("\n");
map01bf@255 325 printf("V1=");
map01bf@255 326 for(CurV = v1Head.Next; CurV != NULL; CurV = CurV->Next)
map01bf@255 327 printf("[%d]",CurV-V);
map01bf@255 328 printf("\n\n");
map01bf@255 329 #endif
map01bf@255 330
map01bf@255 331 found = 0;
map01bf@255 332 if (VfoundNum < _n2)
map01bf@255 333 {
map01bf@255 334 /* LOOP OVER ALL MARKED COLUMNS */
map01bf@255 335 PrevV = &v1Head;
map01bf@255 336 for (CurV=v1Head.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 337 {
map01bf@255 338 j = CurV->i;
map01bf@255 339 /* FIND THE VARIABLES IN COLUMN j */
map01bf@255 340 PrevU = &u0Head;
map01bf@255 341 for (CurU=u0Head.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 342 {
map01bf@255 343 i = CurU->i;
map01bf@255 344 if (_IsX[i][j])
map01bf@255 345 {
map01bf@255 346 /* COMPUTE U[i] */
map01bf@255 347 CurU->val = _C[i][j] - CurV->val;
map01bf@255 348 /* ...AND ADD IT TO THE MARKED LIST */
map01bf@255 349 PrevU->Next = CurU->Next;
map01bf@255 350 CurU->Next = u1Head.Next != NULL ? u1Head.Next : NULL;
map01bf@255 351 u1Head.Next = CurU;
map01bf@255 352 CurU = PrevU;
map01bf@255 353 }
map01bf@255 354 else
map01bf@255 355 PrevU = CurU;
map01bf@255 356 }
map01bf@255 357 PrevV->Next = CurV->Next;
map01bf@255 358 VfoundNum++;
map01bf@255 359 found = 1;
map01bf@255 360 }
map01bf@255 361 }
map01bf@255 362 if (UfoundNum < _n1)
map01bf@255 363 {
map01bf@255 364 /* LOOP OVER ALL MARKED ROWS */
map01bf@255 365 PrevU = &u1Head;
map01bf@255 366 for (CurU=u1Head.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 367 {
map01bf@255 368 i = CurU->i;
map01bf@255 369 /* FIND THE VARIABLES IN ROWS i */
map01bf@255 370 PrevV = &v0Head;
map01bf@255 371 for (CurV=v0Head.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 372 {
map01bf@255 373 j = CurV->i;
map01bf@255 374 if (_IsX[i][j])
map01bf@255 375 {
map01bf@255 376 /* COMPUTE V[j] */
map01bf@255 377 CurV->val = _C[i][j] - CurU->val;
map01bf@255 378 /* ...AND ADD IT TO THE MARKED LIST */
map01bf@255 379 PrevV->Next = CurV->Next;
map01bf@255 380 CurV->Next = v1Head.Next != NULL ? v1Head.Next: NULL;
map01bf@255 381 v1Head.Next = CurV;
map01bf@255 382 CurV = PrevV;
map01bf@255 383 }
map01bf@255 384 else
map01bf@255 385 PrevV = CurV;
map01bf@255 386 }
map01bf@255 387 PrevU->Next = CurU->Next;
map01bf@255 388 UfoundNum++;
map01bf@255 389 found = 1;
map01bf@255 390 }
map01bf@255 391 }
map01bf@255 392 if (! found)
map01bf@255 393 {
map01bf@255 394 fprintf(stderr, "emd: Unexpected error in findBasicVariables!\n");
map01bf@255 395 fprintf(stderr, "This typically happens when the EPSILON defined in\n");
map01bf@255 396 fprintf(stderr, "emd.h is not right for the scale of the problem.\n");
map01bf@255 397 exit(1);
map01bf@255 398 }
map01bf@255 399 }
map01bf@255 400 }
map01bf@255 401
map01bf@255 402
map01bf@255 403
map01bf@255 404
map01bf@255 405 /**********************
map01bf@255 406 isOptimal
map01bf@255 407 **********************/
map01bf@255 408 static int isOptimal(node1_t *U, node1_t *V)
map01bf@255 409 {
map01bf@255 410 double delta, deltaMin;
map01bf@255 411 int i, j, minI, minJ;
map01bf@255 412
map01bf@255 413 /* FIND THE MINIMAL Cij-Ui-Vj OVER ALL i,j */
map01bf@255 414 deltaMin = INFINITY;
map01bf@255 415 for(i=0; i < _n1; i++)
map01bf@255 416 for(j=0; j < _n2; j++)
map01bf@255 417 if (! _IsX[i][j])
map01bf@255 418 {
map01bf@255 419 delta = _C[i][j] - U[i].val - V[j].val;
map01bf@255 420 if (deltaMin > delta)
map01bf@255 421 {
map01bf@255 422 deltaMin = delta;
map01bf@255 423 minI = i;
map01bf@255 424 minJ = j;
map01bf@255 425 }
map01bf@255 426 }
map01bf@255 427
map01bf@255 428 #if DEBUG_LEVEL > 3
map01bf@255 429 printf("deltaMin=%f\n", deltaMin);
map01bf@255 430 #endif
map01bf@255 431
map01bf@255 432 if (deltaMin == INFINITY)
map01bf@255 433 {
map01bf@255 434 fprintf(stderr, "emd: Unexpected error in isOptimal.\n");
map01bf@255 435 exit(0);
map01bf@255 436 }
map01bf@255 437
map01bf@255 438 _EnterX->i = minI;
map01bf@255 439 _EnterX->j = minJ;
map01bf@255 440
map01bf@255 441 /* IF NO NEGATIVE deltaMin, WE FOUND THE OPTIMAL SOLUTION */
map01bf@255 442 return deltaMin >= -EPSILON * _maxC;
map01bf@255 443
map01bf@255 444 /*
map01bf@255 445 return deltaMin >= -EPSILON;
map01bf@255 446 */
map01bf@255 447 }
map01bf@255 448
map01bf@255 449
map01bf@255 450 /**********************
map01bf@255 451 newSol
map01bf@255 452 **********************/
map01bf@255 453 static void newSol()
map01bf@255 454 {
map01bf@255 455 int i, j, k;
map01bf@255 456 double xMin;
map01bf@255 457 int steps;
map01bf@255 458 node2_t *Loop[2*MAX_SIG_SIZE1], *CurX, *LeaveX;
map01bf@255 459
map01bf@255 460 #if DEBUG_LEVEL > 3
map01bf@255 461 printf("EnterX = (%d,%d)\n", _EnterX->i, _EnterX->j);
map01bf@255 462 #endif
map01bf@255 463
map01bf@255 464 /* ENTER THE NEW BASIC VARIABLE */
map01bf@255 465 i = _EnterX->i;
map01bf@255 466 j = _EnterX->j;
map01bf@255 467 _IsX[i][j] = 1;
map01bf@255 468 _EnterX->NextC = _RowsX[i];
map01bf@255 469 _EnterX->NextR = _ColsX[j];
map01bf@255 470 _EnterX->val = 0;
map01bf@255 471 _RowsX[i] = _EnterX;
map01bf@255 472 _ColsX[j] = _EnterX;
map01bf@255 473
map01bf@255 474 /* FIND A CHAIN REACTION */
map01bf@255 475 steps = findLoop(Loop);
map01bf@255 476
map01bf@255 477 /* FIND THE LARGEST VALUE IN THE LOOP */
map01bf@255 478 xMin = INFINITY;
map01bf@255 479 for (k=1; k < steps; k+=2)
map01bf@255 480 {
map01bf@255 481 if (Loop[k]->val < xMin)
map01bf@255 482 {
map01bf@255 483 LeaveX = Loop[k];
map01bf@255 484 xMin = Loop[k]->val;
map01bf@255 485 }
map01bf@255 486 }
map01bf@255 487
map01bf@255 488 /* UPDATE THE LOOP */
map01bf@255 489 for (k=0; k < steps; k+=2)
map01bf@255 490 {
map01bf@255 491 Loop[k]->val += xMin;
map01bf@255 492 Loop[k+1]->val -= xMin;
map01bf@255 493 }
map01bf@255 494
map01bf@255 495 #if DEBUG_LEVEL > 3
map01bf@255 496 printf("LeaveX = (%d,%d)\n", LeaveX->i, LeaveX->j);
map01bf@255 497 #endif
map01bf@255 498
map01bf@255 499 /* REMOVE THE LEAVING BASIC VARIABLE */
map01bf@255 500 i = LeaveX->i;
map01bf@255 501 j = LeaveX->j;
map01bf@255 502 _IsX[i][j] = 0;
map01bf@255 503 if (_RowsX[i] == LeaveX)
map01bf@255 504 _RowsX[i] = LeaveX->NextC;
map01bf@255 505 else
map01bf@255 506 for (CurX=_RowsX[i]; CurX != NULL; CurX = CurX->NextC)
map01bf@255 507 if (CurX->NextC == LeaveX)
map01bf@255 508 {
map01bf@255 509 CurX->NextC = CurX->NextC->NextC;
map01bf@255 510 break;
map01bf@255 511 }
map01bf@255 512 if (_ColsX[j] == LeaveX)
map01bf@255 513 _ColsX[j] = LeaveX->NextR;
map01bf@255 514 else
map01bf@255 515 for (CurX=_ColsX[j]; CurX != NULL; CurX = CurX->NextR)
map01bf@255 516 if (CurX->NextR == LeaveX)
map01bf@255 517 {
map01bf@255 518 CurX->NextR = CurX->NextR->NextR;
map01bf@255 519 break;
map01bf@255 520 }
map01bf@255 521
map01bf@255 522 /* SET _EnterX TO BE THE NEW EMPTY SLOT */
map01bf@255 523 _EnterX = LeaveX;
map01bf@255 524 }
map01bf@255 525
map01bf@255 526
map01bf@255 527
map01bf@255 528 /**********************
map01bf@255 529 findLoop
map01bf@255 530 **********************/
map01bf@255 531 static int findLoop(node2_t **Loop)
map01bf@255 532 {
map01bf@255 533 int i, steps;
map01bf@255 534 node2_t **CurX, *NewX;
map01bf@255 535 char IsUsed[2*MAX_SIG_SIZE1];
map01bf@255 536
map01bf@255 537 for (i=0; i < _n1+_n2; i++)
map01bf@255 538 IsUsed[i] = 0;
map01bf@255 539
map01bf@255 540 CurX = Loop;
map01bf@255 541 NewX = *CurX = _EnterX;
map01bf@255 542 IsUsed[_EnterX-_X] = 1;
map01bf@255 543 steps = 1;
map01bf@255 544
map01bf@255 545 do
map01bf@255 546 {
map01bf@255 547 if (steps%2 == 1)
map01bf@255 548 {
map01bf@255 549 /* FIND AN UNUSED X IN THE ROW */
map01bf@255 550 NewX = _RowsX[NewX->i];
map01bf@255 551 while (NewX != NULL && IsUsed[NewX-_X])
map01bf@255 552 NewX = NewX->NextC;
map01bf@255 553 }
map01bf@255 554 else
map01bf@255 555 {
map01bf@255 556 /* FIND AN UNUSED X IN THE COLUMN, OR THE ENTERING X */
map01bf@255 557 NewX = _ColsX[NewX->j];
map01bf@255 558 while (NewX != NULL && IsUsed[NewX-_X] && NewX != _EnterX)
map01bf@255 559 NewX = NewX->NextR;
map01bf@255 560 if (NewX == _EnterX)
map01bf@255 561 break;
map01bf@255 562 }
map01bf@255 563
map01bf@255 564 if (NewX != NULL) /* FOUND THE NEXT X */
map01bf@255 565 {
map01bf@255 566 /* ADD X TO THE LOOP */
map01bf@255 567 *++CurX = NewX;
map01bf@255 568 IsUsed[NewX-_X] = 1;
map01bf@255 569 steps++;
map01bf@255 570 #if DEBUG_LEVEL > 3
map01bf@255 571 printf("steps=%d, NewX=(%d,%d)\n", steps, NewX->i, NewX->j);
map01bf@255 572 #endif
map01bf@255 573 }
map01bf@255 574 else /* DIDN'T FIND THE NEXT X */
map01bf@255 575 {
map01bf@255 576 /* BACKTRACK */
map01bf@255 577 do
map01bf@255 578 {
map01bf@255 579 NewX = *CurX;
map01bf@255 580 do
map01bf@255 581 {
map01bf@255 582 if (steps%2 == 1)
map01bf@255 583 NewX = NewX->NextR;
map01bf@255 584 else
map01bf@255 585 NewX = NewX->NextC;
map01bf@255 586 } while (NewX != NULL && IsUsed[NewX-_X]);
map01bf@255 587
map01bf@255 588 if (NewX == NULL)
map01bf@255 589 {
map01bf@255 590 IsUsed[*CurX-_X] = 0;
map01bf@255 591 CurX--;
map01bf@255 592 steps--;
map01bf@255 593 }
map01bf@255 594 } while (NewX == NULL && CurX >= Loop);
map01bf@255 595
map01bf@255 596 #if DEBUG_LEVEL > 3
map01bf@255 597 printf("BACKTRACKING TO: steps=%d, NewX=(%d,%d)\n",
map01bf@255 598 steps, NewX->i, NewX->j);
map01bf@255 599 #endif
map01bf@255 600 IsUsed[*CurX-_X] = 0;
map01bf@255 601 *CurX = NewX;
map01bf@255 602 IsUsed[NewX-_X] = 1;
map01bf@255 603 }
map01bf@255 604 } while(CurX >= Loop);
map01bf@255 605
map01bf@255 606 if (CurX == Loop)
map01bf@255 607 {
map01bf@255 608 fprintf(stderr, "emd: Unexpected error in findLoop!\n");
map01bf@255 609 exit(1);
map01bf@255 610 }
map01bf@255 611 #if DEBUG_LEVEL > 3
map01bf@255 612 printf("FOUND LOOP:\n");
map01bf@255 613 for (i=0; i < steps; i++)
map01bf@255 614 printf("%d: (%d,%d)\n", i, Loop[i]->i, Loop[i]->j);
map01bf@255 615 #endif
map01bf@255 616
map01bf@255 617 return steps;
map01bf@255 618 }
map01bf@255 619
map01bf@255 620
map01bf@255 621
map01bf@255 622 /**********************
map01bf@255 623 russel
map01bf@255 624 **********************/
map01bf@255 625 static void russel(double *S, double *D)
map01bf@255 626 {
map01bf@255 627 int i, j, found, minI, minJ;
map01bf@255 628 double deltaMin, oldVal, diff;
map01bf@255 629 double Delta[MAX_SIG_SIZE1][MAX_SIG_SIZE1];
map01bf@255 630 node1_t Ur[MAX_SIG_SIZE1], Vr[MAX_SIG_SIZE1];
map01bf@255 631 node1_t uHead, *CurU, *PrevU;
map01bf@255 632 node1_t vHead, *CurV, *PrevV;
map01bf@255 633 node1_t *PrevUMinI, *PrevVMinJ, *Remember;
map01bf@255 634
map01bf@255 635 /* INITIALIZE THE ROWS LIST (Ur), AND THE COLUMNS LIST (Vr) */
map01bf@255 636 uHead.Next = CurU = Ur;
map01bf@255 637 for (i=0; i < _n1; i++)
map01bf@255 638 {
map01bf@255 639 CurU->i = i;
map01bf@255 640 CurU->val = -INFINITY;
map01bf@255 641 CurU->Next = CurU+1;
map01bf@255 642 CurU++;
map01bf@255 643 }
map01bf@255 644 (--CurU)->Next = NULL;
map01bf@255 645
map01bf@255 646 vHead.Next = CurV = Vr;
map01bf@255 647 for (j=0; j < _n2; j++)
map01bf@255 648 {
map01bf@255 649 CurV->i = j;
map01bf@255 650 CurV->val = -INFINITY;
map01bf@255 651 CurV->Next = CurV+1;
map01bf@255 652 CurV++;
map01bf@255 653 }
map01bf@255 654 (--CurV)->Next = NULL;
map01bf@255 655
map01bf@255 656 /* FIND THE MAXIMUM ROW AND COLUMN VALUES (Ur[i] AND Vr[j]) */
map01bf@255 657 for(i=0; i < _n1 ; i++)
map01bf@255 658 for(j=0; j < _n2 ; j++)
map01bf@255 659 {
map01bf@255 660 float v;
map01bf@255 661 v = _C[i][j];
map01bf@255 662 if (Ur[i].val <= v)
map01bf@255 663 Ur[i].val = v;
map01bf@255 664 if (Vr[j].val <= v)
map01bf@255 665 Vr[j].val = v;
map01bf@255 666 }
map01bf@255 667
map01bf@255 668 /* COMPUTE THE Delta MATRIX */
map01bf@255 669 for(i=0; i < _n1 ; i++)
map01bf@255 670 for(j=0; j < _n2 ; j++)
map01bf@255 671 Delta[i][j] = _C[i][j] - Ur[i].val - Vr[j].val;
map01bf@255 672
map01bf@255 673 /* FIND THE BASIC VARIABLES */
map01bf@255 674 do
map01bf@255 675 {
map01bf@255 676 #if DEBUG_LEVEL > 3
map01bf@255 677 printf("Ur=");
map01bf@255 678 for(CurU = uHead.Next; CurU != NULL; CurU = CurU->Next)
map01bf@255 679 printf("[%d]",CurU-Ur);
map01bf@255 680 printf("\n");
map01bf@255 681 printf("Vr=");
map01bf@255 682 for(CurV = vHead.Next; CurV != NULL; CurV = CurV->Next)
map01bf@255 683 printf("[%d]",CurV-Vr);
map01bf@255 684 printf("\n");
map01bf@255 685 printf("\n\n");
map01bf@255 686 #endif
map01bf@255 687
map01bf@255 688 /* FIND THE SMALLEST Delta[i][j] */
map01bf@255 689 found = 0;
map01bf@255 690 deltaMin = INFINITY;
map01bf@255 691 PrevU = &uHead;
map01bf@255 692 for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 693 {
map01bf@255 694 int i;
map01bf@255 695 i = CurU->i;
map01bf@255 696 PrevV = &vHead;
map01bf@255 697 for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 698 {
map01bf@255 699 int j;
map01bf@255 700 j = CurV->i;
map01bf@255 701 if (deltaMin > Delta[i][j])
map01bf@255 702 {
map01bf@255 703 deltaMin = Delta[i][j];
map01bf@255 704 minI = i;
map01bf@255 705 minJ = j;
map01bf@255 706 PrevUMinI = PrevU;
map01bf@255 707 PrevVMinJ = PrevV;
map01bf@255 708 found = 1;
map01bf@255 709 }
map01bf@255 710 PrevV = CurV;
map01bf@255 711 }
map01bf@255 712 PrevU = CurU;
map01bf@255 713 }
map01bf@255 714
map01bf@255 715 if (! found)
map01bf@255 716 break;
map01bf@255 717
map01bf@255 718 /* ADD X[minI][minJ] TO THE BASIS, AND ADJUST SUPPLIES AND COST */
map01bf@255 719 Remember = PrevUMinI->Next;
map01bf@255 720 addBasicVariable(minI, minJ, S, D, PrevUMinI, PrevVMinJ, &uHead);
map01bf@255 721
map01bf@255 722 /* UPDATE THE NECESSARY Delta[][] */
map01bf@255 723 if (Remember == PrevUMinI->Next) /* LINE minI WAS DELETED */
map01bf@255 724 {
map01bf@255 725 for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 726 {
map01bf@255 727 int j;
map01bf@255 728 j = CurV->i;
map01bf@255 729 if (CurV->val == _C[minI][j]) /* COLUMN j NEEDS UPDATING */
map01bf@255 730 {
map01bf@255 731 /* FIND THE NEW MAXIMUM VALUE IN THE COLUMN */
map01bf@255 732 oldVal = CurV->val;
map01bf@255 733 CurV->val = -INFINITY;
map01bf@255 734 for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 735 {
map01bf@255 736 int i;
map01bf@255 737 i = CurU->i;
map01bf@255 738 if (CurV->val <= _C[i][j])
map01bf@255 739 CurV->val = _C[i][j];
map01bf@255 740 }
map01bf@255 741
map01bf@255 742 /* IF NEEDED, ADJUST THE RELEVANT Delta[*][j] */
map01bf@255 743 diff = oldVal - CurV->val;
map01bf@255 744 if (fabs(diff) < EPSILON * _maxC)
map01bf@255 745 for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 746 Delta[CurU->i][j] += diff;
map01bf@255 747 }
map01bf@255 748 }
map01bf@255 749 }
map01bf@255 750 else /* COLUMN minJ WAS DELETED */
map01bf@255 751 {
map01bf@255 752 for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next)
map01bf@255 753 {
map01bf@255 754 int i;
map01bf@255 755 i = CurU->i;
map01bf@255 756 if (CurU->val == _C[i][minJ]) /* ROW i NEEDS UPDATING */
map01bf@255 757 {
map01bf@255 758 /* FIND THE NEW MAXIMUM VALUE IN THE ROW */
map01bf@255 759 oldVal = CurU->val;
map01bf@255 760 CurU->val = -INFINITY;
map01bf@255 761 for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 762 {
map01bf@255 763 int j;
map01bf@255 764 j = CurV->i;
map01bf@255 765 if(CurU->val <= _C[i][j])
map01bf@255 766 CurU->val = _C[i][j];
map01bf@255 767 }
map01bf@255 768
map01bf@255 769 /* If NEEDED, ADJUST THE RELEVANT Delta[i][*] */
map01bf@255 770 diff = oldVal - CurU->val;
map01bf@255 771 if (fabs(diff) < EPSILON * _maxC)
map01bf@255 772 for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next)
map01bf@255 773 Delta[i][CurV->i] += diff;
map01bf@255 774 }
map01bf@255 775 }
map01bf@255 776 }
map01bf@255 777 } while (uHead.Next != NULL || vHead.Next != NULL);
map01bf@255 778 }
map01bf@255 779
map01bf@255 780
map01bf@255 781
map01bf@255 782
map01bf@255 783 /**********************
map01bf@255 784 addBasicVariable
map01bf@255 785 **********************/
map01bf@255 786 static void addBasicVariable(int minI, int minJ, double *S, double *D,
map01bf@255 787 node1_t *PrevUMinI, node1_t *PrevVMinJ,
map01bf@255 788 node1_t *UHead)
map01bf@255 789 {
map01bf@255 790 double T;
map01bf@255 791
map01bf@255 792 if (fabs(S[minI]-D[minJ]) <= EPSILON * _maxW) /* DEGENERATE CASE */
map01bf@255 793 {
map01bf@255 794 T = S[minI];
map01bf@255 795 S[minI] = 0;
map01bf@255 796 D[minJ] -= T;
map01bf@255 797 }
map01bf@255 798 else if (S[minI] < D[minJ]) /* SUPPLY EXHAUSTED */
map01bf@255 799 {
map01bf@255 800 T = S[minI];
map01bf@255 801 S[minI] = 0;
map01bf@255 802 D[minJ] -= T;
map01bf@255 803 }
map01bf@255 804 else /* DEMAND EXHAUSTED */
map01bf@255 805 {
map01bf@255 806 T = D[minJ];
map01bf@255 807 D[minJ] = 0;
map01bf@255 808 S[minI] -= T;
map01bf@255 809 }
map01bf@255 810
map01bf@255 811 /* X(minI,minJ) IS A BASIC VARIABLE */
map01bf@255 812 _IsX[minI][minJ] = 1;
map01bf@255 813
map01bf@255 814 _EndX->val = T;
map01bf@255 815 _EndX->i = minI;
map01bf@255 816 _EndX->j = minJ;
map01bf@255 817 _EndX->NextC = _RowsX[minI];
map01bf@255 818 _EndX->NextR = _ColsX[minJ];
map01bf@255 819 _RowsX[minI] = _EndX;
map01bf@255 820 _ColsX[minJ] = _EndX;
map01bf@255 821 _EndX++;
map01bf@255 822
map01bf@255 823 /* DELETE SUPPLY ROW ONLY IF THE EMPTY, AND IF NOT LAST ROW */
map01bf@255 824 if (S[minI] == 0 && UHead->Next->Next != NULL)
map01bf@255 825 PrevUMinI->Next = PrevUMinI->Next->Next; /* REMOVE ROW FROM LIST */
map01bf@255 826 else
map01bf@255 827 PrevVMinJ->Next = PrevVMinJ->Next->Next; /* REMOVE COLUMN FROM LIST */
map01bf@255 828 }
map01bf@255 829
map01bf@255 830
map01bf@255 831
map01bf@255 832
map01bf@255 833
map01bf@255 834 /**********************
map01bf@255 835 printSolution
map01bf@255 836 **********************/
map01bf@255 837 static void printSolution()
map01bf@255 838 {
map01bf@255 839 node2_t *P;
map01bf@255 840 double totalCost;
map01bf@255 841
map01bf@255 842 totalCost = 0;
map01bf@255 843
map01bf@255 844 #if DEBUG_LEVEL > 2
map01bf@255 845 printf("SIG1\tSIG2\tFLOW\tCOST\n");
map01bf@255 846 #endif
map01bf@255 847 for(P=_X; P < _EndX; P++)
map01bf@255 848 if (P != _EnterX && _IsX[P->i][P->j])
map01bf@255 849 {
map01bf@255 850 #if DEBUG_LEVEL > 2
map01bf@255 851 printf("%d\t%d\t%f\t%f\n", P->i, P->j, P->val, _C[P->i][P->j]);
map01bf@255 852 #endif
map01bf@255 853 totalCost += (double)P->val * _C[P->i][P->j];
map01bf@255 854 }
map01bf@255 855
map01bf@255 856 printf("COST = %f\n", totalCost);
map01bf@255 857 }
map01bf@255 858
map01bf@255 859