The idea of the algorithm is that it should find the optimum assignment rows to columns minimising the cost of the matrix. from what i can tell i've followed the code on the above website to the letter (apart from adding various debug stuff) while converting, however the code is getting stuck in an endless loop between steps 4 and 6. I am desperately in need of a solution to this so any help would be fantastic. The code is self contained including a main() to test if its working as it should.
If its working correctly it should assign row 1 to column 2, row 2 to column 4, row 3 to column 3 and row 4 to column 1. which i *think* will be shown in M, resulting with something like...
M= |0 1 0 0 |
| 0 0 0 1 |
| 0 0 1 0 |
| 1 0 0 0 |
anyway, have a look at the code (please) and see if you can help, or if you know anywhere where this algorithm is implimented already or have done it yourself that would be fantastic, but i'd really like to get this working myself if possible cos i've spent way too much time on this now, i hate to admit defeat so posting here is a last resort.
#include <iostream>
#include <String>
using namespace std;
class Munkrees {
public:
float** C;
int** M;
int** path;
private:
int *row;
int *col;
bool *C_cov;
bool *R_cov;
int aRow;
int aCol;
int Z0_r;
int Z0_c;
float minval;//should be right
float minvalOld;
int n;//todo remove n so algn works for rectangular arrays properly
public:
int rows;
int columns;
Munkrees(int inRows,int inColumns, float** matrix) {
//aRow=0;
//aCol=0;
rows = inRows;
columns = inColumns;
cout<<"rows = "<<rows<<", columns = "<<columns<<endl;
if(!rows==columns) {
cout<<"rows!=columns - Algorithm undetermined"<<endl;
}
else {
n=rows;
}
cout<<"init"<<endl;
cout<<endl;
cout<<"rows = "<<rows<<", columns = "<<columns<<endl;
printArray(matrix, rows, columns, "matrix");
cout<<"rows = "<<rows<<", columns = "<<columns<<endl;
C= new float* [rows];
for (int i=0; i<rows; i++){
C[i]= new float [columns];
}
for (int i = 0; i<rows;i++) {
for (int j = 0; j<columns; j++ ) {
C[i][j] = matrix[i][j];
}
}
printArray(C, rows,columns,"C");
C_cov = new bool[columns];
for (int i = 0; i<columns;i++) {
C_cov[i] = false;
}
R_cov = new bool[rows];
for (int i = 0; i<rows;i++) {
R_cov[i] = false;
}
M = new int* [rows];
for (int i=0; i<rows; i++){
M[i]= new int [columns];
}
for (int i = 0; i<rows;i++) {
for (int j = 0; j<columns;j++) {
M[i][j] = 0;
}
}
printArray(M, 4,4,"M");
path = new int* [rows];
for (int i=0; i<rows; i++){
path[i]= new int [columns];
}
for (int i = 0; i<rows;i++) {
for (int j = 0; j<columns;j++) {
path[i][j] = 0;
}
}
printArray(path, 4,4,"path");
row = new int[rows];
col = new int[columns];
int stepnum=1;
int aRow=0;
int aCol=0;
int Z0_r=0;
int Z0_c=0;
minval=999;//should be right
minvalOld=minval;//used in step6
bool done=false;
int* returnVal = new int[2];
cout<<"End Init!"<<endl;
while (!done) {
switch(stepnum){
case 1:
stepnum=step1(stepnum);
cout<<"Step1--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
case 2:
stepnum=step2(stepnum);
cout<<"Step2--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
case 3:
stepnum=step3(stepnum);
cout<<"Step3--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
case 4:
stepnum=step4(stepnum);
cout<<"Step4--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
case 5:
stepnum=step5(stepnum);
cout<<"Step5--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
case 6:
stepnum=step6(stepnum);
cout<<"Step6--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
default:
done=true;
cout<<"Step=Done--------------------------------------------------"<<endl;
printArray(C, 4,4,"C");
printArray(M, 4,4,"M");
printArray(path, 4,4,"path");
break;
}
}
cout<<"Printing M"<<endl;
for (int i = 0; i<rows;i++) {
for (int j = 0; j<columns; j++ ) {
matrix[i][j] = (float)M[i][j];
cout << M[i][j]<<"\t";
}
cout<<endl;
}
delete C;
}
private:
int step1(int stepnum){
//For each row of the matrix, find the smallest element and
//subtract it from every element in its row. Go to Step 2
for (int i = 0; i < n; i++) {
minval=C[i][0];
for(int j = 0; j < n; j++) {
if (minval>C[i][j]) {
minval=C[i][j];
}
}
for (int j = 0; j < n; j++) {
C[i][j] =C[i][j]-minval;
}
}
return 2;
}
int step2(int stepnum){
//Find a zero (Z) in the resulting matrix. If there is no starred
//zero in its row or column, star Z. Repeat for each element in the
//matrix. Go to Step 3.
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if ( C[i][j]==0 && C_cov[j]==0 && R_cov[i]==0 ){
M[i][j]=1;
C_cov[j]=1;
R_cov[i]=1;
}
}
}
for (int i = 0; i<n; i++) {//TODO: this line will fail for non square matricies
C_cov[i]=0;
R_cov[i]=0;
}
return 3;
}
int step3(int stepnum){
//Cover each column containing a starred zero.
//If K columns are covered, the starred zeros describe a
//complete set of unique assignments. In this case, Go to DONE
//otherwise, Go to Step 4.
int count;
for (int i = 0; i<rows; i++) {
for (int j = 0; j<columns; j++){
if (M[i][j]==1 ) {
C_cov[j]=1;
}
}
}
count=0;
for (int j = 0; j<rows; j++){
count=count + C_cov[j];
}
if (count>=rows) {
//we're done here
return 7;
}
else {
return 4;
}
}
int step4(int stepnum){
//Find a noncovered zero and prime it. If there is no starred
//zero in the row containing this primed zero, Go to Step 5.
//Otherwise, cover this row and uncover the column containing
//the starred zero. Continue in this manner until there are no
//uncovered zeros left. Save the smallest uncovered value and Go to Step 6
int step;
bool done=false;
while (!done){
cout<<"aRow = "<<aRow;
find_a_zero();
cout<<", and after find_a_zero() aRow = "<<aRow<<endl;
if (aRow==0) {
done=true;
step = 6;
}
else {
M[aRow][aCol]=2;
if (starInRow(aRow)) {
aCol = findStarInRow(aRow);
R_cov[aRow]=1;
C_cov[aCol]=0;
}
else {
done=true;
Z0_r=aRow;
Z0_c=aCol;
step= 5;
}
}
return step;
}
//TODO: this shouldnt be here (return 6) ??
cout<< "Step 4 returning 6 from a place where we shouldnt be?"<<endl;;
return 6;
}
int step5(int stepnum){
//Construct a series of alternating primed and starred zeros
//as follows. Let Z0 represent the uncovered primed zero
//found in Step 4. Let Z1 denote the starred zero in the
//column of Z0 (if any). Let Z2 denote the primed zero in
//the row of Z1 (there will always be one). Continue
//until the series terminates at a primed zero that has
//no starred zero in its column. Unstar each starred zero
//of the series, star each primed zero of the series, erase
//all primes and uncover every line in the matrix.
int count=0;
bool done=false;
int r=0;
int c=0;
path[count][0]=Z0_r;
path[count][1]=Z0_c;
while (!done) {
r=findStarInCol(path[count][1],r);
if (r>0) {
count++;
path[count][0]=r;
path[count][1]=path[count-1][1];
}
else{
done=true;
}
if (!done) {
c=findPrimeInRow(path[count][0],c);
count++;
path[count][0]=path[count-1][1];
path[count][1]=c;
}
}
convertPath(count, path);
clearCovers();
erasePrimes();
return 3;
}
int step6(int stepnum){
//Add the value found in Step 4 to every element of each covered
//row, and subtract it from every element of each uncovered column.
//Return to Step 4 without altering any stars, primes, or covered lines.
minval = find_smallest();
for (int i= 0; i < rows; i++) {
for (int j = 0; j<columns;j++) {
if (R_cov[i]==1) {
C[i][j]=C[i][j]+minval;
}
if (C_cov[j]==0) {
C[i][j]=C[i][j]-minval;
}
}
}
stepnum=4;
return stepnum;
}
float find_smallest()
{
float min;
min=minvalOld;
for (int i= 0; i < rows; i++) {
for (int j = 0; j<columns;j++) {
if (R_cov[i]==0 && C_cov[j]==0){
if (min>C[i][j] ){
min=C[i][j];
}
}
}
}
minvalOld=min;
return min;
}
int findStarInCol(int c, int r){
r=0;
for (int i = 0; i<n; i++) {
if (M[i][c]==1){
r=i;
}
}
return r;
}
int findPrimeInRow (int r, int c) {
for (int j = 0;j<=n;j++) {
if (M[r][j]==2) {
c=j;
}
}
return c;
}
void convertPath (int count, int** path) {
for (int i = 0; i < count; i++) {
if (M[path[i][0]][path[i][1]]==1) {
M[path[i][0]][path[i][1]]=0;
}
else {
M[path[i][0]][path[i][1]]=1;
}
}
return;
}
void clearCovers () {
for (int i = 0; i < n; i++ ) {
R_cov[i]=0;
C_cov[i]=0;
}
return;
}
void erasePrimes () {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (M[i][j]==2) {
M[i][j]=0;
}
}
}
return;
}
void find_a_zero() {
int i=0;
int j;
bool done=false;
aRow=0;
aCol=0;
while (!done) {
j=0;
while (j<rows){
if ((C[i][j]==0) && (R_cov[i]==false) && (C_cov[j]==false)) {
aRow=i;
cout << "aRow changed to "<<i;
aCol=j;
done=true;
}
j++;
}
i++;
if (i==rows ){
done=true;
}
}
return;
}
//never used
bool starInRow(int aRow) {
bool tbool = false;
for (int j = 0;j<rows;j++) {
if (M[aRow][j]==1) {
tbool = true;
}
}
return tbool;
}
int findStarInRow (int aRow) {
aCol=0;
for (int j = 0; j < rows; j++) {
if ( M[aRow][j]==1) {
aCol=j;
}
}
return aCol;
}
void printArray(float** anArray, int ro, int co, string arrayName) {
cout<<"Printing "<<arrayName<<"["<<ro<<","<<co<<"]"<<endl;
for (int i = 0; i<ro; i++ ) {
for (int j = 0; j<co; j++ ){
cout<<anArray[i][j]<<"\t";
}
cout<<endl;
}
}
void printArray(int** anArray, int ro, int co, string arrayName) {
cout<<"Printing "<<arrayName<<"["<<ro<<","<<co<<"]"<<endl;
for (int i = 0; i<ro; i++ ) {
for (int j = 0; j<co; j++ ){
cout<<anArray[i][j]<<"\t";
}
cout<<endl;
}
}
};
void printArray(float** anArray, int ro, int co, string arrayName) {
cout<<"Outside Munkres - Printing "<<arrayName<<"["<<ro<<","<<co<<"]"<<endl;
for (int i = 0; i<ro; i++ ) {
for (int j = 0; j<co; j++ ){
cout<<anArray[i][j]<<"\t";
}
cout<<endl;
}
}
int main () {
cout<<"Init"<<endl;
float ** A;
A= new float* [4];
for (int i=0; i<4; i++){
A[i]= new float [4];
}
A[0][0] = 1.0f;
A[0][1] = 2.0f;
A[0][2] = 3.0f;
A[0][3] = 4.0f;
A[1][0] = 2.0f;
A[1][1] = 4.0f;
A[1][2] = 6.0f;
A[1][3] = 8.0f;
A[2][0] = 3.0f;
A[2][1] = 6.0f;
A[2][2] = 9.0f;
A[2][3] = 12.0f;
A[3][0] = 4.0f;
A[3][1] = 8.0f;
A[3][2] = 12.0f;
A[3][3] = 16.0f;
printArray(A, 4,4, "A");
Munkrees* newMunkrees = new Munkrees(4, 4, A);
cout<<"Done..."<<endl;
printArray(A, 4,4, "A");
//printArray(A, 4,4);
}

New Topic/Question
This topic is locked




MultiQuote




|