EgtNumKernel :
- Aggiunta classe di calcolo per ottimizzazione ordine delle lavorazioni - Aggiunti vincoli obbligatori e dipendenze suggerite a ShortestPath.
This commit is contained in:
+279
@@ -0,0 +1,279 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : Dependences.cpp Data : 16.04.25 Versione : 2.7a1
|
||||
// Contenuto : Scelta dei nodi in base alle dipenze per ShortestPath ;
|
||||
//
|
||||
//
|
||||
// Modifiche : 16.04.25 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "ShortestPath.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <new>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per impostare i vincoli di precendeza obbligatori */
|
||||
bool
|
||||
ShortestPath::SetConstraintOrder( int nPrev, int nNext)
|
||||
{
|
||||
// se ho già delle dipendenze inserite, controllo che non sia già inserita o in conflitto
|
||||
for ( auto it = m_vOrderConstr.begin() ; it != m_vOrderConstr.end() ; ++ it) {
|
||||
// se dipendenza già presente, non la considero
|
||||
if ( ( *it).first == nPrev && ( *it).second == nNext) {
|
||||
LOG_INFO( GetENkLogger(), string( "Constraint Dependence already in : " + ToString( nPrev) + ", " + ToString( nNext)).c_str()) ;
|
||||
return true ;
|
||||
}
|
||||
// se conflitto allora ritorno errore
|
||||
if ( ( *it).first == nNext && ( *it).second == nPrev) {
|
||||
LOG_INFO( GetENkLogger(), string( "Constraint Dependence conflict: " + ToString( nPrev) + ", " + ToString( nNext)).c_str()) ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// inserisco la dipendenze
|
||||
m_vOrderConstr.emplace_back( make_pair( nPrev, nNext)) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per impostare i vincoli di precedenza suggeriti */
|
||||
bool
|
||||
ShortestPath::SetSuggestedOrder( int nPrev, int nNext)
|
||||
{
|
||||
// se vettore dipendenze vuoto, lo alloco
|
||||
if ( m_vOrderSugg.empty()) {
|
||||
m_vOrderSugg.resize( m_nNumPnts * m_nNumPnts, false) ;
|
||||
m_vOrderSuggRowMap.resize( m_nNumPnts, false) ;
|
||||
}
|
||||
// se in conflitto, allora non la inserisco e cancello quella presente
|
||||
if ( m_vOrderSugg[ nNext * m_nNumPnts + nPrev]) {
|
||||
m_vOrderSugg[ nNext * m_nNumPnts + nPrev] = false ;
|
||||
return true ;
|
||||
}
|
||||
// inserisco la dipendenze
|
||||
m_vOrderSugg[ nPrev * m_nNumPnts + nNext] = true ;
|
||||
m_vOrderSuggRowMap[ nPrev] = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per verificare se un vincolo è violato o meno */
|
||||
bool
|
||||
ShortestPath::IsViolatingContraints( int nPrev, int nNext)
|
||||
{
|
||||
// scorro i vincoli
|
||||
for ( const INTINT nC : m_vOrderConstr) {
|
||||
// se il vincolo è ( nNext, nPrev) allora non è violato
|
||||
if ( nC.first == nNext && nC.second == nPrev)
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per verificare se un Path rispetta tutti i vincoli obbligatori */
|
||||
bool
|
||||
ShortestPath::IsPathRespectingContraints( NODE* pPath)
|
||||
{
|
||||
// controllo validità del percorso
|
||||
if ( pPath == nullptr)
|
||||
return false ;
|
||||
// controllo se il percorso ricavato, viola un vincolo
|
||||
for ( unsigned nC = 0 ; nC < m_vOrderConstr.size() ; ++ nC) {
|
||||
// scorro il percorso
|
||||
NODE* pCurr = pPath ;
|
||||
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
||||
if ( pCurr->nPos == m_vOrderConstr[nC].first)
|
||||
break ;
|
||||
if ( pCurr->nPos == m_vOrderConstr[nC].second)
|
||||
return false ;
|
||||
pCurr = pCurr->pNext ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per verificare se una rotazione ciclica di nodi viola dei vincoli */
|
||||
bool
|
||||
ShortestPath::IsChangingStartPathRespectingConstraints( NODE* pPath, NODE* pFirst)
|
||||
{
|
||||
// copio il percorso in quello per le dipendenze
|
||||
CopyPath( pPath, m_pCheckDep) ;
|
||||
NODE* pCurr = m_pCheckDep ;
|
||||
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
||||
// mi muovo alla posizione succesisva nel percorso di test
|
||||
pCurr = pCurr->pNext ;
|
||||
// controllo se il nuovo percorso rispetta i vincoli
|
||||
if ( IsPathRespectingContraints( pCurr)) {
|
||||
pFirst = pFirst->pNext ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per calcolare il numero di dipendenze SUGGERITE non rispettate da un Path */
|
||||
bool
|
||||
ShortestPath::IsPathRespectingSuggestedDependences( NODE* pPath, int& nBreak)
|
||||
{
|
||||
// se non ho dipendenze suggerite, ho finito
|
||||
if ( m_vOrderSugg.empty())
|
||||
return true ;
|
||||
// controllo validità del percorso
|
||||
nBreak = 0 ;
|
||||
if ( pPath == nullptr)
|
||||
return false ;
|
||||
// scrorro i nodi coinvolti da dipendenze
|
||||
unsigned nDim = m_nNumPnts - ( m_nType == SP_OPEN ? 1 : 0) ;
|
||||
for ( unsigned i = 0 ; i < nDim ; ++ i) {
|
||||
// controllo se il nodo corrente è legato da dipendenze suggerite
|
||||
if ( m_vOrderSuggRowMap[i]) {
|
||||
// scorro il percorso
|
||||
NODE* pCurr = pPath ;
|
||||
for ( unsigned j = 0 ; j < m_nNumPnts ; ++ j) {
|
||||
if ( pCurr->nPos != m_nNumPnts - 1) {
|
||||
if ( pCurr->nPos == i)
|
||||
break ;
|
||||
if ( m_vOrderSugg[ i * nDim + pCurr->nPos])
|
||||
++ nBreak ;
|
||||
}
|
||||
pCurr = pCurr->pNext ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( nBreak == 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per calcolare il coefficiente di costo per ogni dipedenza suggerita violata */
|
||||
unsigned
|
||||
ShortestPath::CalcMaxDist( void)
|
||||
{
|
||||
// scorro gli elementi della matrice delle distanze
|
||||
// NB. Si può decidere di calcolarlo diversamente
|
||||
if ( m_Dists == nullptr)
|
||||
return false ;
|
||||
unsigned nMaxDist = 0 ;
|
||||
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
||||
for ( unsigned j = 0 ; j < m_nNumPnts ; ++ j) {
|
||||
if ( i != j && m_Dists[ Index( i, j)] < MAXDIST - 1)
|
||||
nMaxDist = max( nMaxDist, m_Dists[ Index( i, j)]) ;
|
||||
}
|
||||
}
|
||||
return nMaxDist ;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
bool
|
||||
ShortestPath::ChooseFirstNode( unsigned& iFirst)
|
||||
{
|
||||
// definisco un vettore dei soli nodi che posso inserire
|
||||
vector<unsigned> vOkNodes ; vOkNodes.reserve( m_nNumPnts) ;
|
||||
// scorro i nodi i-esimi
|
||||
for ( unsigned i = 0 ; i < m_nNumPnts ; ++ i) {
|
||||
// non deve esistere alcun vincolo del tipo ( j, i)
|
||||
bool bOk = true ;
|
||||
for ( unsigned nC = 0 ; nC < m_vOrderConstr.size() && bOk ; ++ nC) {
|
||||
// recupero il vincolo ( a, b)
|
||||
const INTINT& nnDep = m_vOrderConstr[nC] ;
|
||||
bOk = nnDep.second != i ;
|
||||
}
|
||||
if ( bOk)
|
||||
vOkNodes.push_back( i) ;
|
||||
}
|
||||
// se non ho nodi, allora errore
|
||||
if ( vOkNodes.empty())
|
||||
return false ;
|
||||
// scelgo l'ultimo ( per percorsi OPEN)
|
||||
iFirst = vOkNodes.back() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
bool
|
||||
ShortestPath::ChooseNextNode( NODE* pPath, unsigned nSize, unsigned& jNext, bool bNearVsFar)
|
||||
{
|
||||
// recupero i nodi non inseriti nel path
|
||||
jNext = -1 ;
|
||||
vector<unsigned> vUninstertedNodes ; vUninstertedNodes.reserve( m_nNumPnts) ;
|
||||
for ( unsigned nInd = 0 ; nInd < m_nNumPnts ; ++ nInd) {
|
||||
bool bIn = false ;
|
||||
NODE* pNode = pPath ;
|
||||
for ( unsigned nNode = 0 ; nNode < nSize && ! bIn ; ++ nNode) {
|
||||
bIn = ( pNode->nPos == nInd) ;
|
||||
pNode = pNode->pPrev ;
|
||||
}
|
||||
if ( ! bIn)
|
||||
vUninstertedNodes.push_back( nInd) ;
|
||||
}
|
||||
// se tutti i nodi sono inseriti, allora non faccio nulla
|
||||
if ( vUninstertedNodes.empty())
|
||||
return true ;
|
||||
// se un solo nodo non inserito, allora non ho altra scelta
|
||||
if ( vUninstertedNodes.size() == unsigned( 1)) {
|
||||
jNext = vUninstertedNodes[0] ;
|
||||
return true ;
|
||||
}
|
||||
// definisco un vettore dei soli nodi che posso inserire
|
||||
vector<unsigned> vOkNodes ; vOkNodes.reserve( m_nNumPnts) ;
|
||||
// scorro i nodi che devo ancora posizionare
|
||||
for ( unsigned j : vUninstertedNodes) {
|
||||
/*
|
||||
* l'ultimo nodo inserito è l'i-esimo, e il successivo sarà il j-esimo ( i ---> j)
|
||||
* devo controllare che tra i nodi inseriti non ci sia un nodo k tale per cui viene violato
|
||||
* il vincolo ( k, j)
|
||||
*/
|
||||
// controllo che l'arco ( i --> j) sia valido
|
||||
if ( ! m_Available[ Index( pPath->nPos, j)])
|
||||
continue ;
|
||||
// scorro i vincoli
|
||||
bool bOk = true ;
|
||||
for ( unsigned nC = 0 ; nC < m_vOrderConstr.size() && bOk ; ++ nC) {
|
||||
// recupero il vincolo ( a, b)
|
||||
const INTINT& nnDep = m_vOrderConstr[nC] ;
|
||||
// controllo se esiste un vincolo del tipo ( ?, j)
|
||||
if ( nnDep.second == j) {
|
||||
// in questo caso controllo se esiste un nodo k != j che viola il vincolo ( k, j)
|
||||
for ( unsigned k = 0 ; k < vUninstertedNodes.size() && bOk ; ++ k) {
|
||||
if ( vUninstertedNodes[k] != j)
|
||||
bOk = ( vUninstertedNodes[k] != nnDep.first) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se vincolo non violato, allora il nodo j può essere inserito
|
||||
if ( bOk)
|
||||
vOkNodes.push_back( j) ;
|
||||
}
|
||||
// se non posso inserire alcun nodo, allora errore
|
||||
if ( vOkNodes.empty())
|
||||
return false ;
|
||||
// se un solo nodo possibile, allora è quello
|
||||
if ( vOkNodes.size() == unsigned( 1)) {
|
||||
jNext = vOkNodes[0] ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti seleziono il nodo j-esimo tale per cui l'arco ( i --> j) ha costo minimo/assimo ( bNearVsFar)
|
||||
int nRefDist = bNearVsFar ? MAXDIST : -1 ;
|
||||
for ( unsigned j : vOkNodes) {
|
||||
int nDist = int( ArcCost( pPath->nPos, j)) ;
|
||||
bool bUpdate = false ;
|
||||
if ( bNearVsFar)
|
||||
bUpdate = ( nDist < nRefDist) ;
|
||||
else
|
||||
bUpdate = ( nDist > nRefDist) ;
|
||||
if ( bUpdate) {
|
||||
nRefDist = nDist ;
|
||||
jNext = j ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
Reference in New Issue
Block a user