SkaterOperation.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/SkaterOperation.cpp
22 
23  \brief This file contains a class that represents the skater operation.
24 
25  \reference Adapted from TerraLib4.
26 */
27 
28 //TerraLib
29 #include "../../dataaccess/datasource/DataSource.h"
30 #include "../../dataaccess/datasource/DataSourceManager.h"
31 #include "../../dataaccess/utils/Utils.h"
32 #include "../../datatype/SimpleProperty.h"
33 #include "../../datatype/SimpleData.h"
34 #include "../../graph/core/AbstractGraph.h"
35 #include "../../graph/core/AbstractGraphFactory.h"
36 #include "../../graph/core/Edge.h"
37 #include "../../graph/core/GraphMetadata.h"
38 #include "../../graph/core/Vertex.h"
39 #include "../../graph/iterator/MemoryIterator.h"
40 #include "../../graph/Globals.h"
41 #include "../../memory/DataSet.h"
42 #include "../../memory/DataSetItem.h"
44 #include "MinimumSpanningTree.h"
45 #include "SkaterOperation.h"
46 #include "SkaterPartition.h"
47 #include "Utils.h"
48 
49 //STL
50 #include <cassert>
51 #include <list>
52 #include <queue>
53 
55 
57 
59 {
60  assert(m_inputParams->m_ds.get());
61  assert(m_inputParams->m_dsType.get());
62 
63  //associate gpm vertex attributes
64  std::vector<int> attrsIdx;
65 
66  for(std::size_t t = 0; t < m_inputParams->m_attrs.size(); ++t)
67  {
68  std::string attrName = m_inputParams->m_attrs[t];
69 
70  std::size_t idx = m_inputParams->m_dsType->getPropertyPosition(attrName);
71  int type = m_inputParams->m_ds->getPropertyDataType(idx);
72  int gpmIdx = te::sa::AssociateGPMVertexAttribute(m_inputParams->m_gpm.get(), m_inputParams->m_ds.get(), m_inputParams->m_gpmAttrLink, attrName, type);
73 
74  attrsIdx.push_back(gpmIdx);
75  }
76 
77  //check if use population information
78  if(m_inputParams->m_attrPop != "")
79  {
80  std::size_t idx = m_inputParams->m_dsType->getPropertyPosition(m_inputParams->m_attrPop);
81 
82  int type = m_inputParams->m_ds->getPropertyDataType(idx);
83 
84  te::sa::AssociateGPMVertexAttribute(m_inputParams->m_gpm.get(), m_inputParams->m_ds.get(), m_inputParams->m_gpmAttrLink, m_inputParams->m_attrPop, type);
85  }
86 
87  //calculate gpm edge attribute
89 
90  createWeightAttribute(edgeWeightIdx, attrsIdx);
91 
92  //calculate the mst
93  te::sa::MinimumSpanningTree mst(m_inputParams->m_gpm->getGraph());
94 
95  te::graph::AbstractGraph* graph = mst.kruskal(edgeWeightIdx);
96 
97  //partition the graph
98  te::sa::SkaterPartition sp(graph, m_inputParams->m_attrs);
99 
100  std::vector<std::size_t> roots;
101 
102  if(m_inputParams->m_aggregType == te::sa::Both || m_inputParams->m_aggregType == te::sa::Clusters)
103  roots = sp.execute(m_inputParams->m_nClusters, m_inputParams->m_attrPop, m_inputParams->m_minPop);
104  else if(m_inputParams->m_aggregType == te::sa::Population)
105  roots = sp.execute(m_inputParams->m_attrPop, m_inputParams->m_minPop);
106 
107  m_nClassGroups = (int)roots.size();
108 
109  std::map<int, int> skaterMap = createSkaterMap(graph, roots);
110 
111  //create output information information
112  std::unique_ptr<te::da::DataSetType> outDsType = createDataSetType(m_inputParams->m_dsType.get());
113 
114  std::string gpmLink = m_inputParams->m_gpm->getAttributeName();
115 
116  std::unique_ptr<te::mem::DataSet> outDs = createDataSet(m_inputParams->m_ds.get(), outDsType.get(), skaterMap, gpmLink);
117 
118  //save data
119  saveDataSet(outDs.get(), outDsType.get());
120 
121  roots.clear();
122  skaterMap.clear();
123 
124  delete graph;
125 }
126 
128 {
129  m_inputParams.reset(inParams);
130  m_outputParams.reset(outParams);
131 }
132 
134 {
135  return m_nClassGroups;
136 }
137 
138 std::unique_ptr<te::da::DataSetType> te::sa::SkaterOperation::createDataSetType(te::da::DataSetType* dsType)
139 {
140  std::unique_ptr<te::da::DataSetType> dataSetType(new te::da::DataSetType(m_outputParams->m_outputDataSetName));
141 
142  //create all input dataset properties
143  std::vector<te::dt::Property*> propertyVec = dsType->getProperties();
144 
145  for(std::size_t t = 0; t < propertyVec.size(); ++t)
146  {
147  te::dt::Property* prop = propertyVec[t];
148 
149  te::dt::Property* newProp = prop->clone();
150  newProp->setId(0);
151  newProp->setParent(nullptr);
152 
153  dataSetType->add(newProp);
154  }
155 
156  //create skater class event property
158  dataSetType->add(skaterClass);
159 
160  return dataSetType;
161 }
162 
163 std::unique_ptr<te::mem::DataSet> te::sa::SkaterOperation::createDataSet(te::da::DataSet* inputDataSet, te::da::DataSetType* dsType, std::map<int, int>& skaterMap, std::string linkName)
164 {
165  std::unique_ptr<te::mem::DataSet> outDataset(new te::mem::DataSet(dsType));
166 
167  std::size_t nProp = inputDataSet->getNumProperties();
168 
169  inputDataSet->moveBeforeFirst();
170 
171  while(inputDataSet->moveNext())
172  {
173  //create dataset item
174  te::mem::DataSetItem* outDSetItem = new te::mem::DataSetItem(outDataset.get());
175 
176  std::string idStrValue = inputDataSet->getAsString(linkName);
177 
178  for(std::size_t t = 0; t < nProp; ++t)
179  {
180  te::dt::AbstractData* ad = inputDataSet->getValue(t).release();
181 
182  outDSetItem->setValue(t, ad);
183  }
184 
185  //set kernel default value
186  outDSetItem->setInt32(TE_SA_SKATER_ATTR_CLASS_NAME, skaterMap[atoi(idStrValue.c_str())]);
187 
188  //add item into dataset
189  outDataset->add(outDSetItem);
190  }
191 
192  return outDataset;
193 }
194 
196 {
197  //save dataset
198  dataSet->moveBeforeFirst();
199 
200  std::map<std::string, std::string> options;
201 
202  m_outputParams->m_dataSource->createDataSet(dsType, options);
203 
204  m_outputParams->m_dataSource->add(m_outputParams->m_outputDataSetName, dataSet, options);
205 }
206 
207 void te::sa::SkaterOperation::createWeightAttribute(int weightAttrIdx, std::vector<int> attrsIdx)
208 {
209  te::graph::AbstractGraph* graph = m_inputParams->m_gpm->getGraph();
210 
211  int size = graph->getMetadata()->getEdgePropertySize();
212 
214 
215  te::graph::Edge* edge = iterator->getFirstEdge();
216 
217  while(edge)
218  {
219  te::graph::Vertex* vFrom = graph->getVertex(edge->getIdFrom());
220  te::graph::Vertex* vTo = graph->getVertex(edge->getIdTo());
221 
222  if(vFrom && vTo)
223  {
224  double weight = calculateWeight(attrsIdx, vFrom, vTo);
225 
226  edge->setAttributeVecSize(size);
227  edge->addAttribute(weightAttrIdx, new te::dt::SimpleData<double, te::dt::DOUBLE_TYPE>(weight));
228  }
229 
230  edge = iterator->getNextEdge();
231  }
232 }
233 
234 double te::sa::SkaterOperation::calculateWeight(std::vector<int> attrsIdx, te::graph::Vertex* vFrom, te::graph::Vertex* vTo)
235 {
236  double weight = 0.;
237 
238  for(std::size_t t = 0; t < attrsIdx.size(); ++t)
239  {
240  double valueFrom = te::sa::GetDataValue(vFrom->getAttributes()[attrsIdx[t]]);
241  double valueTo = te::sa::GetDataValue(vTo->getAttributes()[attrsIdx[t]]);
242 
243  weight += (valueTo - valueFrom) * (valueTo - valueFrom);
244  }
245 
246  return sqrt(weight);
247 }
248 
249 std::map<int, int> te::sa::SkaterOperation::createSkaterMap(te::graph::AbstractGraph* graph, std::vector<std::size_t>& roots)
250 {
251  std::map<int, int> skaterMap;
252 
253  for(std::size_t t = 0; t < roots.size(); ++t)
254  {
255  std::size_t rootId = roots[t];
256 
257  //create list
258  std::queue<int> queue;
259  std::set<int> visited;
260 
261  queue.push(static_cast<int>(rootId));
262  visited.insert(static_cast<int>(rootId));
263 
264  //bfs over the graph
265  while(!queue.empty())
266  {
267  int currentId = queue.front();
268  queue.pop();
269 
270  //get vertex from graph
271  te::graph::Vertex* vertex = graph->getVertex(currentId);
272 
273  if(vertex)
274  {
275  //add to map
276  skaterMap.insert(std::map<int, int>::value_type(currentId, (int)t));
277 
278  //get neighbours
279  std::set<int> neighbours = vertex->getNeighborhood();
280  std::set<int>::iterator itNeighbours = neighbours.begin();
281 
282  while(itNeighbours != neighbours.end())
283  {
284  te::graph::Edge* e = graph->getEdge(*itNeighbours);
285  te::graph::Vertex* vTo = nullptr;
286 
287  if(e)
288  {
289  if(e->getIdFrom() == currentId)
290  vTo = graph->getVertex(e->getIdTo());
291  else
292  vTo = graph->getVertex(e->getIdFrom());
293  }
294 
295  if(vTo)
296  {
297  //check if already visted
298  if(visited.find(vTo->getId()) == visited.end())
299  {
300  //add in queue
301  queue.push(vTo->getId());
302  visited.insert(vTo->getId());
303  }
304  }
305 
306  ++itNeighbours;
307  }
308  }
309  }
310  }
311 
312  return skaterMap;
313 }
Class that represents the skater partition operation.
void execute()
Function to execute the skater operation.
virtual te::graph::Edge * getNextEdge()
It returns a pointer to the next edge element of a graph.
#define TE_SA_SKATER_ATTR_CLASS_NAME
void setAttributeVecSize(int size)
This function is used to set the number of attributes associated with the edge elements.
Definition: Edge.cpp:86
An atomic property like an integer or double.
This file contains a class that represents the skater operation.
A class that models the description of a dataset.
Definition: DataSetType.h:72
void saveDataSet(te::da::DataSet *dataSet, te::da::DataSetType *dsType)
#define TE_SA_SKATER_ATTR_WEIGHT_NAME
virtual te::graph::Edge * getEdge(int id)=0
It returns the edge element if it&#39;s exist.
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
double calculateWeight(std::vector< int > attrsIdx, te::graph::Vertex *vFrom, te::graph::Vertex *vTo)
Function to calculate the weight attribute using the euclidean distance.
Class that represents the skater input parameters.
Definition: SkaterParams.h:56
~SkaterOperation()
Virtual destructor.
std::unique_ptr< te::sa::SkaterOutputParams > m_outputParams
Attribute with the skater output parameters.
std::vector< te::dt::AbstractData * > & getAttributes()
It returns the vector of attributes associated with this element.
Definition: Vertex.cpp:74
virtual Property * clone() const =0
It returns a clone of the object.
It models a property definition.
Definition: Property.h:59
Class that represents the skater output parameters.
Definition: SkaterParams.h:98
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
void setId(unsigned int id)
It sets the property identifier.
Definition: Property.h:118
virtual te::graph::GraphMetadata * getMetadata()=0
Function used to access the graph metadata.
void setInt32(std::size_t i, boost::int32_t value)
It sets the value of the i-th property.
Class used to define the edge struct of a graph. Its compose with a identifier, the vertex origin and...
Definition: Edge.h:58
virtual bool moveNext()=0
It moves the internal pointer to the next item of the collection.
std::unique_ptr< te::da::DataSetType > createDataSetType(te::da::DataSetType *dsType)
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
This file contains a class that represents the skater partition operation.
const std::vector< Property * > & getProperties() const
It returns the list of properties describing the CompositeProperty.
std::vector< std::size_t > execute(std::size_t nGroups, std::string popAttr="", std::size_t minPop=0)
Function to execute the skater partition.
void createWeightAttribute(int weightAttrIdx, std::vector< int > attrsIdx)
Function to create the weight attribute.
Abstract class used to define the main functions of graph struct. All graph implementations must used...
Definition: AbstractGraph.h:55
void setParameters(te::sa::SkaterInputParams *inParams, te::sa::SkaterOutputParams *outParams)
virtual std::string getAsString(std::size_t i, int precision=0) const
Method for retrieving a data value as a string plain representation.
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
std::map< int, int > createSkaterMap(te::graph::AbstractGraph *graph, std::vector< std::size_t > &roots)
int getIdFrom()
It returns the vertex origin identification.
Definition: Edge.cpp:71
std::set< int > & getNeighborhood()
Returns the Neighborhood vector.
Definition: Vertex.cpp:111
Utility functions for the data access module.
int m_nClassGroups
Number of classes (clusters) generated.
TESAEXPORT int AssociateGPMVertexAttribute(te::sa::GeneralizedProximityMatrix *gpm, te::da::DataSource *ds, std::string dataSetName, std::string attrLink, std::string attr, int dataType, int srid=TE_UNKNOWN_SRS, int subType=static_cast< int >(te::gm::UnknownGeometryType))
Function used to set a an attribute valeu from a dataset to the vertex objects from a gpm...
std::unique_ptr< te::sa::SkaterInputParams > m_inputParams
Attribute with the skater input parameters.
virtual te::graph::Edge * getFirstEdge()
It returns a pointer to the first edge element of a graph.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
A dataset is the unit of information manipulated by the data access module of TerraLib.
virtual std::unique_ptr< te::dt::AbstractData > getValue(std::size_t i) const
Method for retrieving any other type of data value stored in the data source.
virtual bool moveBeforeFirst()=0
It moves the internal pointer to a position before the first item in the collection.
virtual int getEdgePropertySize()
Used to verify the number of properties associated to edge elements.
std::unique_ptr< te::mem::DataSet > createDataSet(te::da::DataSet *inputDataSet, te::da::DataSetType *dsType, std::map< int, int > &skaterMap, std::string linkName)
int getId()
It returns the vertex id.
Definition: Vertex.cpp:69
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.
virtual std::size_t getNumProperties() const =0
It returns the number of properties that composes an item of the dataset.
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
SkaterOperation()
Default constructor.
int getIdTo()
It returns the vertex destiny identification.
Definition: Edge.cpp:76
This class defines the GPM class.
void setParent(Property *p)
It associate this property to the informed parent.
Definition: Property.h:177