D Schiff
D Schiff

Reputation: 101

R-->cpp how to get C++ pointers to work with sourceCpp (Bellman Ford algorithm)

I'm trying to port a few functions over to r from cpp using rcpp directly using sourceCpp. I'm a total novice so apologies for poorly used language or post. Trying to port over the Bellman Ford algorithm (from Gupte, Shankar, Li, Muthukrishnan, Iftode).

I'm getting two errors:

  1. cannot convert 'SEXP' to 'Rcpp::traits::input_parameter::type* {aka Rcpp::InputParameter*} in initialization
  2. invalid user-defined conversion from 'Rcpp::traits::input_parameter::type {aka Rcpp::InputParameter}' to 'int' [-fpermissive]
  3. Bonus confusion: Also, R studio shows line errors as outside of the range of the code (error in line 600, but Cpp code is only 500 lines long)

I'm guessing this is something to do with class types, wrapping functions, not being able to use pointers or something like that in the very first line. Please let me know how I might adjust this code to correctly export this function to r.

Thank you.

   #include <Rcpp.h> // added this
using namespace Rcpp; // added

#define MAXV 100000
 using namespace std; // commented this out...? don't, throws a lot of errors

struct edge { 
    int u, v, weight;
    edge(int _u, int _v) {
        u = _u, v = _v, weight = -1;
    }      
    edge(int _u, int _v, int _weight) {
        u = _u, v = _v, weight = _weight;
    }
};

// general stuff
int LPvalue; // value for the dual LP
int cycleCount;
int V, E;
vector <edge> edges;
vector <edge> original_edges;
ofstream results, summary;

// stuff for labeling
vector <int> edgesDAG; // edges left over from eulerian subgraph
vector <int> edgesEulerian; // maximal eulerian subgraph
set<int> adjDAG[MAXV]; // these adjacency lists still just keep edge indices
set<int> adjEulerian[MAXV];
bool inEulerian[MAXV];

// stuff for Bellman-Ford
int dist[MAXV];        // vertex -> distance

// [[Rcpp::export]] //ERRORS
void bellman_ford(int *pred) {

    for(int i = 0; i < V; i++) {
        dist[i] = V;
    pred[i] = -1;
    }

    dist[0] = 0;

    int i;
    for(i = 0; i < V; i++) {
        bool changed = false;
    //printf("%d",i);
        for(int j = 0; j < E; j++) {

            int u = edges[j].u;
            int v = edges[j].v;
            int w = edges[j].weight;
            if(dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                pred[v] = j;
                changed = true;
            }
        }

        if(dist[0] < 0) {
            break;
        }

        if(!changed) {
            printf("Bellman Ford done after %d of %d iters\n", i, V);
        //results << "Bellman-Ford done after " << i << " of " << V << " iters" << endl;
            break;
        }
    }
    printf("Bellman Ford took %d of %d iters\n", i+1, V);
}

Upvotes: 2

Views: 158

Answers (1)

Qiang Kou
Qiang Kou

Reputation: 522

  1. use std::vector<int> instead of int *

  2. use Rcpp::Rcout instead of std::ofstream

The following code should compile:

#include <Rcpp.h> // added this
using namespace Rcpp; // added

#define MAXV 100000
using namespace std; // commented this out...? don't, throws a lot of errors

struct edge { 
  int u, v, weight;
  edge(int _u, int _v) {
    u = _u, v = _v, weight = -1;
  }      
  edge(int _u, int _v, int _weight) {
    u = _u, v = _v, weight = _weight;
  }
};

// general stuff
int LPvalue; // value for the dual LP
int cycleCount;
int V, E;
vector <edge> edges;
vector <edge> original_edges;

// stuff for labeling
vector <int> edgesDAG; // edges left over from eulerian subgraph
vector <int> edgesEulerian; // maximal eulerian subgraph
set<int> adjDAG[MAXV]; // these adjacency lists still just keep edge indices
set<int> adjEulerian[MAXV];
bool inEulerian[MAXV];

// stuff for Bellman-Ford
int dist[MAXV];        // vertex -> distance

// [[Rcpp::export]]
void bellman_ford(std::vector<int> pred) {

  for(int i = 0; i < V; i++) {
    dist[i] = V;
    pred[i] = -1;
  }

  dist[0] = 0;

  int i;
  for(i = 0; i < V; i++) {
    bool changed = false;
    //printf("%d",i);
    for(int j = 0; j < E; j++) {

      int u = edges[j].u;
      int v = edges[j].v;
      int w = edges[j].weight;
      if(dist[v] > dist[u] + w) {
        dist[v] = dist[u] + w;
        pred[v] = j;
        changed = true;
      }
    }

    if(dist[0] < 0) {
      break;
    }

    if(!changed) {
      Rcpp::Rcout << "Bellman-Ford done after " << i << " of " << V << " iters" << endl;
      break;
    }
  }
  Rcpp::Rcout << "Bellman Ford took" << i + 1 << " of " << V << " iters" << std::endl;
}

Upvotes: 4

Related Questions