Bizarre behavior of Rcpp NumericMatrix when multiplied by scalar on left/right - rcpp

Can anyone explain the following behavior?
When declaring a new NumericMatrix, y, as the original matrix, x, multiplied by a scalar, c, the order of the scalar/matrix multiplication matters. If I multiply the scalar on the left and the matrix on the right (e.g. NumericMatrix y = c * x;), then I get bizarre behavior. The original matrix, x, is changed!
However if I put the original matrix to the left and multiply the scalar on the right (e.g. NumericMatrix y = x * c;), x remains unchanged.
This doesn't seem to affect other data types. I've tested with int and NumericVector.
Example: Problem appears when using NumericMatrix
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix testfun(NumericMatrix x) {
NumericMatrix y(x.rows(), x.cols());
y = x * 2;
std::cout << x; // x is unmodified
y = 2 * x;
std::cout << x; // x is now modified
return x;
}
/*** R
x <- matrix(2, nrow = 3, ncol = 3)
print(x)
y <- testfun(x = x)
print(y)
print(x)
*/
The output is as follows.
> x <- matrix(2, nrow = 3, ncol = 3)
> print(x)
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 2 2 2
[3,] 2 2 2
> y <- testfun(x = x)
2.00000 2.00000 2.00000
2.00000 2.00000 2.00000
2.00000 2.00000 2.00000
4.00000 4.00000 4.00000
4.00000 4.00000 4.00000
4.00000 4.00000 4.00000
> print(y)
[,1] [,2] [,3]
[1,] 4 4 4
[2,] 4 4 4
[3,] 4 4 4
> print(x)
[,1] [,2] [,3]
[1,] 4 4 4
[2,] 4 4 4
[3,] 4 4 4
Here is my session info
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Catalina 10.15.1
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_3.6.1 tools_3.6.1 RcppArmadillo_0.9.800.1.0
[4] Rcpp_1.0.2 RcppProgress_0.4.1 packrat_0.5.0
[7] RcppParallel_4.4.4
.

The question is way too long as posted and hides its point. We do not need the second and third examples. All we need is this code:
Code
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix testfun(NumericMatrix x) {
NumericMatrix y(x.rows(), x.cols());
y = x * 2;
std::cout << x; // x is unmodified
y = 2 * x; // contrast with x * 2
std::cout << x; // x is now modified
return x;
}
/*** R
print(x <- matrix(2, nrow = 2, ncol = 2))
print(y <- testfun(x = x))
print(x)
*/
Output
R> Rcpp::sourceCpp("~/git/stackoverflow/59515517/question.cpp")
R> print(x <- matrix(2, nrow = 2, ncol = 2))
[,1] [,2]
[1,] 2 2
[2,] 2 2
R> print(y <- testfun(x = x))
2.00000 2.00000
2.00000 2.00000
4.00000 4.00000
4.00000 4.00000
[,1] [,2]
[1,] 4 4
[2,] 4 4
R> print(x)
[,1] [,2]
[1,] 4 4
[2,] 4 4
R>
Issue
Behaviour of x * 2 is different from 2 * x. The latter has a side effect. This is likely a bug,
Bigger issue
There is not really a point to do matrix algebra with Rcpp. The implementation is rudimentary and incomplete. If you want to do "math", use RcppArmadillo or RcppEigen.
Arma implementation
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat testfun(arma::mat x) {
arma::mat y(x.n_rows, x.n_cols);
y = x * 2;
std::cout << x; // x is unmodified
y = 2 * x; // contrast with x * 2
std::cout << x; // x is now modified
return x;
}
/*** R
print(x <- matrix(2, nrow = 2, ncol = 2))
print(y <- testfun(x = x))
print(x)
*/
Arma output
R> Rcpp::sourceCpp("~/git/stackoverflow/59515517/answer.cpp")
R> print(x <- matrix(2, nrow = 2, ncol = 2))
[,1] [,2]
[1,] 2 2
[2,] 2 2
R> print(y <- testfun(x = x))
2.0000 2.0000
2.0000 2.0000
2.0000 2.0000
2.0000 2.0000
[,1] [,2]
[1,] 2 2
[2,] 2 2
R> print(x)
[,1] [,2]
[1,] 2 2
[2,] 2 2
R>
I'll see if I can get to the Rcpp bug you found here.
Edit: It is a bug, and I don't quite understand it yet, but I added something to the issue where the code originated: https://github.com/RcppCore/Rcpp/issues/365
Edit 2: The fix is now in master. Thanks to KK for the PR, to everbody else hinting in the comments what may be behind this, and especially to Ralf for getting us all to try the fix.

