Separate definition of constant values and dependent parameters in Matlab - matlab

In my code, I have a lot of constant values and parameters that take significant space in my code.
For example in C++, I would make a header and a separate file where I would define these parameters as, e.g., "const-type" and share the header with main or other .cpp files.
How do you keep such structuring in MATLAB, is it worth it?
An example: Coefficients.m looks as follows:
classdef coefficients
properties(Constant)
% NIST data
A_N = 28.98641;
end
end
Another file: Gas.m where I would like to use A_N looks as follows:
function Gas()
clear all
clc
import Coefficients.* % Does not work
% A simple print
Values.A_N % Does not work
coefficients.A_N % Does not work
Constant.A_N % Does not work
end

Ok so assuming the class coefficients defined as:
classdef coefficients
properties(Constant)
% NIST data
A_N = 28.98641;
end
end
This code must be saved in a file named coefficients.m (The class name and file name have to match to avoid weird effect sometimes).
Then assuming the following Gas.m file:
function Gas()
% Usage with "disp()"
disp('The A_N coefficient taken from NIST data is:')
disp(coefficients.A_N)
% Usage with fprintf
fprintf('\nFrom NIST data, the coefficient A_N = %f\n',coefficients.A_N)
% Usage in calculation (just use it as if it was a variable/constant name
AN2 = coefficients.A_N^2 ;
fprintf('\nA_N coefficient squared = %.2f\n',AN2)
% If you want a shorter notation, you can copy the coefficient value in
% a variable with a shorter name, then use that variable later in code
A_N = coefficients.A_N ;
fprintf('\nA_N coefficient cubed = %.2f\n',A_N^3)
end
Then running this file (calling it from the command line) yields:
>> Gas
The A_N coefficient taken from NIST data is:
28.98641
From NIST data, the coefficient A_N = 28.986410
A_N coefficient squared = 840.21
A_N coefficient cubed = 24354.73
Or if you simply need to access the coefficient in the Matlab console:
>> coefficients.A_N
ans =
28.98641
Now all these examples assume that the class file coefficient.m is visible in the current Matlab scope. For Matlab, it means the file must be in the MATLAB search path (or the current folder works too).
For more info about what is the Matlab search path and how it works you can read:
What Is the MATLAB Search
Path?
Files and Folders that MATLAB
Accesses
In your case, I would make a folder containing all these sorts of classes, then add this folder to the Matlab path, so you never have to worry again about individual script, function or program calling for it.

See this link for tips on using a class definition for this. Highlights of the tips are:
Properties can be accessed directly to get the value
Properties can be added that give the units of the constant (highly advised!)
Comments can be added that act as help text for the constants
The doc command automatically creates a reference page for this classdef
E.g.,
classdef myconstants
properties(Constant)
% g is the gravity of Earth
% (https://en.wikipedia.org/wiki/Gravity_of_Earth)
g = 9.8;
g_units = 'm/s/s';
% c is the speed of light in a vacuum
c = 299792458;
c_units = 'm/s';
end
end
>> help myconstants.g

Related

Speed-up mex files in Matlab

I have a big loop that I need to compute many times in my code and I thought that it would be possible to speed it up using MATLABcoder. However, the mex file version of my code (the code for the function is attached below) ends up being slower than the m-file. I compiled the code using MINGW64 compiler.
I tried different compiler settings (played with coder.config) and different memory specifications but without any success.
function v_d = test_code(q,v_exp,wealth,b_grid_choice,k_grid_choice,nz,nk,nb)
%#codegen
% Inputs
% q is an array of dimension [nz nk nb]
% v_exp is an array of dimension [nz nk nb]
% wealth is an array of dimension [nz nk nb]
% b_grid_choice is an array of dimension [nk nb]
% k_grid_choice is an array of dimension [nk nb]
% Typically, nz/nk/nb is an integer (currently up to 200)
v_d = coder.nullcopy(zeros(nz,nk,nb));
parfor ii = 1:nz
q_ini_ii = reshape(q(ii,:,:),[],nz);
v_ini_exp_ii = reshape(v_exp(ii,:,:),[],nz);
choice = q_ini_ii.*b_grid_choice - k_grid_choice;
for jj = 1:nk
for kk = 1:nb
% dividends at time t
d = wealth(ii,jj,kk) + choice;
% choosing optimal consumption
vec_d = d + v_ini_exp_ii.*(d>0);
v_d(ii,jj,kk) = max(vec_d,[],'all');
end
end
end
When I run this code when nz=nk=nb=100, the m-file takes 2.5s while the generated mex file takes 7.5s. I tried using both MATLABcoder app as well as the codegen command
codegen -O enable:OpenMP test_code -args {q,v_exp,wealth,b_grid_choice,k_grid_choice,nz,nk,nb}
I also played with codegen.config('mex') but with little impact on the performance.
When I test the speed of the above code I simply generate these matrices using randn command and then pass them into the code. Interestingly, when I generate these matrices inside the function then this has no effect on the speed of the m-file but speeds-up the mex file almost 10 times (so three times faster than the m-file)! This suggests to me that there is a way to speed up that code, but despite my effort I couldn't figure it out. I thought that memory allocation could be behind it, but my attempts with playing with dynamic memory specifications did not lead to any gains either...

How do I resolve name conflict in MATLAB?

I created a GUI called "stack" in MATLAB. It has a .m file associated with it. This GUI is called on multiple occasions by another GUI in the same folder.
Now I discovered that "stack" is a built-in function in MATLAB which I need to use for something else in the same working directory. All calls to the stack function somehow invoke the GUI by calling the stack.m script.
I do not want to rename this because it is used in many places.
Is there a way to use the built-in function without needing to rename? Some way to reference the function and the script separately?
Disclaimer: Please, please, please, do not do this.
Assuming that your own stack.m is only in the search path because it is in the current folder, then the easiest fix is to create some dummy subfolder, navigate to it, execute Matlabs stack function (which is the only stack in the current searchpath) and navigate back.
Here I have exemplified it with magic:
function a= magic
n=5;
cd dummy
a= magic(n);
cd ..
where dummy is the name of the subfolder.
A slight modification of Nicky's answer for the sake of repeatability: before navigating to the map where your stack.m GUI is stored, run
builtinStack = #stack();
which creates a function handle. This way you can call builtinStack() like the MATLAB function is supposed to be called, without having to cd out of the directory every time you want to use it.
The use of builtin, as suggested by hoki doesn't work, since built-in functions are defined as
...Functions such as "ind2sub", "sub2ind", etc. are not MATLAB built-in functions.... Those functions that are shipped with MATLAB but are not defined as built-in functions can be referred to as "MATLAB functions" ...
As answered by MathWorks Technical Support. This means that functions like stack aren't built-in in the sense that they are build in a different language, compiled and then called from MATLAB, but are actually written in MATLAB and are shipped with the release. The main way to check this is typing edit <functionname>; when showing only comments the function is a built-in as defined by TMW, when it shows MATLAB code as well, like stack, it's not a built-in as per the above definition.
An example of a built-in function is sum, whose associated .m-file looks as follows:
%SUM Sum of elements.
% S = SUM(X) is the sum of the elements of the vector X. If X is a matrix,
% S is a row vector with the sum over each column. For N-D arrays,
% SUM(X) operates along the first non-singleton dimension.
%
% S = SUM(X,DIM) sums along the dimension DIM.
%
% S = SUM(...,TYPE) specifies the type in which the
% sum is performed, and the type of S. Available options are:
%
% 'double' - S has class double for any input X
% 'native' - S has the same class as X
% 'default' - If X is floating point, that is double or single,
% S has the same class as X. If X is not floating point,
% S has class double.
%
% S = SUM(...,NANFLAG) specifies how NaN (Not-A-Number) values are
% treated. The default is 'includenan':
%
% 'includenan' - the sum of a vector containing NaN values is also NaN.
% 'omitnan' - the sum of a vector containing NaN values
% is the sum of all its non-NaN elements. If all
% elements are NaN, the result is 0.
%
% Examples:
% X = [0 1 2; 3 4 5]
% sum(X, 1)
% sum(X, 2)
%
% X = int8(1:20)
% sum(X) % returns double(210), accumulates in double
% sum(X,'native') % returns int8(127), because it accumulates in
% % int8 but overflows and saturates.
%
% See also PROD, CUMSUM, DIFF, ACCUMARRAY, ISFLOAT.
% Copyright 1984-2015 The MathWorks, Inc.
% Built-in function.
i.e. it can also be seen from the last line that this is a built-in as per definition. Note that everything contained in the first 'comment' is seen when help sum is typed; in the sense that an empty line breaks the help file. The copyright and built-in information do thus not show up when simply typing help sum on the command line, so for checking whether a function is a built-in you need edit <functionname>.

Arbitrary dimension for CVXGEN program

I would like to solve a QP/LP problem in MatLab using CVXGEN. I have preference for CVXGEN over CVX, since CVXGEN is much faster. In particular, I would like to solve
min f(x) s.t. x in X
where f(x) is in quadratic form and X is compact, convex, and defined by linear functions. The size of the problem varies depending on the run. I would like to automate the procedure as much as possible. To illustrate, an example of a CVXGEN code is:
dimensions
n = 10
end
parameters
Q (n,n) psd # quadratic penalty.
end
variables
x (n)
end
minimize
quad(x, Q)
end​​​​​​​​​​​​​
​This code is inputted at cvxgen.com. On this website, I can then generate the C code which gives me a unique number. I can then compile this into MEX code using the unique number. Last, I can call this MEX code (csolve) from MatLab by running the following code
n=10; % dimension of the problem
params.Q = eye(n,n); % assume that the Hessian is the identity
[vars, status] = csolve(params); % this outputs optimal x* = 0.
This procedure, however, requires for each dimension of the problem n that I want to run, I need to go to cvxgen.com, change n, compile code, then run my MatLab code. Is it possible to let n enter as a parameter? This way, I only need to compile the code once, then in my MatLab code set params.n = n and params.Q = eye(n,n), and then call [vars, status] = csolve(params);.
In short, I do not think it is possible to specify arbitrary dimension on cvxgen.com. I do have one solution: First, in MatLab, allow the user to specify his/her email address and password for cvxgen.com. Next, using system command in MatLab, call a python or javascript program that executes the following steps:
1) Log user into cvxgen.com
2) Goto edit tab on website
3) Copy and paste the cvxgen code
4) Goto generate c tab
5) Click generate code
6) Goto matlab tab
7) Copy unique identifying number for the compiled C code to be downloaded
8) Pass the unique identifying number back to MatLab and compile the Mex files in MatLab by calling the identifying number.
Now the Mex files can be called in MatLab by the following commands:
n=10; % dimension of the problem
params.Q = eye(n,n); % assume that the Hessian is the identity
[vars, status] = csolve(params); % this outputs optimal x* = 0.

