I have a code in which I create a large number of the same variable and I would like to store all of its values. Normally I would use for loops for this and store all of them, but due to some complications it is not possible at the moment.
I have to calculate the variable x, store it as x1. Calcute the x with different conditions and store it as x2 etc. The problem I have that I would have to manually change all the x's in my code to x2, x3, x4 etc. And there are a lot of them. Is there a way to it more efficiently?
To better illustrate:
x1 = 5*y(1);
%some calculations with y
x2 = 5*y(2);
% some claculations with y
x3=5*y(3);
If you are really desperate you could use eval and loop through all of your variable names, assuming they are numbered 1 through n.
count = 1;
while exist(['x',num2str(count)],'var')
eval(['x(count)=x',num2str(count),';'])
count = count + 1;
end
This code assumes everything is numbered x1, x2, x3, etc. It will continue looping until the next "sequential" x no longer exists. This would go at the end of whatever script or function you are running after all the declarations have happened.
Just note that storing everything the way you did initially is very frowned upon. It makes code hard to read and cumbersome, and it not very dynamic.
Either way, the code above should do the trick.
You could also write a regular expression to replace all xn and whatever instances to x(n).
Just run the following lines of code, giving it the file name you want to convert, and boom it will handle all of the replacement for you
fileName = 'findReplace.m';
replaced = regexprep(fileread(fileName),'x([0-9]+)','x($1)');
fh = fopen(fileName,'w');
fprintf(fh,replaced);
fclose(fh);
Related
I have an external function that I require to call at most twice during the simulation. It has a large output of size Real[n][m][k] where n, m, and ks product is a relatively large integer. I call the function inside a when statement. The issue I have is that the output of the function is copied over and over in .mat file for each iteration and causes it to be really large even though I use the output infrequently. I wonder if there is a way to store the output only once and avoid storing the copies of the output in the results file for each time step.
P.s. If that is not possible I might try to store the results of the function in another file, but need to use them in the simulation. So as an alternative is there also a way to make the simulation ignore storing a variable in the results file.
I don't think there is a way to store a subset of variables only at certain points in time.
Select variables
What can be done is using HideResult to avoid storing them in the result file. They can still be used in the simulation though. As an example:
model HideRes
Real y1 annotation(HideResult=true);
Integer y2;
parameter Real x1 = 1;
parameter Real x2 = 2 annotation(HideResult=true);
equation
when time > 0.1 then
y1 = sin(x1);
elsewhen time > 0.2 then
y1 = sin(x2);
end when;
y2 = 10*integer(y1);
end HideRes;
In the above code, y1 and x2 will not be shown in the result file.
Protect variables
As an alternative to the above (thanks Hans O. for pointing at this) it is also possible to use protected variables. By default, they will not be stored in the result file. Additionally, they will not be accessible from higher levels of hierarchy in the model itself. Also parameters will not show up in the parameter dialog.
Below is the same example with protected applied (the parameter x2 cannot be modified from the outside).
model HideRes
Integer y2;
parameter Real x1 = 1;
protected
Real y1;
parameter Real x2 = 2;
equation
when time > 0.1 then
y1 = sin(x1);
elsewhen time > 0.2 then
y1 = sin(x2);
end when;
y2 = 10*integer(y1);
end HideRes;
Chose timing
Some simulators also offer the possibility to store only at defined events. For Dymola, this would e.g. be:
when x > 0 then
Dymola.Simulation.TriggerResultSnapshot();
end when;
Note: it stores all variables, not just a subset.
I have been trying to make a loop for 3 variables that must add 1 to each other, but these variables must change in intervals of 0.1, as long as, they do not exceed the sum of 1.
In addition, I have also been trying to make another loop to export each combination of the variables in a separate CSV file.
I have tried several ways, but to no success..
It would be very helpful if you could solve it. Thanks
function f = MultipleMax(w,mu,sigma)
sum = 0;
zero = 1e-9;
n = length(w);
for i=1:length(w)
if w(i) > zero
sum = sum - w(i) * log(w(i));
end
end
f(1) = -(x)*(w * mu') + (y)*(sqrt(w*sigma*w')) + (z)*exp(sum) ;
end
As you can see in the f(1), the 3 variables are x, y, and z, then they must add 1. So, I need to create a loop that combines each of these variables in changes of 0.1 each.
the other part of my problem is that, I export the tables with this code, T is the name of the table:
writetable(T,'Nombre.csv');
Then, for each combination that I loop the variables above, I must export a file from each table. But I have not had any results with the functions I use.
If you have any answer it would be of great help, thank you.
It seems as though you're looking for something like this.
for x = 0:0.1:1
for y = 0:0.1:1
z = 1-x-y
...
end
end
Regarding the file name, it sounds like you need a separate file for each combination of x,y,z. One way to achieve this is to include the values of x,y,z as part of the file name. For instance:
writetable(T,sprintf('Nombre-x-%.1f-y-%.1f.csv',x,y))
This includes the values of x and y as part of the file name. To find z, use the fact that x+y+z=1.
I am writing a code that generates a function f in a loop. This function f changes in every loop, for example from f = x + 2x to f = 3x^2 + 1 (randomly), and I want to evaluate f at different points in every loop. I have tried using subs, eval, matlabFunction etc but it is still running slowly. How would you tackle a problem like this in the most efficient way?
This is as fast as I have been able to do it. ****matlabFunction and subs go slower than this.
The code below is my solution and it is one loop. In my larger code the function f and point x0 change in every loop so you can imagine why I want this to go as fast as possible. I would greatly appreciate it if someone could go through this, and give me any pointers. If my coding is crap feel free to tell me :D
x = sym('x',[2,1]);
f = [x(1)-x(1)cos(x(2)), x(2)-3x(2)^2*cos(x(1))];
J = jacobian(f,x);
x0 = [2,1];
N=length(x0); % Number of equations
%% Transform into string
fstr = map2mat(char(f));
Jstr = map2mat(char(J));
% replace every occurence of 'xi' with 'x(i)'
Jstr = addPar(Jstr,N);
fstr = addPar(fstr,N);
x = x0;
phi0 = eval(fstr)
J = eval(Jstr)
function str = addPar(str,N)
% pstr = addPar(str,N)
% Transforms every occurence of xi in str into x(i)
% N is the maximum value of i
% replace every occurence of xi with x(i)
% note that we do this backwards to avoid x10 being
% replaced with x(1)0
for i=N:-1:1
is = num2str(i);
xis = ['x' is];
xpis = ['x(' is ')'];
str = strrep(str,xis,xpis);
end
function r = map2mat(r)
% MAP2MAT Maple to MATLAB string conversion.
% Lifted from the symbolic toolbox source code
% MAP2MAT(r) converts the Maple string r containing
% matrix, vector, or array to a valid MATLAB string.
%
% Examples: map2mat(matrix([[a,b], [c,d]]) returns
% [a,b;c,d]
% map2mat(array([[a,b], [c,d]]) returns
% [a,b;c,d]
% map2mat(vector([[a,b,c,d]]) returns
% [a,b,c,d]
% Deblank.
r(findstr(r,' ')) = [];
% Special case of the empty matrix or vector
if strcmp(r,'vector([])') | strcmp(r,'matrix([])') | ...
strcmp(r,'array([])')
r = [];
else
% Remove matrix, vector, or array from the string.
r = strrep(r,'matrix([[','['); r = strrep(r,'array([[','[');
r = strrep(r,'vector([','['); r = strrep(r,'],[',';');
r = strrep(r,']])',']'); r = strrep(r,'])',']');
end
There are several ways to get huge boosts in speed for this sort of problem:
The java GUI front end slows everything down. Go back to version 2010a or earlier. Go back to when it was based on C or fortran. The MATLAB script runs as fast as if you had put it into the MATLAB "compiler".
If you have MatLab compiler (or builder, I forget which) but not the coder, then you can process your code and have it run a few times faster without modifying the code.
write it to a file, then call it as a function. I have done this for changing finite-element expressions, so large ugly math that makes $y = 3x^2 +1$ look simple. In that it gave me solid speed increase.
vectorize, vectorize, vectorize. It used to reliably give 10x to 12x speed increase. Pull it out of loops. The java, I think, obscures this some by making everything slower.
have you "profiled" your function to make sure that "eval" or such are the problem? If you fix "eval" and your bottleneck is elsewhere then you will have problems.
If you have the choice between eval and subs, stick with eval. subs gives you a symbolic solution, not a numeric one.
If there is a clean way to have multiple instances of MatLab running, especially if you have a decently core-rich cpu that MatLab does not fully utilize, then get several of them going. If you are at an educational institution you might try running several different versions (2010a, 2010b, 2009a,...) on the same system. I (fuzzily) recall they didn't collide when I did it. Running more than about 8 started slowing things down more than it improved them. Make sure they aren't colliding on file access if you are using files to share control.
You could write your program in LabVIEW (not MathScript, not MatLab) and because it is a compiled language, there are times that code can run 1000x faster.
You could go all numeric and make it a matrix activity. This depends on your code, but if you could randomly populate the columns in the matrix then matrix multiply it to a matrix $ \left[ 1, x, x^{2}, ...\right] $, that would likely be several hundreds or thousands of times faster than your current level of equation handling and still in MatLab.
About your coding:
don't redeclare "x" as a symbol every loop, that is expensive.
what is this "map2mat" then "addPar" stuff?
the string handling functions are horrible for runtime. Stick to one language. The symbolic toolbox IS maple, and you don't have to get goofy hand-made parsing to make it work with the rest of MatLab.
I am implementing the adaptive Simpsons method in Matlab recursively. I wish to store all of the points where function evaluations take place to generate a histogram after integrating. I currently have:
function [S, points] = adsimp(f, a, b, fv, tol, level, points)
...
d = (a+b)*0.25;
e = (a+b)*0.75;
points = [points, d, e];
...
Thus, for every function call, I am increasing the length of points by two. My understanding of Matlab's function input/output scheme is poor. I'd like to know:
1) When the input and output share a variable name, does this use a single variable, or is a local copy made and then returned?
2) If it is a copy, is there a way to pass points by reference and preallocate sufficient memory?
To answer your first question, see here. Most MATLAB variables are passed by value (matrices, etc.) unless it is a handle object (function handle, axis handle etc.) A local copy of an input variable is made only if that variable is altered in the function. ie.
function y = doTheFunc1(x)
x(2) = 17;
y = x;
a copy must be made. As opposed to:
function y = doTheFunc2(x)
y = x(1);
where no copy need be made inside the function. In other words, MATLAB is a "copy on write" language. I am almost certain this is true regardless what your output variable output name is (ie. this holds even if your output and input are both named x).
To answer your second question, look at the first answer here. Consider using a nested function or a handle object.
I have recently started learning MatLab, and wrote the following script today as part of my practice to see how we can generate a vector:
x = [];
n = 4;
for i = i:n
x = [x,i^2];
end
x
When I run this script I get what I expect, namely the following vector:
x = 0 1 4 9 16
However, if I run the script a second time right afterwards I only get the following output:
x = 16
What is the reason for this? How come I only get the last vector entry as output the second time I run the script, and not the vector in its entirety? If anyone can explain this to me, I would greatly appreciate it.
Beginning with a fresh workspace, i will simply be the complex number 1i (as in x^2=-1). I imagine you got this warning on the first run:
Warning: Colon operands must be real scalars.
So the for statement basically loops over for i = real(1i):4. Note that real(1i)=0.
When you rerun the script again with the variables already initialized (assuming you didn't clear the workspace), i will refer to a variable containing the last value of 4, shadowing the builtin function i with the same name, and the for-loop executes:
x=[];
for i=4:4
x = [x, i^2]
end
which iterates only one time, thus you end up with x=16
you forget to initialize i.
after first execution i is 4 and remains 4.
then you initialize x as an empty vector but because i is 4 the loop runs only once.
clear your workspace and inspect it before and after first execution.
Is it possibly a simple typo?
for i = i:n
and should actually mean
for i = 1:n
as i is (probably) uninitialized in the first run, and therefore 0, it works just fine.
The second time, i is still n (=4), and only runs once.
Also, as a performance-tip: in every iteration of your loop you increase the size of your vector, the more efficient (and more matlaboid) way would be to create the vector with the basevalues first, for example with
x = 1:n
and then square each value by
x = x^2
In Matlab, using vector-operations (or matrix-operations on higher dimensions) should be prefered over iterative loop approaches, as it gives matlab the opportunity to do optimised operations. It is also often more readable that way.