Any example of `cholmod_updown_solve()` (Updating in CHOLMOD)? - c++

I'm working on a project using CHOLMOD in C++ to do Cholesky factorization updating. The only reference I can find is the User Guide. And cholmod_updown_solve() seems to be the right function for me. But there is no example on this function and I can't get a correct result.
Below is the essential part of my code. According to the user guide, the only thing to notice seems to be sorting the update matrix C in advance. But that doesn't work. Could anyone tell me if there's any important step I missed?
Also, I'm confused because the user guide says that the solution phi will be given "in the permuted ordering, not your original ordering". How could I restore the order without knowing the permutation matrix? (L->Perm doesn't work.)
// The original system is At*A*phi = At*b
// Updates: C*Ct is added to At*A (Here C is a sparse column vector)
size_t n = m_pMesh->numVertices();
double w = 1e3;
cholmod_sparse *C;
cholmod_triplet *C_coefficients;
cholmod_dense *Delta_Atb;
cholmod_common common;
cholmod_common *cm = &common;
cholmod_start(cm);
C_coefficients = cholmod_allocate_triplet(n, 1, 2, 0, CHOLMOD_REAL, cm);
Delta_Atb = cholmod_zeros(n, 1, CHOLMOD_REAL, cm);
// updates: two more constraints
CViewerVertex *pNew = stroke_ends.start;
CViewerVertex *qNew = stroke_ends.end;
cholmodEntry(C_coefficients, pNew->sid(), pNew->sid(), w, cm);
cholmodEntry(C_coefficients, qNew->sid(), qNew->sid(), w, cm);
// change to At*b is Delta_Atb
((double*)Delta_Atb->x)[pNew->sid()] = w * w;
C = cholmod_triplet_to_sparse(C_coefficients, C_coefficients->nnz, cm);
cholmod_sort(C, cm);
// phi is the given solution to the original system At*A*phi = At*b
// L is the Cholesky factor to modify
// Both phi and L should be overwritten here
cholmod_updown_solve(1, C, L, phi, Delta_Atb, cm);
cholmod_free_sparse(&C, cm);
cholmod_free_triplet(&C_coefficients, cm);
cholmod_free_dense(&Delta_Atb, cm);
cholmod_finish(cm);

Related

How to solve a state space model with Odeint?

I am trying to implement a numerical simulation of a state space model using Eigen and Odeint. My trouble is that I need to reference control data U (predefined before integration) in order to properly solve the Ax+Bu part of the state space model. I was trying to accomplish this by using a counter to keep track of the current time step, but for whatever reason, it is reset to zero every time the System Function is called by Odeint.
How would I get around this? Is my approach to modeling the state space system flawed?
My System
struct Eigen_SS_NLTIV_Model
{
Eigen_SS_NLTIV_Model(matrixXd &ssA, matrixXd &ssB, matrixXd &ssC,
matrixXd &ssD, matrixXd &ssU, matrixXd &ssY)
:A(ssA), B(ssB), C(ssC), D(ssD), U(ssU), Y(ssY)
{
Y.resizeLike(U);
Y.setZero();
observerStep = 0;
testPtr = &observerStep;
}
/* Observer Function:*/
void operator()(matrixXd &x, double t)
{
Y.col(observerStep) = C*x + D*U.col(observerStep);
observerStep += 1;
}
/* System Function:
* ONLY the mathematical description of the system dynamics may be placed
* here. Any data placed in here is destroyed after each iteration of the
* stepper.
*/
void operator()(matrixXd &x, matrixXd &dxdt, double t)
{
dxdt = A*x + B*U.col(*testPtr);
//Cannot reference the variable "observerStep" directly as it gets reset
//every time this is called. *testPtr doesn't work either.
}
int observerStep;
int *testPtr;
matrixXd &A, &B, &C, &D, &U, &Y; //Input Vectors
};
My ODE Solver Setup
const double t_end = 3.0;
const double dt = 0.5;
int steps = (int)std::ceil(t_end / dt) + 1;
matrixXd A(2, 2), B(2, 2), C(2, 2), D(2, 2), x(2, 1);
matrixXd U = matrixXd::Constant(2, steps, 1.0);
matrixXd Y;
A << -0.5572, -0.7814, 0.7814, 0.0000;
B << 1.0, -1.0, 0.0, 2.0;
C << 1.9691, 6.4493, 1.9691, 6.4493;
D << 0.0, 0.0, 0.0, 0.0;
x << 0, 0;
Eigen_SS_NLTIV_Model matrixTest(A, B, C, D, U, Y);
odeint::integrate_const(odeint::runge_kutta4<matrixXd, double, matrixXd, double,
odeint::vector_space_algebra>(),
matrixTest, x, 0.0, t_end, dt, matrixTest);
//Ignore these two functions. They are there mostly for debugging.
writeCSV<matrixXd>(Y, "Y_OUT.csv");
prettyPrint<matrixXd>(Y, "Out Full");
With classical Runge-Kutta you know that your ODE model function is called 4 times per step with times t, t+h/2, t+h/2, t+h. With other solvers that implement adaptive step size you can not know in advance at what t the ODE model function is called.
You should implement U via some kind of interpolation function, in the most simple case as step function that computes some index from t and returns the U value for that index. Something like
i = (int)(t/U_step)
dxdt = A*x + B*U.col(i);

