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