Can I use my own heap in place of the priority_queue used in <boost graph library> dijkstra_shortest_paths? - graph

I want to write a Dijkstra's algorithm, and I like to take advantage of the boost graph library's code, but I want to use my own implementation of binomial heap and heap instead of the default priority queue. This is my first time using downloaded library code, and I just couldn't figure out a way to do this. Does anyone know how to do this or if this is impossible?

Does anyone know how to do this or if this is impossible?
No, dijkstra_shortest_paths doesn't take a queue type.
That doesn't mean it's impossible. Boost's Dijkstra is an application of BFS. BFS does support custom buffer types.
Keep in mind that Dijkstra requires a priority queue that supports the DECREASE-KEY operation
The decrease-key operation can be specialized for your queue type:
/**
* #brief Updates a particular value in a queue used by Dijkstra's
* algorithm.
*
* This routine is called by Dijkstra's algorithm after it has
* decreased the distance from the source vertex to the given #p
* vertex. By default, this routine will just call #c
* Q.update(vertex). However, other queues may provide more
* specialized versions of this routine.
*
* #param Q the queue that will be updated.
* #param vertex the vertex whose distance has been updated
* #param old_distance the previous distance to #p vertex
*/
template < typename Buffer, typename Vertex, typename DistanceType >
inline void dijkstra_queue_update(
Buffer& Q, Vertex vertex, DistanceType old_distance)
{
(void)old_distance;
Q.update(vertex);
}
All Dijkstra invocations go through dijkstra_shortest_paths_no_init, which is responsible for invoking the BFS:
// Call breadth first search
template < class Graph, class SourceInputIter, class DijkstraVisitor,
class PredecessorMap, class DistanceMap, class WeightMap, class IndexMap,
class Compare, class Combine, class DistZero, class ColorMap >
inline void dijkstra_shortest_paths_no_init(const Graph& g,
SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor,
DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare,
Combine combine, DistZero zero, DijkstraVisitor vis, ColorMap color)
{
typedef indirect_cmp< DistanceMap, Compare > IndirectCmp;
IndirectCmp icmp(distance, compare);
typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
// Now the default: use a d-ary heap
boost::scoped_array< std::size_t > index_in_heap_map_holder;
typedef detail::vertex_property_map_generator< Graph, IndexMap,
std::size_t >
IndexInHeapMapHelper;
typedef typename IndexInHeapMapHelper::type IndexInHeapMap;
IndexInHeapMap index_in_heap
= IndexInHeapMapHelper::build(g, index_map, index_in_heap_map_holder);
typedef d_ary_heap_indirect< Vertex, 4, IndexInHeapMap, DistanceMap,
Compare >
MutableQueue;
MutableQueue Q(distance, index_in_heap, compare);
detail::dijkstra_bfs_visitor< DijkstraVisitor, MutableQueue, WeightMap,
PredecessorMap, DistanceMap, Combine, Compare >
bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color);
}
Your could replace the d_ary_heap with your own queue in your own entry point wrapper function. (You could bypass existing BGL Dijkstra algorithm entry points, or you could conceivably hack it with an overload that kicks in on your specific argument types (graph type or any of the other arguments)).
Proof Of Concept
E.g. a proof-of-concept that arbitrarily wraps the Graph type. In hindsight it could be much easier to wrap e.g. the comparison predicate instead.
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_utility.hpp>
#include <iostream>
#include <queue>
using G = boost::adjacency_list<>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;
namespace PoC {
template <typename Graph> struct Wrapped : Graph {
using Graph::Graph;
Graph& get() { return *this; }
Graph const& get() const { return *this; }
};
template <class Graph, class SourceInputIter, class DijkstraVisitor, class PredecessorMap,
class DistanceMap, class WeightMap, class IndexMap, class Compare, class Combine,
class DistZero, class ColorMap>
inline void dijkstra_shortest_paths_no_init(Wrapped<Graph> const& g, SourceInputIter s_begin,
SourceInputIter s_end, PredecessorMap predecessor,
DistanceMap distance, WeightMap weight, IndexMap index_map,
Compare compare, Combine combine, DistZero zero,
DijkstraVisitor vis, ColorMap color) {
using namespace boost;
indirect_cmp<DistanceMap, Compare> icmp(distance, compare);
using Vertex = typename graph_traits<Graph>::vertex_descriptor;
// Now the default: use a d-ary heap
boost::scoped_array<std::size_t> index_in_heap_map_holder;
using IndexInHeapMapHelper = detail::vertex_property_map_generator<Graph, IndexMap, std::size_t>;
using IndexInHeapMap = typename IndexInHeapMapHelper::type;
using MutableQueue = d_ary_heap_indirect<Vertex, 4, IndexInHeapMap, DistanceMap, Compare>;
IndexInHeapMap index_in_heap = IndexInHeapMapHelper::build(g, index_map, index_in_heap_map_holder);
MutableQueue Q(distance, index_in_heap, compare);
std::cerr << "SEHE WAS HERE - pretend we use different MutableQueue" << std::endl;
detail::dijkstra_bfs_visitor<DijkstraVisitor, MutableQueue, WeightMap, PredecessorMap, DistanceMap,
Combine, Compare>
bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero);
breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color);
}
}
template <typename G>
struct boost::graph_traits<PoC::Wrapped<G>> : graph_traits<G> {};
template <typename G, typename P>
struct boost::graph_property<PoC::Wrapped<G>, P> : graph_property<G, P> {};
int main() {
PoC::Wrapped<G> g(10);
add_edge(1, 3, g);
add_edge(2, 4, g);
add_edge(3, 2, g);
add_edge(4, 8, g);
add_edge(8, 3, g);
print_graph(g);
std::vector<V> pred(num_vertices(g));
std::priority_queue<V> q;
dijkstra_shortest_paths( //
g, 0,
boost::predecessor_map(pred.data()) //
.weight_map(boost::constant_property_map<E, double>(0.0)) //
.max_priority_queue(q) //
);
}
Printing, as expected:
0 -->
1 --> 3
2 --> 4
3 --> 2
4 --> 8
5 -->
6 -->
7 -->
8 --> 3
9 -->
SEHE WAS HERE - pretend we use different MutableQueue
Notes/Caveat
Note: I see two reasons to report this as an issue/feature request with the library maintainers:
the added code will depend on detail::dijkstra_bfs_visitor; the name implies it's not intended as public interface
conceptually, BGL tries to be generic with regard to algorithms and data-structures; the omission of the queue from algorithm parameters could be an oversight

