SMIL  1.0.4
DDigraph.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_DIGRAPH_HPP
31 #define _D_DIGRAPH_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 Diedge
65  {
66  public:
67  typedef WeightT WeightType;
68 
71  Diedge() : source(0), target(0), weight(1)
72  {
73  }
74 
77  Diedge(NodeT a, NodeT b, WeightT w = 1) : source(a), target(b), weight(w)
78  {
79  }
80 
83  Diedge(const Diedge &rhs)
84  : source(rhs.source), target(rhs.target), weight(rhs.weight)
85  {
86  }
87 
89  virtual ~Diedge()
90  {
91  }
97  Diedge &operator=(const Diedge &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 
112  bool oriented;
113 
120  inline bool isActive() const
121  {
122  return (source != 0 || target != 0);
123  }
124 
128  inline void desactivate()
129  {
130  source = 0;
131  target = 0;
132  }
133 
134  // Don't test the weight values (only to check if the edge exists)
135  inline bool operator==(const Diedge &rhs) const
136  {
137  if (rhs.source == source && rhs.target == target)
138  return true;
139  if (rhs.source == target && rhs.target == source)
140  return true;
141  return false;
142  }
143 
144  inline bool operator!=(const Diedge &rhs) const
145  {
146  return !this->operator==(rhs);
147  }
148 
149  inline bool operator<(const Diedge &rhs) const
150  {
151  return weight > rhs.weight;
152  }
153 
154  virtual void printSelf(ostream &os = std::cout, string s = "") const
155  {
156  os << s << (int) source << "-" << (int) target << " (" << (int) weight
157  << ")" << endl;
158  }
159  };
160 
161  // Compare two vectors of edges (test also the weight values)
165  template <class NodeT, class WeightT>
166  bool operator==(const vector<Diedge<NodeT, WeightT>> &e1,
167  const vector<Diedge<NodeT, WeightT>> &e2)
168  {
169  if (e1.size() != e2.size())
170  return false;
171 
172  typedef Diedge<NodeT, WeightT> DiedgeT;
173  typename vector<DiedgeT>::const_iterator it1 = e1.begin(), it2 = e2.begin();
174 
175  for (; it1 != e1.end() && it2 != e2.end(); it1++, it2++) {
176  if ((*it1) != (*it2))
177  return false;
178  if (it1->weight != it2->weight)
179  return false;
180  }
181 
182  return true;
183  }
184 
185  //
186  // #### ##### ## ##### # #
187  // # # # # # # # # # #
188  // # # # # # # # ######
189  // # ### ##### ###### ##### # #
190  // # # # # # # # # #
191  // #### # # # # # # #
192  //
197  template <class NodeT = size_t, class WeightT = size_t>
198  class Digraph : public BaseObject
199  {
200  public:
202 
203  typedef NodeT NodeType;
204  typedef WeightT NodeWeightType;
205  typedef std::map<NodeT, WeightT> NodeValuesType;
206  typedef set<NodeT> NodeListType;
207 
209  typedef WeightT DiedgeWeightType;
210 
211  typedef std::vector<Diedge<NodeT, WeightT>> DiedgeListType;
212  typedef std::vector<size_t> NodeDiedgesType;
213  typedef std::map<NodeT, NodeDiedgesType> NodeDiedgeListType;
214 
215  protected:
216  size_t edgeNbr;
217  NodeListType nodes;
218  NodeValuesType nodeValues;
219  DiedgeListType edges;
220  NodeDiedgeListType nodeEdgeList;
221  bool oriented;
222 
223  public:
225  Digraph() : BaseObject("Digraph"), edgeNbr(0), oriented(true)
226  {
227  }
228 
230  Digraph(const Digraph &rhs)
231  : BaseObject("Digraph"), edgeNbr(rhs.edgeNbr), nodes(rhs.nodes),
232  nodeValues(rhs.nodeValues), edges(rhs.edges),
233  nodeEdgeList(rhs.nodeEdgeList), oriented(rhs.oriented)
234  {
235  }
236 
238  virtual ~Digraph()
239  {
240  }
243  Digraph &operator=(const Digraph &rhs)
244  {
245  nodes = rhs.nodes;
246  nodeValues = rhs.nodeValues;
247  edges = rhs.edges;
248  nodeEdgeList = rhs.nodeEdgeList;
249  edgeNbr = rhs.edgeNbr;
250  oriented = rhs.oriented;
251  return *this;
252  }
253 
255  void clear()
256  {
257  nodes.clear();
258  nodeValues.clear();
259  edges.clear();
260  nodeEdgeList.clear();
261  edgeNbr = 0;
262  oriented = true;
263  }
264 
266  void addNode(const NodeT &ind)
267  {
268  nodes.insert(ind);
269  }
270 
272  void addNode(const NodeT &ind, const WeightT &val)
273  {
274  nodes.insert(ind);
275  nodeValues[ind] = val;
276  }
277 
281  int findEdge(const DiedgeType &e)
282  {
283  typename DiedgeListType::iterator foundEdge =
284  find(edges.begin(), edges.end(), e);
285  if (foundEdge != edges.end())
286  return foundEdge - edges.begin();
287  else
288  return -1;
289  }
290 
294  int findEdge(const NodeT &src, const NodeT &targ)
295  {
296  return findEdge(DiedgeType(src, targ));
297  }
298 
306  void addEdge(const DiedgeType &e, bool checkIfExists = true)
307  {
308  if (checkIfExists)
309  if (findEdge(e) != -1)
310  return;
311 
312  edges.push_back(e);
313  nodes.insert(e.source);
314  nodes.insert(e.target);
315  nodeEdgeList[e.source].push_back(edgeNbr);
316  nodeEdgeList[e.target].push_back(edgeNbr);
317 
318  edgeNbr++;
319  }
320 
330  void addEdge(const NodeT src, const NodeT targ, WeightT weight = 0,
331  bool checkIfExists = true)
332  {
333  addEdge(DiedgeType(src, targ, weight), checkIfExists);
334  }
335 
339  void sortEdges(bool reverse = false)
340  {
341  DiedgeListType sEdges = edges;
342  if (!reverse)
343  sort(sEdges.begin(), sEdges.end());
344  else
345  sort(sEdges.rbegin(), sEdges.rend());
346 
347  nodes.clear();
348  edges.clear();
349  nodeEdgeList.clear();
350  edgeNbr = 0;
351 
352  for (typename DiedgeListType::const_iterator it = sEdges.begin();
353  it != sEdges.end(); it++)
354  addEdge(*it, false);
355  }
356 
361  {
362  return DigraphType(*this);
363  }
364 
368  size_t getNodeNbr()
369  {
370  return nodes.size();
371  }
372 
376  size_t getEdgeNbr()
377  {
378  return edges.size();
379  }
380 
381  protected:
382  void removeNode(const NodeT ind)
383  {
384  typename NodeListType::iterator fNode = nodes.find(ind);
385  if (fNode != nodes.end())
386  nodes.erase(fNode);
387  removeNodeEdges(ind);
388  }
389 
390  void removeNodeEdge(const NodeT node, const size_t edgeIndex)
391  {
392  typename NodeDiedgeListType::iterator nEdges = nodeEdgeList.find(node);
393  if (nEdges == nodeEdgeList.end())
394  return;
395 
396  NodeDiedgesType &eList = nEdges->second;
397 
398  typename NodeDiedgesType::iterator ei =
399  find(eList.begin(), eList.end(), edgeIndex);
400  if (ei != eList.end())
401  eList.erase(ei);
402  }
403 
404  public:
408  void removeNodeEdges(const NodeT node)
409  {
410  typename NodeDiedgeListType::iterator fNodeEdges =
411  nodeEdgeList.find(node);
412  if (fNodeEdges == nodeEdgeList.end())
413  return;
414 
415  NodeDiedgesType &nedges = fNodeEdges->second;
416  for (NodeDiedgesType::iterator it = nedges.begin(); it != nedges.end();
417  it++) {
418  DiedgeType &e = edges[*it];
419  if (e.source == node)
420  removeNodeEdge(e.target, *it);
421  else
422  removeNodeEdge(e.source, *it);
423  e.desactivate();
424  }
425  nedges.clear();
426  }
427 
431  void removeEdge(const size_t index)
432  {
433  if (index >= edges.size())
434  return;
435 
436  DiedgeType &edge = edges[index];
437 
438  removeNodeEdge(edge.source, index);
439  removeNodeEdge(edge.target, index);
440  edge.desactivate();
441  }
442 
446  void removeEdge(const NodeT src, const NodeT targ)
447  {
448  typename DiedgeListType::iterator foundEdge =
449  find(edges.begin(), edges.end(), DiedgeType(src, targ));
450  if (foundEdge == edges.end())
451  return;
452 
453  return removeEdge(foundEdge - edges.begin());
454  }
455 
459  void removeEdge(const DiedgeType &edge)
460  {
461  typename DiedgeListType::iterator foundEdge =
462  find(edges.begin(), edges.end(), edge);
463  if (foundEdge == edges.end())
464  return;
465 
466  return removeEdge(foundEdge - edges.begin());
467  }
468 
475  void removeHighEdges(DiedgeWeightType EdgeThreshold)
476  {
477  size_t nb_edges = edges.size();
478  for (size_t index = 0; index < nb_edges; index++) {
479  DiedgeType &e = edges[index];
480  if (e.weight > EdgeThreshold)
481  removeEdge(index);
482  }
483  }
484 
491  void removeLowEdges(DiedgeWeightType EdgeThreshold)
492  {
493  size_t nb_edges = edges.size();
494  for (size_t index = 0; index < nb_edges; index++) {
495  DiedgeType &e = edges[index];
496  if (e.weight < EdgeThreshold)
497  removeEdge(index);
498  }
499  }
500 
502 #ifndef SWIG
503  const NodeListType &getNodes() const
504  {
505  return nodes;
506  } // lvalue
507 
508  const DiedgeListType &getEdges() const
509  {
510  return edges;
511  } // lvalue
512 
513  const NodeValuesType &getNodeValues() const
514  {
515  return nodeValues;
516  } // lvalue
517 
518  const NodeDiedgeListType &getNodeEdges() const
519  {
520  return nodeEdgeList;
521  } // lvalue
522 #endif // SWIG
530  NodeListType &getNodes()
531  {
532  return nodes;
533  } // rvalue
534 
540  DiedgeListType &getEdges()
541  {
542  return edges;
543  } // rvalue
544 
548  NodeValuesType &getNodeValues()
549  {
550  return nodeValues;
551  } // rvalue
552 
556  NodeDiedgeListType &getNodeEdges()
557  {
558  return nodeEdgeList;
559  } // rvalue
560 
564  NodeDiedgesType getNodeEdges(const size_t &node)
565  {
566  typename NodeDiedgeListType::iterator it = nodeEdgeList.find(node);
567  if (it != nodeEdgeList.end())
568  return it->second;
569  else
570  return vector<size_t>();
571  }
572 
577  {
578  return graphMST(*this);
579  }
580 
584  virtual void printSelf(ostream &os = std::cout, string s = "") const
585  {
586  os << s << "Number of nodes: " << nodes.size() << endl;
587  os << s << "Number of edges: " << edges.size() << endl;
588  os << s << "Oriented: " << (oriented ? "true" : "false") << endl;
589  os << s << "Edges: " << endl << "source-target (weight) " << endl;
590 
591  string s2 = s + "\t";
592  for (typename DiedgeListType::const_iterator it = edges.begin();
593  it != edges.end(); it++)
594  if ((*it).isActive())
595  (*it).printSelf(os, s2);
596  }
597 
605  map<NodeT, NodeT> labelizeNodes() const
606  {
607  map<NodeT, NodeT> lookup;
608  set<NodeT> nodeList(nodes);
609 
610  while (!nodeList.empty()) {
611  propagateLabel(*(nodeList.begin()), *(nodeList.begin()), lookup,
612  nodeList);
613  }
614  return lookup;
615  }
616 
617  protected:
618  void propagateLabel(const NodeT ind, const NodeT lbl,
619  map<NodeT, NodeT> &lookup, set<NodeT> &nList) const
620  {
621  typename NodeListType::iterator foundNode = nList.find(ind);
622  if (foundNode == nList.end())
623  return;
624 
625  lookup[ind] = lbl;
626  nList.erase(foundNode);
627 
628  const NodeDiedgesType &nEdges = nodeEdgeList.at(ind);
629 
630  for (typename NodeDiedgesType::const_iterator it = nEdges.begin();
631  it != nEdges.end(); it++) {
632  const DiedgeType &e = edges[*it];
633  if (e.source != ind)
634  propagateLabel(e.source, lbl, lookup, nList);
635  else if (e.target != ind)
636  propagateLabel(e.target, lbl, lookup, nList);
637  }
638  }
639  };
640 
647  template <class digraphT>
648  digraphT digraphMST(const digraphT &graph)
649  {
650  typedef typename digraphT::NodeType NodeType;
651  typedef typename digraphT::DiedgeType DiedgeType;
652  typedef typename digraphT::DiedgeListType DiedgeListType;
653  typedef typename digraphT::NodeDiedgesType NodeDiedgesType;
654  typedef typename digraphT::NodeDiedgeListType NodeDiedgeListType;
655 
656  std::set<NodeType> visitedNodes;
657  std::priority_queue<DiedgeType> pq;
658  digraphT mst;
659 
660  const DiedgeListType & edges = graph.getEdges();
661  const NodeDiedgeListType &nodeEdgeList = graph.getNodeEdges();
662 
663  NodeType curNode = (*nodeEdgeList.begin()).first;
664  visitedNodes.insert(curNode);
665 
666  const NodeDiedgesType &nodeEdges = nodeEdgeList.at(curNode);
667  for (typename NodeDiedgesType::const_iterator it = nodeEdges.begin();
668  it != nodeEdges.end(); it++)
669  pq.push(edges[*it]);
670 
671  while (!pq.empty()) {
672  DiedgeType edge = pq.top();
673  pq.pop();
674 
675  if (visitedNodes.find(edge.source) == visitedNodes.end())
676  curNode = edge.source;
677  else if (visitedNodes.find(edge.target) == visitedNodes.end())
678  curNode = edge.target;
679  else
680  continue;
681 
682  mst.addEdge(edge, false);
683  visitedNodes.insert(curNode);
684  NodeDiedgesType const &nodeEdges = nodeEdgeList.at(curNode);
685  for (typename NodeDiedgesType::const_iterator it = nodeEdges.begin();
686  it != nodeEdges.end(); it++)
687  pq.push(edges[*it]);
688  }
689  // Copy node values
690  mst.getNodeValues() = graph.getNodeValues();
691 
692  return mst;
693  }
694 
697 } // namespace smil
698 
699 #endif // _D_DIGRAPH_HPP
Base Smil Object.
Definition: DBaseObject.h:52
Non-oriented edge.
Definition: DDigraph.hpp:65
Diedge(const Diedge &rhs)
Copy constructor.
Definition: DDigraph.hpp:83
Diedge(NodeT a, NodeT b, WeightT w=1)
Constructor using two nodes and an optional weight (default 1).
Definition: DDigraph.hpp:77
WeightT weight
Edge weight/value.
Definition: DDigraph.hpp:110
bool isActive() const
Check if the edge is active.
Definition: DDigraph.hpp:120
void desactivate()
Deactivate the Edge.
Definition: DDigraph.hpp:128
NodeT source
Source node.
Definition: DDigraph.hpp:106
NodeT target
Target node.
Definition: DDigraph.hpp:108
Diedge & operator=(const Diedge &rhs)
Copy an edge.
Definition: DDigraph.hpp:97
Diedge()
Default constructor.
Definition: DDigraph.hpp:71
Non-oriented Digraph.
Definition: DDigraph.hpp:199
NodeDiedgesType getNodeEdges(const size_t &node)
getNodeEdges() - Get a map containing the edges linked to a given node
Definition: DDigraph.hpp:564
void removeHighEdges(DiedgeWeightType EdgeThreshold)
removeHighEdges() - remove edges whose weight are greater then some threshold
Definition: DDigraph.hpp:475
void addNode(const NodeT &ind)
Add a node given its index.
Definition: DDigraph.hpp:266
size_t getEdgeNbr()
getEdgeNbr() -
Definition: DDigraph.hpp:376
map< NodeT, NodeT > labelizeNodes() const
labelizeNodes() - Labelize the nodes.
Definition: DDigraph.hpp:605
NodeDiedgeListType & getNodeEdges()
getNodeEdges()-
Definition: DDigraph.hpp:556
void addNode(const NodeT &ind, const WeightT &val)
Add a node given its index and its optional value.
Definition: DDigraph.hpp:272
void removeLowEdges(DiedgeWeightType EdgeThreshold)
removeHighEdges() - remove edges whose weight are lesser then some threshold
Definition: DDigraph.hpp:491
DiedgeListType & getEdges()
getEdges() - Get a vector containing the graph edges
Definition: DDigraph.hpp:540
NodeListType & getNodes()
getNodes() - get the list of nodes
Definition: DDigraph.hpp:530
void removeEdge(const NodeT src, const NodeT targ)
Find and remove an edge linking src to targ.
Definition: DDigraph.hpp:446
Digraph(const Digraph &rhs)
Copy constructor.
Definition: DDigraph.hpp:230
DigraphType clone()
clone() -
Definition: DDigraph.hpp:360
DigraphType computeMST()
computeMST() - Compute the Minimum Spanning Tree graph
Definition: DDigraph.hpp:576
virtual void printSelf(ostream &os=std::cout, string s="") const
printSelf() -
Definition: DDigraph.hpp:584
size_t getNodeNbr()
getNodeNbr() -
Definition: DDigraph.hpp:368
void removeEdge(const size_t index)
Remove an edge.
Definition: DDigraph.hpp:431
void removeEdge(const DiedgeType &edge)
Remove a given edge.
Definition: DDigraph.hpp:459
int findEdge(const NodeT &src, const NodeT &targ)
findEdge() - Find an edge by its nodes - return its index
Definition: DDigraph.hpp:294
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: DDigraph.hpp:330
void sortEdges(bool reverse=false)
Sort edges (by weight as defined by the operator < of class Edge)
Definition: DDigraph.hpp:339
void clear()
Clear graph content.
Definition: DDigraph.hpp:255
void removeNodeEdges(const NodeT node)
Remove all edges linked to the node nodeIndex.
Definition: DDigraph.hpp:408
NodeValuesType & getNodeValues()
getNodeValues() -
Definition: DDigraph.hpp:548
int findEdge(const DiedgeType &e)
findEdge() - Find an edge by its content - return its index
Definition: DDigraph.hpp:281
void addEdge(const DiedgeType &e, bool checkIfExists=true)
Add an edge to the graph.
Definition: DDigraph.hpp:306
Digraph()
Default constructor.
Definition: DDigraph.hpp:225
NodeEdgeListType & getNodeEdges()
getNodeEdges()-
Definition: DGraph.hpp:550
EdgeListType & getEdges()
getEdges() - Get a vector containing the graph edges
Definition: DGraph.hpp:534
NodeValuesType & getNodeValues()
getNodeValues() -
Definition: DGraph.hpp:542
digraphT digraphMST(const digraphT &graph)
graphMST() - create a Mininum Spanning Tree
Definition: DDigraph.hpp:648
bool operator==(const vector< Diedge< NodeT, WeightT >> &e1, const vector< Diedge< NodeT, WeightT >> &e2)
Check if two vectors of edges are equal.
Definition: DDigraph.hpp:166
graphT graphMST(const graphT &graph)
graphMST() - create a Mininum Spanning Tree
Definition: DGraph.hpp:641
Definition: DUtils.h:13