//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : NN.cpp Data : 22.12.15 Versione : 1.6l4 // Contenuto : Miglioramento del percorso con metodo ibrido (ad ogni passo // si sceglie il meglio tra i metodi Popt e TwoOpt). * // // // // // Modifiche : 22.12.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ShortestPath.h" // ---------------------------------------------------------------------------- static void SwapNodesForHybrid1( NODE* pLast, NODE* pFirst, NODE* pKth) { NODE* pSave = pKth->pNext ; pKth->pNext = pKth->pNext->pNext ; pKth->pNext->pPrev = pKth ; pLast->pNext = pSave ; pFirst->pPrev = pSave ; pSave->pNext = pFirst ; pSave->pPrev = pLast ; } // ---------------------------------------------------------------------------- static void SwapNodesForHybrid2( NODE* pLast, NODE* pFirst, NODE* pKth) { for ( NODE* pReverse = pFirst ; pReverse != pKth ;) { NODE* pSave = pReverse->pNext ; pReverse->pNext = pReverse->pPrev ; pReverse->pPrev = pSave ; pReverse = pSave ; } pFirst->pNext = pKth->pNext ; pKth->pNext->pPrev = pFirst ; pKth->pNext = pKth->pPrev ; pKth->pPrev = pLast ; pLast->pNext = pKth ; } // ---------------------------------------------------------------------------- long long unsigned ShortestPath::Hybrid( NODE* pPath) { const int MAX_TRY = 2048 ; unsigned count = 1 ; NODE* pFirst = pPath ; NODE* pFirstDep = m_pCheckDep ; unsigned nTry = 1 ; do { NODE* pLast = pFirst->pPrev ; NODE* pKth = pFirst->pNext ; NODE* pLastDep = pFirstDep->pPrev ; NODE* pKthDep = pFirstDep->pNext ; do { unsigned D1 = 0 ; unsigned D2 = 0 ; unsigned D3 = 0 ; unsigned D4 = 0 ; // se non esistono dipendenze suggerite if ( ! ExistSuggDependences()) { // Point-Opt ( D1=new, D3=original) D1 = ArcCost( pKth->nPos, pKth->pNext->pNext->nPos) + ArcCost( pKth->pNext->nPos, pFirst->nPos) + ArcCost( pLast->nPos, pKth->pNext->nPos) ; D3 = ArcCost( pLast->nPos, pFirst->nPos) + ArcCost( pKth->nPos, pKth->pNext->nPos) + ArcCost( pKth->pNext->nPos, pKth->pNext->pNext->nPos) ; // Two-Opt ( D2=new, D4=original) D2 = ArcCost( pFirst->nPos, pKth->pNext->nPos) + ArcCost( pLast->nPos, pKth->nPos) ; D4 = ArcCost( pLast->nPos, pFirst->nPos) + ArcCost( pKth->nPos, pKth->pNext->nPos) ; // Lunghezze originali e nuova del tratto intermedio che viene invertito for ( NODE* pCurr = pFirst ; pCurr != pKth ; pCurr = pCurr->pNext) { D4 += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ; D2 += ArcCost( pCurr->pNext->nPos, pCurr->nPos) ; } } // se esistono dipendenze suggerite else { D3 = static_cast( TotalCost( pPath)) ; D4 = D3 ; D1 = MAXDIST ; D2 = MAXDIST ; CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ; SwapNodesForHybrid1( pLastDep, pFirstDep, pKthDep) ; bool bOkD1 = ( IsPathRespectingContraints( m_pCheckDep)) ; if ( bOkD1) D1 = static_cast( TotalCost( m_pCheckDep)) ; CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ; SwapNodesForHybrid2( pLastDep, pFirstDep, pKthDep) ; bool bOkD2 = ( IsPathRespectingContraints( m_pCheckDep)) ; if ( bOkD2) D2 = static_cast( TotalCost( m_pCheckDep)) ; } // controllo se ci sono miglioramenti nei persorsi if ( D1 < D3 || D2 < D4) { if ( D1 < D3 && ( D2 >= D4 || ( D3 - D1) >= ( D4 - D2))) { // nel caso di assenza di dipendenze if ( ! ExistConstraints()) { SwapNodesForHybrid1( pLast, pFirst, pKth) ; count = 0 ; pFirst = pLast->pNext ; pKth = pFirst->pNext ; } // nel caso di dipendeze, controllo se il nuovo percorso le rispetta else { CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ; // effettuo i cambi dei nodi sul path di test per le dipendenze SwapNodesForHybrid1( pLastDep, pFirstDep, pKthDep) ; // se il path di test rispetta i vincoli, allora effettuo i cambi sul percorso vero if ( IsPathRespectingContraints( m_pCheckDep)) { SwapNodesForHybrid1( pLast, pFirst, pKth) ; count = 0 ; pFirst = pLast->pNext ; pKth = pFirst->pNext ; } // altrimenti passo al nodo successivo else pKth = pKth->pNext ; } } else { // nel caso di assenza di dipendenze if ( ! ExistConstraints()) { SwapNodesForHybrid2( pLast, pFirst, pKth) ; count = 0 ; pFirst = pLast->pNext ; pKth = pFirst->pNext ; } // nel caso di dipendeze, controllo se il nuovo percorso le rispetta else { CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ; // effettuo i cambi dei nodi sul path di test per le dipendenze SwapNodesForHybrid2( pLastDep, pFirstDep, pKthDep) ; // se il path di test rispetta i vincoli, allora effettuo i cambi sul percorso vero if ( IsPathRespectingContraints( m_pCheckDep)) { SwapNodesForHybrid2( pLast, pFirst, pKth) ; count = 0 ; pFirst = pLast->pNext ; pKth = pFirst->pNext ; } // altrimenti passo al nodo successivo else pKth = pKth->pNext ; } } } else pKth = pKth->pNext ; } while ( pKth != pLast->pPrev->pPrev && count != 0) ; if ( count != 0) pFirst = pFirst->pNext ; count ++ ; nTry ++ ; } while ( count < m_nNumPnts && nTry < MAX_TRY) ; // ricalcolo il costo del percorso return TotalCost( pPath) ; }