summing functions handles in matlab - function

Hi
I am trying to sum two function handles, but it doesn't work.
for example:
y1=#(x)(x*x);
y2=#(x)(x*x+3*x);
y3=y1+y2
The error I receive is "??? Undefined function or method 'plus' for input arguments of type 'function_handle'."
This is just a small example, in reality I actually need to iteratively sum about 500 functions that are dependent on each other.
EDIT
The solution by Clement J. indeed works but I couldn't manage to generalize this into a loop and ran into a problem. I have the function s=#(x,y,z)((1-exp(-x*y)-z)*exp(-x*y)); And I have a vector v that contains 536 data points and another vector w that also contains 536 data points. My goal is to sum up s(v(i),y,w(i)) for i=1...536 Thus getting one function in the variable y which is the sum of 536 functions. The syntax I tried in order to do this is:
sum=#(y)(s(v(1),y,z2(1)));
for i=2:536
sum=#(y)(sum+s(v(i),y,z2(i)))
end

The solution proposed by Fyodor Soikin works.
>> y3=#(x)(y1(x) + y2(x))
y3 =
#(x) (y1 (x) + y2 (x))
If you want to do it on multiple functions you can use intermediate variables :
>> f1 = y1;
>> f2 = y2;
>> y3=#(x)(f1(x) + f2(x))
EDIT after the comment:
I'm not sure to understand the problem. Can you define your vectors v and w like that outside the function :
v = [5 4]; % your 536 data
w = [4 5];
y = 8;
s=#(y)((1-exp(-v*y)-w).*exp(-v*y))
s_sum = sum(s(y))
Note the dot in the multiplication to do it element-wise.

I think the most succinct solution is given in the comment by Mikhail. I'll flesh it out in more detail...
First, you will want to modify your anonymous function s so that it can operate on vector inputs of the same size as well as scalar inputs (as suggested by Clement J.) by using element-wise arithmetic operators as follows:
s = #(x,y,z) (1-exp(-x.*y)-z).*exp(-x.*y); %# Note the periods
Then, assuming that you have vectors v and w defined in the given workspace, you can create a new function sy that, for a given scalar value of y, will sum across s evaluated at each set of values in v and w:
sy = #(y) sum(s(v,y,w));
If you want to evaluate this function using an array of values for y, you can add a call to the function ARRAYFUN like so:
sy = #(y) arrayfun(#(yi) sum(s(v,yi,w)),y);
Note that the values for v and w that will be used in the function sy will be fixed to what they were when the function was created. In other words, changing v and w in the workspace will not change the values used by sy. Note also that I didn't name the new anonymous function sum, since there is already a built-in function with that name.

Related

Function and surface plot Julia

