Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
GraphBaseT.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* GraphBaseT.h (C) 2000-2017 */
9/* */
10/* Common base of graph implementation */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_GRAPHBASET_H_
13#define ARCANE_GRAPHBASET_H_
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include <map>
18#include <set>
19#include <list>
20#include <functional>
21#include <algorithm>
22#include <utility>
23#include <vector>
24#include <numeric>
25
27#include "arcane/utils/SharedArray.h"
28#include "arcane/utils/FatalErrorException.h"
29#include "arcane/utils/ITraceMng.h"
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34ARCANE_BEGIN_NAMESPACE
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38/*! Template base class for Graph.
39 * VertexType must implement a less comparison operator.
40 * To use print, VertexType must implement << operator
41 * Multiple Edges between the same Vertices are not allowed
42 */
43
44// TODO EdgeType = void (default)
45// TODO add a template argument Comparator = std::less
46template <class VertexType, class EdgeType>
48{
49protected:
50
51 /** Constructeur de la classe */
53 : m_trace_mng(trace_mng)
54 {}
55
56 /** Destructeur de la classe */
57 virtual ~GraphBaseT() {}
58
59public:
60
61 template <class ContainerT>
63 {
64 public:
65 IterableEnsembleT(ContainerT& elements) : m_empty_container(nullptr), m_elements(elements) {}
66
67 IterableEnsembleT() : m_empty_container(new ContainerT()), m_elements(*m_empty_container){}
68
69 virtual ~IterableEnsembleT(){if (m_empty_container) delete m_empty_container;}
70
71 typedef typename ContainerT::iterator iterator;
72 typedef typename ContainerT::const_iterator const_iterator;
73
74 iterator begin() {return m_elements.begin();}
75 const_iterator begin() const {return m_elements.begin();}
76
77 iterator end() {return m_elements.end();}
78 const_iterator end() const {return m_elements.end();}
79
80 Integer size() {return m_elements.size();}
81
82 Integer size() const {return m_elements.size();}
83
84 private:
85 ContainerT* m_empty_container;
86 ContainerT& m_elements;
87 };
88
89public :
90 typedef std::reference_wrapper<VertexType> VertexTypeRef;
91 typedef std::reference_wrapper<const VertexType> VertexTypeConstRef;
92 typedef std::reference_wrapper<EdgeType> EdgeTypeRef;
93 typedef std::reference_wrapper<const EdgeType> EdgeTypeConstRef;
94 typedef std::list<VertexType> VertexList;
95 typedef std::list<EdgeType> EdgeList;
96 typedef SharedArray<VertexTypeRef> VertexTypeRefArray;
97 typedef SharedArray<VertexTypeConstRef> VertexTypeConstRefArray;
98 typedef SharedArray<EdgeTypeRef> EdgeTypeRefArray;
99 typedef SharedArray<EdgeTypeConstRef> EdgeTypeConstRefArray;
100 typedef std::map<VertexTypeConstRef,std::pair<VertexTypeRefArray,EdgeTypeRefArray>> AdjacencyListType;
101 typedef std::pair<VertexTypeRef,VertexTypeRef> VertexPair;
102 typedef std::map<EdgeTypeConstRef, VertexPair> EdgeToVertexMap;
103
104 typedef IterableEnsembleT<VertexList> VertexSet;
105 typedef IterableEnsembleT<EdgeList> EdgeSet;
106 typedef IterableEnsembleT<EdgeTypeRefArray> ConnectedEdgeSet;
107
108public:
109
110 typedef VertexType VertexRef;
111 typedef EdgeType EdgeRef;
112
113 // TODO Array de reference_wrapper ne fonctionne pas ...car il fait des T()...voir avec std::vector...
114
115 //! Les arêtes multiples (constituées des mêmes noeuds source et target) ne sont pas autorisées (throw FatalErrorException)
116 void addEdge(const VertexType& source_vertex, const VertexType& target_vertex, const EdgeType& source_to_target_edge)
117 {
118 _addEdge(source_vertex,target_vertex,source_to_target_edge);
119 }
120
121 void addEdge(VertexType&& source_vertex, VertexType&& target_vertex, EdgeType&& source_to_target_edge)
122 {
123 _addEdge(source_vertex,target_vertex,source_to_target_edge);
124 }
125
126 template <class Vertex, class Edge>
127 void _addEdge(Vertex source_vertex, Vertex target_vertex, Edge source_to_target_edge)
128 {
129 bool has_edge = (_getEdgeIndex(source_vertex,target_vertex).first != -1 || m_edge_to_vertex_map.find(source_to_target_edge) != m_edge_to_vertex_map.end());
130 if (has_edge) throw FatalErrorException("Cannot insert existing edge."); // TODO print edge and vertices values if possible (enable_if)
131 m_edges.push_back(source_to_target_edge);
132 EdgeType& inserted_edge = m_edges.back(); // Get a reference to the inserted objects (since objects are only stored in list, other structures handle references)
133 VertexType& inserted_source_vertex = _addVertex(source_vertex);
134 VertexType& inserted_target_vertex = _addVertex(target_vertex);
135 // Fill adjacency map [source_vertex] = pair<TargetVertexArray,EdgeArray>
136 auto adjacency_entry = m_adjacency_list[inserted_source_vertex];
137 adjacency_entry.first.push_back(inserted_target_vertex);
138 adjacency_entry.second.push_back(inserted_edge);
139 // Fill transposed adjacency map [target_vertex] = pair<SourceVertexArray,EdgeArray>
140 auto transposed_adjacency_entry = m_adjacency_list_transposed[inserted_target_vertex];
141 transposed_adjacency_entry.first.push_back(inserted_source_vertex);
142 transposed_adjacency_entry.second.push_back(inserted_edge);
143 // Fill edge map [edge] = pair <Vertex,Vertex>
144 m_edge_to_vertex_map.insert(std::make_pair(std::ref(inserted_edge),std::make_pair(std::ref(inserted_source_vertex),std::ref(inserted_target_vertex))));
145 // c'est moche mais on ne peut pas utiliser [] de la map avec reference_wrapper (not default constructible) ni utiliser emplace (pas supporté dans gcc 4.7.2
146// m_edge_to_vertex_map.emplace(std::cref(inserted_edge),std::make_pair(inserted_source_vertex,inserted_target_vertex)); // No Gcc 4,7,2
147 }
148
149 //! Renvoie un pointeur vers l'instance d'EdgeType stockée dans le graphe ou nullptr si non trouvé.
150 EdgeType* getEdge(const VertexType& source_vertex, const VertexType& target_vertex)
151 {
152 return _getEdge(source_vertex,target_vertex);
153 }
154
155 //! Renvoie un pointeur vers l'instance d'EdgeType stockée dans le graphe ou nullptr si non trouvé.
156 const EdgeType* getEdge(const VertexType& source_vertex, const VertexType& target_vertex) const
157 {
158 return _getEdge(source_vertex,target_vertex);
159 }
160
161 EdgeType* _getEdge(const VertexType& source_vertex, const VertexType& target_vertex)
162 {
163 Integer edge_index;
164 EdgeTypeRefArray edge_array;
165 std::tie(edge_index,edge_array) = _getEdgeIndex(source_vertex,target_vertex);
166 if (edge_index == -1) return nullptr;
167 else return &edge_array[edge_index].get();
168 }
169
170 // Implémenter in_edges(vertex) et out_edges(vertex) avec un itérateur...puis edges() et vertices()
171
172 VertexType* getSourceVertex(const EdgeType& edge)
173 {
174 typename EdgeToVertexMap::iterator edge_entry = m_edge_to_vertex_map.find(edge);
175 if (edge_entry != m_edge_to_vertex_map.end()) return &(edge_entry->second.first.get());
176 else return nullptr;
177 }
178
179 const VertexType* getSourceVertex(const EdgeType& edge) const
180 {
181 auto edge_entry = m_edge_to_vertex_map.find(edge);
182 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.first.get();
183 else return nullptr;
184 }
185
186 VertexType* getTargetVertex(const EdgeType& edge)
187 {
188 auto edge_entry = m_edge_to_vertex_map.find(edge);
189 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.second.get();
190 else return nullptr;
191 }
192
193 const VertexType* getTargetVertex(const EdgeType& edge) const
194 {
195 auto edge_entry = m_edge_to_vertex_map.find(edge);
196 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.second.get();
197 else return nullptr;
198 }
199
200 VertexSet vertices() {return VertexSet(m_vertices);}
201 EdgeSet edges() {return EdgeSet(m_edges);}
202
203 ConnectedEdgeSet inEdges(const VertexType& vertex)
204 {
205 auto found_vertex = m_adjacency_list_transposed.find(vertex);
206 if (found_vertex == m_adjacency_list_transposed.end())
207 {
208 return ConnectedEdgeSet();
209 }
210 else return ConnectedEdgeSet(found_vertex->second.second); // map <vertex, pair <VertexArray, EdgeArray> >
211 }
212
213 ConnectedEdgeSet outEdges(const VertexType& vertex)
214 {
215 auto found_vertex = m_adjacency_list.find(vertex);
216 if (found_vertex == m_adjacency_list.end())
217 {
218 return ConnectedEdgeSet();
219 }
220 else return ConnectedEdgeSet(found_vertex->second.second); // map <vertex, pair <VertexArray, EdgeArray> >
221 }
222
223protected:
224 ITraceMng* m_trace_mng;
225 VertexList m_vertices;
226 EdgeList m_edges;
227 AdjacencyListType m_adjacency_list; //! source_vertex -> target_vertices
228 AdjacencyListType m_adjacency_list_transposed; //! target_vertex -> source_vertices
229 EdgeToVertexMap m_edge_to_vertex_map;
230
231private:
232
233 template <class Vertex>
234 VertexType& _addVertex(Vertex vertex) // to handle _add(VertexType&) et _add(VertexType&&)
235 {
236 // Look up if vertex does exist
237 auto found_vertex = std::find_if(m_vertices.begin(), m_vertices.end(), [&vertex](const VertexType& u){return (!(u < vertex) && !(vertex < u));}); // Unary predicate used to avoid contraining VertexObject to be Equality Comparable objects
238 if (found_vertex == m_vertices.end()) // Vertex does not exist
239 {
240 m_vertices.push_back(vertex);
241 return m_vertices.back();
242 }
243 else return *found_vertex;
244 }
245
246 template <class Vertex> // to handle Vertex&& et Vertex& = another way to do so ?
247 std::pair<Integer,EdgeTypeRefArray> _getEdgeIndex(Vertex source_vertex, Vertex target_vertex)
248 {
249 typename AdjacencyListType::iterator found_source_vertex = m_adjacency_list.find(source_vertex);
250 if (found_source_vertex == m_adjacency_list.end()) return std::make_pair(-1,EdgeTypeRefArray());
251 Integer target_vertex_index = _getTargetVertexIndex(found_source_vertex,target_vertex);
252 return std::make_pair(target_vertex_index,found_source_vertex->second.second); // pair < u, pair <[u], [u_v] > >...Use get<T> with pair when available to improve readability
253 }
254
255 template <class Vertex> // c'est contagieux...
256 Integer _getTargetVertexIndex(typename AdjacencyListType::iterator source_vertex_map_entry, Vertex target_vertex)
257 {
258 if (source_vertex_map_entry == m_adjacency_list.end()) return -1;
259 return _getConnectedVertexIndex(source_vertex_map_entry,target_vertex);
260 }
261
262 template <class Vertex> // c'est contagieux...
263 Integer _getConnectedVertexIndex(typename AdjacencyListType::iterator vertex_map_entry, Vertex connected_vertex)
264 {
265 VertexTypeRefArray& vertex_array = vertex_map_entry->second.first;
266 Int32UniqueArray indexes(vertex_array.size());
267 std::iota(indexes.begin(),indexes.end(),0);
268 auto connected_vertex_index = std::find_if(indexes.begin(), indexes.end(),
269 [&](const Integer index) {return (!(vertex_array[index] < connected_vertex) && !(connected_vertex < vertex_array[index]));} );
270 if (connected_vertex_index == indexes.end()) return -1;
271 else return *connected_vertex_index;
272 }
273
274};
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
278
279ARCANE_END_NAMESPACE
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284#endif /* GRAPHBASET_H_ */
Fichier de configuration d'Arcane.
void addEdge(const VertexType &source_vertex, const VertexType &target_vertex, const EdgeType &source_to_target_edge)
Les arêtes multiples (constituées des mêmes noeuds source et target) ne sont pas autorisées (throw Fa...
Definition GraphBaseT.h:116
virtual ~GraphBaseT()
Definition GraphBaseT.h:57
AdjacencyListType m_adjacency_list_transposed
source_vertex -> target_vertices
Definition GraphBaseT.h:228
GraphBaseT(ITraceMng *trace_mng)
Definition GraphBaseT.h:52
EdgeToVertexMap m_edge_to_vertex_map
target_vertex -> source_vertices
Definition GraphBaseT.h:229
EdgeType * getEdge(const VertexType &source_vertex, const VertexType &target_vertex)
Renvoie un pointeur vers l'instance d'EdgeType stockée dans le graphe ou nullptr si non trouvé.
Definition GraphBaseT.h:150
const EdgeType * getEdge(const VertexType &source_vertex, const VertexType &target_vertex) const
Renvoie un pointeur vers l'instance d'EdgeType stockée dans le graphe ou nullptr si non trouvé.
Definition GraphBaseT.h:156
Interface du gestionnaire de traces.
Vecteur 1D de données avec sémantique par référence.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
Int32 Integer
Type représentant un entier.