![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raúl D. D. Farfan * 00004 * * 00005 * This program is free software: you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation, either version 3 of the License, or * 00008 * any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00017 ************************************************************************/ 00018 00019 #ifndef MECHSYS_TREE_H 00020 #define MECHSYS_TREE_H 00021 00022 // STL 00023 #include <stdlib.h> // for calloc 00024 #include <cstdio> 00025 00026 // iGraph 00027 extern "C" 00028 { 00029 #include <src/igraph.h> 00030 } 00031 00032 // MechSys 00033 #include <mechsys/util/array.h> 00034 #include <mechsys/util/fatal.h> 00035 #include <mechsys/util/numstreams.h> 00036 00037 00038 namespace Util 00039 { 00040 00041 class Tree 00042 { 00043 public: 00044 // Constructors 00045 Tree (Array<int> const & NodesPairs, bool Directed=false) : _directed(Directed) { _init_graph(NodesPairs,Directed); _init_path(); } 00046 00047 // Destructor 00048 ~Tree (); 00049 00050 // Set methods 00051 void Reset (Array<int> const & NodesPairs, bool Directed=false); 00052 void DelEdge (int LeftNodeID, int RightNodeID); 00053 00054 // Get methods 00055 size_t nEdges () const { return igraph_ecount (&_graph); } 00056 size_t GetEdge (int LeftNodeID, int RightNodeID) const; 00057 void GetNodes (size_t i, int & LeftNodeID, int & RightNodeID) const; 00058 void ShortPath (size_t FromNodeID, size_t ToNodeID, Array<int> & Path); 00059 00060 // Methods 00061 void GetClusters (Array< Array<int> > & Clusters, bool Strong=true) const; 00062 void WriteDOT (char const * FileKey) const; 00063 00064 // Operators 00065 void operator= (Tree const & Other); 00066 00067 private: 00068 // Data 00069 bool _directed; 00070 igraph_vector_t _edges; 00071 igraph_t _graph; 00072 igraph_vs_t _anode; 00073 igraph_es_t _epair; 00074 igraph_vector_ptr_t _path; 00075 00076 // Methods 00077 void _init_graph (Array<int> const & NodesPairs, bool Directed); 00078 void _init_path (); 00079 00080 }; // class Tree 00081 00082 00084 00085 00086 /* public */ 00087 00088 inline Tree::~Tree() 00089 { 00090 for (int i=0; i<igraph_vector_ptr_size(&_path); ++i) 00091 { 00092 igraph_vector_destroy (static_cast<igraph_vector_t*>(VECTOR(_path)[i])); 00093 free (VECTOR(_path)[i]); 00094 } 00095 igraph_vs_destroy (&_anode); 00096 igraph_es_destroy (&_epair); 00097 igraph_vector_ptr_destroy (&_path); 00098 igraph_vector_destroy (&_edges); 00099 igraph_destroy (&_graph); 00100 } 00101 00102 inline void Tree::Reset (Array<int> const & NodesPairs, bool Directed) 00103 { 00104 igraph_vector_destroy (&_edges); 00105 igraph_destroy (&_graph); 00106 _init_graph (NodesPairs, Directed); 00107 } 00108 00109 inline void Tree::DelEdge (int LeftNodeID, int RightNodeID) 00110 { 00111 igraph_es_pairs_small (&_epair, IGRAPH_DIRECTED, LeftNodeID, RightNodeID, /*flag*/-1); 00112 igraph_delete_edges (&_graph, _epair); 00113 } 00114 00115 inline void Tree::GetNodes (size_t i, int & LeftNodeID, int & RightNodeID) const 00116 { 00117 igraph_integer_t left; 00118 igraph_integer_t right; 00119 igraph_edge (&_graph, i, &left, &right); 00120 LeftNodeID = left; 00121 RightNodeID = right; 00122 } 00123 00124 inline size_t Tree::GetEdge (int LeftNodeID, int RightNodeID) const 00125 { 00126 igraph_integer_t eid; 00127 igraph_get_eid (&_graph, &eid, LeftNodeID, RightNodeID, /*directed*/1); 00128 return eid; 00129 } 00130 00131 inline void Tree::ShortPath (size_t FromNodeID, size_t ToNodeID, Array<int> & Path) 00132 { 00133 igraph_vs_vector_small (&_anode, ToNodeID, /*flag*/-1); 00134 igraph_get_shortest_paths (&_graph, &_path, FromNodeID, _anode, IGRAPH_ALL); 00135 size_t npaths = igraph_vector_ptr_size(&_path); 00136 if (npaths>1) throw new Fatal("Tree::ShortPath: There are (%d) more than one shortest path",npaths); 00137 size_t path_sz = igraph_vector_size(static_cast<igraph_vector_t*>(VECTOR(_path)[0])); 00138 Path.Resize(path_sz); 00139 for (size_t i=0; i<path_sz; ++i) 00140 Path[i] = VECTOR(*static_cast<igraph_vector_t*>(VECTOR(_path)[0]))[i]; 00141 } 00142 00143 inline void Tree::GetClusters (Array< Array<int> > & Clusters, bool Strong) const 00144 { 00145 igraph_vector_t membership, csize; 00146 igraph_vector_init (&membership, 0); 00147 igraph_vector_init (&csize, 0); 00148 igraph_integer_t no; 00149 if (_directed && Strong) igraph_clusters (&_graph, &membership, &csize, &no, IGRAPH_STRONG); 00150 else igraph_clusters (&_graph, &membership, &csize, &no, IGRAPH_WEAK); 00151 00152 Clusters.Resize (no); 00153 int sz = igraph_vector_size(&membership); 00154 for (int i=0; i<sz; ++i) 00155 { 00156 int cluster_id = VECTOR(membership)[i]; 00157 Clusters[cluster_id].Push (i); 00158 } 00159 00160 //std::cout << "no = " << no << std::endl; 00161 //std::cout << "sz = " << sz << std::endl; 00162 } 00163 00164 inline void Tree::WriteDOT (char const * FileKey) const 00165 { 00166 String fkey(FileKey); 00167 fkey.append(".dot"); 00168 FILE * file = fopen(fkey.CStr(),"w"); 00169 if (file!=NULL) 00170 { 00171 igraph_write_graph_dot (&_graph, file); 00172 //igraph_write_graph_graphml (&_graph, file); 00173 fclose(file); 00174 } 00175 else throw new Fatal("Tree::WriteDOT: Could not open file <%s>",fkey.CStr()); 00176 } 00177 00178 // Operators 00179 00180 inline void Tree::operator= (Tree const & Other) 00181 { 00182 Array<int> nodes_pairs; 00183 nodes_pairs.Resize(Other.nEdges()*2); 00184 size_t k = 0; 00185 for (size_t i=0; i<Other.nEdges(); ++i) 00186 { 00187 int lef, rig; 00188 Other.GetNodes (i, lef, rig); 00189 nodes_pairs[k ] = lef; 00190 nodes_pairs[k+1] = rig; 00191 k += 2; 00192 } 00193 Reset (nodes_pairs); 00194 } 00195 00196 00197 /* private */ 00198 00199 inline void Tree::_init_graph (Array<int> const & NodesPairs, bool Directed) 00200 { 00201 igraph_vector_init (&_edges, NodesPairs.Size()); 00202 for (size_t i=0; i<NodesPairs.Size(); ++i) 00203 VECTOR(_edges)[i] = NodesPairs[i]; 00204 igraph_create (&_graph, &_edges, /*nVerts=auto*/0, /*Directed*/Directed); 00205 } 00206 00207 inline void Tree::_init_path () 00208 { 00209 igraph_vector_ptr_init (&_path, 1); 00210 for (int i=0; i<igraph_vector_ptr_size(&_path); ++i) 00211 { 00212 VECTOR(_path)[i] = calloc (1, sizeof(igraph_vector_t)); 00213 igraph_vector_init (static_cast<igraph_vector_t*>(VECTOR(_path)[i]), 0); 00214 } 00215 } 00216 00217 00218 /* Output */ 00219 00220 std::ostream & operator<< (std::ostream & os, Util::Tree const & T) 00221 { 00222 for (size_t i=0; i<T.nEdges(); ++i) 00223 { 00224 int lef, rig; 00225 T.GetNodes (i, lef, rig); 00226 os << i << ":(" << lef << ", " << rig << ") "; 00227 } 00228 return os; 00229 } 00230 00231 00232 }; // namespace Util 00233 00234 #endif // MECHSYS_TREE_H