Related

How do I convert a signed 8-byte integer to normalised float? [duplicate]

I try to optimize a working compute shader. Its purpose is to create an image: find the good color (using a little palette), and call imageStore(image, ivec2, vec4).
The colors are indexed, in an array of uint, in an UniformBuffer.
One color in this UBO is packed inside one uint, as {0-255, 0-255, 0-255, 0-255}.
Here the code:
struct Entry
{
*some other data*
uint rgb;
};
layout(binding = 0) uniform SConfiguration
{
Entry materials[MATERIAL_COUNT];
} configuration;
void main()
{
Entry material = configuration.materials[currentMaterialId];
float r = (material.rgb >> 16) / 255.;
float g = ((material.rgb & G_MASK) >> 8) / 255.;
float b = (material.rgb & B_MASK) / 255.;
imageStore(outImage, ivec2(gl_GlobalInvocationID.xy), vec4(r, g, b, 0.0));
}
I would like to clean/optimize a bit, because this color conversion looks bad/useless in the shader (and should be precomputed). My question is:
Is it possible to directly pack a vec4(r, g, b, 0.0) inside the UBO, using 4 bytes (like a R8G8B8A8) ?
Is it possible to do it directly? No.
But GLSL does have a number of functions for packing/unpacking normalized values. In your case, you can pass the value as a single uint uniform, then use unpackUnorm4x8 to convert it to a vec4. So your code becomes:
vec4 color = unpackUnorm4x8(material.rgb);
This is, of course, a memory-vs-performance tradeoff. So if memory isn't an issue, you should probably just pass a vec4 (never use vec3) directly.
Is it possible to directly pack a vec4(r, g, b, 0.0) inside the UBO, using 4 bytes (like a R8G8B8A8) ?
There is no way to express this directly as 4 single byte values; there is no appropriate data type in the shader to allow you to do declare this as a byte type.
However, why do you think you need to? Just upload it as 4 floats - it's a uniform so it's not like you are replicating it thousands of times, so the additional size is unlikely to be a problem in practice.

using `XPtr` to create pointer to a user defined function in Rcpp

--------- Adding a summary of the problem ---------------------------------
I want to create a externalpointer for a user defined function which can be passed to the another function. The user will provide function name as a string, my question is how can I convert that into a function pointer, after checking that the user provided string (say fstr) matches with the name of the function that was created by the user, i.e.
if (fstr == "<USER_DEFINED_FUNCTION_NAME>")
XPtr<funcPtr> fun(new funcPtr(&<USER_DEFINED_FUNCTION_NAME>), true);
else
Rcpp::Rcout << "Supply the correct function name" << std::endl;
since, I don't know the name of the function created by the user, essentially the problem is - how can I get the string stored in the variable fstr?
The full problem is described below. Of course, I could be thinking of this problem in a totally wrong way and there may be a better way to create a function pointer to a user defined function.
Thanks
I am writing a package which provides a wrapper around the cvode solver for solving ODEs from the SUNDIALS ODE solving C library. The C function which describes the right hand side of the ODEs must be have the signature
int <FUNCTION_NAME> (realtype t, N_Vector y, N_Vector ydot, void *user_data)
where realtype, N_Vector are datatypes defined in the library and t is time, y is the vector of states (dependent variables) and ydot is the rate of change of those variables w.r.t. time.
I have written a package which provides a wrapper around the cvode function in this library to solve ODEs expressed as above. The package source code can be found here. The cvode function can be used to solve the example in SUNDIALS provided as follows:
I create a test.cpp (pasted below) which describes the RHS of ODEs, it also has the exported function to create externalpointer for the function which gets exported to R. Note that NV_Ith_S is also defined by the library. Also, a good example about function pointers in Rcpp can be found here
First I run Rcpp::sourceCpp(test.cpp), then I run my_fun <- putFunPtrInXPtr() to create a external pointer my_fun to my test function in test.cpp. Finally, after loading the package, I run the command
time_t <- c(0.0, 0.4, seq(from = 10.4, len = 12, by = 10)) # time vector
cvode(time_t, c(1,0,0), my_fun, 1e-04, c(1e-08, 1e-08, 1e-08))
to get results on console successfully. Here the second argument is the initial conditions (IC), my_fun is the pointer to ODE function, third argument is relative tolerance and fourth argument is absolute tolerance. See details about cvode here.
My question is this - I want to change the cvode in my package so that it can take function name as a string, i.e. cvode(NumericVector time, NumericVector IC, std::string fstr, double reltol, NumericVector abstol), instead of cvode(NumericVector, NumericVector, SEXP, double, NumericVector) where the string (fstr) is the user given name which should be same as the same of the function defined in .cpp file (here test function in test.cpp).
I am thinking in my cvode function, I can write
if (fstr == "<USER_DEFINED_FUNCTION_NAME>")
XPtr<funcPtr> fun(new funcPtr(&<USER_DEFINED_FUNCTION_NAME>), true);
else
Rcpp::Rcout << "Supply the correct function name" << std::endl;
However, I cannot think of any way of getting information regarding the USER_DEFINED_FUNCTION_NAME. Essentially, I want fun to point to the USER_DEFINED_FUNCTION_NAME, but can't think of any way.
In the end, I actually want the RHS function defined in .cpp to have the signature int <FUNCTION_NAME>(double t, NumericVector y, NumericVector ydot, void *user_data), from which I create a function with the correct signature to be fed to cvode, but not sure how this is possible also.
I would be very thankful for any guidance. Thanks!
#include <Rcpp.h>
using namespace Rcpp;
#include <cvode/cvode.h> /* prototypes for CVODE fcts., consts. */
#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., macros */
#include <cvode/cvode_dense.h> /* prototype for CVDense */
#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
#include <sundials/sundials_types.h> /* definition of type realtype */
int test (realtype t, N_Vector y, N_Vector ydot, void *user_data){
// static keyword before int is not really required here
NV_Ith_S(ydot,0) = -0.04 * NV_Ith_S(y,0) + 1e04 * NV_Ith_S(y,1) * NV_Ith_S(y,2);
NV_Ith_S(ydot,2) = 3e07 * NV_Ith_S(y,1) * NV_Ith_S(y,1);
NV_Ith_S(ydot,1) = -NV_Ith_S(ydot,0) - NV_Ith_S(ydot,2);
return(0);
}
// declare funcPtr as a type for function pointer to a function with the
// signature same as function which describes the RHS for ODEs
// see reference here - http://gallery.rcpp.org/articles/passing-cpp-function-pointers/
typedef int (*funcPtr)(realtype t, N_Vector y, N_Vector ydot, void *user_data);
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
// return(XPtr<funcPtr> (new funcPtr(&test)));
XPtr<funcPtr> testptr(new funcPtr(&test), true);
return testptr;
}

