I meet a problem in the s function builder, I have to use a temp structure variable to transport the inputs to the extended C function.
Background: csolve function is a quadratic programming solver generated by CVXGEN for my QP problem, and I have tested the function in level-2 matlab s-fun. Now I want to use s function builder to genetate the TLC file that support the embedded code generate.
My Problem:
1) I have to use a temp structure variable 'params' to the inputs to csolve function in the outputs panel, could you please help me to solve this problem?
2) I find that in cvxgen folder contains a header file contains 'tic' and 'toc' function, how to use these functions in s function builder?
params.Aeq=Aeq;
params.beq=beq;
params.Aineq=Aineq;
params.bineq=bineq;
params.Smat=Smat;
params.Wmat=Wmat;
params.alpha=alpha;
[vars, status] = csolve(params)
y0=vars.x;
converge=status.converge;
for the attached files please see here
First some background information that you should know:
Matlab and C work completely differently and use different kinds of data types. To call C code from Matlab, so called "mex-functions" are generated. Matlab uses a special data type named mxArray to exchange data between Matlab and these "mex-functions", which are written in C.
In the C program an element (for example a variable) of the type mxArray represents a Matlab value of any data type. Matlab provides some functions (like mxGetData()) to access the actual data of the Matlab data element from the C function: There is some function for checking if the mxArray represents a floating-point value or a string. Another function allows you to convert the value from mxArray to double if the element has a floating-point value.
[vars, status] = csolve(params)
This means you want to call a "mex-function" from an "S-function".
Theoretically, this is possible but it is not as easy as you think:
First of all, the entry point of both types of functions is named mexFunction() in the C code. This means you cannot simply combine the C codes of both functions because in this case you would have two functions with the same name (mexFunction) in your S-function.
You might call the function mexCallMATLAB; however Mathworks writes that this function should not be called from S-functions.
The other possibility would be loading the mex-function using DLL functions (in Windows: LoadLibrary, GetProcAddress, FreeLibrary) and call the function mexFunction() of the mex-function using a function pointer.
However, in this case you have to convert all C data types to mxArray data and the data returned from the mex-function must be converted back ...
... a TLC file that is needed in ... embedded coder
The functions that access data of the mxArray type are only available when Matlab is running.
If you generate code that shall be executable outside Matlab, you cannot use mxArray and therefore you cannot call mex-functions.
The file csolve.c defines four structure variables:
Vars vars;
Params params;
Workspace work;
Settings settings;
And what the file actually does is the following:
Read the structure params (mxArray data type), convert these content to C data types and write the data into the four structure variables above
Call the following code:
steps = solve();
for (i = 0; i < extra_solves; i++)
solve();
The function solve() is defined in the other .c files in the project.
Take the values from the four structure variables and the value step returned by solve() and convert the data to mxArray.
Return the result as [vars, status]
You can define the four variables in your S-function code, fill these structures the same way the file csolve.c does it, call the solve() function as it is shown above and read the data of vars and status directly from the four variables.
You remove csolve.c from your project and add the other .c files of your mex-function to the S-function.
Related
Problem Statement: I am trying to write MATLAB code for a main caller function (like run_experiment below) to specify which computations I want to execute where computations are made sequentially using other MATLAB functions. Those other functions are to be evaluated based on parameters passed with the main caller function. The said functions used in computations are to be specified with name of the scripts they are written in.
Example Desired Code Behavior: For example, a command like the following should run the preprocess_data, initialise_model and train_model scripts.
>> run_experiment('dataset_1_options', '|preprocess_data|initialise_model|train_model|');
And this command should run only the train_model script but also evaluates its performance:
>> run_experiment('dataset_1_options', '|train_model|evaluate_model|');
In the above examples "|" is used as a delimiter to specify separate function names to be evaluated. Those functions use the options specified with dataset_1_options. Please do not focus on how to separate that part of the input into meaningful function names; I know how to do it with strsplit.
Constraints and Specifications: The function names to be passed as input to the main caller function are NOT anonymous functions. The purpose is to be able to pass such multiple function names as input AND to evaluate them with the options like the above example. They return output to be evaluated in other parts of the research code (i.e. passing data matrices to other functions within the research code as results of the computations carried out within them.)
Question: Given the desired behavior and constraints mentioned above, can anybody help in how to pass the separate function names from another caller function along with options/parameter to those functions? How should the main caller function evaluate the function names passed in as input with the options specified during the call?
Thank you in advance.
You can pass functions to functions in matlab. You just need to use the # sign when you pass it. In your case it would be run_experiment('dataset_1_options', #train_model) inside a script. You could keep your options in a cell array or something. The run_experiment function would just be a regular function,
function [output] = run_experiment(options, train_model, ...);
train_model(options{1}, ...)
.
.
.
end
What you need to do this is create a cell array with your function names and another array with the corresponding options as below
% Function name array
fn_array = {#fn_1, #fn_2, ...};
% Option array
option_array = {{fn1_opt1, fn2opt2, ...}; {fn2_opt1, fn2_opt2, ...};, ...};
These two need to be passed to your run_experiment function which will evaluate them as below
function run_experiment(fn_array, option_array)
num_fn = length(fn_array); %Finds number of functions to evaluate
for ii = 1:num_fn %Evaluates each function
fn_array{ii}(option_array{ii}{:});
end
MATLAB allows overloading various operators for custom classes. One of the unlisted overloadable operators is end, as can be learned from \matlab\lang\end.m:
% END(A,K,N) is called for indexing expressions involving the object A
% when END is part of the K-th index out of N indices. For example,
% the expression A(end-1,:) calls A's END method with END(A,1,2).
An example of such a method is table.end (paste in the MATLAB command line and press "Open Selection" to go to its definition; it is defined in ...\matlab\datatypes\#tabular\end.m).
Unlike a normal method, one cannot simply write hEnd = #end, because this gives the error:
>> hEnd = #end;
hEnd = #end;
↑
Error: Illegal use of reserved keyword "end".
On the other hand, writing e = str2func('end'); works, but it links to the default end function (even when temporarily switching to the folder where the desired end.m is found).
Failed attempts include str2func('table>end');, str2func('table\end');, str2func('table.end'); and #(a,b,c)table.end(a,b,c);.
My question: How do I create a handle to the end function of a specific class?
Overloading — If the function you specify overloads a function in a class that is not a fundamental MATLAB class, the function is not associated with the function handle at the time it is constructed. Instead, MATLAB considers the input arguments and determines which implementation to call at the time of evaluation.
Function handles store their absolute path, so when you have a valid handle, you can invoke the function from any location. You do not have to specify the path to the function when creating the handle, only the function name.
so if your 'end' function is in matlab path , matlab consider it as a candidate for evaluation depending on the inputs,in your case if input object is of 'table' class type the feval(str2func('end'),i,j) evaluate the end function which is defined in the folder #table/end.m
Maybe it's a basic question but here I go. I would like to have a .m with all the functions that will be accessed by other scripts and functions.
I tried just doing a script with all the functions and call it in other functions code.
And I got and error. Could you please explain me how can I solve this?
I'm trying this, which gives me no error, and does what I want it to do, still, is it a good way to do it? Any suggestions?
function PruebasLlamaFuncion
funcionFEM=#PruebasTodasFunciones;
a=funcionFEM('OVERPOWER',1,5)
b=funcionFEM('POWEROVERWELMING',2)
end
...
function a=f(nombre,varargin)
f=str2func(nombre)
a=f(varargin{1:end});
end
function d=OVERPOWER(J,c)
d=J*c;
end
function e=POWEROVERWELMING(J)
e=J;
end
Function placement
Matlab, unlike a number of other languages, permits a single file to contain only one main function that is visible to the rest of the system. The main function is the first function. (Documentation)
Any functions that are defined after the main function body are called local functions. These functions each create their own separate workspace (scope) and can be called by one another and, of course, by the main function.
Any functions that are defined within the main function body are called nested functions. These functions have their own workspace but are also able to access and change the variables of their parent function under certain conditions. Nested functions at the same nesting level can call each other and local functions, but local functions cannot call nested functions since they are out of scope.
Workarounds
There are several options available to you depending on how you would like to proceed.
At the risk of giving too many options but desiring to be exhaustive, I'll put the list from what I would do first to what I would do last.
For most things, I would recommend 1 or 2.
The other options are more for creating libraries/APIs, but I included them to show what can be done.
Define Function1 and Function2 in separate m-files on the Matlab path or in the present working directory to call them normally.
Wrap the main body of your work (the one calling the functions) in a function itself and define the other functions as local functions or nested functions. Example:
function output = main(a,b,c)
Result=Function1(a,b,c);
Result2=Function2(b,d);
...
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
You can get a bit more fancy and have a function that returns function handles (pointers) to the local or nested functions and then use the (in the example) struct to call the functions in another script:
function Functions = GetFunctions()
Functions.F1 = #(a,b,c) Function1(a,b,c);
Functions.F2 = #(a,b) Function2(a,b);
% You can define Function1 and Function2 here for nested functions
end
% Or you can define Function1 and Function2 here for local functions
If you have R2013b or above, you can do the same thing as above using the localfunctions function to create a cell array of handles to all local functions (in this case, the definitions are required to be outside the main function body).
function Functions = GetFunctions()
Functions = localfunctions(); % R2013b+ only
end
% Define Function1 and Function2 here for local functions
You can also create a class with static functions:
classdef Functions
methods(Static)
% Define Function1 and Function2 here and call them just like the struct above.
end
end
I hope that makes sense and hopefully helps.
I think you're misunderstanding something. A script is for calling a series of functions/other scripts in sequence. If you just want your functions to be accessible in other code, you only need to make sure they're on the path. You would never need a "script containing all the functions". You may be thinking of local functions, but these are the exact opposite of what you want (they can't be called from outside the function where they're defined or other local functions in the same file).
e.g. if Function1 and Function2 are on your path, you could write a script like this, perhaps as a demo for how to use those two functions:
a = 0;
b = 1;
c = 2;
d = 'Unicorns';
Result=Function1(a,b,c);
Result2=Function2(b,d);
It does not and should not have any function definitions in it. If your script can't find the functions, use addpath (see docs), to put the folder where these function files reside into your path. The m files should be given the same name, e.g. the following needs to go in a file called myfunc.m
function result = myfunc(a,b,c)
Functions in your working directory can also be called even if that directory isn't on your path.
I have a file funcs.m that stores anonymous functions. They must be usable by the files in the directory where it is. Currently, I use the anonymous functions so that I execute the file funcs.m in different files but I think this is a a wrong way of doing things. The other functions such as main.m and its nested function nest.m need to use the anonymous functions from funcs.m. I think paths won't solve this problem because the files are in the same folder. Basically I could solve this problem by copy-pasting the anonymous functions to every file but code-smell so:
Is there some way of reusing the funcs.m having the anon functions in Matlab?
Example
main.m
function main
funcs; % loads the anonymous functions
nest(par1,...,parN)
end
nest.m
function nest(par1,...,parN)
funcs; %ERRR: This fires err, why? Look: this was sourced already in main.m!
function neededOnlyHere(par100)
bq(q,A) %This needs the functions of the funcs
end
neededOnlyHere(somePar) %ERR to use the anon funcs from funcs
end
Functions main.m and nest.m use this function funcs.m having the anonymous funcs
bq=#(q,A) q*A; %Bolded q
I=#(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0);
AiNotj=zeros(1,Ncut);
...
ERROR
Attempt to add "bq" to a static workspace.
See MATLAB Programming, Restrictions on
Assigning to Variables for details.
Error in funcs (line 10)
bq=#(q,A) q*A;
%Bolded q
Why it's breaking
You get the error when calling it in nest.m because having a nested function makes its enclosing function's workspace a "static workspace"; that is, variable names cannot be added via eval(), assignin(), or other "dynamic" techniques; only variables that are explicitly assigned in that function's text are allowed. Evaluating a script to define local variables - which is what you're doing when calling funcs.m - is "dynamic", so prohibited in functions with nested functions. It works in main.m because main has no nested functions and is thus a "dynamic" workspace.
There are a couple ways you could change it to work with static workspaces and nested functions. The first thing to ask is whether you really need to make them anonymous functions?
Using package functions instead
If you don't need them to be anonymous functions per se, just break them out and put each one as a regular function in its own .m file; e.g. bg.m, I.m, AiNotj.m, and so on. Then they're all available to all other functions in that directory.
If that turns in to a mess of files, or if you want to scope them and maybe make them available only to the selected functions that really need them (that is, the functions currently calling funcs()), then you can stick them in a package. Create a subdirectory called +myfuncs and move all the little function files in there; e.g. +myfuncs/bq.m, +myfuncs/I.m, +myfuncs/AiNotj.m. (The + prefix tells Matlab the directory is a package.) Then you can pull all of them in to your function scope by doing import myfuncs.* as a direct replacement for where you're currently calling funcs().
function nest(par1,...,parN)
import myfuncs.*;
function neededOnlyHere(par100)
bq(q,A) % This will work, resolving to myfuncs.bq
end
You can do the import myfuncs.* from the command line to make them available interactively, too.
This is probably how Matlab itself wants you to organize clusters of related functions like this, and would be my first approach. It's the least "smelly" IMHO. If you really wanted to be able to edit them all in a single file like funcs.m for convenience, you could write a little code munger in Perl or whatever that parsed funcs.m and output them all as equivalent individual functions as a preprocessing step. (I think it's a bit of a bummer that you can't define multiple top-level functions in an M-file like this, but oh well.)
If you really need to work with anonymous functions, there are some workarounds.
Passing functions in a struct
You can change your funcs() function to actually return a struct of all those anonymous functions, using field names instead of local variable names.
function out = funcs
out.bq=#(q,A) q*A; %Bolded q
out.I=#(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0);
out.AiNotj=zeros(1,Ncut);
For this, you'd have to prefix all the function references with the struct name you're holding them in. Don't know how big a deal this is for you.
function nest(par1,...,parN)
fs = funcs;
function neededOnlyHere(par100)
fs.bq(q,A) %This needs the functions of the funcs
end
Preallocating variables
To get funcs() to work as-is, you can statically pre-allocate variables with all the function names you're going to use, so the Matlab parser recognizes them as statically assigned variables. Then when you call funcs(), it will re-assign the values of the existing variables, which is permissible in dynamic workspaces.
function nest(par1,...,parN)
[bq, I, AiNotj] = deal(); % Preallocate all names from funcs
funcs;
function neededOnlyHere(par100)
bq(q,A) %This needs the functions of the funcs
end
This would be a bit of a pain, because you'd have to re-edit every file that uses funcs whenever a new function name is added. You could at least write a little perl script to auto-generate that line of code by parsing funcs.m and outputting a "[bg, I, AiNotj,...] = deal();" with all the functions it finds, and you can just copy that in to your code.
Another way to do this would be to have funcs actually return all the functions in its output list. This would have the benefit of continuing to work even as you add new functions to funcs.m, as long as you don't remove or change the order of your existing anonymous functions.
function [bg,I,AiNotj] = funcs()
bg = ...
I = ...
% And then in the calling functions:
[bg,I,AiNotj] = funcs(); % which you can copy and paste from funcs.m's header
There are many ways of passing anonymous functions:
1) Pass the function itself:
function main
f = #(t) t^2 - 3;
param = randn(12,1);
g = test22(param,f);
disp (g)
end
function g = test22(param,f)
g = f(param(2));
disp(param(2))
end
2) Use globals (which usually should be avoided in complex code)
function main
global f
f = #(t) t^2 - 3;
param = randn(12,1);
g = test22(param);
disp (g)
end
function g = test22(param)
global f
g = f(param(2));
disp(param(2))
end
I have an enum like this:
classdef(Enumeration) bla_type < int32
enumeration
bla_one(1)
bla_2(2)
end
end
I can get the 'string representation of an element' like this:
char(bla_type.bla_one)
=>
bla_one
Unfortunately, matlab coder does not like this. Are there any alternatives?
There's no elegant built-in way in Coder to do this; the enumerated type becomes a standard enum in C, and the enumeration function in MATLAB is unavailable in Coder. The simplest, but unpleasant, way to do it is to create a function with a switch statement with the manually populated string names. It's not nice, since now you have to maintain the names in two places.
However, one way that does work nicely is to use one of the more powerful features of Coder: coder.const.
The solution is to have a function that creates a table of the enumeration members and their values. This function itself cannot be compiled, but rather is called during compilation to build a lookup table in the resulting C code. We can use this lookup table in a Coder compatible function to get the data.
Imagine we have an enumerated type like this (in someenum.m):
classdef someenum < int32 %#codegen
enumeration
First_thing (0)
Second_thing (2)
Another_thing (3)
No_thing (4000)
end
end
We also then have the build-time function called 'buildsomeenum2name.m':
function [namearray, memberidx] = buildsomeenum2name
%BUILDSOMEENUM2NAME Compile-time creation of lookup table for someenum
% THIS FUNCTION IS NOT CODER COMPATIBLE, BUT IS CALLED DURING COMPILE
% TO CREATE A LOOKUP TABLE.
[members, names]=enumeration('someenum');
maxlen = 0;
for i=1:numel(names)
maxlen = max(maxlen, numel(names{i}));
end
namearray = char(zeros(numel(names), maxlen));
for i=1:numel(names)
namearray(i, 1:numel(names{i})) = names{i};
end
memberidx = int32(members); %#ok<NASGU>
end
When buildsomeenum2name is called in MATLAB, it creates an array of string names of all the members of the enumerated type and another vector list of their numeric values in the same order.
Here's the cool part. MATLAB Coder can evaluate functions at build time and turn them into constants. These constants become literals in the resulting C code, rather than actual code. Since the functions are evaluated at build time, the enumeration information is put into a nice table, therefore if we make a Coder-compatible lookup function, we can use it to convert the member types into a string. We'll call this function 'someenum2name.m':
function name = someenum2name(enum) %#codegen
%SOMEENUM2NAME Get the string name of an enumerated type
% The following line loads namearray and memberidx with constant arrays
coder.extrinsic('buildsomeenum2name');
[namearray, memberidx] = coder.const(#buildsomeenum2name);
% First find the index of the enumerated type in the memberidx vector
index = find(memberidx==int32(enum));
if isempty(index)
name = 'UNKNOWN';
return;
end
name = deblank(namearray(index,:));
end
This function uses the coder.const command to evaluate buildsomeenum2name at compile time and create the lookup tables. We have to instruct Coder not to try to compile buildsomeenum2name, so use the coder.extrinsic command to tell it to ignore the function. Then someenum2name can look up the index for the string and pull it out (deblank is used because the strings in the array have trailing 0's that need to be pulled out.) The function someenum2name can be called both within MATLAB and in Coder compiled code.
This method keeps everything in-sync, so if you ever add a new member to the enum or rearrange them, the coder.const function will make sure that the values are rebuilt in the output code so that someenum2name works.
At the command line, this looks like:
>> someenum2name(someenum.No_thing)
ans =
No_thing
Try [~,s]=enumeration('bla_type'). You get a cell array of strings containing the name of elements in s. So bla_one will be in s{1}. Don't know whether that is supported by MATLAB coder though.