📄 emd.c
字号:
if (deltaMin == INFINITY) { mexErrMsgTxt("emd: Unexpected error in isOptimal.\n"); /*exit(0);*/ } _EnterX->i = minI; _EnterX->j = minJ; /* IF NO NEGATIVE deltaMin, WE FOUND THE OPTIMAL SOLUTION */ return deltaMin >= -EPSILON * _maxC;/* return deltaMin >= -EPSILON; */}/********************** newSol**********************/static void newSol(){ int i, j, k; double xMin; int steps; node2_t *Loop[2*MAX_SIG_SIZE1], *CurX, *LeaveX; #if DEBUG_LEVEL > 3 printf("EnterX = (%d,%d)\n", _EnterX->i, _EnterX->j);#endif /* ENTER THE NEW BASIC VARIABLE */ i = _EnterX->i; j = _EnterX->j; _IsX[i][j] = 1; _EnterX->NextC = _RowsX[i]; _EnterX->NextR = _ColsX[j]; _EnterX->val = 0; _RowsX[i] = _EnterX; _ColsX[j] = _EnterX; /* FIND A CHAIN REACTION */ steps = findLoop(Loop); /* FIND THE LARGEST VALUE IN THE LOOP */ xMin = INFINITY; for (k=1; k < steps; k+=2) { if (Loop[k]->val < xMin) { LeaveX = Loop[k]; xMin = Loop[k]->val; } } /* UPDATE THE LOOP */ for (k=0; k < steps; k+=2) { Loop[k]->val += xMin; Loop[k+1]->val -= xMin; }#if DEBUG_LEVEL > 3 printf("LeaveX = (%d,%d)\n", LeaveX->i, LeaveX->j);#endif /* REMOVE THE LEAVING BASIC VARIABLE */ i = LeaveX->i; j = LeaveX->j; _IsX[i][j] = 0; if (_RowsX[i] == LeaveX) _RowsX[i] = LeaveX->NextC; else for (CurX=_RowsX[i]; CurX != NULL; CurX = CurX->NextC) if (CurX->NextC == LeaveX) { CurX->NextC = CurX->NextC->NextC; break; } if (_ColsX[j] == LeaveX) _ColsX[j] = LeaveX->NextR; else for (CurX=_ColsX[j]; CurX != NULL; CurX = CurX->NextR) if (CurX->NextR == LeaveX) { CurX->NextR = CurX->NextR->NextR; break; } /* SET _EnterX TO BE THE NEW EMPTY SLOT */ _EnterX = LeaveX;}/********************** findLoop**********************/static int findLoop(node2_t **Loop){ int i, steps; node2_t **CurX, *NewX; char IsUsed[2*MAX_SIG_SIZE1]; for (i=0; i < _n1+_n2; i++) IsUsed[i] = 0; CurX = Loop; NewX = *CurX = _EnterX; IsUsed[_EnterX-_X] = 1; steps = 1; do { if (steps%2 == 1) { /* FIND AN UNUSED X IN THE ROW */ NewX = _RowsX[NewX->i]; while (NewX != NULL && IsUsed[NewX-_X]) NewX = NewX->NextC; } else { /* FIND AN UNUSED X IN THE COLUMN, OR THE ENTERING X */ NewX = _ColsX[NewX->j]; while (NewX != NULL && IsUsed[NewX-_X] && NewX != _EnterX) NewX = NewX->NextR; if (NewX == _EnterX) break; } if (NewX != NULL) /* FOUND THE NEXT X */ { /* ADD X TO THE LOOP */ *++CurX = NewX; IsUsed[NewX-_X] = 1; steps++;#if DEBUG_LEVEL > 3 printf("steps=%d, NewX=(%d,%d)\n", steps, NewX->i, NewX->j); #endif } else /* DIDN'T FIND THE NEXT X */ { /* BACKTRACK */ do { NewX = *CurX; do { if (steps%2 == 1) NewX = NewX->NextR; else NewX = NewX->NextC; } while (NewX != NULL && IsUsed[NewX-_X]); if (NewX == NULL) { IsUsed[*CurX-_X] = 0; CurX--; steps--; } } while (NewX == NULL && CurX >= Loop); #if DEBUG_LEVEL > 3 printf("BACKTRACKING TO: steps=%d, NewX=(%d,%d)\n", steps, NewX->i, NewX->j); #endif IsUsed[*CurX-_X] = 0; *CurX = NewX; IsUsed[NewX-_X] = 1; } } while(CurX >= Loop); if (CurX == Loop) { mexErrMsgTxt( "emd: Unexpected error in findLoop!\n"); /*exit(1);*/ }#if DEBUG_LEVEL > 3 printf("FOUND LOOP:\n"); for (i=0; i < steps; i++) printf("%d: (%d,%d)\n", i, Loop[i]->i, Loop[i]->j);#endif return steps;}/********************** russel**********************/static void russel(double *S, double *D){ int i, j, found, minI, minJ; double deltaMin, oldVal, diff; double Delta[MAX_SIG_SIZE1][MAX_SIG_SIZE1]; node1_t Ur[MAX_SIG_SIZE1], Vr[MAX_SIG_SIZE1]; node1_t uHead, *CurU, *PrevU; node1_t vHead, *CurV, *PrevV; node1_t *PrevUMinI, *PrevVMinJ, *Remember; /* INITIALIZE THE ROWS LIST (Ur), AND THE COLUMNS LIST (Vr) */ uHead.Next = CurU = Ur; for (i=0; i < _n1; i++) { CurU->i = i; CurU->val = -INFINITY; CurU->Next = CurU+1; CurU++; } (--CurU)->Next = NULL; vHead.Next = CurV = Vr; for (j=0; j < _n2; j++) { CurV->i = j; CurV->val = -INFINITY; CurV->Next = CurV+1; CurV++; } (--CurV)->Next = NULL; /* FIND THE MAXIMUM ROW AND COLUMN VALUES (Ur[i] AND Vr[j]) */ for(i=0; i < _n1 ; i++) for(j=0; j < _n2 ; j++) { float v; v = _C[i][j]; if (Ur[i].val <= v) Ur[i].val = v; if (Vr[j].val <= v) Vr[j].val = v; } /* COMPUTE THE Delta MATRIX */ for(i=0; i < _n1 ; i++) for(j=0; j < _n2 ; j++) Delta[i][j] = _C[i][j] - Ur[i].val - Vr[j].val; /* FIND THE BASIC VARIABLES */ do {#if DEBUG_LEVEL > 3 printf("Ur="); for(CurU = uHead.Next; CurU != NULL; CurU = CurU->Next) printf("[%d]",CurU-Ur); printf("\n"); printf("Vr="); for(CurV = vHead.Next; CurV != NULL; CurV = CurV->Next) printf("[%d]",CurV-Vr); printf("\n"); printf("\n\n");#endif /* FIND THE SMALLEST Delta[i][j] */ found = 0; deltaMin = INFINITY; PrevU = &uHead; for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next) { int i; i = CurU->i; PrevV = &vHead; for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next) { int j; j = CurV->i; if (deltaMin > Delta[i][j]) { deltaMin = Delta[i][j]; minI = i; minJ = j; PrevUMinI = PrevU; PrevVMinJ = PrevV; found = 1; } PrevV = CurV; } PrevU = CurU; } if (! found) break; /* ADD X[minI][minJ] TO THE BASIS, AND ADJUST SUPPLIES AND COST */ Remember = PrevUMinI->Next; addBasicVariable(minI, minJ, S, D, PrevUMinI, PrevVMinJ, &uHead); /* UPDATE THE NECESSARY Delta[][] */ if (Remember == PrevUMinI->Next) /* LINE minI WAS DELETED */ { for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next) { int j; j = CurV->i; if (CurV->val == _C[minI][j]) /* COLUMN j NEEDS UPDATING */ { /* FIND THE NEW MAXIMUM VALUE IN THE COLUMN */ oldVal = CurV->val; CurV->val = -INFINITY; for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next) { int i; i = CurU->i; if (CurV->val <= _C[i][j]) CurV->val = _C[i][j]; } /* IF NEEDED, ADJUST THE RELEVANT Delta[*][j] */ diff = oldVal - CurV->val; if (fabs(diff) < EPSILON * _maxC) for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next) Delta[CurU->i][j] += diff; } } } else /* COLUMN minJ WAS DELETED */ { for (CurU=uHead.Next; CurU != NULL; CurU=CurU->Next) { int i; i = CurU->i; if (CurU->val == _C[i][minJ]) /* ROW i NEEDS UPDATING */ { /* FIND THE NEW MAXIMUM VALUE IN THE ROW */ oldVal = CurU->val; CurU->val = -INFINITY; for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next) { int j; j = CurV->i; if(CurU->val <= _C[i][j]) CurU->val = _C[i][j]; } /* If NEEDED, ADJUST THE RELEVANT Delta[i][*] */ diff = oldVal - CurU->val; if (fabs(diff) < EPSILON * _maxC) for (CurV=vHead.Next; CurV != NULL; CurV=CurV->Next) Delta[i][CurV->i] += diff; } } } } while (uHead.Next != NULL || vHead.Next != NULL);}/********************** addBasicVariable**********************/static void addBasicVariable(int minI, int minJ, double *S, double *D, node1_t *PrevUMinI, node1_t *PrevVMinJ, node1_t *UHead){ double T; if (fabs(S[minI]-D[minJ]) <= EPSILON * _maxW) /* DEGENERATE CASE */ { T = S[minI]; S[minI] = 0; D[minJ] -= T; } else if (S[minI] < D[minJ]) /* SUPPLY EXHAUSTED */ { T = S[minI]; S[minI] = 0; D[minJ] -= T; } else /* DEMAND EXHAUSTED */ { T = D[minJ]; D[minJ] = 0; S[minI] -= T; } /* X(minI,minJ) IS A BASIC VARIABLE */ _IsX[minI][minJ] = 1; _EndX->val = T; _EndX->i = minI; _EndX->j = minJ; _EndX->NextC = _RowsX[minI]; _EndX->NextR = _ColsX[minJ]; _RowsX[minI] = _EndX; _ColsX[minJ] = _EndX; _EndX++; /* DELETE SUPPLY ROW ONLY IF THE EMPTY, AND IF NOT LAST ROW */ if (S[minI] == 0 && UHead->Next->Next != NULL) PrevUMinI->Next = PrevUMinI->Next->Next; /* REMOVE ROW FROM LIST */ else PrevVMinJ->Next = PrevVMinJ->Next->Next; /* REMOVE COLUMN FROM LIST */}/********************** printSolution**********************/static void printSolution(){ node2_t *P; double totalCost; totalCost = 0;#if DEBUG_LEVEL > 2 printf("SIG1\tSIG2\tFLOW\tCOST\n");#endif for(P=_X; P < _EndX; P++) if (P != _EnterX && _IsX[P->i][P->j]) {#if DEBUG_LEVEL > 2 printf("%d\t%d\t%f\t%f\n", P->i, P->j, P->val, _C[P->i][P->j]);#endif totalCost += (double)P->val * _C[P->i][P->j]; } printf("COST = %f\n", totalCost);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -