How to pass additional array to Thrust's min_element predicate - c++

I'm trying to use Thrust's min_element reduction to find next edge in Prim's algorithm. I iterate over graph edges. This is my comparison function:
struct compareEdge {
__host__ /*__device__*/ bool operator()(Edge l, Edge r) {
if (visited[l.u] != visited[l.v] && visited[r.u] != visited[r.v]) {
return l.cost < r.cost;
} else if (visited[l.u] != visited[l.v]) {
return true;
} else {
return false;
}
}
};
Unfortunately this code cannot run on device, because I use visited array, where I mark already visited nodes. How can I pass this array to my predicate to make it usable from device-executed code?

There are probably a number of ways this can be handled. I will present one approach. Please note that your question is how to pass an arbitrary data set to a functor, which is what I'm trying to show. I'm not trying to address the question of whether or not your proposed functor is a useful comparison predicate for thrust::min_element (which I'm not sure of).
One approach is simply to have a statically defined array:
__device__ int d_visited[DSIZE];
then in your host code, before using the functor, you will need to initialize the array:
cudaMemcpyToSymbol(d_visited, visited, DSIZE*sizeof(int));
Your functor code would have to be modified. Since you may want the functor to be usable either on the host or the device, we will need to control the code based on this:
struct compareEdge {
__host__ __device__ bool operator()(Edge l, Edge r) {
#ifdef __CUDA_ARCH__
if (d_visited[l.u] != d_visited[l.v] && d_visited[r.u] != d_visited[r.v]) {
return l.cost < r.cost;
} else if (d_visited[l.u] != d_visited[l.v]) {
return true;
} else {
return false;
}
#else
if (visited[l.u] != visited[l.v] && visited[r.u] != visited[r.v]) {
return l.cost < r.cost;
} else if (visited[l.u] != visited[l.v]) {
return true;
} else {
return false;
}
#endif
}
};

Related

C++ runtime error: addition of unsigned offset?

I wrote the following to check if text is palindrome, I run it on leetcode and I am getting errors:
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
while (!isalpha(s[r]))
{
--r;
}
while (!isalpha(s[l]))
{
++l;
}
if (tolower(s[r])!=tolower(s[l]))
return false;
--r;
++l;
}
return true;
}
};
Line 1061: Char 9: runtime error: addition of unsigned offset to
0x7ffc7cc10880 overflowed to 0x7ffc7cc1087f (basic_string.h) SUMMARY:
UndefinedBehaviorSanitizer: undefined-behavior
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1070:9
what's the problem with my code?
You're going out of bounds here:
while (!isalpha(s[r]))
and here
while (!isalpha(s[l]))
r can became negative and l can become >= s.length().
You should add some checks like
while (l < r && !isalpha(s[r]))
and
while (l < r && !isalpha(s[l]))
The same problem in this line
if (tolower(s[r])!=tolower(s[l]))
This should be
if (l < r && tolower(s[r])!=tolower(s[l]))
Different approach (C++20)
A different approach is to erase all non-alpha characters from s with
std::erase_if(s, [](char c) { return !isalpha(c); });
and remove the inner while loops.
I think you were very close to the solution. The pitfall here are that:
you are modifying the loop control variable more than once in the loop
(as consequence) you are using the loop control variable after changing their values without further checks.
The easy way to fix this kind of issue is to do one single action for every iteration. you can achieve this just using "else".
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
if(!isalpha(s[r]))
{
--r;
}
else if(!isalpha(s[l]))
{
++l;
}
else if (tolower(s[r])!=tolower(s[l]))
{
return false;
}
else
{
--r;
++l;
}
}
return true;
}
};

Is a throw good in recursion?

So this toy problem is a graph problem using dfs to see if this entire course schedule is valid and doesn't have a course that can't be taken since its prereq can't be taken etc, etc...
I want to know if by using a throw in the visit method is good practice. Since if we found a cycle in the graph, I can just throw. Now does the throw totally ignore the stack and goes straight down until it finds a catch. If so, does that mean, instead of implementing visit method to return false when a cycle is found. It would be faster to just throw instead of returning false all the way down the stack? Is this good practice for production level code. or is the return bool method better?
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<list<int>> vMap(numCourses);
vector<bool> globalVisited(numCourses, false);
for (auto it : prerequisites){
vMap[it.first].push_back(it.second);
}
try {
for (int i=0; i<numCourses; i++){
if (globalVisited[i] != true){
vector<bool> localVisited(numCourses, false);
visit(vMap, globalVisited, localVisited, i);
}
}
}
catch (...){
return false;
}
return true;
}
void visit(vector<list<int>>& vMap, vector<bool>& globalVisited, vector<bool>& localVisited, int i){
if (globalVisited[i] == true){ //reached a deadend, try a different node
return;
}
else if (localVisited[i] == true){ //found a cycle
throw new exception;
}
localVisited[i] = true;
for (auto it : vMap[i]){
visit(vMap, globalVisited, localVisited, it);
}
globalVisited[i] = true;
}
};

qsort and std::sort behaving differently

