Trouble with anonymous functions in matlab - matlab

I am having trouble with printing out h_a_b. I am able to get functions f and g but not this one. I need to use h_a_b function so i can do h(f(x),g(x)) and calculate the sqrt of h(a,b). see equations
I am always getting this error
Undefined function 'h_a_b' for input arguments of type 'function_handle'.
I am suppose to write a program that create 3 anonymous functions representing the function
Equations needed
f(x) = 10*cos x ,
g(x) = 5*sin * x, and
h(a,b) = \sqrt(a^2 + b^2).
Here is my code
f = # (x) 5*sin(x);
g = # (x) 10*cos(x);
h_a_b = # (a,b) sqrt(a.^2 + b.^2);
then I plot it with this function that was given to me.
function plotfunc(fun,points)
%PLOTFUNC Plots a function between the specified points.
% Function PLOTFUNC accepts a function handle, and
% plots the function at the points specified.
% Define variables:
% fun -- Function handle
% msg -- Error message
%
msg = nargchk(2,2,nargin);
error(msg);
% Get function name
fname = func2str(fun);
% Plot the data and label the plot
plot(points,fun(points));
title(['\bfPlot of ' fname '(x) vs x']);
xlabel('\bfx');
ylabel(['\bf' fname '(x)']);
grid on;
end

Because your function (h_a_b) takes a vector as input and gives scalar as output it represents a surface, thus plot cannot be used to visualize it (that is only for 2D, scalar-scalar plots).
Are you looking for something like this?:
f = # (x) 5*sin(x);
g = # (x) 10*cos(x);
h_a_b = # (a,b) sqrt(a.^2 + b.^2);
z = #(a,b) sqrt(h_a_b(f(a),g(b)));
[A, B] = meshgrid(0:0.1:8, 0:0.1:9);
Z = z(A,B);
surfc(A,B,Z)
xlabel('a')
ylabel('b')
figure
contourf(A,B,Z)
xlabel('a')
ylabel('b')
Second option, considering z as scalar-scalar function and using your plotfunc function:
f = # (x) 5*sin(x);
g = # (x) 10*cos(x);
h_a_b = # (a,b) sqrt(a.^2 + b.^2);
z = #(x) sqrt(h_a_b(f(x),g(x)));
points = 0:0.1:8;
plotfunc(z,points)
Which is one slice of the above surface.

Related

Adding function handlers in cell array in MATLAB

