Yet another BGL's Betweenness centrality issue - c++

Drawing on this reply, I've tried to implement the Betweenness centrality as follows:
typedef struct vpr_
{
int id;
} VProp;
typedef boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, VProp, EProp> graph_t;
boost::shared_array_property_map<double, boost::property_map<graph_t, int>::const_type> centrality_map(num_vertices(g), get(VProp::id, g));
But the following error was returned.
In file included from /usr/local/include/boost/graph/adjacency_list.hpp:246:0,
from /usr/local/include/boost/graph/random.hpp:23,
from ../../src/graph/Graph.h:25,
from Graph.cpp:23:
/usr/local/include/boost/graph/detail/adjacency_list.hpp: In instantiation of ‘struct boost::adj_list_any_vertex_pa::bind_<int, boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, vpr_>’:
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2568:12: required from ‘struct boost::detail::adj_list_choose_vertex_pa<int, boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, vpr_>’
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2705:12: required from ‘struct boost::adj_list_vertex_property_selector::bind_<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, vpr_, int>’
/usr/local/include/boost/graph/properties.hpp:217:12: required from ‘struct boost::detail::vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, int>’
/usr/local/include/boost/graph/properties.hpp:228:10: required from ‘struct boost::property_map<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, int>’
Graph.cpp:374:76: required from here
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2498:29: error: forming reference to void
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2499:35: error: forming reference to void
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2502:47: error: forming reference to void
/usr/local/include/boost/graph/detail/adjacency_list.hpp:2504:53: error: forming reference to void
Graph.cpp: In member function ‘void Graph::getBetweennes()’:
Graph.cpp:374:88: error: template argument 2 is invalid
Graph.cpp:375:17: error: invalid type in declaration before ‘(’ token
In file included from ../../src/graph/graph_t.h:33:0,
from ../../src/graph/Graph.h:26,
from Graph.cpp:23:
../../src/graph/VProp.h:38:6: error: invalid use of non-static data member ‘vpr_::id’
Graph.cpp:375:46: error: from this location
Graph.cpp:375:52: error: expression list treated as compound expression in initializer [-fpermissive]
EDIT
#include <boost/graph/iteration_macros.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/graph/random.hpp>
typedef struct vpr_
{
int id;
} VProp;
typedef struct epr_
{
int id;
} EProp;
typedef boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, VProp, EProp> graph_t;
int main(void) {
graph_t g;
boost::shared_array_property_map<double, boost::property_map<graph_t, VProp::*>::const_type> centrality_map(num_vertices(g), get(&VProp::id, g));
}
The code has been compiled with g++ -L/usr/local/lib -lboost_graph gtest.cpp, and the returned error is:
gtest.cpp: In function ‘int main()’:
gtest.cpp:18:81: error: template argument 2 is invalid
gtest.cpp:18:94: error: template argument 2 is invalid
gtest.cpp:18:110: error: invalid type in declaration before ‘(’ token
gtest.cpp:18:146: error: expression list treated as compound expression in initializer [-fpermissive]
gtest.cpp:18:146: error: cannot convert ‘boost::adj_list_any_vertex_pa::bind_<int vpr_::*, boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, vpr_>::type {aka boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, vpr_, epr_>, int, int&, int vpr_::*>}’ to ‘int’ in initialization
How could I fix this? Thanks in advance

Jackb, this BGL algorithm like many others in BGL requires a "vertex index property map" -- a one-to-one mapping between set of graph vertices and integer numbers within interval [0,num_vertices(g)).
Now, your structures EProp and VProp cannot be used as substitutes for vertex_index property maps, and it is what causes the compilation errors.
If you can use boost::adjacency_list<boost::vecS, ...> as your graph type, then vertex_index mapping will come for free (as internal property of the graph). Then you will be able to call centrality algorithms the way it is called in your referenced thread: centrality_map(num_vertices(g), get(boost::vertex_index, g));.
If for some reasons you cannot use boost::vecS, you have to organize the mapping yourself. For setS and listS it is discussed here How to use boost::graph algorithms with listS, setS as vertex/edge containers? and references thereof.
See related discussions on Property Map here What is a property map in BOOST? and specifically on vertex_index map here: Dijkstra Shortest Path with VertexList = ListS in boost graph

Related

Recursive unordered_map

I have a tree structure that internally uses unordered map
#include <unordered_map>
struct Node {
std::unordered_map<int, Node> children;
};
int main() {
Node a;
}
It works just fine on Apple clang 11.0.3 and MSVC v19.24, but it fails to compile on clang 10.0.0 and gcc 10.1
While regular std::map works just fine on all compilers. I failed to find the reason for this discrepancy. Is there any way to use std::unordered_map as a value for itself? Or pointers is the only solution here?
Here's the compiler explorer link https://godbolt.org/z/6eYch9
Here's an error from gcc:
#3 with x86-64 gcc 10.1
In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/unordered_map:43,
from <source>:1:
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_pair.h:
In instantiation of 'struct std::pair<const int, Node>':
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/ext/aligned_buffer.h:91:28:
required from 'struct __gnu_cxx::__aligned_buffer<std::pair<const int,
Node> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:233:43:
required from 'struct
std::__detail::_Hash_node_value_base<std::pair<const int, Node> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:279:12:
required from 'struct std::__detail::_Hash_node<std::pair<const int,
Node>, false>'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:1973:13:
required from 'struct
std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, Node>, false> > >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable.h:173:11:
required from 'class std::_Hashtable<int, std::pair<const int, Node>,
std::allocator<std::pair<const int, Node> >,
std::__detail::_Select1st, std::equal_to<int>, std::hash<int>,
std::__detail::_Mod_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Prime_rehash_policy,
std::__detail::_Hashtable_traits<false, false, true> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/unordered_map.h:105:18:
required from 'class std::unordered_map<int, Node>'
<source>:4:39: required from here
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_pair.h:218:11:
error: 'std::pair<_T1, _T2>::second' has incomplete type
218 | _T2 second; ///< The second member
| ^~~~~~
<source>:3:8: note: forward declaration of 'struct Node'
3 | struct Node {
| ^~~~
Compiler returned: 1
STL containers are not required to work with incomplete types. If you don't mind extra indirection, then the workaround is std::map<int, std::unique_ptr<Node>>
It's the same problem as doing e.g.
struct Node
{
Node child; // An instance of the full structure
};
You can't use a structure (or class) before it's fully defined, which it is at the closing }.
You can however define pointers to the structure, because then the compiler don't need the full structure definition, only know the name of the structure:
struct Node
{
Node* child; // Pointer to the structure
};
So to solve your problem, you need a map of pointers:
std::unordered_map<int, Node*> children;
Running into this while coding a Trie data structure I've noticed that in the latest of clang (v14) and GCC (v12) I don't get the error and my code operates as expected but anything below those versions (on godbolt.com) I get the same error. This is all using -std=c++14 so it's should not be related to the standard.

boost mpl fold placeholder expression fails to compile

I'm trying to compile the Statemachine example from boost-mpl (located in libs/mpl/examples/fsm/player2.cpp), but it fails with boost version 1.37 and g++ 4.8.2. With boost version 1.56 and the same compiler, the build succeeds. Unfortunately, due to some platform constraints, I cannot switch to version 1.56.
I'm not expecting anyone to look into the above mentioned lengthy example, therefore I identified a minimal code snippet which illustrates the problem:
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
//Basic queue datatype
template< class CURRENT, class NEXT >
struct queue_element
{
typedef typename CURRENT::mytype mytype;
};
//type to be put at the end of the queue
struct default_queue_element
{
};
template <class TYPE>
struct wrapper{
typedef TYPE mytype;
};
typedef mpl::vector<wrapper<int>, wrapper<char> > myvector;
//the following fold expression should create this type:
typedef queue_element<wrapper<char>, queue_element<wrapper<int>,
default_queue_element> > this_type_should_be_created;
//This typedef fails to compile with boost Version 1.37,
//but works perfectly with version 1.56
typedef typename
mpl::fold<
myvector
,default_queue_element
,queue_element<_2,_1>
>::type
generate_queue;
With boost 1.37, g++ issues the following errors:
foldtest2.cpp: In instantiation of ‘struct queue_element<mpl_::arg<2>, mpl_::arg<1> >’:
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:85:5: required from ‘const int boost::mpl::aux::template_arity_impl<queue_element<mpl_::arg<2>, mpl_::arg<1> >, 1>::value’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:93:5: required from ‘const int boost::mpl::aux::template_arity<queue_element<mpl_::arg<2>, mpl_::arg<1> > >::value’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:98:30: required from ‘struct boost::mpl::aux::template_arity<queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8: required from ‘struct boost::mpl::apply2<queue_element<mpl_::arg<2>, mpl_::arg<1> >, default_queue_element, wrapper<int> >’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp:67:85: required from ‘struct boost::mpl::aux::fold_impl<2, boost::mpl::v_iter<boost::mpl::vector<wrapper<int>, wrapper<char> >, 0l>, boost::mpl::v_iter<boost::mpl::vector<wrapper<int>, wrapper<char> >, 2l>, default_queue_element, queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
../boost_1_37_0/boost/mpl/fold.hpp:39:18: required from ‘struct boost::mpl::fold<boost::mpl::vector<wrapper<int>, wrapper<char> >, default_queue_element, queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
foldtest2.cpp:39:6: required from here
foldtest2.cpp:15:38: error: no type named ‘mytype’ in ‘struct mpl_::arg<2>’
typedef typename CURRENT::mytype mytype;
Is there a work-around to make the code compile with boost 1.37? I have been searching the web for quite some time. If nevertheless the question has already been answered somewhere, I would be grateful if you could point that out.
Looks to be very simply a bug in that ancient(¹) version of boost.
A quick bisection tells me it was fixed in v1.43.0(²). Release notes don't disclose the secret, but git does:
c5621d9 MPL: merge fix for ticket #1992 boost::mpl::zip_view does not support use as a metafunction with ::type
31a2c78 MPL: merge fix for ticket #4061 [MPL] gcc-4.5 compilation problems related to arity_helper
It clearly appears to be the latter (confirmed by compiling against 31a2c78).
So your fix this single line in include/boost/mpl/aux_/template_arity.hpp(³):
sizeof(arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1
should be
sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1
Of course the proper way to fix this is to use a supported version of boost
¹ (November 3rd, 2008)!!
² (May 6th, 2010)
³ warning: also present in several copies generated in preprocessed versions of the header

Boost graph library causing errors when applying dijkstra's algorithm

I have been loosely following this example, this one, and this stack overflow post to try to apply Dijkstra's algorithm to find the cost of the shortest path between two nodes.
If I try to follow the first example, I get an error with the typedef statement for NameMap. This error is cryptic, verbose, and I don't quite know what to do with it.
If I try to follow the second example (copy-pasted from the Boost documentation!!) it does not compile. The error is even more cryptic and verbose.
The third one (the stack overflow post) relies on the same typedef as the first one.
Is this user error? It probably is, but how should I interpret an error message that spawns from the library code?
Update 1
I am using g++ (Debian 4.8.2-21) 4.8.2 from debian testing.
Update 2
Here is a condensed version of the source code that doesn't work. There are two lines prefaced by "// The following line causes an error" are the ones in question.
Update 3
I have changed
typedef adjacency_list<listS, vecS, directedS, allow_parallel_edge_tag, EdgeWeightProperty> Graph;
typedef adjacency_list<listS, vecS, directedS, no_property , EdgeWeightProperty> Graph;
Your first attempt didn't define a property with the vertex_name_t tag (or pass it as a adjacency_list template parameter), so when you try to create a property_map with that tag the compiler emits an error.
Your code:
typedef property<edge_weight_t, Weight> EdgeWeightProperty;
typedef boost::adjacency_list<listS, vecS, directedS, allow_parallel_edge_tag, EdgeWeightProperty> Graph;
// ^ What's this?
The example code you cited:
typedef boost::property<boost::edge_weight_t, Weight> WeightProperty;
typedef boost::property<boost::vertex_name_t, std::string> NameProperty; // <-- not in your code
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS, NameProperty, WeightProperty > Graph;
// ^ Used here
I have no idea why you are passing allow_parallel_edge_tag as a template parameter. If I'm reading the documentation correctly, that struct is designed for parallel_edge_traits specializations when you are using custom container types.
Edit: The second case is actually easy to diagnose once you have the code. Going through the error messages emitted by the compiler, we look for reasons why the compiler didn't select the 3-parameter overload for dijkstra_shortest_paths. A lot of the messages merely tells you that it rejected overloads with about a dozen parameters - as it should!
Now, this error message (emitted by g++ using Coliru) is pertinent, because it tells you why compiler rejected the three-parameter version:
In file included from main.cpp:5:0:
/usr/local/include/boost/graph/dijkstra_shortest_paths.hpp:602:3: note: void boost::
dijkstra_shortest_paths(const VertexListGraph&, typename boost::graph_traits<Graph>::
vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&) [ /* irrelevant stuff
telling you how it deduced the template parameters here */ ] <near match>
dijkstra_shortest_paths
^
/usr/local/include/boost/graph/dijkstra_shortest_paths.hpp:602:3: note: no known conversion for
argument 2 from 'long int [6]' to 'boost::graph_traits<boost::adjacency_list<boost::listS,
boost::vecS, boost::directedS, boost::no_property, boost::property<boost::edge_weight_t, long int> >
>::vertex_descriptor {aka long unsigned int}'
You passed s, the array containing source vertices, as the second parameter designating the starting vertex, when you should have passed v0, and the compiler is rightfully complaining that it cannot convert an array of longs to a single vertex.

Map two integers to another integer [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have two integers and I want to create a hash map which maps the two integers to another integer.
In order to so I created the following program, however it is giving me errors:
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
std::pair <int, int> var1;
var1=std::make_pair(10,20);
cout<<"\n var1.f="<<var1.first<<"\t 2."<<var1.second<<"\n";
std::unordered_map <std::pair <int,int>, int> yeah;
return 0;
}
Is there some way to get rid of the errors?
Is there some way to do the same in a scalable manner?
Error:
n file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:2:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::_Hash_code_base<std::pair<int, int>, std::pair<const std::pair<int, int>, int>, std::__detail::_Select1st, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>’:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1402:10: required from ‘struct std::__detail::_Hashtable_base<std::pair<int, int>, std::pair<const std::pair<int, int>, int>, std::__detail::_Select1st, std::equal_to<std::pair<int, int> >, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:174:11: required from ‘class std::_Hashtable<std::pair<int, int>, std::pair<const std::pair<int, int>, int>, std::allocator<std::pair<const std::pair<int, int>, int> >, std::__detail::_Select1st, std::equal_to<std::pair<int, int> >, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/unordered_map.h:100:18: required from ‘class std::unordered_map<std::pair<int, int>, int>’
main.cpp:12:50: required from here
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash<std::pair<int, int> >’
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/basic_string.h:3033:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/string:52,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/locale_classes.h:40,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/ios_base.h:41,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/ios:42,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/ostream:38,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/iostream:39,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::pair<int, int> >’
struct hash;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:2:
I assume the error is something like "The C++ Standard doesn't provide a hash for this type"? The problem is that anything you use as the key in an unordered map must be hashable, and there is no built-in hash function for pair<int, int>. A couple possibilities are:
-Write your own hasher for pair<int, int> and use it as the third template parameter to the unordered_map. This post may be able to help with that.
-Use std::unordered_map<int, std::unordered_map<int, int>> instead. Be careful not to accidentally create copies of the inner map when you're performing operations.
-Use map instead of unordered_map. This will give you logarithmic operations instead of constant-time, but unless the map is huge and you're doing tons of lookups per second, you won't notice the difference.
Edit in response to your edit: Yes, that's what those error messages amount to, though they don't say it in quite as friendly a fashion as Microsoft's compiler does. :)

generate random graph with named vertices

I'm new to boost and i am trying to build up a distributed random graph generated by the erdos algorithm. All goes well since i specialize the internal_vertex_name template to work with named vertices as suggested in the doc.
You can find the code here.
I get a lot of compilation errors like:
boost/graph/distributed/shuffled_distribution.hpp:62:56: error: ‘const struct boost::graph::distributed::hashed_distribution<std::basic_string<char> >’ has no member named ‘block_size’
error: ‘const struct boost::adjacency_list<boost::vecS, boost::distributedS<boost::graph::distributed::mpi_process_group, boost::vecS>, boost::directedS, TNode, boost::property<boost::edge_weight_t, int>
>::base_distribution_type’ has no member named ‘local
boost/graph/distributed/adjlist/initialize.hpp:29:5: error: invalid conversion from ‘long unsigned int’ to ‘const char*’
Any suggestion?