snark
equivalence_classes.h
1 // This file is part of snark, a generic and flexible library
2 // for robotics research.
3 //
4 // Copyright (C) 2011 The University of Sydney
5 //
6 // snark is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // snark is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 // for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with snark. If not, see <http://www.gnu.org/licenses/>.
18 
20 
21 #ifndef SNARK_PERCEPTION_EQUIVALENCECLASSES_HEADER_GUARD_
22 #define SNARK_PERCEPTION_EQUIVALENCECLASSES_HEADER_GUARD_
23 
24 #include <cmath>
25 #include <list>
26 #include <map>
27 #include <boost/unordered_map.hpp>
28 #include <boost/unordered_set.hpp>
29 #include <comma/base/types.h>
30 
31 namespace snark {
32 
34 template < typename It, typename N, typename Tr >
35 inline std::map< comma::uint32, std::list< It > > equivalence_classes( const It& begin, const It& end, comma::uint32 minId )
36 {
37  typedef std::list< It > partition_type;
38  typedef std::map< comma::uint32, partition_type > partitions_type;
39  partitions_type partitions;
40  comma::uint32 maxId = minId;
41  for( It it = begin; it != end; ++it )
42  {
43  if( Tr::skip( *it ) ) { continue; }
44  if( !Tr::visited( *it ) )
45  {
46  for( typename N::iterator nit = N::begin( it ); nit != N::end( it ); ++nit )
47  {
48  if( Tr::skip( *nit ) ) { continue; }
49  if( !Tr::visited( *nit ) || !Tr::same( *it, *nit ) ) { continue; }
50  Tr::set_visited( *it, true );
51  Tr::set_id( *it, Tr::id( *nit ) );
52  }
53  if( !Tr::visited( *it ) )
54  {
55  Tr::set_visited( *it, true );
56  Tr::set_id( *it, maxId++ );
57  }
58  }
59  comma::uint32 id = Tr::id( *it );
60  partition_type& p( partitions[id] );
61  p.push_back( it );
62  for( typename N::iterator nit = N::begin( it ); nit != N::end( it ); ++nit )
63  {
64  if( Tr::skip( *nit ) ) { continue; }
65  if( !Tr::visited( *nit ) || !Tr::same( *it, *nit ) || id == Tr::id( *nit ) ) { continue; }
66  typename partitions_type::iterator old = partitions.find( Tr::id( *nit ) );
67  for( typename partition_type::iterator i = old->second.begin(); i != old->second.end(); ++i ) // todo: below is quite suboptimal, improve!
68  {
69  Tr::set_id( *It( *i ), id ); // quick and dirty to wave constness // Tr::set_id( **i, id );
70  }
71  p.splice( p.end(), old->second, old->second.begin(), old->second.end() );
72  partitions.erase( old );
73  }
74  }
75  return partitions;
76 }
77 
78 } // namespace snark
79 
80 #endif // SNARK_PERCEPTION_EQUIVALENCECLASSES_HEADER_GUARD_