Calling BFGS optimization in C++ from optim.c - c++

So I have to rewrite my R code to C++. That is relatively easy, given the Rcpp package. I came across a problem while solving an optimization problem. In R I call:
optimum_optim = optim(par=A, fn=negative_LL, gr=negative_grad_LL, .c = c, .t = t, .i = i, .N = N, method = 'BFGS')
Given that I have rewritten the negative_LL and negative_grad_LL functions into my C++ file already I wanted to call the underlying routine for BFGS optimization from R: it is the vmmin function from optim.c
I have the problem that I cannot understand the signature of that function. It is:
vmmin(int n0, double *b, double *Fmin, optimfn fminfn, optimgr fmingr,
int maxit, int trace, int *mask,
double abstol, double reltol, int nREPORT, void *ex,
int *fncount, int *grcount, int *fail)
It's not that I did not put any effort into search - I just cannot find a description... Could someone please help call this function in my particular case (and tell me what the arguments are)?

It sounds like you've already been using this advice, but you need to go a bit deeper: "Use the source, Luke".
My starting point was to, from the R console, type simply
optim
This prints the R source code of that function. There I saw it calls
.External2(C_optim, par, fn1, gr1, method, con, lower, upper)
My favorite mirror for the R source code is this GitHub repo. If you head there, search for "optim", and filter only the C results, we'll go to the top hit, src/library/stats/src/optim.c. Then we can see how the C-level optim() (line 177) function calls vmmin() (line 295).
The way optim() initializes those arguments is as follows
int n length(par)
double *b vect(npar); dpar[i] = REAL(par)[i] / (OS->parscale[i])
double *Fmin 0.0
optimfn fn function defined in the C code
optimgr gr function defined in the C code
int maxit asInteger(getListElement(options, "maxit"))
int trace asInteger(getListElement(options, "trace"))
int *mask mask = (int *) R_alloc(npar, sizeof(int));
for (i = 0; i < npar; i++) mask[i] = 1;
double abstol asInteger(getListElement(options, "abstol"))
double reltol asInteger(getListElement(options, "reltol"))
int nREPORT asInteger(getListElement(options, "REPORT"));
void *ex OptStruct OS; /* tons of stuff done to this */
int *fncount 0
int *grcount 0
int *fail 0
I haven't put in all the details here, but I believe this should be enough to help you figure out how you need to use these things in your own function, once you find out about one other thing: the control list in optim(). If you notice in the .External2() call from above, there's an argument called con. This is defined in the R code as
con <- list(trace = 0, fnscale = 1, parscale = rep.int(1, npar),
ndeps = rep.int(1e-3, npar),
maxit = 100L, abstol = -Inf, reltol = sqrt(.Machine$double.eps),
alpha = 1.0, beta = 0.5, gamma = 2.0,
REPORT = 10, warn.1d.NelderMead = TRUE,
type = 1,
lmm = 5, factr = 1e7, pgtol = 0,
tmax = 10, temp = 10.0)
though these elements can be overridden by user input in the control argument, and if you check out help("optim"), you'll see
The ‘control’ argument is a list that can supply any of the following components:
‘trace’ ...
The C function refers to this list by the name options that you see referenced several times in the table I constructed above.

Related

Incompatible types in assignment of variables in C++

recently I have been trying to make a Neural Network with an arduino library and I came across a library, that was quite literally, called Neural Network by George Chousos. I stumbled apon a couple of errors that I managed to fix quite simply, but then I got caught on the error of
sketch_sep22b:24:43: error: incompatible types in assignment of 'float*' to 'float [4]' outputs = NN.FeedForward(inputs[i]);
This is all of my code:
#include <math.h> // Include Math Library
#include <NeuralNetwork.h> // Include Neural Network Framework
const unsigned int layers[] = {4, 9, 4}; // First Value (Inputs), Second Value (Neurons / Hidden Layers), Third Value (Outputs)
float outputs[4] = {}; //Outputs Float
const float* /* Pointer */ inputs[1] = {1};
const float expectedOutputs[1] = {1}; //Training Values
void setup()
{
Serial.begin(9600);
NeuralNetwork NN(layers, NumberOf(layers));
for (int i = 0; i < 3000; i++)
{
for (int j = 0; j < NumberOf(inputs); j++)
{
for (int i = 0; i < NumberOf(inputs) - 1; i++)
{
outputs = NN.FeedForward(inputs[i]);
Serial.println(outputs[0], 7);
}
NN.print();
}
}
}
Edit:
The declaration for FeedForward is:
float *FeedForward(const float *inputs); // Moves Calculated outputs as inputs to next layer.
Okay, I looked at the link and the declaration. The first problem, and the one that's leading to the compiler error is the return type. The declaration is expecting output to be a pointer, not an array. So, changing the declaration of output to:
float* outputs; //Outputs Float
should fix the compiler error. I haven't tried it, but that looks to be the issue the compiler is catching. This will likely return a pointer to an array of 4 floats which you will need to deallocate later (using either free or delete[] depending on how the library allocated the memory) once you're done with it or it will create a memory leak.
As others have noted, your current declaration of input is attempting to access a fixed memory location (1) which leads to undefined behavior, so, you still need to address this as well. Since the library appears to be expecting an input with 4 float values, you should either give it an array with 4 float values declared at compile time, or you could dynamically allocate an array with 4 values at run time.
The first option looks like this:
const float inputs[4] = {1.0, 2.0, 3.0, 4.0};
The second option looks like:
float* input;
...
input = new float[4];
input[0] = 1.0;
input[1] = 2.0;
input[2] = 3.0;
input[3] = 4.0;
...
output = NN.FeedForward(input);
...
delete[] input;