Related

Display expression defined using lambda function

I am using the following code to find piecewise polynomial functions
import scipy
from scipy.interpolate import UnivariateSpline, splrep
x = np.array([0., 0.75, 1.8, 2.25, 3.75, 4.5, 6.45, 6.75,
7.5, 8.325, 10.875, 11.25, 12.525, 12.75, 15.,
20.85, 21.])
y = np.array([2.83811035, 2.81541896, 3.14311655,
3.22373554, 3.43033456, 3.50433385,
3.66794514, 3.462296, 3.59480959,
3.56250726, 3.6209845, 3.63034523,
3.68238915, 3.69096892, 3.75560395,
3.83545191, 3.90419498])
k = 3 # polynomial order
spl = UnivariateSpline(x, y, k=3, s=0.09)
xs = np.linspace(x.min(), x.max(), 100)
plt.plot(x, y, 'ro', ms=5)
plt.plot(xs, spl(xs), 'cyan', lw=5, alpha=0.3)
# get spline coeffs and knots
tck = (spl._data[8], spl._data[9], k) # tck = (knots, coefficients, degree)
p = scipy.interpolate.PPoly.from_spline(tck)
# plot each segment and return knots and coeffs
for idx, i in enumerate(range(k, len(spl.get_knots()) + k - 1)):
xs = np.linspace(p.x[i], p.x[i + 1], 100)
plt.plot(xs, np.polyval(p.c[:, i], xs - p.x[i]))
print("knot ", p.x[i], " to ", p.x[i + 1])
print("coeffs ", p.c[:, i], "\n")
f0 = lambda x: p.c[0, i] * (x - p.x[i]) ** 3 + p.c[1, i] * (x - p.x[i]) ** 2 + p.c[2, i] * (x - p.x[i]) + p.c[3, i]
f0 = lambda x: [p.c[:, i] * (x - p.x[i]) ** (3 - i) for i in range(k + 1)] # k = degree i.e no. of. coeffs = degree +1
print(f0)
plt.show()
print(f0) outputs <function fit_spline1.<locals>.<lambda> at 0x0000028697B94F70>.
Instead, I would like to display the polynomial expression.
Suggestions on how to do this will be really helpful.
EDIT:
I found the following in a post https://stackoverflow.com/a/60114991/8281509 . But not sure how to use this for my case.
from sympy import lambdify, bspline_basis_set
from sympy.abc import u
basis = bspline_basis_set(tck[2], tck[0], u)
for i, b in enumerate(basis):
print(f"Basis {i} :", b)
returns 16 basis function. Instead I expect only 3 for my case
You can use the string formatting like this:
for idx, i in enumerate(range(k, len(spl.get_knots()) + k - 1)):
xs = np.linspace(p.x[i], p.x[i + 1], 100)
plt.plot(xs, np.polyval(p.c[:, i], xs - p.x[i]))
print("knot ", p.x[i], " to ", p.x[i + 1])
print("coeffs ", p.c[:, i], "\n")
print(f"{p.c[0, i]} * {(x - p.x[i])} ** 3 + {p.c[1, i]} * {(x - p.x[i])} ** 2 + {p.c[2, i]} * {(x - p.x[i])} + {p.c[3, i]}")
Output:
0.00041014998689577995 * [ 0. 0.75 1.8 2.25 3.75 4.5 6.45 6.75 7.5 8.325
10.875 11.25 12.525 12.75 15. 20.85 21. ] ** 3 + -0.015832105893445334 * [ 0. 0.75 1.8 2.25 3.75 4.5 6.45 6.75 7.5 8.325
10.875 11.25 12.525 12.75 15. 20.85 21. ] ** 2 + 0.20309856945144328 * [ 0. 0.75 1.8 2.25 3.75 4.5 6.45 6.75 7.5 8.325
10.875 11.25 12.525 12.75 15. 20.85 21. ] + 2.8044698839070015
The array contents are printed. If you don't want it then replace it with literal u like this:
print(f"{p.c[0, i]} * u ** 3 + {p.c[1, i]} * u ** 2 + {p.c[2, i]} * u + {p.c[3, i]}")
Output:
0.00041014998689577995 * u ** 3 + -0.015832105893445334 * u ** 2 + 0.20309856945144328 * u + 2.8044698839070015

