Getting large estimates of error while using EIGEN sparse library - eigen

I am using the EIGEN sparse library to solve a system. I tried to test on a smaller matrix and got the estimated error close to zero. I attach the snippet of the code below.
MatrixXd Dense(4,4);
Dense<<2.0,0.0,0.0,0.0,
0.0,1.0,0.0,1.0,
0.0,0.0,5.0,0.0,
0.0,0.0,0.0,1.0;
Vector4d b(4.0, 5.0, 8.0, 1.0),xsol;
cout << "The least-squares solution is:\n"
<< Dense.jacobiSvd(ComputeThinU | ComputeThinV).solve(b) << endl;
SpMat SparseA;
SparseA = Dense.sparseView();
cout<<SparseA<<endl;
BiCGSTAB<SparseMatrix<double> > bicg;
bicg.compute(SparseA);
xsol = bicg.solve(b);
std::cout << "#iterations: " << bicg.iterations() << std::endl;
std::cout << "estimated error: " << bicg.error() << std::endl;
// update and solve again
xsol = bicg.solve(b);
cout << "Sparse Matrix Solution is:\n" << xsol << endl;**
This is what I get when I run the code:
iterations: 1
estimated error: 0
Sparse Matrix Solution is:
2
4
1.6
1
Now comes the problem I scale up the system and try to solve I get huge estimated errors. How do I resolve this. By the way I follow the same procedure of defining a dense matrix and converting them into a sparse one before solving the system. The code snippet is as follows
typedef Eigen::SparseMatrix<double> SpMat;
SpMat SparseKGl;
VectorXd wsol;
SparseKGl = KGl.sparseView();
BiCGSTAB<SparseMatrix<double> > bicg;
wsol=bicg.compute(SparseKGl).solve(ForceGl);
std::cout << "iterations: " << bicg.iterations() << std::endl;
std::cout << "estimated error: " << bicg.error() << std::endl;
// update and solve again
wsol = bicg.solve(ForceGl);
The output I get is
iterations: 22
estimated error: 70549
Can anyone please provide some insights into the same?
Regards

Related

How to reshape submatrix into another existing matrix without an intermediate matrix (using Eigen)

I'm fairly new to Eigen. I have a primary and secondary question.
The primary question is that I would like to copy a submatrix into another existing matrix and reshape it during the process without the need for a temparary matrix.
The secondary question is similar, can I generate a linSpaced Vector and copy it into an existing Matrix with the same dimensions of the vector without the need for a temporary Vector?
The following code shows solutions using temporary variables,
void main(void)
{
Eigen::Matrix<double,3,4> mOut;
mOut.setZero();
// generate linspaced data for mIn [SECONDARY QUESTION]
Eigen::Matrix<double,36,1> mIn;
Eigen::VectorXd tmpIn(Eigen::VectorXd::LinSpaced(36,0,35));
mIn = Eigen::Map<Eigen::Matrix<double,36,1>>(tmpIn.data());
std::cout << "mIn = " << mIn << std::endl;
// copy a subset of mIn into mOut [PRIMARY QUESTION]
Eigen::Matrix<double,12,1> tmpOut(mIn.block<12,1>(24,0));
mOut = Eigen::Map<Eigen::Matrix<double,3,4>>(tmpOut.data(),3,4);
std::cout << "mOut = " << mOut << std::endl;
}
I tried the following for the primary question but it did not work,
mOut = Eigen::Map<Eigen::Matrix<double,3,4>>(mIn.block<12,1>(24,0));
if gave an error,
Error 5 error C2440: '<function-style-cast>' : cannot convert from 'Eigen::Block<XprType,BlockRows,BlockCols,InnerPanel>' to 'Eigen::Map<PlainObjectType,MapOptions>'

Eigen reduction examples are not building with Error C2100 illegal indirection

