reverse_graph argument to dijkstra_shortest_paths - boost-graph

What is the correct way to pass a reverse_graph as an argument to Dijkstra? I want to achieve something like this:
graph_t G;
vertex_descriptor u;
dijkstra_shortest_paths(G, u,
predecessor_map(get(vertex_predecessor,G))
.distance_map(get(vertex_distance,G))
.weight_map(get(edge_weight,G));
with the parameter that is a reverse graph adaptor:
reverse_graph<graph_t> R(G);
The problem is that the straightforward guess doesn't work:
dijkstra_shortest_paths(R,u,
predecessor_map(get(vertex_predecessor,R))
.distance_map(get(vertex_distance,R))
.weight_map(get(edge_weight,R)));
The boost doc pages are very frugal about reverse graphs... I managed to narrow it down to an issue with accessing the edges of R, I think, since this works:
print_graph(R,get(vertex_name,R));
but this doesn't:
print_graph(R,get(edge_weight,R));

Related

Access and insert a map of map of pair and int in C++

For example I've got a map like this:
std::map<std::map<pair<int, int>, pair<int, int> >, int> mp;
How do I insert/access element into/in that map?
For inserting I've tried with
// using nested map
std::map<pair<int, int>, pair<int, int> > mp2;
mp2.insert(make_pair(1,2), make_pair(3,4));
mp.insert(make_pair(mp2, 1));
For accessing the elements, I couldn't insert element into the map so I don't know if I did it right or wrong, but I think it is gonna be like this
mp[[1,2],[3,4]];
And the compiler throws a lot of errors . Some even navigate me to the implementation code of std::map, or to be more specific, the stl_tree.h thing.
What's wrong? I'm just a mere beginner so any help would be genuinely appreciated.
In addition, this is my homework. Basically I have to store coordinates like (x,y) and (i,j) to form a path into a container, and I've tried with vectors but I couldn't pass the time limit.
Please reconsider your choice of data structure. Using std::map as a key to std::map will incur large overheads due to necessity of creating temporary keys to compare (when accessing outer map elements). It's highly unlikely that it will help you get through the time limit of yours.
std::map::insert requires a ready std::pair<Key, Value>, which means you need to wrap your arguments in one more std::make_pair
mp2.insert(std::make_pair(std::make_pair(1,2), std::make_pair(3,4)));
Or you can replace insert with emplace
mp2.emplace(make_pair(1,2), make_pair(3,4));
To access elements you must construct a temporary map to be used as a key:
mp[{{{1,2},{3,4}}}]; //extra {} required
See it online
As pointed out by #Yksisarvinen, you should reconsider using a map as a key to another map.
That being said, I guess you forgot an enclosing std::make_pair() at:
mp2.insert(make_pair(make_pair(1,2), make_pair(3,4)));
For accessing that, you'd need to do something like:
template <class K, class V>
std::map<K, V> make_map(std::pair<K, V>&& pair)
{
return std::map<K, V> { pair };
}
mp[make_map(make_pair(make_pair(1 ,2), make_pair(3 , 4)))]
But beware that this is very inefficient!

How to implement something like std::copy_if but apply a function before inserting into a different container

Full disclosure, this may be a hammer and nail situation trying to use STL algorithms when none are needed. I have seen a reappearing pattern in some C++14 code I am working with. We have a container that we iterate through, and if the current element matches some condition, then we copy one of the elements fields to another container.
The pattern is something like:
for (auto it = std::begin(foo); it!=std::end(foo); ++it){
auto x = it->Some_member;
// Note, the check usually uses the field would add to the new container.
if(f(x) && g(x)){
bar.emplace_back(x);
}
}
The idea is almost an accumulate where the function being applied does not always return a value. I can only think of a solutions that either
Require a function for accessing the member your want to accumulate and another function for checking the condition. i.e How to combine std::copy_if and std::transform?
Are worse then the thing I want to replace.
Is this even a good idea?
A quite general solution to your issue would be the following (working example):
#include <iostream>
#include <vector>
using namespace std;
template<typename It, typename MemberType, typename Cond, typename Do>
void process_filtered(It begin, It end, MemberType iterator_traits<It>::value_type::*ptr, Cond condition, Do process)
{
for(It it = begin; it != end; ++it)
{
if(condition((*it).*ptr))
{
process((*it).*ptr);
}
}
}
struct Data
{
int x;
int y;
};
int main()
{
// thanks to iterator_traits, vector could also be an array;
// kudos to #Yakk-AdamNevraumont
vector<Data> lines{{1,2},{4,3},{5,6}};
// filter even numbers from Data::x and output them
process_filtered(std::begin(lines), std::end(lines), &Data::x, [](int n){return n % 2 == 0;}, [](int n){cout << n;});
// output is 4, the only x value that is even
return 0;
}
It does not use STL, that is right, but you merely pass an iterator pair, the member to lookup and two lambdas/functions to it that will first filter and second use the filtered output, respectively.
I like your general solutions but here you do not need to have a lambda that extracts the corresponding attribute.
Clearly, the code can be refined to work with const_iterator but for a general idea, I think, it should be helpful. You could also extend it to have a member function that returns a member attribute instead of a direct member attribute pointer, if you'd like to use this method for encapsulated classes.
Sure. There are a bunch of approaches.
Find a library with transform_if, like boost.
Find a library with transform_range, which takes a transformation and range or container and returns a range with the value transformed. Compose this with copy_if.
Find a library with filter_range like the above. Now, use std::transform with your filtered range.
Find one with both, and compose filtering and transforming in the appropriate order. Now your problem is just copying (std::copy or whatever).
Write your own back-inserter wrapper that transforms while inserting. Use that with std::copy_if.
Write your own range adapters, like 2 3 and/or 4.
Write transform_if.

Best way to return a transform iterator range

Let's say I want to write a simple function keys that takes in a std::map and returns an iterator_range that provides the keys of the map. How would I do it?
template<typename A, typename B>
Range<A> keys(const std::map<A, B> & m) { ??? }
I want to apply the same pattern to various other containers, but I think this is a good prototypical example.
Edit: I'm guessing I need something in the realm of Boost's range_adapters and/or transform_iterators but I'm not familiar enough with them to apply them here.
This particular need is met with boost::adapters::keys. More generally, boost::range allows you to design your own adapters, but it's somewhat involved. So unless you're designing a new library, you might be able to get away with transformed.
If you need the result of your range back into a container, you can write a simple collect function which will "collect" the result of a boost::range pipeline.
template<typename Output, typename SinglePassRange>
Output collect(const SinglePassRange & rng)
{
Output r;
boost::range::copy(rng, std::inserter(r, boost::begin(r)));
return r;
}
Now you can easily whip up some little functions and
collect<vector<int>>(numbers | filtered(odd))
collect<vector<int>>(numbers | transformed(doubled))
collect<vector<K>>(myMap | transformed(keyOf))

Using std::bind to create a UnaryPredicate out of a BinaryPredicate to use in std::transform

I recently encountered this use of for_each:
std::for_each(ts.begin(), ts.end(), [=](T& t){t *= f;});
Well, it works. For a container of Ts and a T f, this multiplies each value by f. However I dislike the use of the lambda here. It's short, but it seems to me that it only duplicates std::multiplies. Additionally, it shouldn't be for_each, but transform, to express the intent of modifying.
However, std::multiplies is a binary predicate, std::transform requires a unary predicate.
I tried to bind f as one parameter, but apparently I'm using it wrong:
std::transform(ts.begin(), ts.end(), std::bind(std::multiplies<T>(), f));
GCC tries to give me a hint with the error message, but I don't see the actual cause:
no matching function for call to ‘transform(std::vector<int>::iterator, std::vector<int>::iterator, std::_Bind_helper<false, std::multiplies<int>, const int&>::type)’
I suspect that I'm using std::bind wrong. What is my mistake?
You forgot the iterator for result range and a placeholder in bind-expression:
std::transform(
ts.begin(), ts.end(), // source range
ts.begin(), // beginning of result range
std::bind(std::multiplies<int>(), f, std::placeholders::_1) );
// ^^^^^^^^^^^^^^^^^^^^^
// this is where the value from
// dereferenced source iterator go

Check if another vertex has the same attribute value

I have a graph made with the Boost's graph library. It is based on the adjaceny list structure. I have the following simple definition of a vertex.
struct Vertex
{
string unique_id_name;
};
I want to be able to test if a vertex with a given unique_id_name exists. How can you do this?
You can use std::find_if() - for example, suppose you are looking for vertex_im_looking_for.
If you are using C++11, you can plug in a lambda into std::find_if() - if not, you can plug in a standard functor (a predicate).
typename boost::graph_traits<Graph>::vertex_iterator vi, vi_end;
tie(vi, vi_end) = vertices(my_graph);
bool found = std::find_if(
vi, vi_end,
[&](const Vertex& vertex){
return vertex.unique_id_name==vertex_im_looking_for.unique_id_name;
}
)!=vi_end;
std::find_if() returns an iterator so you can compare with vi_end to see if you found what you are looking for. If it equals vi_end, your vertex was not found.