Tridiagonal Matrix in Matlab - matlab

Anyone know a quick efficient way in matlab to build the following square matrix
1 -1 0 0 0 0
-1 2 -1 0 0 0
0 -1 2 -1 0 0
0 0 -1 2 -1 0
0 0 0 -1 2 -1
0 0 0 0 -1 1
Which has 2's on the diagonal except at first and last element of the diagonal and -1 on the two adjacent diagonals.
This was a 6x6 examples and I'd like to generate in Matlab nxn one as quick and as efficient as possible. I tried with the built-in function kron but couldn't get away with it.
Thansk a lot

Here is one option
function a = laplacianMatrix(n)
a = toeplitz([2,-1,zeros(1,n-2)]);
a([1,end]) = 1;
end
Whether this version or the version using gallery (see Sam Roberts' answer) is faster seems to depend on the size of the matrix. For small matrices (up to around n = 200 on my machine) it is faster to use toeplitz. For larger matrices it is faster to use gallery.

How about this:
function mymatrix = makemymatrix(n)
mymatrix = full(gallery('tridiag',n,-1,2,-1));
mymatrix([1,end]) = 1;
Does that work for you?

result = conv2(eye(6), [-1 2 -1],'same');
result([1 end]) = 1;

n=6;
B=zeros(n);
for i=1:n
for j=1:n
B(1,1)=1;
if i==j
B(i,j)=2;
elseif i==j+1
B(i,j)=-1;
elseif j==i+1
B(i,j)=-1
else
B(i,j)=0;
end
B(n,n)=1;
end
end;
B

Related

How to input a value in the very middle of a matrix

I am trying to put a value in the middle of a matrix n*n (n being a positive odd integer) without the use of mod or disp
Currently I have this code with mod and disp
function [] = centerzero(n)
v=zeros(n,n);
a=length(v);
b=(size(v,2)+1)/2;
if mod(a,2)==1
v(b,b)=n;
disp(v);
end
end
How would I output the vector (with the very middle value in the matrix equaling n)?
Would I have to use for-loops or is their another way to do this?
A simple function which achieves what you want is
function a = centerzero(n)
a = zeros(n,n);
m = floor((n+1)/2);
a(m,m) = n;
end
and used like
>> centerzero(5)
ans =
0 0 0 0 0
0 0 0 0 0
0 0 5 0 0
0 0 0 0 0
0 0 0 0 0
oh sorry but I forgot to mention that i don't want to use floor or
ceil functions either – TheBOI
Just remove the floor function from Chris's answer. It's just keeps things from messing up if you enter something like 5.5. you could also incorporate the modulus 2 check back in to ensure your value isn't even.

How does Y = eye(K)(y, :); replace a "for" loop? Coursera

Working on an assignment from Coursera Machine Learning. I'm curious how this works... From an example, this much simpler code:
% K is the number of classes.
K = num_labels;
Y = eye(K)(y, :);
seems to be a substitute for the following:
I = eye(num_labels);
Y = zeros(m, num_labels);
for i=1:m
Y(i, :)= I(y(i), :);
end
and I have no idea how. I'm having some difficulty Googling this info as well.
Thanks!
Your variable y in this case must be an m-element vector containing integers in the range of 1 to num_labels. The goal of the code is to create a matrix Y that is m-by-num_labels where each row k will contain all zeros except for a 1 in column y(k).
A way to generate Y is to first create an identity matrix using the function eye. This is a square matrix of all zeroes except for ones along the main diagonal. Row k of the identity matrix will therefore have one non-zero element in column k. We can therefore build matrix Y out of rows indexed from the identity matrix, using y as the row index. We could do this with a for loop (as in your second code sample), but that's not as simple and efficient as using a single indexing operation (as in your first code sample).
Let's look at an example (in MATLAB):
>> num_labels = 5;
>> y = [2 3 3 1 5 4 4 4]; % The columns where the ones will be for each row
>> I = eye(num_labels)
I =
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
>> Y = I(y, :)
Y =
% 1 in column ...
0 1 0 0 0 % 2
0 0 1 0 0 % 3
0 0 1 0 0 % 3
1 0 0 0 0 % 1
0 0 0 0 1 % 5
0 0 0 1 0 % 4
0 0 0 1 0 % 4
0 0 0 1 0 % 4
NOTE: Octave allows you to index function return arguments without first placing them in a variable, but MATLAB does not (at least, not very easily). Therefore, the syntax:
Y = eye(num_labels)(y, :);
only works in Octave. In MATLAB, you have to do it as in my example above, or use one of the other options here.
The first set of code is Octave, which has some additional indexing functionality that MATLAB does not have. The second set of code is how the operation would be performed in MATLAB.
In both cases Y is a matrix generated by re-arranging the rows of an identity matrix. In both cases it may also be posible to calculate Y = T*y for a suitable linear transformation matrix T.
(The above assumes that y is a vector of integers that are being used as an indexing variables for the rows. If that's not the case then the code most likely throws an error.)

converting elements in a vector in matlab

For a project, I'm trying to find the first 1 of a series of ones in a vector. For example, I have as input:
x1=[1 0 0 1 1 1 0 1 0 1 0 0 1 1]
and I need as output:
Y1=[1 0 0 1 0 0 0 1 0 1 0 0 1 0]
So every time there is a 1 in the vector, all consequent ones need to be turned into zeroes.
I have the following code, but for some reason it just returns Y1 with exactly the same values as x1.
n=numel(x1);
Y1=zeros(n,1);
for i = 1:n
if x1(i) == 1
Y1(i)= 1;
for j = (i+1): n
if x1(j)== 1
Y1(j)=0;
elseif x1(j) == 0
Y1(j)=0;
i=j+1;
break
end
end
elseif x1(i) == 0
Y1(i)= 0;
end
end
Any help would be greatly appreciated.
Easy with diff. No loops needed.
Y1 = [ x1(1) diff(x1)==1 ];
or equivalently
Y1 = diff([0 x1])==1;
How this works: diff computes the difference of an element with respect to the preceding element. When that difference is 1, a new run of ones has begun. The first element requires special treatment.
A generalization of the answer by #Luis for the case where your vectors don't just contain zeros and ones:
Y1 = diff([0 x1]) & x1 == 1
This checks whether the value is one, and whether it is different from the previous value.

Effiicient ways to count a streak of consecutive integers in MATLAB

Say I have a vector containing only logical values, such as
V = [1 0 1 0 1 1 1 1 0 0]
I would like to write a function in MATLAB which returns a 'streak' vector S for V, where S(i) represents the number of consecutive 1s in V up to but not including V(i). For the example above, the streak vector would be
S = [0 1 0 1 0 1 2 3 4 0]
Given that I have to do this for a very large matrix, I would very much appreciate any solution that is vectorized / efficient.
This should do the trick:
S = zeros(size(V));
for i=2:length(V)
if(V(i-1)==1)
S(i) = 1 + S(i-1);
end
end
The complexity is only O(n), which I guess should be good enough.
For your sample input:
V = [1 0 1 0 1 1 1 1 0 0];
S = zeros(size(V));
for i=2:length(V)
if(V(i-1)==1)
S(i) = 1 + S(i-1);
end
end
display(V);
display(S);
The result would be:
V =
1 0 1 0 1 1 1 1 0 0
S =
0 1 0 1 0 1 2 3 4 0
You could also do it completely vectorized with a couple intermediate steps:
V = [1 0 1 0 1 1 1 1 0 0];
Sall = cumsum(V);
stopidx = find(diff(V)==-1)+1;
V2=V;
V2(stopidx) = -Sall(stopidx)+[0 Sall(stopidx(1:end-1))];
S2 = cumsum(V2);
S = [0 S2(1:end-1)];
Afaik the only thing that can take a while is the find call; you can't use logical indexing everywhere and bypass the find call, because you need the absolute indices.
It's outside the box - but have you considered using text functions? Since strings are just vectors for Matlab it should be easy to use them.
Regexp contains some nice functions for finding repeated values.

Linear programming - MATLAB

I've a [8x4] matrix, 'A', and a [8x1] matrix, 'B'. How do I check if there exists a [4x1] matrix 'x' such that A * X = B?
This can be done using linprog in MATLAB, but I'm not sure how to give the constraints. I tried x = linprog([],[],[],A,B);, but this doesn't seem to work.
How to specify the condition x>=0 and optimize it for A*X-B so that, if it returns 0, we know there is X.
Update:
pinv in MATLAB doesn't work in all the cases. Consider the following example:
A= [1 0 0 0
0 1 -1 -1
-1 -1 1 -1
-1 -1 -1 1
0 0 0 0
0 0 0 0
0 0 0 0
1 1 1 1]
B = [0
0
0
-1
0
0
0
1]
using pinv gives the the value of X as:
X = [-2.7756e-017
0.5000
0.5000
0]
but when linear programming is used I get x as:
X = [ 0
0.5000
0.5000
0]
This is the reason why I preferred linprog tool in MATLAB. I just used it the way I mentioned previously but it is throwing a lot of warnings. I still think there is a better way to use this function correctly. It did not throw for this matrix but in general when I loop through a lot of matrices my command window overflow with warnings.
Why use linear programming? You can just solve the system A*x=B directly:
A =[ 1 -1 -1 -1 1 0 0 1
-1 1 -1 0 0 1 0 0
-1 -1 1 0 1 0 0 0
-1 -1 -1 1 1 1 0 0]'; %'#
B = [-1 -1 0 0 0 0 1 1]'; %'#
x = A\B
x =
0.16327
0.097959
0.46531
0.11837
The problem you may face is that A can be rank deficient, but in that case, you'll get infinitely many solutions for x.
But why use a code that will do MORE work than necessary to solve the problem? Just use the pseudo-inverse. If A is of full rank, then backslash will be entirely sufficient.
Compute the solution. If the norm of your residuals is less than some tolerance, then you have a solution. Note that essentially no solution is ever assured to give you truly zero residuals, so you must apply a tolerance. Thus
x = A\B;
if norm(B - A*x) < tol
disp('Eureeka!')
end
Or use x=pinv(A)*B if you are worried about the rank of A.
Trying to throw linprog at the problem will surely not be more efficient than the direct solution itself.
Edit: Since non-negativity of the result has now been added as a requirement, use lsqnonneg instead. Just compare the norm of the residual vector to a tolerance. If the norm is too large, then no solution exists.
Unfortunately, you can not use array division. This is not the same a matrix division. However, you could use the inverse of the Matrix A to multiply it with matrix B to get x x = (A-1)B, but I am not sure if an inverse is possible for non-square matrix A (8x4). Hence, you might not have been able to work that with linprog