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 
54 {
55  //create iterator
57 
58  std::size_t nEdge = iterator->getEdgeInteratorCount();
59  std::size_t nVertex = iterator->getVertexInteratorCount();
60 
61  //create boost graph
62  typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property<boost::edge_weight_t, int > > boostGraph;
63 
64  typedef std::pair < int, int > boostEdge;
65 
66  std::vector<boostEdge> edge_vec;
67 
68  std::vector<double> weight_vec;
69 
70  te::graph::Edge* edge = iterator->getFirstEdge();
71 
72  while(edge)
73  {
74  edge_vec.push_back(boostEdge(edge->getIdFrom(), edge->getIdTo()));
75 
76  weight_vec.push_back(te::sa::GetDataValue(edge->getAttributes()[weightAttrIdx]));
77 
78  edge = iterator->getNextEdge();
79  }
80 
81  boostGraph graph(nVertex);
82 
83  boost::property_map<boostGraph, boost::edge_weight_t>::type weightmap = boost::get(boost::edge_weight, graph);
84 
85  for(std::size_t t = 0; t < nEdge; ++t)
86  {
87  boost::graph_traits<boostGraph>::edge_descriptor e;
88 
89  bool inserted;
90 
91  boost::tie(e, inserted) = boost::add_edge(edge_vec[t].first, edge_vec[t].second, graph);
92 
93  weightmap[e] = (int)weight_vec[t];
94  }
95 
96  //run kruskal algorithm
97  typedef boost::graph_traits<boostGraph>::edge_descriptor Edge;
98 
99  boost::property_map<boostGraph, boost::edge_weight_t>::type weight = boost::get(boost::edge_weight, graph);
100 
101  std::vector<Edge> spanning_tree;
102 
103  kruskal_minimum_spanning_tree(graph, std::back_inserter(spanning_tree));
104 
105  //create output graph
107 
108  //create edge weight property
110  int size = graphOut->getMetadata()->getEdgePropertySize();
111 
112  //copy the minimum spanning tree graph
113  for(std::size_t t = 0; t < spanning_tree.size(); ++t)
114  {
115  Edge eCur = spanning_tree[t];
116 
117  int vertexSourceId = static_cast<int>(boost::source(eCur, graph));
118  int vertexTargetId = static_cast<int>(boost::target(eCur, graph));
119 
120  double weightEdge = weight[eCur];
121 
122  //check if output graph already has the input vertex
123  te::graph::Vertex* vFrom = graphOut->getVertex(vertexSourceId);
124 
125  if(!vFrom)
126  {
127  vFrom = new te::graph::Vertex(m_inputGraph->getVertex(vertexSourceId));
128 
129  vFrom->getNeighborhood().clear();
130  vFrom->getPredecessors().clear();
131  vFrom->getSuccessors().clear();
132 
133  graphOut->add(vFrom);
134  }
135 
136  //check if output graph already has the output vertex
137  te::graph::Vertex* vTo = graphOut->getVertex(vertexTargetId);
138 
139  if(!vTo)
140  {
141  vTo = new te::graph::Vertex(m_inputGraph->getVertex(vertexTargetId));
142 
143  vTo->getNeighborhood().clear();
144  vTo->getPredecessors().clear();
145  vTo->getSuccessors().clear();
146 
147  graphOut->add(vTo);
148  }
149 
150  //create edge
151  te::graph::Edge* e = new te::graph::Edge((int)t, vertexSourceId, vertexTargetId);
152 
153  e->setAttributeVecSize(size);
154  e->addAttribute(edgeWeightIdx, new te::dt::SimpleData<double, te::dt::DOUBLE_TYPE>(weightEdge));
155 
156  graphOut->add(e);
157  }
158 
159  return graphOut;
160 }
161 
163 {
164 // graph type
166 
167 // connection info
168  const std::string connInfo("memory:");
169 
170 // graph information
171  std::map<std::string, std::string> graphInfo;
172  graphInfo["GRAPH_DATA_SOURCE_TYPE"] = "MEM";
173  graphInfo["GRAPH_NAME"] = "mst_graph";
174  graphInfo["GRAPH_DESCRIPTION"] = "Generated by Minimum Spanning Tree.";
175 
176  //create output graph
177  te::graph::AbstractGraph* graph = te::graph::AbstractGraphFactory::make(graphType, connInfo, graphInfo);
178 
179  //copy vertex properties from gpm graph
180  for(int i = 0; i < m_inputGraph->getMetadata()->getVertexPropertySize(); ++i)
181  {
183 
184  p->setParent(nullptr);
185 
186  graph->getMetadata()->addVertexProperty(p);
187  }
188 
189  return graph;
190 }
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.
virtual te::dt::Property * getVertexProperty(int idx)
Get a vertex property given a index.
Utilitary function for spatial analysis module.
virtual int getVertexPropertySize()
Used to verify the number of properties associated to vertex elements.
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.
#define TE_SA_SKATER_ATTR_WEIGHT_NAME
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.
static const std::string sm_factoryGraphTypeUndirectedGraph
Undirected Graph Factory Name.
virtual Property * clone() const =0
It returns a clone of the object.
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
te::gm::Polygon * p
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.
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.
TESAEXPORT double GetDataValue(te::dt::AbstractData *ad)
Function used to get the numeric value from a gpm property.
te::graph::AbstractGraph * m_inputGraph
Pointer to input graph.
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&#39;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