Potentially undefined behaviour with restricted pointers

Here are four code fragments. Why is this code guaranteed (or not guaranteed) to produce well defined behaviour?
Restricted "circular references":
struct B;
struct A { struct B *restrict b1, *restrict b2; };
struct B { struct A *restrict a1, *restrict a2; };
Assignment outer-to-inner:
void f1(int *restrict p) {
{
int *restrict p2 = p;
*p2 = 0;
}
}
Pass to function:
static inline void f2helper(int *restrict p) {
*p = 0;
}
void f2(int *restrict p) {
f2helper(p);
}
Pointer-arithmetic loop:
void f3(int *restrict p, size_t s) {
int * p2 = p + s;
while (p2 > p)
*--p2 = 0;
}
Restricted "circular references":
Originally, the question contained code that is guaranteed not to compile:
struct B;
struct A { struct B *restrict b1, b2; };
struct B { struct A *restrict a1, a2; };
The first structure is equivalent to:
struct A { struct B *restrict b1; struct B b2; };
and you cannot have an element that is an incomplete type (though you can have the restricted pointer to the incomplete type), so b2 is not valid.
This was pointed out and two possibilities were offered:
'Either':
struct B;
struct A { struct B *restrict b1, *restrict b2; };
struct B { struct A *restrict a1, *restrict a2; };
'Or':
struct B;
struct A { struct B *restrict b1; int b2; };
struct B { struct A *restrict a1; int a2; };
The 'either' option is what was intended, and what the question now lists.
The 'either' structures are syntactically valid but pretty much useless; you can create them, but they can't really hold anything useful in the way of information.
struct A a1, a2;
struct B b1, b2;
a1 = (struct A){ &b1, &b2 };
a2 = (struct A){ &b2, &b1 };
b1 = (struct B){ &a1, &a2 };
b2 = (struct B){ &a2, &a1 };
There really isn't very much you can do with those.
The 'or' structures are also syntactically valid and could have some use, though it is hard to see them being fantastically useful.
Assignment outer-to-inner:
Pass to function:
Pointer-arithmetic loop:
All three sets of functions are clean as far as I can tell.
Section 6.7.3 Type qualifiers of C11 (ISO/IEC 9899:2011) says:
8 An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.135) The intended use of the restrict qualifier (like the register storage class) is to promote optimization, and deleting all instances of the qualifier from all preprocessing translation units composing a conforming program does not change its meaning (i.e., observable
behavior).
135) For example, a statement that assigns a value returned by malloc to a single pointer establishes this
association between the allocated object and the pointer.
Section 6.7.3.1 Formal definition of restrict says:
1 Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.
2 If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of whatever function is called at program startup in a freestanding environment).
3 In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E.137) Note that ‘‘based’’ is defined only for expressions with pointer types.
4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause. If P
is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined.
5 Here an execution of B means that portion of the execution of the program that would correspond to the lifetime of an object with scalar type and automatic storage duration associated with B.
137) In other words, E depends on the value of P itself rather than on the value of an object referenced indirectly through P. For example, if identifier p has type (int **restrict), then the pointer expressions p and p+1 are based on the restricted pointer object designated by p, but the pointer expressions *p and p[1] are not.
That seems to allow the code you show. The pointer references are 'based on' the restricted pointers and that's allowed by that section.

two dimensional vector

