Skip to content

Instantly share code, notes, and snippets.

@Hermann-SW
Created November 9, 2024 16:38
Show Gist options
  • Save Hermann-SW/539d2396e567a2ee26f4e0213f3b5fe7 to your computer and use it in GitHub Desktop.
Save Hermann-SW/539d2396e567a2ee26f4e0213f3b5fe7 to your computer and use it in GitHub Desktop.
Demonstration of Boost O(1) remove_edge() in class derived from "edge_index_update_visitor"
//=======================================================================
// Copyright 2024
// Author: Hermann Stamm-Wilbrandt
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include <iostream>
#include <boost/graph/undirected_graph.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/planar_detail/add_edge_visitors.hpp>
using namespace boost;
template < typename EdgeIndexMap, typename Graph > struct o1_edge_visitor
: edge_index_update_visitor< EdgeIndexMap >
{
typedef
typename property_traits< EdgeIndexMap >::value_type edge_index_value_t;
typedef
typename graph_traits< Graph >::out_edge_iterator out_edge_iterator;
typedef
typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
typedef
typename graph_traits< Graph >::edge_descriptor edge_descriptor;
typedef
edge_index_update_visitor< EdgeIndexMap > edge_index_update_visitor_t;
o1_edge_visitor(
EdgeIndexMap em, edge_index_value_t next_index_available, Graph)
: edge_index_update_visitor_t::edge_index_update_visitor(
em, next_index_available),
m_em(em)
{
}
explicit o1_edge_visitor(Graph g)
: o1_edge_visitor(get(edge_index, g), num_edges(g), g)
{
}
void visit_vertex_pair(vertex_descriptor u, vertex_descriptor v, Graph& g)
{
edge_index_update_visitor_t::visit_vertex_pair(u, v, g);
storage.push_back(
std::make_pair(
--(out_edges(u, g).second), // std::prev() hangs
--(out_edges(v, g).second)));
}
// O(1)
void visit_edge(edge_descriptor e, Graph& g)
{
auto it_to_front = [](out_edge_iterator it, Graph& g)
{
auto &L = g.impl().out_edge_list(it.m_src);
L.splice(L.begin(), L, it.base());
};
it_to_front(storage[m_em[e]].first, g);
it_to_front(storage[m_em[e]].second, g);
boost::remove_edge(e, g);
}
private:
EdgeIndexMap m_em;
std::vector< std::pair< out_edge_iterator, out_edge_iterator > > storage;
};
int main(int, char*[]) {
typedef undirected_graph<> ugraph;
typedef ugraph::vertex_descriptor vertex_descriptor;
typedef ugraph::edge_descriptor edge_descriptor;
typedef boost::property_map< ugraph, boost::edge_index_t >::type
EdgeIndexMap;
int n = 5;
ugraph U;
o1_edge_visitor< EdgeIndexMap, ugraph > vis(U);
std::vector< vertex_descriptor > V(n);
for (int i = 0; i < n; ++i) { V[i] = add_vertex(U); }
std::cout << num_vertices(U) << std::endl;
vis.visit_vertex_pair(V[0], V[1], U);
vis.visit_vertex_pair(V[1], V[2], U);
vis.visit_vertex_pair(V[2], V[3], U);
vis.visit_vertex_pair(V[3], V[0], U);
vis.visit_vertex_pair(V[0], V[2], U);
print_graph(U);
std::cout << num_edges(U) << std::endl;
edge_descriptor e = *(--edges(U).second);
vis.visit_edge(e, U);
print_graph(U);
std::cout << num_edges(U) << std::endl;
return 0;
}
@Hermann-SW
Copy link
Author

hermann@7600x:~$ g++ -Wall -Wextra -pedantic o1_edge_visitor.cpp
hermann@7600x:~$ ./a.out 
5
0 <--> 1 3 2 
1 <--> 0 2 
2 <--> 1 3 0 
3 <--> 2 0 
4 <--> 
5
0 <--> 1 3 
1 <--> 0 2 
2 <--> 1 3 
3 <--> 2 0 
4 <--> 
4
hermann@7600x:~$

@Hermann-SW
Copy link
Author

Hermann-SW commented Nov 9, 2024

Below are the 9 ccclint errors that will not be "corrected".
Most Boost graph code does not adhere to { "error" below.

hermann@7600x:~$ cppcheck --enable=all --suppress=missingIncludeSystem o1_edge_visitor.cpp --check-config
Checking o1_edge_visitor.cpp ...
hermann@7600x:~$ cpplint o1_edge_visitor.cpp
o1_edge_visitor.cpp:14:  Do not use namespace using-directives.  Use using-declarations instead.  [build/namespaces] [5]
o1_edge_visitor.cpp:18:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
o1_edge_visitor.cpp:35:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
o1_edge_visitor.cpp:40:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
o1_edge_visitor.cpp:43:  Is this a non-const reference? If so, make const or use a pointer: Graph& g  [runtime/references] [2]
o1_edge_visitor.cpp:44:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
o1_edge_visitor.cpp:54:  Is this a non-const reference? If so, make const or use a pointer: Graph& g  [runtime/references] [2]
o1_edge_visitor.cpp:55:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
o1_edge_visitor.cpp:57:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
Done processing o1_edge_visitor.cpp
Total errors found: 9
hermann@7600x:~$

@Hermann-SW
Copy link
Author

For discussion in this pull request comment:
boostorg/graph#387 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment