display variable value each n iterations with condition outside the loop - matlab

When I have to display the variable value every n iterations of a for loop I always do something along these lines:
for ii=1:1000
if mod(ii,100)==0
display(num2str(ii))
end
end
I was wondering if there is a way to move the if condition outside the loop in order to speed up the code. Or also if there is something different I could do.

You can use nested loops:
N = 1000;
n = 100;
for ii = n:n:N
for k = ii-n+1:ii-1
thingsToDo(k);
end
disp(ii)
thingsToDo(ii);
end
where thingsToDo() get the relevant counter (if needed). This a little more messy, but can save a lot of if testing.

Unless the number of tested values is much larger than the number of printed values, I would not blame the if-statement. It may not seem this way at first, but printing is indeed a fairly complex task. A variable needs to be converted and sent to an output stream which is then printing in the terminal. In case you need to speed the code up, then reduce the amount of printed data.
Normally Matlab function takes vector inputs as well. This is the case for disp and display and does only take a single function call. Further, conversion to string is unnecessary before printing. Matlab should send the data to some kind of stream anyway (which may indeed take argument of type char but this is not the same char as Matlab uses), so this is probably just a waste of time. In addition to that num2str do a lot of things to ensure typesafe conversion. You already know that display is typesafe, so all these checks are redundant.
Try this instead,
q = (1:1000)'; % assuming q is some real data in your case
disp(q(mod(q,100)==0)) % this requires a single call to disp

Related

Clean methodology for running a function for a large set of input parameters (in Matlab)

I have a differential equation that's a function of around 30 constants. The differential equation is a system of (N^2+1) equations (where N is typically 4). Solving this system produces N^2+1 functions.
Often I want to see how the solution of the differential equation functionally depends on constants. For example, I might want to plot the maximum value of one of the output functions and see how that maximum changes for each solution of the differential equation as I linearly increase one of the input constants.
Is there a particularly clean method of doing this?
Right now I turn my differential-equation-solving script into a large function that returns an array of output functions. (Some of the inputs are vectors & matrices). For example:
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
Here I loop through the function. The function solves a differential equation, and then returns the set of solution functions for that input parameter, and then each is appended as a row to a matrix.
There are a few issues I have with my method:
If I want to see the solution to the differential equation for a different parameter, I have to redefine the function so that it is an input of one of the thirty other parameters. For the sake of code readability, I cannot see myself explicitly writing all of the input parameters as individual inputs. (Although I've read that structures might be helpful here, but I'm not sure how that would be implemented.)
I typically get lost in parameter space and often have to update the same parameter across multiple scripts. I have a script that runs the differential-equation-solving function, and I have a second script that plots the set of simulated data. (And I will save the local variables to a file so that I can load them explicitly for plotting, but I often get lost figuring out which file is associated with what set of parameters). The remaining parameters that are not in the input of the function are inside the function itself. I've tried making the parameters global, but doing so drastically slows down the speed of my code. Additionally, some of the inputs are arrays I would like to plot and see before running the solver. (Some of the inputs are time-dependent boundary conditions, and I often want to see what they look like first.)
I'm trying to figure out a good method for me to keep track of everything. I'm trying to come up with a smart method of saving generated figures with a file tag that displays all the parameters associated with that figure. I can save such a file as a notepad file with a generic tagging-number that's listed in the title of the figure, but I feel like this is an awkward system. It's particularly awkward because it's not easy to see what's different about a long list of 30+ parameters.
Overall, I feel as though what I'm doing is fairly simple, yet I feel as though I don't have a good coding methodology and consequently end up wasting a lot of time saving almost-identical functions and scripts to solve fairly simple tasks.
It seems like what you really want here is something that deals with N-D arrays instead of splitting up the outputs.
If all of the OutputArray_ variables have the same number of rows, then the line
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
seems to suggest that what you really want your function to return is an M x K array (where in this case, K = 5), and you want to pack that output into an M x K x N array. That is, it seems like you'd want to refactor your DE_Simulation to give you something like
for i = 1:N
OutputArray(:,:,i) = DE_Simulation(Parameter1Array(i));
end
If they aren't the same size, then a struct or a table is probably the best way to go, as you could assign to one element of the struct array per loop iteration or one row of the table per loop iteration (the table approach would assume that the size of the variables doesn't change from iteration to iteration).
If, for some reason, you really need to have these as separate outputs (and perhaps later as separate inputs), then what you probably want is a cell array. In that case you'd be able to deal with the variable number of inputs doing something like
for i = 1:N
[OutputArray{i, 1:K}] = DE_Simulation(Parameter1Array(i));
end
I hesitate to even write that, though, because this almost certainly seems like the wrong data structure for what you're trying to do.