Saving a Matrix in MatLab

I have a MatLab program that generates a large 1000x1000 matrix. How can I save this matrix for use in future programs. Ideally, I want to save it as a particular variable. Here is the code that I am using.
function A = generateSPDmatrix(n)
A = rand(n,n); % generate a random n x n matrix
A = A+A';
A = A*A';
A = A + n*eye(n);
end
If you want to use it in future Matlab programs, you could do it like this:
save('A.mat', 'A');
To load, just do it like this:
load('A.mat');
% the file path is current path.
save('A.txt', 'A','-ascii');
% save to your file path
save('D:\test.txt','m','-ascii')
'D:\test.txt': file name and path
'm': your matrix
'-ascii': 8-digit ASCII format
See the matlab Help. Search the save(Save workspace variables to file) function
save(filename, variables, format) saves in the specified format: '-mat' or '-ascii'. You can specify the format option with additional inputs such as variables, '-struct' , '-append', or version.

Matlab integral function & function handles in a loop

'Outliers.m' is called from a higher level .m file. The variables are all defined in the higher level file, and set as globals for access by Outliers.m. The purpose of the code is to identify outliers using Chauvenets Criterion, and for this, I have to calculate the integral of the guassian distribution, using the Integral function and function handles. The code works and gives sensible values when I enter specific variables as a test, but I cannot get it to work in a loop. My data set is comprised of 7 individual samples, each 1x30, all of which need to be analyzed. I have had various errors, read through the guidance on Integral and function handles, but cannot seem to find the solution...Any help or guidance would be very much appreciated.... Here is my code:
n = 7
for x = 1:n
for y = 1:30
z(x,y) = abs((cc(x,y) - mastercc(1,y))/masterccstd(1,y));
xmax(x,y) = mastercc(1,y)+z(x,y)*masterccstd(1,y);
xmin(x,y) = mastercc(1,y)-z(x,y)*masterccstd(1,y);
p(x,y) = 1/(masterccstd(1,y)*(sqrt(2*pi)));
fun(x,y)= #(x,y,z) (exp(-1/2)*z(x,y).^2);
q(x,y) = integral(fun(x,y),xmin(x,y),xmax(x,y),'ArrayValued',true);
pq(x,y) = p(x,y)*q(x,y); % probability
value(x,y) = n*(1/pq(x,y));
count(x,y) = logical(value(x,y) <0.5);
badbins(x)=sum(count(x,:));
end
end
It seems like your error is caused by an invald function definition.
If you try it like this it should work:
fun = #(x,y,z) (exp(-1/2)*z(x,y).^2)
Now it can be called like this for example:
fun(1,2,magic(4))
Solution to the loop problem, courtesy Andrei Bobrov via Matlab Central, link below:
http://www.mathworks.com/matlabcentral/answers/103958#comment_177000
NB: Please note the code is not complete for the purpose I explained in the problem description, but it does solve the Loop error.