Double Summation expression in MATLAB - matlab

I have a Parameter matrix, C of size 2x2. It looks like this.
C= [2 4; 6 8]
I have a decision variable, X of size 2x2. It looks like this
[ X('S1', 'D1') X('S1', 'D2') ]
[ X('S2', 'D1') X('S2', 'D2') ]
I want to formulate my Objective Function as a series of double expression (Please refer the attachment),
Which shall look like the following after the expansion.
Z = 2*X('S1', 'D1') + 4*X('S1', 'D2') + 6*X('S2', 'D1') + 8*X('S2', 'D2')
I try the following.
Z = sum(C.*X,1);
But it creates An optimizationExpression of size 1x3, which is not desired.
What am I doing wrong? Is there any easier way to do so without using for loop. I have just started learning "Problem-Based Optimization" in MATLAB today. Any help will be greatly appreciated.

As C and X are 2x2 matrices, so C.*X gives a 2x2 matrix. With sum(C.*X,1);, summation is done along the first dimension (i.e. rows are added). But you want to sum all the elements. So if you convert your matrices into a vector and then multiply element-wise and then apply sum, it will add all the elements i.e.
Z = sum(C(:).*X(:));
Alternatively, you can first multiply and then convert the result into a vector before applying sum.
CX = C.*X;
Z = sum(CX(:));
or sum along all the dimensions one by one. But I'd go with the solution suggested in the beginning.

Related

How can I easily create a dynamic 2D matrix of vectors in Matlab