Declaration issues - C++

TL;DR - Have some instructions on how to use some C++ code from a github readme (see below) and I'm struggling to implement them as I have never done any C++ before.
So first things first; I am a science student with an okay background in python. I need to use some code thats been written in C++ (I have never used C++ before). Over the past few days I've been googling like a madman in order to figure out how to use the code. Nonetheless excuse me if I've made silly pythonic mistakes everywhere. The github gives these instructions:
"To generate an adjacency matrix for a single statistically homogeneous network in a C++ program, include the header file secorder_rec_1p.hpp and call secorder_rec_1p as
gsl_matrix *W = secorder_rec_1p(N_nodes, p, alpha_recip, alpha_conv,alpha_div, cc_chain, rng);
where N_nodes is the number of nodes in the network and rng is a pointer to an initialized gsl random number generator. W is an adjacency matrix where W_ij=1 if there is a connection from node j onto node i and is zero otherwise."
For someone who has never done C++ before this was at first rather confusing. After much googling etc it is now less confusing and I have a .c file that I was hoping would do the trick. Unfortunately it's giving me an error I somewhat understand but dont know how to fix.
so my code is:
#include "secorder_rec_1p.hpp"
#include <time.h>
#include <gsl/gsl_rng.h>
using namespace std;
extern int N;
extern double p, recip, conv, divg, chain;
int main (){
int N;
N = 1000;
gsl_rng * rng = gsl_rng_alloc(gsl_rng_taus); //I'm not really sure what it does but I don't get any mention of this in the errors so I think it's ok. Not entirely sure if this is a "pointer to an initialized gsl random num generator"
double p, recip, conv, divg, chain;
recip = 0.1;
p = 0.1;
conv = 0.1;
divg = 0.1;
chain = 0.1;
int W [N][N];
int i,j;
double result = rand()/ RAND_MAX;
for(i=0; i<N; i++)
for(j=0; j<N; j++)
{
if(result > p){
W [i][j] = 1;
} else {
W[i][j] = 0;
}
}
gsl_matrix *W = secorder_rec_1p(N, p, recip, conv, divg, chain, rng);
}
I'm getting a declaration error when I try to "make" the .c file (this is compiling it right? I need to do this before I can actually run the script?). The error cites a conflicting declaration with my W's.
My (obviously incorrect) understanding is that I'm creating an N by N array (matrix?) that is filled with 1s and 0s where element M_ij is 1 with a probability p and 0 otherwise.
Then this is where my understanding falls apart a little, but *W means it points to the thing labelled by W, so it should be my matrix and a gsl_matrix that are equal to the output of that function. I'm not sure what the equals means in this case because it should be generating a new matrix. So if this was python I'd expect the name of my new matrix to be on the left hand side of the equals and the stuff on the right the code used to generate it. I'm not sure what's going on here though.
Any help with my error as well as information about how c++ works etc is greatly appreciated.

ctypes: Initialize array of arrays and pass to C function

