Entering default values in a function.

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 Kommentare

dpb
dpb am 26 Mär. 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.
KieranSQ
KieranSQ am 26 Mär. 2019
Bearbeitet: KieranSQ am 26 Mär. 2019
Apologies, I was trying to remove pointless names before but missed the size_matrix. I have adjusted it now. I have also noted that n must be chosen before hand.
if nargin < 1
error('n required');
end
if nargin < 2
x0 = ones(n, 1);
end
if nargin < 3
Tol = 10^-6;
end
KieranSQ
KieranSQ am 27 Mär. 2019
This still gives me the error 'Undefined function or variable 'n'.'. Is there a particular place this should go? i.e. like my example or somewhere else?
If I input n it then says the same for x0 and TOL...
Rik
Rik am 27 Mär. 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.
@KieranSQ: show us your code. Walter Roberson's code worked for me when I tried it:
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
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
Rik am 27 Mär. 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
Walter Roberson am 27 Mär. 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
Rik am 27 Mär. 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
Walter Roberson am 27 Mär. 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
dpb am 27 Mär. 2019
" I have a function with 22 named parameters (so far.)"
findpeaks() lite??? <VBG>
Walter Roberson
Walter Roberson am 28 Mär. 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.
Adam
Adam am 28 Mär. 2019
Bearbeitet: Adam am 28 Mär. 2019
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.
KieranSQ
KieranSQ am 28 Mär. 2019
Bearbeitet: KieranSQ am 28 Mär. 2019
@Stephen Cobeldick apologies for my delay. My code is below and run it by typing [counter,ratio,x,TOL,ROC]=FixedPointIteration(n,x0, TOL) for a specified n.
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
Adam
Adam am 28 Mär. 2019
So what is the problem with this code as is?

Melden Sie sich an, um zu kommentieren.

Antworten (1)

Rik
Rik am 28 Mär. 2019

0 Stimmen

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 Kommentare

KieranSQ
KieranSQ am 28 Mär. 2019
Ok, so if i provided n and TOL, how do I specify this in the function? Apologies I am coming from a python setup to this!
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
Walter Roberson am 28 Mär. 2019
Bearbeitet: Walter Roberson am 28 Mär. 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

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Data Type Identification finden Sie in Hilfe-Center und File Exchange

Gefragt:

am 26 Mär. 2019

Bearbeitet:

am 28 Mär. 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by