From 31a96af3ba55e615189a8b41e350434f73e72327 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 8 Feb 2024 13:02:09 +0100 Subject: [PATCH 1/2] EgtNumKernel : - aggiunto algoritmo Dijkstra. --- Dijkstra.cpp | 151 +++++++++++++++++++++++++++++++++++ Dijkstra.h | 40 ++++++++++ EgtNumKernel.vcxproj | 2 + EgtNumKernel.vcxproj.filters | 9 +++ 4 files changed, 202 insertions(+) create mode 100644 Dijkstra.cpp create mode 100644 Dijkstra.h diff --git a/Dijkstra.cpp b/Dijkstra.cpp new file mode 100644 index 0000000..fcbad8b --- /dev/null +++ b/Dijkstra.cpp @@ -0,0 +1,151 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : Dijkstra.cpp Data : 08.02.24 Versione : 2.6b1 +// Contenuto : Classe per calcolo del percorso a peso minimo su un grafo orientato. +// +// +// Modifiche : 02.02.2024 RE Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "DllMain.h" +#include "Dijkstra.h" +#include "/EgtDev/Include/EGnStringUtils.h" +#include "/EgtDev/Include/EgtILogger.h" +#include "set" +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +IDijkstra* +CreateDijkstra( void) +{ + return static_cast ( new(nothrow) Dijkstra) ; +} + +//---------------------------------------------------------------------------- +Dijkstra::Dijkstra( void) +{ + m_AdjMatrix = { } ; + m_nDest = -1 ; + m_bValid = false ; +} + +//---------------------------------------------------------------------------- +Dijkstra::~Dijkstra( void) +{ +} + +//---------------------------------------------------------------------------- +bool +Dijkstra::SetGraph( DBLMATRIX AdjMatrix, int nDestInd) { + + // se vuota, errore + if ( AdjMatrix.empty()) + return false ; + + // controllo che la matrice sia quadrata + int nRows = static_cast( AdjMatrix.size()) ; + for ( int i = 0 ; i < nRows ; ++ i) + if ( static_cast( AdjMatrix[i].size()) != nRows) + return false ; + + // i pesi non devono essere negativi + for ( int i = 0 ; i < nRows ; ++ i) + for ( int j = 0 ; j < int( AdjMatrix[i].size()) ; ++ j) + if ( AdjMatrix[i][j] < 0) + return false ; + + // assegno la matrice delle adiancenze e la destinazione + m_AdjMatrix = AdjMatrix ; + m_nDest = nDestInd ; + + // per sicurezza assegno agli elementi sulla diagonale la massima distanza + for ( int i = 0 ; i < nRows ; ++ i) + m_AdjMatrix[i][i] = MAXDIST ; + + // il grafo è valido + m_bValid = true ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Dijkstra::GetPath( INTVECTOR& vNodePath) +{ + // se il grafo non è valido, allora esco + if ( ! m_bValid) + return false ; + + // dimensione dei nodi + const int DIM = static_cast( m_AdjMatrix.size()) ; + + // ridimensiono il percorso + vNodePath.resize( DIM) ; + + // definisco il vettore delle distanze + vector vDists ; vDists.resize( DIM) ; + + // definisco l'insieme dei nodi visitati + set sNode_toCheck ; + + // inizializzo l'insieme dei nodi da visitare, le distanze ( ad infinito) e gli indici dei nodi + // precedenti ( tutti a -1) + for ( int i = 0 ; i < DIM ; ++ i) { + sNode_toCheck.insert( i) ; + vNodePath[i] = -1 ; + vDists[i] = MAXDIST ; + } + // il nodo sorgente ( in posizione zero) ha distanza nulla + vDists[0] = 0. ; + + // finchè non ho controllato tutti i nodi... + while ( ! sNode_toCheck.empty()) { + // cerco il nodo ( tra quelli non ancora visitati) a cui è associata la distanza minima + // ( alla prima iterazione il nodo è lo 0) + int nMinInd = -1 ; + double dDistRef = MAXDIST - 1 ; + for ( int i = 0 ; i < DIM ; ++ i) { + // cerco un nodo i disponibile + set::iterator iter = sNode_toCheck.find( i) ; + if ( iter == sNode_toCheck.end()) + continue ; + // se la distanza e minore del riferimento, aggiorno + if ( vDists[i] < dDistRef) { + dDistRef = vDists[i] ; + nMinInd = i ; + } + } + // se nodo non trovato o coincidente alla sorgente ( se presente), allora il percorso è terminato + if ( nMinInd == -1) + break ; + + // escludo il nodo i-esimo trovato + sNode_toCheck.erase( nMinInd) ; + + // cerco i nodi ad esso adiacenti + for ( int i = 0 ; i < DIM ; ++ i) { + if ( m_AdjMatrix[nMinInd][i] < MAXDIST) { + // la distanza per raggiungere il nodo i dal nodo nMinInd è pari alla somma dei contributi + // associati alle lunghezza trovate + double myDist = vDists[nMinInd] + m_AdjMatrix[nMinInd][i] ; + // se inferiore... + if ( myDist < vDists[i]) { + // aggiorno la distanza per raggiungere il nodo i + vDists[i] = myDist ; + // aggiorno l'indice per raggiungere il nodo i + vNodePath[i] = nMinInd ; + } + } + } + + } + + return true ; +} diff --git a/Dijkstra.h b/Dijkstra.h new file mode 100644 index 0000000..76231e9 --- /dev/null +++ b/Dijkstra.h @@ -0,0 +1,40 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : Dijkstra.h Data : 08.02.24 Versione : 2.6b1 +// Contenuto : Classe per calcolo del percorso a peso minimo su un grafo orientato. +// +// +// Modifiche : 02.02.2024 RE Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/ENkDijkstra.h" + +//---------------------------------------------------------------------------- +#define MAXDIST 1073741823U // 2^30 - 1 per evitare overflow + +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +class Dijkstra : public IDijkstra +{ + public : + ~Dijkstra( void) override ; + bool SetGraph( DBLMATRIX AdjMatrix, int nDestInd = -1) override ; + bool GetPath( INTVECTOR& vNodePath) override ; + + public : + Dijkstra( void) ; + + private : + int m_nDest ; + DBLMATRIX m_AdjMatrix ; + bool m_bValid ; +} ; + +const double DIST_NO_ADJ = 1073741823U ; + diff --git a/EgtNumKernel.vcxproj b/EgtNumKernel.vcxproj index 86214a1..5a09544 100644 --- a/EgtNumKernel.vcxproj +++ b/EgtNumKernel.vcxproj @@ -207,6 +207,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -236,6 +237,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtNumKernel.vcxproj.filters b/EgtNumKernel.vcxproj.filters index 4ef54e5..e4e0e4c 100644 --- a/EgtNumKernel.vcxproj.filters +++ b/EgtNumKernel.vcxproj.filters @@ -22,6 +22,9 @@ {205f239f-c48e-4049-bac5-74708a6c530c} + + {54a2fd6b-2491-42af-932a-eaa6f62f1ae2} + @@ -66,6 +69,9 @@ File di origine\MaximumFilling + + File di origine\Dijkstra + @@ -110,6 +116,9 @@ File di intestazione + + File di intestazione + From 897b45e54975ecce10fda28035bf00da41485e2a Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 13 Feb 2024 12:29:25 +0100 Subject: [PATCH 2/2] EgtNumKernel : - piccole migliorie. --- Dijkstra.cpp | 10 +++++----- Dijkstra.h | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Dijkstra.cpp b/Dijkstra.cpp index fcbad8b..7469cf4 100644 --- a/Dijkstra.cpp +++ b/Dijkstra.cpp @@ -67,7 +67,7 @@ Dijkstra::SetGraph( DBLMATRIX AdjMatrix, int nDestInd) { // per sicurezza assegno agli elementi sulla diagonale la massima distanza for ( int i = 0 ; i < nRows ; ++ i) - m_AdjMatrix[i][i] = MAXDIST ; + m_AdjMatrix[i][i] = WEIGHT_NO_ADJ ; // il grafo è valido m_bValid = true ; @@ -100,7 +100,7 @@ Dijkstra::GetPath( INTVECTOR& vNodePath) for ( int i = 0 ; i < DIM ; ++ i) { sNode_toCheck.insert( i) ; vNodePath[i] = -1 ; - vDists[i] = MAXDIST ; + vDists[i] = WEIGHT_NO_ADJ ; } // il nodo sorgente ( in posizione zero) ha distanza nulla vDists[0] = 0. ; @@ -110,7 +110,7 @@ Dijkstra::GetPath( INTVECTOR& vNodePath) // cerco il nodo ( tra quelli non ancora visitati) a cui è associata la distanza minima // ( alla prima iterazione il nodo è lo 0) int nMinInd = -1 ; - double dDistRef = MAXDIST - 1 ; + double dDistRef = WEIGHT_NO_ADJ - 1 ; for ( int i = 0 ; i < DIM ; ++ i) { // cerco un nodo i disponibile set::iterator iter = sNode_toCheck.find( i) ; @@ -122,8 +122,8 @@ Dijkstra::GetPath( INTVECTOR& vNodePath) nMinInd = i ; } } - // se nodo non trovato o coincidente alla sorgente ( se presente), allora il percorso è terminato - if ( nMinInd == -1) + // se nodo non trovato o coincidente alla destinazione ( se presente), allora il percorso è terminato + if ( nMinInd == -1 || nMinInd == m_nDest) break ; // escludo il nodo i-esimo trovato diff --git a/Dijkstra.h b/Dijkstra.h index 76231e9..c1c7776 100644 --- a/Dijkstra.h +++ b/Dijkstra.h @@ -36,5 +36,3 @@ class Dijkstra : public IDijkstra bool m_bValid ; } ; -const double DIST_NO_ADJ = 1073741823U ; -