Solve matrix equation in matlab - matlab

I have an equation of the type c = Ax + By where c, x and y are vectors of dimensions say 50,000 X 1, and A and B are matrices with dimensions 50,000 X 50,000.
Is there any way in Matlab to find matrices A and B when c, x and y are known?
I have about 100,000 samples of c, x, and y. A and B remain the same for all.

Let X be the collection of all 100,000 xs you got (such that the i-th column of X equals the x_i-th vector).
In the same manner we can define Y and C as 2D collections of ys and cs respectively.
What you wish to solve is for A and B such that
C = AX + BY
You have 2 * 50,000^2 unknowns (all entries of A and B) and numel(C) equations.
So, if the number of data vectors you have is 100,000 you have a single solution (up to linearly dependent samples). If you have more than 100,000 samples you may seek for a least-squares solution.
Re-writing:
C = [A B] * [X ; Y] ==> [X' Y'] * [A';B'] = C'
So, I suppose
[A' ; B'] = pinv( [X' Y'] ) * C'
In matlab:
ABt = pinv( [X' Y'] ) * C';
A = ABt(1:50000,:)';
B = ABt(50001:end,:)';
Correct me if I'm wrong...
EDIT:
It seems like there is quite a fuss around dimensionality here. So, I'll try and make it as clear as possible.
Model: There are two (unknown) matrices A and B, each of size 50,000x50,000 (total 5e9 unknowns).
An observation is a triplet of vectors: (x,y,c) each such vector has 50,000 elements (total of 150,000 observed points at each sample). The underlying model assumption is that an observation is generated by c = Ax + By in this model.
The task: given n observations (that is n triplets of vectors { (x_i, y_i, c_i) }_i=1..n) the task is to uncover A and B.
Now, each sample (x_i,y_i,c_i) induces 50,000 equations of the form c_i = Ax_i + By_i in the unknown A and B. If the number of samples n is greater than 100,000, then there are more than 50,000 * 100,000 ( > 5e9 ) equations and the system is over constraint.
To write the system in a matrix form I proposed to stack all observations into matrices:
A matrix X of size 50,000 x n with its i-th column equals to observed x_i
A matrix Y of size 50,000 x n with its i-th column equals to observed y_i
A matrix C of size 50,000 x n with its i-th column equals to observed c_i
With these matrices we can write the model as:
C = A*X + B*Y
I hope this clears things up a bit.
Thank you #Dan and #woodchips for your interest and enlightening comments.
EDIT (2):
Submitting the following code to octave. In this example instead of 50,000 dimension I work with only 2, instead of n=100,000 observations I settled for n=100:
n = 100;
A = rand(2,2);
B = rand(2,2);
X = rand(2,n);
Y = rand(2,n);
C = A*X + B*Y + .001*randn(size(X)); % adding noise to observations
ABt = pinv( [ X' Y'] ) * C';
Checking the difference between ground truth model (A and B) and recovered ABt:
ABt - [A' ; B']
Yields
ans =
5.8457e-05 3.0483e-04
1.1023e-04 6.1842e-05
-1.2277e-04 -3.2866e-04
-3.1930e-05 -5.2149e-05
Which is close enough to zero. (remember, the observations were noisy and solution is a least-square one).

Related

For n = 2 ... 11 set up Vandermonde matrix A of size m × n and for each n given data set a. Matlab

I am given set of 50 data points with values {a^(i),b^(i)} for i=1,...,50
stored in the arrays a and b.
I know that the Vandermonde matrix A has size m x n, where n = 2 ... 11 and m is the size of the array a.
I want to to fit the data with a polynomial of degree (n − 1), for n = 2,...,11. To do that for each n I have to set up the Vandermonde matrix A of size m × n.
The Vandermonde matrix A solves the following equation:
A^T*A*x = A^T*b
Where the A^T is the transpose matrix and I have b already given.
Also we know that Aij = (a^(i))^(j−1) for j = 1,...,n,
What confuses me is how to set the matrix for n = 2,..,11.
What my line of thought is:
I have m = length(a); this will set up m = 50;
n = 11;
Then A=ones(m,n); This creates a matrix A filled with ones that has the correct size.
However I am not sure how to populate the matrix.
I wrote the following for loop which I thought will populate the matrix:
for n = 2:11
j=n;
for i = 1:50
A(i,n) = (a^(i))^(j-1);
end
end
Could you help me please with setting up the matrix?
You should use the vander function. However, vander will return an m x m matrix, which is usually used to fit the data to a polynomial of degree (m-1). Since you want to fit to a polynomial of degree (n-1), you only need the last n columns of that matrix.
Here's the code:
A = vander(a);
A = A(:,end-n+1:end);

Perform element wise multiplication of vectors efficiently?

