1

I create a C++ program to use Dijkstra algorithm. To be more precise in calculations, i create a function that verify if a path exists between 2 values of my dijkstra matrix.

My function :

void existence_chemin(unsigned int tab[50][50], unsigned int i, unsigned int j, unsigned int rang) {
unsigned int n = 1;
unsigned int r, s, ta; /* indices courants */
unsigned int puissance_tab[50][50];
initialisation_matrice_0(puissance_tab);
unsigned int puissance_tab2[50][50];
initialisation_matrice_0(puissance_tab2);
unsigned int puissance_tab3[50][50];
initialisation_matrice_0(puissance_tab3);

if (tab[i - 1][j - 1] != 0) {
    cout << endl << " Chemin direct de poids "<< tab[i - 1][j - 1] <<" existant entre les sommets " << i << " et " << j << "." << endl;
    //afficher_matrice(tab, rang);
    n++;
    dijkstra(tab, i - 1, j - 1, rang);
}
else {    // (tab[i - 1][j - 1] == 0)
    cout << endl << " Chemin direct entre les sommets " << i << " et " << j << " inexistant.\n Poursuite des recherches en cours ..." << endl;
        unsigned int p, q, r;
        for (p = 0; p < rang; p++)
        {
            for (q = 0; q < rang; q++)
            {
                for (r = 0; r < rang; r++)
                {
                    puissance_tab[p][q] += tab[p][r] * tab[r][q];
                }
            }
        }


    if (puissance_tab[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        //cout << "\n\nAffichage de la matrice a l'ordre " << t - 1;
        //afficher_matrice(puissance_tab, rang);
        dijkstra(tab, i - 1, j - 1,rang);
    }
    else {
        unsigned int s, t, u;
        for (s = 0; s < rang; s++)
        {
            for (t = 0; t < rang; t++)
            {
                for (u = 0; u < rang; u++)
                {
                    puissance_tab2[s][t] += puissance_tab[s][u] * tab[u][t];
                }
            }
        }

        if (puissance_tab2[i - 1][j - 1] != 0) {
            cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
            //cout << "\n\nAffichage de la matrice a l'ordre " << t - 1;
            //afficher_matrice(puissance_tab, rang);
            dijkstra(tab, i - 1, j - 1, rang);
        }
        else {
            unsigned int aaa, ttt, uuu;
            for (aaa = 0; aaa < rang; aaa++)
            {
                for (ttt = 0; ttt < rang; ttt++)
                {
                    for (uuu = 0; uuu < rang; uuu++)
                    {
                        puissance_tab3[aaa][ttt] += puissance_tab2[aaa][uuu] * puissance_tab[uuu][ttt];
                    }
                }
            }

            if (puissance_tab2[i - 1][j - 1] != 0) {
                cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
                //cout << "\n\nAffichage de la matrice a l'ordre " << t - 1;
                //afficher_matrice(puissance_tab, rang);
                dijkstra(tab, i - 1, j - 1, rang);
            }
            else{
                cout << " \nCONCLUSION :\n Aucun chemin n'existe donc entre les sommets " << i << " et " << j << " sur ce graphe." << endl;
            }
        }
    }
}
cout << endl;
choix(tab,rang);
}

I have done many if/else nesting to verify if a path exists for distances of 1, 2 and 3. But if the path is bigger than 3, it return that there is no path between 2 matrix values. That's because i nested if/else. I achieve to create a loop, can you help me to correct this problem ?

The whole code is here, on GitHub.

Thomas
  • 73
  • 9
  • 1
    Sorry, I don't know what an "imbrication" is. – Asteroids With Wings Jun 06 '20 at 22:13
  • @AsteroidsWithWings Neither did I. It seems to be a [medical term](https://www.merriam-webster.com/dictionary/imbrication#:~:text=Medical%20Definition%20of%20imbrication,surgical%20closure%20of%20a%20wound). – Adrian Mole Jun 06 '20 at 22:15
  • sorry, it's "nesting", many if/else in other if/else... – Thomas Jun 06 '20 at 22:16
  • Sometimes it's useful to write out how you would do a task by hand. Forget the code for a moment, and write out step-by-step how to determine if a path exists between two vertices. Your nested `if-else` setup corresponds to what you would start writing. A looping setup appears when you get tired of writing and make the next step something like "go back to step 3 and repeat.". – JaMiT Jun 07 '20 at 04:19
  • @JaMiT thanks, yes I know it's better to try by hand. The problem I have here is that on each if-else statement I use a table calculated in previous if-else. I don't know how to code this in only one loop. By hand, it's easier and I already have this. – Thomas Jun 07 '20 at 09:19
  • 1
    @Thomas Ah, yes, those matrices do make the task look more complicated. I would call the matrices a black box. Pretend you have a variable called `puissance` that will somehow (to be determined later) provide you with the information you need. Those loops where you define the elements of your matrices would end up in a method of the black box. The start of your first `else` clause would become something like `else { cout << endl << " Chemin [etc.]"; puissance.update(); if ( puissance.test() ) { cout << " \nCONCLUSION :[etc.]"`. Once you have the loop logic, work on the black box. – JaMiT Jun 07 '20 at 21:35

2 Answers2

1

A cursory look at your code (even before trying to understand it) reveals that you compute puissance_tab3, and ignore it. That's the danger of copy-paste programming.

Now, assuming that you mean puissance_tab3, first thing to do is to unnest it. Rather than spelling out an else clause, immediately return from if:

void existence_chemin(unsigned int tab[50][50], unsigned int i, unsigned int j, unsigned int rang) {
    unsigned int n = 1;
    unsigned int r, s, ta; /* indices courants */
    unsigned int puissance_tab[50][50];
    initialisation_matrice_0(puissance_tab);
    unsigned int puissance_tab2[50][50];
    initialisation_matrice_0(puissance_tab2);
    unsigned int puissance_tab3[50][50];
    initialisation_matrice_0(puissance_tab3);

    if (tab[i - 1][j - 1] != 0) {
        cout << endl << " Chemin direct de poids "<< tab[i - 1][j - 1] <<" existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }
    cout << endl << " Chemin direct entre les sommets " << i << " et " << j << " inexistant.\n Poursuite des recherches en cours ..." << endl;
    unsigned int p, q, r;
    for (p = 0; p < rang; p++) {
        for (q = 0; q < rang; q++) {
            for (r = 0; r < rang; r++) {
                puissance_tab[p][q] += tab[p][r] * tab[r][q];
            }   
        }   
    }   

    if (puissance_tab[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1,rang);
        return;
    }   
    unsigned int s, t, u;
    for (s = 0; s < rang; s++) {
        for (t = 0; t < rang; t++) {
            for (u = 0; u < rang; u++) {
                puissance_tab2[s][t] += puissance_tab[s][u] * tab[u][t];
            }   
        }   
    }   

    if (puissance_tab2[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }   
    unsigned int aaa, ttt, uuu;
    for (aaa = 0; aaa < rang; aaa++) {
        for (ttt = 0; ttt < rang; ttt++) {
            for (uuu = 0; uuu < rang; uuu++) {
                puissance_tab3[aaa][ttt] += puissance_tab2[aaa][uuu] * puissance_tab[uuu][ttt];
            }
        }
    }

    if (puissance_tab3[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }
    cout << " \nCONCLUSION :\n Aucun chemin n'existe donc entre les sommets " << i << " et " << j << " sur ce graphe." << endl;
}

The code already looks much more manageable. Next step is to factor out matric multiplication:

void existence_chemin(unsigned int tab[50][50], unsigned int i, unsigned int j, unsigned int rang) {
    unsigned int puissance_tab[50][50];
    initialisation_matrice_0(puissance_tab);
    unsigned int puissance_tab2[50][50];
    initialisation_matrice_0(puissance_tab2);
    unsigned int puissance_tab3[50][50];
    initialisation_matrice_0(puissance_tab3);

    if (tab[i - 1][j - 1] != 0) {
        cout << endl << " Chemin direct de poids "<< tab[i - 1][j - 1] <<" existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }
    cout << endl << " Chemin direct entre les sommets " << i << " et " << j << " inexistant.\n Poursuite des recherches en cours ..." << endl; 

    matrix_multiply(tab, tab, puissance_tab, rang);
    if (puissance_tab[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1,rang);
        return;
    }

    matrix_multiply(puissance_tab, tab, puissance_tab2, rang);
    if (puissance_tab2[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }

    matrix_multiply(puissance_tab2, puissance_tab, puissance_tab3, rang);
    if (puissance_tab3[i - 1][j - 1] != 0) {
        cout << " \nCONCLUSION :\n Chemin existant entre les sommets " << i << " et " << j << "." << endl;
        dijkstra(tab, i - 1, j - 1, rang);
        return;
    }
    cout << " \nCONCLUSION :\n Aucun chemin n'existe donc entre les sommets " << i << " et " << j << " sur ce graphe." << endl;
}

Now we are almost there. You can see the pattern which begs to be a loop. The only thing remaining is to manage those matrices. I hope you can do it.

A word of warning though. I have a SWAG that you need successive powers of tab. You compute something entirely different. Indeed,

puissance_tab = tab * tab = tab ^ 2
puissance_tab2 = puissance_tab * tab = tab ^ 3
puissance_tab3 = puissance_tab2 * puissance_tab = tab ^ 5

are not successive powers.

user58697
  • 6,907
  • 1
  • 11
  • 24
  • thanks for your answer, i dit not know that I can use `return` to keep in memory a variable. You're right I dit a mistake with copy-paste. I do not really understand `matrix-multiply`. It's something you wrote to see how to create the loop ? And it's just an example ? or should I define this function to use it ? You're right, I also did a mistake with successive powers... – Thomas Jun 07 '20 at 19:38
  • Yes, you should define the matrix multiplication function. You already have the code. – user58697 Jun 07 '20 at 20:39
0

@user58697 i did the function, but I have an error in return.

Function :

unsigned int rechercheLoop(unsigned int tab1[50][50], unsigned int tab2[50][50], unsigned int rang, unsigned int i, unsigned int j){
unsigned int successivePower[50][50];
unsigned int s, t, u;

for (s = 0; s < rang; s++) {
    for (t = 0; t < rang; t++) {
        for (u = 0; u < rang; u++) {
            successivePower[s][t] += tab1[s][u] * tab2[u][t];
        }
    }
}
return successivePower[50][50];
}


Call :

  unsigned int puissanceSuccessive[50][50];
initialisation_matrice_0(puissanceSuccessive);

puissanceSuccessive = rechercheLoop(tab[50][50],puissanceSuccessive[50][50], rang, i, j)
while(puissanceSuccessive[i - 1][j - 1] == 0){
    puissanceSuccessive1[50][50] = rechercheLoop(tab[50][50], puissanceSuccessive[50][50], rang, i, j)
}


I also have an error that says "No matching function"...

Thomas
  • 73
  • 9