SMIL  1.1
DGraph.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _D_GRAPH_HPP
31 #define _D_GRAPH_HPP
32 
33 #include "Core/include/DBaseObject.h"
34 
35 #include <list>
36 #include <algorithm>
37 #include <vector>
38 #include <utility>
39 #include <iostream>
40 #include <stdexcept>
41 #include <set>
42 #include <queue>
43 
44 namespace smil
45 {
51  //
52  // ###### ##### #### ######
53  // # # # # # #
54  // ##### # # # #####
55  // # # # # ### #
56  // # # # # # #
57  // ###### ##### #### ######
58  //
63  template <class NodeT = size_t, class WeightT = size_t>
64  class Edge
65  {
66  public:
67  typedef WeightT WeightType;
68 
71  Edge() : source(0), target(0), weight(1)
72  {
73  }
74 
77  Edge(NodeT a, NodeT b, WeightT w = 1) : source(a), target(b), weight(w)
78  {
79  }
80 
83  Edge(const Edge &rhs)
84  : source(rhs.source), target(rhs.target), weight(rhs.weight)
85  {
86  }
87 
89  virtual ~Edge()
90  {
91  }
97  Edge &operator=(const Edge &rhs)
98  {
99  source = rhs.source;
100  target = rhs.target;
101  weight = rhs.weight;
102  return *this;
103  }
104 
106  NodeT source;
108  NodeT target;
110  WeightT weight;
111 
118  inline bool isActive() const
119  {
120  return (source != 0 || target != 0);
121  }
122 
126  inline void desactivate()
127  {
128  source = 0;
129  target = 0;
130  }
131 
132  // Don't test the weight values (only to check if the edge exists)
133  inline bool operator==(const Edge &rhs) const
134  {
135  if (rhs.source == source && rhs.target == target)
136  return true;
137  if (rhs.source == target && rhs.target == source)
138  return true;
139  return false;
140  }
141 
142  inline bool operator!=(const Edge &rhs) const
143  {
144  return !this->operator==(rhs);
145  }
146 
147  inline bool operator<(const Edge &rhs) const
148  {
149  return weight > rhs.weight;
150  }
151 
152  virtual void printSelf(ostream &os = std::cout, string s = "") const
153  {
154  os << s << (int) source << "-" << (int) target << " (" << (int) weight
155  << ")" << endl;
156  }
157  };
158 
159  // Compare two vectors of edges (test also the weight values)
163  template <class NodeT, class WeightT>
164  bool operator==(const vector<Edge<NodeT, WeightT>> &e1,
165  const vector<Edge<NodeT, WeightT>> &e2)
166  {
167  if (e1.size() != e2.size())
168  return false;
169 
170  typedef Edge<NodeT, WeightT> EdgeT;
171  typename vector<EdgeT>::const_iterator it1 = e1.begin(), it2 = e2.begin();
172 
173  for (; it1 != e1.end() && it2 != e2.end(); it1++, it2++) {
174  if ((*it1) != (*it2))
175  return false;
176  if (it1->weight != it2->weight)
177  return false;
178  }
179 
180  return true;
181  }
182 
183  //
184  // #### ##### ## ##### # #
185  // # # # # # # # # # #
186  // # # # # # # # ######
187  // # ### ##### ###### ##### # #
188  // # # # # # # # # #
189  // #### # # # # # # #
190  //
195  template <class NodeT = size_t, class WeightT = size_t>
196  class Graph : public BaseObject
197  {
198  public:
200 
201  typedef NodeT NodeType;
202  typedef WeightT NodeWeightType;
203  typedef std::map<NodeT, WeightT> NodeValuesType;
204  typedef set<NodeT> NodeListType;
205 
207  typedef WeightT EdgeWeightType;
208 
209  typedef std::vector<Edge<NodeT, WeightT>> EdgeListType;
210  typedef std::vector<size_t> NodeEdgesType;
211  typedef std::map<NodeT, NodeEdgesType> NodeEdgeListType;
212 
213  protected:
214  size_t edgeNbr;
215  NodeListType nodes;
216  NodeValuesType nodeValues;
217  EdgeListType edges;
218  NodeEdgeListType nodeEdgeList;
219 
220  public:
222  Graph() : BaseObject("Graph"), edgeNbr(0)
223  {
224  }
225 
227  Graph(const Graph &rhs)
228  : BaseObject("Graph"), edgeNbr(rhs.edgeNbr), nodes(rhs.nodes),
229  nodeValues(rhs.nodeValues), edges(rhs.edges),
230  nodeEdgeList(rhs.nodeEdgeList)
231  {
232  }
233 
235  virtual ~Graph()
236  {
237  }
240  Graph &operator=(const Graph &rhs)
241  {
242  nodes = rhs.nodes;
243  nodeValues = rhs.nodeValues;
244  edges = rhs.edges;
245  nodeEdgeList = rhs.nodeEdgeList;
246  edgeNbr = rhs.edgeNbr;
247  return *this;
248  }
249 
251  void clear()
252  {
253  nodes.clear();
254  nodeValues.clear();
255  edges.clear();
256  nodeEdgeList.clear();
257  edgeNbr = 0;
258  }
259 
261  void addNode(const NodeT &ind)
262  {
263  nodes.insert(ind);
264  }
265 
267  void addNode(const NodeT &ind, const WeightT &val)
268  {
269  nodes.insert(ind);
270  nodeValues[ind] = val;
271  }
272 
276  int findEdge(const EdgeType &e)
277  {
278  typename EdgeListType::iterator foundEdge =
279  find(edges.begin(), edges.end(), e);
280  if (foundEdge != edges.end())
281  return foundEdge - edges.begin();
282  else
283  return -1;
284  }
285 
289  int findEdge(const NodeT &src, const NodeT &targ)
290  {
291  return findEdge(EdgeType(src, targ));
292  }
293 
301  void addEdge(const EdgeType &e, bool checkIfExists = true)
302  {
303  if (checkIfExists)
304  if (findEdge(e) != -1)
305  return;
306 
307  edges.push_back(e);
308  nodes.insert(e.source);
309  nodes.insert(e.target);
310  nodeEdgeList[e.source].push_back(edgeNbr);
311  nodeEdgeList[e.target].push_back(edgeNbr);
312 
313  edgeNbr++;
314  }
315 
325  void addEdge(const NodeT src, const NodeT targ, WeightT weight = 0,
326  bool checkIfExists = true)
327  {
328  addEdge(EdgeType(src, targ, weight), checkIfExists);
329  }
330 
334  void sortEdges(bool reverse = false)
335  {
336  EdgeListType sEdges = edges;
337  if (!reverse)
338  sort(sEdges.begin(), sEdges.end());
339  else
340  sort(sEdges.rbegin(), sEdges.rend());
341 
342  nodes.clear();
343  edges.clear();
344  nodeEdgeList.clear();
345  edgeNbr = 0;
346 
347  for (typename EdgeListType::const_iterator it = sEdges.begin();
348  it != sEdges.end(); it++)
349  addEdge(*it, false);
350  }
351 
356  {
357  return GraphType(*this);
358  }
359 
363  size_t getNodeNbr()
364  {
365  return nodes.size();
366  }
367 
371  size_t getEdgeNbr()
372  {
373  return edges.size();
374  }
375 
376  protected:
377  void removeNode(const NodeT ind)
378  {
379  typename NodeListType::iterator fNode = nodes.find(ind);
380  if (fNode != nodes.end())
381  nodes.erase(fNode);
382  removeNodeEdges(ind);
383  }
384 
385  void removeNodeEdge(const NodeT node, const size_t edgeIndex)
386  {
387  typename NodeEdgeListType::iterator nEdges = nodeEdgeList.find(node);
388  if (nEdges == nodeEdgeList.end())
389  return;
390 
391  NodeEdgesType &eList = nEdges->second;
392 
393  typename NodeEdgesType::iterator ei =
394  find(eList.begin(), eList.end(), edgeIndex);
395  if (ei != eList.end())
396  eList.erase(ei);
397  }
398 
399  public:
403  void removeNodeEdges(const NodeT node)
404  {
405  typename NodeEdgeListType::iterator fNodeEdges = nodeEdgeList.find(node);
406  if (fNodeEdges == nodeEdgeList.end())
407  return;
408 
409  NodeEdgesType &nedges = fNodeEdges->second;
410  for (NodeEdgesType::iterator it = nedges.begin(); it != nedges.end();
411  it++) {
412  EdgeType &e = edges[*it];
413  if (e.source == node)
414  removeNodeEdge(e.target, *it);
415  else
416  removeNodeEdge(e.source, *it);
417  e.desactivate();
418  }
419  nedges.clear();
420  }
421 
425  void removeEdge(const size_t index)
426  {
427  if (index >= edges.size())
428  return;
429 
430  EdgeType &edge = edges[index];
431 
432  removeNodeEdge(edge.source, index);
433  removeNodeEdge(edge.target, index);
434  edge.desactivate();
435  }
436 
440  void removeEdge(const NodeT src, const NodeT targ)
441  {
442  typename EdgeListType::iterator foundEdge =
443  find(edges.begin(), edges.end(), EdgeType(src, targ));
444  if (foundEdge == edges.end())
445  return;
446 
447  return removeEdge(foundEdge - edges.begin());
448  }
449 
453  void removeEdge(const EdgeType &edge)
454  {
455  typename EdgeListType::iterator foundEdge =
456  find(edges.begin(), edges.end(), edge);
457  if (foundEdge == edges.end())
458  return;
459 
460  return removeEdge(foundEdge - edges.begin());
461  }
462 
469  void removeHighEdges(EdgeWeightType EdgeThreshold)
470  {
471  size_t nb_edges = edges.size();
472  for (size_t index = 0; index < nb_edges; index++) {
473  EdgeType &e = edges[index];
474  if (e.weight > EdgeThreshold)
475  removeEdge(index);
476  }
477  }
478 
485  void removeLowEdges(EdgeWeightType EdgeThreshold)
486  {
487  size_t nb_edges = edges.size();
488  for (size_t index = 0; index < nb_edges; index++) {
489  EdgeType &e = edges[index];
490  if (e.weight < EdgeThreshold)
491  removeEdge(index);
492  }
493  }
494 
496 #ifndef SWIG
497  const NodeListType &getNodes() const
498  {
499  return nodes;
500  } // lvalue
501 
502  const EdgeListType &getEdges() const
503  {
504  return edges;
505  } // lvalue
506 
507  const NodeValuesType &getNodeValues() const
508  {
509  return nodeValues;
510  } // lvalue
511 
512  const NodeEdgeListType &getNodeEdges() const
513  {
514  return nodeEdgeList;
515  } // lvalue
516 #endif // SWIG
524  NodeListType &getNodes()
525  {
526  return nodes;
527  } // rvalue
528 
534  EdgeListType &getEdges()
535  {
536  return edges;
537  } // rvalue
538 
542  NodeValuesType &getNodeValues()
543  {
544  return nodeValues;
545  } // rvalue
546 
550  NodeEdgeListType &getNodeEdges()
551  {
552  return nodeEdgeList;
553  } // rvalue
554 
558  NodeEdgesType getNodeEdges(const size_t &node)
559  {
560  typename NodeEdgeListType::iterator it = nodeEdgeList.find(node);
561  if (it != nodeEdgeList.end())
562  return it->second;
563  else
564  return vector<size_t>();
565  }
566 
571  {
572  return graphMST(*this);
573  }
574 
578  virtual void printSelf(ostream &os = std::cout, string s = "") const
579  {
580  os << s << "Number of nodes: " << nodes.size() << endl;
581  os << s << "Number of edges: " << edges.size() << endl;
582  os << s << "Edges: " << endl << "source-target (weight) " << endl;
583 
584  string s2 = s + "\t";
585  for (typename EdgeListType::const_iterator it = edges.begin();
586  it != edges.end(); it++)
587  if ((*it).isActive())
588  (*it).printSelf(os, s2);
589  }
590 
598  map<NodeT, NodeT> labelizeNodes() const
599  {
600  map<NodeT, NodeT> lookup;
601  set<NodeT> nodeList(nodes);
602 
603  while (!nodeList.empty()) {
604  propagateLabel(*(nodeList.begin()), *(nodeList.begin()), lookup,
605  nodeList);
606  }
607  return lookup;
608  }
609 
610  protected:
611  void propagateLabel(const NodeT ind, const NodeT lbl,
612  map<NodeT, NodeT> &lookup, set<NodeT> &nList) const
613  {
614  typename NodeListType::iterator foundNode = nList.find(ind);
615  if (foundNode == nList.end())
616  return;
617 
618  lookup[ind] = lbl;
619  nList.erase(foundNode);
620 
621  const NodeEdgesType &nEdges = nodeEdgeList.at(ind);
622 
623  for (typename NodeEdgesType::const_iterator it = nEdges.begin();
624  it != nEdges.end(); it++) {
625  const EdgeType &e = edges[*it];
626  if (e.source != ind)
627  propagateLabel(e.source, lbl, lookup, nList);
628  else if (e.target != ind)
629  propagateLabel(e.target, lbl, lookup, nList);
630  }
631  }
632  };
633 
640  template <class graphT>
641  graphT graphMST(const graphT &graph)
642  {
643  typedef typename graphT::NodeType NodeType;
644  typedef typename graphT::EdgeType EdgeType;
645  typedef typename graphT::EdgeListType EdgeListType;
646  typedef typename graphT::NodeEdgesType NodeEdgesType;
647  typedef typename graphT::NodeEdgeListType NodeEdgeListType;
648 
649  std::set<NodeType> visitedNodes;
650  std::priority_queue<EdgeType> pq;
651  graphT mst;
652 
653  const EdgeListType & edges = graph.getEdges();
654  const NodeEdgeListType &nodeEdgeList = graph.getNodeEdges();
655 
656  NodeType curNode = (*nodeEdgeList.begin()).first;
657  visitedNodes.insert(curNode);
658 
659  const NodeEdgesType &nodeEdges = nodeEdgeList.at(curNode);
660  for (typename NodeEdgesType::const_iterator it = nodeEdges.begin();
661  it != nodeEdges.end(); it++)
662  pq.push(edges[*it]);
663 
664  while (!pq.empty()) {
665  EdgeType edge = pq.top();
666  pq.pop();
667 
668  if (visitedNodes.find(edge.source) == visitedNodes.end())
669  curNode = edge.source;
670  else if (visitedNodes.find(edge.target) == visitedNodes.end())
671  curNode = edge.target;
672  else
673  continue;
674 
675  mst.addEdge(edge, false);
676  visitedNodes.insert(curNode);
677  NodeEdgesType const &nodeEdges = nodeEdgeList.at(curNode);
678  for (typename NodeEdgesType::const_iterator it = nodeEdges.begin();
679  it != nodeEdges.end(); it++)
680  pq.push(edges[*it]);
681  }
682  // Copy node values
683  mst.getNodeValues() = graph.getNodeValues();
684 
685  return mst;
686  }
687 
690 } // namespace smil
691 
692 #endif // _D_GRAPH_HPP
Base Smil Object.
Definition: DBaseObject.h:52
Non-oriented edge.
Definition: DGraph.hpp:65
Edge(NodeT a, NodeT b, WeightT w=1)
Constructor using two nodes and an optional weight (default 1).
Definition: DGraph.hpp:77
WeightT weight
Edge weight/value.
Definition: DGraph.hpp:110
Edge(const Edge &rhs)
Copy constructor.
Definition: DGraph.hpp:83
bool isActive() const
Check if the edge is active.
Definition: DGraph.hpp:118
Edge & operator=(const Edge &rhs)
Copy an edge.
Definition: DGraph.hpp:97
void desactivate()
Deactivate the Edge.
Definition: DGraph.hpp:126
NodeT source
Source node.
Definition: DGraph.hpp:106
Edge()
Default constructor.
Definition: DGraph.hpp:71
NodeT target
Target node.
Definition: DGraph.hpp:108
Non-oriented graph.
Definition: DGraph.hpp:197
Graph(const Graph &rhs)
Copy constructor.
Definition: DGraph.hpp:227
void addNode(const NodeT &ind)
Add a node given its index.
Definition: DGraph.hpp:261
size_t getEdgeNbr()
getEdgeNbr() -
Definition: DGraph.hpp:371
map< NodeT, NodeT > labelizeNodes() const
labelizeNodes() - Labelize the nodes.
Definition: DGraph.hpp:598
void addEdge(const EdgeType &e, bool checkIfExists=true)
Add an edge to the graph.
Definition: DGraph.hpp:301
void addNode(const NodeT &ind, const WeightT &val)
Add a node given its index and its optional value.
Definition: DGraph.hpp:267
GraphType clone()
clone() -
Definition: DGraph.hpp:355
NodeListType & getNodes()
getNodes() - get the list of nodes
Definition: DGraph.hpp:524
void removeEdge(const NodeT src, const NodeT targ)
Find and remove an edge linking src to targ.
Definition: DGraph.hpp:440
GraphType computeMST()
computeMST() - Compute the Minimum Spanning Tree graph
Definition: DGraph.hpp:570
virtual void printSelf(ostream &os=std::cout, string s="") const
printSelf() -
Definition: DGraph.hpp:578
NodeEdgeListType & getNodeEdges()
getNodeEdges()-
Definition: DGraph.hpp:550
void removeLowEdges(EdgeWeightType EdgeThreshold)
removeHighEdges() - remove edges whose weight are lesser then some threshold
Definition: DGraph.hpp:485
NodeEdgesType getNodeEdges(const size_t &node)
getNodeEdges() - Get a map containing the edges linked to a given node
Definition: DGraph.hpp:558
size_t getNodeNbr()
getNodeNbr() -
Definition: DGraph.hpp:363
void removeEdge(const size_t index)
Remove an edge.
Definition: DGraph.hpp:425
void removeHighEdges(EdgeWeightType EdgeThreshold)
removeHighEdges() - remove edges whose weight are greater then some threshold
Definition: DGraph.hpp:469
int findEdge(const NodeT &src, const NodeT &targ)
findEdge() - Find an edge by its nodes - return its index
Definition: DGraph.hpp:289
void addEdge(const NodeT src, const NodeT targ, WeightT weight=0, bool checkIfExists=true)
Add an edge to the graph given two nodes src and targ and an optional weight.
Definition: DGraph.hpp:325
EdgeListType & getEdges()
getEdges() - Get a vector containing the graph edges
Definition: DGraph.hpp:534
void sortEdges(bool reverse=false)
Sort edges (by weight as defined by the operator < of class Edge)
Definition: DGraph.hpp:334
void removeEdge(const EdgeType &edge)
Remove a given edge.
Definition: DGraph.hpp:453
void clear()
Clear graph content.
Definition: DGraph.hpp:251
void removeNodeEdges(const NodeT node)
Remove all edges linked to the node nodeIndex.
Definition: DGraph.hpp:403
NodeValuesType & getNodeValues()
getNodeValues() -
Definition: DGraph.hpp:542
int findEdge(const EdgeType &e)
findEdge() - Find an edge by its content - return its index
Definition: DGraph.hpp:276
Graph()
Default constructor.
Definition: DGraph.hpp:222
graphT graphMST(const graphT &graph)
graphMST() - create a Mininum Spanning Tree
Definition: DGraph.hpp:641
bool operator==(const vector< Edge< NodeT, WeightT >> &e1, const vector< Edge< NodeT, WeightT >> &e2)
Check if two vectors of edges are equal.
Definition: DGraph.hpp:164
Definition: DUtils.h:13