Matrix multiplication issues using C++ Eigen, and matlab mexFunction

// computing the matrix operation here
// resultEigen = Input matrix
// result1Eigen = hidden bias
// result2Eigen = visible bias
// result3Eigen = weight matrix
MatrixXd H;
MatrixXd V;
double well[36];
Map<MatrixXd>( well, H.rows(), H.cols() ) = H;
H = resultEigen * result3Eigen + result1Eigen;
mexPrintf("H is here\n");
for (int i=0; i<36; i++)
{
mexPrintf("%d\n",H);
}
mexPrintf("\n");
I need to build a reconstructing function for my RBM and since direct matrix multiplication could get me a better result, I have been referring to eigen library to solve my issues but I am facing some difficulties.
when running the above code I end up getting a single value for the H matrix and I wonder why!
Moreover the parameters used in for the computation of H have been initiated as follows:
double *data1 = hbias;
Map<VectorXd>hidden_bias(data1,6,1);
VectorXd result1Eigen;
double result1[6];
result1Eigen = hidden_bias.transpose();
Map<VectorXd>(result1, result1Eigen.cols()) = result1Eigen;
// next param
double *data2 = vbias;
Map<VectorXd>visible_bias(data2,6,1);
VectorXd result2Eigen;
double result2[6];
result2Eigen = visible_bias.transpose();
Map<VectorXd>(result2, result2Eigen.cols()) = result2Eigen;
// next param
double *data3 = w;
Map<MatrixXd>weight_matrix(data3,n_visible,n_hidden);
MatrixXd result3Eigen;
// double result3[36];
mxArray * result3Matrix = mxCreateDoubleMatrix(n_visible, n_hidden, mxREAL );
double *result3=(double*)mxGetData(result3Matrix);
result3Eigen = weight_matrix.transpose();
Map<MatrixXd>(result3, result3Eigen.rows(), result3Eigen.cols()) = result3Eigen
At last I also face issues printing out data using std::cout from inside the mexFunction.
Thanks for any hints.
The problem is in the printing code which should be:
mexPrintf("%d\n",H(i));
Then, there is no need to duplicate vectors and matrices. For instance, result1 is useless, as you can get a raw pointer to the data stored in result1Eigen using result1Eigen.data(). Likewise, you can directly assign weight_matrix.transpose() to Map<MatrixXd>(result3,...), and I don't see the purpose of well.
Finally, if sizes are really known at compile-time, then better using Matrix<double,6,1> instead of a VectorXd and Matrix<double,6,6> instead of a MatrixXd. Yo ucan expect significant speedup.

