Output argument "am" (and maybe others) not assigned during call to - matlab

I am trying to use this function in my m file but I get an error(mentioned in question). Everything seems correct and a, b and c are defined in my m file. Any thoughts?
Error:
Error in modal2 (line 8)
[v,an]=eig(a);
Output argument "am" (and maybe others) not assigned during call to "C:\Users\Cena\Desktop\Thesis\My Codes\SMC\modal2.m>modal2".
function [r,am,bm,cm] = modal2(a,b,c)
% this function determines the modal representation 2(am,bm,cm)
%given a generic state-space representation (a,b,c)
%and the transformation r to the modal representation
%such that am=inv(r)*a*r, bm=inv(r)*b and cm=c*r
%transformation to complex-diagonal form:
[v,an]=eig(a);
bn=inv(v)*b;
cn=c*v;
%transformation to modal form 2:
i = find(imag(diag(an))');
index = i(1:2:length(i));
j=sqrt(-1);
t = eye(length(an));
if isempty(index)
am=an;bm=bn;cm=cn;
else
for i=index
t(i:i+1,i:i+1)=[j 1;-j 1];
end
%Modal transformation
r=v*t;
end

The problem is likely in
if isempty(index)
am=an;bm=bn;cm=cn;
The assignment to those variables is only being done if the conditional passes. If it doesn't , there is no assignment.
You need to modify your code to assign to those variables under all conditions if they are going to be output arguments.

Related

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

Operations with function handle in matlab

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

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.

How to write a function that does not throw a "wrong number of arguments" error

I am trying to write a minimal function that can be called with a variable number of arguments but that will not throw a wrong number of arguments error if miscalled.
Here is where I start from :
function varargout=fname(varargin)
% FNAME
% Usage: output=fname(input)
% Arguments check
if(nargin~=1 || nargout~=1)
disp('Function fname requires one input argument');
disp('and one output argument');
disp('Try `help fname`');
varargout(1:nargout)={0};
return;
end
input=varargin{1};
output=input;
varargout(1)={output};
end
However this does not work as I would like it to. Is there a way to write a function that :
never throw a "wrong number of arguments" error (so that the rest of the execution can continue)
accepts variable number of input and output arguments and checks them inside the function
(maybe more tricky) if the number of input / output arguments is not correct, does not replace the value of the provided output arguments (so that any misplaced call does not erase the previous value of the output argument)
I am open to any suggestions / other methods.
Thank you for your help.
UPDATE: thanks to #Amro for his answer, I guess what I miss here is either a call by address of reference for Matlab functions or a way to interrupt a function without returning anything and without stopping the rest of the execution.
Here is one way to implement your function:
function varargout = fname(input,varargin)
%# FNAME
%# Usage: output=fname(input)
%%# INPUT
if nargin<1
varargout(1:nargout) = {[]};
warning('Not enough input arguments.'), return
end
if ~isempty(varargin)
warning('Too many input arguments.')
end
%%# YOUR CODE: manipulate input, and compute output
output = input;
%%# OUTPUT
varargout{1} = output;
if nargout>1
warning('Too many output arguments.')
varargout(2:nargout) = {[]};
end
end
Obviously you can customize the warning messages to your liking...
Also, if you want your function to simply print the message instead of issuing warnings, replace all WARNING calls with simple DISP function calls.
Examples of function call:
fname()
fname(1)
fname(1,2)
x = fname()
x = fname(1)
x = fname(1,2)
[x,y] = fname()
[x,y] = fname(1)
[x,y] = fname(1,2)
The above calls execute as expected (showing warning messages when applicable). One caveat though, in the last three calls, if the variable y already existed in the workspace prior to the calls, it would be overwritten by the empty value y=[] in each...
If I understand your question correctly, then the answer is no. If a caller calls a function like this:
[a, b, c] = fname('foo');
then fname is required to return (at least) three outputs. There's no way to tell MATLAB that it should leave b and c alone if fname only returns one output.