EgtNumKernel 2.7l1 :
- in Machining Optimization aggiunta ottimizzazione mirata ai singoli gruppi.
This commit is contained in:
+252
-62
@@ -59,6 +59,7 @@ MachOptimization::MachOptimization( void)
|
||||
m_dFeedL = 1. ;
|
||||
m_dFeedA = 1. ;
|
||||
m_bAllMandatory = false ;
|
||||
m_bOptInGroup = false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -233,6 +234,14 @@ MachOptimization::SetAllGroupsAsMandatory( bool bAllMandatory)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MachOptimization::SetOptimizationForGroups( bool bOptForGroups)
|
||||
{
|
||||
m_bOptInGroup = bOptForGroups ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione che assegna le dipendenze suggerite in base ai Gruppi */
|
||||
bool
|
||||
@@ -469,6 +478,14 @@ MachOptimization::CalcMachTime( int nInd1, int nInd2, int& nTime)
|
||||
MachOptm& Lav1 = m_vMachOptm[nInd1] ;
|
||||
MachOptm& Lav2 = m_vMachOptm[nInd2] ;
|
||||
|
||||
return ( CalcMachTime( Lav1, Lav2, nTime)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per calcolare il tempo nel passare da una lavorazione all'altra */
|
||||
bool
|
||||
MachOptimization::CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int& nTime)
|
||||
{
|
||||
// Se l'utensile è lo stesso
|
||||
if ( Lav1.nIdTool == Lav2.nIdTool)
|
||||
nTime = int( max( CalcTimeLavLav( Lav1, Lav2, true), CalcTimeLavLav( Lav1, Lav2, false))) ;
|
||||
@@ -494,8 +511,6 @@ bool
|
||||
MachOptimization::ComputeTimeMatrix( INTMATRIX& mTimes)
|
||||
{
|
||||
// Creo una copia dei vettori delle dipendenze ( le cancello di volta in volta che le assegno)
|
||||
INTINTVECTOR vDep = m_vDependences ;
|
||||
INTINTVECTOR vSuggDep = m_vSuggDependences ;
|
||||
const int N = int( m_vMachOptm.size()) ;
|
||||
// Matrice NxN ( con Flag per cella già calcolata)
|
||||
mTimes.clear() ;
|
||||
@@ -573,6 +588,70 @@ MachOptimization::GetIndById( int nId)
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per separare le lavorazioni e le dipendenze a seconda dei gruppi */
|
||||
bool
|
||||
MachOptimization::SplitMachOptsInGroups( MACHOPTMMATRIX& matMachOpt, vector<INTINTVECTOR>& matDep,
|
||||
vector<INTINTVECTOR>& matSuggDep)
|
||||
{
|
||||
// Se non ho lavorazioni, non faccio nulla
|
||||
if ( m_vMachOptm.empty())
|
||||
return true ;
|
||||
// Se non devo ottimizzare per gruppi, errore
|
||||
if ( ! m_bOptInGroup)
|
||||
return false ;
|
||||
|
||||
// Ordino le lavorazioni in base al gruppo
|
||||
sort( m_vMachOptm.begin(), m_vMachOptm.end(), []( const MachOptm& MachA, const MachOptm& MachB) {
|
||||
return ( MachA.nGroup > MachB.nGroup) ;
|
||||
}) ;
|
||||
|
||||
// Separo le lavorazioni
|
||||
int nHighestPriority = m_vMachOptm[0].nGroup ;
|
||||
matMachOpt.emplace_back( MACHOPTMVECTOR{}) ;
|
||||
matMachOpt.back().emplace_back( m_vMachOptm[0]) ;
|
||||
for ( int i = 1 ; i < int( m_vMachOptm.size()) ; ++ i) {
|
||||
if ( m_vMachOptm[i].nGroup < nHighestPriority) {
|
||||
matMachOpt.emplace_back( MACHOPTMVECTOR{}) ;
|
||||
nHighestPriority = m_vMachOptm[i].nGroup ;
|
||||
}
|
||||
matMachOpt.back().emplace_back( m_vMachOptm[i]) ;
|
||||
}
|
||||
|
||||
// Recupero le Dipendeze Obbligatorie e Suggerite tra i vari gruppi
|
||||
BOOLVECTOR vbDep( m_vDependences.size(), false) ;
|
||||
BOOLVECTOR vbSuggDep( m_vSuggDependences.size(), false) ;
|
||||
for ( const MACHOPTMVECTOR& vMachOpt : matMachOpt) {
|
||||
// Recupero gli Id delle lavorazioni correnti
|
||||
INTVECTOR vId ; vId.reserve( vMachOpt.size()) ;
|
||||
for ( const MachOptm& Lav : vMachOpt)
|
||||
vId.push_back( Lav.nId) ;
|
||||
// Inizializzo i vettori delle dipendenze
|
||||
matDep.emplace_back( INTINTVECTOR{}) ;
|
||||
matSuggDep.emplace_back( INTINTVECTOR{}) ;
|
||||
// Recupero le dipendenze associate a questo gruppo
|
||||
// NB. Devono essere solamente dipendenze interne al gruppo ( le altre vengono scartate a priori)
|
||||
for ( int i = 0 ; i < int( m_vDependences.size()) ; ++ i) {
|
||||
if ( ! vbDep[i] &&
|
||||
find( vId.begin(), vId.end(), m_vDependences[i].first) != vId.end() &&
|
||||
find( vId.begin(), vId.end(), m_vDependences[i].second) != vId.end()) {
|
||||
matDep.back().emplace_back( m_vDependences[i]) ;
|
||||
vbDep[i] = true ;
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < int( m_vSuggDependences.size()) ; ++ i) {
|
||||
if ( ! vbSuggDep[i] &&
|
||||
find( vId.begin(), vId.end(), m_vSuggDependences[i].first) != vId.end() &&
|
||||
find( vId.begin(), vId.end(), m_vSuggDependences[i].second) != vId.end()){
|
||||
matSuggDep.back().emplace_back( m_vSuggDependences[i]) ;
|
||||
vbSuggDep[i] = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MachOptimization::GetResult( INTVECTOR& vIds)
|
||||
@@ -586,73 +665,184 @@ MachOptimization::GetResult( INTVECTOR& vIds)
|
||||
vIds.push_back( m_vMachOptm[0].nId) ;
|
||||
return true ;
|
||||
}
|
||||
// Inserisco le lavorazioni per ordine di inserimento
|
||||
for ( const MachOptm& myLav : m_vMachOptm)
|
||||
vIds.push_back( myLav.nId) ;
|
||||
// Inizializzo le dipendenze suggerite dai gruppi di lavorazione
|
||||
if ( ! SetGroupDependences()) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in defining Group depedences") ;
|
||||
return false ;
|
||||
}
|
||||
// Calcolo la matrice dei tempi
|
||||
INTMATRIX mTimes ;
|
||||
if ( ! ComputeTimeMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in Computing Time Matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Istanzio il Problema ShortesPath con vincoli
|
||||
PtrOwner<IShortestPath> mySP( CreateShortestPath()) ;
|
||||
if ( IsNull( mySP))
|
||||
return false ;
|
||||
// Per ogni lavorazione inserisco gli estremi
|
||||
for ( const MachOptm& Lav : m_vMachOptm) {
|
||||
if ( ! mySP->AddPoint( Lav.dX_Start, Lav.dY_Start, Lav.dZ_End, 0., 0.,
|
||||
Lav.dX_End, Lav.dY_End, Lav.dZ_End, 0., 0.)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error adding Machining Bounds") ;
|
||||
|
||||
// --- Se richiesta ottimizzazione solo interna per i gruppi
|
||||
if ( m_bOptInGroup) {
|
||||
// Recupero tutti i gruppi e le dipendenze separatamente ed ordinate per priorità di gruppo
|
||||
MACHOPTMMATRIX matMachOpt ;
|
||||
vector<INTINTVECTOR> matDep, matSuggDep ;
|
||||
if ( ! SplitMachOptsInGroups( matMachOpt, matDep, matSuggDep))
|
||||
return false ;
|
||||
// Per ognuna di esse eseguo l'algoritmo di ShortestPath
|
||||
MachOptm LastMach ;
|
||||
for ( int i = 0 ; i < int( matMachOpt.size()) ; ++ i) {
|
||||
m_vMachOptm.clear() ;
|
||||
m_vDependences.clear() ;
|
||||
m_vSuggDependences.clear() ;
|
||||
if ( matMachOpt.empty())
|
||||
continue ;
|
||||
m_vMachOptm = matMachOpt[i] ;
|
||||
m_vDependences = matDep[i] ;
|
||||
m_vSuggDependences = matSuggDep[i] ;
|
||||
// Calcolo la matrice dei tempi
|
||||
INTMATRIX mTimes ;
|
||||
if ( ! ComputeTimeMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in Computing Time Matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Istanzio il Problema ShortesPath con vincoli
|
||||
PtrOwner<IShortestPath> mySP( CreateShortestPath()) ;
|
||||
if ( IsNull( mySP))
|
||||
return false ;
|
||||
// Per ogni lavorazione inserisco gli estremi
|
||||
for ( const MachOptm& Lav : m_vMachOptm) {
|
||||
if ( ! mySP->AddPoint( Lav.dX_Start, Lav.dY_Start, Lav.dZ_End, 0., 0.,
|
||||
Lav.dX_End, Lav.dY_End, Lav.dZ_End, 0., 0.)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error adding Machining Bounds") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Assegno la matrice delle distanze calcolata in precedenza
|
||||
if ( ! mySP->SetDistMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Se ho una lavorazione impostata in precedenza
|
||||
if ( LastMach.nId != -1) {
|
||||
// Cerco le lavorazioni che non presentano precedenze
|
||||
MACHOPTMVECTOR vLav ; vLav.reserve( m_vMachOptm.size()) ;
|
||||
if ( m_vDependences.empty())
|
||||
vLav = m_vMachOptm ;
|
||||
else {
|
||||
INTSET setSecondDep ;
|
||||
for ( const INTINT& Dep : m_vDependences)
|
||||
setSecondDep.insert( Dep.second) ;
|
||||
for ( int i = 0 ; i < int( m_vMachOptm.size()) ; ++ i) {
|
||||
if ( setSecondDep.find( m_vMachOptm[i].nId) == setSecondDep.end())
|
||||
vLav.emplace_back( m_vMachOptm[i]) ;
|
||||
}
|
||||
}
|
||||
// Tra quelle valide cerco la migliore da cui partire
|
||||
int nBestLavId = 0 ;
|
||||
int nBestTime = MAXTIME ;
|
||||
for ( int i = 0 ; i < int( vLav.size()) ; ++ i) {
|
||||
int nCurrTime = MAXTIME ;
|
||||
CalcMachTime( LastMach, vLav[i], nCurrTime) ;
|
||||
if ( nCurrTime < nBestTime) {
|
||||
nBestTime = nCurrTime ;
|
||||
nBestLavId = vLav[i].nId ;
|
||||
}
|
||||
}
|
||||
// Imposto la prima lavorazione
|
||||
if ( ! SetFirstMachining( nBestLavId))
|
||||
return false ;
|
||||
}
|
||||
// Per ogni dipendeza obbligatoria assegno un vincolo
|
||||
for ( const INTINT& nnDep : m_vDependences) {
|
||||
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Constraints") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Aggiungo le dipendenza suggerite
|
||||
for ( const INTINT& nnSuggDep : m_vSuggDependences) {
|
||||
if ( ! mySP->SetSuggestedOrder( GetIndById( nnSuggDep.first), GetIndById( nnSuggDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Suggested Dependence") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Calcolo la soluzione
|
||||
#if _TIME_DEBUG
|
||||
PerformanceCounter PC ; PC.Start() ;
|
||||
#endif
|
||||
if ( ! mySP->Calculate( IShortestPath::SP_OPEN)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
|
||||
return false ;
|
||||
}
|
||||
// Recupero l'ordine
|
||||
INTVECTOR U ;
|
||||
if ( ! mySP->GetOrder( U)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in ordering") ;
|
||||
return false ;
|
||||
}
|
||||
// Restituisco gli Id ordinati
|
||||
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
|
||||
vIds.emplace_back( m_vMachOptm[U[nInd]].nId) ;
|
||||
// Memorizzo l'ultima lavorazione per il gruppo successivo
|
||||
LastMach = ( U.empty() ? MachOptm() : m_vMachOptm[U.back()]) ;
|
||||
}
|
||||
}
|
||||
// Assegno la matrice delle distanze calcolata in precedenza
|
||||
if ( ! mySP->SetDistMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Per ogni dipendeza obbligatoria assegno un vincolo
|
||||
for ( const INTINT& nnDep : m_vDependences) {
|
||||
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Constraints") ;
|
||||
|
||||
//--- Se invece ottimizzazione globale
|
||||
else {
|
||||
// Inserisco le lavorazioni per ordine di inserimento
|
||||
for ( const MachOptm& myLav : m_vMachOptm)
|
||||
vIds.push_back( myLav.nId) ;
|
||||
// Inizializzo le dipendenze suggerite dai gruppi di lavorazione
|
||||
if ( ! SetGroupDependences()) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in defining Group depedences") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Aggiungo le dipendenza suggerite
|
||||
for ( const INTINT& nnSuggDep : m_vSuggDependences) {
|
||||
if ( ! mySP->SetSuggestedOrder( GetIndById( nnSuggDep.first), GetIndById( nnSuggDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Suggested Dependence") ;
|
||||
// Calcolo la matrice dei tempi
|
||||
INTMATRIX mTimes ;
|
||||
if ( ! ComputeTimeMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in Computing Time Matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Istanzio il Problema ShortesPath con vincoli
|
||||
PtrOwner<IShortestPath> mySP( CreateShortestPath()) ;
|
||||
if ( IsNull( mySP))
|
||||
return false ;
|
||||
// Per ogni lavorazione inserisco gli estremi
|
||||
for ( const MachOptm& Lav : m_vMachOptm) {
|
||||
if ( ! mySP->AddPoint( Lav.dX_Start, Lav.dY_Start, Lav.dZ_End, 0., 0.,
|
||||
Lav.dX_End, Lav.dY_End, Lav.dZ_End, 0., 0.)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error adding Machining Bounds") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Assegno la matrice delle distanze calcolata in precedenza
|
||||
if ( ! mySP->SetDistMatrix( mTimes)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
|
||||
return false ;
|
||||
}
|
||||
// Per ogni dipendeza obbligatoria assegno un vincolo
|
||||
for ( const INTINT& nnDep : m_vDependences) {
|
||||
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Constraints") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Aggiungo le dipendenza suggerite
|
||||
for ( const INTINT& nnSuggDep : m_vSuggDependences) {
|
||||
if ( ! mySP->SetSuggestedOrder( GetIndById( nnSuggDep.first), GetIndById( nnSuggDep.second))) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in adding Suggested Dependence") ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// Calcolo la soluzione
|
||||
#if _TIME_DEBUG
|
||||
PerformanceCounter PC ; PC.Start() ;
|
||||
#endif
|
||||
if ( ! mySP->Calculate( IShortestPath::SP_OPEN)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
|
||||
return false ;
|
||||
}
|
||||
#if _TIME_DEBUG
|
||||
string sTime = string( to_string( m_vDependences.size()) + string( "Time : ") + ToString( PC.Stop())) ;
|
||||
LOG_INFO( GetENkLogger(), sTime.c_str()) ;
|
||||
#endif
|
||||
// Recupero l'ordine
|
||||
INTVECTOR U ;
|
||||
if ( ! mySP->GetOrder( U)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in ordering") ;
|
||||
return false ;
|
||||
}
|
||||
// Restituisco gli Id ordinati
|
||||
vIds.resize( m_vMachOptm.size()) ;
|
||||
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
|
||||
vIds[nInd] = m_vMachOptm[U[nInd]].nId ;
|
||||
}
|
||||
// Calcolo la soluzione
|
||||
#if _TIME_DEBUG
|
||||
PerformanceCounter PC ; PC.Start() ;
|
||||
#endif
|
||||
if ( ! mySP->Calculate( IShortestPath::SP_OPEN)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
|
||||
return false ;
|
||||
}
|
||||
#if _TIME_DEBUG
|
||||
string sTime = string( to_string( m_vDependences.size()) + string( "Time : ") + ToString( PC.Stop())) ;
|
||||
LOG_INFO( GetENkLogger(), sTime.c_str()) ;
|
||||
#endif
|
||||
// Recupero l'ordine
|
||||
INTVECTOR U ;
|
||||
if ( ! mySP->GetOrder( U)) {
|
||||
LOG_ERROR( GetENkLogger(), "Error in ordering") ;
|
||||
return false ;
|
||||
}
|
||||
// Restituisco gli Id ordinati
|
||||
vIds.resize( m_vMachOptm.size()) ;
|
||||
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
|
||||
vIds[nInd] = m_vMachOptm[U[nInd]].nId ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user