I've been playing around with using more efficient data structures and parallel processing and a few other things. I've made good progress getting a script from running in ~60 seconds down to running in about ~9 seconds.
The one thing I can't for the life of me get my head around though is writing a loop in Rcpp. Specifically, a loop that calculates line-by-line depending on previous-line results and updates the data as it goes.
Wondering if someone could convert my code into Rcpp that way I can back-engineer and figure out, with an example that I'm very familiar with, how its done.
It's a loop that calculates the result of 3 variables at each line. Line 1 has to be calculated separately, and then line 2 onwards calculates based on values from the current and previous lines.
This example code is just 6 lines long but my original code is many thousands:
temp <- matrix(c(0, 0, 0, 2.211, 2.345, 0, 0.8978, 1.0452, 1.1524, 0.4154,
0.7102, 0.8576, 0, 0, 0, 1.7956, 1.6348, 0,
rep(NA, 18)), ncol=6, nrow=6)
const1 <- 0.938
for (p in 1:nrow(temp)) {
if (p==1) {
temp[p, 4] <- max(min(temp[p, 2],
temp[p, 1]),
0)
temp[p, 5] <- max(temp[p, 3] + (0 - const1),
0)
temp[p, 6] <- temp[p, 1] - temp[p, 4] - temp[p, 5]
}
if (p>1) {
temp[p, 4] <- max(min(temp[p, 2],
temp[p, 1] + temp[p-1, 6]),
0)
temp[p, 5] <- max(temp[p, 3] + (temp[p-1, 6] - const1),
0)
temp[p, 6] <- temp[p-1, 6] + temp[p, 1] - temp[p, 4] - temp[p, 5]
}
}
Thanks in advance, hopefully this takes someone with Rcpp skills just a minute or two!
Here is an the sample Rcpp equivalent code:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix getResult(NumericMatrix x, double const1){
for (int p = 0; p < x.nrow(); p++){
if (p == 0){
x(p, 3) = std::max(std::min(x(p, 1), x(p, 0)), 0.0);
x(p, 4) = std::max(x(p, 2) + (0.0 - const1), 0.0);
x(p, 5) = x(p, 0) - x(p, 3) - x(p, 4);
}
if (p > 0){
x(p, 3) = std::max(std::min(x(p, 1), x(p, 0) + x(p - 1, 5)), 0.0);
x(p, 4) = std::max(x(p, 2) + (x(p - 1, 5) - const1), 0.0);
x(p, 5) = x(p - 1, 5) + x(p, 0) - x(p, 3) - x(p, 4);
}
}
return x;
}
A few notes:
Save this in a file and do Rcpp::sourceCpp("myCode.cpp") in your session to compile it and make it available within the session.
We use NumericMatrix here to represent the matrix.
You'll see that we call std::max and std::min respectively. These functions require two common data types, i.e. if we do max(x, y), both x and y must be of the same type. Numeric matrix entries are double (I believe), so you need to provide a double; hence, the change from 0 (an int in C++) to 0.0 (a double)
In C++, indexing starts from 0 instead of 1. As such, you convert R code like temp[1, 4] to temp(0, 3)
Have a look at http://adv-r.had.co.nz/Rcpp.html for more information to support your development
Update: If x was a list of vectors, here's an approach:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List getResult(List x, double const1){
// Create a new list from x called `res`
Rcpp::List res(x);
for (int p = 0; p < x.size(); p++){
// Initiate a NumericVector `curr` with the contents of `res[p]`
Rcpp::NumericVector curr(res[p]);
if (p == 0){
curr(3) = std::max(std::min(curr(1), curr(0)), 0.0);
curr(4) = std::max(curr(2) + (0.0 - const1), 0.0);
curr(5) = curr(0) - curr(3) - curr(4);
}
if (p > 0){
// Initiate a NumericVector `prev` with the contents of `res[p-1]`
Rcpp::NumericVector prev(res[p-1]);
curr(3) = std::max(std::min(curr(1), curr(0) + prev(5)), 0.0);
curr(4) = std::max(curr(2) + (prev(5) - const1), 0.0);
curr(5) = prev(5) + curr(0) - curr(3) - curr(4);
}
}
return x;
}
So I tried both jav's answers, and did a little bit of reading. Looks to me like Lists are a R-kinda-thing and Rcpp seems to prefer simple vectors and matrices and whatnot.
So I decided to pass my vectors from the list directly into the Rcpp script. The whole thing works wonders. My ~70 second script which I got down to about ~5 seconds with parallel processing is now running in 0.3 seconds. So Rcpp is pretty awesome at this as I had read.
Here's the code I went with:
(temp is a list of 3 vectors that feed into the calculation of the other 3 vectors, and that const 1 is a constant defined earlier in the code)
R code that calls the script:
temp <- getResult(zero=temp[[i]][, 1],
one=temp[[i]][, 2],
two=temp[[i]][, 3],
const1=constant, rows=(as.double(rowslength)))
Output is a matrix with 3 columns calculated by the following Rcpp script:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix AWBMgetResult(NumericVector zero, NumericVector one,
NumericVector two, double const1, double rows){
// create numericmatrix x
Rcpp::NumericMatrix x(rows, 3);
// compute loop
for (int p = 0; p < rows; p++){
if (p == 0){
x(p, 0) = std::max(std::min(one(p), zero(p)), 0.0);
x(p, 1) = std::max(two(p) + (0.0 - const1), 0.0);
x(p, 2) = zero(p) - x(p, 0) - x(p, 1);
}
else{
x(p, 0) = std::max(std::min(one(p), zero(p) + x(p - 1, 2)), 0.0);
x(p, 1) = std::max(two(p) + (x(p - 1, 2) - const1), 0.0);
x(p, 2) = x(p - 1, 2) + zero(p) - x(p, 0) - x(p, 1);
}
}
return x;
}
I went with if else in the Rcpp code because I couldn't find out how to do 2 loops in a row, 1 of for (p in 1:1) and 1 of for (p in 2:rowslength). But it doesn't seem to matter from a speed point of view. I assumed an if else would still be quicker than an if = 1, if > 1 (since that is checking the value of p at every row)
Related
I'm a newbie that is driving nuts with a really simple problem :\ How to define a quad that has its center at position x=10 y=11 z=12 with side 5 and it is facing at camera.
My naive implementation:
Eigen::Vector3f quadPosition(10, 11, 12);
Eigen::Vector3f camPos(10, 5, 12);
float sideLength = 5;
Eigen::Affine3f transform = Eigen::Translation3f(position) * Eigen::AngleAxisf(3.141595, (camPos - quadPosition).normalized());
Eigen::Vector3f v0 = transform * Eigen::Vector3f(-sideLength / 2, -sideLength / 2, 0);
Eigen::Vector3f v1 = transform * Eigen::Vector3f(sideLength / 2, -sideLength / 2, 0);
Eigen::Vector3f v2 = transform * Eigen::Vector3f(sideLength / 2, sideLength / 2, 0);
Eigen::Vector3f v3 = transform * Eigen::Vector3f(-sideLength / 2, sideLength / 2, 0);
Eigen::MatrixXd verts;
verts.resize(4, 3);
verts(0, 0) = v0(0);
verts(0, 1) = v0(1);
verts(0, 2) = v0(2);
verts(1, 0) = v1(0);
verts(1, 1) = v1(1);
verts(1, 2) = v1(2);
verts(2, 0) = v2(0);
verts(2, 1) = v2(1);
verts(2, 2) = v2(2);
verts(3, 0) = v3(0);
verts(3, 1) = v3(1);
verts(3, 2) = v3(2);
Eigen::MatrixXi faces;
faces.resize(2, 3);
faces(0, 0) = 0;
faces(0, 1) = 1;
faces(0, 2) = 2;
faces(1, 0) = 0;
faces(1, 1) = 2;
faces(1, 2) = 3;
Any idea? Thank you in advance!
One common approach is to define the quad in terms of two opposed corners like: [0,0,0] and [1,1,1]. Now you know that anything in between 0 and 1 in X, Y and Z axis belong to the box ... as long as there is no rotation. Otherwise, you could also add it.
I'm trying to calculate the points in a cuboid given its centre (which is a Vector3) and the lengths of the sides along the x, y and z axis. I found the following on math.stackexchange.com: https://math.stackexchange.com/questions/107778/simplest-equation-for-drawing-a-cube-based-on-its-center-and-or-other-vertices which says I can use the following formulae:
The constructor for the World class is:
World::World(Vector3 o, float d1, float d2, float d3) : origin(o)
{
// If we consider an edge length to be d, we need to find r such that
// 2r = d in order to calculate the positions of each vertex in the world.
float r1 = d1 / 2,
r2 = d2 / 2,
r3 = d3 / 2;
for (int i = 0; i < 8; i++)
{
/* Sets up the vertices of the cube.
*
* #see http://bit.ly/1cc2RPG
*/
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
points[i] = Vector3(x, y, z);
std::cout << points[i] << "\n";
}
}
And I passing the following parameters to the constructor:
Vector3 o(0, 0, 0);
World w(o, 100.f, 100.f, 100.f);
The coordinates being output for all 8 vertices are:
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
Which cannot be correct. Any guidance would be very much appreciated!
The problem lies in the bitwise & inside your pow calls:
In the y and z components, they always return 0 and 2 or 4, respectively. -1^2 = -1^4 = 1, which is why the sign of these components is always positive. You could try (i&2)!=0 or (i&2) >> 1 for the y component instead. The same goes for the z component.
Change this:
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
To this:
float x = o.getX() + (std::pow(-1, (i ) & 1) * r1), // pow(-1, 0) == 1, pow(-1, 1) == -1
y = o.getY() + (std::pow(-1, (i >> 1) & 1) * r2), // pow(-1, 0) == 1, pow(-1, 1) == -1
z = o.getZ() + (std::pow(-1, (i >> 2) & 1) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
Or even to this:
float x = o.getX() + (std::pow(-1, (i )) * r1), // pow(-1, {0, 2, 4, 6}) == 1, pow(-1, {1, 3, 5, 7}) == -1
y = o.getY() + (std::pow(-1, (i >> 1)) * r2), // pow(-1, {0, 2}) == 1, pow(-1, {1, 3}) == -1
z = o.getZ() + (std::pow(-1, (i >> 2)) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
The problem is that as written even though the values you mask out identify weather or not the lengths need to be negated. They are not in the correct place value to get the desired properties from the exponentiation of -1.
Rewriting the code as I have above will solve this issue, however it would be more readable and in general more permanent just to unroll the loop and manually write if each one is an addition or subtraction without using the pow function.
My understanding is that (one use of) numpy's vectorize allows me to send an array to a function that normally only takes scalars, instead of using the built in map function (in combination with a lambda function or the like). However, under the following scenario I am getting different results when I use map vs numpy.vectorize and I can't seem to figure out why.
import numpy as np
def basis2(dim, k, x):
y = np.array([-0.2, -0.13, -0.06, 0, 0.02, 0.06, 0.15, 0.3, 0.8,
1.6, 3.1, 6.1, 10.1, 15.1, 23.1, 30.1, 35.0, 40.0, 45.0, 50.0, 55.0])
if x < y[k] or x > y[k + dim + 1]:
return 0
elif dim != 0:
ret = ((x - y[k]) / (y[k + dim] - y[k])) * basis2(dim - 1, k, x) + (
(y[k + dim + 1] - x) / (y[k + dim + 1] - y[k + 1])) * basis2(dim - 1, k + 1, x)
return ret
else:
return 1.0
w = np.array([20.0, 23.1, 30.0])
func = lambda x: basis2(3, 14, x)
vec = map(func, w)
func2 = np.vectorize(basis2)
vec2 = func2(3, 14, w)
print vec # = [0, 0.0, 0.23335417007039491]
print vec2 # = [0 0 0]
As the docstring says:
The data type of the output of vectorized is determined by calling
the function with the first element of the input. This can be avoided
by specifying the otypes argument.
you need to add a otypes argument:
func2 = np.vectorize(basis2, otypes="d")
or change return 0 to return 0.0 in basis2().
This question already has an answer here:
Conway's Game of Life, counting neighbors [closed]
(1 answer)
Closed 9 years ago.
I am working on project containing cellular automat methods. What I am trying to figure is how to write function helping to find all the neighbours in a 2d array.
for example i ve got size x size 2d array [size = 4 here]
[x][n][ ][n]
[n][n][ ][n]
[ ][ ][ ][ ]
[n][n][ ][n]
Field marked as x [0,0 index] has neighbours marked as [n] -> 8 neighbours. What Im trying to do is to write a function which can find neighbours wo writting tousands of if statements
Does anybody have an idea how to do it ?
thanks
For the neighbours of element (i,j) in NxM matrix:
int above = (i-1) % N;
int below = (i+1) % N;
int left = (j-1) % M;
int right = (j+1) % M;
decltype(matrix[0][0]) *indices[8];
indices[0] = & matrix[above][left];
indices[1] = & matrix[above][j];
indices[2] = & matrix[above][right];
indices[3] = & matrix[i][left];
// Skip matrix[i][j]
indices[4] = & matrix[i][right];
indices[5] = & matrix[below][left];
indices[6] = & matrix[below][j];
indices[7] = & matrix[below][right];
Suppose you are in cell (i, j). Then, on an infinite grid, your neighbors should be [(i-1, j-1), (i-1,j), (i-1, j+1), (i, j-1), (i, j+1), (i+1, j-1), (i+1, j), (i+1, j+1)].
However, since the grid is finite some of the above values will get outside the bounds. But we know modular arithmetic: 4 % 3 = 1 and -1 % 3 = 2. So, if the grid is of size n, m you only need to apply %n, %m on the above list to get the proper list of neighbors: [((i-1) % n, (j-1) % m), ((i-1) % n,j), ((i-1) % n, (j+1) % m), (i, (j-1) % m), (i, (j+1) % m), ((i+1) % n, (j-1) % m), ((i+1) % n, j), ((i+1) % n, (j+1) % m)]
That works if your coordinates are between 0 and n and between 0 and m. If you start with 1 then you need to tweak the above by doing a -1 and a +1 somewhere.
For your case n=m=4 and (i, j) = (0, 0). The first list is [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]. Applying the modulus operations you get to [(3, 3), (3, 0), (3, 1), (0, 3), (0, 1), (1, 3), (1, 0), (1, 1)] which are exactly the squares marked [n] in your picture.
Add and subtract one from the coordinates, in all possible permutations. Results outside the boundaries wrap around (e.g. -1 becomes 3 and 4 becomes 0). Just a couple of simple loops needed basically.
Something like
// Find the closest neighbours (one step) from the coordinates [x,y]
// The max coordinates is max_x,max_y
// Note: Does not contain any error checking (for valid coordinates)
std::vector<std::pair<int, int>> getNeighbours(int x, int y, int max_x, int max_y)
{
std::vector<std::pair<int, int>> neighbours;
for (int dx = -1; dx <= 1; ++dx)
{
for (int dy = -1; dy <= 1; ++dy)
{
// Skip the coordinates [x,y]
if (dx == 0 && dy == 0)
continue;
int nx = x + dx;
int ny = y + dy;
// If the new coordinates goes out of bounds, wrap them around
if (nx < 0)
nx = max_x;
else if (nx > max_x)
nx = 0;
if (ny < 0)
ny = max_y;
else if (ny > max_y)
ny = 0;
// Add neighbouring coordinates to result
neighbours.push_back(std::make_pair(nx, ny));
}
}
return neighbours;
}
Example use for you:
auto n = getNeighbours(0, 0, 3, 3);
for (const auto& p : n)
std::cout << '[' << p.first << ',' << p.second << "]\n";
Prints out
[3,3]
[3,0]
[3,1]
[0,3]
[0,1]
[1,3]
[1,0]
[1,1]
which is the correct answer.
Nearly every OpenGL tutorial lets you implement drawing a cube. Therefore the vertices of the cube are needed. In the example code I saw a long list defining every vertex. But I would like to compute the vertices of a cube rather that using a overlong list of precomputed coordinates.
A cube is made of eight vertices and twelve triangles. Vertices are defined by x, y, and z. Triangles are defined each by the indexes of three vertices.
Is there an elegant way to compute the vertices and the element indexes of a cube?
When i was "porting" the csg.js project to Java I've found some cute code which generated cube with selected center point and radius. (I know it's JS, but anyway)
// Construct an axis-aligned solid cuboid. Optional parameters are `center` and
// `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be
// specified using a single number or a list of three numbers, one for each axis.
//
// Example code:
//
// var cube = CSG.cube({
// center: [0, 0, 0],
// radius: 1
// });
CSG.cube = function(options) {
options = options || {};
var c = new CSG.Vector(options.center || [0, 0, 0]);
var r = !options.radius ? [1, 1, 1] : options.radius.length ?
options.radius : [options.radius, options.radius, options.radius];
return CSG.fromPolygons([
[[0, 4, 6, 2], [-1, 0, 0]],
[[1, 3, 7, 5], [+1, 0, 0]],
[[0, 1, 5, 4], [0, -1, 0]],
[[2, 6, 7, 3], [0, +1, 0]],
[[0, 2, 3, 1], [0, 0, -1]],
[[4, 5, 7, 6], [0, 0, +1]]
].map(function(info) {
return new CSG.Polygon(info[0].map(function(i) {
var pos = new CSG.Vector(
c.x + r[0] * (2 * !!(i & 1) - 1),
c.y + r[1] * (2 * !!(i & 2) - 1),
c.z + r[2] * (2 * !!(i & 4) - 1)
);
return new CSG.Vertex(pos, new CSG.Vector(info[1]));
}));
}));
};
I solved this problem with this piece code (C#):
public CubeShape(Coord3 startPos, int size) {
int l = size / 2;
verts = new Coord3[8];
for (int i = 0; i < 8; i++) {
verts[i] = new Coord3(
(i & 4) != 0 ? l : -l,
(i & 2) != 0 ? l : -l,
(i & 1) != 0 ? l : -l) + startPos;
}
tris = new Tris[12];
int vertCount = 0;
void AddVert(int one, int two, int three) =>
tris[vertCount++] = new Tris(verts[one], verts[two], verts[three]);
for (int i = 0; i < 3; i++) {
int v1 = 1 << i;
int v2 = v1 == 4 ? 1 : v1 << 1;
AddVert(0, v1, v2);
AddVert(v1 + v2, v2, v1);
AddVert(7, 7 - v2, 7 - v1);
AddVert(7 - (v1 + v2), 7 - v1, 7 - v2);
}
}
If you want to understand more of what is going on, you can check out the github page I wrote that explains it.