C++ Objective AlgLib

I have an c++ code. that i have to use in objective c.
double[,] x = new double[,]{{-1},{-0.8},{-0.6},{-0.4},{-0.2},{0},{0.2},{0.4},{0.6},{0.8},{1.0}};
double[] y = new double[]{0.223130,0.382893,0.582748,0.786628,0.941765,1.000000,0.941765,0.786628,0.582748,0.382893,0.223130};
double[] c = new double[]{0.3};
double epsf = 0;
double epsx = 0.000001;
int maxits = 0;
int info;
alglib::lsfitstate state;
alglib::lsfitreport rep;
double diffstep = 0.0001;
//
// Fitting with weights
// (you can change weights and see how it changes result)
//
double[] w = new double[]{1,1,1,1,1,1,1,1,1,1,1};
alglib::lsfitcreatewf(x, y, w, c, diffstep, out state);
alglib::lsfitsetcond(state, epsf, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func, null, null);
alglib::lsfitresults(state, out info, out c, out rep);
i already called my objective file at the end with .mm
But i get difference Errors. (first lines - expected expression when i init my vars).
I can't c++. But i only need this one function.
I hope that this is a solution for this question.
https://gis.stackexchange.com/questions/74567/math-algorithm-for-n-amount-points-in-objective-c
That is mostly Java code at the beginning for the array declarations, not C, C++ or ObjC.
This would be C/C++ code:
double x[][1] = {{-1},{-0.8},{-0.6},{-0.4},{-0.2},{0},{0.2},{0.4},{0.6},{0.8},{1.0}};
double y[] = {0.223130,0.382893,0.582748,0.786628,0.941765,1.000000,0.941765,0.786628,0.582748,0.382893,0.223130};
double c[] = {0.3};
However, according to the lsfitcreatewf function reference here, you need it to be of the type alglib::real_2d_array. There are some examples here how to generate such data.
Here and following are some general examples about how to use the lsfit subpackage.

How to add elements to a triplet matrix using CHOLMOD?

Can anyone please give me a simple example of how to add elements to a triplet matrix using CHOLMOD.
I have tried something like this:
cholmod_triplet *A;
int k;
void add_A_entry(int r, int c, double x)
{
((int*)A->i)[k] = r;
((int*)A->j)[k] = c;
((double*)A->x)[k] = x;
k++;
}
int main()
{
k = 0;
cholmod_common com;
cholmod_start(&com);
A = cholmod_allocate_triplet(202, 202, 202*202, -1, CHOLMOD_REAL, &com);
add_A_entry(2, 2, 1.);
add_A_entry(4, 1, 2.);
add_A_entry(2, 10, -1.);
cholmod_print_triplet(A, "A", &com);
cholmod_finish(&com);
return 0;
}
However, this doesn't add any elements to the matrix. I simply get the output:
CHOLMOD triplet: A: 202-by-202, nz 0, lower. OK
Of course, I have tried to find the solution both by searching and in the CHOLMOD documentation, but I found no help.
cholmod_allocate_triplet() sets A->nzmax, which in your case is 202*202. That just defines the space available to add triplets. The actual number of triplets in the matrix is A->nnz, which gets set to zero by cholmod_allocate_triplet().
The A->nnz should be used instead of your variable k.
Tim Davis (CHOLMOD author)

Creating a sparse matrix in CHOLMOD or SuiteSparseQR

