Looping Through Large, Multidimensional Array Using Rcpp - c++

I am trying to create models that involve looping through large multidimensional arrays (ex: dimensions = 20 x 1000 x 60), which run very slow the way I code them in R. I downloaded Rcpp and have been trying to implement such a model, since C++ handles loops very well. Normally, I would write such a function in R as:
fun <- function(x,y,z){
f <- array(0, dim = c(18,50,10));
for (i in 1:18){
for (j in 1:50){
for (l in 1:10){
f[i,j,l] <- (i*j/10) + l;
}
}
}
return(f[x,y,z])
}
and as expected the function yields:
> fun(10,20,5)
[1] 25
This is what I thought the equivalent code in Rcpp should look like:
cppFunction('
double fun(int x, int y, int z){
int f[18][50][10] = {0};
for (int i = 1; i > 18; i++){
for (int j = 1; j > 50; j++){
for (int l = 1; l > 10; l++){
f[i][j][l] = (i * j/10) + l;
}
}
}
return f[x][y][z];
}
')
but I am getting 0's anytime I go to use the function.
> fun(10,20,5)
[1] 0
The actual models I'll be implementing use backward iteration, so I do need the arrays as part of the function. Alternatively, returning the array itself would also work for my purposes, but I haven't had luck with that either.
Any help would be sincerely appreciated.
Thanks

Remember that C++ is 0 indexed. You need to start your indexing at 0 rather than 1 as in R. You also need to make sure that your loops only continue while the value of i, j, and l are less than the dimensions of the array (so switch > for <. And your array needs to be an array of double, not int:
Rcpp::cppFunction('
double fun(int x, int y, int z){
double f[18][50][10] = {0};
for (int i = 0; i < 18; i++){
for (int j = 0; j < 50; j++){
for (int l = 0; l < 10; l++){
f[i][j][l] = (i * j/10) + l;
}
}
}
return f[x][y][z];
}
')
Testing gives:
fun(10, 20, 5)
#> [1] 25

Related

Iterate over m^n combinations with nested loops [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 1 year ago.
Improve this question
I have an array y of dimension n, every dimension has m entries.
How do I iterate over all combinations of indices using nested for loops?
I'd like to get all possible combinations of sums like shown in this code:
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
...
for (int k = 0; k < m; ++k) {
z = x[0] + y[i]*x[1] + y[j]*x[2] + ... + y[k]*x[n];
}
}
}
If this is not possible using for loops, how else can it be achieved?
Here's a solution to the problem, probably not the optimal one, but illustrates the idea. Since you need to index y with as many indices at a time as there are y's, you need an array. The array's indices will be incremented each iteration, starting at the 0th index. When the 0th index reaches m, we carry over a 1, just like normal addition. When the integer at that next index reaches m, we carry over a 1 to the next index. When all of the indices went from 0 through m - 1, we know we're done. Test it in the browser if you wish.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<int> y = { 1, 2, 3 };
std::vector<int> x = { 0, 1, 2, 3 };
std::vector<int> indices = { 0, 0, 0 };
int m = y.size();
int sum = 0;
int index_to_increment_next = 0;
while (index_to_increment_next < m)
{
// sum up at current indices
sum += x[0];
for (int i = 0; i < m; i++)
{
sum += x[i + 1] * y[indices[i]];
}
int j;
for (j = 0; j < m; j++)
{
if (indices[j] < m - 1)
{
// increment indices
indices[j]++;
break;
}
// when the index reaches m, reset it to 0
// and try to increment the next one
indices[j] = 0;
}
// on the last iteration, this will be equal to m
// and all of the indices will be reset back to 0
index_to_increment_next = j;
}
std::cout << sum;
}
Update
I need a separate sum for every possible combination z = x[0] + y[i]*x[1] + y[j]*x[2] + ... + y[k]*x[n] where i,j,...k are n counters and take on values from 0 to m.
Just save the individual sums on each iteration and store them in e.g. a vector. See the code.
// declare above the while
std::vector<int> sums;
// ...
int sum = x[0];
for (int i = 0; i < m; i++)
{
sum += x[i + 1] * y[indices[i]];
}
sums.push_back(sum);
If I understand your problem correctly, then as Daniyal Shaikh said above in a comment
You can use recursion instead. it can prove to be a better alternate
An easy implementation of n for-loops is:
(n_counter and z are globals)
int n_counter = 0; // which is the 1,2,3 of your y[i]*x[**1**]
int z = x[0]; // all possible combinations of sums at every iteration
void recursion(int n, int m){
n_counter++;
for(int i=0 ; i<m ; i++){
z += y[i]*x[n_counter];
}
if(n_counter<=n){ // go deeper n times, which is equal to n for-loops
recursion(n, m);
}
return;
}
Every time we get deeper in the recursion, n_counter will increase because we need the number that increases.
For example with number 2: ".. + y[j]*x[2] + ..".
Lastly, all you have to do is to print z.

C++ Part of brute-force knapsack

reader,
Well, I think I just got brainfucked a bit.
I'm implementing knapsack, and I thought about I implemented brute-force algorithm like 1 or 2 times ever. So I decided to make another one.
And here's what I chocked in.
Let us decide W is maximum weight, and w(min) is minimal-weighted element we can put in knapsack like k=W/w(min) times. I'm explaining this because you, reader, are better know why I need to ask my question.
Now. If we imagine that we have like 3 types of things we can put in knapsack, and our knapsack can store like 15 units of mass, let's count each unit weight as its number respectively. so we can put like 15 things of 1st type, or 7 things of 2nd type and 1 thing of 1st type. but, combinations like 22222221[7ed] and 12222222[7ed] will mean the same for us. and counting them is a waste of any type of resources we pay for decision. (it's a joke, 'cause bf is a waste if we have a cheaper algorithm, but I'm very interested)
As I guess the type of selections we need to go through all possible combinations is called "Combinations with repetitions". The number of C'(n,k) counts as (n+k-1)!/(n-1)!k!.
(while I typing my message I just spotted a hole in my theory. we will probably need to add an empty, zero-weighted-zero-priced item to hold free space it's probably just increases n by 1)
so, what's the matter.
https://rosettacode.org/wiki/Combinations_with_repetitions
as this problem is well-described up here^ I don't really want to use stack this way, I want to generate variations in single cycle, which is going from i=0 to i<C'(n,k).
so, If I can make it, how it works?
we have
int prices[n]; //appear mystically
int weights[n]; // same as previous and I guess we place (0,0) in both of them.
int W, k; // W initialized by our lord and savior
k = W/min(weights);
int road[k], finalroad[k]; //all 0
int curP = curW = maxP = maxW = 0;
for (int i = 0; i < rCombNumber(n, k); i ++) {
/*guys please help me to know how to generate this mask which is consists of indices from 0 to n (meaning of each element) and k is size of mask.*/
curW = 0;
for (int j = 0; j < k; j ++)
curW += weights[road[j]];
if (curW < W) {
curP = 0;
for (int l = 0; l < k; l ++)
curP += prices[road[l]];
if (curP > maxP) {
maxP = curP;
maxW = curW;
finalroad = road;
}
}
}
mask, road -- is an array of indices, each can be equal from 0 to n; and have to be generated as C'(n,k) (link about it above) from { 0, 1, 2, ... , n } by k elements in each selection (combination with repetitions where order is unimportant)
that's it. prove me wrong or help me. Much thanks in advance _
and yes, of course algorithm will take the hell much time, but it looks like it should work. and I'm very interesting in it.
UPDATE:
what do I miss?
http://pastexen.com/code.php?file=EMcn3F9ceC.txt
The answer was provided by Minoru here https://gist.github.com/Minoru/745a7c19c7fa77702332cf4bd3f80f9e ,
it's enough to increment only the first element, then we count all of the carries, set where we did a carry and count reset value as the maximum of elements to reset and reset with it.
here's my code:
#include <iostream>
using namespace std;
static long FactNaive(int n)
{
long r = 1;
for (int i = 2; i <= n; ++i)
r *= i;
return r;
}
static long long CrNK (long n, long k)
{
long long u, l;
u = FactNaive(n+k-1);
l = FactNaive(k)*FactNaive(n-1);
return u/l;
}
int main()
{
int numberOFchoices=7,kountOfElementsInCombination=4;
int arrayOfSingleCombination[kountOfElementsInCombination] = {0,0,0,0};
int leftmostResetPos = kountOfElementsInCombination;
int resetValue=1;
for (long long iterationCounter = 0; iterationCounter<CrNK(numberOFchoices,kountOfElementsInCombination); iterationCounter++)
{
leftmostResetPos = kountOfElementsInCombination;
if (iterationCounter!=0)
{
arrayOfSingleCombination[kountOfElementsInCombination-1]++;
for (int anotherIterationCounter=kountOfElementsInCombination-1; anotherIterationCounter>0; anotherIterationCounter--)
{
if(arrayOfSingleCombination[anotherIterationCounter]==numberOFchoices)
{
leftmostResetPos = anotherIterationCounter;
arrayOfSingleCombination[anotherIterationCounter-1]++;
}
}
}
if (leftmostResetPos != kountOfElementsInCombination)
{
resetValue = 1;
for (int j = 0; j < leftmostResetPos; j++)
{
if (arrayOfSingleCombination[j] > resetValue)
{
resetValue = arrayOfSingleCombination[j];
}
}
for (int j = leftmostResetPos; j != kountOfElementsInCombination; j++)
{
arrayOfSingleCombination[j] = resetValue;
}
}
for (int j = 0; j<kountOfElementsInCombination; j++)
{
cout<<arrayOfSingleCombination[j]<<" ";
}
cout<<"\n";
}
return 0;
}
thanks a lot, Minoru

Bucket sort and User input

Here's the problem I'm working on: a user gives me an unspecified number of points on a standard x,y coordinate plane, where 0 < x^2 + y^2 <= 1. (x squared plus y squared, just for clarity).
Here is an example of the input:
0.2 0.38
0.6516 -0.1
-0.3 0.41
-0.38 0.2
From there, I calculate the distance of those points from the origin, (0, 0). Here is the function I use to find the distance and push it into a vector of doubles, B.
void findDistance(double x = 0, double y = 0) {
double x2 = pow(x, 2);
double y2 = pow(y, 2);
double z = x2 + y2;
double final = sqrt(z);
B.push_back(final);
}
Then, I want to bucket sort vector B, where there are n buckets for n points. Here is my current build of the bucketSort:
void bucketSort(double arr[], int n)
{
vector<double> b[n];
for (int i=0; i<n; i++)
{
int bi = n*arr[i];
b[bi].push_back(arr[i]);
}
for (int i=0; i<n; i++)
sort(b[i].begin(), b[i].end());
int index = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < b[i].size(); j++)
arr[index++] = b[i][j];
}
My problem is I can't get bucketSort to work without crashing. I get a windows message saying the program has stopped working. Now, I know the function works, but only when I initialize the vector and fill it at the same time. This is an example of a call that works:
double arr[] = {0.707107, 0.565685, 0.989949, 0.848528 };
int n = sizeof(arr)/sizeof(arr[0]);
bucketSort(arr, n);
So far, I've yet to find any other format for calling and initializing the vector that the function will accept and run. I need to find a way to take the points, computer the distances, and sort the distances. Current main that I'm plugging in and getting as a backfire:
int main(){
int number;
while (cin >> number){
A.push_back(number); }
int q = 0; double r = 0; double d = 0;
while (q < (A.size() - 1)){
findDistance(A[q], A[q+1]);
q += 2;
}
double arr[B.size()]; copy(B.begin(), B.end(), arr);
int n = (sizeof(B) + sizeof(B[0])) / sizeof(B[0]);
bucketSort(arr, n);
int w = 0;
while (w < y){ cout << arr[w] << endl; w++; }
The arr copy was created in some strange debugging attempt: sorry if unclear. Results of distance function stored in B, copied into arr, and arr is what's attempted to be sorted. The user inputs are given through the command prompt, using the syntax listed in the beginning. Output should be something like:
0.42941
0.49241
0.50804
0.65923
If anyone can offer suggestions of edits to either of functions that would make it work, the assistance would be greatly appreciated.
Here are a few issues to work on:
Your input loop will stop when it reads a non-integer. Change number to double
Your size calculation
int n = (sizeof(B) + sizeof(B[0])) / sizeof(B[0]);
I am not sure what you are trying to do here, but sizeof on a vector is not what you want. I think replacing this with:
int n = B.size();
is what you want.
I am not sure why you needed to convert the vector to an array to do the bucket sort - much easier to just pass the vector through to the bucket sort, then the size comes with the vector.
Change the bucketSort function to take a reference to a vector:
void bucketSort(vector<double> &arr)
{
int n = B.size();
...
and just pass B into the function. The rest of the code should be the same.
Also a portability note: not every compiler supports variable sized arrays, you are better off sticking with vector wherever possible.

Merging 3 sets of arrays

I am consider new to c++ and I have facing some doubt on merging three set of arrays.
For example:
x = 2,3,1,4,5
y = 1,3,5,7,9
z = 3,5,4,6,1
I would like to merge them into:
w = 2,1,3,3,3,5,1,5,4,4,7,6,5,9,1
I have been searching through Google. However what I get is how to merge the arrays and put them in an ascending orders.
What I actually needed:
1st from x, 1st from y, 1st from z, 2nd from x, 2nd from y, 2nd from z ............ 5th from z
Thank you very much!
It's just a matter of making a loop with i from 0 to 4 and mapping every i to the corresponding element of the array w.
Here's the skeleton of the algorithm:
std::array<int, 5> x, y, z;
std::array<int, 15> w;
for (int i = 0; i < 5; i++) {
w[i*3] = x[i];
w[i*3+1] = y[i];
w[i*3+2] = z[i];
}
And here's the working example.
If you are using std::vector, then the algorithm gets a little bit trickier. You'll need to find the maximum size, using std::max for example, and perform a loop based on that value. Then whenever a vector is empty, you'll need to skip it. Here's the skeleton again:
std::vector<int> x, y, z;
std::vector<int> w;
std::size_t max = std::max({x.size(), y.size(), z.size()});
for (std::size_t i = 0; i < max; i++) {
if (x.size() > i) w.push_back(x[i]);
if (y.size() > i) w.push_back(y[i]);
if (z.size() > i) w.push_back(z[i]);
}
As long as you know the size of x, y, z, and w, this is a fairly straightforward solution.
In C++, unlike other higher-level programming languages, most array-based operations are not handled by special functions. Instead, the user is required to write a loop to do this task themselves.
In your case, assuming that x, y, z, and w are all declared and defined properly, the most straightforward way is probably using a for loop, as follows:
int i;
for(i=0; i<(size_of_x); i++){
w[i*3] = x[i];
w[i*3+1] = y[i];
w[i*3+2] = z[i];
}
Notice that the variable size_of_x will need to be defined for this to work.
You might also want to consider the fact that the lengths of the arrays may differ.
int *resArray;
int totalLength = sizeof(x) + sizeof(y) + sizeof(z);
int maxLength = max(sizeof(x), max(sizeof(y), sizeof(x));
resArray = new int[totalLength];
int j = 0;
for (int i = 0; i < maxLength; i++)
{
if (i < sizeof(x))
{
resArray[j] = x[i];
j++
}
if (i < sizeof(y))
{
resArray[j] = y[i];
j++
}
if (i < sizeof(z))
{
resArray[j] = z[i];
j++
}
}
It'll not be the fastest solution, but it can handle arrays of different lengths.
Edit:
Do not forget to free the memory you've allocated using new.
And you can consider the use of std::vector
How about some C++11?
#include <vector>
int main()
{
std::vector<int> x {2,3,1,4,5}, y {1,3,5,7,9}, z {3,5,4,6,1};
std::vector<int> w;
for (int i {}; i < x.size(); ++i)
{
w.insert(v.end(),{x[i], y[i], z[i]});
}
}

Passing Python array to c++ function with SWIG

I have written a good bit of code in python and it works great. But now I'm scaling up the size of the problems that I'm analyzing and python is dreadfully slow. The slow part of the python code is
for i in range(0,H,1):
x1 = i - length
x2 = i + length
for j in range(0,W,1):
#print i, ',', j # check the limits
y1 = j - length
y2 = j + length
IntRed[i,j] = np.mean(RawRed[x1:x2,y1:y2])
With H and W equal to 1024 the function takes around 5 minutes to excute. I've written a simple c++ program/function that performs the same computation and it excutes in less than a second with the same data size.
double summ = 0;
double total_num = 0;
double tmp_num = 0 ;
int avesize = 2;
for( i = 0+avesize; i <X-avesize ;i++)
for(j = 0+avesize;j<Y-avesize;j++)
{
// loop through sub region of the matrix
// if the value is not zero add it to the sum
// and increment the counter.
for( int ii = -2; ii < 2; ii ++)
{
int iii = i + ii;
for( int jj = -2; jj < 2 ; jj ++ )
{
int jjj = j + jj;
tmp_num = gsl_matrix_get(m,iii,jjj);
if(tmp_num != 0 )
{
summ = summ + tmp_num;
total_num++;
}
}
}
gsl_matrix_set(Matrix_mean,i,j,summ/total_num);
summ = 0;
total_num = 0;
}
I have some other methods to perform on the 2D array. The one listed is a simple examples.
What I want to do is pass a python 2D array to my c++ function and return a 2D array back to python.
I've read a bit about swig, and have sereached pervious questions, and it seems like it's a possible solution. But I can't seem to figure out what I actually need to do.
Can I get any help? Thanks
You can use arrays as it is described here: Doc - 5.4.5 Arrays, the carray.i or std_vector.i from the SWIG library.
I find it easier to work with std::vector from the SWIG library std_vector.i to send a python list to a C++ SWIG extension. Though in your case where optimization matters, it may not be the optimal.
In your case you can define:
test.i
%module test
%{
#include "test.h"
%}
%include "std_vector.i"
namespace std {
%template(Line) vector < int >;
%template(Array) vector < vector < int> >;
}
void print_array(std::vector< std::vector < int > > myarray);
test.h
#ifndef TEST_H__
#define TEST_H__
#include <stdio.h>
#include <vector>
void print_array(std::vector< std::vector < int > > myarray);
#endif /* TEST_H__ */
test.cpp
#include "test.h"
void print_array(std::vector< std::vector < int > > myarray)
{
for (int i=0; i<2; i++)
for (int j=0; j<2; j++)
printf("[%d][%d] = [%d]\n", i, j, myarray[i][j]);
}
If you run the following python code (I used python 2.6.5), you can see that the C++ function can access the python list:
>>> import test
>>> a = test.Array()
>>> a = [[0, 1], [2, 3]]
>>> test.print_array(a)
[0][0] = [0]
[0][1] = [1]
[1][0] = [2]
[1][1] = [3]