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
+99 -39
View File
@@ -54,7 +54,7 @@ ShortestPath::Tsp( void)
m_Dists = new(nothrow) unsigned[ m_nNumPnts * m_nNumPnts] ;
if ( m_Dists == nullptr)
return false ;
// alloco la matrice ausiliaria
// alloco la matrice ausiliaria
if ( m_Available != nullptr)
delete m_Available ;
m_Available = new(nothrow) bool[ m_nNumPnts * m_nNumPnts] ;
@@ -72,6 +72,10 @@ ShortestPath::Tsp( void)
m_pDupl = new(nothrow) NODE[ m_nNumPnts] ;
if ( m_pDupl == nullptr)
return false ;
// alloco la copia del path per controllo dipendenze
if ( m_pCheckDep != nullptr)
delete m_pCheckDep ;
m_pCheckDep = new(nothrow) NODE[ m_nNumPnts] ;
// calcolo la matrice delle distanze
CalcDistances() ;
@@ -79,6 +83,7 @@ ShortestPath::Tsp( void)
// organizzo percorsi
PreparePath( m_pMain) ;
PreparePath( m_pDupl) ;
PreparePath( m_pCheckDep) ;
// inizializzo minimo costo
m_nMinCost = LLONG_MAX ;
@@ -87,6 +92,7 @@ ShortestPath::Tsp( void)
long long unsigned nMinNN = NearNeighbor() ;
string sOut = "-- NearNeighbor : TotalCost = " + to_string( nMinNN) ;
MY_LOG( sOut.c_str()) ;
_printPath( m_pMain, ToString( "NN : ")) ;
// se migliora, salvo l'ordinamento
if ( nMinNN < m_nMinCost) {
MY_LOG( " Improve") ;
@@ -101,38 +107,42 @@ ShortestPath::Tsp( void)
// ---- Applico percorso invertito, se risultato precedente scarso ----
const double COEFF_INVERTED = 1.2 ;
const int MIN_PNTS_INVERTED = 128 ;
if ( m_nMinCost > COEFF_INVERTED * m_nTotMin || m_nNumPnts < MIN_PNTS_INVERTED) {
// inverto il percorso
NODE* pCurr = m_pDupl->pPrev ;
NODE* pPath = m_pMain ;
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
pPath->nPos = pCurr->nPos ;
pPath = pPath->pNext ;
pCurr = pCurr->pPrev ;
if ( ! ExistConstraints()) {
if ( m_nMinCost > COEFF_INVERTED * m_nTotMin || m_nNumPnts < MIN_PNTS_INVERTED) {
// inverto il percorso
NODE* pCurr = m_pDupl->pPrev ;
NODE* pPath = m_pMain ;
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
pPath->nPos = pCurr->nPos ;
pPath = pPath->pNext ;
pCurr = pCurr->pPrev ;
}
// ne calcolo il risultato
long long unsigned nMinInv = TotalCost( m_pMain) ;
_printPath( m_pMain, "Inverted NN : ") ;
string sOut = "-- Inverted NN : TotalCost = " + to_string( nMinInv) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
if ( nMinInv < m_nMinCost) {
MY_LOG( " Improve") ;
m_nMinCost = nMinInv ;
UpdateOrder( m_pMain) ;
}
// salvo il percorso in un duplicato
SavePath( m_pMain) ;
// miglioramenti aggiuntivi
CalculateImprovements( m_pMain) ;
}
// ne calcolo il risultato
long long unsigned nMinInv = TotalCost( m_pMain) ;
string sOut = "-- Inverted NN : TotalCost = " + to_string( nMinInv) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
if ( nMinInv < m_nMinCost) {
MY_LOG( " Improve") ;
m_nMinCost = nMinInv ;
UpdateOrder( m_pMain) ;
}
// salvo il percorso in un duplicato
SavePath( m_pMain) ;
// miglioramenti aggiuntivi
CalculateImprovements( m_pMain) ;
else
MY_LOG( "-- Inverted NN : Not necessary") ;
}
else
MY_LOG( "-- Inverted NN : Not necessary") ;
// ---- Applico pessima partenza, se risultato precedente scarso ----
const double COEFF_FARNEIG = 1.4 ;
const int MIN_PNTS_FARNEIG = 128 ;
if ( m_nMinCost > COEFF_FARNEIG * m_nTotMin || m_nNumPnts < MIN_PNTS_FARNEIG) {
long long unsigned nMinFN = FarNeighbor() ;
_printPath( m_pMain, "FN : ") ;
string sOut = "-- FarNeighbor : TotalCost = " + to_string( nMinFN) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
@@ -159,6 +169,7 @@ ShortestPath::CalculateImprovements( NODE* pPath)
// Ottimizzazione con movimento di singolo punto
RestorePath( pPath) ;
long long unsigned nPntOpt = PointOpt( pPath) ;
_printPath( pPath, "PointOpt : ") ;
string sOut = " PointOpt : TotalCost = " + to_string( nPntOpt) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
@@ -173,6 +184,7 @@ ShortestPath::CalculateImprovements( NODE* pPath)
if ( m_nNumPnts <= MAX_NODES_2OPT) {
RestorePath( pPath) ;
long long unsigned nTwoOpt = TwoOpt( pPath) ;
_printPath( pPath, "TwoOpt : ") ;
string sOut = " TwoOpt : TotalCost = " + to_string( nTwoOpt) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
@@ -188,6 +200,7 @@ ShortestPath::CalculateImprovements( NODE* pPath)
if ( m_nNumPnts <= MAX_NODES_HYBRID) {
RestorePath( pPath) ;
long long unsigned nHybOpt = Hybrid( pPath) ;
_printPath( pPath, "Hybrid : ") ;
string sOut = " Hybrid : TotalCost = " + to_string( nHybOpt) ;
MY_LOG( sOut.c_str()) ;
// se migliora, salvo l'ordinamento
@@ -342,29 +355,40 @@ ShortestPath::CalcDistances( void)
}
// ciclo per calcolare le distanze tra tutte le coppie di nodi
bool bCalcDistances = ( m_ExtDistMat.empty()) ;
for ( unsigned i = 0 ; i < nLimit ; ++ i) {
unsigned nRowMinDist = INT_MAX ;
for ( unsigned j = 0 ; j < nLimit ; ++ j) {
if ( i != j) {
// calcolo distanza i -> j
float dDx = float( m_Points[i].dXf - m_Points[j].dXi) ;
float dDy = float( m_Points[i].dYf - m_Points[j].dYi) ;
float dDz = float( m_Points[i].dZf - m_Points[j].dZi) ;
float dDh = float( m_Points[i].dHf - m_Points[j].dHi) ;
float dDv = float( m_Points[i].dVf - m_Points[j].dVi) ;
unsigned nDist = min( GetDistance( dDx, dDy, dDz, dDh, dDv), MAXDIST) ;
m_Dists[ Index( i, j)] = nDist ;
// verifico se nuovo minimo di linea
if ( nDist < nRowMinDist)
nRowMinDist = nDist ;
// se ho già impostato una matrice delle distanze, allora uso quella
if ( ! bCalcDistances)
m_Dists[Index( i, j)] = m_ExtDistMat[i][j] ;
// altrimenti calcolo le rispettive distanze
else {
if ( i != j) {
// calcolo distanza i -> j
float dDx = float( m_Points[i].dXf - m_Points[j].dXi) ;
float dDy = float( m_Points[i].dYf - m_Points[j].dYi) ;
float dDz = float( m_Points[i].dZf - m_Points[j].dZi) ;
float dDh = float( m_Points[i].dHf - m_Points[j].dHi) ;
float dDv = float( m_Points[i].dVf - m_Points[j].dVi) ;
unsigned nDist = min( GetDistance( dDx, dDy, dDz, dDh, dDv), MAXDIST) ;
m_Dists[ Index( i, j)] = nDist ;
// verifico se nuovo minimo di linea
if ( nDist < nRowMinDist)
nRowMinDist = nDist ;
}
else
m_Dists[ Index( i, j)] = MAXDIST ;
}
else
m_Dists[ Index( i, j)] = MAXDIST ;
}
// aggiorno il totale delle minime distanze
m_nTotMin += nRowMinDist ;
}
// nel caso di dipendenze suggerite, calcolo il coefficiente di costo massimo associato
if ( ExistSuggDependences())
m_nMaxDistSuggDep = CalcMaxDist() ;
// nel caso di percorso aperto senza vincoli, il numero delle distanze è uno meno di quello dei veri nodi
if ( m_nType == SP_OPEN &&
m_ObStart.nF == OB_NONE && m_ObEnd.nF == OB_NONE)
@@ -423,6 +447,38 @@ ShortestPath::RestorePath( NODE* pPath)
}
}
//----------------------------------------------------------------------------
void
ShortestPath::CopyPath( NODE* pPath, NODE* pPathCopy)
{
NODE* pCurr = pPathCopy ;
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
pCurr->nPos = pPath->nPos ;
pPath = pPath->pNext ;
pCurr = pCurr->pNext ;
}
}
//----------------------------------------------------------------------------
void
ShortestPath::CopyPathAdv( NODE* pPath, NODE* pPathCopy, NODE* pLast, NODE* pFirst, NODE* pKth,
NODE** pLastCopy, NODE** pFirstCopy, NODE** pKthCopy)
{
CopyPath( pPath, pPathCopy) ;
NODE* pCurr = pPath ;
NODE* pCurrCopy = pPathCopy ;
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
if ( pCurr == pLast)
*pLastCopy = pCurrCopy ;
if ( pCurr == pKth)
*pKthCopy = pCurrCopy ;
if ( pCurr == pFirst)
*pFirstCopy = pCurrCopy ;
pCurr = pCurr->pNext ;
pCurrCopy = pCurrCopy->pNext ;
}
}
//----------------------------------------------------------------------------
long long unsigned
ShortestPath::TotalCost( NODE* pPath)
@@ -438,6 +494,10 @@ ShortestPath::TotalCost( NODE* pPath)
nCost += ArcCost( pCurr->nPos, pCurr->pNext->nPos) ;
pCurr = pCurr->pNext ;
}
// se sono presenti delle dipendenze suggerite violate, aumento il costo
int nBreak = 0 ;
if ( ! IsPathRespectingSuggestedDependences( pPath, nBreak))
nCost += m_nMaxDistSuggDep * nBreak ;
return nCost ;
}