Force entries of a matrix to be a variable - matlab

I have a square matrix that I need to use with fminsearch. Some of the values of the matrix need to be variable because they are the values that I will be using with fminsearch, and I need to preserve their location in the matrix. So for example, with
X=[1,2,3;4,5,6;7,8,9];
I would like make this
p(1)=a1;
p(2)=a2;
p(3)=a3;
p(4)=a4;
X=[1, 2, a1 ; a2, 5, a3 ; 7, 8, a4];
So that I could do operations on X to create something to be minimized with fminsearch. For example, suppose I wanted to find a1, a2, a3, and a4 so that I minimized C in the following code, which computes the summed entropy of a given matrix:
Ent=zeros(size(X,1),1);
for k=1:size(X,2);
const=X(k,:);
logX=log(X(k,:));
logX=logX';
Ent(k,:)=const*logX;
end
Ent=-Ent;
C=sum(Ent);
Is this possible with MATLAB? Suppose further I had an nxn matrix with q paramaters, how would I adjust the idea to minimize the same C?
EDIT:
I figured out how to do what I want. However it has come to me that a gradient descent algorithm is really a better way of doing this. I'll post a sample of what I was doing:
function test()
[new_param entropy]=fminsearch(#Cost,[3,3,3]);
function C=Cost(p)
X=rand(5);
X(1,1)=p(1);
X(2,2)=p(2);
X(3,3)=p(3);
Ent=zeros(size(X,1),1);
for k=1:size(X,2);
const=X(k,:);
logX=log(X(k,:));
logX=logX';
Ent(k,:)=const*logX;
end
Ent=-Ent;
C=sum(Ent);
end
X(1,1)=new_param(1);
X(2,2)=new_param(2);
X(3,3)=new_param(3);
X
new_param
entropy
end

I think that you could try something like this:
A = #(x) [1 2 x(1); 3 4 x(2); 5 6 x(3)];
or, alternatively, making use of the Symbolic Toolbox:
syms x y z
A = [1 2 x; 3 4 y; 5 6 z];

I may misunderstand, but I think it is as simple as this:
X=[1, 2, p(1) ; p(2), 5, p(3) ; 7, 8, p(4)];
After updating p just run this statement again and you have your desired X.

Related

apply arrayfun for a couple of values

I wrote a syntax that calculate values of a function in different values.
For example
x1=[1 2 10 11];
x2=[10 11 12 14];
C= arrayfun (#(t1,t2) myfunction(A,B,t1,t2),x1,x2,'UniformOutput',0);
% A and B are matrixs
In this example the function will do an operation on A(x1,x2) and B(x1,x2) . The problem is that arrayfun will work on each couple (x1(1),x2(1)), x1(2),x2(2)),etc. But I want it to work on all the values of x1 and x2 (16 couples of values so that it can be applied also to for example (x1(1),x2(3))).
Is there any way to do that without a loop?
using ndgrid:
[X Y] = ndgrid(x1,x2);
C= arrayfun (#(x1,x2) myfunction(A,B,t1,t2),X(:),Y(:),'UniformOutput',0);
So I'm going to offer the "dumb" way of doing it without you having to modify your call to your function:
x1=[1 2 10 11];
x2=[10 11 12 14];
v = combvec(x1,x2);
X1 = v(1,:);
X2 = v(2,:);
C= arrayfun (#(X1,X2) myfunction(A,B,t1,t2),X1,X2,'UniformOutput',0);
This effectively calculated all combinations of x1 and x2, then you input it thru your function in pairs just like you were doing it before.

applying arrayfun on n-dimensional matrixes

i need your help in solving the following problem:
how can i generalize the following for any n dimensional array:
reshape(arrayfun(#(x,y)sprintf('%d,%d',x,y),C{:},'un',0),size(M));
M is my matrix and C is my matrix of indexes of M.
thanks in advance.
The problem isn't the number of dimensions in the arguments to arrayfun per se, but the number of arguments themselves - which happens in your example to correspond to the number of dimensions each argument has. You therefore need to pass it a function that accepts varargin, which still works on an anonymous function:
reshape(arrayfun(#(varargin)sprintf(strjoin(repmat('%d',size(varargin)),','),varargin{:}),C{:},'un',0),size(M));
This function gave me a lot of headache.
For functions like
f1 = #(x1,x2) x1*x2
You can do
output = arrayfun(f1,x1,x2);
where x1 and x2 are input columns.
However, if you're doing a generalized program, where f1 could have any number of inputs and you need a generalized input matrix like X, you'll need, for example
f1 = #(x1,x2,x3,x4,x5) 2*x1+4*x2+10*x3+0.2*x4+x5;
output = arrayfun(f1,num2cell(X,1){:});
where X represents a matrix with 5 columns representing x1 through x5
For example:
X = [1, 2, 3, 4, 5;
6, 7, 8, 9, 0;];

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!

Need help in using bsxfun

I have two arrays in MATLAB:
A; % size(A) = [NX NY NZ 3 3]
b; % size(b) = [NX NY NZ 3 1]
In fact, in the three dimensional domain, I have two arrays defined for each (i, j, k) which are obtained from above-mentioned arrays A and b, respectively and their sizes are [3 3] and [3 1], respectively. Let's for the sake of example, call these arrays m and n.
m; % size(m) = [3 3]
n; % size(n) = [3 1]
How can I solve m\n for each point of the domain in a vectorize fashion? I used bsxfun but I am not successful.
solution = bsxfun( #(A,b) A\b, A, b );
I think the problem is with the expansion of the singleton elements and I don't know how to fix it.
I tried some solutions, it seems that a for loop is acutally the fastest possibility in this case.
A naive approach looks like this:
%iterate
C=zeros(size(B));
for a=1:size(A,1)
for b=1:size(A,2)
for c=1:size(A,3)
C(a,b,c,:)=squeeze(A(a,b,c,:,:))\squeeze(B(a,b,c,:));
end
end
end
The squeeze is expensive in computation time, because it needs some advanced indexing. Swapping the dimensions instead is faster.
A=permute(A,[4,5,1,2,3]);
B=permute(B,[4,1,2,3]);
C2=zeros(size(B));
for a=1:size(A,3)
for b=1:size(A,4)
for c=1:size(A,5)
C2(:,a,b,c)=(A(:,:,a,b,c))\(B(:,a,b,c));
end
end
end
C2=permute(C2,[2,3,4,1]);
The second solution is about 5 times faster.
/Update: I found an improved version. Reshaping and using only one large loop increases the speed again. This version is also suitable to be used with the parallel computing toolbox, in case you own it replace the for with a parfor and start the workers.
A=permute(A,[4,5,1,2,3]);
B=permute(B,[4,1,2,3]);
%linearize A and B to get a better performance
linA=reshape(A,[size(A,1),size(A,2),size(A,3)*size(A,4)*size(A,5)]);
linB=reshape(B,[size(B,1),size(B,2)*size(B,3)*size(B,4)]);
C3=zeros(size(linB));
for a=1:size(linA,3)
C3(:,a)=(linA(:,:,a))\(linB(:,a));
end
%undo linearization
C3=reshape(C3,size(B));
%undo dimension swap
C3=permute(C3,[2,3,4,1]);

How can one use ezplot in MATLAB to effectively draw implicit curves and surfaces?

I need to draw a 2D ellipse using its general form (x-c)'A(x-c)=1
I would like to know how to do this effectively in MATLAB using ezplot.
This answer is applicable to almost any problem which can be formulated as an implicit surface/curve in MATLAB. I am going to demonstrate it on an ellipse.
Short Version:
A = [5 4; 4 5]
c = [1; 2]
elFunc = #(A11,A22,A12,A21,c1,c2,x,y) (c1-x).*(A11*(c1-x)+A21*(c2-y))+(c2-y).*(A12*(c1-x)+A22*(c2-y))-1
ezplot(#(x,y) elFunc(A(1,1),A(2,2),A(1,2),A(2,1),c(1),c(2),x,y), [0 2 0 4])
Long Version:
An ellipse can be written implicitly in its most general form (for any dimension) as
(x-c)'A(x-c) = 1 or (x-c)'A(x-c)-1 = 0
where x,c are in R^n and A is an nxn matrix.
In order to get this into a form that MATLAB can use we can use the symbolic toolbox.
For a 2D ellipse we write:
syms A11 A12 A21 A22 c1 c2 x y real
impl = ([x y]-[c1 c2])*[A11 A12; A21 A22]*([x;y]-[c1;c2])-1
This produces the following output:
(c1 - x)*(A11*(c1 - x) + A21*(c2 - y)) + (c2 - y)*(A12*(c1 - x) + A22*(c2 - y)) - 1
We dont need the symbolic toolbox anymore so we just copy the string, vectorize it by adding the dot operator version and turn it into a function
elFunc = #(A11,A22,A12,A21,c1,c2,x,y) (c1-x).*(A11*(c1-x)+A21*(c2-y))+(c2-y).*(A12*(c1-x)+A22*(c2-y))-1
Now we can use ezplot to draw our curve. ezplot assumes that when you give it a function handle it needs to solve for func = 0 so our curve is already described by elFunc in implicit format.
All that is left for us to do is to define the domain over which we want ezplot to try and draw the curve. The following example demonstrates the result:
A = [5 4; 4 5]
c = [1; 2]
elFunc = #(A11,A22,A12,A21,c1,c2,x,y) (c1-x).*(A11*(c1-x)+A21*(c2-y))+(c2-y).*(A12*(c1-x)+A22*(c2-y))-1
ezplot(#(x,y) elFunc(A(1,1),A(2,2),A(1,2),A(2,1),c(1),c(2),x,y), [0 2 0 4])
This answer is exactly the same as #twerdster's answer, except the notation is a bit more Matlabby:
A = [5 4; 4 5];
c = [1 2];
elFunc = #(x,y) sum(([x(:)-c(1) y(:)-c(2)] * A) .* [x(:)-c(1) y(:)-c(2)], 2) - 1;
ezplot(elFunc, [0 2 0 4])
As a final remark: as both our answers already kind of indicate, ezplot is intended for things that are easy-to-plot. The ellipse is already on the edge of still being 'easy' enough for anonymous functions and ezplot.
In general, I'd suggest you avoid using ezplot for anything harder than ezplot(#(x)sin(x).*cos(2*x)) or so. It is much more fruitful to practice and become fluent in functions and plot(), surf(), and friends.