Inverse matrix with SparseMatrix<..,RowMajor> - sparse-matrix

I'm looking for a way to retrieve the inverse of a SparseMatrix using RowMajor storage with EIGEN 3.3.4. I found an answer to this question there, but I'm experiencing issues adapting it to my case.
The given way to do it is by using a Solver, and resolve Ax=I (I is identity), to retrieve the inverse of A.
What I do not understand is the following :
auto A_inv = solver.solve(I);
Looks like, in the author case, the result of solver.solve() is a SparseMatrix object. In mine, it is a Solve object and this is why I'm in trouble right now.
I'm using SimplicialLDLT as follow :
SimplicialLDLT<SparseMatrix<short, RowMajor> solver;
solver.compute(A);
SparseMatrix<short,RowMajor> identity(A.rows(), A.cols()); identity.setIdentity();
auto result = solver.solve(identity);
std::cout<<"INVERSE MATRIX : "<<result<<std::endl;
Which does not work since result is a Solve(I guess there's no << overload). What I'm looking for is a way to do :
SparseMatrix<short,RowMajor> matrix_result = result;
For now, the result of this conversion is an error : THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES.
The question is : How do you setup a RowMajor solver, and how do you retrieve the result of this in a usable RowMajor matrix?
Thanks in advance.
With ColMajor
Using ColMajor for both the solver and rhs (lhs is still rowmajor, I can't change it), the result is wrong. The matrix A is :
A = 1 -1 0
0 1 0
0 0 1
The code is :
SparseMatrix<short,RowMajor> A;
//set A values
SparseMatrix<short,ColMajor> I(A.rows(),A.cols());I.setIdentity();
SimplicialLDLT<SparseMatrix<short,ColMajor>> solver;
solver.compute(A);
SparseMatrix<short,ColMajor> result = solver.solve(I);
std::cout<<result<<std::endl;
Displaying the wrong following :
1 0 0
0 1 0
0 0 1
Where the expected result was :
1 1 0
0 1 0
0 0 1
I'm probably doing something wrong there but I can't figure it out.
Solution : Change the solver to SparseLU, SimplicialLDLT is only working for symmetric matrices.

Related

A matrix and a column vector containing indices, how to iterate with no loop?

I have a big matrix (500212x7) and a column vector like below
matrix F vector P
0001011 4
0001101 3
1101100 6
0000110 1
1110000 7
The vector contains indices considered within the matrix rows. P(1) is meant to point at F(1,4), P(2) at F(2,3) and so on.
I want to negate a bit in each row in F in a column pointed by P element (in the same row).
I thought of things like
F(:,P(1)) = ~F(:,P(1));
F(:,P(:)) = ~F(:,P(:));
but of course these scenarios won't produce the result I expect as the first line won't make P element change and the second one won't even let me start the program because a full vector cannot make an index.
The idea is I need to do this for all F and P rows (changing/incrementing "simultaneously") but take the value of P element.
I know this is easily achieved with for loop but due to large dimensions of the F array such a way to solve the problem is completely unacceptable.
Is there any kind of Matlab wizardry that lets solving such a task with the use of matrix operations?
I know this is easily achieved with for loop but due to large dimensions of the F array such a way to solve the problem is completely unacceptable.
You should never make such an assumption. First implement the loop, then check to see if it really is too slow for you or not, then worry about optimizing.
Here I'm comparing Luis' answer and the trival loop:
N = 500212;
F = rand(N,7) > 0.6;
P = randi(7,N,1);
timeit(#()method1(F,P))
timeit(#()method2(F,P))
function F = method1(F,P)
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries
end
function F = method2(F,P)
for ii = 1:numel(P)
F(ii,P(ii)) = ~F(ii,P(ii));
end
end
Timings are 0.0065 s for Luis' answer, and 0.0023 s for the loop (MATLAB Online R2019a).
It is especially true for very large arrays, that loops are faster than vectorized code, if the vectorization requires creating an intermediate array. Memory access is expensive, using more of it makes the code slower.
Lessons: don't dismiss loops, don't prematurely try to optimize, and don't optimize without comparing.
Another solution:
xor( F, 1:7 == P )
Explanation:
1:7 == P generates one-hot arrays.
xor will cause a bit to retain its value against a 0, and flip it against a 1
Not sure if it qualifies as wizardry, but linear indexing does exactly what you want:
F = [0 0 0 1 0 1 1; 0 0 0 1 1 0 1; 1 1 0 1 1 0 0; 0 0 0 0 1 1 0; 1 1 1 0 0 0 0];
P = [4; 3; 6; 1; 7];
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries

MATLAB - Finite Differences [Subscript indices must either be real positive integers or logicals] [duplicate]

This question already has answers here:
Subscript indices must either be real positive integers or logicals, generic solution
(3 answers)
Closed 6 years ago.
Not sure if I should have posted this here or on the Maths stackexchange, so sorry if it's the wrong place. I'm very new to MATLAB and programming in general, and am having some troubles trying to solve an ODE problem using finite difference methods for an assignment.
My finite difference equation is:
z(t+dt) = (dt^2*(γ^2*h*sin(γ*t)-β*z(t)) - z(t-dt)*(1-dt*α)+2*z(t))/(1 + dt*α)
Where t is a 51x1 array for the time increments. Basically I want to calculate z(t) for t values from 0 to 1 in increments of 0.02. I have the initial conditions z(0) = 0 and z(Δt) = 0.
My current code (not everything, but the bit that's giving me trouble:
dt = 0.02
t = [0:dt:T]';
z(0) = 0
z(dt)= 0
for i = t
z(i+dt) = (dt^2*(gamma^2.*h.*sin(gamma*t)-beta*z(i)) - z(i-dt)*(1-dt*alpha)+2*z(i))/(1 + dt*alpha)
end
Alpha, beta and gamma are all constants in this case, they're defined earlier in the code.
I keep getting the error "Subscript indices must either be real positive integers or logicals." I understand that MATLAB arrays begin with element 1 and not 0, so trying to access element 0 will give an error.
I'm not sure if the error is with how I've entered my finite difference function, or the initial conditions. By setting i = t, am I running the for loop for those values of t, or for those elements in the matrix? E.g. when i = 0, is it trying to access the 0 element of the matrix, or is it setting the i variable in the equation to 0 like I want it to?
Any help would be greatly appreciated.
Thankyou!
problem is with dt and I think dt is not integer value and cannot be used for indexing array. index of arrays are always integer values in Matlab. Please try below code and check if solves the problem
t = [0:dt:T]';
z(1) = 0
z(2)= 0
for i = 2 : length(t)
z(i) = (dt^2*(gamma^2.*h.*sin(gamma*t(i))-beta*z(i)) - z(i-1)*(1-dt*alpha)+2*z(i))/(1 + dt*alpha)
end

How to compare each matrix to mean and return value in Matlab

for example lets consider
a = fix(8 * randn(10,5));
and mean(a) would give me mean of each column.
So, what I was planning to do was comparing the mean of first column to each of its content till the column and and proceed to the next column with its mean and comparing with each of its content.
I was able to get this code here (I know there are multiple for loops but thats the best I could come up with, any alternate answer would be greatly accepted)
if(ndims(a)==2)
b = mean(a);
for c = 1:size(a,2)
for d = 1:size(a)
for e = 1:size(b,2)
if(a(d,c)>b(1,c))
disp(1);
else
disp(false);
end
end
end
end
else
disp('Input should be a 2D matrix');
end
I don't know if this is the right answer? Could any one tell me?
Thanks in advance.
It seems you want to know whether each entry is greater than its column-mean.
This is done efficiently with bsxfun:
result = bsxfun(#gt, a, mean(a,1));
Example:
a =
3 1 3 2
5 2 3 1
1 3 5 2
The column-means, given by mean(a,1), are
ans =
3.000000000000000 2.000000000000000 3.666666666666667 1.666666666666667
Then
>> result = bsxfun(#gt, a, mean(a,1))
result =
0 0 0 1
1 0 0 0
0 1 1 1
If you are trying to do what I think you are (print one if the average value of a column is greater than the value in that column, zero otherwise) you can eliminate a lot of loops doing the following (using your same a and b):
for ii=1:length(b)
c(:,ii) = b(ii) > a(:,ii);
end
c will be your array of ones and zeros.

FOR loop with multiple values from two arrays in different configurations

I am working on a project involving calculating the work volume for a device.
Given that I have two angles, beta1 and beta2 between let's say 0-10 degrees ([deg] used for simplification here, in reality in [rad]),
I want to calculate the work volume for different combinations of e.g.
beta1 = 1 [deg]
and at the same time
beta2 = 8 [deg]
I can't get my head around how to do it. I tried to cheat by running the FOR loop for 1000 values of beta1 and then a random entry from the beta2 array, but obviously it is not very reliable.
Here is the code: (it is a mess, but it is just trigonometry)
for ii=1:1000
for jj=randi(1000)
T_0{ii} = [0 0 0 (l_joint/beta1(ii))*tan(beta1(ii)/2); 0 1 0 0; 0 0 1 0; 0 0 0 1];
T_1{ii} = [cos(beta1(ii)) -sin(beta1(ii))*cos(alpha1) sin(beta1(ii))*sin(alpha1) ...
((l_joint/beta1(ii))*tan(beta1(ii)/2)+l_disk+(l_joint/beta2(ii))*tan(beta2(jj)/2))*cos(beta1(ii)); ...
sin(beta1(ii)) cos(beta1(ii))*cos(alpha1) -cos(beta1(ii))*sin(alpha1) ...
((l_joint/beta1(ii))*tan(beta1(ii)/2)+l_disk+(l_joint/beta2(jj))*tan(beta2(jj)/2))*sin(beta1(ii)); ...
0 sin(alpha1) cos(alpha1) 0; ...
0 0 0 1];
T_2{ii} = [cos(beta2(jj)) -sin(beta2(jj))*cos(alpha2) sin(beta2(jj))*sin(alpha2) ...
((l_disk+(l_joint/beta2(jj))*tan(beta2(jj)/2)))*cos(beta2(jj)); ...
sin(beta2(jj)) cos(beta2(jj))*cos(alpha2) -cos(beta2(jj))*sin(alpha2) ...
((l_disk+(l_joint/beta2(jj))*tan(beta2(jj)/2)))*sin(beta2(jj)); ...
0 sin(alpha2) cos(alpha2) 0; ...
0 0 0 1];
T_section{ii} = (T_0{ii}*T_1{ii}*T_2{ii})^n;
end end
As far as i can work out, you have a function T_section with 2 parameters beta1 and beta2 and are asking how to calculate the value of the function T_section(beta1, beta2) for all combinations of beta1 and beta2. You can calculate and visualize the results of a 2-D function in MATLAB like this:
beta1 = 0:0.1:10;
beta2 = 0:0.1:10;
[B1, B2] = meshgrid(beta1, beta2);
T_section = sind(10*B2)*cosd(20*B1); % replace with actual function
surf(beta1, beta2, T_section,'EdgeColor','none')
xlabel('\beta_1'); ylabel('\beta_2');
which yields this plot:
No need for loops here, vectorizing your calculations in MATLAB is very likely much faster (see the excellent MATLAB documentation, e.g. http://de.mathworks.com/help/matlab/matlab_prog/vectorization.html). You should probably also read the documentation about meshgrid (doc meshgrid on the console).

Neural Network Artificial Intelligence

In a simple perception, can someone explain to me the concept of the Threshold and and how to set it, i.e. initially what is the value of the Threshold input and weight??
Since by definition the perceptron is a binary classifier even in it's simplest incarnation you can think of it as having a bias/threshold of 0:
y = f( wn* xn> 0 ? 1 : 0 )
But since 0 is a pretty arbitrary value the bias/threshold is explicitly introduced into the model as a variable:
y = f( wn* xn> b'? 1 : 0 ) or y = f( wn* xn+ b > 0 ? 1 : 0 )
The problem is that now the model another variables (b [which is a scalar] apart from the original wn [which is a vector]) that needs to be taken into account when training.
There are many ways to do that, the naive way being to just pick some of the possible values of b and for each train the model on wn and keep the ( b, wn) pair that produced the best result.
A more elegant way is to just think of the bias/threshold variable b as being a weight that is attached to an input that is always 1 which basically brings the model back to the original form with only 1 variable w except that now the vectors x and w have n + 1 elements:
y = f( wn + 1* xn + 1> 0 ? 1 : 0 )

Resources