I am very amazed that sorting via qsort and std::sort can produce different results. I need help explaining the behavior of the following snippets:
using qsort:
// the following comparator has been used in qsort.
// if l<r : -1, l==r : 0 , l>r 1
int cmpre(const void *l, const void *r) {
if ((*(tpl *)l).fhf < (*(tpl *)r).fhf)
return -1;
else
if ((*(tpl *)l).fhf == (*(tpl *)r).fhf) {
if ((*(tpl *)l).nhf == (*(tpl *)r).nhf)
return 0;
else
if ((*(tpl *)l).nhf > (*(tpl *)r).nhf)
return 1;
else
return -1;
} else
return 1;
}
// and sort statement looks like :
qsort(tlst, len, sizeof(tpl), cmpre);
Complete Code link =>
http://ideone.com/zN87tX
Using sort:
// the following comparator was used for sort
int cmpr(const tpl &l, const tpl &r) {
if (l.fhf < r.fhf)
return -1;
else
if (l.fhf == r.fhf) {
if (l.nhf == r.nhf)
return 0;
else
if (l.nhf > r.nhf)
return 1;
else
return -1;
} else
return 1;
}
// and sort statement looks like :
sort(tlst, tlst + len, cmpr);
Complete code link at =>
http://ideone.com/37Dc2S
You can see the output on the link, after and before sorting operation and may wish to check out the compr and compre methods used to compare two tuples. I do not understand why sort is not able to sort the array whereas qsort is able to do so.
Rewrite cmpr() as
bool cmpr(const tpl &l, const tpl &r){
if(l.fhf != r.fhf) return l.fhf < r.fhf;
return l.nhf < r.nhf;
}
Or, you may also reuse cmpre() to implement cmpr().
bool cmpr(const tpl &l, const tpl &r) {
return (cmpre(&l, &r) < 0);
}

How to reset a static vector inside a function?

I am trying to solve a certain problem on an online judge using the Dynamic Programming paradigm. I have written a function which memoizes the results of smaller subproblems. But this function will be called t times in a single run. So when the function calls itself I want its "Memory" to be preserved, but when it is called from the driver I wan't the vector to be reset. How do I do that? I think having a global vector and reseting it after each call from the driver is possible, but as I have learnt from books and stack overflow that is "bad programming style". So what is a good sollution to this problem? Heres the code :
class mem{
public:
bool mike_win;
bool written;
};
bool calc(int a){
static vector<mem> memory(a);
if( a == 1){
return false;
}
if(memory[a-1].written == true){
return (!(memory[a-1].mike_win))
}
vector<int> div_list = divis(a);
//^^ divis is a function which takes a number and returns
//all its divisors in descending order in a vector<int>
for(vector<int>::iterator i = div_list.begin();i != div_list.end();i++){
if ( ! ( calc( a / (*i) ))){
memory[a-1].written = true;
memory[a-1].mike_win = true;
return true;
}
}
if(calc(a-1 ) == false){
memory[a-1].written = true;
memory[a-1].mike_win = true;
return true;
}
else{
memory[a-1].written = false;
memory[a-1].mike_win = false;
return false;
}
}
Heres a link to the question. And heres the function divis :
vector<int> divis(int a){
vector<int> div_list(int a )
if(a==2){
return div_list;
}
int k = sqrt(a);
for(int i=2;i<=k;i++){
if(!(a%i)){
div_list.push_back(i);
div_list.push_back(a/i);
}
}
sort(div_list.rbegin(),div_list.rend());
div_list.erase(unique(div_list.begin(),div_list.end()),div_list.end());
return div_list;
}
I think the way I would do it is to create two overloads of calc: on that takes just int as a parameter, and another that takes an int and a reference to vector<int>. That way, a user will call the first overload, which will create the temporary vector for memorization, and pass it to the second function, which passes the reference upon recursion. Kinda like this:
bool calc(int a, vector<int>& memory)
{
// Do your stuff here
// Instead of calling it as calc( a / (*i) ), just call
// it as calc( a / (*i) , memory )
}
bool calc(int a)
{
vector<int> memory(a);
calc(a, memory);
}
That way, you avoid having to do any sort of book-keeping in the heart of your algorithm to determine whether to clear the vector or not; it will be done automatically after the first call returns.

Subset sum recursion with c++

This is one of the solution of getting true or false from given set and target value
bool subsetSumExists(Set<int> & set, int target) {
if (set.isEmpty()) {
return target == 0;
} else {
int element = set.first();
Set<int> rest = set - element;
return subsetSumExists(rest, target)
|| (subsetSumExists(rest, target- element));
}
}
However, this solution will return true or false value only. How is it possible to get the element that involve in the subset(set that add together will equal to target) as well?
Do I have to use dynamic programming? Coz as i know.. recursion is building up stack actually and after the function return the value, the value inside the frame will be discarded as well.
So, is it possible to get the elements that add up equal to the target value.
Is passing an object a solution of the problem?
Thank you
First of all you can optimize your program a little bit - check if target is 0 and if it is always return true. Now what you need is to have somewhere to store the elements that you have already used. I will show you a way to do that with a global "stack"(vector in fact so that you can iterate over it), because then the code will be easier to understand, but you can also pass it by reference to the function or avoid making it global in some other way.
By the way the stl container is called set not Set.
vector<int> used;
bool subsetSumExists(Set<int> & set, int target) {
if (target == 0) {
cout << "One possible sum is:\n";
for (int i = 0; i < used.size(); ++i) {
cout << used[i] << endl;
}
return true;
} else if(set.empty()) {
return false;
}else {
int element = set.first();
Set<int> rest = set - element;
used.push_back(element);
if (subsetSumExists(rest, target- element)) {
return true;
} else {
used.pop_back();
}
return subsetSumExists(rest, target);
}
}
Hope this helps.