Rcpp: List <-> Matrix conversions by reference?? + Optimizing memory allocation when programming with matrices

As far as I understand it, in Rcpp a Matrix is implemented as a vector with a dimension attribute while a List is a kind of vector of different objects. Thus is there a trick to convert a List of vectors of equal length (i.e. a DataFrame) into a NumericMatrix (or arma::mat for that matter) and vice-versa by reference, that is without copying the data column-by column into the new data structure?
I presume that this is not possible as it would be extremely useful for R users and I'm sure I would have come across it. Under this assumption - which means List and Matrix methods need to be implemented separately - my question then becomes one of how to write Rcpp functions for Lists and Matrices that are equally efficient. My experience is that Lists are more memory efficient because they automatically allocate memory as they are filled, while matrices need to be defined and all memory allocated beforehand. Consider the example below: I have written two versions of a grouped sum - one for matrices and one for Lists / data.frames:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix gsumm(NumericMatrix x, int ng = 0, IntegerVector g = 0, bool fill = false) {
int n = x.nrow();
int c = x.ncol();
NumericMatrix sum(ng, c); // here memory needs to be allocated
for(int j = c; j--; ) {
NumericMatrix::Column column = x( _ , j);
NumericMatrix::Column sumj = sum( _ , j);
for(int i = n; i--; ) sumj[g[i]-1] += column[i];
}
if(fill) {
NumericMatrix out(n, c); // allocating space for this matrix is the main speed-killer
for(int j = c; j--; ) {
NumericMatrix::Column colo = out( _ , j);
NumericMatrix::Column sumj = sum( _ , j);
for(int i = n; i--; ) colo[i] = sumj[g[i]-1];
}
return out;
} else return sum;
}
// [[Rcpp::export]]
List gsuml(List x, int ng = 0, IntegerVector g = 0, bool fill = false) {
int l = x.size(), n;
List sum(l);
for(int j = l; j--; ) {
NumericVector column = x[j];
n = column.size();
NumericVector sumj(ng);
for(int i = n; i--; ) sumj[g[i]-1] += column[i];
sum[j] = sumj;
}
if(fill) for(int j = l; j--; ) {
NumericVector sgj(n);
NumericVector sumj = sum[j];
for(int i = n; i--; ) sgj[i] = sumj[g[i]-1];
sum[j] = sgj;
}
return sum;
}
if fill = false, the group-aggregated data is returned, while if fill = true, data of the same dimensions is returned where every element was replaced by it's in-group sum. In both cases the list method is faster, especially if fill = true where a full empty n x c matrix needs to be created before filling it up:
library(microbenchmark)
testm = matrix(rnorm(10000000), ncol = 1000)
testl = as.data.frame(testm)
ng = 1000
g = sample.int(ng, 10000, replace = TRUE)
> microbenchmark(gsumm(testm,ng,g, fill = FALSE),gsuml(testl,ng,g, fill = FALSE))
Unit: milliseconds
expr min lq mean median uq max neval
gsumm(testm, ng, g, fill = FALSE) 15.45847 16.28559 17.82400 16.67717 17.41415 63.40689 100
gsuml(testl, ng, g, fill = FALSE) 13.61055 14.12062 16.06388 14.59342 15.45356 96.93972 100
cld
a
a
> microbenchmark(gsumm(testm,ng,g, fill = TRUE),gsuml(testl,ng,g, fill = TRUE))
Unit: milliseconds
expr min lq mean median uq max neval cld
gsumm(testm, ng, g, fill = TRUE) 34.45835 36.28886 51.42828 39.87513 60.51453 242.2054 100 b
gsuml(testl, ng, g, fill = TRUE) 29.92314 30.69269 34.83283 31.33239 32.67136 115.8745 100 a
It would be great if both methods could be brought to the same speed. or potentially even made more efficient. I guess for that a way of programming with matrices that avoids huge apriori memory allocations needs to be devised. I am grateful for any comments and suggestions!
The amount of memory allocated in both your methods is the same. You can see this from the mem_alloc column when using bench::mark() for benchmarking:
> bench::mark(gsumm(testm,ng,g, fill = FALSE),gsuml(testl,ng,g, fill = FALSE), check = FALSE)
# A tibble: 2 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
<bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
1 gsumm(testm, ng, g, fill = FALSE) 14.1ms 15.1ms 64.7 7.63MB 0 33 0 510ms <dbl …
2 gsuml(testl, ng, g, fill = FALSE) 12.5ms 15.1ms 67.0 7.68MB 4.19 32 2 478ms <list…
# … with 3 more variables: memory <list>, time <list>, gc <list>
> bench::mark(gsumm(testm,ng,g, fill = TRUE),gsuml(testl,ng,g, fill = TRUE), check = FALSE)
# A tibble: 2 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
<bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
1 gsumm(testm, ng, g, fill = TRUE) 39.2ms 45.6ms 20.0 83.9MB 20.0 5 5 250ms <dbl …
2 gsuml(testl, ng, g, fill = TRUE) 30.3ms 32ms 26.7 84MB 20.0 8 6 299ms <list…
# … with 3 more variables: memory <list>, time <list>, gc <list>
However, the memory is not only allocated, which is fast anyway, but also initialized with zero everywhere. This is unnecessary in your case and can be avoided by replacing Rcpp::NumericMatrix mat(rows, cols) with Rcpp::NumericMatrix mat = Rcpp::no_init(rows, cols) as well as Rcpp::NumericVector vec(length) with Rcpp::NumericVector vec = Rcpp::no_init(length). If I do this with your code, both functions profit:
> bench::mark(gsumm(testm,ng,g, fill = FALSE),gsuml(testl,ng,g, fill = FALSE), check = FALSE)
# A tibble: 2 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
<bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
1 gsumm(testm, ng, g, fill = FALSE) 13ms 14.7ms 67.1 7.63MB 0 34 0 507ms <dbl …
2 gsuml(testl, ng, g, fill = FALSE) 12.8ms 14.6ms 67.4 7.68MB 2.04 33 1 489ms <list…
# … with 3 more variables: memory <list>, time <list>, gc <list>
> bench::mark(gsumm(testm,ng,g, fill = TRUE),gsuml(testl,ng,g, fill = TRUE), check = FALSE)
# A tibble: 2 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result
<bch:expr> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list>
1 gsumm(testm, ng, g, fill = TRUE) 27.5ms 31ms 26.6 83.9MB 10.7 10 4 375ms <dbl …
2 gsuml(testl, ng, g, fill = TRUE) 24.7ms 26.4ms 36.9 84MB 36.9 9 9 244ms <list…
# … with 3 more variables: memory <list>, time <list>, gc <list>
I am not sure why the matrix version profits more from not initializing the memory, though.