I have a bunch of anonymous functions stored in a cell array as follows:
F = {#(x) x + 1, #(x) x * x}
I want to create a new anonymous function to add them all up and average the result given an input x. F can have arbitrary number of function handles and is generated at run time. If F is known, then it is simply f = #(x) (F{1}(x) + F{2}(x)) / length(F). But I don't know how to append all elements of F onto this new anonymous function (presumably in a loop?) How would I do this?
Use cellfun to define a function that evaluates each function f in F using just one line. An anonymous function handle for arbitrary F and x is as follows:
F = {#(x) x + 1, #(x) x * x};
%// Build anonymous function that evaluates each function, sums,
%// divides by length of F
new_F = #(x,F)sum(cellfun(#(f)f(x), F)) / length(F);
Then, to evaluate, simply call:
x = 2; %// data to apply fcns on
result = new_F(x, F)

How to use output variables of a function as input for another function

I would like to use the output of a function as input for a function that builds a polynom:
here is my code:
function c = interpolation(x, y)
n = length(x);
V = ones(n);
for j = 2:n
V(:,j) = x.*V(:,j-1);
end
c = V \ y;
disp(V)
for i = 0:n-1
fprintf('c%d= %.3f\n', i, c(i+1));
end
polynome(c);
function p = polynome(x)
n = length(x);
for l= 0:n-1
polynome = polynome * x^l;
end
end
The first function alone, works. That means my code works if I comment starting from line 13 to end, and I get the c values, whose number depends from the length of the entered x vector in the beginning.
I want to use that c values, to build a polynom of this form: p(x) = c0 + c^1*x1 + c2^x2 + .... + c(n-1)^x(n-1) and plot that polynom, with the points aswell xi,yi given at the beginning through the 2 vectors as input of the function interpolation.
Can someone help me here?
make a separate function polynome e.g.
function y=polynome(x,c)
y=sum(c.*x.^(0:length(c)-1));
or just use
y=sum(c.*x.^(0:length(c)-1));
to compute the polynome for your coefficients c.
If you have multiple values of x, e.g.
x=[0:.1:3]';
y=repmat(x,1,numel(c)).^repmat((0:numel(c)-1),numel(x),1)*c';
should give you the values of the polynome

Numerical Integral in MatLab using integral command

I am trying to compute the value of this integral using Matlab
Here the other parameters have been defined or computed in the earlier part of the program as follows
N = 2;
sigma = [0.01 0.1];
l = [15];
meu = 4*pi*10^(-7);
f = logspace ( 1, 6, 500);
w=2*pi.*f;
for j = 1 : length(f)
q2(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(2));
q1(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(1));
C2(j)= 1/(q2(j));
C1(j)= (q1(j)*C2(j) + tanh(q1(j)*l))/(q1(j)*(1+q1(j)*C2(j)*tanh(q1(j)*l)));
Z(j) = sqrt(-1)*2*pi*f(j)*C1(j);
Apprho(j) = meu*(1/(2*pi*f(j))*(abs(Z(j))^2));
Phi(j) = atan(imag(Z(j))/real(Z(j)));
end
%integration part
c1=w./(2*pi);
rho0=1;
fun = #(x) log(Apprho(x)/rho0)/(x.^2-w^2);
c2= integral(fun,0,Inf);
phin=pi/4-c1.*c2;
I am getting an error like this
could anyone help and tell me where i am going wrong.thanks in advance
Define Apprho in a separate *.m function file, instead of storing it in an array:
function [ result ] = Apprho(x)
%
% Calculate f and Z based on input argument x
%
% ...
%
meu = 4*pi*10^(-7);
result = meu*(1/(2*pi*f)*(abs(Z)^2));
end
How you calculate f and Z is up to you.
MATLAB's integral works by calling the function (in this case, Apprho) repeatedly at many different x values. The x values called by integral don't necessarily correspond to the 1: length(f) values used in your original code, which is why you received errors.

Matlab function for lorentzian fit with global variables

I want to fit a Lorentzian to my data, so first I want to test my fitting procedure to simulated data:
X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));
starting parameters
a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];
find minimum for fit
afinal = fminsearch(#devsum,a0);
afinal is vector with parameters for my fit. If I test my function as follows
d= devsum(a0)
then d= 0, but if I do exactly what's in my function
a=a0;
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2)
then d is not equal to zero. How is this possible? My function is super simple so I don't know what's going wrong.
my function:
%devsum.m
function d = devsum(a)
global X Y
d = sum((Y - a(1)./((X-a(2)).^2+a(3))).^2);
end
Basically I'm just implementing stuff I found here
http://www.home.uni-osnabrueck.de/kbetzler/notes/fitp.pdf
page 7
It is usually better to avoid using global variables. The way I usually solve these problems is to first define a function which evaluates the curve you want to fit as a function of x and the parameters:
% lorentz.m
function y = lorentz(param, x)
y = param(1) ./ ((x-param(2)).^2 + param(3))
In this way, you can reuse the function later for plotting the result of the fit.
Then, you define a small anonymous function with the property you want to minimize, with only a single parameter as input, since that is the format that fminsearch needs. Instead of using global variables, the measured X and Y are 'captured' (technical term is doing a closure over these variables) in the definition of the anonymous function:
fit_error = #(param) sum((y_meas - lorentz(param, x_meas)).^2)
And finally you fit your parameters by minimizing the error with fminsearch:
fitted_param = fminsearch(fit_error, starting_param);
Quick demonstration:
% simulate some data
X = linspace(0,100,200);
Y = 20./((X-30).^2+20)+0.08*randn(size(X));
% rough guess of initial parameters
a3 = ((max(X)-min(X))/10)^2;
a2 = (max(X)+min(X))/2;
a1 = max(Y)*a3;
a0 = [a1,a2,a3];
% define lorentz inline, instead of in a separate file
lorentz = #(param, x) param(1) ./ ((x-param(2)).^2 + param(3));
% define objective function, this captures X and Y
fit_error = #(param) sum((Y - lorentz(param, X)).^2);
% do the fit
a_fit = fminsearch(fit_error, a0);
% quick plot
x_grid = linspace(min(X), max(X), 1000); % fine grid for interpolation
plot(X, Y, '.', x_grid, lorentz(a_fit, x_grid), 'r')
legend('Measurement', 'Fit')
title(sprintf('a1_fit = %g, a2_fit = %g, a3_fit = %g', ...
a_fit(1), a_fit(2), a_fit(3)), 'interpreter', 'none')
Result:

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