Generating complex antisymmetric matrix in Matlab - matlab

Is there any possibility to generate Gaussian random complex antisymmetric matrices in Matlab?
I have tried using randn(M). But that simply gives random matrices of Gaussian distribution.

This will deliver you a Gaussian random complex antisymmetric matrix M with numbers from 0 to x. If you change x, you change the upper limit of the RNG.
n = 5; %rows and columns
M = ones(n,n); %matrix initiation
x = 50; %limit of random number generator;
for i = 1 : n
M(i,:) = complex(round(50.*randn(1,n)),round(50.*randn(1,n))); %generate random number for the row;
M(:,i) = M(i,:).'; % take the same number and put it in the antisymmetric slot
end %for

Related

Why isn't my Matlab code for a randomly generated covariance matrix making a positive definite matrix?

Here is my code. I'm getting an error that when I use chol(V) that V is not positive definite. I would think that by construction it must be positive definite. Any idea what's going wrong?
% I want 10000 draws of a 5x1 multivariate normal distribution
N =5;
T = 10000;
% randomly generate standard deviations
sigma = 1 + .1*rand(N,1);
% randomly generate correlations which are between [-1,1]
rho = -1+2*rand(nchoosek(N,2),1);
% This grabs the indices of the elements in the lower triangle below the main diagonal
% itril comes from https://www.mathworks.com/matlabcentral/fileexchange/23391-triangular-and-diagonal-indexing
I = itril(N,-1);
% Initialize correlation matrix
corr = zeros(N);
% Fill in lower triangle of correlation matrix with generated correlations
corr(I) = rho;
% make correlation matrix symmetric with 1s on diagonal
corr = corr+corr'+eye(N);
% Variance matrix is sigma_i*sigma_j*corr(i,j)
V = (sigma*sigma').*corr;
% means vector
mu = rand(N,1);
% generate multivariate normal draws
e = mu' + randn(T,N)*chol(V);
That's just not the way to create a correlation matrix. Just because your matrix is symmetric, has 1's on the diagonal and values between -1 and 1 off the diagonal doesn't mean it's a correlation matrix. E.g. the way you create your matrix, you could have correlation +1 between random variables X1 and X2, +1 between X2 and X3, and -1 between X1 and X3, which is clearly not possible if the matrix entries come from the correlations between "real" random variables. So, there's also no guarantee that the matrix thus generated is positive (semi-) definite.
You should rather generate some matrix X that contains the (linear) dependencies between your random variables, and then your covariance matrix is simply X' * X (or X * X' depending on how you order X).

Generating random diagonally dominant dense/sparse matrices in matlab

Is there a matlab command for generating a random n by n matrix, with elements taken in the interval [0,1], with x% of the entries on the off-diagonal to be 0. Then, additionally setting the element in the diagonal to be the sum of every element in its respective column? In order to create a diagonally dominant dense/sparse matrix? This may be easy enough to write a code for but I was wondering if there was already a built in function with this capability.
EDIT:
I am new to Matlab/programming so this was an easier said than done. I'm having trouble making the matrix with the percentage ignoring the diagonal. It's a n x n matrix, so there are $n^2$ entries, with n of them on the diagonal, I want the percentage of zeros to be taken from $n^2 - n$ elements, i.e. all the off-diagonal elements. I cannot implement this correctly. I do not know how to initialize my M (see below) to correspond correctly.
% Enter percentage as a decimal
function [M] = DiagDomSparse(n,x)
M = rand(n);
disp("Original matrix");
disp(M);
x = sum(M);
for i=1:n
for j=1:n
if(i == j)
M(i,j) = x(i);
end
end
end
disp(M);
Here is one approach that you could use. I'm sure you will get some other answers now with a more clever approach, but I like to keep things simple and understandable.
What I'm doing below is creating the data to be put in the off-diagonal elements first. I create an empty matrix and copy this data into the off-diagonal elements using linear indexing. Now I can compute the sum of columns and write those into the diagonal elements using linear indexing again. Because the matrix was initialized to zero, the diagonal elements are still zero when I compute the sum of columns, so they don't interfere.
n = 5;
x = 0.3; % fraction of zeros in off-diagonal
k = round(n*(n-1)*x); % number of zeros in off-diagonal
data = randn(n*(n-1)-k,1); % random numbers, pick your distribution here!
data = [data;zeros(k,1)]; % the k zeros
data = data(randperm(length(data))); % shuffle
diag_index = 1:n+1:n*n; % linear index to all diagonal elements
offd_index = setdiff(1:n*n,diag_index); % linear index to all other elements
M = zeros(n,n);
M(offd_index) = data; % set off-diagonal elements to data
M(diag_index) = sum(M,1); % set diagonal elements to sum of columns
To refer to the diagonal you want eye(n,'logical'). Here is a solution:
n=5;
M = rand(n);
disp("Original matrix");
disp(M);
x = sum(M);
for i=1:n
for j=1:n
if(i == j)
M(i,j) = x(i);
end
end
end
disp('loop solution:')
disp(M);
M(eye(n,'logical'))=x;
disp('eye solution:')
disp(M);

