GraphDom
Loading...
Searching...
No Matches
full_labeled_multiset_ugraph.h
1/*
2 * Copyright 2026 Michele Comparini
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef GRAPHDOM_FULL_LABELED_MULTISET_UGRAPH_IMPL_H
8#define GRAPHDOM_FULL_LABELED_MULTISET_UGRAPH_IMPL_H
9
10#include "../full_labeled_multiset_ugraph.h"
11
12template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
15labeled_vertex_multiset_graph<VertexType,VertexLabelType,VertexLabellerType>(),
16labeled_edge_non_mixed_graph<VertexType,EdgeLabelType,EdgeLabellerType>(),
17number_of_vertices_inserted(0) {}
18
19template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
21full_labeled_multiset_ugraph(const VertexLabellerType& v_lab, const EdgeLabellerType& e_lab) :
22labeled_vertex_multiset_graph<VertexType,VertexLabelType,VertexLabellerType>(v_lab),
23labeled_edge_non_mixed_graph<VertexType,EdgeLabelType,EdgeLabellerType>(e_lab),
24number_of_vertices_inserted(0) {}
25
26template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
28full_labeled_multiset_ugraph(const VertexLabellerType& v_lab, EdgeLabellerType&& e_lab) :
29labeled_vertex_multiset_graph<VertexType,VertexLabelType,VertexLabellerType>(v_lab),
30labeled_edge_non_mixed_graph<VertexType,EdgeLabelType,EdgeLabellerType>(std::move(e_lab)),
31number_of_vertices_inserted(0) {}
32
33template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
35full_labeled_multiset_ugraph(VertexLabellerType&& v_lab, const EdgeLabellerType& e_lab) :
36labeled_vertex_multiset_graph<VertexType,VertexLabelType,VertexLabellerType>(std::move(v_lab)),
37labeled_edge_non_mixed_graph<VertexType,EdgeLabelType,EdgeLabellerType>(e_lab),
38number_of_vertices_inserted(0) {}
39
40template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
42full_labeled_multiset_ugraph(VertexLabellerType&& v_lab, EdgeLabellerType&& e_lab) :
43labeled_vertex_multiset_graph<VertexType,VertexLabelType,VertexLabellerType>(std::move(v_lab)),
44labeled_edge_non_mixed_graph<VertexType,EdgeLabelType,EdgeLabellerType>(std::move(e_lab)),
45number_of_vertices_inserted(0) {}
46
47template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
48graphdom::full_labeled_multiset_ugraph<VertexType,VertexLabelType,EdgeLabelType,VertexLabellerType,EdgeLabellerType>::~full_labeled_multiset_ugraph() {
49 while ( ! vertices.empty() ) {
50 auto& vertex_to_erase = vertices.front();
51 auto& vertex_to_erase_adj = vertex_to_erase.adj;
52 for (auto edge_endpoint_to_deallocate = vertex_to_erase_adj.begin();
53 edge_endpoint_to_deallocate != vertex_to_erase_adj.end();
54 ++edge_endpoint_to_deallocate) {
55 safe_edge_endpoint_deallocation(*edge_endpoint_to_deallocate); // This is to avoid memory leaks
56 }
57 vertices.pop_front();
58 }
59}
60
61template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
65
66template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
68 const typename graph<VertexType>::vertex_const_handle& vertex) const {
69 if ( graphdom::graph<VertexType>::get_owner_graph(vertex) != this ) {
70 throw std::runtime_error("Error"); //TODO: write a better message
71 }
72 const auto* const vertex_container_ptr = static_cast< const vertex_container* >( graphdom::graph< VertexType >::get_vertex_container( vertex ) );
73 return vertex_container_ptr->vertex_label;
74}
75
76template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
78const typename graph<VertexType>::adj_list_const_iterator& edge) const {
79 if ( graphdom::graph<VertexType>::get_owner_graph( edge ) != this ) {
80 throw std::runtime_error("Error"); //TODO: write a better message
81 }
82 return
83 *(
84 (
85 *(
86 static_cast<edge_endpoint*>(
88 )
89 )
90 ).edge_label_ptr
91 );
92}
93
94template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
97 if( graphdom::graph<VertexType>::get_owner_graph(vertex) == this ) {
98 const auto vertex_container_to_erase_ptr = graphdom::graph<VertexType>::get_vertex_container(vertex);
99 if ( vertex_container_to_erase_ptr != nullptr ) {
100 for(auto vertices_itr = vertices.before_begin(); vertices_itr != vertices.end(); ++vertices_itr) {
101 auto vertices_itr_next = std::next(vertices_itr);
102 if( vertices_itr_next != vertices.end() ){
103 if( ( &( *vertices_itr_next ) ) == vertex_container_to_erase_ptr ){
104 auto& vertex_container_to_erase_adj = ( *vertices_itr_next ).adj;
105 for (auto vertex_container_to_erase_adj_itr = vertex_container_to_erase_adj.begin();
106 vertex_container_to_erase_adj_itr != vertex_container_to_erase_adj.end();
107 ++vertex_container_to_erase_adj_itr) {
108 const auto& edge_endpoint_vertex_container =
109 *(
110 static_cast< const vertex_container* >(
111 (
112 *(
113 *(
114 vertex_container_to_erase_adj_itr
115 )
116 )
117 ).vertex_container_ptr
118 )
119 );
120 if ( ( &edge_endpoint_vertex_container ) != vertex_container_to_erase_ptr ) { //The edge could be a loop
121 auto& edge_endpoint_vertex_container_adj = edge_endpoint_vertex_container.adj;
122 const auto vertex_container_to_erase_founded_in_edge_endpoint_vertex_container_adj =
123 edge_endpoint_vertex_container_adj.find( vertex_container_to_erase_ptr );
124 safe_edge_endpoint_deallocation( *vertex_container_to_erase_founded_in_edge_endpoint_vertex_container_adj );
125 edge_endpoint_vertex_container_adj.erase( vertex_container_to_erase_founded_in_edge_endpoint_vertex_container_adj );
126 }
127 safe_edge_endpoint_deallocation( *vertex_container_to_erase_adj_itr );
128 }
129 vertices.erase_after( vertices_itr );
130 --number_of_vertices_inserted;
131 break;
132 }
133 }
134 }
135 //TODO:: Evaluate a possible exception throw HERE
136 }
137 //TODO:: Evaluate a possible exception throw HERE
138 }
139 //TODO:: Evaluate a possible exception throw HERE
140}
141
142template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
143typename graphdom::graph<VertexType>::adj_list_iterator
145 const typename graph<VertexType>::adj_list_const_iterator& edge_itr) {
146 if ( graphdom::graph<VertexType>::get_owner_graph(edge_itr) != this ) {
147 throw std::runtime_error("Error"); //TODO: write a better message
148 }
149 auto const edge_itr_begin_point = const_cast< vertex_container* >( static_cast< const vertex_container* >( graphdom::graph<VertexType>::get_begin_point(edge_itr) ) );
150 auto inner_iterator_of_begin_point_adj = graphdom::multiset_graph<VertexType>::get_inner_iterator( edge_itr );
151 auto const edge_itr_endpoint = static_cast< vertex_container* >( ( *( *inner_iterator_of_begin_point_adj ) ).vertex_container_ptr );
152 if ( edge_itr_begin_point != edge_itr_endpoint ) { //The edge could be a loop
153 auto inner_iterator_of_end_point_adj = ( (*edge_itr_endpoint).adj ).find( edge_itr_begin_point );
154 safe_edge_endpoint_deallocation(*inner_iterator_of_end_point_adj);
155 ( (*edge_itr_endpoint).adj ).erase( inner_iterator_of_end_point_adj );
156 }
157 safe_edge_endpoint_deallocation(*inner_iterator_of_begin_point_adj);
159 this,
160 edge_itr_begin_point,
162 ( (*edge_itr_begin_point).adj ).erase( inner_iterator_of_begin_point_adj )
163 );
164}
165
166template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
168 const typename graph<VertexType>::vertex_const_handle& vertex) {
169 if ( graphdom::graph<VertexType>::get_owner_graph(vertex) != this ) {
170 throw std::runtime_error("Error"); //TODO: write a better message
171 }
172 const auto* const vertex_container_ptr = static_cast< const vertex_container* >( graphdom::graph< VertexType >::get_vertex_container( vertex ) );
173 return const_cast< VertexLabelType& >( (*vertex_container_ptr).vertex_label );
174}
175
176template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
179 const VertexType& v_core, const VertexLabelType& vertex_label) {
180 vertices.emplace_front(
181 v_core,
182 vertex_label
183 );
184 ++number_of_vertices_inserted;
186 this,
187 vertices.front(),
189 );
190}
191
192template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
195const VertexType& v_core, VertexLabelType&& vertex_label) {
196 vertices.emplace_front(
197 v_core,
198 std::move(vertex_label)
199 );
200 ++number_of_vertices_inserted;
202 this,
203 vertices.front(),
205 );
206}
207
208template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
211VertexType&& v_core, const VertexLabelType& vertex_label) {
212 vertices.emplace_front(
213 std::move(v_core),
214 vertex_label
215 );
216 ++number_of_vertices_inserted;
218 this,
219 vertices.front(),
221 );
222}
223
224template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
227VertexType&& v_core, VertexLabelType&& vertex_label) {
228 vertices.emplace_front(
229 std::move(v_core),
230 std::move(vertex_label)
231 );
232 ++number_of_vertices_inserted;
234 this,
235 vertices.front(),
237 );
238}
239
240template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
242 const typename graph<VertexType>::adj_list_const_iterator& edge ) {
243 if ( graphdom::graph<VertexType>::get_owner_graph( edge ) != this ) {
244 throw std::runtime_error("Error"); //TODO: write a better message
245 }
246 return
247 *(
248 (
249 *(
250 static_cast<edge_endpoint*>(
252 )
253 )
254 ).edge_label_ptr
255 );
256}
257
258template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
260 const typename graph<VertexType>::vertex_const_handle& first_endpoint,
261 const typename graph<VertexType>::vertex_const_handle& second_endpoint,
262 const EdgeLabelType& edge_label) {
263 if (
264 graphdom::graph<VertexType>::get_owner_graph( first_endpoint ) != this ||
265 graphdom::graph<VertexType>::get_owner_graph( second_endpoint ) != this
266 ) {
267 throw std::runtime_error("Error"); //TODO: write a better message
268 }
269 auto const begin_point_vertex_container = const_cast< vertex_container* >( static_cast< const vertex_container* >( graphdom::graph<VertexType>::get_vertex_container( first_endpoint ) ) );
270 auto const end_point_vertex_container = const_cast< vertex_container* >( static_cast< const vertex_container* >( graphdom::graph<VertexType>::get_vertex_container( second_endpoint ) ) );
271 if ( begin_point_vertex_container == nullptr || end_point_vertex_container == nullptr ) {
272 throw std::runtime_error("Error"); //TODO: write a better message
273 }
274 std::unique_ptr< edge_endpoint > edge_endpoint_to_insert_in_begin_point_adj( new edge_endpoint( end_point_vertex_container , edge_label ) );
275 const auto inner_insertion_result_in_begin_point_adj = ( begin_point_vertex_container->adj ).insert( edge_endpoint_to_insert_in_begin_point_adj.get() );
276 if ( inner_insertion_result_in_begin_point_adj.second ) {
277 edge_endpoint_to_insert_in_begin_point_adj.release();
278 if ( begin_point_vertex_container != end_point_vertex_container ) { //The edge could be a loop
279 std::unique_ptr< edge_endpoint > edge_endpoint_to_insert_in_end_point_adj(
280 new edge_endpoint(
281 begin_point_vertex_container ,
282 ( static_cast< edge_endpoint* >( *( inner_insertion_result_in_begin_point_adj.first ) ) )->edge_label_ptr
283 )
284 );
285 const auto inner_insertion_result_in_end_point_adj = ( ( end_point_vertex_container->adj ).insert( edge_endpoint_to_insert_in_end_point_adj.get() ) ).second;
286 if ( inner_insertion_result_in_end_point_adj ) {
287 edge_endpoint_to_insert_in_end_point_adj.release();
288 }
289 else {
290 safe_edge_endpoint_deallocation( *( inner_insertion_result_in_begin_point_adj.first ) );
291 ( begin_point_vertex_container->adj ).erase( inner_insertion_result_in_begin_point_adj.first );
292 }
293 }
294 }
295}
296
297template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
299 const typename graph<VertexType>::vertex_const_handle& first_endpoint,
300 const typename graph<VertexType>::vertex_const_handle& second_endpoint,
301 EdgeLabelType&& edge_label) {
302 if (
303 graphdom::graph<VertexType>::get_owner_graph( first_endpoint ) != this ||
304 graphdom::graph<VertexType>::get_owner_graph( second_endpoint ) != this
305 ) {
306 throw std::runtime_error("Error"); //TODO: write a better message
307 }
308 auto const begin_point_vertex_container = const_cast< vertex_container* >( static_cast< const vertex_container* >( graphdom::graph<VertexType>::get_vertex_container( first_endpoint ) ) );
309 auto const end_point_vertex_container = const_cast< vertex_container* >( static_cast< const vertex_container* >( graphdom::graph<VertexType>::get_vertex_container( second_endpoint ) ) );
310 if ( begin_point_vertex_container == nullptr || end_point_vertex_container == nullptr ) {
311 throw std::runtime_error("Error"); //TODO: write a better message
312 }
313 const auto lower_bound = ( begin_point_vertex_container->adj ).lower_bound( end_point_vertex_container );
314 if ( lower_bound == ( begin_point_vertex_container->adj ).cend() ) {
315 const auto first_insertion_itr = ( begin_point_vertex_container->adj ).emplace_hint( lower_bound, new edge_endpoint( end_point_vertex_container , std::move(edge_label) ) );
316 if ( begin_point_vertex_container != end_point_vertex_container ) { //The edge could be a loop
317 ( end_point_vertex_container->adj ).emplace( new edge_endpoint( begin_point_vertex_container, static_cast< const edge_endpoint* >( *first_insertion_itr )->edge_label_ptr ) );
318 }
319 }
320 else {
321 if ( ( ( begin_point_vertex_container->adj ).key_comp() )( end_point_vertex_container, *lower_bound ) ) {
322 const auto first_insertion_itr = ( begin_point_vertex_container->adj ).emplace_hint( lower_bound, new edge_endpoint( end_point_vertex_container , std::move(edge_label) ) );
323 if ( begin_point_vertex_container != end_point_vertex_container ) { //The edge could be a loop
324 ( end_point_vertex_container->adj ).emplace( new edge_endpoint( begin_point_vertex_container, static_cast< const edge_endpoint* >( *first_insertion_itr )->edge_label_ptr ) );
325 }
326 }
327 }
328 /*
329 std::unique_ptr< edge_endpoint > edge_endpoint_to_insert_in_begin_point_adj( new edge_endpoint( end_point_vertex_container , std::move(edge_label_to_insert) ) );
330 const auto inner_insertion_result_in_begin_point_adj = ( begin_point_vertex_container->adj ).insert( edge_endpoint_to_insert_in_begin_point_adj.get() );
331 if ( inner_insertion_result_in_begin_point_adj.second ) {
332 edge_endpoint_to_insert_in_begin_point_adj.release();
333 if ( begin_point_vertex_container != end_point_vertex_container ) { //The edge could be a loop
334 std::unique_ptr< edge_endpoint > edge_endpoint_to_insert_in_end_point_adj(
335 new edge_endpoint(
336 begin_point_vertex_container ,
337 ( static_cast< edge_endpoint* >( *( inner_insertion_result_in_begin_point_adj.first ) ) )->edge_label_ptr
338 )
339 );
340 const auto inner_insertion_result_in_end_point_adj = ( ( end_point_vertex_container->adj ).insert( edge_endpoint_to_insert_in_end_point_adj.get() ) ).second;
341 if ( inner_insertion_result_in_end_point_adj ) {
342 edge_endpoint_to_insert_in_end_point_adj.release();
343 }
344 else {
345 safe_edge_endpoint_deallocation( *( inner_insertion_result_in_begin_point_adj.first ) );
346 ( begin_point_vertex_container->adj ).erase( inner_insertion_result_in_begin_point_adj.first );
347 }
348 }
349 }
350 */
351}
352
353template<typename VertexType, typename VertexLabelType, typename EdgeLabelType, typename VertexLabellerType, typename EdgeLabellerType>
356 typename graphdom::graph<VertexType>::template edge_endpoint<VertexContainerPointerType>* ee_ptr) {
357 delete static_cast<edge_endpoint*>(ee_ptr);
358}
359
360#endif //GRAPHDOM_FULL_LABELED_MULTISET_UGRAPH_IMPL_H
Definition full_labeled_multiset_ugraph.h:35
const VertexLabelType & get_vertex_label(const typename graph< VertexType >::vertex_const_handle &vertex) const override
Definition full_labeled_multiset_ugraph.h:67
multiset_graph< VertexType >::vertex_handle insert_vertex(const VertexType &v_core, const VertexLabelType &vertex_label) override
Definition full_labeled_multiset_ugraph.h:178
const EdgeLabelType & get_edge_label(const typename graph< VertexType >::adj_list_const_iterator &) const override
Definition full_labeled_multiset_ugraph.h:77
void insert_edge(const typename graph< VertexType >::vertex_const_handle &first_endpoint, const typename graph< VertexType >::vertex_const_handle &second_endpoint, const EdgeLabelType &edge_label) override
Definition full_labeled_multiset_ugraph.h:259
std::size_t order() const override
Returns the order of *this, i.e. the number of vertices inside the graph.
Definition full_labeled_multiset_ugraph.h:62
graphdom::graph< VertexType >::adj_list_iterator erase_edge(const typename graph< VertexType >::adj_list_const_iterator &) override
Definition full_labeled_multiset_ugraph.h:144
void erase_vertex(const typename graphdom::graph< VertexType >::vertex_const_handle &vertex) override
Removes the vertex identified by vertex.
Definition full_labeled_multiset_ugraph.h:95
Every valid instance of this class can be used to identify a specific vertex of a graph and to access...
Definition vertex_const_handle.h:35
Every graph created using this library is an instance of a concrete class publicly derived,...
Definition graph.h:43
Every valid instance of this class can be used to identify a specific vertex of a multiset graph and ...
Definition multiset_graph_vertex_handle.h:31
Every multiset graph created using this library is an instance of a concrete class publicly derived,...
Definition multiset_graph.h:19
@ undirected
This enum value means undirected edge.
Definition graph.h:22