Shortening long expressions - matlab

I want to create a function handle to the function:
f = #(x) (x-1)*(x-2)*...*(x-50);
How can I do this in MATLAB without typing all 50 terms?

Here is a vectorized solution:
y = prod((x-[1:50]))
Or if you want an anonymous function:
f = #(x) ( prod((x-[1:50])) )
By the way, it might not be faster than #Chris solution (which is good, and I upvoted it), because of Matlab JIT-Accelerator.

You could wrap it in a function. For example,
function y = myfunc(x, n)
y = 1.;
for i = 1:n
y = y*(x-i);
end
end
The function you defined is basically the product of a sequence, which are trivially written as for loops.
In your case you want to compute this result for 50 terms, so you could just use y = myfunc(x, 50) or, if you want this to be a function handle, you could define
f = #(x) myfunc(x, 50);

Related

calling pattern search in vectorized function

I have a vectorized function which is an objective function for an optimizer (genetic algorithm).
Inside this function, there is a fast optimization which is part of the computation of this function as follow:
function error = ObjectiveFunction(a, b, c)
x = a.*b;
y = c.*b;
z = patternsearch(#fun, [x, y]);
error = x+y.*z;
end
solution = ga(#ObjectiveFunction, 'vectorized', true);
ObjectiveFunction accepts vector of solution. This makes ga works faster. However, since inside ObjectiveFunction there is patternsearch process, this vectorization will be useless because patternsearch (as an optimizer) does not work in vectorized manner.
So I had to edit my function to:
function error = ObjectiveFunction(a, b, c)
x = a.*b;
y = c.*b;
for i = 1:size(x,1)
z(i) = patternsearch(#fun, [x(i), y(i)]);
end
error = x+y.*z;
end
Is there anyway to replace the loop with a vectorized call to patternsearch?
Please consider using arrayfun as follow
function error = ObjectiveFunction(a, b, c)
x = a.*b;
y = c.*b;
z = arrayfun(#(x1,y1) patternsearch(#fun, [x1, y1]),x,y);
error = x+y.*z;
end
I hope this may help

I want to feed in a function handle into a matlab function I made

I am trying to feed a function handle into the function I created below. I'm not exactly sure how to do this.
For example, how do I get:
conjugate_gradient(#(y) ABC(y), column_vector, initial_guess)
to not error?
If I use matlab's pcg function in the same way it will work:
pcg(#(y) ABC(y),b,tol).
I tried reading the pcg function, and they do take about this in the function description, however I'm still super inexperienced with MATLAB and had shall we say some difficulty understanding what they did.Thank You!
function [x] = conjugate_gradient(matrix, column_vector, initial_guess)
y = [];
col_size = length(column_vector);
temp = size(matrix);
mat_row_len = temp(2);
% algorithm:
r_cur = column_vector - matrix * initial_guess;
p = r_cur;
k = 0;
x_approx = initial_guess;
for i=1:mat_row_len
alpha = ( r_cur.' * r_cur ) / (p.' *(matrix* p));
x_approx = x_approx + alpha * p;
r_next = r_cur - alpha*(matrix * p);
fprintf(num2str(r_next'*r_next), num2str(i))
y = [y; i, r_next'*r_next];
%exit condition
if sqrt(r_next'*r_next) < 1e-2
y
break;
end
beta = (r_next.'* r_next )/(r_cur.' * (r_cur) );
p = r_next + beta * p;
k = k+1;
r_cur = r_next;
end
y
[x] = x_approx;
end
When you do
f = #(y) ABC(y)
You create a function handle. (Note that in this case it's the same as f=#ABC). This handle is a variable, and this can be passed to a function, but is otherwise the same as the function. Thus:
f(1)
is the same as calling
ABC(1)
You pass this handle to a function as the first argument, which you have called matrix. This seems misleading, as the variable matrix will now be a function handle, not a matrix. Inside your function you can do matrix(y) and evaluate the function for y.
However, reading your function, it seems that you treat the matrix input as an actual matrix. This is why you get errors. You cannot multiply it by a vector and expect a result!

Problems attaching a function handle on Matlab to integral expression

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)

Create a variable number of terms in an anonymous function that outputs a vector

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.

Using inline function with constant arguments in MATLAB

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')