not enough argument, self-defined function in matlab - matlab

I am a newbie of matlab and am trying to define a pretty complex function to plot it. The content of file is following:
function [res] = distribution (input)
a = factorial(30)
b = factorial(input) * factorial(30-input)
c = power(0.05, input)
d = power(0.95, 30-input)
a/b*c*d
end
in the file named distribution with .m extension. But when I run it error returns: "Error using distribution (line 4). Not enough input arguments."
I read through the "Getting Started" and find no solution. Does anyone have suggestions on this?

The name of the single argument to your function distribution(..), namely argument input, conflicts with the existing native input command of Matlab,
input: Prompt for user input.
...
x = input(prompt)
Try choosing a different name of this argument (in example below: foo), and also remember to return your result by assigning it to the return variable res:
function res = distribution (foo)
a = factorial(30);
b = factorial(foo) * factorial(30-foo);
c = power(0.05, foo);
d = power(0.95, 30-foo);
res = a/b*c*d; % <--- note, return parameter assignment
end

Related

Linking input file with variable stored in it to several function files

I have code which is in multiple function files, input to these functions are stored in one file called inputfile.m(script file), in which I assigned some constant values to the inputs. These values act as a input to several function files named degree_eq.m(function file).
How I can write the code so that every time of execution, function files takes the required inputs from the inputfile.m.
Let's say you have two functions, one with your inputs (inputfile) and one where you do stuff (do_stuff).
function [a,b,c] = inputfile()
%define your constants
a=10;
b=100;
c=8.3;
function z = do_stuff()
[a, b, c] = inputfile() %takes the inputs from inputfile.m
z = a*c - b;
You can exploit the fact that matlab variables are persistent outside their scope. Lets say you have 6 constants a,b,c,d,e,f defined in input file. So what can be done is, write a top script called top.m which would be something like
inputfile
degree_eq1(a,b,c)
degree_eq2(c,d,e)
A third approach (combining Nirvedh Meshram and qbzenker answers) is to call an input script inside your MATLAB functions.
The advantage is that you do not have to specify which parameters are needed from or specified in your input script, but this is a disadvantage too, because the needed inputs are not made explicit. So, it is much more error prone. I only recommend this approach for a large number of input variables.
inputfile.m:
a = 5;
b = 8;
c = 10;
degree_eq.m:
function d = degree_eq()
inputfile;
d = a + b + c;
end
As an alternative, you can specify which input file to use:
degree_eq.m:
function d = degree_eq(inputFilename)
eval(inputFilename);
d = a + b + c;
end
and call it as follows:
degree_eq('inputfile');

Function with different return variables

Is there a way to have one function that can return two different variables, but only one at a time AND knowing which one is returned in the function call?
example:
I have the following function in which only one of the outputs is valid (the other one would be [])
function [a,b] = AlternatingOutput (input)
if input == 1
return ONLY A
else
return ONLY B
end
end
and i call it in a script
[a,b] = AlternatingOutput (input)
i want a way to say the following (pseudocode):
if (function outputs a)
[a,~] = AlternatingOutput(input)
elseif (function outputs b)
[~,b] = AlternatingOutput(input)
end
the script is run in a loop, and later i need the newest Valid values for a and b, so i cannot overwrite one of the two with []
I do understand that I could just write a function that checks which variable will be output, but I was wondering if there is a more elegant way.
I hope I have made my question clear, and I hope someone can answer me :)
There is no way to tell if an output argument is actually used. You may check the number of output arguments using nargout and it would allow to distinguish between [a] = AlternatingOutput(input) and [~,b] = AlternatingOutput(input)
I don't know the full context of your problem, but maybe you can put all your variables into a struct? Simply pass this struct everytime you call the function and let it decide which variables to manipulate. (This might be slow in some programming languages, but not in matlab).
How about retuning a cell?
function [ ab ] = testfun( input )
if input
ab={'ax'};
else
ab={2};
end
end
No worries about what is in the cell.
thb you could return what ever you want, Matlab does not check the type anyways
If only one of the outputs from the function AlternatingOutput is valid, then you only need to return one output:
function [X] = AlternatingOutput(input)
if input == 1
X = A;
else
X = B;
end
end
To allocate the retured value to either a or b in the loop, put them into a cell:
C = {AlternatingOutput(1), AlternatingOutput(2)};
and then use input to determine which value is change. If input is either 1 or 2 you can just do
for counter = ...
input = mod(input,2)+1;
C{input}=AlternatingOutput(input);
end
If your function doesn't mind accepting more input variables, why not pass a and b as input:
function [a,b] = AlternatingOutput(a,b,input)
if input == 1
a = new_value_for_a;
% b retains its former value
else
% a retains its former value
b = new_value_for_b;
end
end
Then it can be easily called from your script in a loop:
for i= ...
[a,b] = AlternatingOutput(a,b,input);
...
...
end