I am trying to use examples from
Reduction Dimensions
section of Eigen Tensors README
This:
// Create a tensor of 2 dimensions
Eigen::Tensor<int, 2> a(2, 3);
a.setValues({{1, 2, 3}, {6, 5, 4}});
// Reduce it along the second dimension (1)...
Eigen::array<int, 1> dims({1 /* dimension to reduce */});
// ...using the "maximum" operator.
// The result is a tensor with one dimension. The size of
// that dimension is the same as the first (non-reduced) dimension of a.
Eigen::Tensor<int, 1> b = a.maximum(dims);
cout << "a" << endl << a << endl << endl;
cout << "b" << endl << b << endl << endl;
And other examples from that section gives me Error C2100 illegal indirection compile error. In VS 2015. Everything else works and compile well. Any ideas what is the problem with that code?
Eigen::array<int, 1> dims({1 /* dimension to reduce */});
Should be changed to:
const std::array<DenseIndex, 1> action_cards_dims = { 1 };

performing N independent 1D FFT on a 2D matrix with FFTW

I have a 2 dimensional matrix with each column corresponding to one independent signal. I am going to perform N 1D fft on each column. In matlab, apply a fft to a 2D matrix will do the trick. But I am porting my code to c++ with fftw. I wonder if there is a way to do so. I try the following code by setting the column size to 1 and row size to 4 (total row number), but it does not help.
#include <iostream>
#include <complex>
#include "fftw3.h"
using namespace std;
int main(int argc, char** argv)
{
complex<double> data[4][2];
data[0][0] = complex<double>(1,1);
data[1][0] = complex<double>(2,1);
data[2][0] = complex<double>(3,1);
data[3][0] = complex<double>(4,1);
data[0][1] = complex<double>(1,1);
data[1][1] = complex<double>(1,2);
data[2][1] = complex<double>(1,3);
data[3][1] = complex<double>(1,4);
cout << "original data ..." << endl;
cout << data[0][0] << '\t' << data[0][1] << endl;
cout << data[1][0] << '\t' << data[1][1] << endl;
cout << data[2][0] << '\t' << data[2][1] << endl;
cout << data[3][0] << '\t' << data[3][1] << endl;
cout << endl << endl;
fftw_plan plan=fftw_plan_dft_2d(4, 1,(fftw_complex*)&data[0][0], (fftw_complex*)&data[0][0], FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(plan);
cout << "after fftw ..." << endl;
cout << data[0][0] << '\t' << data[0][1] << endl;
cout << data[1][0] << '\t' << data[1][1] << endl;
cout << data[2][0] << '\t' << data[2][1] << endl;
cout << data[3][0] << '\t' << data[3][1] << endl;
return 0;
}
Above code takes the first and second row and reshape them to 2x2 matrix then perform a 2D fft.
Up to now, the only way that comes to my mind is as follow. Let's say I have NxM (N rows, M columns), I create M fftw plans for M 1D fftw. I execute M fftw in serial to get the result. But in practical application, the matrix is very big, M is so large. It is very inefficient to do this way. Any better idea? Thanks.
For those stumbling across this nowadays, the FFTW devs have implemented routines for this operation, which is faster than looping through each column and taking a separate transform. You certainly don't want to take a 2D transform (as is shown in the question), which is mathematically different than row-wise 1D transforms.
The key to you question is in fftw_plan_many_dft. Here is a link to the full documentation.
Here is an example (modifed from the above link) that illustrates what you're looking for.
#include "fftw3.h"
int main() {
fftw_complex *A; // array of data
A = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*10*3);
// ...
/* Transform each column of a 2d array with 10 rows and 3 columns */
int rank = 1; /* not 2: we are computing 1d transforms */
int n[] = {10}; /* 1d transforms of length 10 */
int howmany = 3;
int idist = 1;
int odist = 1;
/* distance between two elements in the same column */
int istride = 3;
int ostride = 3;
int *inembed = n, *onembed = n;
/* forward, in-place, 1D transform of each column */
fftw_plan p;
p = fftw_plan_many_dft(rank, n, howmany, A, inembed, istride, idist, A, onembed, ostride, odist, FFTW_FORWARD, FFTW_ESTIMATE);
// ...
/* run transform */
fftw_execute_dft(p, A, A);
// ...
/* we don't want memory leaks */
fftw_destroy_plan(p);
fftw_free(A);
}

OpenCV perspectiveTransform broken function

