I am working on an application which is a translation from Matlab to C/C++ and so I need the same outputs. The problem is that I tried to use the Eigen library to replace the Matlab eig command. I obtain different eigenvectors but the same eigenvalues.
C/C++
#include <iostream>
#include <Eigen/Eigenvalues>
using namespace Eigen;
int main(){
MatrixXd A(4,4);
A << 0.680375, 0.823295, -0.444451, -0.270431,
-0.211234, -0.604897, 0.10794, 0.0268018,
0.566198, -0.329554, -0.0452059, 0.904459,
0.59688, 0.536459, 0.257742, 0.83239;
EigenSolver<MatrixXd> es(A);
std::cout << "The matrix A is:\n" << A << "\n\n";
std::cout << "Eigenvectors:\n" << es.eigenvectors() << "\n";
std::cout << "Eigenvalues:\n" << es.eigenvalues() << "\n";
}
Output
The matrix A is:
0.680375 0.823295 -0.444451 -0.270431
-0.211234 -0.604897 0.10794 0.0268018
0.566198 -0.329554 -0.0452059 0.904459
0.59688 0.536459 0.257742 0.83239
Eigenvectors:
(0.349378,0.540657) (0.349378,-0.540657) (-0.0377612,-0.222364) (-0.0377612,0.222364)
(-0.0630065,-0.0993635) (-0.0630065,0.0993635) (-0.179376,0.000710941) (-0.179376,-0.000710941)
(0.313002,-0.372126) (0.313002,0.372126) (-0.594826,-0.663137) (-0.594826,0.663137)
(0.25223,-0.521263) (0.25223,0.521263) (0.212016,0.280058) (0.212016,-0.280058)
Eigenvalues:
(0.754819,0.527518)
(0.754819,-0.527518)
(-0.323488,0.0964573)
(-0.323488,-0.0964573)
Matlab
A=[0.680375 0.823295 -0.444451 -0.270431; -0.211234 -0.604897 0.10794 0.0268018; 0.566198 -0.329554 -0.0452059 0.904459; ...
0.59688 0.536459 0.257742 0.83239];
[eig_vectors, eig_value] = eig(A);
Output
eig_vectors =
0.6437 + 0.0000i 0.6437 + 0.0000i 0.1907 + 0.1204i 0.1907 - 0.1204i
-0.1177 - 0.0010i -0.1177 + 0.0010i 0.1192 - 0.1340i 0.1192 + 0.1340i
-0.1427 - 0.4649i -0.1427 + 0.4649i 0.8908 + 0.0000i 0.8908 + 0.0000i
-0.3009 - 0.4948i -0.3009 + 0.4948i -0.3500 - 0.0292i -0.3500 + 0.0292i
eig_value =
0.7548 + 0.5275i 0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i
0.0000 + 0.0000i 0.7548 - 0.5275i 0.0000 + 0.0000i 0.0000 + 0.0000i
0.0000 + 0.0000i 0.0000 + 0.0000i -0.3235 + 0.0965i 0.0000 + 0.0000i
0.0000 + 0.0000i 0.0000 + 0.0000i 0.0000 + 0.0000i -0.3235 - 0.0965i
Now, I know that eigenvectors are not unique, but I need to have the same output. Could it be possible ?
Related
When trying to retrieve data from an af::array (arrayfire) from the device via host(), my output data on the host is wrong (i.e. wrong values). For testing that, I wrote a small code sample (based on https://stackoverflow.com/a/29212923/2546099):
int main(void) {
size_t vector_size = 16;
af::array in_test_array = af::constant(1., vector_size), out_test_array = af::constant(0., vector_size);
af_print(in_test_array);
double *local_data_ptr = new double[vector_size]();
for(int i = 0; i < vector_size; ++i)
std::cout << local_data_ptr[i] << '\t';
std::cout << '\n';
in_test_array.host(local_data_ptr);
for(int i = 0; i < vector_size; ++i)
std::cout << local_data_ptr[i] << '\t';
std::cout << '\n';
delete[] local_data_ptr;
out_test_array = in_test_array;
af_print(out_test_array);
return 0;
}
My output is
in_test_array
[16 1 1 1]
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0.007813 0.007813 0.007813 0.007813 0.007813 0.007813 0.007813 0.007813 0 0 0 0 0 0 0 0
out_test_array
[16 1 1 1]
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
Why are half the values in the pointer set to 0.007813, and not all values to 1? When changing the default value for in_test_array to 2, half the values are set to 2, and for 3 those values are set to 32. Why does that happen?
The datatypes between arrayfire and C are in conflict.
For float use:
af::array in_test_array = af::constant(1., vector_size),
out_test_array = af::constant(0., vector_size);
float *local_data_ptr = new float[vector_size]();
For double use:
af::array in_test_array = af::constant(1., vector_size, f64),
out_test_array = af::constant(0., vector_size, f64)
double *local_data_ptr = new double[vector_size]();
IN both cases above, you will see that arrayfire will return you 1.0 in the local_data_ptr buffer, although with different data types.
I have a problem with my ray tracer program. The image looks wrong. Here is the output image:
Barycentric coordinates and collision calculation codes are as follows:
bool CTriangle::Intersect(Calculus::CRay& ray, CIntersection* isect) const {
// Möller–Trumbore intersection algorithm
const Calculus::CPoint3<float>& p1 = v_points[0];
const Calculus::CPoint3<float>& p2 = v_points[1];
const Calculus::CPoint3<float>& p3 = v_points[2];
Calculus::CVector3<float> e1 = p2 - p1;
Calculus::CVector3<float> e2 = p3 - p1;
Calculus::CVector3<float> s1 = Calculus::Math::Cross(ray.direction, e2);
float determinant = Calculus::Math::Dot(s1, e1);
if (determinant == 0.0f)
return false;
float inv_determinant = 1.0f / determinant;
Calculus::CVector3<float> s = ray.origin - p1;
float b1 = Calculus::Math::Dot(s, s1) * inv_determinant;
if (b1 < 0.0f || b1 > 1.0f)
return false;
Calculus::CVector3<float> s2 = Calculus::Math::Cross(s, e1);
float b2 = Calculus::Math::Dot(ray.direction, s2) * inv_determinant;
if (b2 < 0.0f || b1 + b2 > 1.0f)
return false;
float b0 = 1 - b1 - b2;
float thit = Calculus::Math::Dot(e2, s2) * inv_determinant;
if (thit < ray.mint || thit > ray.maxt)
return false;
isect->p = ray(thit);
isect->n = Calculus::Math::Normalize(Calculus::CVector3<float>
(v_normals[0].x, v_normals[0].y, v_normals[0].z) * b0 +
Calculus::CVector3<float>(v_normals[1].x, v_normals[1].y,
v_normals[1].z) * b1 +
Calculus::CVector3<float>(v_normals[2].x, v_normals[2].y,
v_normals[2].z) * b2);
isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;
isect->tHit = thit;
isect->ray_epsilon = 1e-5f * thit;
return true;
}
Texture i used int the ray trace program:(file type: bmp)
my obj file is as follows. The background shape consists of two triangles. Texture projection is applied only to the background shape:
v -24.1456 -11.1684 -26.2413
v 24.1455 -11.1684 -26.2413
v -24.1456 37.1227 -26.2413
v 24.1455 37.1227 -26.2413
# 4 vertices
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
# 6 vertex normals
vt 0.9995 0.0005 0.0000
vt 0.0005 0.0005 0.0000
vt 0.9995 0.9995 0.0000
vt 0.0005 0.9995 0.0000
# 4 texture coords
o back
g back
usemtl default
s 1
f 1/1/1 2/2/2 4/4/3
f 4/4/4 3/3/5 1/1/6
# 2 faces
Here is the interpolated uv draw call.
Here is indexing algorithm, i'm starting from zero:
...
Calculus::CPoint3<unsigned short> p, t, n;
sscanf_s(token, "%hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu",
&p.x, &t.x, &n.x, &p.y, &t.y, &n.y, &p.z, &t.z, &n.z);
pi.push_back(p);
ti.push_back(t);
ni.push_back(n);
…
index = ti[i].x - 1;
temp_t[0] = vt[index]; // first uv
index = ti[i].y - 1;
temp_t[1] = vt[index]; // second uv
index = ti[i].z - 1;
temp_t[2] = vt[index]; // third uv
I wonder where I'm making a mistake. Thank you.
isect->uv = v_uvs[0] * b1 + v_uvs[1] * b2;
This is not the correct parametric interpolation of vertex attributes:
The parameters b1, b2 are being applied to the wrong vertices
You are not taking the third vertex v_uvs[2] into account
Correct version:
isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;
Not sure if this is the best place to ask this.
So I'm trying to study the orthogonality of the wave function solutions by calculating the Integral of the product of two solutions of different orders m and n. Now I get to the part where I have to do the product of 2 Hermite matrices of different dimensions, which I can't mathematically perform, one being 3x20 and the other one 4x20. Is there a way around this?
arma::mat Orthonormality::gaussHermiteG(int n, int m, arma::mat Z)
{
Miscellaneous misc;
Calcul *caln = new Calcul(n,Z);
Calcul *calm = new Calcul(m,Z);
double f1;
arma::mat Hnm;
arma::mat res;
f1 = (1 / std::sqrt(std::exp(n * std::log(2)) * misc.factorial(n))) * (1 / std::sqrt(std::exp(m * std::log(2)) * misc.factorial(m))) * std::sqrt(1 / M_PI);
Hnm = caln->calculPolynomeHermite() % calm->calculPolynomeHermite();
res = f1 * Hnm;
return res;
}
Here's my function for getting the quadrature. It this the way to prove the orthogonality, or am I doing it wrong?
long double Orthonormality::quadrature(int n, int m)
{
arma::mat gx;
arma::mat gauss_point = {{
-2.453407083009012499038365306336166239661e-1,
2.453407083009012499038365306336166239661e-1,
-7.374737285453943587056051442521042290772e-1,
7.374737285453943587056051442521042290772e-1,
1.234076215395323007885818346959410229585,
-1.234076215395323007885818346959410229584,
-1.738537712116586206780865662136406442958,
1.738537712116586206780865662136406442953,
2.254974002089275523082333344734565128082,
-2.254974002089275523082333344734565128065,
-2.788806058428130480525033756403185410695,
2.788806058428130480525033756403185410655,
3.347854567383216326914924522996463698566,
-3.347854567383216326914924522996463698495,
-3.94476404011562521037562880052441180715,
3.944764040115625210375628800524411807067,
4.603682449550744273077675248978347585171,
-4.603682449550744273077675248978347585109,
5.387480890011232862016900410681120753981,
-5.387480890011232862016900410681120754003,
}
};
arma::mat gauss_point_weight = {{
4.622436696006100896503286398612081142142e-1,
4.622436696006100896503286398612081142142e-1,
2.866755053628341297196597062280879168236e-1,
2.866755053628341297196597062280879168236e-1,
1.090172060200233200137550335354255770852e-1,
1.090172060200233200137550335354255770846e-1,
2.481052088746361088216495255894039439922e-2,
2.481052088746361088216495255894039440028e-2,
3.24377334223786183218324713235370544232e-3,
3.243773342237861832183247132353705443042e-3,
2.283386360163539672571459179634955394906e-4,
2.283386360163539672571459179634955393512e-4,
7.802556478532063694145991999647569104495e-6,
7.802556478532063694145991999647569095955e-6,
1.086069370769281693999524563447163430255e-7,
1.086069370769281693999524563447163432688e-7,
4.399340992273180553628851455467928211995e-10,
4.399340992273180553628851455467928212879e-10,
2.229393645534151292522500616029095785758e-13,
2.22939364553415129252250061602909578525e-13,
}
};
gx = Orthonormality::gaussHermiteG(n, m, gauss_point);
arma::mat res;
res = gx * gauss_point_weight.t();
long double resDouble = res(0, 0);
return resDouble;
}
Here's the Hermite Polynomial function and its output for the 3 an 4 modes:
mat Calcul::calculPolynomeHermite(int n_max, mat z)
{
mat H(n_max, z.n_elem);
if (n_max == 0)
{
H = z.ones(size(z));
}
else
{
if (n_max == 1)
{
return z.for_each([](arma::mat::elem_type& val)
{
val = 2 * val;
});
}
else {
for(int i = 0; i < z.n_elem; ++i)
{
H(0, i) = 1;
}
rowvec h2 = rowvec(z.n_elem);
h2 = 2 * z;
H.row(1) = h2;
for(int i = 2; i < n_max; i++)
{
rowvec hn = rowvec(z.n_elem);
hn = h2 % H.row(i - 1) - (2 * i) * H.row(i - 2);
H.row(i) = hn;
}
}
}
return H;
}
output :
H(3,z):
1.0000 1.0000 1.0000 1.0000 1.0000
-4.0000 -2.0000 0 2.0000 4.0000
12.0000 0 -4.0000 0 12.0000
H(4,z):
1.0000 1.0000 1.0000 1.0000 1.0000
-4.0000 -2.0000 0 2.0000 4.0000
12.0000 0 -4.0000 0 12.0000
-24.0000 12.0000 0 -12.0000 24.0000
Can someone explain to me why the results are different.
Code in C++:
MatrixXcd testTest;
testTest.resize(3,3);
testTest.real()(0,0) = 1;
testTest.real()(0,1) = 2;
testTest.real()(0,2) = 3;
testTest.real()(1,0) = 1;
testTest.real()(1,1) = 2;
testTest.real()(1,2) = 3;
testTest.real()(2,0) = 1;
testTest.real()(2,1) = 2;
testTest.real()(2,2) = 3;
testTest.imag()(0,0) = 1;
testTest.imag()(0,1) = 2;
testTest.imag()(0,2) = 3;
testTest.imag()(1,0) = 1;
testTest.imag()(1,1) = 2;
testTest.imag()(1,2) = 3;
testTest.imag()(2,0) = 1;
testTest.imag()(2,1) = 2;
testTest.imag()(2,2) = 3;
cout<< endl << testTest << endl;
cout<< endl << testTest.transpose() << endl;
cout<< endl << testTest*testTest.transpose() << endl;
cout<< endl << testTest << endl;
Results from C++:
(1,1) (2,2) (3,3)
(1,1) (2,2) (3,3)
(1,1) (2,2) (3,3)
(1,1) (1,1) (1,1)
(2,2) (2,2) (2,2)
(3,3) (3,3) (3,3)
(0,28) (0,28) (0,28)
(0,28) (0,28) (0,28)
(0,28) (0,28) (0,28)
(1,1) (2,2) (3,3)
(1,1) (2,2) (3,3)
(1,1) (2,2) (3,3)
And the same thing written in Matlab:
testTest = [ complex(1,1) complex(2,2) complex(3,3);
complex(1,1) complex(2,2) complex(3,3);
complex(1,1) complex(2,2) complex(3,3)];
testTest
testTest'
testTest*testTest'
testTest
Matlab results:
testTest =
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
ans =
1.0000 - 1.0000i 1.0000 - 1.0000i 1.0000 - 1.0000i
2.0000 - 2.0000i 2.0000 - 2.0000i 2.0000 - 2.0000i
3.0000 - 3.0000i 3.0000 - 3.0000i 3.0000 - 3.0000i
ans =
28 28 28
28 28 28
28 28 28
testTest =
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
1.0000 + 1.0000i 2.0000 + 2.0000i 3.0000 + 3.0000i
Multiplication of testTest * testTest' in C returns returns complex numbers with real part 0 and imag part 28. Matlab returns just dobule with value 28.
' in Matlab does the transpose and takes the complex conjugate (http://uk.mathworks.com/help/matlab/ref/ctranspose.html). If you want to just do the transpose use .' (with a dot infront).
Thus, if you change your MATLAB test to
testTest*testTest.'
the results should be the same.
If you want the complex transpose in eigen then you can go matrix.adjoint() (or matrix.conjugate().transpose())
I was trying to solve the following problem, using the GLPSOL solver:
Fred has $5000 to invest over the next five years. At the beginning of each year he can invest money in one- or two-year time deposits. The bank pays 4% interest on one-year time deposits and 9 percent (total) on two-year time deposits. In addition, West World Limited will offer three-year certificates starting at the beginning of the second year. These certificates will return 15% (total). If Fred reinvest his money that is available every year, formulate a linear program to show him how to maximize his total cash on hand at the end of the fifth year.
I came up with the following LP model:
Being xij the amount invested in option i at year j, we look to
maximize z = 1,04x15 + 1,09x24 + 1,15x33,
subject to:
x11 + x12 <= 5000
x31 = x34 = x35 = 0
x12 + x22 + x32 <= 1,04 x11
x13 + x23 + x33 <= 1,04 x12 + 1,09 x21
x14 + x24 <= 1,04 x13 + 1,09 x22
x15 <= 1,04 x14 + 1,09 x23 + 1,15 x32
xij >= 0
And tried to write it in GMPL:
/* Variables */
var x{i in 1..3, j in 1..5} >= 0;
/* Objective */
maximize money: 1.04*x[1,5] + 1.09*x[2,4] + 1.15*x[3,3];
/* Constraints */
s.t. x[1,1] + x[2,1] <= 5000;
s.t. x[3,1] = x[3,4] = x[3,5] = 0;
s.t. x[1,2] + x[2,2] + x[3,2] <= 1.04 * x[1,1];
s.t. x[1,3] + x[2,3] + x[3,3] <= 1.04 * x[1,2] + 1.09 * x[2,1];
s.t. x[1,4] + x[2,4] <= 1.04 * x[1,3] + 1.09 * x[2,2];
s.t. x[1,5] <= 1.04 * x[1,4] + 1.09 * x[2,3] + 1.15 * x[3,2];
/* Resolve */
solve;
/* Results */
printf{j in 1..5}:"\n* %.2f %.2f %2.f \n", x[1,j], x[2,j], x[3,j];
end;
However, I'm getting the following error:
inv.mod:14: x multiply declared
Context: ...[ 1 , 5 ] + 1.09 * x [ 2 , 4 ] + 1.15 * x [ 3 , 3 ] ; s.t. x
MathProg model processing error
Does anyone have any thoughts about this?
You have to give a unique name to each constraint. Multiple assignments are not allowed.
This works on my machine:
/* Variables */
var x{i in 1..3, j in 1..5} >= 0;
/* Objective */
maximize money: 1.04*x[1,5] + 1.09*x[2,4] + 1.15*x[3,3];
/* Restrições */
s.t. c1: x[1,1] + x[2,1] <= 5000;
s.t. c2: x[3,1] = 0;
s.t. c3: x[3,4] = 0;
s.t. c4: x[3,5] = 0;
s.t. c5: x[1,2] + x[2,2] + x[3,2] <= 1.04 * x[1,1];
s.t. c6: x[1,3] + x[2,3] + x[3,3] <= 1.04 * x[1,2] + 1.09 * x[2,1];
s.t. c7: x[1,4] + x[2,4] <= 1.04 * x[1,3] + 1.09 * x[2,2];
s.t. c8: x[1,5] <= 1.04 * x[1,4] + 1.09 * x[2,3] + 1.15 * x[3,2];
/* Resolve */
solve;
/* Results */
printf{j in 1..5}:"\n* %.2f %.2f %2.f \n", x[1,j], x[2,j], x[3,j];
end;
It prints:
* 0.00 5000.00 0
* 0.00 0.00 0
* 0.00 0.00 5450
* 0.00 0.00 0
* 0.00 0.00 0
Good luck!