In SparseSuiteQR, all of the examples I can find use stdin or a file read to create a sparse matrix. Could someone provide a simple example of how to create one directly in C++?
Even better, in the CHOLMOD documentation, there is mention of a sparse2 function available in matlab, which behaves the same as the sparse. Can this be used in C++?
The data structures used by SuiteSparseQR (e.g. cholmod_sparse) are defined in the CHOLMOD library. You can find more information about it on the CHOLMOD documentation, which is much larger than the one from SuiteSparseQR.
I am assuming that you try to solve a linear system, see the CSparse package from Tim Davies, or boost matrix libraries which also have numeric bindings which interface umfpack and some lapack functions AFAIK...
CHOLMOD is a pretty awesome project - thanks Tim Davis :)
There is surprisingly a lot of code on GitHub that makes use of CHOLMOD, but you have to be logged into GitHub and know what you're looking for!
So, after crawling through CHOLMOD documentation and source code and then searching through GitHub for source code that uses CHOLMOD you would find out what to do.
But for most developers who want/need a quick example, here it is below.
*Note that your mileage might vary depending on how you compiled SuiteSparse.
(You might need to use the cholmod_ variant (without the l), i.e. not cholmod_l_; and use int for indexing, not long int).
// example.cpp
#include "SuiteSparseQR.hpp"
#include "SuiteSparse_config.h"
int main (int argc, char **argv)
{
cholmod_common Common, *cc;
cholmod_sparse *A;
cholmod_dense *X, *B;
// start CHOLMOD
cc = &Common;
cholmod_l_start (cc);
/* A =
[
1.1, 0.0, -0.5, 0.7
0.0, -2.0, 0.0, 0.0
0.0, 0.0, 0.9, 0.0
0.0, 0.0, 0.0, 0.6
]
*/
int m = 4; // num rows in A
int n = 4; // num cols in A
int nnz = 6; // num non-zero elements in A
int unsymmetric = 0; // A is non-symmetric: see cholmod.h > search for `stype` for more details
// In coordinate form (COO) a.k.a. triplet form (zero-based indexing)
int i[nnz] = {0, 1, 0, 2, 0, 3}; // row indices
int j[nnz] = {0, 1, 2, 2, 3, 3}; // col indices
double x[nnz] = {1.1, -2.0, -0.5, 0.9, 0.7, 0.6}; // values
// Set up the cholmod matrix in COO/triplet form
cholmod_triplet *T = cholmod_l_allocate_triplet(m, n, nnz, unsymmetric, CHOLMOD_REAL, cc);
T->nnz = nnz;
for (int ind = 0; ind < nnz; ind++)
{
((long int *) T->i)[ind] = i[ind]; // Notes:
((long int *) T->j)[ind] = j[ind]; // (1) casting necessary because these are void* (see cholmod.h)
((double *) T->x)[ind] = x[ind]; // (2) direct assignment will cause memory corruption
} // (3) long int for index pointers corresponds to usage of cholmod_l_* functions
// convert COO/triplet to CSC (compressed sparse column) format
A = (cholmod_sparse *) cholmod_l_triplet_to_sparse(T, nnz, cc);
// note: if you already know CSC format you can skip the triplet allocation and instead use cholmod_allocate_sparse
// and assign the member variables: see cholmod.h > cholmod_sparse_struct definition
// B = ones (size (A,1),1)
B = cholmod_l_ones (A->nrow, 1, A->xtype, cc);
// X = A\B
X = SuiteSparseQR <double> (A, B, cc);
// Print contents of X
printf("X = [\n");
for (int ind = 0; ind < n; ind++)
{
printf("%f\n", ((double *) X->x)[ind]);
}
printf("]\n");
fflush(stdout);
// free everything and finish CHOLMOD
cholmod_l_free_triplet (&T, cc);
cholmod_l_free_sparse (&A, cc);
cholmod_l_free_dense (&X, cc);
cholmod_l_free_dense (&B, cc);
cholmod_l_finish (cc);
return 0;
}
Supposing you have compiled SuiteSparse successfully and you have saved example.cpp in the base directory, then the following should work (on Linux):
gcc example.cpp -I./include -L./lib -lcholmod -lspqr -lsuitesparseconfig -o example
#Add SuiteSpare libraries to your `ld` search path if necessary
LD_LIBRARY_PATH=$(pwd)/lib
export LD_LIBRARY_PATH
./example
Output:
X = [
0.353535
-0.500000
1.111111
1.666667
]