The NLopt objective function looks like this:
double myfunc(const std::vector<double> &x, std::vector<double> &grad, void *my_func_data)
x is the data being optimized, grad is a vector of gradients, and my_func_data holds additional data.
I am interested in supplying Armadillo matrices A and B to void *my_func_data.
I fiddled with Armadillo's member functions
mat A(5,5);
mat B(5,5);
double* A_mem = A.memptr();
double* B_mem = B.memptr();
which gives me a pointers to the matrices A and B. I was thinking of defining another pointer to these pointers:
double** CombineMat;
int* Arow = A.n_rows; int* Acols = A.n_cols; //obtain dimensions of A
int* Brows = B.n_rows; int* Bcols = B.n_cols; // dim(B)
CombineMat[0] = A_mem; CombineMat[1] = Arows; CombineMat[2] = Acols;
CombineMat[3] = B_mem; CombineMat[4] = Brows; CombineMat[5] = Bcols;
and then passing *CombineMat as my_func_data.
- Is this the way to do it? It seems clumsy...
- Once CombineMat is passed, how do re-cast the void type into something usable when I'm inside myfunc?
ANSWER
I answered my own question with help from here.
mat A(2,2);
A << 1 << 2 << endr << 3 << 4;
mat B(2,2);
B << 5 << 6 << endr << 7 << 8;
mat C[2];
C[0] = A;
C[1] = B;
opt.set_min_objective(myfunc, &C);
Once inside myfunc, the data in C can be converted back to Armadillo matrices like this:
mat* pC = (mat*)(my_func_data);
mat A = pC[0];
mat B = pC[1];
You can also use Armadillo's Cube class ("3D matrix", or 3-rd order tensor).
Each slice in a cube is just a matrix. For example:
cube X(4,5,2);
mat A(4,5);
mat B(4,5);
X.slice(0) = A; // set the individual slices
X.slice(1) = B;
mat& C = X.slice(1); // get the reference to a matrix stored in a cube
来源:https://stackoverflow.com/questions/8434884/nlopt-with-armadillo-data