I wanted to have a linked list of nodes with below structure.
struct node
{
string word;
string color;
node *next;
}
for some reasons I decided to use vector instead of list.my question is that is it possible to implement a vector which it's j direction is bounded and in i direction is unlimited and to add more two strings at the end of my vertex.
in other words is it possible to implement below structure in vector ?
j
i color1 color2 …
word1 word2 …
I am not good with C/C++, so this answer will only be very general. Unless you are extremely concerned about speed or memory optimization (most of the time you shouldn't be), use encapsulation.
Make a class. Make an interface which says what you want to do. Make the simples possible implementation of how to do it. Most of the time, the simplest implementation is good enough, unless it contains some bugs.
Let's start with the interface. You could have made it part of the question. To me it seems that you want a two-dimensional something-like-an-array of strings, where one dimension allows only values 0 and 1, and the other dimension allows any non-genative integers.
Just to make sure there is no misunderstanding: The bounded dimension is always size 2 (not at most 2), right? So we are basicly speaking about 2×N "rectangles" of strings.
What methods will you need? My guesses: A constructor for a new 2×0 size rectangle. A method to append a new pair of values, which increases the size of the rectangle from 2×N to 2×(N+1) and sets the two new values. A method which returns the current length of the rectangle (only the unbounded dimension, because the other one is constant). And a pair of random-access methods for reading or writing a single value by its coordinates. Is that all?
Let's write the interface (sorry, I am not good at C/C++, so this will be some C/Java/pseudocode hybrid).
class StringPairs {
constructor StringPairs(); // creates an empty rectangle
int size(); // returns the length of the unbounded dimension
void append(string s0, string s1); // adds two strings to the new J index
string get(int i, int j); // return the string at given coordinates
void set(int i, int j, string s); // sets the string at given coordinates
}
We should specify what will the functions "set" and "get" do, if the index is out of bounds. For simplicity, let's say that "set" will do nothing, and "get" will return null.
Now we have the question ready. Let's get to the answer.
I think the fastest way to write this class would be to simply use the existing C++ class for one-dimensional vector (I don't know what it is and how it is used, so I just assume that it exists, and will use some pseudocode; I will call it "StringVector") and do something like this:
class StringPairs {
private StringVector _vector0;
private StringVector _vector1;
private int _size;
constructor StringPairs() {
_vector0 = new StringVector();
_vector1 = new StringVector();
_size = 0;
}
int size() {
return _size;
}
void append(string s0, string s1) {
_vector0.appens(s0);
_vector1.appens(s1);
_size++;
}
string get(int i, int j) {
if (0 == i) return _vector0.get(j);
if (1 == i) return _vector1.get(j);
return null;
}
void set(int i, int j, string s) {
if (0 == i) _vector0.set(j, s);
if (1 == i) _vector1.set(j, s);
}
}
Now, translate this pseudocode to C++, and add any new methods you need (it should be obvious how).
Using the existing classes to build your new classes can help you program faster. And if you later change your mind, you can change the implementation while keeping the interface.

MPI derived type from a struct

I have to transfer a number of elements of type:
typedef struct
{
float w;
int a, b;
} edge;
to different processes, hence I am creating an MPI derived type like this:
unsigned int typecount;
MPI_Datatype PEDGE, types[2] = { MPI_FLOAT, MPI_INT };
MPI_Aint offsets[2], extent;
int blocklen[2] = { 1, 2 };
typecount = 2;
offsets[0] = 0;
MPI_Type_extent(MPI_FLOAT, &extent);
offsets[1] = (1*extent);
MPI_Type_struct (typecount, blocklen, offsets, types, &PEDGE);
MPI_Type_commit(&PEDGE);
When I do a sizeof(edge) I get 12 bytes, but I am getting only 8 bytes when I do sizeof(PEDGE)...why is that? Apart from this, my code for sending some elements of PEDGE type to arrays of edge type are failing, probably because of this mismatch.
The problem here is that an MPI_Datatype object such as PEDGE is not itself the new datatype, merely an opaque handle to some implementation-specific entity that MPI can interpret as a datatype. As such, sizeof() will not be able to return its accurate size. Use MPI_Type_size() instead.
As for the sends failing, I can't say much without seeing your code, but your datatype definition does look correct.

Resources