EgtNumKernel :

- Aggiunta classe di calcolo per ottimizzazione ordine delle lavorazioni
- Aggiunti vincoli obbligatori e dipendenze suggerite a ShortestPath.
This commit is contained in:
Riccardo Elitropi
2025-04-23 10:09:41 +02:00
parent d9818970e7
commit 558b590810
13 changed files with 1552 additions and 172 deletions
+81 -32
View File
@@ -21,6 +21,27 @@
#include "stdafx.h"
#include "ShortestPath.h"
// ----------------------------------------------------------------------------
static void
SwapNodesForTwoOpt( NODE* pFirst, NODE* pKth, NODE* pLast)
{
// inverto il tratto intermedio
for ( NODE* pCurr = pFirst ; pCurr != pKth ; ) {
NODE* pSave = pCurr->pNext ;
pCurr->pNext = pCurr->pPrev ;
pCurr->pPrev = pSave ;
pCurr = pSave ;
}
// sistemo gli estremi
pFirst->pNext = pKth->pNext ;
pKth->pNext->pPrev = pFirst ;
pKth->pNext = pKth->pPrev ;
pKth->pPrev = pLast ;
pLast->pNext = pKth ;
pFirst = pLast->pNext ;
pKth = pFirst->pNext ;
}
// ----------------------------------------------------------------------------
long long unsigned
ShortestPath::TwoOpt( NODE* pPath)
@@ -29,44 +50,72 @@ ShortestPath::TwoOpt( NODE* pPath)
unsigned nTry = 1 ;
unsigned nCount = 1 ;
NODE* pFirst = pPath ;
NODE* pFirstDep = m_pCheckDep ;
do {
NODE* pLast = pFirst->pPrev ;
NODE* pKth = pFirst->pNext ;
NODE* pLastDep = pFirstDep->pPrev ;
NODE* pKthDep = pFirstDep->pNext ;
do {
// lunghezza originale dei tratti da scambiare
unsigned nEXIST = ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) ;
// nuova lunghezza dei tratti da scambiare
unsigned nTEST = ArcCost( pFirst->nPos, pKth->pNext->nPos) +
ArcCost( pLast->nPos, pKth->nPos) ;
// lunghezze originali e nuova del tratto intermedio che viene invertito
for ( NODE* pCurr = pFirst ; pCurr != pKth ; pCurr = pCurr->pNext) {
nEXIST += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
nTEST += ArcCost( pCurr->pNext->nPos, pCurr->nPos) ;
}
// se lo scambio fa risparmiare
if ( nTEST < nEXIST) {
// inverto il tratto intermedio
for ( NODE* pCurr = pFirst ; pCurr != pKth ;) {
NODE* pSave = pCurr->pNext ;
pCurr->pNext = pCurr->pPrev ;
pCurr->pPrev = pSave ;
pCurr = pSave ;
// se non esistono dipendenze suggerite
if ( ! ExistSuggDependences()) {
// lunghezza originale dei tratti da scambiare
unsigned nEXIST = ArcCost( pLast->nPos, pFirst->nPos) +
ArcCost( pKth->nPos, pKth->pNext->nPos) ;
// nuova lunghezza dei tratti da scambiare
unsigned nTEST = ArcCost( pFirst->nPos, pKth->pNext->nPos) +
ArcCost( pLast->nPos, pKth->nPos) ;
// lunghezze originali e nuova del tratto intermedio che viene invertito
for ( NODE* pCurr = pFirst ; pCurr != pKth ; pCurr = pCurr->pNext) {
nEXIST += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
nTEST += ArcCost( pCurr->pNext->nPos, pCurr->nPos) ;
}
// sistemo gli estremi
pFirst->pNext = pKth->pNext ;
pKth->pNext->pPrev = pFirst ;
pKth->pNext = pKth->pPrev ;
pKth->pPrev = pLast ;
pLast->pNext = pKth ;
pFirst = pLast->pNext ;
pKth = pFirst->pNext ;
// faccio ripartire il conto
nCount = 0 ;
// se lo scambio fa risparmiare
if ( nTEST < nEXIST) {
// se non esistono vincoli, effettuo i cambi
if ( ! ExistConstraints()) {
SwapNodesForTwoOpt( pFirst, pKth, pLast) ;
nCount = 0 ;
}
// se esistono i vincoli
else {
// copio il Path e i puntatori sul Path di test per le dipendenze
CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ;
// effettuo i cambi dei nodi sul path di test per le dipendenze
SwapNodesForTwoOpt( pFirstDep, pKthDep, pLastDep) ;
// se il path di test rispetta i vincoli, allora effettuo i cambi sul percorso vero
if ( IsPathRespectingContraints( m_pCheckDep)) {
SwapNodesForTwoOpt( pFirst, pKth, pLast) ;
nCount = 0 ;
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
}
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
}
// se esistono dipendenze suggerite
else {
CopyPathAdv( pPath, m_pCheckDep, pLast, pFirst, pKth, &pLastDep, &pFirstDep, &pKthDep) ;
SwapNodesForTwoOpt( pFirstDep, pKthDep, pLastDep) ;
if ( IsPathRespectingContraints( m_pCheckDep)) {
unsigned long long nEXIST = TotalCost( pPath) ;
unsigned long long nTEST = TotalCost( m_pCheckDep) ;
if ( nTEST < nEXIST) {
SwapNodesForTwoOpt( pFirst, pKth, pLast) ;
nCount = 0 ;
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
}
// altrimenti passo al nodo successivo
else
pKth = pKth->pNext ;
} while ( pKth != pLast->pPrev->pPrev && nCount != 0) ;
if ( nCount != 0)
pFirst = pFirst->pNext ;