Given my code:
G=zeros(height,width); %zeros or whatever
for y = 1 : height
for x = 1 : width
magnitude = sqrt(Gx(y,x)^2 + Gy(y,x)^2);
gradient_direction = atan(Gy(y,x)/Gx(y,x));
G(y,x) = [magnitude gradient_direction];
end
end
I keep getting this (if I don't use zeros()):
Subscripted assignment dimension mismatch.
or this:
Assignment has more non-singleton rhs dimensions than non-singleton
subscripts
While #atru answer works, I would want to suggest a vectorize way that faster and neater, if that will help. The operations here can easily converted to vectorized operations:
G=cat(3,hypot(Gy,Gx),atan(Gy./Gx));
By using G(y,x,:) = [magnitude, gradient_direction]; you are attempting to assign two values to a spot reserved for a single value with indices (y,x). One way to fix this is to use a 3 dimensional array G instead,
G=zeros(height,width,2);
for y = 1 : height
for x = 1 : width
magnitude = sqrt(Gx(y,x)^2 + Gy(y,x)^2);
gradient_direction = atan(Gy(y,x)/Gx(y,x));
G(y,x,:) = [magnitude, gradient_direction];
end
end
Now at each point G(y,x) you can store both of the values and access them as for instance G(1,2,1) for magnitude at (1,2) position and G(1,2,2) for gradient_direction. This assumes Gx and Gy are both arrays with size height x width.
Important thing to note is that slices of G along the third dimension will also be 3D arrays, i.e. mag_dir = G(3,2,:) will have a size [1 1 2] and not [1 2]. This may cause errors in some applications, examples include trying to concatenate mag_dir with another vector (that does not have the extra dimension) and linear algebra operations.
To resolve this, use reshape to explicitly change the dimensions to to target ones. For the vector here it would be reshape(mag_dir, 1, 2). Same holds for 2D slices like more_md = G(1,:,:) - this will need for instance more_md = reshape(more_md,2,5).

Find the position of the minimal value of a three dimensional array in Matlab

Sorry for asking such a simple and silly question, but Matlab is really too hard to use for me. My question is just how to find the position the minimal value of a three dimensional array in Matlab.
For example, suppose I define a three dimensional array
m=zeros(2,2,2);
m(1,2,2)=-2;
The minimal value of m should be -2, located at (1,2,2). I can find the minimal value by
m0=min(min(min(m)));
But when I find its position by using
[x y z]=find(m==m0);
Instead of returning x=1, y=2 and z=2, it returns x=1, y=4 and z=1.
I appreciate if anyone would answer this question!
You can use min to find the minimum index of m and then convert it to x, y and z coordinates. There is no need to use find also.
min can be used with multiple output arguments to return the index of the minimum element. Here, I also use : to return every element of m as a column vector.
>> m=zeros(2,2,2);
>> m(1,2,2)=-2;
>> m(:)
ans =
0
0
0
0
0
0
-2
0
>> [~, ind] = min(m(:))
ind =
7
Now we have our index we need to convert it back into x, y and z coordinates. This can be done using ind2sub or manually by hand.
>> [x y z] = ind2sub(size(m), ind)
x =
1
y =
2
z =
2
You're correct. This is more complicated than it should be. The problem is that MATLAB is hardwired to work with matrices (i.e. arrays of rank 2), rather than arrays of general rank. Here's the solution:
m0 = min(m(:))
[x y z] = ind2sub(size(m), find(m(:) == m0))
Explanation:
If you type help find, you may notice that your original code was using the [rows, cols, vals] version of find, which is not what you expected.
Instead, min(m(:)) is a simplification of your min(min(min(m))). It automatically reshapes m into a rank one array (i.e. a vector).
The expression find(m(:) == m0) returns a single index for the minimum position in this reshaped vector. Finally, ind2sub converts this single index into a set of three indices, given the shape of m.

Matlab integral over function of symbolic matrix

In an attempt to speed up for loops (or eliminate all together), I've been trying to pass matrices into functions. I have to use sine and cosine as well. However, when I attempt to find the integral of a matrix where the elements are composed of sines and cosines, it doesn't work and I can't seem to find a way to make it do so.
I have a matrix SI that is composed of sines and cosines with respect to a variable that I have defined using the Symbolic Math Toolbox. As such, it would actually be even better if I could just pass the SI matrix and receive a matrix of values that is the integral of the sine/cosine function at every location in this matrix. I would essentially get a square matrix back. I am not sure if I phrased that very well, but I have the following code below that I have started with.
I = [1 2; 3 4];
J = [5 6; 7 8];
syms o;
j = o*J;
SI = sin(I + j);
%SI(1,1) = sin(5*o + 1)
integral(#(o) o.*SI(1,1), 0,1);
Ideally, I would want to solve integral(#(o) o*SI,0,1) and get a matrix of values. What should I do here?
Given that A, B and C are all N x N matrices, for the moment, let's assume they're all 2 x 2 matrices to make the example I'm illustrating more succinct to understand. Let's also define o as a mathematical symbol based on your comments in your question above.
syms o;
A = [1 2; 3 4];
B = [5 6; 7 8];
C = [9 10; 11 12];
Let's also define your function f according to your comments:
f = o*sin(A + o*B + C)
We thus get:
f =
[ o*sin(5*o + 10), o*sin(6*o + 12)]
[ o*sin(7*o + 14), o*sin(8*o + 16)]
Remember, for each element in f, we take the corresponding elements in A, B and C and add them together. As such, for the first row and first column of each matrix, we have 1, 5 and 9. As such, A + o*B + C for the first row, first column equates to: 1 + 5*o + 9 = 5*o + 10.
Now if you want to integrate, just use the int command. This will find the exact integral, provided that the integral can be solvable in closed form. int also can handle matrices so it will integrate each element in the matrix. You can call it like so:
out = int(f,a,b);
This will integrate f for each element from the lower bound a to the upper bound b. As such, supposing our limits were from 0 to 1 as you said. Therefore:
out = int(f,0,1);
We thus get:
out =
[ sin(15)/25 - sin(10)/25 - cos(15)/5, sin(18)/36 - sin(12)/36 - cos(18)/6]
[ sin(21)/49 - sin(14)/49 - cos(21)/7, sin(24)/64 - sin(16)/64 - cos(24)/8]
Bear in mind that out is defined in the symbolic math toolbox. If you want the actual numerical values, you need to cast the answer to double. Therefore:
finalOut = double(out);
We thus get:
finalOut =
0.1997 -0.1160
0.0751 -0.0627
Obviously, this can generalize for any size M x N matrices, so long as they all share the same dimensions.
Caveat
sin, cos, tan and the other related functions have their units in radians. If you wish for the degrees equivalent, append a d at the end of the function (i.e. sind, cosd, tand, etc.)
I believe this is the answer you're after. Good luck!

Graphing Polynomials in MATLAB

I need to create a polynomial of the form:
P(x) = q(1,1) + q(2,2)(x-z(1)) + q(3,3)(x-z(1))(x-z(2)) + --- + q(2n, 2n)(x-z(1))(x-z(2))...(x-z(2n)) NOTE: The indices of the equation have been shifted to accomodate MATLAB.
in MATLAB. Consult this link here specifically slides 15 and 16.
I have the matrix Q filled, so I have the diagonal, and I also have z(1:2n) filled.
I'm having a hard time figuring out a way to create a polynomial that I can graph this polynomial. I've tried to use a for loop to append each term to P(x), but it doesn't operate the way I thought it would.
So far, my code will calculate the coefficients (presented as Q(0,0) -> Q(2n+1, 2n+1) in the problem above) without a problem.
I'm having an issue with the construction of a degree n polynomial of the form described above. Plotting makes more sense now, create a vector x with evaluative values, and then run them through the polynomial "function" and plot the x vector against the resulting vector.
So I just need to create this polynomial.
I would use diag and cumprod to help you accomplish this. First use diag to extract the diagonals of your matrix Q. After, use cumprod to generate a vector of cumulative products.
How cumprod works on a vector is that for each element in the vector, the i'th element collects products from 1 up to the i'th element. As an example, if we had a vector V = [1 2 3 4 5], cumprod(V) would produce [1 2 6 24 120]. The 4th element (as an example) would be 1*2*3*4, representing the products from the 1st to the 4th element.
As such, this is the code that I would do:
qdiag = diag(Q);
xMinusZ = x - z; % Takes z and does x - z for every element in z
cumProdRes = cumprod(xMinusZ);
P = sum(qdiag .* [1;cumProdRes(1:end-1)]);
P should give you P(x) that you desired. Make sure that z is a column vector to make it compatible with the diagonals extracted from Q.
NB: I believe there is a typo in your equation. The last term of your equation (going with your convention) should have (x-z(2n-1)) and not (x-z(2n)). This is because the first term in your equation does not have z.
Here's an example. Let's suppose Q is defined
Q = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
The vector z is:
z = [4;3;2;1];
Let's evaluate the function at x = 2
Extracting the diagonals of Q should give us Q = [1;6;11;16]. Subtract x from every element of z should give us:
xMinusZ = [-2;-1;0;1];
Using the equation that you have above, we have:
P = 1 + 6*(-2) + 11*(-2)*(-1) + 16*(-2)*(-1)*(0) = 11
This is what the code should give.
What if we want to do this for more than one value of x?
As you have stated in your post, you want to evaluate this for a series of x values. As such, you need to modify the code so that it looks like this (make sure that x is a column vector):
qdiag = diag(Q);
xMinusZ = repmat(x,1,length(z)) - repmat(z',length(z),1);
cumProdRes = cumprod(xMinusZ,2);
P = sum(repmat(qdiag',length(z),1).*[ones(length(z),1) cumProdRes(:,1:end-1)],2);
P should now give you a vector of outputs, and so if you want to plot this, simply do plot(x,P);

How do I put in two variables in a matlab function (ERROR: inner matrix dimensions must agree)?

When I try to plot a function h in MATLAB, using a variable omega which is defined as its own function, I get an Inner matrix dimensions must agree, error using _*_ response from the console.
The function works when I use a + between the seperate function-components of h; It does not work when I try multiplying the two inner functions in h, which is, from what I guess, what causes the matrix dim error.
function h = freqp(omega)
k = (1:1024-1);
hh = (1:1024-1);
omega = zeros(length(k),1);
omega = (k-1)*((2*pi)/1024);
hh = 2*exp((-3j)*omega)*cos(omega); % This works for ...omega) + cos(...
% but not for ...omega) * cos(, why?
y = fft(hh);
stem(real(y), omega);
How can I solve this? I read the info on mathworks but it only gives a solution for e.g. loading a file. Any help would be greatly appreciated!
Since Omega is a vector, the addition works. But multiplication of two vectors will result as a matrix. You can modify
hh = 2*exp((-3j)*omega)*cos(omega);
as
hh = 2*exp((-3j)*omega)*(cos(omega))';
or looking for element wise multiplication,
use
hh = 2*exp((-3j)*omega).*cos(omega);
The part exp((-3j)*omega worked fine because -3j is a complex scalar and omega a vector. Thus, MATLAB multiplies each element of omega with -3i. However, that result is a vector itself. Also cos(omega) is a vector, and both are row vectors.
In this case, with two vectors, the *-operator means dot product but that would be calculated between a column vector and a row vector, not two row vectors. So, [1 2 3] * [4 5 6] will raise the same error you are reporting, but [1 2 3] * [4 5 6]' yields 32.
From invoking fft on hh your code looks, however, as if you never intended to calculate a dot product (a scalar) but instead were looking for element-wise multiplication. The operator for element-wise multiplication is .*, such that your expression would be instead
hh = 2*exp((-3j)*omega).*cos(omega);