ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/transportSimplex.h
Revision: 2.1
Committed: Wed Mar 26 02:52:31 2014 UTC (10 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad4R2, rad4R2P1
Log Message:
Changed to optimized transport matrix computation

File Contents

# User Rev Content
1 greg 2.1 /* RCSid $Id$ */
2     /*
3     transportSimplex.h
4    
5     A C++ implementation of the transportation simplex algorithm.
6    
7     Last edit Sept 3 2006
8    
9     Copyright (C) 2006 Darren MacDonald
10     [email protected]
11     www.site.uottawa.ca/~dmacd070/emd
12    
13     except some data structures and interface adapted from
14     http://ai.stanford.edu/~rubner/emd/emd.c,
15     Copyright 1998 Yossi Rubner.
16    
17     This algorithm solves the problem of finding the least-cost way to transport
18     goods from a set of source (supply) nodes to a set of sink (demand) nodes.
19    
20     To use the code, simply include this file in the user code and add 'using namespace t_simplex;'.
21     Organize the nodes into signatures using the TsSignature<TF> class, which contains a feature
22     array (of type TF) and an array of the respective weights of the features.
23    
24     Solve the system by calling
25     transportSimplex(&Sig1, &Sig2, grndDist);
26     where Sig1 is the source signature, containing an array of source features and an array of their respective
27     supplies, Sig2 is the sink signature, containing the sink features and and their respective demands, and
28     grndDist is a pointer to a function which accepts two features pointers as arguments and returns the unit
29     cost of transporting goods between the two.
30    
31     transportSimplex either returns the optimal transportation cost or throws a TsError.
32    
33     For more information see the documentation at
34     www.site.uottawa.ca/~dmacd070/emd/index.html
35     and the example implemenation at
36     www.site.uottawa.ca/~dmacd070/emd/main.cpp.
37     */
38    
39     #ifndef _T_SIMPLEX_H
40     #define _T_SIMPLEX_H
41     #include <iostream>
42     #include <stdlib.h>
43     #include <math.h>
44     #include <new>
45    
46     #define TSINFINITY 1e20
47     #define TSEPSILON 1e-6
48     #define TSPIVOTLIMIT 0.00
49    
50     namespace t_simplex {
51    
52     /* DECLARATION OF DATA TYPES */
53     enum TsError { TsErrBadInput };
54    
55     //TsSignature is used for inputting the source and sink signatures
56     template <class TF>
57     class TsSignature {
58     public:
59     int n; // Number of features in the signature
60     TF *features; // Pointer to the features vector
61     double *weights; // Pointer to the weights of the features
62     TsSignature(int nin, TF *fin, double * win):n(nin), features(fin), weights(win){};
63     };
64    
65     //TsFlow is used for outputting the final flow table
66     typedef struct TsFlow {
67     int from; // Feature number in signature 1
68     int to; // Feature number in signature 2
69     double amount; // Amount of flow from signature1.features[from] to signature2.features[to]
70     } TsFlow;
71    
72     // TsBasic is used for 2D lists, allowing for easy navigation of the basic variables
73     typedef struct TsBasic{
74     int i, j;
75     double val;
76     TsBasic *nextSnk, *prevSnk; // next/previous node in the column
77     TsBasic *nextSrc, *prevSrc; // next/previous node in the row
78     } TsBasic;
79    
80     // TsStone is used for _BFS
81     typedef struct TsStone {
82     struct TsStone *prev;
83     struct TsBasic *node;
84     } TsStone;
85    
86     // TsRusPen is used for 1D lists in _initRussel
87     typedef struct TsRusPen {
88     int i;
89     double val;
90     struct TsRusPen *next, *prev;
91     } TsRusPen;
92    
93     // TsVogPen is used for 1D lists in _initVogel
94     typedef struct TsVogPen {
95     int i;
96     struct TsVogPen *next, *prev;
97     int one, two;
98     double oneCost, twoCost;
99     } TsVogPen;
100    
101     /* DECLARATION OF GLOBALS */
102     double ** _tsC = NULL; // Cost matrix
103     double _tsMaxC; // Maximum of all costs
104     double _tsMaxW; // Maximum of all weights
105    
106    
107     /* INTERNAL FUNCTIONS */
108     double _pivot(TsBasic * basics, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2);
109     TsStone * _BFS(TsStone *stoneTree, TsBasic ** srcBasics, TsBasic ** snkBasics, bool complete = false);
110     void _initVogel(double *S, double *D, TsBasic * basicsEnd, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2);
111     void _initRussel(double *S, double *D, TsBasic * basicsEnd, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2);
112    
113     /*
114     transportSimplex() - Program entry point.
115    
116     signature1 and signature2 define the source and sink sets. Unit costs between two features are computed from
117     grndDist. Signature weights must be positive and all costs must be positive.
118     TsFlow is an output parameter which can be set to an array that will be filled with the final flow amounts.
119     The array must be of size signature1->n + signature2->n - 1 . flowSize is a pointer to an integer which
120     indicates the number of functional entries in Flow, because all spaces are not necessarily used. Flow and
121     flowSize can be set to NULL or omitted from the argument list if this information is not important.
122    
123     The return value is the transportation cost.
124    
125     */
126     template <class TF>
127     double transportSimplex(TsSignature<TF> *signature1, TsSignature<TF> *signature2, double (*grndDist)(TF *, TF *),
128     TsFlow *flowTable = NULL, int *flowSize = NULL) {
129    
130     int n1, n2; // number of features in signature1 and Signature 2
131     int i, j;
132    
133     double totalCost;
134     double w;
135    
136     double srcSum, snkSum, diff;
137    
138     TF *P1, *P2;
139    
140     n1 = signature1->n;
141     n2 = signature2->n;
142    
143     TsBasic * basics = NULL; ///Array of basic variables.
144     bool ** isBasic = NULL; //Flag matrix. isBasic[i][j] is true there is flow between source i and sink j
145     TsBasic **srcBasics = NULL; //Array of pointers to the first basic variable in each row
146     TsBasic **snkBasics = NULL; //Array of pointers to the first basic variable in each column
147     double * src = NULL; //Array of source supplies
148     double * snk =NULL; //Array of sink demands
149    
150    
151     // Equalize source and sink weights. A dummy source or sink may be added to equalize the total sink
152     // and source weights. n1 = signature1->n + 1 if there is a dummy source, and n2 = signature2->n + 1
153     // if there is a dummy sink.
154     srcSum = 0.0;
155     for(i=0; i < n1; i++)
156     srcSum += signature1->weights[i];
157    
158     snkSum = 0.0;
159     for(j=0; j < n2; j++)
160     snkSum += signature2->weights[j];
161    
162     diff = srcSum - snkSum;
163     if (fabs(diff) > TSEPSILON * srcSum)
164     if (diff < 0.0)
165     n1++;
166     else
167     n2++;
168    
169     _tsMaxW = srcSum > snkSum ? srcSum : snkSum;
170     w = srcSum < snkSum ? srcSum : snkSum;
171    
172     //Allocate memory for arrays
173     try {
174    
175     basics = new TsBasic[n1 + n2];
176    
177     isBasic = new bool*[n1];
178     for(i = 0; i < n1; i++)
179     isBasic[i] = NULL;
180    
181     for(i = 0; i < n1; i++) {
182     isBasic[i] = new bool[n2];
183     for (j=0; j < n2; j++)
184     isBasic[i][j] = 0;
185     }
186    
187     srcBasics = new TsBasic*[n1];
188     for (i = 0; i < n1; i++)
189     srcBasics[i] = NULL;
190    
191     snkBasics = new TsBasic*[n2];
192     for (i = 0; i < n2; i++)
193     snkBasics[i] = NULL;
194    
195     // Compute the cost matrix
196     _tsMaxC = 0;
197     _tsC = new double*[n1];
198     for(i=0; i < n1; i++)
199     _tsC[i] = NULL;
200    
201     for(i=0, P1=signature1->features; i < n1; i++, P1++) {
202     _tsC[i] = new double[n2]; //What happens if bad here?
203     for(j=0, P2=signature2->features; j < n2; j++, P2++) {
204     if (i == signature1->n || j == signature2->n) {
205     _tsC[i][j] = 0; // cost is zero for flow to or from a dummy
206     } else {
207     _tsC[i][j] = grndDist(P1, P2);
208     if (_tsC[i][j] < 0) throw TsErrBadInput;
209     }
210    
211    
212     if (_tsC[i][j] > _tsMaxC)
213     _tsMaxC = _tsC[i][j];
214     }
215     }
216    
217     src = new double[n1]; //init the source array
218     for (i = 0; i < signature1->n; i++) {
219     src[i] = signature1->weights[i];
220     if (src[i] < 0) throw TsErrBadInput;
221     }
222     if (n1 != signature1->n)
223     src[signature1->n] = -diff;
224    
225     snk = new double[n2]; //init the sink array
226     for (i = 0; i < signature2->n; i++) {
227     snk[i] = signature2->weights[i];
228     if (snk[i] < 0) throw TsErrBadInput;
229     }
230     if (n2 != signature2->n)
231     snk[signature2->n] = diff;
232    
233     // Find the initail basic feasible solution. Use either _initRussel or _initVogel
234    
235    
236     _initRussel(src, snk, basics, srcBasics, snkBasics, isBasic, n1, n2);
237     //_initVogel(src, snk, basics, srcBasics, snkBasics, isBasic, n1, n2);
238    
239    
240     // Enter the main pivot loop
241     totalCost = _pivot(basics, srcBasics, snkBasics, isBasic, n1, n2);
242    
243     } catch (...) {
244     for(i = 0; i < n1; i++)
245     delete[] isBasic[i];
246     delete[] isBasic;
247    
248     for (i = 0; i < n1; i++)
249     delete[] _tsC[i];
250     delete[] _tsC;
251    
252     delete[] src;
253     delete[] snk;
254     delete[] srcBasics;
255     delete[] snkBasics;
256     delete[] basics;
257    
258     throw;
259     }
260    
261     // Fill the Flow data structure
262     TsBasic * basicPtr;
263     TsFlow * flowPtr = flowTable;
264     if (flowTable != NULL) {
265     for (i = 0; i < n1+n2 -1; i++) {
266     basicPtr = basics + i;
267     if (isBasic[basicPtr->i][basicPtr->j] && basicPtr->i != signature1->n && basicPtr->j != signature2->n && basicPtr->val != 0.0) {
268     flowPtr->to = basicPtr->j;
269     flowPtr->from = basicPtr->i;
270     flowPtr->amount = basicPtr->val;
271     flowPtr++;
272     }
273     }
274     }
275     if (flowSize != NULL) {
276     *flowSize = (int)(flowPtr - flowTable);
277     }
278    
279    
280     for(i = 0; i < n1; i++)
281     delete[] isBasic[i];
282     delete[] isBasic;
283    
284     for (i = 0; i < n1; i++)
285     delete[] _tsC[i];
286     delete[] _tsC;
287    
288     delete[] src;
289     delete[] snk;
290     delete[] srcBasics;
291     delete[] snkBasics;
292     delete[] basics;
293    
294     return totalCost;
295     }
296    
297     /*
298     Main pivot loop.
299     Pivots until the system is optimal and return the optimal transportation cost.
300     */
301     double _pivot(TsBasic * basics, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2) {
302    
303     double * srcDuals = NULL;
304     double * snkDuals = NULL;
305     TsStone * stonePath = NULL;
306    
307     TsStone * spitra, * spitrb, * leaving;
308     TsBasic * XP;
309     TsBasic * basicsEnd = basics + n1 + n2;
310     TsBasic * entering = basicsEnd - 1 ;
311     TsBasic dummyBasic;
312     dummyBasic.i = -1;
313     dummyBasic.j = 0;
314    
315     int i,j, lowI, lowJ;
316     double objectiveValue = TSINFINITY, oldObjectiveValue = 0;
317     double lowVal;
318     int numPivots = 0;
319    
320     try {
321     srcDuals = new double[n1];
322     snkDuals = new double[n2];
323     stonePath = new TsStone[n1 + n2];
324     } catch (std::bad_alloc) {
325     delete[] srcDuals;
326     delete[] snkDuals;
327     delete[] stonePath;
328     throw;
329     }
330    
331     while (1) {
332    
333     oldObjectiveValue = objectiveValue;
334     objectiveValue = 0;
335    
336     for (XP = basics; XP != basicsEnd; XP++){
337     if (XP != entering)
338     objectiveValue += _tsC[XP->i][XP->j] * XP->val;
339     }
340    
341     // Compute the dual variables for each row and column. Begin by finding a spanning tree (stonepath)
342     // of the basic variables using the breadth-first search routine seeded at an imaginary basic
343     // variable in the first column. The dual variables can then be computed incrementally by traversing
344     // the tree.
345     stonePath[0].node = &dummyBasic;
346     stonePath[0].prev = NULL;
347     spitrb = _BFS(stonePath, srcBasics, snkBasics, true);
348    
349     spitra = stonePath;
350     snkDuals[spitra->node->j] = 0;
351     for (spitra++; spitra != spitrb; spitra++) {
352     if (spitra->node->i == spitra->prev->node->i) {
353     //node is in same row as parent
354     snkDuals[spitra->node->j] = _tsC[spitra->node->i][spitra->node->j] - srcDuals[spitra->node->i];
355     } else if (spitra->node->j == spitra->prev->node->j) {
356     srcDuals[spitra->node->i] = _tsC[spitra->node->i][spitra->node->j] - snkDuals[spitra->node->j];
357     }
358     }
359    
360     // After computing the duals, find the non-basic variable that has the greatest negative value of
361     // delta = _tsC[i][j] - srcDuals[i] - snkDuals[j]. This is the entering variable
362     lowVal = 0.0;
363     for (i = 0; i < n1; i++)
364     for (j = 0; j < n2; j++)
365     if (!isBasic[i][j] && _tsC[i][j] - srcDuals[i] - snkDuals[j] < lowVal) {
366     lowVal = _tsC[i][j] - srcDuals[i] - snkDuals[j];
367     lowI = i;
368     lowJ = j;
369     }
370    
371     // If all delta values are non-negative, the table is optimal
372     if (lowVal >= -TSEPSILON * _tsMaxC || (oldObjectiveValue - objectiveValue) < TSPIVOTLIMIT) {
373     delete[] srcDuals;
374     delete[] snkDuals;
375     delete[] stonePath;
376     //std::cout << numPivots << "\t";
377     return objectiveValue;
378     }
379    
380     // Add the entering variable
381     entering->i = lowI;
382     entering->j = lowJ;
383     isBasic[lowI][lowJ] = 1;
384     entering->val = 0;
385    
386     entering->nextSrc = srcBasics[lowI];
387     if (srcBasics[lowI] != NULL) srcBasics[lowI]->prevSrc = entering;
388     entering->nextSnk = snkBasics[lowJ];
389     if (snkBasics[lowJ] != NULL) snkBasics[lowJ]->prevSnk = entering;
390    
391     srcBasics[lowI] = entering;
392     entering->prevSrc = srcBasics[lowI];
393     snkBasics[lowJ] = entering;
394     entering->prevSnk = snkBasics[lowJ];
395    
396     stonePath[0].node = entering;
397     stonePath[0].prev = NULL;
398    
399     // Use breadth-first search to find a loop of basics.
400     spitra = spitrb = _BFS(stonePath, srcBasics, snkBasics);
401     lowVal = TSINFINITY;
402     bool add = false;
403    
404     // Find the lowest flow along the loop (leaving variable)
405     do {
406     if (!add && spitrb->node->val < lowVal) {
407     leaving = spitrb;
408     lowVal = spitrb->node->val;
409     }
410     add = !add;
411     } while (spitrb = spitrb->prev);
412    
413     add = false;
414     spitrb = spitra;
415    
416     // Alternately increase and decrease flow along the loop
417     do {
418     if (add) spitrb->node->val += lowVal;
419     else spitrb->node->val -= lowVal;
420     add = !add;
421     } while (spitrb = spitrb->prev);
422    
423     i = leaving->node->i;
424     j = leaving->node->j;
425     isBasic[i][j] = 0;
426    
427    
428     if (srcBasics[i] == leaving->node) {
429     srcBasics[i] = leaving->node->nextSrc;
430     srcBasics[i]->prevSrc = NULL;
431     } else {
432     leaving->node->prevSrc->nextSrc = leaving->node->nextSrc;
433     if (leaving->node->nextSrc != NULL)
434     leaving->node->nextSrc->prevSrc = leaving->node->prevSrc;
435     }
436    
437     if (snkBasics[j] == leaving->node) {
438     snkBasics[j] = leaving->node->nextSnk;
439     snkBasics[j]->prevSnk = NULL;
440     } else {
441     leaving->node->prevSnk->nextSnk = leaving->node->nextSnk;
442     if (leaving->node->nextSnk != NULL)
443     leaving->node->nextSnk->prevSnk = leaving->node->prevSnk;
444     }
445     entering = leaving->node;
446     numPivots++;
447     }
448     };
449    
450    
451     /*******************
452     _BFS
453     Perform a breadth-first search of the basic varaibles. The search tree is stored in stoneTree, where each
454     'stone' contains a pointer to a basic variable, and a pointer to that stone's parent. srcBasics and snkBasics
455     are arrays of linked lists which allow for easy identification of a node's neighbours in the flow network.
456     If complete == true, find all basics in the table. Otherwise, terminate when a basic variable which completes
457     a loop has been found and return a pointer to the final stone in the loop.
458     *********************/
459     TsStone * _BFS(TsStone * stoneTree, TsBasic ** srcBasics, TsBasic ** snkBasics, bool complete) {
460     bool column = true;
461     int jumpoffset = 0;
462     TsBasic * bitr;
463     TsStone * sitra = &stoneTree[0], * sitrb = &stoneTree[1];
464     do {
465     if (column) {
466     for (bitr = snkBasics[sitra->node->j]; bitr != NULL; bitr = bitr->nextSnk) {
467     if (bitr != sitra->node){
468     sitrb->node = bitr;
469     sitrb->prev = sitra;
470     sitrb++;
471     }
472     }
473     } else {
474     for (bitr = srcBasics[sitra->node->i]; bitr != NULL; bitr = bitr->nextSrc) {
475     if (bitr != sitra->node){
476     sitrb->node = bitr;
477     sitrb->prev = sitra;
478     sitrb++;
479     }
480     }
481     }
482    
483     sitra++;
484     if (sitra == sitrb) //no cycle found and no cycles in tree
485     return sitra;
486    
487     if (sitra->node->i == sitra->prev->node->i)
488     column = true;
489     else
490     column = false;
491    
492     // cycle found
493     if (!complete && sitra->node->i == stoneTree[0].node->i && sitra->node->j != stoneTree[0].node->j && column == false)
494     return sitra;
495     } while(1);
496     }
497    
498    
499     // Helper function for _initVogel
500     inline void addPenalty(TsVogPen * pitr, double cost, int i) {
501     if (cost < pitr->oneCost) {
502     pitr->twoCost = pitr->oneCost;
503     pitr->two = pitr->one;
504     pitr->oneCost = cost;
505     pitr->one = i;
506     } else if (cost < pitr->twoCost) {
507     pitr->twoCost = cost;
508     pitr->two = i;
509     }
510     }
511    
512    
513     /**********************
514     Vogel's initialization method
515     **********************/
516     void _initVogel(double *S, double *D, TsBasic * basicsEnd, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2) {
517     int i, j;
518     TsVogPen *srcPens = NULL;
519     TsVogPen *snkPens = NULL;
520     TsVogPen *pitra, *pitrb; //iterators
521     TsVogPen *maxPen;
522     TsVogPen srcPenHead, snkPenHead;
523     bool maxIsSrc;
524     double lowVal;
525    
526     try {
527     srcPens = new TsVogPen[n1];
528     snkPens = new TsVogPen[n2];
529     } catch (std::bad_alloc) {
530     delete[] srcPens;
531     delete[] snkPens;
532     throw;
533     }
534    
535     srcPenHead.next = pitra = srcPens;
536     for (i=0; i < n1; i++) {
537     pitra->i = i;
538     pitra->next = pitra+1;
539     pitra->prev = pitra-1;
540     pitra->one = pitra->two = 0;
541     pitra->oneCost = pitra->twoCost = TSINFINITY;
542     pitra++;
543     }
544     (--pitra)->next = NULL;
545     srcPens[0].prev = &srcPenHead;
546    
547     snkPenHead.next = pitra = snkPens;
548     for (i=0; i < n2; i++) {
549     pitra->i = i;
550     pitra->next = pitra+1;
551     pitra->prev = pitra-1;
552     pitra->one = pitra->two = 0;
553     pitra->oneCost = pitra->twoCost = TSINFINITY;
554     pitra++;
555     }
556     (--pitra)->next = NULL;
557     snkPens[0].prev = &snkPenHead;
558    
559    
560     for (pitra = srcPenHead.next, i=0; pitra != NULL; pitra = pitra->next, i++)
561     for (pitrb = snkPenHead.next, j=0; pitrb != NULL; pitrb = pitrb->next, j++) {
562     //initialize Source Penalties;
563     addPenalty(pitra, _tsC[i][j], j);
564     addPenalty(pitrb, _tsC[i][j], i);
565     }
566    
567    
568     while (srcPenHead.next != NULL && snkPenHead.next != NULL) {
569     maxIsSrc = true;
570     for (maxPen = pitra = srcPenHead.next; pitra != NULL; pitra = pitra->next)
571     if ((pitra->twoCost - pitra->oneCost) > (maxPen->twoCost - maxPen->oneCost))
572     maxPen = pitra;
573    
574     for (pitra = snkPenHead.next; pitra != NULL; pitra = pitra->next)
575     if ((pitra->twoCost - pitra->oneCost) > (maxPen->twoCost - maxPen->oneCost)) {
576     maxPen = pitra;
577     maxIsSrc = false;
578     }
579    
580     if (maxIsSrc) {
581     i = maxPen->i;
582     j = maxPen->one;
583     } else {
584     j = maxPen->i;
585     i = maxPen->one;
586     }
587    
588     if (D[j] - S[i] > _tsMaxW * TSEPSILON || (srcPenHead.next->next != NULL && fabs(S[i] - D[j]) < _tsMaxW * TSEPSILON)) {
589     //delete source
590     lowVal = S[i];
591     maxPen = srcPens + i;
592     maxPen->prev->next = maxPen->next;
593     if (maxPen->next != NULL)
594     maxPen->next->prev = maxPen->prev;
595    
596     for (pitra = snkPenHead.next; pitra != NULL; pitra = pitra->next) {
597     if (pitra->one == i || pitra->two == i){
598     pitra->oneCost = TSINFINITY;
599     pitra->twoCost = TSINFINITY;
600     for (pitrb = srcPenHead.next; pitrb != NULL; pitrb = pitrb->next)
601     addPenalty(pitra, _tsC[pitrb->i][pitra->i], pitrb->i);
602     }
603     }
604     } else {
605     //delete sink
606     lowVal = D[j];
607     maxPen = snkPens + j;
608     maxPen->prev->next = maxPen->next;
609     if (maxPen->next != NULL)
610     maxPen->next->prev = maxPen->prev;
611    
612     for (pitra = srcPenHead.next; pitra != NULL; pitra = pitra->next) {
613     if (pitra->one == j || pitra->two == j){
614     pitra->oneCost = TSINFINITY;
615     pitra->twoCost = TSINFINITY;
616     for (pitrb = snkPenHead.next; pitrb != NULL; pitrb = pitrb->next)
617     addPenalty(pitra, _tsC[pitra->i][pitrb->i], pitrb->i);
618     }
619     }
620     }
621    
622     S[i] -= lowVal;
623     D[j] -= lowVal;
624    
625     isBasic[i][j] = 1;
626     basicsEnd->val = lowVal;
627     basicsEnd->i = i;
628     basicsEnd->j = j;
629    
630     basicsEnd->nextSnk = snkBasics[j];
631     if (snkBasics[j] != NULL) snkBasics[j]->prevSnk = basicsEnd;
632     basicsEnd->nextSrc = srcBasics[i];
633     if (srcBasics[i] != NULL) srcBasics[i]->prevSrc = basicsEnd;
634    
635     srcBasics[i] = basicsEnd;
636     basicsEnd->prevSnk = NULL;
637     snkBasics[j] = basicsEnd;
638     basicsEnd->prevSrc = NULL;
639    
640     basicsEnd++;
641    
642     }
643     delete[] srcPens;
644     delete[] snkPens;
645     }
646    
647    
648     /**********************
649     Russel's initialization method
650     **********************/
651     void _initRussel(double *S, double *D, TsBasic * basicsEnd, TsBasic ** srcBasics, TsBasic ** snkBasics, bool ** isBasic, int n1, int n2) {
652     double ** Delta = NULL;
653     int i, j, lowI, lowJ;
654     TsRusPen *U = NULL;
655     TsRusPen *V = NULL;
656     TsRusPen *Uhead, *Vhead;
657     TsRusPen *Uitr, *Vitr;
658     double cost, lowVal;
659    
660     try {
661     Delta = new double*[n1];
662     for (i = 0; i < n1; i++)
663     Delta[i] = new double[n2];
664    
665     U = new TsRusPen[n1];
666     V = new TsRusPen[n2];
667     } catch (std::bad_alloc) {
668     for (i = 0; i < n1; i++)
669     delete[] Delta[i];
670     delete[] Delta;
671    
672     delete[] U;
673     delete[] V;
674     throw;
675     }
676    
677     for (i = 0; i < n1; i++) {
678     U[i].i = i;
679     U[i].val = 0;
680     U[i].next = &U[i+1];
681     U[i].prev = &U[i-1];
682     }
683     U[n1-1].next = NULL;
684     U[0].prev = NULL;
685    
686     for (i = 0; i < n2; i++) {
687     V[i].i = i;
688     V[i].val = 0;
689     V[i].next = &V[i+1];
690     V[i].prev = &V[i-1];
691     }
692     V[n2-1].next = NULL;
693     V[0].prev = NULL;
694    
695     for (i = 0; i < n1; i++)
696     for (j = 0; j < n2; j++) {
697     cost = _tsC[i][j];
698     if (cost > U[i].val)
699     U[i].val = cost;
700     if (cost > V[j].val)
701     V[j].val = cost;
702     }
703    
704     for (i = 0; i < n1; i++)
705     for (j = 0; j < n2; j++)
706     Delta[i][j] = _tsC[i][j] - U[i].val - V[j].val;
707    
708     Uhead = U;
709     Vhead = V;
710     while (Uhead != NULL && Vhead != NULL) {
711    
712     //Find lowest Delta
713     lowVal = TSINFINITY;
714     for (Uitr = Uhead; Uitr != NULL; Uitr = Uitr->next)
715     for (Vitr = Vhead; Vitr != NULL; Vitr = Vitr->next)
716     if (Delta[Uitr->i][Vitr->i] < lowVal) {
717     lowI = Uitr->i;
718     lowJ = Vitr->i;
719     lowVal = Delta[Uitr->i][Vitr->i];
720     }
721    
722    
723     if (D[lowJ] - S[lowI] > _tsMaxW * TSEPSILON || (fabs(S[lowI] - D[lowJ]) < _tsMaxW * TSEPSILON && Uhead->next != NULL)) {
724     //Delete Source
725     if (&U[lowI] == Uhead) { //Entering variable is first in list
726     Uhead = Uhead->next;
727     if (Uhead != NULL) Uhead->prev = NULL;
728     } else {
729     U[lowI].prev->next = U[lowI].next; //Entering variable is in middle of list;
730     if (U[lowI].next != NULL) //Entering variable is at the end of the list;
731     U[lowI].next->prev = U[lowI].prev;
732     }
733     //See if this source was the maximum cost for any dest
734     for (Vitr = Vhead; Vitr != NULL; Vitr = Vitr->next) {
735     if (Vitr->val == _tsC[lowI][Vitr->i]) {
736     //it is; update the dest
737     //find maximum cost in the dest
738     Vitr->val = 0;
739     for (Uitr = Uhead; Uitr != NULL; Uitr = Uitr->next)
740     if (_tsC[Uitr->i][Vitr->i] > Vitr->val)
741     Vitr->val = _tsC[Uitr->i][Vitr->i];
742     //update Delta
743     for (Uitr = Uhead; Uitr != NULL; Uitr = Uitr->next)
744     Delta[Uitr->i][Vitr->i] = _tsC[Uitr->i][Vitr->i] - Uitr->val - Vitr->val;
745    
746     }
747     }
748     lowVal = S[lowI];
749    
750     } else {
751     //Delete Dest
752     if (&V[lowJ] == Vhead) { //Entering variable is first in list
753     Vhead = Vhead->next;
754     if (Vhead != NULL) Vhead->prev = NULL;
755     } else {
756     V[lowJ].prev->next = V[lowJ].next; //Entering variable is in middle of list;
757     if (V[lowJ].next != NULL) //Entering variable is at the end of the list;
758     V[lowJ].next->prev = V[lowJ].prev;
759     }
760     //See if this source was the maximum cost for any dest
761     for (Uitr = Uhead; Uitr != NULL; Uitr = Uitr->next) {
762     if (Uitr->val == _tsC[Uitr->i][lowJ]) {
763     //it is; update the dest
764     //find maximum cost in the dest
765     Uitr->val = 0;
766     for (Vitr = Vhead; Vitr != NULL; Vitr = Vitr->next)
767     if (_tsC[Uitr->i][Vitr->i] > Uitr->val)
768     Uitr->val = _tsC[Uitr->i][Vitr->i];
769     //update Delta
770     for (Vitr = Vhead; Vitr != NULL; Vitr = Vitr->next)
771     Delta[Uitr->i][Vitr->i] = _tsC[Uitr->i][Vitr->i] - Uitr->val - Vitr->val;
772    
773     }
774     }
775     lowVal = D[lowJ];
776     }
777    
778     S[lowI] -= lowVal;
779     D[lowJ] -= lowVal;
780    
781     isBasic[lowI][lowJ] = 1;
782     basicsEnd->val = lowVal;
783     basicsEnd->i = lowI;
784     basicsEnd->j = lowJ;
785    
786     basicsEnd->nextSnk = snkBasics[lowJ];
787     if (snkBasics[lowJ] != NULL) snkBasics[lowJ]->prevSnk = basicsEnd;
788     basicsEnd->nextSrc = srcBasics[lowI];
789     if (srcBasics[lowI] != NULL) srcBasics[lowI]->prevSrc = basicsEnd;
790    
791     srcBasics[lowI] = basicsEnd;
792     basicsEnd->prevSnk = NULL;
793     snkBasics[lowJ] = basicsEnd;
794     basicsEnd->prevSrc = NULL;
795    
796     basicsEnd++;
797    
798     }
799    
800     delete[] U;
801     delete[] V;
802     for (i = 0; i < n1; i++)
803     delete[] Delta[i];
804     delete[] Delta;
805     }
806     }
807     #endif
808