I've been fooling with ctypes and have come across two problems:
Problem 1. I would like to build a cellComplex using double* arrays, but I want new_cellComplex to accept an array of double*'s (along with a size_t argument) rather than a fixed number of double*'s. With a fixed number the code looks like this (and it runs fine):
extern "C" {
void * new_cellComplex(double* p_x, double* p_y, double* p_z) {
std::vector< std::pair<double,double> > point;
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
with Python code:
import ctypes
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [ctypes.c_double*2,
ctypes.c_double*2,
ctypes.c_double*2]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
cmplx = cellComplex_lib.new_cellComplex(p_x,p_y,p_z)
I would rather have the following (which segfaults):
extern "C" {
void * new_cellComplex(double** p, size_t dim) {
std::vector< std::pair<double,double> > point;
for (size_t i=0; i<dim; ++i) {
point.push_back( std::make_pair(p[i][0],p[i][1]));
}
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
}
With Python code:
import ctypes
dim = 3
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [(ctypes.c_double*2)*dim,
ctypes.c_size_t]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
p = ((ctypes.c_double*2)*dim)(p_x,p_y,p_z)
cmplx = cellComplex_lib.new_cellComplex(p,dim)
^This doesn't work and I don't know why.
Problem 2. (Included here because it's glaring in Problem 1) I am returning an essentially anonymous pointer from my C code! This just feels, well, dirty, and there must be a better way to return a custom data type and deal with it back in Python. For the record, I am extremely grateful for this stackoverflow answer where I learned such sorcery - but I'm not going to be able to sleep at night as long as it's in my code...
Instead of double **, use double [][2]. You're passing a contiguous C array that you want to access as a pointer to a row of 2 items. The first index is the row index.
Declaring the array as a double ** is a pointer to a double pointer, so p[i] is a pointer, and p[i][0] dereferences it again. But p[i] is a NULL pointer by chance according to your data.
Refer to the comp.lang.c FAQ, question
6.18: My compiler complained when I passed a two-dimensional array to a function expecting a
pointer to a pointer.
For the return type, you can subclass c_void_p, or use the hooks from_param and _as_parameter_ per the last paragraph of section 15.17.1.7 in the ctypes docs.

Rcpp function to be SLOWER than same R function

I have been coding a R function to compute an integral with respect to certain distributions, see code below.
EVofPsi = function(psi, probabilityMeasure, eps=0.01, ...){
distFun = function(u){
probabilityMeasure(u, ...)
}
xx = yy = seq(0,1,length=1/eps+1)
summand=0
for(i in 1:(length(xx)-1)){
for(j in 1:(length(yy)-1)){
signPlus = distFun(c(xx[i+1],yy[j+1]))+distFun(c(xx[i],yy[j]))
signMinus = distFun(c(xx[i+1],yy[j]))+distFun(c(xx[i],yy[j+1]))
summand = c(summand, psi(c(xx[i],yy[j]))*(signPlus-signMinus))
}
}
sum(summand)
}
It works fine, but it is pretty slow. It is common to hear that re-programming the function in a compiled language such as C++ would speed it up, especially because the R code above involves a double loop. So did I, using Rcpp:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double EVofPsiCPP(Function distFun, Function psi, int n, double eps) {
NumericVector xx(n+1);
NumericVector yy(n+1);
xx[0] = 0;
yy[0] = 0;
// discretize [0,1]^2
for(int i = 1; i < n+1; i++) {
xx[i] = xx[i-1] + eps;
yy[i] = yy[i-1] + eps;
}
Function psiCPP(psi);
Function distFunCPP(distFun);
double signPlus;
double signMinus;
double summand = 0;
NumericVector topRight(2);
NumericVector bottomLeft(2);
NumericVector bottomRight(2);
NumericVector topLeft(2);
// compute the integral
for(int i=0; i<n; i++){
//printf("i:%d \n",i);
for(int j=0; j<n; j++){
//printf("j:%d \n",j);
topRight[0] = xx[i+1];
topRight[1] = yy[j+1];
bottomLeft[0] = xx[i];
bottomLeft[1] = yy[j];
bottomRight[0] = xx[i+1];
bottomRight[1] = yy[j];
topLeft[0] = xx[i];
topLeft[1] = yy[j+1];
signPlus = NumericVector(distFunCPP(topRight))[0] + NumericVector(distFunCPP(bottomLeft))[0];
signMinus = NumericVector(distFunCPP(bottomRight))[0] + NumericVector(distFunCPP(topLeft))[0];
summand = summand + NumericVector(psiCPP(bottomLeft))[0]*(signPlus-signMinus);
//printf("summand:%f \n",summand);
}
}
return summand;
}
I'm pretty happy since this C++ function works fine. However, when I tested both functions, the C++ one ran SLOWER:
sourceCpp("EVofPsiCPP.cpp")
pFGM = function(u,theta){
u[1]*u[2] + theta*u[1]*u[2]*(1-u[1])*(1-u[2])
}
psi = function(u){
u[1]*u[2]
}
print(system.time(
for(i in 1:10){
test = EVofPsi(psi, pFGM, 1/100, 0.2)
}
))
test
print(system.time(
for(i in 1:10){
test = EVofPsiCPP(psi, function(u){pFGM(u,0.2)}, 100, 1/100)
}
))
So, is there some kind expert around willing to explain me this? Did I code like a monkey and is there a way to speed up that function? Moreover, I would have a second question. Indeed, I could have replaced the output type double by SEXP, and the argument types Function by SEXP as well, it doesn't seem to change anything. So what is the difference?
Thank you very much in advance,
Gildas
Others have answered in comments already. So I'll just emphasize the point: Calling back to R functions is expensive as we need to be extra cautious about error handling. Just having the loop in C++ and call R functions is not rewriting your code in C++. Try rewriting psi and pFGM as C++ functions and report back here what happens.
You might argue that you lose some flexibility and you're not able anymore to use any R function. For situations like this, I'd advise to use some sort of hybrid solution where you have implemented the most common cases in C++ and fallback to an R solution otherwise.
As for the other question, a SEXP is an R object. This is part of the R API. It can be anything. When you create a Function from it (as is done implicitly for you when create a function that takes a Function argument), you are guaranteed that this is indeed an R function. The overhead is very small, but the gain in terms of expressiveness of your code is huge.

Simple question regarding an equation inside of a function

Hey, so basically I have this issue, where I'm trying to put an equation inside of a function however it doesn't seem to set the value to the function and instead doesn't change it at all.
This is a predator prey simulation and I have this code inside of a for loop.
wolves[i+1] = ((1 - wBr) * wolves[i] + I * S * rabbits[i] * wolves[i]);
rabbits[i+1] = (1 + rBr) * rabbits[i] - I * rabbits[i] * wolves[i];
When I execute this, it works as intended and changes the value of both of these arrays appropriately, however when I try to put it inside of a function,
int calcRabbits(int R, int rBr, int I, int W)
{
int x = (1 + rBr) * R - I * R * W;
return x;
}
int calcWolves(int wBr, int W, int I, int S, int R)
{
int x = ((1 - wBr) * W + I * S * R * R);
return x;
}
And set the values as such
rabbits[i+1] = calcRabbits ( rabbits[i], rBr, I, wolves[i]);
wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
The values remain the same as they were when they were initialized and it doesn't seem to work at all, and I have no idea why. I have been at this for a good few hours and it's probably something that I'm missing, but I can't figure it out.
Any and all help is appreciated.
Edit: I realized the parameters were wrong, but I tried it before with the correct parameters and it still didnt work, just accidentally changed it to the wrong parameters (Compiler mouse-over was showing the old version of the parameters)
Edit2: The entire section of code is this
days = getDays(); // Runs function to get Number of days to run the simulation for
dayCycle = getCycle(); // Runs the function get Cycle to get the # of days to mod by
int wolves[days]; // Creates array wolves[] the size of the amount of days
int rabbits[days]; // Creates array rabbits [] the size of the amount of days
wolves[0] = W; // Sets the value of the starting number of wolves
rabbits[0] = R; // sets starting value of rabbits
for(int i = 0; i < days; i++) // For loop runs the simulation for the number of days
{
// rabbits[i+1] = calcRabbits ( rabbits[i], rBr, I, wolves[i]);
// // //This is the code to change the value of both of these using the function
// wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
// This is the code that works and correctly sets the value for wolves[i+1]
wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
rabbits[i+1] = (1 + rBr) * rabbits[i] - I * rabbits[i] * wolves[i];
}
Edit: I realized my mistake, I was putting rBr and wBr in as ints, and they were floats which were numbers that were below 1, so they were being automatically converted to be 0. Thanks sje
Phil I cannot see anything evidently wrong in your code.
My hunch is that your are messing up the parameters.
Using gdb at this point would be an over kill. I recommend you put print outs in calcRabbits and calcWolves. Print out all the parameters, the new value, and the iteration number. That will give you a good idea of what is going on and will help trace the problem.
Do you have the full code with initialization we could try to test and run?
I'm not sure this is the problem, but this is bad:
int wolves[days]; // Creates array wolves[] the size of the amount of days
int rabbits[days]; // Creates array rabbits [] the size of the amount of days
days is determined at runtime. This is nonstandard in c++ (and for large number of days could destroy your stack) you should only be using constants in array sizes. You can dynamically size a vector to workaround this limitation (or heap allocate the array).
Change to this:
std::vector<int> wolves(days);
std::vector<int> rabbits(days);
Or to this:
int *wolves = new int[days];
int *rabbits = new int[days];
// all your code goes here
delete [] wolves; // when you're done
delete [] rabbits; // when you're done
Which will dynamically allocate the array on the heap. The rest of the code should work the same.
Don't forget to #include <vector>, if you use the vector approach.
If you're still having problems, I would cout << "Days: " << days << endl; to make sure you're getting the right number back from getDays(). If you got zero, it would seem to manifest itself in "the loop not working".
I was using an integer as an argument for a double.