MATLAB: How to make the Hermitean matrix from specific complex vectors? - matlab

Is given:
stationary mass ms=1;
Eta-constant eta=0.45;
variable number of repetitions, e.g. N=5;
omega OM=sqrt(ks/ms);
angular frequency om=eta*OM;
time period T=2*pi/om;
upper bound TTT=1.5;
variable for creating function t=0:0.001:TTT;
I made a function like that:
kt=zeros(size(t));
for j=1:2*N+1
n= j-(N+1);
if n==0
k(j)=ks/2;
else
k(j)=i/pi/n;
end
kt=kt+k(j)*exp(i*n*om*t);
end
It’s a Sawtooth wave and there is my problem. From the complex vector kt with value 1x1501 double I have to make the Hermitean matrix for variable N. This means that N can be 5, can be 50, 100, etc. The matrix should look like (picture):
Where k1 is k for N=1, k0 is k for N=0 or k-1 is k for N=-1. Size of matrix is 2*N+1 and 2*N+1.
Thank you for your help and responding!

That's a Toeplitz matrix, you can use the toeplitz command to generate the matrix above. In the general case, this would have been written as:
H = toeplitz(kt(N:end), kt(1:N + 1))
where the first N values in kt correspond to k-N, ... k-1, and the last N + 1 values are k0, ... kN. However, since H is Hermitian, this can be simplified to:
H = toeplitz(kt(N:end));

Try this code:
k=[1 2+i 3+i 4+i 5+i];
N=7;
M=diag(k(1)*ones(N,1));
for j=1:length(k)-1
M=M+diag(k(j+1)*ones(N-j,1),j)+diag(conj(k(j+1))*ones(N-j,1),-j)
end;
Here N should be equal or greater than the length of k array

Related

How do you find an 'M' by 'M' submatrix in the center of an input 'N' by 'N' matrix? (In Matlab)

How do I write a function in Matlab to output the M x M submatrix at the center of an N x N input matrix? The function should have two input arguments—the N x N input matrix (2D array) and the size of the square submatrix, M, to be extracted from the input matrix. The sole output should be the M x M submatrix at the center of the input matrix. The function should use for loops to extract the submatrix and not use colon notation or any built-in functions for this part of the code. The function should work for any square input matrix where N ≥ 3. If N is even, M should be even. If N is odd, M should be odd.
Here is a picture of my flowchart so far.
Using For-Loops and Offsetting Indexing
Preface:
Here I like to visualize this question as trimming the matrix. The amount to trim I denote in this example is Trim_Amount. The Trim_Amount dictates the size of the sub-matrix and the start point to begin reading/saving the sub-matrix.
Since the trim amount is always taken from each side you can expect the sub-matrix to have dimensions in the form:
Sub-Matrix Width = M - (2 × Trim_Amount)
2 × Trim_Amount will always result in an even number therefore the following can be said:
if M is even → M - (Even Number) → Even Number
if M is odd → M - (Even Number) → Odd Number
Test Output Results:
I recommend going through the code to filter through any unexpected issues.
Full Script:
Dimension = 7;
Matrix = round(100*rand(Dimension));
Trim_Amount = 1;
[Sub_Matrix] = Grab_Sub_Matrix(Matrix,Trim_Amount);
Matrix
Sub_Matrix
%Function definition%
function [Sub_Matrix] = Grab_Sub_Matrix(Matrix,Trim_Amount)
%Minimum of M must be 5 since N >= 3%
[M,~] = size(Matrix);
%Ensuring the trimming factor does not go over possible range%
Max_Trimming_Factor = M - 3;
if(Trim_Amount > Max_Trimming_Factor)
Trim_Amount = Max_Trimming_Factor;
end
%Fill in the boundaries%
Row_Start_Limit = Trim_Amount + 1;
Column_Start_Limit = Trim_Amount + 1;
%Creating sub-matrix based on amount of trimming%
Sub_Matrix = zeros(M-(2*Trim_Amount),M-(2*Trim_Amount));
for Row = 1: length(Sub_Matrix)
for Column = 1: length(Sub_Matrix)
% fprintf("(%d,%d)\n",Row,Column);
Sub_Matrix(Row,Column) = Matrix(Row + Row_Start_Limit-1,Column + Column_Start_Limit-1);
end
end
end
Ran using MATLAB R2019b