I have to perform matrix updating by M = M + c*a*a' large number of times, where c is a constant and a is a column vector. If the size of matrix is larger than 1000, this simple updating will cost most of the time of my function, typically more than 1 min counted by profile.
Main codes are:
for i = 1:N
_do something..._
for k = 1:n
a(1:k) = M(1:k,1:k)*p(1:k);
M(1:k,1:k) = M(1:k,1:k)+c*a(1:k)*a(1:k)';
M(1:k, k+1) = b(1:k);
M(k+1, 1:k) = b(1:k)';
M(k+1, k+1) = x;
......
end
end
I have preallocated all variables, column vectors p and b are known, and x is another constant.
As I have large number of data to process by this function, does there exist more efficient alternative to this matrix updating?
You can concatenate a vectors to create a matrix A then apply multiplication just one time.
A =[a1 a2 a3];
M = c * A * A.';
consider the example
A = rand(5,5);
M = 0;
c=4;
for n = 1:5
M = M + c * A(:,n) * A(:,n).';
end
and this one
M1 = c * A * A.'
both M and M1 are equal
Have you tried using bsxfun?
In any case, bsxfun is much faster than regular multiplication, but the vectors/matrices have to be of equal length (which they are for you, aren't they?), and it's operating elementwise (i.e. a Nx1 vector bsx-multiplied with itself yields a Nx1 vector, multiplied with the transpose however yields a NxN matrix).
see https://mathworks.com/help/matlab/ref/bsxfun.html
use as
bsxfun(#times, a, a')

How to sum a sub-tensor of high dimention tensor in Matlab?

We are given a D-dimensional tensor, represented as a vector of size n^D.
The vector represents a D-dimensional distribution of a random variable X \in {0,1,..,n}^d. That is the (i_1,i_2,...,i_d) entry in the tensor represents the probability of X_1 = i_1, X_2 = i_2, ... X_d = i_d.
I need to compute, for each dimension d, and value i\in [n] the marginal distribution P(X_d = i).
i.e., this means that the answer of P(X_d = i) is the sum of n^(D-1) entries of the vector.
For example, if D=2 and n=4, we have a vector x of size (16,1) and the probability of the first dimension being equal to 1 is
P(X_1 = 1) = x(1) + x(2) + x(3) + x(4)
The probability of the second dimension being equal to 3 is '
P(X_2 = 3) = x(3) + x(7) + x(11) + x(15)
I'm writing Matlab code that needs to compute these marginal distributions, but I'm not familiar enough with Matlab to do it in a simple way (it is doable using some ugly recursion, but there has to be a better option).
To calculate P(X_k=z) for a D-dimensional matrix you can use
xD = reshape(x, n*ones(1,D));
B = permute(xD, [k setdiff(1:D, k)]);
P = sum(B(z,:));
It first makes it a D-dimensional matrix. It brings the dimension of interest k to the beginning and then chooses the z-th element and sums over elements corresponding to that.
Mohsen Nosratinia's answer would be my first option. As an alternative, it can be done without reshaping or permuting dimensions, which can result in faster code:
k = 2; %// chosen dimension
z = 3; %// chosen value (along d-th dimension)
result = sum(x(mod(floor((0:end-1)/n^(k-1)), n)==z-1));

Using matlabs regress like polyfit

I have:
x = [1970:1:2000]
y = [data]
size(x) = [30,1]
size(y) = [30,1]
I want:
% Yl = kx + m, where
[k,m] = polyfit(x,y,1)
For some reason i have to use "regress" for this.
Using k = regress(x,y) gives some totally random value that i have no idea where it comes from. How do it?
The number of outputs you get in "k" is dependant on the size of input X, so you will not get both m and k just by putting in your x and y straight. From the docs:
b = regress(y,X) returns a p-by-1 vector b of coefficient estimates for a multilinear regression of the responses in y on the predictors in X. X is an n-by-p matrix of p predictors at each of n observations. y is an n-by-1 vector of observed responses.
It is not exactly stated, but the example in the help docs using the carsmall inbuilt dataset shows you how to set this up. For your case, you'd want:
X = [ones(size(x)) x]; % make sure this is 30 x 2
b = regress(y,X); % y should be 30 x 1, b should be 2 x 1
b(1) should then be your m, and b(2) your k.
regress can also provide additional outputs, such as confidence intervals, residuals, statistics such as r-squared, etc. The input remains the same, you'd just change the outputs:
[b,bint,r,rint,stats] = regress(y,X);

trim auto-correlation result in MATLAB

I am using xcorr2(A,A) for computing the auto-correlation. But, the output is bigger than A. How I should trim the output to find the correct auto-correlation matrix? For example, my A matrix is 51x51 and the output will be 101x101. It is clear that the central point has the maximum correlation with itself which in this case is located in (26,26), but in the new auto-correlation map, it is located in (51,51). I need a general way to trim the final output.
In general you have to take M points from M/2 to 3M/2 in the 1st dimension, and N points from N/2 to 3N/2 in the 2nd dimension, assuming A is an M-by-N matrix:
[M, N] = size(A);
cor = xcorr2(A); %# Shorter form of xcorr(A, A)
C = cor(ceil(M / 2):floor(3 * M / 2), ceil(N / 2):floor(3 * N / 2))
Here C would be the trimmed output.
EDIT:
For any two matrices A and B, the result of xcorr2(A, B) would be a (MA+MB-1)×(NA+NB-1) matrix. Here, however, you'll have to decide for yourself which part you want to extract, if the matrices are not of equal dimensions. If you want to extract the significant central part, you can do it like so:
[MA, NA] = size(A);
[MB, NB] = size(B);
v = [MA + MB, NA + NB] / 4; %# Just a temporary vector
cor = xcorr2(A, B);
C = cor(ceil(v(1)):floor(3 * v(1)), ceil(v(2)):floor(3 * v(2))