advice with pointers in matlab

I am running a very large meta-simulation where I go through two hyperparameters (lets say x and y) and for each set of hyperparameters (x_i & y_j) I run a modest sized subsimulation. Thus:
for x=1:I
for y=1:j
subsimulation(x,y)
end
end
For each subsimulation however, about 50% of the data is common to every other subsimulation, or subsimulation(x_1,y_1).commondata=subsimulation(x_2,y_2).commondata.
This is very relevant since so far the total simulation results file size is ~10Gb! Obviously, I want to save the common subsimulation data 1 time to save space. However, the obvious solution, being to save it in one place would screw up my plotting function, since it directly calls subsimulation(x,y).commondata.
I was wondering whether I could do something like
subsimulation(x,y).commondata=% pointer to 1 location in memory %
If that cant work, what about this less elegant solution:
subsimulation(x,y).commondata='variable name' %string
and then adding
if(~isstruct(subsimulation(x,y).commondata)),
subsimulation(x,y).commondata=eval(subsimulation(x,y).commondata)
end
What solution do you guys think is best?
Thanks
DankMasterDan
You could do this fairly easily by defining a handle class. See also the documentation.
An example:
classdef SimulationCommonData < handle
properties
someData
end
methods
function this = SimulationCommonData(someData)
% Constructor
this.someData = someData;
end
end
end
Then use like this,
commonData = SimulationCommonData(something);
subsimulation(x, y).commondata = commonData;
subsimulation(x, y+1).commondata = commonData;
% These now point to the same reference (handle)
As per my comment, as long as you do not modify the common data, you can pass it as third input and still not copy the array in memory on each iteration (a very good read is Internal Matlab memory optimizations). This image will clarify:
As you can see, the first jump in memory is due to the creation of common and the second one to the allocation of the output c. If the data were copied on each iteration, you would have seen many more memory fluctuations. For instance, a third jump, then a decrease, then back up again and so on...
Follows the code (I added a pause in between each iteration to make it clearer that no big jumps occur during the loop):
function out = foo(a,b,common)
out = a+b+common;
end
for ii = 1:10; c = foo(ii,ii+1,common); pause(2); end

how to create a changing variable for fsolve

i want fsolve to calculate the output for different uc each time (increasing uc by 0.001 each time). each output from fsolve should be sent to a simulink model seperatly. so i set a loop to do so, but i believe that at the currenty constellation (if it will work)will just calculate 1000 different values? is there a way to send out the values seperately?
if not, how can i create a parameter uc. that goes from 0 to say 1000? i tried uc=0:0.001:1000, but again, the demension doen't seem to fit.
how do i create a function that takes the next element of a vector/matrix each time the function is called?
best regards
The general approach to iterating over an array of values and feeding them one-by-one into a series of evaluations of a function follows this form:
for ix = 0:0.1:10
func(arg1, arg2, ix)
end
See how each call to func includes the current value of ix ? On the first iteration ix==0, on the next ix==0.1 and so forth. You should be able to adapt this to your needs; in your code the loop index (which you call i) is not used inside the loop.
Now some un-asked-for criticism of your code. The lines
x0=[1,1,1];
y=x0(1);
u=x0(2);
yc=x0(3);
options=optimset('Display','off');
do not change as the loop iterations advance; they always return the same values whatever the value of the loop iterator (i in your code) may be. It is pointless including them inside the loop.
Leaving them inside the loop may even be a waste of a lot of time if Matlab decides to calculate them at every iteration. I'm not sure what Matlab does in this case, it may be smart enough to figure out that these values don't change at each iteration, but even if it does it is bad programming practice to write your code this way; lift constant expressions such as these out of loops.
It's not clear from the fragment you've posted why you have defined y, u and yc at all, they're not used anywhere; perhaps they're used in other parts of your program.

Concatenate equivalent in MATLAB for a single value