How can I factor specific variables out of a formula in Matlab?

Suppose I have a column vector of formulae like this
N =
4*k2 + 5*k3 + k1*x
7*k2 + 8*k3 + k1*y
and a column vector of symbolic variables like this
k =
k1
k2
k3
The formulae are linear with respect to k. I'd like to find a matrix M such that M*k equals N.
I can do this with N/k. However, that gives
[ (4*k2 + 5*k3 + k1*x)/k1, 0, 0]
[ (7*k2 + 8*k3 + k1*y)/k1, 0, 0]
which is correct, but not what I want. What I want is the matrix
x 4 5
y 7 8
which seems to me the simplest answer in that it involves no variables from k.
How do I convince Matlab to factor out the specified variables from a formula or a vector of formulae?
You can use coeffs, specifically the form
C = coeffs(p,vars) returns coefficients of the multivariate polynomial p with respect to the variables vars.
Since the first input needs to be a polynomial, you need to pass each component of N:
coeffs(N(1), k)
coeffs(N(2), k)
Or use a loop and store all results in a symbolic array:
result = sym('result', [numel(N) numel(k)]); % create symbolic array
for m = 1:numel(N)
result(m,:) = coeffs(N(m), k);
end
In your example, this gives
result =
[ 5, 4, x]
[ 8, 7, y]
Based on #LuisMendo's answer, I used coeffs. But there are a couple of problems with coeffs. The first is that its result doesn't include any coefficients that are 0. The second is that it doesn't seem to guarantee that the coefficients are ordered the same way as the variables in its second argument. I came up with the following function to replace coeffs.
Luckily coeffs returns a second result that lists the variables associated with each item in the first result. (It's more complicated if the formula is not linear.)
function m = factorFormula(f, v )
% Pre: f is a 1x1 sym representing a
% linear function of the variables in v.
% Pre: v is a column vector of variables
% Post: m is a row vector such that m*v equals f
% and the formulas in m do not contain the
% variables in v
[cx,tx] = coeffs(f,v)
n = size(v,1)
m = sym(zeros(1,n))
for i = 1:n
j = find(tx==v(i))
if size(j,2) == 1
m(i) = cx(j)
end
end
end
This only works for one formula, but it can be extended to a vector using the loop in #LuisMendo's answer or this equivalent expression in #Sanchises comment there.
cell2sym(arrayfun( #(f)factorFormula(f,k),N,'UniformOutput',false ) )
I hope there is a better answer than this.

Double for loop MATLAB

I need to do an estimation procedure for n time series (n vectors of T observations). I have the formula to evaluate my variable (using a for loop) but I need to repeat this n times (the number of vectors).
h0 = var(residuals);
ht=zeros(T,n); ht(T,1)=h0;
for i=2:T
ht(i) = theta(1) + theta(2)*residuals(i-1)^2 + theta(3)*ht(i-1);
end
So this loop calculates ht for all of the observations in series one, but I need another for loop that helps me to use this formula for all of the series.
Edit: This is what I've done based on the below answer:
function ht = VarEQ(theta,residuals)
[T,n] = size(residuals)
for k=1:n
h0 = var(residuals(:,k));
ht=zeros(T,n); ht(1,k)=h0;
for i=2:T
ht(i,k) = theta(1,k) + theta(2,k)*residuals(i-1,k)^2 + theta(3,k)*ht(i-1,k);
end
end
end
Current problem:
Now ht is all columns of zero and just the last column of correct values.
Variables
var is a 1xn row vector of variances. Using k, I want just the scalar for each residual.
theta is a 3xn matrix of parameters.
residuals is a Txn matrix.
This seems simple given what you already have set up:
function ht = VarEQ(theta,residuals)
[T,n] = size(residuals)
ht=zeros(T,n); % Initialise matrix OUTSIDE loop so it isn't over-written!
for k=1:n % additional loop for series 1 to n
ht(1,k) = var(residuals(:,k));;
for i = 2:T
% Ensure you are referencing the kth series
ht(i,k) = theta(1,k) + theta(2,k)*residuals(i-1,k)^2 + theta(3,k)*ht(i-1,k);
end
end
end
Note: previously, all columns of ht were the same, because theta and residuals were the same for each series!
With your updated code, and the updated code in this answer, that has been fixed.

matlab concatenating vectors

I'm new to MATLAB, and programming in general, and I am having difficulty accomplishing what I am sure is a very, very simple task:
I have a list of vectors v_i for i from 1 to n (n in some number), all of the same size k. I would like to create a vector v that is a "concatenation" (don't know if this is the correct terminology) of these vectors in increasing order: what I mean by this is that the first k entries of v are the k entries of v_1, the k+1 to 2k entries of v are the k entries of v_2 etc. etc. Thus v is a vector of length nk.
How should I create v?
To put this into context, here is function I've began writing (rpeakindex will just a vector, roughq would be the vector v I mentioned before):
function roughq = roughq(rpeakindex)
for i from 1 to size(rpeakindex) do
v_i = [rpeakindex(i)-30:1:rpeakindex(i)+90]
end
Any help is appreciated
Let's try two things.
First, for concatenating vectors there are a couple of methods here, but the simplest would be
h = horzcat(v_1, v_2);
The bigger problem is to enumerate all vectors with a "for" loop. If your v_n vectors are in a cell array, and they are in fact v{i}, then
h= [];
for j=1:n
h = horzcat(h, v{i});
end
Finally, if they only differ by name, then call them with
h=[];
for j=1:n
h= horzcat(h, eval(sprintf('v_%d',j));
end
Let the arrays (vectors) be:
v_1=1:10;
v_2=11:20;
v_3=21:30;
v_4=31:40;
and so on.
If they are few (e. g. 4), you can directly set then as input in the cat function:
v=cat(2,v_1,v_2,v_3,v_4)
or the horzcat function
v=horzcat(v_1,v_2,v_3,v_4)
otherwise you can use the eval function within a loop
v1=[];
for i=1:4
eval(['v1=[v1 v_' num2str(i) ']'])
end
Hope this helps.
Concatenating with horzcat is definitely an option, but since these vectors are being created in a function, it would be better to concatenate these vectors automatically in the function itself rather than write out horzcat(v1,v2,....vn) manually.
Given the function mentioned in the question, I would suggest something like this:
function v = roughq(rpeakindex)
v = zeros(121,length(rpeakindex)); %// create a 2D array of all zeros
for i = 1:size(rpeakindex)
v(:,i) = [rpeakindex(i)-30:1:rpeakindex(i)+90]; %// set result to ith column of v
end
v = v(:)'; %'//reshape v to be a single vector with the columns concatenated
end
Here's a simplified example of what's going on:
N = 3;
v = zeros(5,N);
for i = 1:N
v(:,i) = (1:5)*i;
end
v = v(:)';
Output:
v =
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15
You may want to read up on MATLAB's colon operator to understand the v(:) syntax.
If you mean 2d matrix, you are using for holding vectors and each row hold vector v then you can simply use the reshape command in matlab like below:
V = [] ;
for i = 1:10
V(i,:) = randi (10,1 ,10) ;
end
V_reshpae = reshape (V, 1, numel(V)) ;

Vectorising 5 nested FOR loops

I am writing a program in MATLAB as a part of my project based on DFT.
Let the N x N data matrix be X and the corresponding DFT matrix be Y, then the DFT coefficients can be expressed as
Y(k1,k2) = ∑(n1=0:N-1)∑(n2=0:N-1)[X(n1,n2)*(WN^(n1k1+n2k2))] (1)
0≤k1,k2≤N-1
Where WN^k=e^((-j2πk)/N)
Since the twiddle factor WN is periodic, (1) can be expressed as
Y(k1,k2)=∑(n1=0:N-1)∑(n1=0:N-1)[X(n1,n2)*(WN^([(n1k1+n2k2)mod N) ] (2)
The exponent ((n1k1 +n2k2)) N = p is satisfied by a set of (n1,n2) for a given (k1,k2). Hence, by grouping such data and applying the property that WN^(p+N /2) = -(WN^P),
(2) can be expressed as
Y(k1,k2)= ∑(p=0:M-1)[Y(k1,k2,p)*(WN^p)] (3)
Where
Y(k1,k2,p)= ∑(∀(n1,n2)|z=p)X(n1,n2) - ∑(∀(n1,n2)|z=p+M)X(n1,n2) (4)
z=[(n1k1+n2k2)mod N] (5)
I am coding a program to find Y(k1,k2,p).ie I need to create slices of 2d matrices(ie a 3D matrix in which each slice is a 2D matrix )from a given 2D square matrix (which is the matrix X)..Dimensions of X can be upto 512.
Based on the above equations,I have written a code as follows.I need to vectorise it.
N=size(X,1);
M=N/2;
Y(1:N,1:N,1:M)=0;
for k1 = 1:N
for k2 = 1:N
for p= 1:M
for n1=1:N
for n2=1:N
N1=n1-1; N2=n2-1; P=p-1; K1=k1-1; K2=k2-1;
z=mod((N1*K1+N2*K2),N);
if (z==P)
Y(k1,k2,p)= Y(k1,k2,p)+ X(n1,n2);
elsif (z==(P+M))
Y(k1,k2,p)= Y(k1,k2,p)- X(n1,n2);
end
end
end
end
end
As there is 5 FOR loops, the execution time is very large for large dimensions of N. Hence please provide me a solution for eliminating the FOR loops and vectorising the code..I need to make the code execute in maximum speed...Thanks Again..
Here is a first hint to vectorize the most inner loop.
From your code, we can notice that n1, N1, P, K1 and K2 are constant in this loop.
So we can rewrite z as a mask vector as follows:
z = mod(N1*K1+K2*(0:N-1));
Then your if-statement is equivalent to adding the sum of all elements in X so that z==P minus the sum of all elements in X so that z==P+M. Rewriting this is straightforward:
Y(k1,k2,p)= Y(k1,k2,p)+sum(X(n1,z==P))-sum(X(n1,z==P+M));
So your program can be first written as follows:
N=size(X,1);
M=N/2;
Y(1:N,1:N,1:M)=0;
for k1 = 1:N
for k2 = 1:N
for p= 1:M
for n1=1:N
N1=n1-1; P=p-1; K1=k1-1; K2=k2-1;
z=mod(N1*K1+K2*(0:N-1),N);
Y(k1,k2,p) = sum(X(n1,z==P))-sum(X(n1,z==P+M));
end
end
end
end
Then you can do the same thing with n1; for that, you need to construct a 2D array for z, such as:
z = mod(K1*repmat(0:N-1,N,1)+K2*repmat((0:N-1).',1,N));
Notice that size(z)==size(X).Then the 2D sum for Y becomes:
Y(k1,k2,p) = Y(k1,k2,p)+sum(X(z==P))-sum(X(z==P+M));
The += operation is here no longer needed, since you access only once to each element of Y:
Y(k1,k2,p)= sum(X(n1,z==P))-sum(X(n1,z==P+M));
And so we discard one more loop:
N=size(X,1);
M=N/2;
Y(1:N,1:N,1:M)=0;
for k1 = 1:N
for k2 = 1:N
for p= 1:M
P=p-1; K1=k1-1; K2=k2-1;
z = mod(K1*repmat(0:N-1,N,1)+K2*repmat((0:N-1).',1,N));
Y(k1,k2,p) = sum(X(z==P))-sum(X(z==P+M));
end
end
end
Concerning the other loops, I don't think it worths it to vectorize them, as you have to build a 5D array, which could be very huge in memory. My advise is to keep z as a 2D array, as it is of the size of X. If it does not fit well in memory, just vectorize the most inner loop.