How to generate a probability vector?

I would like to generate a vector of probabilities that is following some known distribution.
For example when I want the distribution to be uniform I can do in MATLAB:
N = 5;
proba = (1/(N))*ones(1, N);
What to do if I want to do it with Poisson distribution or Binomial distribution?
If you're looking for a solution that uses built-in MATLAB functions, you can look into random, which allows you to supply parameters to many types of well-known distributions.
For example, if you want to draw a M x N matrix of values from a binomial distribution with n trials and a p chance of success:
n=3; p=0.5; M=20; N=1;
random('Binomial',n,p,[M,N])
If you have a (discrete) probability distribution of your own creation, with the PMF given as a vector, you can sample from it by generating a random number r from a uniform distribution on [0,1] using r=rand() and then picking the first bin in the CMF which is greater than r.
x = [ 0 1 2 3 ];
PMF = [0.25 0.2 0.5 0.05];
CMF = cumsum(PMF);
N = 10000;
valuesDrawn = zeros(N,1);
for i = 1:N
r = rand();
for j = 1:length(PMF)
if r < CMF(j)
valuesDrawn(i) = x(j);
break;
end
end
end
hist(valuesDrawn);

Creating a sparse matrix in Matlab with a specified number of independent Bernoulli +-1 nonzero entries

How in Matlab we can form a matrix X, 1000 by 1000, which is sparse with, say,
5% of independent Bernoulli +-1 nonzero entries?
I.e. such a matrix would have rho = ||X||_0/10^6 = 0.05.
Randomly choose 5% of elements
n = numel(X);
ind = randi(n, round(.05*n), 1);
Assign these elements with random variable
X(ind) = binornd(1, .5, length(ind), 1) *2-1;
Check binornd's documentation for more details.
To avoid duplicate randi numbers, you can use randsample from the Statistics Toolbox, or something like randperm as mentioned in this post, or something like
EDIT
ind = [];
t0 = round(.05*n);
t1 = length(ind);
while t1 < t0
ind(end+1:t0) = randi(n, t0-t1, 1);
ind = unique(ind);
t1 = length(ind);
end
If you need to build the matrix as sparse (in Matlab's sense):
M = 1000; %// number of rows
N = 1000; %// number of columns
perc = 5/100; %// percentage (fraction) of +/-1 entries
n = round(M*N*perc); %// compute number of nonzero entries
nz = 2*(rand(1,n)<.5)-1; %// generate nonzero entries: +/-1 with .5 probability
ind = randsample(M*N,n); %// choose linear indices of nonzero entries
X = sparse(ind, 1 ,nz , M*N, 1, n); %// build matrix as linearized
X = reshape(X,M,N); %// put into shape

Creating Gaussian random variable with MATLAB

By using randn function I want to create a Gaussian random variable X such that X ~ N(2,4) and plot this simulated PDF together with theoretic curve.
Matlab randn generates realisations from a normal distribution with zero mean and a standard deviation of 1.
Samples from any other normal distribution can simply be generated via:
numSamples = 1000;
mu = 2;
sigma = 4;
samples = mu + sigma.*randn(numSamples, 1);
You can verify this by plotting the histogram:
figure;hist(samples(:));
See the matlab help.
N = 1000;
x = [-20:20];
samples = 2 + 4*randn(N, 1);
ySamples = histc(samples,x) / N;
yTheoretical = pdf('norm', x, 2, 4);
plot(x, yTheoretical, x, ySamples)
randn(N, 1) creates an N-by-1 vector.
histc is histogram count by bins given in x - you can use hist to plot the result immediately, but here we want to divide it by N.
pdf contains many useful PDFs, normal is just one example.
remember this: X ~ N(mean, variance)
randn in matlab produces normal distributed random variables W with zero mean and unit variance.
To change the mean and variance to be the random variable X (with custom mean and variance), follow this equation:
X = mean + standard_deviation*W
Please be aware of that standard_deviation is square root of variance.
N = 1000;
x = [-20:20];
samples = 2 + sqrt(4)*randn(N, 1);
ySamples = histc(samples,x) / N;
yTheoretical = pdf('norm', x, 2, sqrt(4)); %put std_deviation not variance
plot(x, yTheoretical, x, ySamples)
A quick and easy way to achieve this using one line of code is to use :
mu = 2;
sigma = 2;
samples = normrnd(mu,sigma,M,N);
This will generate an MxN matrix, sampled from N(μ,𝜎), (= N(2,2) in this particular case).
For additional information, see normrnd.