I want to plot a function using surface in Julia. I manage to plot te desired function:
x = 0:0.1:4
y = 0:0.1:4
f(x,y) = x^0.2 * y^0.8
surface(x, y, f, camera=(10,30),linealpha=0.3, fc=:heat)
However, I would f(*) to be a proper function over which I could also optimize (e.g. utility maximisation in economics). This is my attempt:
function Utility(x1, x2)
u= x.^0.2 .* y.^0.8
return u
end
But it unfortunately does not work. Can anybody help me?
Best
Daniel
I think Benoit's comment really should be the answer, but let me expand a little bit.
First of all, an inline function definition is not any different from a multi-line function definiton (see the first two examples in the docs here). Therefore, doing
utility(x, y) = x^0.2 * y^0.8
will give you a function that works exactly like
function utility(x, y)
x^0.2 * y^0.8
end
However, your Utility function is actually different from your f function - you are defining it with the arguments x1 and x2, but in the function body you are using y rather than x2.
This would ordinarily raise an undefined variable error, except that in the code snippet you posted, y is already defined in global scope as the range 0:0.1:4, so the function will use this:
julia> y = 0:0.1:4
0.0:0.1:4.0
julia> u(x1, x2) = x1 .^ 0.2 * y .^ 0.8
u (generic function with 1 method)
julia> u(2.0, 0.0)
41-element Array{Float64,1}:
0.0
0.18205642030260805
0.3169786384922227
...
this is also where your introduction of broadcasting in the Utility function (the second difference between your two examples as Benoit pointed out) comes back to haunt you: calling the function while relying on it to use the global variable y would error immediately without broadcasting (as you can't exponentiate a range):
julia> u2(x1, x2) = x1^0.2 * y^0.8
u2 (generic function with 1 method)
julia> u2(2.0, 0.0)
ERROR: MethodError: no method matching ^(::StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}, ::Float64)
with broadcasting, however, this exponentiation works and returns the full range, with every element of the range exponentiated. Thus, your function returns an array rather than a single number (as you can see above from my call to u(2.0, 0.0). This is what Plots complains about - it doesn't know how to plot an array, when it expects to just be plotting a single data point.

Defining a Differential Equation in Octave

I am attempting to use Octave to solve for a differential equation using Euler's method.
The Euler method was given to me (and is correct), which works for the given Initial Value Problem,
y*y'' + (y')^2 + 1 = 0; y(1) = 1;
That initial value problem is defined in the following Octave function:
function [YDOT] = f(t, Y)
YDOT(1) = Y(2);
YDOT(2) = -(1 + Y(2)^2)/Y(1);
The question I have is about this function definition. Why is YDOT(1) != 1? What is Y(2)?
I have not found any documentation on the definition of a function using function [YDOT] instead of simply function YDOT, and I would appreciate any clarification on what the Octave code is doing.
First things first: You have a (non linear) differential equation of order two which will require you to have two initial conditions. Thus the given information from above is not enough.
The following is defined for further explanations: A==B means A is identical to B; A=>B means B follows from A.
It seems you are mixing a few things. The guy who gave you the files rewrote the equation in the following way:
y*y'' + (y')^2 + 1 = 0; y(1) = 1; | (I) y := y1 & (II) y' := y2
(I) & (II)=>(III): y' = y2 = y1' | y2==Y(2) & y1'==YDOT(1)
Ocatve is "matrix/vector oriented" so we are writing everything in vectors or matrices. Rather writing y1=alpha and y2=beta we are writing y=[alpha; beta] where y(1)==y1=alpha and y(2)==y2=beta. You will soon realize the tremendous advantage of using especially this mathematical formalization for ALL of your problems.
(III) & f(t,Y)=>(IV): y2' == YDOT(2) = y'' = (-1 -(y')^2) / y
Now recall what is y' and y from the definitions in (I) and (II)!
y' = y2 == Y(2) & y = y1 == Y(1)
So we can rewrite equation (IV)
(IV): y2' == YDOT(2) = (-1 -(y')^2) / y == -(1 + Y(2)^2)/Y(1)
So from equation (III) and (IV) we can derive what you already know:
YDOT(1) = Y(2)
YDOT(2) = -(1 + Y(2)^2)/Y(1)
These equations are passed to the solver. Differential equations of all types are solved numerically by retrieving the "next" value in a near neighborhood to some "previously known" value. (The step size inside this neighborhood is one of the key questions when writing solvers!) So your solver uses your initial condition Y(1)==y(1)=1 to make the next step and calculate the "next" value. So right at the start YDOT(1)=Y(2)==y(2) but you didn't tell us this value! But from then on YDOT(1) is varied by the solver in dependency to the function shape to solve your problem and give you ONE unique y(t) solution.
It seems you are using Octave for the first time so let's make a last comment on function [YDOT] = f(t, Y). In general a function is defined in this way:
function[retVal1, retVal2, ...] = myArbitraryName(arg1, arg2, ...)
Where retVal is the return value or output and arg is the argument or input.

Creating a function from a 2D array in MATLAB (For use in ode45)

