Arcane  v3.15.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
GraphBaseT.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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-2024 */
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/*---------------------------------------------------------------------------*/
44// TODO EdgeType = void (default)
45// TODO add a template argument Comparator = std::less
46template <class VertexType, class EdgeType>
48{
49protected:
50
53 : m_trace_mng(trace_mng)
54 {}
55
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;
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
107
108private:
109
110 bool isNull(EdgeType const& edge)
111 {
112 if (std::is_pointer_v<EdgeType> && edge == nullptr) return true;
113 else return false;
114 }
115public:
116
117 typedef VertexType VertexRef;
118 typedef EdgeType EdgeRef;
119
120 // TODO Array de reference_wrapper ne fonctionne pas ...car il fait des T()...voir avec std::vector...
121
127
129 {
131 }
132
133 template <class Vertex, class Edge>
134 void _addEdge(Vertex source_vertex, Vertex target_vertex, Edge source_to_target_edge)
135 {
136 bool has_edge = (_getEdgeIndex(source_vertex,target_vertex).first != -1 ||
137 m_edge_to_vertex_map.find(source_to_target_edge) != m_edge_to_vertex_map.end() && !isNull(source_to_target_edge));
138 if (has_edge) throw FatalErrorException("Cannot insert existing edge."); // TODO print edge and vertices values if possible (enable_if)
139 m_edges.push_back(source_to_target_edge);
140 EdgeType& inserted_edge = m_edges.back(); // Get a reference to the inserted objects (since objects are only stored in list, other structures handle references)
141 VertexType& inserted_source_vertex = _addVertex(source_vertex);
142 VertexType& inserted_target_vertex = _addVertex(target_vertex);
143 // Fill adjacency map [source_vertex] = pair<TargetVertexArray,EdgeArray>
144 auto adjacency_entry = m_adjacency_list[inserted_source_vertex];
145 adjacency_entry.first.push_back(inserted_target_vertex);
146 adjacency_entry.second.push_back(inserted_edge);
147 // Fill transposed adjacency map [target_vertex] = pair<SourceVertexArray,EdgeArray>
148 auto transposed_adjacency_entry = m_adjacency_list_transposed[inserted_target_vertex];
149 transposed_adjacency_entry.first.push_back(inserted_source_vertex);
150 transposed_adjacency_entry.second.push_back(inserted_edge);
151 // Fill edge map [edge] = pair <Vertex,Vertex>
152 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))));
153 // 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
154// m_edge_to_vertex_map.emplace(std::cref(inserted_edge),std::make_pair(inserted_source_vertex,inserted_target_vertex)); // No Gcc 4,7,2
155 }
156
162
165 {
166 return _getEdge(source_vertex,target_vertex);
167 }
168
170 {
171 Integer edge_index;
172 EdgeTypeRefArray edge_array;
173 std::tie(edge_index,edge_array) = _getEdgeIndex(source_vertex,target_vertex);
174 if (edge_index == -1) return nullptr;
175 else return &edge_array[edge_index].get();
176 }
177
178 // Implémenter in_edges(vertex) et out_edges(vertex) avec un itérateur...puis edges() et vertices()
179
180 VertexType* getSourceVertex(const EdgeType& edge)
181 {
182 typename EdgeToVertexMap::iterator edge_entry = m_edge_to_vertex_map.find(edge);
183 if (edge_entry != m_edge_to_vertex_map.end()) return &(edge_entry->second.first.get());
184 else return nullptr;
185 }
186
187 const VertexType* getSourceVertex(const EdgeType& edge) const
188 {
189 auto edge_entry = m_edge_to_vertex_map.find(edge);
190 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.first.get();
191 else return nullptr;
192 }
193
194 VertexType* getTargetVertex(const EdgeType& edge)
195 {
196 auto edge_entry = m_edge_to_vertex_map.find(edge);
197 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.second.get();
198 else return nullptr;
199 }
200
201 const VertexType* getTargetVertex(const EdgeType& edge) const
202 {
203 auto edge_entry = m_edge_to_vertex_map.find(edge);
204 if (edge_entry != m_edge_to_vertex_map.end()) return &edge_entry->second.second.get();
205 else return nullptr;
206 }
207
208 VertexSet vertices() {return VertexSet(m_vertices);}
209 EdgeSet edges() {return EdgeSet(m_edges);}
210
211 ConnectedEdgeSet inEdges(const VertexType& vertex)
212 {
213 auto found_vertex = m_adjacency_list_transposed.find(vertex);
214 if (found_vertex == m_adjacency_list_transposed.end())
215 {
216 return ConnectedEdgeSet();
217 }
218 else return ConnectedEdgeSet(found_vertex->second.second); // map <vertex, pair <VertexArray, EdgeArray> >
219 }
220
221 ConnectedEdgeSet outEdges(const VertexType& vertex)
222 {
223 auto found_vertex = m_adjacency_list.find(vertex);
224 if (found_vertex == m_adjacency_list.end())
225 {
226 return ConnectedEdgeSet();
227 }
228 else return ConnectedEdgeSet(found_vertex->second.second); // map <vertex, pair <VertexArray, EdgeArray> >
229 }
230
231protected:
232 ITraceMng* m_trace_mng;
233 VertexList m_vertices;
234 EdgeList m_edges;
235 AdjacencyListType m_adjacency_list;
236 AdjacencyListType m_adjacency_list_transposed;
237 EdgeToVertexMap m_edge_to_vertex_map;
238
239private:
240
241 template <class Vertex>
242 VertexType& _addVertex(Vertex vertex) // to handle _add(VertexType&) et _add(VertexType&&)
243 {
244 // Look up if vertex does exist
245 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
246 if (found_vertex == m_vertices.end()) // Vertex does not exist
247 {
248 m_vertices.push_back(vertex);
249 return m_vertices.back();
250 }
251 else return *found_vertex;
252 }
253
254 template <class Vertex> // to handle Vertex&& et Vertex& = another way to do so ?
255 std::pair<Integer,EdgeTypeRefArray> _getEdgeIndex(Vertex source_vertex, Vertex target_vertex)
256 {
257 typename AdjacencyListType::iterator found_source_vertex = m_adjacency_list.find(source_vertex);
258 if (found_source_vertex == m_adjacency_list.end()) return std::make_pair(-1,EdgeTypeRefArray());
259 Integer target_vertex_index = _getTargetVertexIndex(found_source_vertex,target_vertex);
260 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
261 }
262
263 template <class Vertex> // c'est contagieux...
264 Integer _getTargetVertexIndex(typename AdjacencyListType::iterator source_vertex_map_entry, Vertex target_vertex)
265 {
266 if (source_vertex_map_entry == m_adjacency_list.end()) return -1;
267 return _getConnectedVertexIndex(source_vertex_map_entry,target_vertex);
268 }
269
270 template <class Vertex> // c'est contagieux...
271 Integer _getConnectedVertexIndex(typename AdjacencyListType::iterator vertex_map_entry, Vertex connected_vertex)
272 {
273 VertexTypeRefArray& vertex_array = vertex_map_entry->second.first;
274 Int32UniqueArray indexes(vertex_array.size());
275 std::iota(indexes.begin(),indexes.end(),0);
276 auto connected_vertex_index = std::find_if(indexes.begin(), indexes.end(),
277 [&](const Integer index) {return (!(vertex_array[index] < connected_vertex) && !(connected_vertex < vertex_array[index]));} );
278 if (connected_vertex_index == indexes.end()) return -1;
279 else return *connected_vertex_index;
280 }
281
282};
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
287ARCANE_END_NAMESPACE
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
292#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:123
virtual ~GraphBaseT()
Definition GraphBaseT.h:57
AdjacencyListType m_adjacency_list_transposed
source_vertex -> target_vertices
Definition GraphBaseT.h:236
GraphBaseT(ITraceMng *trace_mng)
Definition GraphBaseT.h:52
EdgeToVertexMap m_edge_to_vertex_map
target_vertex -> source_vertices
Definition GraphBaseT.h:237
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:158
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:164
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Interface du gestionnaire de traces.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:552
Int32 Integer
Type représentant un entier.