Radium Engine  1.5.0
AdjacencyList.cpp
1 #include <Core/Containers/AdjacencyList.hpp>
2 
3 #include <fstream>
4 
5 namespace Ra {
6 namespace Core {
7 
9 AdjacencyList::AdjacencyList() : m_child(), m_parent() {}
10 AdjacencyList::AdjacencyList( const uint n ) : m_child( n ), m_parent( n, -1 ) {}
12  m_child( adj.m_child ), m_parent( adj.m_parent ) {}
13 
16 
19  uint idx = size();
20  m_child.push_back( ChildrenList() );
21  m_parent.push_back( -1 );
22  m_level.push_back( 0 );
23  return idx;
24 }
25 
26 uint AdjacencyList::addNode( const uint parent ) {
27  CORE_ASSERT( ( parent < size() ), "Index parent out of bounds" );
28  uint idx = size();
29  m_child.push_back( ChildrenList() );
30  m_parent.push_back( parent );
31  m_level.push_back( m_level[parent] + 1 );
32  m_child[parent].push_back( idx );
33  return idx;
34 }
35 
36 void AdjacencyList::pruneLeaves( std::vector<uint>& pruned, std::vector<bool>& delete_flag ) {
37  pruned.clear();
38  delete_flag.clear();
39  delete_flag.resize( this->size(), false );
40  std::vector<bool> prune_flag = delete_flag;
41  for ( uint i = 0; i < this->size(); ++i ) {
42  if ( this->isLeaf( i ) && !this->isRoot( i ) ) {
43  delete_flag[i] = true;
44  prune_flag[i] = true;
45  }
46  else { pruned.push_back( i ); }
47  }
48 
49  for ( uint j = this->size(); j > 0; --j ) {
50  const uint i = j - 1;
51  if ( prune_flag[i] ) {
52  this->m_parent.erase( this->m_parent.begin() + i );
53  this->m_child.erase( this->m_child.begin() + i );
54  prune_flag.erase( prune_flag.begin() + i );
55  ++j;
56  }
57  }
58 
59  for ( uint i = 0; i < this->size(); ++i ) {
60  this->m_parent[i] =
61  ( ( this->m_parent[i] == -1 ) || ( delete_flag[i] ) ) ? -1 : pruned[this->m_parent[i]];
62  for ( auto it = this->m_child[i].begin(); it != this->m_child[i].end(); ++it ) {
63  if ( delete_flag[( *it )] ) {
64  this->m_child[i].erase( it );
65  --it;
66  }
67  else { *it = pruned[*it]; }
68  }
69  }
70 }
71 
73  std::vector<uint> p;
74  std::vector<bool> d;
75  this->pruneLeaves( p, d );
76 }
77 
79  using Edge = Eigen::Matrix<uint, 2, 1>;
80  VectorArray<Edge> edgeList;
81 
82  for ( uint i = 0; i < m_child.size(); ++i ) {
83  if ( include_leaf && isLeaf( i ) ) {
84  Edge e;
85  e( 0 ) = i;
86  e( 1 ) = i;
87  edgeList.push_back( e );
88  }
89  else {
90  for ( const auto& edge : m_child[i] ) {
91  Edge e;
92  e( 0 ) = i;
93  e( 1 ) = edge;
94  edgeList.push_back( e );
95  }
96  }
97  }
98  return edgeList;
99 }
100 
101 AdjacencyList::ConsistencyStatus AdjacencyList::computeConsistencyStatus() const {
102  // Note: we abort at the first error found to keep the error backtrace
103  if ( m_parent.size() != m_child.size() ) {
104  return ConsistencyStatus::IncompatibleChildrenAndParentList;
105  }
106 
107  for ( uint node = 0; node < size(); ++node ) {
108  if ( m_parent.at( node ) >= int( node ) ) { return ConsistencyStatus::WrongParentOrdering; }
109  if ( m_parent.at( node ) < -1 ) { return ConsistencyStatus::WrongParentIndex; }
110 
111  for ( const auto& child : m_child.at( node ) ) {
112  if ( m_parent.at( child ) != int( node ) ) {
113  return ConsistencyStatus::InconsistentParentIndex;
114  }
115  }
116 
117  if ( isLeaf( node ) != ( m_child.at( node ).size() == 0 ) ) {
118  return ConsistencyStatus::NonLeafNodeWithoutChild;
119  }
120  }
121  return ConsistencyStatus::Valid;
122 }
123 
124 std::ofstream& operator<<( std::ofstream& ofs, const AdjacencyList& adj ) {
125  const std::string header { "ADJACENCYLIST\n" };
126  const std::string comment { "#ID PARENT nCHILDREN CHILDREN\n" };
127  const uint size = adj.size();
128 
129  ofs << header + comment + std::to_string( size ) + "\n";
130  for ( uint i = 0; i < size; ++i ) {
131  uint c;
132  ofs << std::to_string( i ) + " " + std::to_string( adj.parents()[i] ) + " " +
133  std::to_string( c = adj.children()[i].size() );
134  for ( uint j = 0; j < c; ++j ) {
135  ofs << " " + std::to_string( adj.children()[i][j] );
136  }
137  ofs << "\n";
138  }
139  return ofs;
140 }
141 
142 } // namespace Core
143 } // namespace Ra
AdjacencyList()
CONSTRUCTOR.
ConsistencyStatus computeConsistencyStatus() const
Return true if the graph is consistent.
uint size() const
Return the number of nodes in the graph.
void pruneLeaves()
Prune the leaves of the graph.
uint addRoot()
Return the index of the added root.
bool isLeaf(const uint i) const
Return true if the node is a leaf node.
bool isRoot(const uint i) const
Return true if a node is a root node.
VectorArray< Eigen::Matrix< uint, 2, 1 > > extractEdgeList(bool include_leaf=false) const
uint addNode(const uint parent)
Return the index of the added leaf.
This class implements ContainerIntrospectionInterface for AlignedStdVector.
Definition: VectorArray.hpp:35
Definition: Cage.cpp:3