I want to use an integral over a vector but I will see an error for sys_eff which is " First input argument is not function handle."
I will be glad to have your guide and thanks in advance.
I should mention that all vectors have the same ize as 345600.
function [ P_loss,time_eff, sys_eff ] = final( Pmpp, Pl_inv, Pl_bat_inv, Pl_bat_r )
j=length(Pmpp);
for t=1:j;
P_loss(t)= Pl_inv(t) + Pl_bat_inv(t) + Pl_bat_r(t);
time_eff(t)= P_loss(t)/Pmpp(t);
end
sys_eff=integral(time_eff,0,345600);
end
As from the error message, the first input you provided to the function integral (i.e. time_eff) is not a function handle, but a vector.
If you want to make a numeric integral of the function use the function trapz
sys_eff=trapz(t,time_eff)
if t is your integration variable.
Related
It was suggested in this comment that there is a difference between how Matlab and Python pass around functions. From what I can tell by looking and using the two, there is no difference between the two, but maybe I'm missing something?
In Matlab, you would create a quick function handle like this:
fun = #(x) x.^2 + 1;
In Python, using a lambda function, you could create a similar function like this:
def fun(x):
return x^2
In both languages, it's possible to send the term 'fun' to another function as an argument - but the commenter I linked to insinuated that they are not the same and/or need to be used differently.
What am I missing?
The first comment seems to simply reiterate the idea that you can pass a MATLAB function handle as an argument (although the answer didn't state anything that would make me think otherwise). The second comment seemed to interpret this to mean that the first commenter thought that you couldn't do this in Python and responded to state that you can use either a lambda or pass the function directly.
Regardless, assuming that you use them correctly, a function handle in MATLAB is functionally equivalent to using either a lambda or function object as an input argument in Python.
In python, if you don't append the () to the end of the function, it doesn't execute the function and instead yields the function object which can then be passed to another function.
# Function which accepts a function as an input
def evalute(func, val)
# Execute the function that's passed in
return func(val)
# Standard function definition
def square_and_add(x):
return x**2 + 1
# Create a lambda function which does the same thing.
lambda_square_and_add = lambda x: x**2 + 1
# Now pass the function to another function directly
evaluate(square_and_add, 2)
# Or pass a lambda function to the other function
evaluate(lambda_square_and_add, 2)
In MATLAB, you have to use a function handle because MATLAB attempts to execute a function even if you omit the ().
function res = evaluate(func, val)
res = func(val)
end
function y = square_and_add(x)
y = x^2 + 1;
end
%// Will try to execute square_and_add with no inputs resulting in an error
evaluate(square_and_add)
%// Must use a function handle
evaluate(#square_and_add, 2)
Could you please help me with the following issue: I have the following function handle:
r1 = #(lambda) b + lambda*(r - b); % r and b are vectors of return data
I want to find the optimal lambdas that set me a mean function to zero, for a given set of powers within that function. What I tried to do and didn't work, as it returns me an error for undefined operators for input arguments of type 'function_handle' is:
lambda0 = 0.3;
for a = 2:10 %power coefficient
S1(a) = fzero(mean((r - b)*r1.^(1/(a - 1))),lambda0);
end
Any suggestion as to how to go about this problem is highly appreciated! Thank you in advance.
fzero accepts a function handle as the first input. As you currently have it, you're trying to pass a statement as the first input. This statement can't even be properly evaluated because you are trying to perform numerical operations on a function handle (more on this in a bit).
You need to instead do something like this where we create a new function handle that evaluates the original function handle and performs the other operations you need.
S1(a) = fzero(#(lambda)mean((r - b)*r1(lambda).^(1/(a - 1))),lambda0);
Further Explanation
Performing operations on a function handle is not the same as performing them on the result.
So for example, if we had a function handle:
func = #(x)2*x;
If we evaluation this, by calling it with an input value for x
func(2)
4
This works as we would expect. If now we really want the value (2*x)^2, we could try to write it the way that you wrote your statement in your question
func2 = func^2;
We will get an error!
Undefined operator '^' for input arguments of type 'function_handle'.
This does not work because MATLAB attempts to apply the ^ operation to the function handle itself and not the value of the evaluated function handle.
Instead, we would need to create a new function handle that essentially wraps the other one and performs any additional options:
func2 = #(x)func(x)^2;
func2(2)
16
Bringing it Full-Circle
So if we go back to your question, you defined your anonymous function r1 like this.
r1 = #(lambda) b + lambda*(r - b); % r and b are vectors of return data
This all looks great. You have one input argument and you reference r and b from the parent workspace.
Now when you call fzero you try to perform operations on this function handle in hopes of creating a new function handle.
mean((r - b)*r1.^(1/(a - 1)))
Like we just showed this will result in a very similar error
Undefined operator .^ for input arguments of type 'function_handle'
So we need to wrap this into a new function.
newfunc = #(lambda)mean((r - b)*r1(lambda).^(1 / (a - 1)));
Now we can safely pass this to fzero.
result = fzero(newfunc, lambda0);
I called Matlab's genetic algorithm solver, ga, in the following way:
[theta,fval,exitflag] = ga(smmobj,26,[],[],[],[],LB,UB,[],[]);
where theta is a 26-by-1 column vector that needs to be optimized.
So in the main function, it goes like this:
clc
clear
global var1 var2...
load ('abcd.mat')
theta0=[1 2 3....];
LB=[26-by-1 row vector];
UB=[26-by-1 row vector];
[theta,fval,exitflag] = ga(smmobj,26,[],[],[],[],LB,UB,[],[]);
The fitness function, smmobj, is defined as:
function [obj]=smmobj(theta)
global var1 var2...
But when I run it, it always says:
Error using smmobj (line 4)
Not enough input arguments.
Error in SMMga (line 32)
[theta,fval,exitflag] = ga(smmobj,26,[],[],[],[],LB,UB,[],[]);
But I run the fitness function by itself, it works.
[theta,fval,exitflag] = ga(smmobj,26,[],[],[],[],LB,UB,[],[]);
will throw that error because you are essentially calling the function smmobj (with no parameters) instead of passing your ga function a function handle to your objective function. You do this using the # symbol so
[theta,fval,exitflag] = ga(#smmobj,26,[],[],[],[],LB,UB,[],[]);
Incidentally, I would recommend that you do not use global in order to pass the extra parameters of var1 and var2 to your objective function but rather use anonymous functions:
[theta,fval,exitflag] = ga(#(x)(smmobj(x,var1,var2)),26,[],[],[],[],LB,UB,[],[]);
and then change smmobj's definition to
function [obj]=smmobj(theta,var1,var2)
Function:
My MATLAB function has one output and several input arguments, most of which are optional, i.e.:
output=MyFunction(arg1,arg2,opt1,opt2,...,optN)
What I want to do:
I'd like to give only arg1, arg2 and the last optional input argument optN to the function. I used the tilde operator as follows:
output=MyFunction(str1,str2,~,~,...,true)
Undesired result:
That gives the following error message:
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.
The error points to the comma after the first tilde, but I don't know what to make of it to be honest.
Problem identification:
I use MATLAB 2013b, which supports the tilde operator.
According to MATLAB's documentation the above function call should work:
You can ignore any number of function inputs, in any position in the argument list. Separate consecutive tildes with a comma...
I guess there are a few workarounds, such as using '' or [] as inputs, but I'd really like to understand how to correctly use '~' because actually leaving inputs out allows me to use exist() when checking the input arguments of a function.
If you need any further info from me, please let me know.
Thank you very much!
The tilde is only for function declaration. Matlab's mlint recommends to replace unused arguments by ~. The result is a function declared like this function output = MyFunction(a, b, ~, c). This is a very bad practice.
Since you have a function where the parameters are optional, you must call the function with empty arguments output=MyFunction(str1,str2,[],[],...,true).
A better way to do it is to declare the function with the varargin argument and prepare your function for the different inputs:
function output = MyFunction(varargin)
if nargin == 1
% Do something for 1 input
elseif nargin == 2
% Do something for 3 inputs
elseif nargin == 3
% Do something for 3 inputs
else
error('incorrect number of input arguments')
end
It is even possible to declare your function as follows:
function output = MyFunction(arg1, arg2, varargin)
The declaration above will tell Matlab that you are expecting at least two parameters.
See the documentation of nargin here.
... and the documentation of varargin here
To have variable number of inputs, use varargin. Use it together with nargin.
Example:
function varlist2(X,Y,varargin)
fprintf('Total number of inputs = %d\n',nargin);
nVarargs = length(varargin);
fprintf('Inputs in varargin(%d):\n',nVarargs)
for k = 1:nVarargs
fprintf(' %d\n', varargin{k})
end
To learn how to work with fzero() I tried this code:
function equation(x)
k=(96-x)/6;
end
and then:
x0=4;
x=fzero('equation',x0)
The error is:
??? Error using ==> fzero at 307
FZERO cannot continue because user supplied function_handle ==> equation
failed with the error below.
Too many output arguments.
fzerois expecting a return value from your equation so (internally) it is trying to assign something to the output of that function. If I try
result = equation(42);
I get the same error message
Error using equation
Too many output arguments.
Just change your function signature to
function [k] = equation(x)
to indicate that k is the output of this function.
Try to supply the function argument as handle:
x = fzero(#equation,x0)