How to define a function with a parameter in it in Octave? - function

I am trying to define a function with a predefined variable, and Octave says that the variable was not defined. I am trying to run the following code in Octave,
q = 5;
function w = tointegrate(x)
w = 2 * q * sin(x);
endfunction
[ans, ier, nfun, err] = quad("tointegrate", -10*q, 10*q);
ans
Octave gives the error
error: 'q' undefined near line 3 column 10
error: quad: evaluation of user-supplied function failed
How to fix this error?

You are expecting 'commandline functions' in octave to have lexical scope, but this is simply not the case.
If all of this was inside a function, and you defined a nested function, it would work as you expect. But 'commandline functions' like this are treated as if they are in their own file, and have no knowledge of the workspace in which they've been defined.
In this particular case, since your function is effectively a one-liner, you can get the effect you want by making it a function handle instead, which 'does' capture the local workspace. I.e. this will work
q = 5;
tointegrate = #(x) 2 * q * sin(x);
[ans, ier, nfun, err] = quad("tointegrate",-10 *q ,10*q);
Note, however, that 'q' will have the value it had at the time it was captured. I.e. if you update q dynamically, its value will not be updated in the function handle.
Otherwise, for more complex functions, the solution is really to pass it as a parameter (or to access it as a global etc).

You can solve this by having q be a parameter to the function, then creating an anonymous function to call quad, like so:
function w = tointegrate(x, q)
w = 2 * q * sin(x);
endfunction
q = 5;
[ans, ier, nfun, err] = quad(#(x)tointegrate(x,q), -10*q, 10*q);
ans

Related

function handle to nested function not working for some values of parameter

This function is supposed to return a function handle to the nested function inside, but if the variable x is set to a negative value in the outer function, it doesn't work.
The inner nested function is just a constant function returning the value of the variable x that is set in the outer function.
function t=test(x)
x=-1;
function y=f()
y=x;
endfunction
t=#f;
endfunction
If I try to evaluate the returned function, e.g. test()(3), I get an error about x being undefined. The same happens if x is defined as a vector with at least one negative entry or if x is argument of the function and a negative default value is used for evaluation. But if I instead define it as some nonnegative value
function t=test(x)
x=1;
function y=f()
y=x;
endfunction
t=#f;
endfunction,
then the returned function works just fine. Also if I remove the internal definition of x and give the value for x as an argument to the outer function (negative or not), like
function t=test(x)
function y=f()
y=x;
endfunction
t=#f;
endfunction
and then evaluate e.g. test(-1)(3), the error doesn't occur either. Is this a bug or am misunderstanding how function handles or nested functions work?
The Octave documentation recommends using subfunctions instead of nested functions, but they cannot access the local variables of their parent function and I need the returned function to depend on the input of the function returning it. Any ideas how to go about this?
This is a bug that was tracked here:
https://savannah.gnu.org/bugs/?func=detailitem&item_id=60137
Looks like it was fixed and will be gone in the next release.
Also, to explain the different behavior of negative and positive numbers: I experimented a bit, and no variable that is assigned a computed value is being captured:
function t=tst()
x = [5,3;0,0]; # captured
y = [5,3;0,0+1]; # not captured
z = x + 1; # not captured
function y=f()
endfunction
t=#f;
endfunction
>> functions(tst)
ans =
scalar structure containing the fields:
function = f
type = nested
file =
workspace =
{
[1,1] =
scalar structure containing the fields:
t = #f
x =
5 3
0 0
}
The different behavior of negative and positive numbers are probably caused by the minus sign - before the numbers being treated as a unary operator (uminus).
As of octave version 5.2.0 the nested function handles were not supported at all. I'm going to guess that is the novelty of the version 6.
In octave functions are not variables, the engine compiles\translates them at the moment of reading the file. My guess would be that behavior you are observing is influenced by your current workspace at the time of function loading.
The common way for doing what you are trying to do was to generate the anonymous (lambda) functions:
function t = test1(x=-1)
t = #()x;
end
function t = test2(x=-1)
function s = calc(y,z)
s = y + 2*z;
end
t = #(a=1)calc(a,x);
end
Note that default parameters for the generated function should be stated in lambda definition. Otherwise if you'd call it like test2()() it would not know what to put into a when calling calc(a,x).
If you are trying to create a closure (a function with associated state), octave has limited options for that. In such a case you could have a look at octave's object oriented functionality. Classdef might be useful for quick solutions.

Octave function definition error

I am trying to use octave for the first time and I want to create a function as follows:
1;
function test=calc(x)
a=x^2;
factorial(a)
endfunction
val = calc (3)
I saved this as calc.m and when I run it I get an error that variable x is not defined.
What am I doing wrong?
Update: The original question I managed to get working but now I ended up with another problem. Please consider the following code:
init = 5.;
function val=prodval(x)
global init;
val=x+init^2;
endfunction
fin=prodval(3)
When I save the script as test.m and run it i get the following error:
>> test
error: for x^A, A must be a square matrix. Use .^ for elementwise power.
error: called from
prodval at line 5 column 6
test at line 7 column 4
What exactly is going on here? I do not see where I defined a matrix by mistake... I also realise that this may not be the best definition of a function but I am trying...
[UPDATE]
For each scope you want a global to be "visible" you have to declare
it as global. Reference
global init = 5;
function val = prodval (x)
global init;
val = x + init^2;
endfunction
fin=prodval(3)
fin = 28

Writing a function m-file in MATLAB

I am a beginner to coding and I need to write a function.m file for use with Newton's Method. I am having trouble defining the function, where r is radius and p is density:
f(theta) = ((r^2)/2)*((2*pi*p)-(theta - sin(theta)*p))
where radius r = 30cm and density p = 0.82 grams per cm^3
So far, I have written:
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
Things I am having trouble with:
Problem defining r and p. Getting an error:
Undefined function or variable 'r'
Having trouble plotting the function.
Things I want to do:
Plot the function to see where the roots are.
Be able to evaluate the function for a given theta.
All help is appreciated. Thank you!
i tried your code without changing. i named the M-file as f1 and executed the function in command line it is working.
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
i am getting the output as below
f=f1(45)
f =
-1.7618
this tells that there is no problem in your function. see for some other reason. if you could give your whole code it would be better to diagnose.
This could be done using an anonymous function
r=0.3;
p=0.82;
f=#(theta) (r^2)/2*(2*pi*p-theta+p*sin(theta));
then to evaluate the function just use eg: f(1), and to plot it, for example:
angles=0:.01:pi;
plot(angles,f(angles))
If you don't want to use an anonymous function, then use
function funcVal=func(angles)
r=0.3;
p=0.82;
funcVal=(r^2)/2*(2*pi*p-angles+p*sin(angles));
end
and call it by
angles=0:.01:pi;
plot(angles,func(angles))

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

Matlab ode45. How to change a parameter inside it while calling it?

I'm new with Matlab. I hope you can help me.
I have to solve a system of ODEs using ODE45 function. Here is the function which describes my equitions.
function dNdt = rateEquations(t, y)
%populations of corresponding state
Ng = y(1);
Ns = y(2);
Nt = y(3);
%All constants used are dropped for the sake of easy reading.
Note the parameter F.
%rate equations
dNs = s0 * Ng * F - Ns/ t_S1;
dNt = Ns / t_ISC - Nt / t_T1;
dNg = -dNt - dNs;
dNdt = [dNg; dNs; dNt];
end
Then, in my script .m-file i call the ode45 function in 'for loop'. During each iteration i have to change the parameter F and pass it to my 'rateEquations' - function. But i don't know how to realize it.
for T = Tmin: dt : Tmax
%initial conditions
initialConditions = [N0 0 0];
timeSpan = [T T+dt];
before calling ODE45 F is to be changed.
[t,N] = ode45('rateEquations', timeSpan, initialConditions)
and so on ...
end
Thanks in advance.
You want make F an argument of your derivative function and pass the right anonymous function to ode45:
[t,N] = ode45(#(t,y) rateEquations(t,y,F), timeSpan, initialConditions)