How do I write an expression in Matlab code involving summation of a variable and then how do I minimize the expression?
ex. I need to minimize the following function
E= \sum_{i,j}[C_{ij}(r_{ij}) + C2_{ij}(r_{ij})^2]
I need to minimize the above expression for any values of r_{ij}s where i and j vary.
I could use the fmincon() in MATLAB but I am unable to write my expression suitably to give it as input to the fmincon().
Thanks.
Try this:
E = sum(sum( C.*r + C2.*r.^2 ));
where C, C2 and r are matrices of the same shape.
fmincon and other optimization functions do not require you to write everything as an expression, they can optimize for functions as well.
function E = criterion(r, C, C2)
e = C.*r + C2.*r.^2;
E = sum(e(:));
I'm not completely sure about the syntax required by fmincon, but I guess it's something like E = f(theta), where theta is a parameter vector you want adjusted such that E is minimal. Since I don't find your problem clearly described, I will assume your parameters are C and C2 (in the case that r are your parameters, the case is similar and simpler).
As fmincon uses a vector to store the coefficients, we need a function that takes such a vector and transforms it into the sizes required by the criterion function above.
function E = criterionRolledC(theta,r)
assert(numel(theta)==2*numel(r), 'The size of theta has to be twice the size of r');
[M N] = size(r);
C = theta(1:M*N);
C2 = theta(M*N+1:end);
C = reshape(C , M, N);
C2 = reshape(C2, M, N);
E = criterion(r,C,C2);
That way, you can make an anonymous function that easily conforms to the interface of the optimizer: #(theta)(criterionRolledC(theta,rValues)) will do when the variable rValues in your current workspace contains your r values.
In case you want the exact opposite, i.e. your parameters are r, it is simpler:
function E = criterionRolledR(theta,C,C2)
assert(numel(theta)==numel(C), 'The size of theta has to be the same size as C');
assert(all(size(C)==size(C2)), 'C and C2 need to have the same size');
[M N] = size(C);
r = reshape(theta, M, N);
E = criterion(r,C,C2);
And you can construct an anonymous function similarly to the other case.
Related
I've noticed some weird facts about integral2. These are probably due to my limitations in understanding how it works. I have some difficulties in integrating out variables when I have particular functions. For instance, look at the following Code:
function Output = prova(p,Y)
x = p(1);
y = p(2);
w = p(3);
z = p(4);
F1 = #(Data,eta_1,eta_2,x,y,w,z) F2(eta_1,eta_2,Data) .* normpdf(eta_1,x,y) .* normpdf(eta_2,w,z);
Output = integral2(#(eta_1,eta_2)F1(Y,eta_1,eta_2,0,1,10,2),-5,5,-5,5);
end
function O = F2(pp1,pp2,D)
O = pp1 + pp2 + sum(D);
end
In this case the are no problems in evaluating the integral. But if I change the code in this way I obtain some errors, although the output of F2 is exactly the same:
function Output = prova(p,Y)
x = p(1);
y = p(2);
w = p(3);
z = p(4);
F1 = #(Data,eta_1,eta_2,x,y,w,z) F2(eta_1,eta_2,Data) .* normpdf(eta_1,x,y) .* normpdf(eta_2,w,z);
Output = integral2(#(eta_1,eta_2)F1(Y,eta_1,eta_2,0,1,10,2),-5,5,-5,5);
end
function O = F2(pp1,pp2,D)
o = sum([pp1 pp2]);
O = o + sum(D);
end
The problems increase if F2 for example have some matrix multiplication in which "eta_1" and "eta_2", which I want to integrate out, are involved. This problems makes practically impossible to solve computations in which, for instance, we have to integrate out a variable X which is inside a Likelihood Function (whose calculation could require some internal Loop, or Sum, or Prod involving our variable X). What is the solution?
I have a dataset with 1125 rows and 64 columns. Where first 554 rows belong to one class and the remaining rows belong to the other class. The objective function
is to be minimized in terms of R_1 and R_2 where both are are row vectors(1 x 64). x_i and x_l are the rows from the data matrix. I am trying to minimize this objective function using the optimization toolbox, but I am struggling to get the objective function in the desired form and running into errors. This is how I have coded so far
data = xlsread('data.xlsx');
dat1 = data(1:554,:);
dat2 = data(555:1125,:);
f1 = #(x) 0;
f2 = #(x) 0;
%% for digits labeled 0
for i = 1:554
f1 = #(x) f1 + (dat1(i,:) - x(1)).^2;
end
%% for digits labeled 1
for j = 1:571
f2 = #(x) f2 + (dat2(j,:) - x(2)).^2;
end
%% final objective function
f = #(x) 1/554*f1 + 1/571*f2;
%%
x = fminunc(f);
Please guide me on how to correctly form this type of objective function in Matlab
None of your code makes sense. A few issues
f1 = #(x) 0; and f2 = #(x) 0 define anonymous functions which always return zero. What is the purpose of this?
Every further definition of f1,f2,f is attempting to do arithmetic operations on an anonymous function. It's not clear what you expect this to accomplish.
x = fminunc(f); is missing an argument, it needs an initial guess as well. This isn't just to initialize the algorithm but also so that fminunc knows the dimensions that the input to f should have.
For your case f should be defined so half the values passed to it refer to R1 and the other half refer to R2. For example define
l2_sq = #(x) sum(x.^2,2); % return norm(x,2)^2 for each row of x
f1 = #(R1) sum(l2_sq(bsxfun(#minus, dat1, R1)));
f2 = #(R2) sum(l2_sq(bsxfun(#minus, dat2, R2)));
f3 = #(R1,R2) -10 * norm(R1-R2,1);
f = #(R) f1(R(1:64)) + f2(R(65:128)) + f3(R(1:64), R(65:128));
Since the combined R vector has 128 elements, we need to generate an initial guess that contains 128 elements. In this case we could just use random Gaussian noise
R0 = randn(1,128);
Finally, call fminunc as
Rhat = fminunc(f, R0);
R1 = Rhat(1:64);
R2 = Rhat(65:128);
where R1 and R2 are the optimal values.
Note In MATLAB 2016b and newer, implicit expansion allows you to replace bsxfun(#minus, dat1, R1) with the more efficient dat1 - R1. Similarly for bsxfun(#minus, dat2, R2).
I have an integral expression which I defined on Matlab using
x = 0:1/1000:1;
g = #(x) (exp(-1./x.^2).*heaviside(x)).*(exp(-1./(1-x).^2).*heaviside(1-x));
t = 0:1/1000:1;
f = zeros(size(t));
for i = 1:length(t)
f(i) = integral(g,0,t(i));
end
I can plot it, for example, using plot(t,f), but for other purposes I would like to attach a function handle to f, i.e. something like f = #(t) zeros(size(t)). I have not been able to figure it out thus far. f = #(t) integral(#(x)g(x),0,t) is also not sufficient.
Sorry, I can't comment yet. But does this work?
funcHand= #(t) integral(g,0,t);
You don't have to define x in your code above, since the input to integral is a function handle.
Then to check it's the same:
f2 = zeros(size(t));
for i = 1:length(t)
f2(i) = funcHand(t(i));
end
Whoops, the other answer said all the above (just replaced the for loop with arrayfun. I didn't see it while writing the answer.
Edit
If you want to build-in the for loop, try:
funcHand= #(t) arrayfun(#(u) integral(g, 0, u),t);
And test:
plot(funcHand(t))
Try
f = #(u) integral(g, 0, u)
The additional level of indirection in g seems superfluous. Note that I have called the input u. Keep in mind that f will not accept vectors as its inputs. So doing something like f(t) in your current workspace will not create the same array as your for loop is doing. You will have to iterate through the array. The convenience function arrayfun will do this for you:
o = arrayfun(f, t)
It is roughly equivalent to the loop you have now:
o = zeros(size(t));
for i = 1:length(o)
o(i) = f(t(i));
end
arrayfun can actually be incorporated into your function handle to allow it to process vector arguments:
h = #(t) arrayfun(f, t)
To avoid the proliferation of unnecessary function handles, you can do
f = #(t) arrayfun(#(u) integral(g, 0, u), t)
I'd like to create an anonymous function that does something like this:
n = 5;
x = linspace(-4,4,1000);
f = #(x,a,b,n) a(1)*exp(b(1)^2*x.^2) + a(2)*exp(b(2)^2*x.^2) + ... a(n)*exp(b(n)^2*x.^2);
I can do this as such, without passing explicit parameter n:
f1 = #(x,a,b) a(1)*exp(-b(1)^2*x.^2);
for j = 2:n
f1 = #(x,a,b) f1(x,a,b) + a(j)*exp(b(j)^2*x.^2);
end
but it seems, well, kind of hacky. Does someone have a better solution for this? I'd like to know how someone else would treat this.
Your hacky solution is definitely not the best, as recursive function calls in MATLAB are not very efficient, and you can quickly run into the maximum recursion depth (500 by default).
You can introduce a new dimension along which you can sum up your arrays a and b. Assuming that x, a and b are row vectors:
f = #(x,a,b,n) a(1:n)*exp((b(1:n).^2).'*x.^2)
This will use the first dimension as summing dimension: (b(1:n).^2).' is a column vector, which produces a matrix when multiplied by x (this is a dyadic product, to be precise). The resulting n * length(x) matrix can be multiplied by a(1:n), since the latter is a matrix of size [1,n]. This vector-matrix product will also perform the summation for us.
Mini-proof:
n = 5;
x = linspace(-4,4,1000);
a = rand(1,10);
b = rand(1,10);
y = 0;
for k=1:n
y = y + a(k)*exp(b(k)^2*x.^2);
end
y2 = a(1:n)*exp((b(1:n).^2).'*x.^2); %'
all(abs(y-y2))<1e-10
The last command returns 1, so the two are essentially identical.
This is a part of my code.
clear all;
clc;
p = 50;
t = [-6 : 0.01 : 6];
f = inline('(t+2).*sin(t)', 't')
v = inline('3*f(p*t+2)','t','f','p')
plot(t,f(t));
v(t,f,p);
figure;
plot(t,v(t,f,p));
Here I have two questions.
Why I have to pass p into the function v even though p is a constant which has already declared ?
How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form ?
Update
This is an update for the second question
Let
f(x) = 1 + x - x^2
g(x) = sin(x)
If I give f(g(x)), I wanna get the output in words, like this
f(g(x)) = (cos(X))^2 + sin(x)
not in numerical value. Is there any function capable to do that?
1) Why do I have to pass p to v even though p is a constant which has already been declared?
Well, a MATLAB's inline function object has an eval wrapper, so the only variables in its scope are those which were automatically captured from the expression or explicitly specified.
In other words, if you want v to recognize p, you have no other option but declaring it when creating the inline object and passing it to v explicitly. The same goes for f as well!
2) How I can get an expression for v completely in terms of t as 3*[(50*t+2)*sin(50*t+2)] or in its simplified form?
Use anonymous functions, like Shai suggested. They are more powerful, more elegant and much faster. For instance:
v = #(t)(3*(50*t+2)*sin(50*t+2))
Note that if you use a name, which is already in use by a variable, as an argument, the anonymous function will treat it as an argument first. It does see other variables in the scope, so doing something like g = #(x)(x + p) is also possible.
EDIT #1:
Here's another example, this time a function of a function:
x = 1:5;
f = #(x)(x .^ 3); %// Here x is a local variable, not as defined above
g = #(x)(x + 2); %// Here x is also a local variable
result = f(g(x));
or alternatively define yet another function that implements that:
h = #(x)f(g(x)); %// Same result as h = #(x)((x + 2) .^ 3)
result = h(x);
The output should be the same.
EDIT #2:
If you want to make an anonymous function out of the expression string, concatenate the '#(x)' (or the correct anonymous header, as you see fit) to the beginning and apply eval, for example:
expr = '(x + 2) .^ 3';
f = eval(['#(x)', expr]) %// Same result as f = #(x)((x + 2) .^ 3)
Note that you can also do char(f) to convert it back into a string, but you'll have to manually get rid of the '#(...)' part.
EDIT #3:
If you're looking for a different solution, you can explore the Symbolic Toolbox. For example, try:
syms x
f(x) = x + 2
g(x) = x ^ 3
or can also use sym, like so:
f(x) = sym('x + 2');
g(x) = sym('x ^ 3');
Use subs to substitute values and evaluate the symbolic expression.
How about using anonymous functions:
p = 50;
t = -6:0.01:6;
f = #(x) (x+2).*sin(x);
v = #(x) 3*f(p*x+2);
figure;
subplot(1,2,1); plot( t, f(t) ); title('f(t)');
subplot(1,2,2); plot( t, v(t) ); title('v(t)');
Is this what you wanted?
Adding a constant into an inline can be done during its definition.
Instead of
p = 50;
v = inline('3*f(p*t+2)','t','f','p')
You can write
p = 50;
v = inline( sprintf('3*f(%f*t+2)', p), 't','f')