Entering default values in a function.
Show older comments
I am trying to add default values into my function but whenever I use nargin or varargin i still get 'undefined function or variable 'x0'', could someone advise? I would like to have it for x0 and TOL not being entered. The function requires you to input n, say n=10.
function code(n,x0,TOL)
switch nargin
case 0
ee=ones(n,1);
x0 = ee;
end
break
end
%Or using this.
% if nargin < 3
% Tol = 10^-6;
% if nargin < 2
% x0 = ee;
% end
end
As requested, my full code:
function [counter,ratio,x,TOL,ROC]=FixedPointIteration(n,x0, TOL)
if nargin < 1
error('n required');
end
if nargin < 2
x0 = ones(n, 1);
end
if nargin < 3
TOL = 10^-6;
end
A=abs(rand(n)*10^0);
A=A*transpose(A);
% A=[1,5;5,5];
ee=ones(n,1);
x0=ee;
x=x0;
% x=[1;2] %column vector
D=zeros(length(x),length(x));
for i=1:length(x)
D(i,i)=x(i);
end
e=ones(length(x),1);
MaxTOL=10^(-6);
Tolerance=norm(D*A*D*e-e,1);
counter=1;
while Tolerance>TOL
TOLprevious=Tolerance;
counter=counter+1;
y=x;
x_k1=1./(A*x); %Calculates the iterative solution
ratio=x_k1./y; %Ratio of current solution against previous
x=x_k1./(ratio).^0.5;
for i=1:length(x)
D(i,i)=x(i);
end %Builds the matrix D(x)
P=D*A*D;
Tolerance=norm(D*A*D*e-e,1);
ratio_list(counter-1)=Tolerance/TOLprevious;
end
figure(1)
% max(ratio_list)
semilogy(1:counter-1,(ratio_list))
title('Error Ratio Against Step Number')
xlabel('Step Number')
ylabel('Log Error Ratio')
% hold off
if length(A)>2
t=eig(P);
ROC=t(3)/t(2); %Extracts the initial rate of convergence
else
t=eig(p);
ROC=t(2)/t(1);
end
end
16 Comments
dpb
on 26 Mar 2019
If you pass no arguments, then size_matrix is undefined so ee won't be defined 'cuz it'll error before getting there...everything needs a definition before it is used.
Walter Roberson
on 26 Mar 2019
if nargin < 1
error('n required');
end
if nargin < 2
x0 = ones(n, 1);
end
if nargin < 3
Tol = 10^-6;
end
KieranSQ
on 27 Mar 2019
Rik
on 27 Mar 2019
If you are using the code that Walter suggested you should not get that error. Please share the code you're actually using, because apparently there is something going wrong when converting this suggested to your function.
Stephen23
on 27 Mar 2019
function out = myfun(n,x0,Tol)
if nargin < 1
error('n required');
end
if nargin < 2
x0 = ones(n, 1);
end
if nargin < 3
Tol = 10^-6;
end
out = (n+x0)*Tol;
end
and tested:
>> myfun(1)
ans = 2.000000000000001e-006
>> myfun(2,3)
ans = 5.000000000000003e-006
>> myfun(2,3,4)
ans = 20
Adam
on 27 Mar 2019
I generally go for an
if ~exist( 'x0', 'var' )
...
end
if ~exist( 'TOL', 'var' )
...
end
approach to provide more robustness against changes in the number or order of inputs in the function signature, but the nargin approach should work fine too for a fixed function signature.
I usually go a step further with
if exist( 'x0', 'var' ) && ~isempty( x0 )
validateattributes( ... )
else
x0 = ones( n, 1 );
end
and so on, to also provide validation of my inputs and support passing in [ ] for e.g. the 2nd argument if I want to use the default for that but specify my own 3rd argument.
But this is all just down to how fussy you want to be. I like to be very fussy often!
You can also use
doc inputParser
but that is a rather overblown solution here and one i only rarely use anywhere as it works best, in my opinion, with varargin type inputs which I generally steer clear of in my function definitions.
Rik
on 27 Mar 2019
I switched to using a form of an input parser (as you can see in some of my FEX submissions). Those provide the flexibility to have struct input and Name,Value pairs. I agree with Adam that such a solution might be shooting at a fly with a cannon.
Walter Roberson
on 27 Mar 2019
I tend to find that about the time that a program becomes complex enough to warrant using inputParser, that it is probably also getting complex enough that people would benefit from a GUI to make the various choices more visible and easier for the user to remember.
... Not that I am especially likely to bother to write that GUI: it is just that by the time an interface gets complex enough that order of inputs becomes too tricky to remember reliably, thus warranting named options, then it has probably become complex enough that even remembering what the options are has become tricky.
Rik
on 27 Mar 2019
@Walter, if your comment is target at the situation presented in this question I might agree, but if your comment is (at least partially) replying to my comment then I don't understand you. I don't really see how a bunch of Name,Value pairs are better suited to be shown in a GUI instead of extensive documentation in the function header.
Walter Roberson
on 27 Mar 2019
For example I have a function with 22 named parameters (so far.) By the time you got to the bottom of the description of each of the 22 and how they interact, then you would probably have forgotten exactly what you need to type in -- and you certainly would have caused the window to scroll up thus obscuring the names and values of variables you have in the command window.
Sometimes a GUI is just easier on the user.
... Not that I tend to create GUIs these days, but I do recognize that my two major works-in-progress are weak on user interface and that no-one other than myself could be expected to understand them in their current interface form.
dpb
on 27 Mar 2019
" I have a function with 22 named parameters (so far.)"
findpeaks() lite??? <VBG>
Walter Roberson
on 28 Mar 2019
findpeaks() only has 10... I have
- F_spec
- Fvec
- Farray
- nvars
- iters
- pop_in
- zone
- targetmem
- subdiv
- numnicer
- residuetarget
- firstpastthepost
- lb
- ub
- showallbest
- maxfunevals
- maxiter
- imagtol
- random
- near
- nonlcon
- constrainttolerance
7 of those are used "most" times.
Where I use varargin it is almost exclusively with a class and the (name,value) pairs that are supported are just any of the public properties of the class, which at least helps to keep that a little simpler. I remember some quote from someone once to the effect of 'If your function takes 10 arguments you probably forgot a few'. I don't generally subscribe to the hard-core software engineer folks who like to limit to something like 3 maximum arguments, but I don't like functions that are getting on for 7, 8+ arguments. I tend to feel as though I'm definitely doing something wrong in that case, unless it is in the initial construction of a class object, which is where I sometimes use Matlab's (Name,Value) style.
When I see function signatures like this in the Matlab help I do despair though:
[dW,LS] = learnsomb(W,P,Z,N,A,T,E,gW,gA,D,LP,LS)
Of course, verbose parameter naming would mean that would scroll way off screen, but yeah, that just loses me! Especially when the only example in the help shows:
[dW,ls] = learnsomb(w,p,[],[],a,[],[],[],[],d,lp,ls)
You know something has gone wrong in your public function interface if standard usage is to pass in 6 empty arguments!
But anyway, that is rather an aside to the question at hand!! But it is a tricky topic that I'm never really fully happy with the solutions I apply myself.
Adam
on 28 Mar 2019
So what is the problem with this code as is?
Answers (1)
Rik
on 28 Mar 2019
If you only want to specify n, you should only provide that as the input:
n=4;
[counter,ratio,x,TOL,ROC]=FixedPointIteration(n)
3 Comments
KieranSQ
on 28 Mar 2019
Rik
on 28 Mar 2019
There is a difference between the function definition and a function call. If you provide fewer input variables than are defined in the function header, Matlab will try to run the function without defining the variables. That is why you define them after checking nargin.
The following two lines are equivalent in Matlab:
n=4;
[counter,ratio,x,TOL,ROC]=FixedPointIteration(n);
[counter,ratio,x,TOL,ROC]=FixedPointIteration(4);
Walter Roberson
on 28 Mar 2019
Edited: Walter Roberson
on 28 Mar 2019
Arguments are positional in MATLAB unless you deliberately parse the input such as using name/value pairs. So you cannot simply call your function with n and TOL because TOL is your third argument and when you pass it in the second position, MATLAB would have no way of knowing that the value was intended to be a tolerance rather than an x0 value.
The typical convention in MATLAB is for the user to pass [] (empty array) in the places they want to default the input, and for the code to detect those [] and use default values. For example,
if nargin < 3 || isempty(x0)
x0 = ones(1,n);
end
Categories
Find more on Data Type Identification in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!