Unable to get the simplified coordinates using sympy - python

I have x2, x3, y2, y3, d1, d2, d3 values which is,
x2 = 0
x3 = 100
y2 = 0
y3 = 0
d1 = 100
d2 = 100
d3 = 87
When I use the below script,
from sympy import symbols, Eq, solve
x, y = symbols('x y')
eq1 = Eq((x - x2) ** 2 + (y - y2) ** 2 - d2 ** 2)
eq2 = Eq((x - x3) ** 2 + (y - y3) ** 2 - d3 ** 2)
sol_dict = solve((eq1, eq2), (x, y))
I got the ans as,
sol_dict = [(12431/200, -87*sqrt(32431)/200), (12431/200, 87*sqrt(32431)/200)]
How can I achieve the simplified solution like
sol_dict = [(62.155, -78.33), (62.155, 78.33)]
in python?
You can numerically evaluate the solution to get floats:
In [40]: [[x.evalf(3) for x in s] for s in sol_dict]
Out[40]: [[62.2, -78.3], [62.2, 78.3]]
I would only recommend doing that for display though. If you want to use the values in sol_dict for further calculations it's best to keep them as exact rational numbers.

Converting R for loop to C++ equivalent in Rcpp: Expected ; after top level declarator

I am fairly new learner to Rcpp, primarily needing it to speed up slow R code that is not easily parallelized because of dependencies within for loop iterations.
I wish to convert the following R code to C++ code to be directly used via Rcpp.
migrate_r <- function(pop) {
if (m != 0) {
if (model == "Step") {
for (i in 1:K) {
for (j in 1:K) {
for (k in 2:(K - 1)) {
i <- sample(perms, size = ceiling(perms * m/2), replace = FALSE)
j <- sample(perms, size = ceiling(perms * m/2), replace = FALSE)
tmp <- pop[i,, sample(k)]
pop[i,, sample(k)] <- pop[j,, sample(k)]
pop[j,, sample(k)] <- tmp
}
}
}
}
}
pop
}
My attempt is as follows:
// [[Rcpp::depends(RcppArmadillo)]]
#define ARMA_DONT_PRINT_OPENMP_WARNING
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
#include <set>
using namespace Rcpp;
// [[Rcpp::export]]
arma::Cube<int> migrate_cpp(arma::Cube<int> pop) {
String model;
int i, j, k, K, perms, tmp;
double m;
if (m != 0) {
if (model == "Step") {
for (i = 0; i < K; i++) {
for (j = 0; j < K; j++) {
for(k = 1; k < (K - 1); k++) {
i = RcppArmadillo::sample(perms, ceil(perms * m / 2), false);
j = RcppArmadillo::sample(perms, ceil(perms * m / 2), false);
tmp = pop[i, RcppArmadillo::sample(k, K, true)];
pop[i, RcppArmadillo::sample(k, K, true)] = pop[j, RcppArmadillo::sample(k, K, true)];
pop[j, RcppArmadillo::sample(k, K, true)] = tmp;
}
}
}
}
}
return pop;
}
Essentially both functions swap random rows in an 3-dimensional array ('pop') via a temporary variable. The C++ code doesn't run.
I know I am close to getting the C++ code to work, which will result in massive speedup compared to the R for loop.
Is there something I am missing here? Any assistance is greatly appreciated and warmly welcomed.
A reproducible example
##### Load packages #####
library(Rcpp)
library(RcppArmadillo)
### Set parameters ###
K <- 2
N <- 6
Hstar <- 5
probs <- rep(1/Hstar, Hstar)
m <- 0.20
perms <- 2 # number of permutations
num.specs <- ceiling(N / K)
haps <- 1:Hstar
specs <- 1:num.specs
gen.perms <- function() {
sample(haps, size = num.specs, replace = TRUE, prob = probs)
}
pop <- array(dim = c(perms, num.specs, K))
for (i in 1:K) {
pop[,, i] <- replicate(perms, gen.perms())
}
pop
, , 1
[,1] [,2] [,3]
[1,] 3 5 1
[2,] 2 3 3
, , 2
[,1] [,2] [,3]
[1,] 2 5 3
[2,] 3 5 3
migrate_r(pop) # notice rows have been swapped between subarrays
, , 1
[,1] [,2] [,3]
[1,] 3 5 1
[2,] 2 5 3
, , 2
[,1] [,2] [,3]
[1,] 3 5 3
[2,] 2 3 3

How to pass a differentiable function explicitly to T.grad?

Can you please tell, how can I pass various differentiable function to T.grad? I want something like this:
x = T.dscalar('x')
ellipic_paraboloid = x ** 2 + y ** 2
hyperbolic_paraboloid = x ** 2 - y ** 2
gradients = theano.function([function_of_xy, x, y], T.grad(function_of_xy, gx, gy))
gradients(ellipic_paraboloid, 1, 1)
gradients(hyperbolic_paraboloid, 1, 1)

Resources