-#ifndef __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
-#define __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+#ifndef __fpa__Base__MinimumSpanningTree__hxx__
+#define __fpa__Base__MinimumSpanningTree__hxx__
#include <limits>
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-const unsigned long fpa::Base::
-MinimumSpanningTree< _TSuperclass, _TVertex >::INF_VALUE =
- std::numeric_limits< unsigned long >::max( );
-
+template< class _TVertex, class _TSuperclass >
+const typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+TCollisions& fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+GetCollisions( ) const
+{
+ return( this->m_Collisions );
+}
+
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
SetCollisions( const TCollisions& collisions )
{
- // Prepare a front graph
+ static const unsigned long _inf =
+ std::numeric_limits< unsigned long >::max( );
+ if( this->m_Collisions == collisions )
+ return;
+
this->m_Collisions = collisions;
- unsigned long nSeeds = this->m_Collisions.size( );
- _TMatrix dist( nSeeds, _TRow( nSeeds, Self::INF_VALUE ) );
+
+ // Prepare a front graph
+ unsigned long N = this->m_Collisions.size( );
+ _TMatrix dist( N, _TRow( N, _inf ) );
this->m_FrontPaths = dist;
- for( unsigned long i = 0; i < nSeeds; ++i )
+ for( unsigned long i = 0; i < N; ++i )
{
- for( unsigned long j = 0; j < nSeeds; ++j )
+ for( unsigned long j = 0; j < N; ++j )
{
if( this->m_Collisions[ i ][ j ].second )
{
} // rof
- // Use Floyd-Warshall to compute all possible paths
- for( unsigned long k = 0; k < nSeeds; ++k )
+ // Use Floyd-Warshall to compute all possible paths between fronts
+ for( unsigned long k = 0; k < N; ++k )
{
- for( unsigned long i = 0; i < nSeeds; ++i )
+ for( unsigned long i = 0; i < N; ++i )
{
- for( unsigned long j = 0; j < nSeeds; ++j )
+ for( unsigned long j = 0; j < N; ++j )
{
- if( ( dist[ i ][ k ] + dist[ k ][ j ] ) < dist[ i ][ j ] )
+ // WARNING: you don't want a numeric overflow!!!
+ unsigned long dik = dist[ i ][ k ];
+ unsigned long dkj = dist[ k ][ j ];
+ unsigned long sum = _inf;
+ if( dik < _inf && dkj < _inf )
+ sum = dik + dkj;
+
+ // Ok, continue Floyd-Warshall
+ if( sum < dist[ i ][ j ] )
{
- dist[ i ][ j ] = dist[ i ][ k ] + dist[ k ][ j ];
+ dist[ i ][ j ] = sum;
this->m_FrontPaths[ i ][ j ] = this->m_FrontPaths[ i ][ k ];
} // fi
}
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TVertices fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetPath( const TVertex& a ) const
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+ClearSeeds( )
{
- TVertices path;
- if( this->_HasVertex( a ) )
- this->_Path( path, a );
- return( path );
+ this->m_Seeds.clear( );
+ this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TSuperclass >
+void fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+AddSeed( const _TVertex& seed )
+{
+ this->m_Seeds.push_back( seed );
+ this->Modified( );
}
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TVertices fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetPath( const TVertex& a, const TVertex& b ) const
+template< class _TVertex, class _TSuperclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+GetPath( const _TVertex& a ) const
{
TVertices path;
+ _TVertex it = a;
+ _TVertex p = this->GetParent( it );
+ while( it != p )
+ {
+ path.push_front( it );
+ it = p;
+ p = this->GetParent( it );
- // Check existence
- if( !this->_HasVertex( a ) || !this->_HasVertex( b ) )
- return( path );
-
- // Get front ids
- short fa = this->_FrontId( a );
- short fb = this->_FrontId( b );
+ } // elihw
+ path.push_front( it );
+ return( path );
+}
- if( fa == fb )
- {
- // Get paths
- TVertices ap, bp;
- this->_Path( ap, a );
- this->_Path( bp, b );
-
- // Ignore common part: find common ancestor
- auto raIt = ap.rbegin( );
- auto rbIt = bp.rbegin( );
- while( *raIt == *rbIt && raIt != ap.rend( ) && rbIt != bp.rend( ) )
- {
- ++raIt;
- ++rbIt;
-
- } // elihw
- if( raIt != ap.rbegin( ) ) --raIt;
- if( rbIt != bp.rbegin( ) ) --rbIt;
-
- // Add part from a
- for( auto iaIt = ap.begin( ); iaIt != ap.end( ) && *iaIt != *raIt; ++iaIt )
- path.push_back( *iaIt );
-
- // Add part from b
- for( ; rbIt != bp.rend( ); ++rbIt )
- path.push_back( *rbIt );
- }
- else
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TSuperclass >
+typename fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+TVertices fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
+GetPath( const _TVertex& a, const _TVertex& b ) const
+{
+ static const unsigned long _inf =
+ std::numeric_limits< unsigned long >::max( );
+
+ TVertices path;
+ TVertices pa = this->GetPath( a );
+ TVertices pb = this->GetPath( b );
+ if( pa.size( ) > 0 && pb.size( ) > 0 )
{
- // Use this->m_FrontPaths from Floyd-Warshall
- if( this->m_FrontPaths[ fa ][ fb ] < Self::INF_VALUE )
+ // Find front identifiers
+ unsigned long ia = _inf, ib = _inf;
+ unsigned long N = this->m_Seeds.size( );
+ for( unsigned long i = 0; i < N; ++i )
{
- // Compute front path
- std::vector< long > fpath;
- fpath.push_back( fa );
- while( fa != fb )
- {
- fa = this->m_FrontPaths[ fa ][ fb ];
- fpath.push_back( fa );
+ if( this->m_Seeds[ i ] == pa.front( ) )
+ ia = i;
+ if( this->m_Seeds[ i ] == pb.front( ) )
+ ib = i;
- } // elihw
+ } // rof
- // Continue only if both fronts are connected
- unsigned int N = fpath.size( );
- if( N > 0 )
+ if( ia != ib )
+ {
+ // Use this->m_FrontPaths from Floyd-Warshall
+ if( this->m_FrontPaths[ ia ][ ib ] < _inf )
{
- // First path: from start vertex to first collision
- path = this->GetPath(
- a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
- );
-
- // Intermediary paths
- for( unsigned int i = 1; i < N - 1; ++i )
+ // Compute front path
+ std::vector< long > fpath;
+ fpath.push_back( ia );
+ while( ia != ib )
{
- TVertices ipath =
- this->GetPath(
- this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first,
- this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first
- );
- path.insert( path.end( ), ipath.begin( ), ipath.end( ) );
+ ia = this->m_FrontPaths[ ia ][ ib ];
+ fpath.push_back( ia );
- } // rof
+ } // elihw
- // Final path: from last collision to end point
- TVertices lpath =
- this->GetPath(
- this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b
+ // Continue only if both fronts are connected
+ unsigned int N = fpath.size( );
+ if( N > 0 )
+ {
+ // First path: from start vertex to first collision
+ path = this->GetPath(
+ a, this->m_Collisions[ fpath[ 0 ] ][ fpath[ 1 ] ].first
);
- path.insert( path.end( ), lpath.begin( ), lpath.end( ) );
- } // fi
+ // Intermediary paths
+ for( unsigned int i = 1; i < N - 1; ++i )
+ {
+ TVertices ipath =
+ this->GetPath(
+ this->m_Collisions[ fpath[ i ] ][ fpath[ i - 1 ] ].first,
+ this->m_Collisions[ fpath[ i ] ][ fpath[ i + 1 ] ].first
+ );
+ path.insert( path.end( ), ipath.begin( ), ipath.end( ) );
- } // fi
+ } // rof
- } // fi
- return( path );
-}
+ // Final path: from last collision to end point
+ TVertices lpath =
+ this->GetPath(
+ this->m_Collisions[ fpath[ N - 1 ] ][ fpath[ N - 2 ] ].first, b
+ );
+ path.insert( path.end( ), lpath.begin( ), lpath.end( ) );
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TPoints fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetEuclideanPath( const TVertex& a ) const
-{
- TPoints points;
- return( points );
-}
+ } // fi
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-typename fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-TPoints fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-GetEuclideanPath( const TVertex& a, const TVertex& b ) const
-{
- TPoints points;
- return( points );
-}
+ } // fi
+ }
+ else
+ {
+ // Ignore common part: find common ancestor
+ auto aIt = pa.begin( );
+ auto bIt = pb.begin( );
+ while( *aIt == *bIt && aIt != pa.end( ) && bIt != pb.end( ) )
+ {
+ ++aIt;
+ ++bIt;
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-bool fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-IsDefinedInEuclideanSpace( ) const
-{
- return( false );
-}
+ } // elihw
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-SetNode(
- const TVertex& v, const TVertex& p,
- const short& fid, const double& cost
- )
-{
- typedef typename TNodeQueue::value_type _TNodeQueueValue;
- if( this->m_FillNodeQueue )
- this->m_NodeQueue.insert( _TNodeQueueValue( cost, v ) );
-}
+ // Glue both parts
+ for( --aIt; aIt != pa.end( ); ++aIt )
+ path.push_front( *aIt );
+ for( ; bIt != pb.end( ); ++bIt )
+ path.push_back( *bIt );
-// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-void fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
-Clear( )
-{
- this->m_NodeQueue.clear( );
+ } // fi
+
+ } // fi
+ return( path );
}
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
MinimumSpanningTree( )
- : Superclass( ),
- m_FillNodeQueue( false )
+ : Superclass( )
{
}
// -------------------------------------------------------------------------
-template< class _TSuperclass, class _TVertex >
-fpa::Base::MinimumSpanningTree< _TSuperclass, _TVertex >::
+template< class _TVertex, class _TSuperclass >
+fpa::Base::MinimumSpanningTree< _TVertex, _TSuperclass >::
~MinimumSpanningTree( )
{
}
-#endif // __FPA__BASE__MINIMUMSPANNINGTREE__HXX__
+#endif // __fpa__Base__MinimumSpanningTree__hxx__
// eof - $RCSfile$