calling arrayfun; parameter estimation; - function

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

Related

Input vector to a symbolic system of functions

Suppose that I have written a function containing 3 separable functions(a system of equations).
I want to calculate the value of this function for 3 different values of my variables but I do not want to use "subs" function. What I want to do is enter a vector containing the desired values of my variables and calculate the main function which is a vector. How could I do that?. Notice that I do not want to call the function by each variable. Here is my code:
syms x y z
f1 = symfun(x.^2+3.*x.*y,[x,y,z]);
f2 = symfun(z.^3+y-x.^3-12,[x,y,z]);
f3 = symfun(2*z+x.*y+z.*x+1,[x,y,z]);
f = [f1;f2;f3];
What I mean is to calculate the f function by for example: f([12 4 6]) not byf(12 4 5)
Not the most elegant, but the best I could think of at the moment is to put it in a function wrapper. This might be one way to pass inputs as an array. This will bridge the gap between indexing the array input to be passed into the symfcn (symbolic functions).
f([12 4 6])
function [Results] = f(Inputs)
syms x y z
f1(x,y,z) = x.^2+3.*x.*y;
f2(x,y,z) = z.^3+y-x.^3-12;
f3(x,y,z) = 2*z+x.*y+z.*x+1;
Sym_Functions = [f1;f2;f3];
Results = Sym_Functions(Inputs(1),Inputs(2),Inputs(3));
end

Octave: defining a function to interpolate data points

Write an octave function to implement f(x) = sin(3x)/(0.4+(x-2)^2).
Write an octave script to interpolate between the values of f(x) = sin(3x)/(0.4+(x-2)^2) sampled uniformly at up to 9 points in the interval x = [0,4].
I'm confused as to what this question is asking. I interpreted the 1st part as defining a function fx that can be called from anywhere to return the values of f(x) for a given x, but I'm not sure if the x's have to be inputs.
For the 2nd part, am I correct in using the interpl function?
My attempt:
Function file fx.m
function fx
x=(0:0.25:4);
y = sin(3*x)/(0.4+(x-2))^2
endfunction
But this only returns 1 value for y. I need to return 9 uniformly spaced samples. I feel as though I need to use a for loop somehow...
Script intpl.m
1;
yi=interpl(x,y,0.4:0.4:3.6)
I think your teacher wants something like:
function y = f(x)
y = ....x..... (fill your formula here but use elementwise operations [1])
endfunction
and then use this function for the given range:
x = linspace (0, 4, 9);
y = f(x)
if you want to have this in one file foo.m be sure to not start the file with the function definition. I normally use "1;" so your script foo.m becomes:
1;
function y = f(x)
x = ....;
endfunction
x = linspace (...);
y = f(x)
plot (x, y) # if you want to plot it
[1] https://www.gnu.org/software/octave/doc/interpreter/Arithmetic-Ops.html

Passing additional arguments through function handle in Matlab

I have a function to optimize, say Function, in Matlab. This function depends on variables (say x) over which I want to optimize and one parameter (say, Q) which does not need to be optimized.Hence, the function Function(x,Q). In other words, I have an array of values for Q and want to find optimal x values for each Q. However, I cannot find a way how to pass those Q values when using function handle #Function in optimization function.
So, my question is how to pass those Q values when using function handle in optimization functions, for example fmincon(#Function,x0,A,b)?
Try using anonymous function:
x = cell( 1, numel(Q) );
for qi = 1:numel( Q )
x{qi} = fmincon( #(x) Function(x, Q(qi)), A, b );
end
As described in MATLAB documentation, there are actually 3 solutions for this problem:
Anonymous Functions
which is described in the Shai's answer of this post.
Nested Functions:
in this approach the outer function accepts all arguments, and the inner function only accepts parameters that optimization takes place on them.
this is an example taken from MATLAB documentation:
function [x,fval] = runnested(a,b,c,x0)
[x,fval] = fminunc(#nestedfun,x0);
% Nested function that computes the objective function
function y = nestedfun(x)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)x(2) +...
(-c + cx(2)^2)*x(2)^2;
end
end
Global Variables
in this approach you should define the parameters that are needed in objective function as global in workspace, and use them in objective function with declaring them as global.
here is an example again from MATLAB documentation:
Defining objective function:
function y = globalfun(x)
global a b c
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)x(2) + ...
(-c + cx(2)^2)*x(2)^2;
end
Optimization:
global a b c;
a = 4; b = 2.1; c = 4; % Assign parameter values
x0 = [0.5,0.5];
[x,fval] = fminunc(#globalfun,x0)
You may be able to do the following:
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options,Q)
which will pass Q along to fun(x,Q)!

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

summing functions handles in matlab

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.