Im trying to use perspectiveTransform but I keep getting error. I tried to follow the solution from this thread http://answers.opencv.org/question/18252/opencv-assertion-failed-for-perspective-transform/
_players[i].getCoordinates() is of type Point
_homography_matrix is a 3 x 3 Mat
Mat temp_Mat = Mat::zeros(2, 1, CV_32FC2);
for (int i = 0; i < _players.size(); i++)
{
cout << Mat(_players[i].get_Coordinates()) << endl;
perspectiveTransform(Mat(_players[i].get_Coordinates()), temp_Mat, _homography_matrix);
}
Also, how do I convert temp_Mat into type Point ?
OpenCV Error: Assertion failed (scn + 1 == m.cols) in cv::perspectiveTransform
Basically you just need to correct from
Mat(_players[i].get_Coordinates()) ...
to
Mat2f(_players[i].get_Coordinates()) ...
In the first case you are creating a 2x1, 1 channel float matrix, in the second case (correct) you create a 1x1, 2 channel float matrix.
You also don't need to initialize temp_Mat.
You can also use template Mat_ to better control the types of your Mats. E.g. creating a Mat of type CV_32FC2 is equivalent to create a Mat2f.
This sample code will show you also how to convert back and forth between Mat and Point:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
// Some random points
vector<Point2f> pts = {Point2f(1,2), Point2f(5,10)};
// Some random transform matrix
Mat1f m(3,3, float(0.1));
for (int i = 0; i < pts.size(); ++i)
{
cout << "Point: " << pts[i] << endl;
Mat2f dst;
perspectiveTransform(Mat2f(pts[i]), dst, m);
cout << "Dst mat: " << dst << endl;
Point2f p(dst(0));
cout << "Dst point: " << p << endl;
}
return 0;
}

Address of an instance emplaced to std::vector is invalid

I have 2 std::vectors:
to first vector, I emplace instance
to second vector, I want to store the address of the instance just emplaced
But it does not work, i.e., the stored address differs from the emplaced instance's address.
If it matters at all, I'm on Linux and using g++ 5.1 and clang 3.6 with -std=c++11.
Here's a working example to illustrate the problem.
#include <iostream>
#include <vector>
struct Foo {
Foo(int a1, int a2) : f1(a1), f2(a2) {}
int f1;
int f2;
};
int main(int, char**) {
std::vector<Foo> vec1;
std::vector<Foo*> vec2;
int num = 10;
for (int i = 0; i < num; ++i) {
vec1.emplace_back(i, i * i);
// I want to store the address of *emplaced* instance...
vec2.push_back(&vec1.back());
}
// same
std::cout << "size 1: " << vec1.size() << std::endl;
std::cout << "size 2: " << vec2.size() << std::endl;
// same for me
std::cout << "back 1: " << &vec1.back() << std::endl;
std::cout << "back 2: " << vec2.back() << std::endl;
// typically differ ?
std::cout << "front 1: " << &vec1.front() << std::endl;
std::cout << "front 2: " << vec2.front() << std::endl;
for (int i = 0; i < num; ++i) {
std::cout << i + 1 << "th" << std::endl;
// same for last several (size % 4) for me
std::cout << "1: " << &vec1[i] << std::endl;
std::cout << "2: " << vec2[i] << std::endl;
}
}
Questions
Is it correct behavior ? I guess it's caused by storing the address of temporary instance but I want to know whether it's permitted by the standard (just curious).
If above is true, how to work around this ? I resolved this by changing first one to vector<unique_ptr<Foo>> but is there any idiomatic way ?
Two options:
1) You can simply fix your test. You just need in you test preallocate enough memory first with
vec1.reserve(10);
Well, this is implementation details for std::vector. As more and more items are added to std::vector it needs to get more space for them. And this space must be contigious. So when there is not enough space for a new element std::vector allocates a bigger block of memory, copies existing elements to it, add the new element and finally frees the block of memory that it used before. As a result addresses that you stored in vec2 might become invalid.
However, if you preallocate enough memory for 10 elements then you code is correct.
Or, since reserving memory is sort of tricky thing to do
2) use std::deque since insertion and deletion at either end of a deque never invalidates pointers or references to the rest of the elements (http://en.cppreference.com/w/cpp/container/deque) and forget about the problem with invalidated addresses. So no need to reserve memory.

Resources