I am a first time MATLAB user. I have a 2d array of t vs f in MATLAB. This 2d array correponds to a function, say f(t). I am using ode45 to solve a set of differential equations and f(t) is one of the coefficients i.e. I have a set of equations of the form x'(t)=f(t)x(t) or variations thereof. How do I proceed?
I need a way to convert my array of t vs f into a function that can be used in the ode45 method. Presumably, the conversion will do some linear interpolation and give me the equation of the best fit curve.
Or if there is another approach, I'm all ears!
Thank you!
This is a simple example with passing function as a parameter to right hand side of the ODE. Create files in the same directory and run main
main.m
t = 0:0.2:10; f = sin(t);
fun = #(xc) interp1(t, f, xc);
x0=0.5
% solve diff(x, t)=sin(t)
% pass function as parameter
[tsol, xsol] = ode45(#(t, x) diff_rhs(t, x, fun),[0.0 8.0], 0.5);
% we solve equation dx/dt = sin(x), x(0)=x0
% exact solution is x(t) = - cos(t) + x(0) + 1
plot(tsol, xsol, 'x');
hold on
plot(tsol, -cos(tsol) + x0 + 1, '-');
legend('numerical', 'exact');
diff_rhs.m
function dx = diff_rhs(t, x, fun)
dx = fun(t);
end
References in the documentation: interp1 and anonymous Functions.

Error plotting a function of 2 variables

I am trying to plot the function
f(x, y) = (x – 3).^2 – (y – 2).^2.
x is a vector from 2 to 4, and y is a vector from 1 to 3, both with increments of 0.2. However, I am getting the error:
"Subscript indices must either be real positive integers or logicals".
What do I do to fix this error?
I (think) I see what you are trying to achieve. You are writing your syntax like a mathematical function definition. Matlab is interpreting f as a 2-dimensional data type and trying to assign the value of the expression to data indexed at x,y. The values of x and y are not integers, so Matlab complains.
If you want to plot the output of the function (we'll call it z) as a function of x and y, you need to define the function quite differently . . .
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
z = f( repmat(x(:)',numel(y),1) , repmat(y(:),1,numel(x) ) );
surf(x,y,z);
xlabel('X'); ylabel('Y'); zlabel('Z');
This will give you an output like this . . .
The f = #(x,y) part of the first line states you want to define a function called f taking variables x and y. The rest of the line is the definition of that function.
If you want to plot z as a function of both x and y, then you need to supply all possible combinations in your range. This is what the line containing the repmat commands is for.
EDIT
There is a neat Matlab function meshgrid that can replace the repmat version of the script as suggested by #bas (welcome bas, please scroll to bas' answer and +1 it!) ...
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
[X,Y] = meshgrid(x,y);
surf(x,y,f(X,Y));
xlabel('x'); ylabel('y'); zlabel('z');
I typically use the MESHGRID function. Like so:
x = 2:0.2:4;
y = 1:0.2:3;
[X,Y] = meshgrid(x,y);
F = (X-3).^2-(Y-2).^2;
surf(x,y,F);
xlabel('x');ylabel('y');zlabel('f')
This is identical to the answer by #learnvst. it just does the repmat-ing for you.
Your problem is that the function you are using uses integers, and you are trying to assign a double to it. Integers cannot have decimal places. To fix this, you can make it to where it increases in increments of 1, instead of 0.2

calling arrayfun; parameter estimation;

I have a problem with estimation.
I have a function, which is dependent on the values of an unknown vector V = [v1, …, v4].
I also have a vector of reference data YREF = [yref1, …, yrefn].
I would like to write a function, which returns the vector Y (in order to compare it later, say using lsqnonlin). I am aware of the “arrayfun”, but it seems not to work.
I have a subfunction, which returns a concrete value from the range [-100, 100],
%--------------------------------------------------------------------------
function y = SubFunction(Y, V)
y = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y, [-100 100]);
end
%--------------------------------------------------------------------------
then I make some operations on the results:
%--------------------------------------------------------------------------
function y = SomeFunction(Y,V)
temp = SubFunction (Y,V);
y = temp + v(4).*Y;
end
%--------------------------------------------------------------------------
These functions work well for a single value of Y, but not for the whole vector. How to store the results into a matrix for future comparison?
Thanks in advance
Chris
If Y is a vector, then the anonymous function defined as an argument to fzero returns a vector, not a scalar.
You can solve it by using a loop (notice the Y(k) inside the anonymous function definition):
function y = SubFunction(Y, v)
y = zeros (size(Y));
for k = 1 : length (Y)
y(k) = fzero(#(x) v(1).*sinh(x./v(2)) + v(3).*x - Y(k), [-100 100]);
end
end