I am trying to use MATLAB in order to generate a variable whose elements are either 0 or 1. I want to define this variable using some kind of concatenation (equivalent of Java string append) so that I can add as many 0's and 1's according to some upper limit.
I can only think of using a for loop to append values to an existing variable. Something like
variable=1;
for i=1:N
if ( i%2==0)
variable = variable.append('0')
else
variable = variable.append('1')
i=i+1;
end
Is there a better way to do this?
In MATLAB, you can almost always avoid a loop by treating arrays in a vectorized way.
The result of pseudo-code you provided can be obtained in a single line as:
variable = mod((1:N),2);
The above line generates a row vector [1,2,...,N] (with the code (1:N), use (1:N)' if you need a column vector) and the mod function (as most MATLAB functions) is applied to each element when it receives an array.
That's not valid Matlab code:
The % indicates the start of a comment, hence introducing a syntax error.
There is no append method (at least not for arrays).
Theres no need to increment the index in a for loop.
Aside of that it's a bad idea to have Matlab "grow" variables, as memory needs to be reallocated at each time, slowing it down considerably. The correct approach is:
variable=zeros(N,1);
for i=1:N
variable(i)=mod(i,2);
end
If you really do want to grow variables (some times it is inevitable) you can use this:
variable=[variable;1];
Use ; for appending rows, use , for appending columns (does the same as vertcat and horzcat). Use cat if you have more than 2 dimensions in your array.

Slow anonymous function

Suppose you have a loop with 50000 iterations and want to calculate mean values (scalars) from alot of matrices. This is not complete, but roughly like this:
for k=1:50000
...
mean=sum(sum(matrix))/numel(matrix); %Arithmetic mean
...
end
And now want to include different mean equations to choose from. First I tried this:
average='arithmetic'
for k=1:50000
...
switch average
case 'arithmetic'
mean=sum(sum(matrix))/numel(matrix); %Arithmetic mean
case 'geometric'
mean=prod(prod(matrix)).^(1/numel(matrix)); %Geometric mean
case 'harmonic'
mean=numel(matrix)/sum(sum(1./matrix)); %Harmonic mean
end
...
end
This is obviously alot slower than the first loop because it needs to find the matching string for every iteration which feels really unnecessary. Then I tried this:
average='arithmetic'
switch average
case 'arithmetic'
eq=#(arg)sum(sum(arg))/numel(arg); %Arithmetic mean
case 'geometric'
eq=#(arg)prod(prod(arg)).^(1/numel(arg)); %Geometric mean
case 'harmonic'
eq=#(arg)numel(arg)/sum(sum(1./arg)); %Harmonic mean
end
for k=1:50000
...
mean=eq(matrix); %Call mean equation
...
end
This is still about twice as slow as the first loop and I don't get why. The two last loops are almost similar in speed.
Am I doing something wrong here? How can I achieve the same performance as the first loop with this extra feature?
Help is very much appreciated!
Having the switch inside the loop is performing a comparison 50000 times which only needs to be performed once, something I'd advise against.
The second is a little more subtle, but it's quite probable the eq function is being dynamically looked up every iteration and possibly interpreted each time as well (not sure how MATLAB does optimisation). Your best bet for performance is probably to put the for loop inside of the switch
switch average
case 'arithmetic'
for ... end
case 'geometric'
for ... end
case 'harmonic'
for ... end
end
Well, every function, even anonymous functions, can be expected to have some amount of extra overhead involved in calling it, making them slightly slower than their single-line expression counterparts in your example. However, in this case there may be extra overhead due to the fact that functions by the name eq already exist in abundance in MATLAB, since eq is the method name of the overloaded == operator. Using the WHICH command like so:
>> which eq -all
Will show you that eq is heavily overloaded, with one existing for each of the fundamental data types and most objects.
I would try using a different name for your anonymous function handle just to see if dispatching may be a factor, although I kinda doubt it based on the function precedence order (i.e. variables always appear to take precedence). Your best solution performance-wise may be to avoid the extra function call overhead by doing something like what DavW suggests.
I would like to make one other suggestion. Many of the mathematical operations you are doing can be greatly improved to make them more efficient, specifically by making use of the function MEAN and the colon operator to reshape an entire matrix into a column vector:
result = mean(matrix(:)); %# For the arithmetic mean
result = prod(matrix(:))^(1/numel(matrix)); %# For the geometric mean
result = 1/mean(1./matrix(:)); %# For the harmonic mean
Note that I didn't use the name mean for my variable since that is already used for the built-in function, and you definitely don't want to shadow it.