Workaround equivalent of "inputname" to return structure name?

I know that, inside a MATLAB function, inputname(k) will return the k-th argument iff the argument is a variable name. Is there any way to write some parsing code that can retrieve the full input argument when that argument is a structure, e.g. foo.bar ? The reason I want to be able to do this is that I'm writing some tools for generic use where the input could be either a named variable or a named structure element.
My primary intent is to be able to store and return the input argment(s) as part of a structure or other variable that the function returns. This is a 'chain of custody' feature which makes it easier for me or others to verify the source data sets used to generate the output data sets.
I don't want the user to have to self-parse externally, or to have to deal with some kludge like
function doit(name,fieldname)
if(exist('fieldname','var'))
name = name.(fieldname);
myinput = [inputname(1),inputname(2)];
else
myinput = inputname(1);
end
% do the function stuff
(I call this a kludge because it both requires the user to enter strange arguments and because it fouls up the argument sequence for functions with multiple inputs)
There is no support from the language to get the input names when passing structs. The reason is probably x.a is internally a call to subsref which returns a new variable, all context is lost. The only possibility you have is using the debug tools and parse the code. There is no other option.
function x=f(varargin)
[ST, I] = dbstack('-completenames', 1);
if numel(ST)>0
fid=fopen(ST(1).file,'r');
for ix=2:ST(1).line;fgetl(fid);end
codeline=fgetl(fid);
fclose(fid);
fprintf('function was called with line %s\n',codeline);
else
fprintf('function was called from base workspace\n');
end
end
From there you may try to parse the code line to get the individual argument names.
Far uglier than Daniel's approach, and probably will crash on the wrong OS, but here's a hack that works to retrieve the first argument; easily adjusted to retrieve all arguments.
[~,myname] = system('whoami');
myname = strtrim(myname(4:end)); % removes domain tag in my Windows envir
% sorry about " \' " fouling up SO's color parsing
myloc = ['C:\Users\' , myname , '\AppData\Roaming\MathWorks\MATLAB\R2015a\History.xml'] ;
f = fopen(myloc,'r');
foo = fscanf(f,'%s');
fclose(f);
pfoo = findpat(foo,'myFunctionName');
% just look for the last instance
namstart = find(foo(pfoo(end):(pfoo(end)+30)) =='(',1) +pfoo(end);
% catch either ')' or ','
namend(1) = find(foo((namstart):end)== ')',1) -2 +namstart;
if numel(find(foo((namstart):end)== ',',1)),
namend(2) = find(foo((namstart):end)== ',',1) -2 +namstart;
end
thearg = foo(namstart:(min(namend)) );

How do I use MATLAB's inputParser with optional string inputs? The documentation says "use a validation function" but it's unclear how to do that

I have a MATLAB file that contains a single top-level function, called sandbox. That function in turn contains two nested functions, mysum and myprod, which are identical in functionality and what parameters they allow except that one uses #sum internally and the other uses #prod internally. My goal is to create a wrapper function to use in both mysum and myprod that takes care of all the validation and input parsing. This function is called applyFunc.
Here's where it gets tricky. mysum and myprod come in two forms:
mysum(v) returns sum(v, 1).
mysum(v, 'imag') returns sum(v, 1) + 1i
Any other combinations of input should throw an error.
I'm having trouble using inputParser to parse these various combinations of input, specifically the optional string input. Here's the code:
function sandbox()
%% Data
v = [1 4; 3 3];
%% Calculations
s = mysum(v);
si = mysum(v, 'imag');
p = myprod(v);
pi = myprod(v, 'imag');
%% Accuracy tests
assert(isequal(s, [4 7]))
assert(isequal(si, [4+1i 7+1i]))
assert(isequal(p, [3 12]))
assert(isequal(pi, [3+1i 12+1i]))
function x = mysum(varargin)
x = applyFunc(#sum, varargin{:});
end
function x = myprod(varargin)
x = applyFunc(#prod, varargin{:});
end
end
function x = applyFunc(func, varargin)
p = inputParser();
p.addRequired('func', #(x) validateattributes(x, {'function_handle'}, {'scalar'}));
p.addRequired('v', #(x) validateattributes(x, {'double'}, {}, 'applyFunc:msg', 'v'));
p.addOptional('imag', '', #(x) validatestring(x, {'imag', ''})); % THIS LINE IS THE PROBLEM
p.parse(func, varargin{:});
f = p.Results.func;
v = p.Results.v;
strflag = p.Results.imag;
x = f(v);
if ~isempty(strflag)
validatestring(strflag, {'imag'});
x = x + 1i;
end
end
The line that's causing the problem is this one (as marked in the code above):
p.addOptional('imag', '', #(x) validatestring(x, {'imag', ''}));
The documentation for inputParser says that:
For optional string inputs, specify a validation function. Without a validation function, the input parser interprets valid string inputs as invalid parameter names and throws an error.
Unfortunately I don't have any idea how to do this. Is there something simple Im missing or what? If the 'imag' argument isn't passed at all (as in the assignment of s and p), the code works fine, but if I do pass it, I get this error:
Error using sandbox>applyFunc (line 32)
The value of 'imag' is invalid. It must satisfy the function:
#(x)validatestring(x,{'imag',''}).
Error in sandbox/mysum (line 18)
x = applyFunc(#sum, varargin{:});
Error in sandbox (line 7)
si = mysum(v, 'imag');
Any help?
The problem is that validatestring returns the matching string from the cell argument ({'imag',''}) rather than a Boolean indicating if it passes validation. Instead, use strcmp and any:
#(x) any(strcmp(x,{'imag', ''}))
Also, with validatestring, if the input string did not match either 'imag' or '' (actually just 'imag' since empty strings only match in R2014a+), it would throw an error rather than returning false so that the inputParser could return the appropriate error.
Another nice way to fix the problem is to change the syntax of applyFunc entirely so that instead of just 'imag' as an optional string input argument, use a Parameter-Value with 'imag' as the parameter and a validated boolean as the input.
The input definition suggested by Amro in the comments:
p.addParameter('imag', false, #(x)validateattributes(x, {'logical'}, {'scalar'}))
The usage:
mysum(x,'imag',true)
mysum(x) % default is equivalent to mysum(x,'imag',false)
This would simplify the rest of the code with p.Result.imag being a logical scalar. I would suggest:
x = f(v) + p.Result.imag*1i;
The problem is not inputParser, I think the issue is with validatestring.
1) First it does not match on empty strings:
>> x = ''
x =
''
>> validatestring(x, {'imag',''})
Expected input to match one of these strings:
imag,
The input did not match any of the valid strings.
Caused by:
Error using validatestring>checkString (line 85)
Expected input to be a row vector.
2) Second, if it successfully matches, it returns the resolved string (from one of the valid choice), instead of true/false. inputParser requires that the validation function either return a boolean, or nothing but throws error on failure.

Invoking a function from another which has the same number of inputs and outputs

I want to call a function in Matlab using another one, which has the same number of inputs and outputs. In fact, those inputs and outputs have the same name.
Example:
function [a,b] = gettwo(matrix,string,varargin)
[a,b] = getone(matrix,string,varargin{:});
end
This code produces the following error:
Error in getone(line 3)
aux = 'matrix(varargin{:})';
Output argument "b" (and maybe others) not assigned during
call to "C:\Users\baister\Documents\MATLAB\soft\getone.m>getone".
Error in results (line 4)
[a,b] = getone(matrix,string,varargin{:});
How should I wrap getone?
(The definitive function will have more lines than those shown in this post.)
Thanks.
The general wrapping for variable number of outputs should work like this:
function [varargout] = gettwo(matrix,string,varargin)
[varargout{1:nargout}] = getone(matrix,string,varargin{:});
end
You'll get the same error as above though, in case you do
[a,b] = gettwo(...);
and getone returns only 1 argument.