📄 emd.c
字号:
if (deltaMin == INFINITY)
{
fprintf(stderr, "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)
{
fprintf(stderr, "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 + -