contrib/mul/mmn/mmn_graph_rep1.cxx
Go to the documentation of this file.
00001 #include "mmn_graph_rep1.h"
00002 //:
00003 // \file
00004 // \brief Representation of a graph, stored by links at each node.
00005 // \author Tim Cootes
00006 
00007 #include <vcl_cassert.h>
00008 
00009 //: Default constructor
00010 mmn_graph_rep1::mmn_graph_rep1()
00011   : max_n_arcs_(0), n_arcs_(0)
00012 {
00013 }
00014 
00015 //: Build from list of arcs
00016 void mmn_graph_rep1::build(unsigned n_nodes,
00017                            const vcl_vector<mmn_arc>& arcs)
00018 {
00019   node_data_.resize(n_nodes);
00020   for (unsigned i=0;i<n_nodes;++i) node_data_[i].resize(0);
00021 
00022   for (unsigned i=0;i<arcs.size();++i)
00023   {
00024     node_data_[arcs[i].v1].push_back(vcl_pair<unsigned,unsigned>(arcs[i].v2,i));
00025     node_data_[arcs[i].v2].push_back(vcl_pair<unsigned,unsigned>(arcs[i].v1,i));
00026   }
00027 
00028   max_n_arcs_ = arcs.size();
00029   n_arcs_ = arcs.size();
00030 
00031   // root node not chosen, so allow automatic selection
00032   root_index_ = n_nodes+1;
00033 }
00034 
00035 //: Return index of arc between v1 and v2, or -1 if none
00036 int mmn_graph_rep1::arc_index(unsigned v1, unsigned v2) const
00037 {
00038   const vcl_vector<vcl_pair<unsigned,unsigned> >& nd = node_data_[v1];
00039   for (unsigned i=0;i<nd.size();++i)
00040     if (nd[i].first==v2) return nd[i].second;
00041   return -1;
00042 }
00043 
00044 //: Return index of arc between v1 and v2, creating one if none exists
00045 unsigned mmn_graph_rep1::get_arc(unsigned v1, unsigned v2)
00046 {
00047   int a = arc_index(v1,v2);
00048   if (a>=0) return a;
00049 
00050   // No existing arc, so add one.
00051   a = max_n_arcs_;
00052   node_data_[v1].push_back(vcl_pair<unsigned,unsigned>(v2,a));
00053   node_data_[v2].push_back(vcl_pair<unsigned,unsigned>(v1,a));
00054   max_n_arcs_++;
00055   n_arcs_++;
00056   return a;
00057 }
00058 
00059 #if 0
00060 //: Remove record of arc between v1 and v2
00061 //  Returns false if there isn't one.
00062 bool mmn_graph_rep1::remove_arc(unsigned v1, unsigned v2)
00063 {
00064 }
00065 #endif // 0
00066 
00067 //: Remove record of arc v1-v2 from v1
00068 void mmn_graph_rep1::remove_arc_from_node(unsigned v1, unsigned v2)
00069 {
00070   vcl_vector<vcl_pair<unsigned,unsigned> >& nd = node_data_[v1];
00071   vcl_vector<vcl_pair<unsigned,unsigned> >::iterator ndi;
00072   for (ndi=nd.begin();ndi!=nd.end();++ndi)
00073     if (ndi->first==v2)
00074     {
00075       nd.erase(ndi);
00076       break;
00077     }
00078 }
00079 
00080 
00081 //: Remove some of leaves of graph, recording dependencies
00082 //  A leaf node is one with only one arc
00083 //  For each leaf node removed, add one dependency object to
00084 //  the deps list.
00085 //  Returns number of leaves removed.
00086 unsigned mmn_graph_rep1::remove_leaves(vcl_vector<mmn_dependancy>& deps)
00087 {
00088   unsigned n_removed = 0;
00089   for (unsigned v1=0;v1<node_data_.size();++v1)
00090   {
00091     if (v1==root_index_) continue;  // Don't remove the root
00092 
00093     if (node_data_[v1].size()==1)
00094     {
00095       // v1 is a leaf node, connected to node_data_[v1][0].first
00096       unsigned v2 = node_data_[v1][0].first;
00097       unsigned arc12 = node_data_[v1][0].second;
00098 
00099       // Record dependency
00100       deps.push_back(mmn_dependancy(v1,v2,arc12));
00101       n_removed++;
00102 
00103       // Remove the record of the arc from v1
00104       node_data_[v1].resize(0);
00105       // Remove the record of the arc from v2
00106       remove_arc_from_node(v2,v1);
00107 
00108       n_arcs_--;
00109       if (n_arcs_==0) break;
00110     }
00111   }
00112 
00113   return n_removed;
00114 }
00115 
00116 //: Remove all of leaves of graph, recording dependencies
00117 //  A leaf node is one with only one arc
00118 //  For each leaf node removed, add one dependency object to
00119 //  the deps list.  On exit, this graph has no leaves.
00120 //  Returns number of leaves removed.
00121 unsigned mmn_graph_rep1::remove_all_leaves(vcl_vector<mmn_dependancy>& deps)
00122 {
00123   unsigned n_removed=0;
00124   unsigned nr=0;
00125   do
00126   {
00127     nr=remove_leaves(deps);
00128     n_removed+=nr;
00129   } while (nr!=0);
00130 
00131   return n_removed;
00132 }
00133 
00134 //: Remove arcs from some of the nodes with two neighbours
00135 //  Record the pairwise dependencies.
00136 //  For each node removed, add one dependency object to
00137 //  the deps list.
00138 //  Returns number of removed.
00139 unsigned mmn_graph_rep1::remove_pair_deps(vcl_vector<mmn_dependancy>& deps)
00140 {
00141   unsigned n_removed = 0;
00142   for (unsigned v0=0;v0<node_data_.size();++v0)
00143   {
00144     if (v0==root_index_) continue;  // Don't remove the root
00145 
00146     if (node_data_[v0].size()==2)
00147     {
00148       // v0 has two neighbours,
00149       // node_data_[v0][0].first and node_data_[v0][1].first
00150       unsigned v1 = node_data_[v0][0].first;
00151       unsigned arc1 = node_data_[v0][0].second;
00152       unsigned v2 = node_data_[v0][1].first;
00153       unsigned arc2 = node_data_[v0][1].second;
00154 
00155       // Find arc between v1-v2, or create one if necessary
00156       unsigned arc12 = get_arc(v1,v2);
00157 
00158       // Record dependency
00159       // If one of v1,v2 is root_index, then re-arrange so that it is v1
00160       if (v2==root_index_)
00161         deps.push_back(mmn_dependancy(v0,v2,v1,arc2,arc1,arc12));
00162       else
00163         deps.push_back(mmn_dependancy(v0,v1,v2,arc1,arc2,arc12));
00164       n_removed++;
00165 
00166       // Remove the record of the arcs from v0
00167       node_data_[v0].resize(0);
00168       // Remove the record of the arc from v1
00169       remove_arc_from_node(v1,v0);
00170       // Remove the record of the arc from v2
00171       remove_arc_from_node(v2,v0);
00172 
00173       n_arcs_-=2;
00174       if (n_arcs_<2) break;
00175     }
00176   }
00177 
00178   return n_removed;
00179 }
00180 
00181 //: Compute list of all single and pairwise dependencies
00182 //  Return true if graph can be fully decomposed in this way
00183 bool mmn_graph_rep1::compute_dependancies(vcl_vector<mmn_dependancy>& deps, unsigned root_index)
00184 {
00185   assert(root_index<node_data_.size());
00186 
00187   root_index_=root_index;
00188 
00189   deps.resize(0);
00190   unsigned nr1=0;
00191   do
00192   {
00193     nr1=remove_all_leaves(deps);
00194     if (n_arcs_>1)
00195       nr1+=remove_pair_deps(deps);
00196   }
00197   while (nr1>0 && n_arcs_>0);
00198 
00199   return n_arcs_==0;
00200 }
00201 
00202 //: Compute list of all single and pairwise dependencies
00203 //  Return true if graph can be fully decomposed in this way
00204 bool mmn_graph_rep1::compute_dependancies(vcl_vector<mmn_dependancy>& deps)
00205 {
00206   // Indicate that root index is undefined.
00207   root_index_=node_data_.size()+1;
00208 
00209   deps.resize(0);
00210   unsigned nr1=0;
00211   do
00212   {
00213     nr1=remove_all_leaves(deps);
00214     if (n_arcs_>1)
00215       nr1+=remove_pair_deps(deps);
00216   }
00217   while (nr1>0 && n_arcs_>0);
00218 
00219   return n_arcs_==0;
00220 }
00221