SCL  1.0
Standard Control Library : Control, dynamics, physics, and simulation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Groups Pages
CMappedDirGraph.hpp
1 /* This file is part of sUtil, a random collection of utilities.
2 
3 sUtil is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License as published by the Free Software Foundation; either
6 version 3 of the License, or (at your option) any later version.
7 
8 Alternatively, you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
12 
13 sUtil is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public
19 License and a copy of the GNU General Public License along with
20 sUtil. If not, see <http://www.gnu.org/licenses/>.
21  */
22 /* \file CMappedDirGraph.hpp
23  *
24  * Created on: Jul 7, 2014
25  *
26  * Copyright (C) 2014, Samir Menon <smenon@stanford.edu>
27  */
28 
29 #ifndef CMAPPEDDIRGRAPH_HPP_
30 #define CMAPPEDDIRGRAPH_HPP_
31 
32 #include <sutil/CMappedTree.hpp>
33 #include <limits>
34 
35 #ifdef DEBUG
36 #include <iostream>
37 #include <cassert>
38 #endif
39 
40 namespace sutil
41 {
67  template <typename TIdx, typename TNode>
68  class CMappedDirGraph : public sutil::CMappedTree<TIdx,TNode>
69  {
70  public:
73  std::vector<std::pair<TNode*, TNode*> > st_broken_edges_;
74 
76  struct SMGNodeBase;
77 
78  CMappedDirGraph() : CMappedTree<TIdx,TNode>::CMappedTree() { st_broken_edges_.clear(); }
79  virtual ~CMappedDirGraph() { }
80 
82  virtual bool linkNodes();
83 
85  virtual bool genSpanningTree();
86  }; //End of template class
87 
89  template <typename TIdx, typename TNode>
90  struct CMappedDirGraph<TIdx,TNode>::SMGNodeBase : public CMappedTree<TIdx,TNode>::SMTNodeBase
91  {
92  public:
94  std::vector<TIdx> gr_parent_names_;
96  std::vector<TNode*> gr_parent_addrs_;
98  std::vector<TNode*> gr_child_addrs_;
99 
102  {
103  gr_parent_names_.clear();
104  gr_parent_addrs_.clear();
105  gr_child_addrs_.clear();
106  }
107  };
108 
109  /***************************************************************
110  *******************************Function Definitions*************
111  ****************************************************************
112  */
118  template <typename TIdx, typename TNode>
120  {
121  //Clear previous links (if any)
122  typename CMappedList<TIdx,TNode>::iterator it,ite;
125  it != ite; ++it)
126  {
127  TNode& tmp_node = *it;
128 
129  //Clear the graph
130  tmp_node.gr_parent_addrs_.clear();
131  tmp_node.gr_child_addrs_.clear();
132  }
133 
134  //Form the new links for the graph
136  it != ite; ++it)
137  {
138  TNode& tmp_node = *it;
139  //Iterate over all nodes and connect them to their
140  //parents
141  if(&tmp_node == CMappedTree<TIdx,TNode>::root_node_)
142  {//No parents
143  continue;
144  }
145  else
146  {
147  typename std::vector<TIdx>::iterator itp,itpe; //Each TIdx corresponds to an entry in : std::vector<TNode*> parent_addrs_;
148  for(itp = tmp_node.gr_parent_names_.begin(), itpe = tmp_node.gr_parent_names_.end();
149  itp!=itpe;++itp)
150  {
151  TNode * tmp_node2add = sutil::CMappedList<TIdx,TNode>::at(*itp);
152  if(tmp_node2add == NULL)
153  {//No parent -- Ignore this node
154 #ifdef DEBUG
155  std::cerr<<"\nCBranchingStructure::linkNodes(): Warning.";
156  std::cerr<<"Orphan node found: "<<*itp<<". Ignoring.";
157 #endif
158  continue;
159  }
160  //Link the node
161  tmp_node.gr_parent_addrs_.push_back(tmp_node2add);
162  tmp_node2add->child_addrs_.push_back(&tmp_node);
163 
164 #ifdef DEBUG
165  std::cerr<<"\n\tAdding child "<<tmp_node.name_
166  <<" to (parent) "<<tmp_node2add->name_;
167  std::cerr<<std::flush;
168 #endif
169  }
170  }
171  }//End of while loop
172 
173  //Now set up the spanning tree and affirm initialization is complete.
174  bool flag = genSpanningTree();
175  CMappedTree<TIdx,TNode>::has_been_init_ = false; //Not done yet.
176 
177  //Now compute the broken edges.
178  st_broken_edges_.clear();
180  it != ite; ++it)
181  {
182  TNode &tmp_node = *it;
183  typename std::vector<TIdx>::iterator itp,itpe; //Each TIdx corresponds to an entry in : std::vector<TNode*> parent_addrs_;
184  for(itp = tmp_node.gr_parent_names_.begin(), itpe = tmp_node.gr_parent_names_.end();
185  itp!=itpe;++itp)
186  {
187  TIdx &pidx = *itp;
188  TNode* test_parent = CMappedList<TIdx,TNode>::at(pidx);
189  if(test_parent != tmp_node.parent_addr_)
190  {//Found a parent who is disconnected in the spanning tree
191  std::pair<TNode*, TNode*> tmp_broken_edge;
192  tmp_broken_edge.first = test_parent;
193  tmp_broken_edge.second = &tmp_node;
194  st_broken_edges_.push_back(tmp_broken_edge);
195  }
196  }
197  }
198 
199  CMappedTree<TIdx,TNode>::has_been_init_ = true; //Finally done.
200 
201  //Return the end result
203  }
204 
209  template <typename TIdx, typename TNode>
211  {
212  // Must have a root node to be able to create the spanning tree.
213  // NOTE TODO : Potentially eliminate this requirement and pick a suitable root node.
214  TNode* root = CMappedTree<TIdx,TNode>::getRootNode();
215  if(NULL == root)
216  { return false; }
217 
218  int graph_sz = CMappedList<TIdx,TNode>::size();
219 
220  struct SSTreeStruct{ bool in_stree_; TNode* node_; };
221  SSTreeStruct *in_stree = new SSTreeStruct[graph_sz];
222 
223  //First populate the node pointers (create a temp data struct to store stuff).
224  typename CMappedTree<TIdx,TNode>::iterator it,ite;
225  int i=0;
226  for(it = CMappedTree<TIdx,TNode>::begin(), ite = CMappedTree<TIdx,TNode>::end(); it!=ite; ++it)
227  {
228  //Get the node's numeric index in the underlying mapped list.
230  //Set values at corresponding position in the data struct array
231  in_stree[i].node_ = &(*it);
232  if(CMappedTree<TIdx,TNode>::getRootNodeConst() == in_stree[i].node_)
233  { in_stree[i].in_stree_ = true; }
234  else
235  { in_stree[i].in_stree_ = false; }
236  }
237 
238  //Now compute the spanning tree.
239  bool complete = false;
240  int nodes_in_stree_pre = 1, nodes_in_stree_curr = 1;//Only root so far.
241  while(false == complete)
242  {
243  //Update distances from the spanning tree for each node
244  for(int i=0; i<graph_sz; ++i)
245  {
246  if(in_stree[i].in_stree_){ continue; } //I'm already in.
247 
248  // Else try to find a parent for me.
249  typename std::vector<TIdx>::iterator itp, itpe;
250  for(itp = in_stree[i].node_->gr_parent_names_.begin(),itpe = in_stree[i].node_->gr_parent_names_.end();
251  itp!=itpe;++itp)
252  {
253  TIdx &pidx = *itp;
254  int pnidx = CMappedList<TIdx,TNode>::getIndexNumericAt(pidx); //numeric parent index
255 #ifdef DEBUG
256  assert(-1 != pnidx);
257 #endif
258  if(in_stree[pnidx].in_stree_)
259  {//Parent is in the spanning tree. Then add me as a child and forget about other parents.
260  in_stree[i].node_->parent_name_ = in_stree[pnidx].node_->name_;
261  in_stree[i].in_stree_ = true;
262  nodes_in_stree_curr++;
263  break;
264  }
265  }
266  }
267 
268  // Check if all nodes have been added to the spanning tree.
269  complete = true;
270  for(int i=0; complete && i<graph_sz; ++i)
271  { complete = (complete && in_stree[i].in_stree_); }
272 
273  if(false == complete && nodes_in_stree_curr == nodes_in_stree_pre)
274  { return false; }//Could not add any node this time. And not complete. Algo is stuck.
275  else
276  { nodes_in_stree_pre = nodes_in_stree_curr; }
277  }
278 
279  //Start at the root node (which has, presumably, been set)
281  }
282 
283 }//End of namespace sutil
284 
285 #endif /*CMAPPEDDIRGRAPH_HPP_*/
Definition: CMappedTree.hpp:155
virtual bool clear()
Definition: CMappedList.hpp:1127
Definition: CMappedList.hpp:85
virtual bool genSpanningTree()
Definition: CMappedDirGraph.hpp:210
std::vector< TIdx > gr_parent_names_
Definition: CMappedDirGraph.hpp:94
virtual bool linkNodes()
Definition: CMappedTree.hpp:316
virtual T * at(const std::size_t arg_idx)
Definition: CMappedList.hpp:832
std::vector< TNode * > gr_child_addrs_
Definition: CMappedDirGraph.hpp:98
Definition: CMappedDirGraph.hpp:90
std::vector< std::pair< TNode *, TNode * > > st_broken_edges_
Definition: CMappedDirGraph.hpp:73
Definition: CMappedDirGraph.hpp:68
Definition: CMappedTree.hpp:66
std::vector< TNode * > gr_parent_addrs_
Definition: CMappedDirGraph.hpp:96
virtual TNode * getRootNode()
Definition: CMappedTree.hpp:132
virtual bool linkNodes()
Definition: CMappedDirGraph.hpp:119
virtual std::size_t size() const
Definition: CMappedList.hpp:240
virtual int getIndexNumericAt(const Idx &arg_idx) const
Definition: CMappedList.hpp:910
SMGNodeBase()
Definition: CMappedDirGraph.hpp:101