All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MinimumSpanningTree.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/sa/core/MinimumSpanningTree.cpp
22 
23  \brief This file contains a class that represents the Minimum Spanning Tree operation.
24 
25  \reference Boost BGL.
26 */
27 
28 //TerraLib
29 #include "../../datatype/SimpleData.h"
30 #include "../../graph/core/AbstractGraph.h"
31 #include "../../graph/core/AbstractGraphFactory.h"
32 #include "../../graph/core/Edge.h"
33 #include "../../graph/core/GraphMetadata.h"
34 #include "../../graph/core/Vertex.h"
35 #include "../../graph/iterator/MemoryIterator.h"
36 #include "../../graph/Globals.h"
37 #include "MinimumSpanningTree.h"
38 #include "Utils.h"
39 
40 //STL
41 #include <cassert>
42 
43 //Boost
44 #include <boost/graph/adjacency_list.hpp>
45 #include <boost/graph/kruskal_min_spanning_tree.hpp>
46 
48 {
49 }
50 
52 {
53 }
54 
56 {
57  //create iterator
58  te::graph::MemoryIterator* iterator = new te::graph::MemoryIterator(m_inputGraph);
59 
60  std::size_t nEdge = iterator->getEdgeInteratorCount();
61  std::size_t nVertex = iterator->getVertexInteratorCount();
62 
63  //create boost graph
64  typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property<boost::edge_weight_t, int > > boostGraph;
65 
66  typedef std::pair < int, int > boostEdge;
67 
68  std::vector<boostEdge> edge_vec;
69 
70  std::vector<double> weight_vec;
71 
72  te::graph::Edge* edge = iterator->getFirstEdge();
73 
74  while(edge)
75  {
76  edge_vec.push_back(boostEdge(edge->getIdFrom(), edge->getIdTo()));
77 
78  weight_vec.push_back(te::sa::GetDataValue(edge->getAttributes()[weightAttrIdx]));
79 
80  edge = iterator->getNextEdge();
81  }
82 
83  boostGraph graph(nVertex);
84 
85  boost::property_map<boostGraph, boost::edge_weight_t>::type weightmap = boost::get(boost::edge_weight, graph);
86 
87  for(std::size_t t = 0; t < nEdge; ++t)
88  {
89  boost::graph_traits<boostGraph>::edge_descriptor e;
90 
91  bool inserted;
92 
93  boost::tie(e, inserted) = boost::add_edge(edge_vec[t].first, edge_vec[t].second, graph);
94 
95  weightmap[e] = (int)weight_vec[t];
96  }
97 
98  //run kruskal algorithm
99  typedef boost::graph_traits<boostGraph>::edge_descriptor Edge;
100  typedef boost::graph_traits<boostGraph>::vertex_descriptor Vertex;
101 
102  boost::property_map<boostGraph, boost::edge_weight_t>::type weight = boost::get(boost::edge_weight, graph);
103 
104  std::vector<Edge> spanning_tree;
105 
106  kruskal_minimum_spanning_tree(graph, std::back_inserter(spanning_tree));
107 
108  //create output graph
109  te::graph::AbstractGraph* graphOut = createGraph();
110 
111  //create edge weight property
113  int size = graphOut->getMetadata()->getEdgePropertySize();
114 
115  //copy the minimum spanning tree graph
116  for(std::size_t t = 0; t < spanning_tree.size(); ++t)
117  {
118  Edge eCur = spanning_tree[t];
119 
120  int vertexSourceId = boost::source(eCur, graph);
121  int vertexTargetId = boost::target(eCur, graph);
122 
123  double weightEdge = weight[eCur];
124 
125  //check if output graph already has the input vertex
126  te::graph::Vertex* vFrom = graphOut->getVertex(vertexSourceId);
127 
128  if(!vFrom)
129  {
130  vFrom = new te::graph::Vertex(m_inputGraph->getVertex(vertexSourceId));
131 
132  vFrom->getNeighborhood().clear();
133  vFrom->getPredecessors().clear();
134  vFrom->getSuccessors().clear();
135 
136  graphOut->add(vFrom);
137  }
138 
139  //check if output graph already has the output vertex
140  te::graph::Vertex* vTo = graphOut->getVertex(vertexTargetId);
141 
142  if(!vTo)
143  {
144  vTo = new te::graph::Vertex(m_inputGraph->getVertex(vertexTargetId));
145 
146  vTo->getNeighborhood().clear();
147  vTo->getPredecessors().clear();
148  vTo->getSuccessors().clear();
149 
150  graphOut->add(vTo);
151  }
152 
153  //create edge
154  te::graph::Edge* e = new te::graph::Edge((int)t, vertexSourceId, vertexTargetId);
155 
156  e->setAttributeVecSize(size);
157  e->addAttribute(edgeWeightIdx, new te::dt::SimpleData<double, te::dt::DOUBLE_TYPE>(weightEdge));
158 
159  graphOut->add(e);
160  }
161 
162  return graphOut;
163 }
164 
166 {
167 // graph type
169 
170 // connection info
171  std::map<std::string, std::string> connInfo;
172 
173 // graph information
174  std::map<std::string, std::string> graphInfo;
175  graphInfo["GRAPH_DATA_SOURCE_TYPE"] = "MEM";
176  graphInfo["GRAPH_NAME"] = "mst_graph";
177  graphInfo["GRAPH_DESCRIPTION"] = "Generated by Minimum Spanning Tree.";
178 
179  //create output graph
180  te::graph::AbstractGraph* graph = te::graph::AbstractGraphFactory::make(graphType, connInfo, graphInfo);
181 
182  //copy vertex properties from gpm graph
183  for(int i = 0; i < m_inputGraph->getMetadata()->getVertexPropertySize(); ++i)
184  {
185  te::dt::Property* p = m_inputGraph->getMetadata()->getVertexProperty(i)->clone();
186 
187  p->setParent(0);
188 
189  graph->getMetadata()->addVertexProperty(p);
190  }
191 
192  return graph;
193 }
virtual te::graph::Edge * getNextEdge()
It returns a pointer to the next edge element of a graph.
void setAttributeVecSize(int size)
This function is used to set the number of attributes associated with the edge elements.
Definition: Edge.cpp:86
~MinimumSpanningTree()
Virtual destructor.
te::graph::AbstractGraph * kruskal(int weightAttrIdx)
Function to execute the kruskal operation.
te::graph::AbstractGraph * createGraph()
Function to create a empty graph with vertex attributes from gpm graph.
std::set< int > & getPredecessors()
Returns the Predecessors vector.
Definition: Vertex.cpp:101
virtual void addVertexProperty(te::dt::Property *p)
Add a new property associated to the vertex element.
virtual Property * clone() const =0
It returns a clone of the object.
static const std::string sm_factoryGraphTypeUndirectedGraph
Undirected Graph Factory Name.
Definition: Globals.h:55
Utilitary function for spatial analysis module.
virtual void add(Vertex *v)=0
Add a new vertex element to a graph.
It models a property definition.
Definition: Property.h:59
This file contains a class that represents the Minimum Spanning Tree operation.
From the point of view of graph theory, vertices are treated as featureless and indivisible objects...
Definition: Vertex.h:68
virtual te::graph::GraphMetadata * getMetadata()=0
Function used to access the graph metadata.
Class used to define the edge struct of a graph. Its compose with a identifier, the vertex origin and...
Definition: Edge.h:58
Abstract class used to define the main functions of graph struct. All graph implementations must used...
Definition: AbstractGraph.h:55
std::set< int > & getSuccessors()
Returns the Successors vector.
Definition: Vertex.cpp:106
int getIdFrom()
It returns the vertex origin identification.
Definition: Edge.cpp:71
std::set< int > & getNeighborhood()
Returns the Neighborhood vector.
Definition: Vertex.cpp:111
virtual te::graph::Edge * getFirstEdge()
It returns a pointer to the first edge element of a graph.
virtual size_t getEdgeInteratorCount()
It returns the number of elements of this iterator.
#define TE_SA_SKATER_ATTR_WEIGHT_NAME
Definition: Config.h:101
virtual int getEdgePropertySize()
Used to verify the number of properties associated to edge elements.
virtual size_t getVertexInteratorCount()
It returns the number of elements of this iterator.
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
TESAEXPORT int AddGraphEdgeAttribute(te::graph::AbstractGraph *graph, std::string attrName, int dataType)
Function used to create the edge attribute metadata in the graph of the gpm.
Definition: Utils.cpp:142
TESAEXPORT double GetDataValue(te::dt::AbstractData *ad)
Function used to get the numeric value from a gpm property.
Definition: Utils.cpp:200
static AbstractGraph * make()
It creates and returns an empty graph with default graph type.
virtual te::graph::Vertex * getVertex(int id)=0
It returns the vertex element if it's exist.
void addAttribute(int idx, te::dt::AbstractData *ad)
Add a new attribute to this element.
Definition: Edge.cpp:91
std::vector< te::dt::AbstractData * > & getAttributes()
It returns the vector of attributes associated with this element.
Definition: Edge.cpp:81
MinimumSpanningTree(te::graph::AbstractGraph *inputGraph)
Default constructor.
int getIdTo()
It returns the vertex destiny identification.
Definition: Edge.cpp:76
void setParent(Property *p)
It associate this property to the informed parent.
Definition: Property.h:177