How to safely manipulate MATLAB anonymous functions in string form - matlab

I have an anonymous function that I would like to manipulate in string form then use with fsolve.
When I do this the references in the anonymous function to constants are lost and fsolve fails.
The problem is easily illustrated.
The following works:
A=3;
myfun=#(x)sin(A*x);
x = fsolve(#(x)myfun(x),[1 4],optimoptions('fsolve','Display','off'))
The following throws an error as explained here:
A=3;
myfun=#(x)sin(A*x);
mystring=func2str(myfun);
%string operations would go here such as strrep(mystring,'A','A^2') or whatever
myfun2=str2func(mystring);
x = fsolve(#(x)myfun2(x),[1 4],optimoptions('fsolve','Display','off'))
Is there some way I CAN safely manipulate an anonymous function while retaining references to constant parameters?
more info
Specifically I'm writing a simple wrapper to allow fsolve to accept imaginary numbers for simple cases. The following illustrates a working example without a constant parameter:
myeqn=#(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
f1=strrep(func2str(myeqn),'#(x)','');
f2=strrep((f1),'x','(x(1)+(x(2))*1i)');
f3=strcat('#(x)[real(',f2,'); imag(',f2,')]');
fc=str2func(f3);
opts=optimoptions('fsolve','Display','off');
result=arrayfun(#(cinput)[1 1i]*(real(fsolve(fc,[real(cinput);imag(cinput)],opts))),cX0)
As in the failed example above if I include a parameter in my wrapper the process fails with the same error as above.

I originally suggested to use the symbolic math toolbox, but reading your question again I realized it's just a simple substitution of input parameters. You can achieve this using function handles without any string processing.
myeqn=#(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
wrapper=#(x,f)([real(f(x(1)+x(2)*i)),imag(f(x(1)+x(2)*i))])
opts=optimoptions('fsolve','Display','off');
result=arrayfun(#(cinput)[1 1i]*(real(fsolve(#(x)wrapper(x,myeqn),[real(cinput);imag(cinput)],opts))),cX0)

As much as I hate to suggest using the eval function, you could do:
myfun2 = eval(mystring);
Using eval is kinda frowned upon because it makes code hard to analyze (since arbitrary nastiness could be going on in that string), but don't let other people's coding style stop you from doing what works :)
In your longer example, this would correspond to changing the line:
fc=str2func(f3);
to:
fc=eval(f3);
Again, the use of eval is strongly discouraged, so you should consider alternatives to this type of string manipulation of function definitions.

Related

equivalent of `evalin` that doesn't require an output argument (internally)

Background -- I was reading up on accessing shadowed functions, and started playing with builtin . I wrote a little function:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
This throws the error:
Error using clear
Too many output arguments.
I think this happens because evalin demands an output from whatever it's being fed, but clear is one of the functions which has no return value.
So two questions: am I interpreting this correctly, and if so, is there an alternative function that allows me to execute a function in the parent environment (that doesn't require an output)?
Note: I'm fully aware of the arguments against trying to access shadowed funcs (or rather, to avoid naming functions in a way that overload base funcs, etc). This is primarily a question to help me learn what can and can't be done in MATLAB.
Note 2
My original goal was to write an overload function that would require an input argument, to avoid the malware-ish behavior of clear, which defaults to deleting everything. In Q&D pseudocode,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
There's a couple issues with your clear override:
It will always clear in the base workspace regardless of where it's called from.
It doesn't support multiple inputs, which is a common use case for clear.
Instead I'd have it check for whether it was called from the base workspace, and special-case that for your check for whether it's clearing everything. If some function is calling plain clear to clear all its variables, that's bad practice, but it's still how that function's logic works, and you don't want to break that. Otherwise it could error, or worse, return incorrect results.
So, something like this:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
I hope it goes without saying that this is an atrocious hack that I wouldn't recommend in practice. :)
What happens in your code:
evalin('base', builtin('clear','x'));
is that builtin is evaluated in the current context, and because it is used as an argument to evalin, it is expected to produce an output. It is exactly the same as:
ans = builtin('clear','x');
evalin('base',ans);
The error message you see occurs in the first of those two lines of code, not in the second. It is not because of evalin, which does support calling statements that don't produce an output argument.
evalin requires a string to evaluate. You need to build this string:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(In MATLAB, the quote character is escaped by doubling it.)
You function thus would look like this:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(Inserting a string into another string this way is rather awkward, one of the many reasons I don't like eval and friends).
It might be better to use evalin('caller',...) in this case, so that when you call the new clear from within a function, it deletes something in the function's workspace, not the base one. I think 'base' should only be used from within a GUI that is expected to control variables in the user's workspace, not from a function that could be called anywhere and is expected (by its name in this case) to do something local.
There are reasons why this might be genuinely useful, but in general you should try to avoid the use of clear just as much as the use of eval and friends. clear slows down program execution. It is much easier (both on the user and on the MATLAB JIT) to assign an empty array to a variable to remove its contents from memory (as suggested by rahnema1 in a comment. Your base workspace would not be cluttered with variables if you used function more: write functions, not scripts!

handing string to MATLAB function in Simulink

In my Simulink Model I have a MATLAB function, this_function, which uses as one parameter the name of the Simulink Model, modelname. The name is defined in an extra parameter file with all other parameters needed. Loading the parameter file loads modelname into the workspace. The problem is now, that this_function can't access modelname in the workspace and therefore the model doesn't run.
I tried to use modelname as a constant input source for this_function, which I used as a work-around previously, but Simulink doesn't accept chars/strings as signals. Furthermore does setting modelname to global not work as well.
Is there a way to keep modelname in the parameter file instead of writing it directly into this_function?
Simulink does not support strings. Like, anywhere. It really sucks and I don't know why this limitation exists - it seems like a pretty horrible design choice to me.
I've found the following workarounds for this limitation:
Dirty Casting
Let
function yourFun(num_param1, num_param2, ..., str_param);
be your MATLAB function inside the Simulink block, with str_param the parameter you want to be a string, and num_param[X] any other parameters. Then pass the string signal to the function like so:
yourFun(3, [4 5], ..., 'the_string'+0);
Note that '+0' at the end; that is shorthand for casting a string to an array of integers, corresponding to the ASCII codes of each character in the string. Then, inside the function, you could get the string back by doing the inverse:
model = char(str_param);
but usually that results in problems later on (strcmp not supported, upper/lower not supported, etc.). So, you could do string comparisons (and similar operations) in a similar fashion:
isequal(str_param, 'comparison'+0);
This has all the benefits of strings, without actually using strings.
Of course, the '+0' trick can be used inside constant blocks as well, model callbacks to convert workspace variables on preLoad, etc.
Note that support for variable size arrays must be enabled in the MATLAB function.
Fixed Option Set
Instead of passing in a string, you can pass a numeric scalar, which corresponds to a selection in a list of fixed, hardcoded options:
function yourFun(..., option)
...
switch (option)
case 1
model = 'model_idealised';
case 2
model = 'model_with_drag';
case 3
model = 'model_fullscale';
otherwise
error('Invalid option.');
end
...
end
Both alternatives are not ideal, both are contrived, and both are prone to error and/or have reusability and scalability problems. It's pretty hopeless.
Simulink should start supporting strings natively, I mean, come on.

Set Matlab function parameter as uint8

Is it possible in Matlab to say what the function expects? something like this:
function functionA( obj, uint8(param) )
Here I am saying that the function expects one parameter of type uint8.
Not on the function signature. Typically, you do this via an assert block:
function (obj, param)
assert(isa(param, 'uint8'),...
[mfilename ':invalid_datatype'],...
'Parameter ''param'' must be of class ''uint8''; received ''%s''.',...
class(param));
To complement Rody's answer, there are four ways that you can do this:
Use a conditional and raise an exception if the argument is not of the expected type. The problem with this method is that you have to write a lot of code.
Use an assertion. See Rody's answer or here. One can argue that this is not what assertions are supposed to be used for, but you can certainly use them this way.
Use the validateattributesfunction. See here. This is a very good balance between simplicity and utility. It allows you to check for a number of properties in an argument (and generally, any variable at any part of code)
Use the inputParser class. See here. This is the most powerful method of parsing inputs, but may be overkill. Also, the cost of creating an inputParser object means that it may not be a good idea for functions that are called repeatedly. Nevertheless, it's very good for the public API.

MATLAB bug? "Undefined function or variable" error when using same name for function and variable

It is occasionally convenient to use a function as a "constant" variable of sorts in MATLAB. But when I was using this feature recently, I ran into an unexpected error. When I run the MWE below, I get the error Undefined function or variable 'a'. despite the function being clearly available in the same file. When I comment out the if statement, the error goes away. This seems to imply that MATLAB is pre-interpreting a as a variable even though the variable assignment line is never reached, ignoring the fact that there is a function by the same name. Is this a MATLAB bug or is it somehow the desired behavior?
Here is the MWE:
function matlabBugTest( )
if false
a = 'foo';
end
a
end
function b = a()
b = 'bar';
end
Follow-up:
I know it seems weird to intentionally use the same name for a variable and a function, so I'll give an example of where this can be useful. For instance, you may want to use a function to store some constant (like a file path), but also want to be able to use a different value in case the function cannot be found. Such a case might look like:
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
I know that language design decisions are often difficult and complicated, but one of the more unfortunate consequences of MATLAB's choice here to ignore the function by the same name is that it breaks compatibility between functions and scripts/command line. For instance, the following runs without issue in a script:
if false
a = 'foo';
end
a
where the function a (shown above) is saved in its own file.
It has to do with how Matlab performs name-binding at compilation time. Because matlabBugTest has a line that assigns a value to a, a is determined to be a variable, and the later line with a is a reference to that variable and not a call to the local function. More modern versions of Matlab, like my R2015a install, gives a more clear error message:
At compilation, "a" was determined to be a variable and this variable is uninitialized. "a" is also a function name and previous versions of MATLAB would have called the
function. However, MATLAB 7 forbids the use of the same name in the same context as both a function and a variable.
It's not so much a bug, as it is an ambiguity introduced by the naming scheme that was given a default resolution method, which can be annoying if you have never encountered the problem before and m-lint doesn't mark it. Similar behavior occurs when variables are poofed into the workspace without initialization beforehand.
So the solution is to either change the name of the function or the variable to different things, which I would argue is good practice anyways.
In considering your follow-up example, I have noticed some interesting behavior in moving things around in the function. Firstly, if the function is either external or nested, you get the behavior discussed very well by Suever's answer. However, if the function is local, you can get around the limitation (at least you can in my R2014b and R2015a installs) by invoking the function prior to converting it to a variable as long as you initialize it or explicitly convert it to a variable at some point. Going through the cases, the following bodies of matlabBugTest perform thusly:
Fails:
a
if false
a = 'foo';
end
a
Runs:
a
if true
a = 'foo';
end
a
Runs:
a = a;
if false % runs with true as well.
a = 'foo';
end
a
I'm not entirely sure why this behavior is the way it is, but apparently the parser handles things differently depending on the scope of the function and the order of what symbols appear and in what contexts.
So assuming this behavior hasn't and will not change you could try something like:
pathConstant = pathConstant;
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
Though, entirely personal opinion here, I would do something like
pathConstant = getPathConstant();
if ~exist('pathConstant.m', 'file')
pathConstant = 'C:\some\path';
end
load(fullfile(pathConstant, 'filename.ext'));
Concerning breaking "compatibility between functions and scripts/command line", I don't really see this as an issue since those are two entirely different contexts when it comes to Matlab. You cannot define a named function on the command line nor in a script file; therefore, there is no burden on the Matlab JIT to properly and unambiguously determine whether a symbol is a function call or a variable since each line executes sequentially and is not compiled (aside from certain blocks of code the JIT is designed to recognize and optimize like loops in scripts). Now as to why the above juggling of declarations works, I'm not entirely sure since it relies on the Matlab JIT which I know nothing about (nor have I taken a compiler class, so I couldn't even form an academic reason if I wanted).
The reason that you get this behavior is likely that Matlab never have implemented scope resolution for any of their statements. Consider the following code,
(a)
if true
a = 'foo';
end
disp(a)
This would actually display "foo". On the other hand would,
(b)
if false
a = 'foo';
end
disp(a)
give you the error Undefined function or variable "a". So let us consider the following example,
(c,1)
enterStatement = false;
if enterStatement
a = 'foo';
end
disp(a)
(c,2)
enterStatement = mod(0,2);
if enterStatement
a = 'foo';
end
disp(a)
TroyHaskin clearly states the following in his answer
It has to do with how Matlab performs name-binding at compilation time. Because matlabBugTest has a line that assigns a value to a, a is determined to be a variable, and the later line with a is a reference to that variable and not a call to the local function
Matlab does not support constant expressions and does only a limited amout of static code analysis. In fact, if the if statement takes argument false, or if enterStatement is false, Matlab provides a warning, This statement (and possibly following ones) cannot be reached. If enterStatement is set to false Matlab also generates another warning, Variable a is used, but might be unset. However if enterStatement = mod(0,2), so to say if enterStatement calls a function, you get no warning at all. This means that if the example in the question was allowed then (c,2) would compile based on how the function were evaluated and that is a contradiction. This would mean that the code would have to compile based on its runtime results.
Note: Sure it could be good if Matlab could generate an error in case the enterStatement was an expression instead of a constant false, but whether or not this is possible it would depend on implementation I guess.

how single and double type variables work in the same copy of code in Matlab like template in C++

I am writing a signal processing program using matlab. I know there are two types of float-pointing variables, single and double. Considering the memory usage, I want my code to work with only single type variable when the system's memory is not large, while it can also be adapted to work with double type variables when necessary, without significant modification (simple and light modification before running is OK, i.e., I don't need runtime-check technique). I know this can be done by macro in C and by template in C++. I don't find practical techniques which can do this in matlab. Do you have any experience with this?
I have a simple idea that I define a global string containing "single" or "double", then I pass this string to any memory allocation method called in my code to indicate what type I need. I think this can work, I just want to know which technique you guys use and is widely accepted.
I cannot see how a template would help here. The type of c++ templates are still determined in compile time (std::vector vec ...). Also note that Matlab defines all variables as double by default unless something else is stated. You basically want runtime checks for your code. I can think of one solution as using a function with a persistent variable. The variable is set once per run. When you generate variables you would then have to generate all variables you want to have as float through this function. This will slow down assignment though, since you have to call a function to assign variables.
This example is somehow an implementation of the singleton pattern (but not exactly). The persistent variable type is set at the first use and cannot change later in the program (assuming that you do not do anything stupid as clearing the variable explicitly). I would recommend to go for hardcoding single in case performance is an issue, instead of having runtime checks or assignment functions or classes or what you can come up with.
function c = assignFloat(a,b)
persistent type;
if (isempty(type) & nargin==2)
type = b;
elseif (isempty(type))
type = 'single';
% elseif(nargin==2), error('Do not set twice!') % Optional code, imo unnecessary.
end
if (strcmp(type,'single'))
c = single(a);
return;
end
c = double(a);
end