Matlab coder reallocation - matlab

I have some code like this in my matlab function:
for i = init:end
a= [a, char(zeros(size(a))]
a= func(a)
a = a(a~=0)
end
So, in each step of the loop, you first double the size of a, apply some random function to it, and then remove everything that is a zero.
Now, I want to run coder on this to eventually make it into c code. Of course, it gives me allocation errors.
Allowing dynamically allocated arrays doesn't help. I can't simply use different names for my variables either because it is in a for loop.

This may come a year late however something like:
function a = foobar(init,ub)
coder.varsize('a',[1,Inf]);
a = 1;
for i = init:ub
a = [a, ones(size(a))];
a = sin(a);
a = a(a~=0);
end
>> codegen foobar -args {1,1} -report
works for me in R2014a.
When you are trying to grow an array, it may be necessary to use coder.varsize in order to tell MATLAB Coder that the array is going to change size. In many cases MATLAB Coder can figure this out without using coder.varsize so it is best to try without it first and then add it in if errors are encountered.

Related

Simplify the code to flatten arrays in matlab

Suppose I have a 1000x2x10x10 matrix, and currently I put them into two cell arrays by the following code,
for i=1:1000
tmp = seqs(i,1,:);
patterns{i} = tmp(:);
tmp = seqs(i,2,:);
labels{i} = tmp(:);
end
The purpose of patterns{i} = tmp(:) and labels{i} = tmp(:) is to flatten the matrix. My question is that, is it possible to simplify the code like patterns{i}=seqs(i,1,:)(:)? I tried this one but Matlab does not allow this, and that's why I currently have to use a temporary variable tmp.
I'll just give you 3 ways to do this. All of which work.
The first is the one I normally use is to have a function on my computer called vec
function out = vec(in)
out = in(:);
end
and then you can use it via
patterns{i} = vec(seqs(i,1,:));
Then you can call this function and it allows for more streamlined code. The second is reshape mentioned in the comments
patterns{i}=reshape(seqs(i,1,:),[],1);
I typically don't recommend reshape for these types of problems because it tends to fail if you aren't careful. The last is to use squeeze and transpose.
patterns{i} = squeeze(seqs(i,1,:))';
Personally, I prefer the first because it makes my code look nicer.

How to use a M-.file in a parfor loop in Matlab?

my code inside a parfor loop is getting longer and longer and I would like to split it up. Having parts of the code saved in different script files seems logical and very attractive and since it doesn't change anything except where the code is saved it seems like it should work. But it doesn't.
I get the usual "Transparency violation error".
The problem seems typical but I did not find this question asked or answered anywhere.
Below is a small working example.
(Yes, this could be made as a function. But in case of many more Input and Output variables this becomes really ugly imo and probably also slower due to communicating the arguments)
C = NaN(10,1); %Result vector
parfor loop = 1:10
a = 1;
b = 2;
MFile_Test %Run the m-file which contains only one line:
% c = a + b;
C(loop)=c;
end
the MFile_Test is a script just containing the line one line c = a + b.
I am beginning to understand why parallel computing has an issue here but not how to solve it. Since this would be possible without any problem if I just had the line c = a + b inside the parfor file I cannot belief there is no simple way to solve this (e.g. in the worst case something like tell matlab to load the text from another file and run it as code here and now).
If there are alternative ways to structure my code without using the script files (and, if possible, without using only functions ;)) I would appreciate such comments as well, of course.
Many thanks,
Daniel
parfor has various constraints that make using scripts inside the loop generally a bad option. The main constraint is that the text of the parfor loop must be analysable to see what new variables might be created - this is referred to as "transparency" in the doc. Try using a function instead.
So, for other people or for possible hints to improve, here is how I did it with a function and loading the input variables.
a = 1;
b = 2;
save('Input.mat');
pseudo_input = NaN;%for the function
D= NaN(10,1);%result vector
parfor loop = 1:10
D(loop) = Parfor_Fun_Test(pseudo_input);
end
And the function looks like this:
function d = Parfor_Fun_Test(InputArgs)
load('Input.mat');
d = a + b ;
end
I would have preferred to also save the output, i.e. 'd', within the function and then load it in the parfor loop, but that causes an error, probably because the same file is accessed for loading and saving at the same time by different parallel workers. So this will have to do it. (This can apparently be circumvented by saving under a different name each time, but that would probably really slow down the code.)
By the way, it seems that using cells or structures is slightly faster, but then I have to write the code inside the function as this, I assume:
d = Input.a + Input.b ;
which is more ugly and more work. So I use the save and load method as above for now.

I am having trouble creating function handles. I want to embed a maximizing function within a minimizing function

The following code won't work, but this is the idea I'm trying to get at.
c = #(x)constraints;
%this is where I would initialize sum as 0 but not sure how...
for i = 1:length(c)
sum = #(x)(sum(x) + (min(c(x)(i),0))^2);
end
penFunc = #(x)(funcHandle(x) + sig*sum(x));
where constraints and funcHandle are functions of x. This entire code would iterate for a sequence of sig's.
Obviously c(x)(i) isn't functional. I'm trying to write the function where the minimum of c(x) at i (c(x) is a vector) or 0 is taken and then squared.
I know I could calculate c(x) and then analyze it at each i, but I eventually want to pass penFunc as a handle to another function which calculates the minimum of penFunc, so I need to keep it as a function.
I confess I don't understand entirely what you're trying to achieve, but it appears you're trying to create a function handle of an anonymous function with a changing value sum that you precompute. MATLAB anonymous functions do allow you to do this.
It appears there might be some confusion with anonymous functions here. To start with, the line:
c = #(x)constraints;
is probably supposed to be something else, unless you really want c to be a function handle. The # at the start of the line declares a new anonymous function, when I think you just want to call the existing function constraints. It appears you really want c to be an array of constraints coming from the constraints function, in which case I think you mean to say
c = constraints(x);
Then we get to the sum, which I can't tell if you want as a vector or as a single sum. To start with, let's not name it 'sum', since that's the name of a built-in MATLAB function. Let's call it 'sumval'. If it's just a single value, then it's easy (it's easy both ways, but let's do this.) Start before the for loop with sumval=0; to initialize it, then the loop would be:
sumval = 0;
for i = 1:length(c)
sumval = sumval + (min(c(i),0))^2);
end
All four lines could be vectorized if you like to:
c(c>0) = 0; %Replace all positive values with 0
sumval = sum(c.^2); % Use .^ to do a element by element square.
The last line is obviously where you make your actual function handle, and I'm still not quite sure what is desired here. If sig is a function, then perhaps you really meant to have:
penFunc = #(x)(funcHandle(x) + sig*sumval);
But I'm not sure. If you wanted sum to be a vector, then how we specified it here wouldn't work.
Notice that it is indeed fine to have penFunc be an anonymous function with a variable within it (namely sumval), but it will continue to use the value of sumval that existed at the time of the function handle declaration.
So really the issues are A) the creation of c, which I don't think you meant to be a function handle, and B) the initialization of sum, which should probably be sumval (to not interact with MATLAB's own function), and which probably shouldn't declare a new function handle.

MATLAB Using fzero - returns error

I'm trying to use the MATLAB function fzero properly but my program keeps returning an error message. This is my code (made up of two m-files):
friction_zero.m
function fric_zero = friction_zero(reynolds)
fric_zero = 0.25*power(log10(5.74/(power(reynolds,0.9))),-2);
flow.m
function f = flow(fric)
f = 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(power(10,4));
z = fzero(#flow,f_initial)
The goal is to return z as the root for the equation specified by f when flow.m is run.
I believe I have the correct syntax as I have spent a couple of hours online looking at examples. What happens is that it returns the following error message:
"Undefined function or variable 'fric'."
(Of course it's undefined, it's the variable I'm trying to solve!)
Can someone point out to me what I've done wrong? Thanks
EDIT
Thanks to all who helped! You have assisted me to eventually figure out my problem.
I had to add another file. Here is a full summary of the completed code with output.
friction_zero.m
function fric_zero = friction_zero(re)
fric_zero = 0.25*power(log10(5.74/(power(re,0.9))),-2); %starting value for fric
flow.m
function z = flow(fric)
re = power(10,4);
z = 1/(sqrt(fric))-1.873*log10(re*sqrt(fric))-233/((re*sqrt(fric))^0.9)-0.2361;
flow2.m
f_initial = friction_zero(re); %arbitrary starting value (Reynolds)
x = #flow;
fric_root = fzero(x,f_initial)
This returns an output of:
fric_root = 0.0235
Which seems to be the correct answer (phew!)
I realised that (1) I didn't define reynolds (which is now just re) in the right place, and (2) I was trying to do too much and thus skipped out on the line x = #flow;, for some reason when I added the extra line in, MATLAB stopped complaining. Not sure why it wouldn't have just taken #flow straight into fzero().
Once again, thanks :)
You need to make sure that f is a function in your code. This is simply an expression with reynolds being a constant when it isn't defined. As such, wrap this as an anonymous function with fric as the input variable. Also, you need to make sure the output variable from your function is z, not f. Since you're solving for fric, you don't need to specify this as the input variable into flow. Also, you need to specify f as the input into fzero, not flow. flow is the name of your main function. In addition, reynolds in flow is not defined, so I'm going to assume that it's the same as what you specified to friction_zero. With these edits, try doing this:
function z = flow()
reynolds = power(10,4);
f = #(fric) 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(reynolds);
z = fzero(#f, f_initial); %// You're solving for `f`, not flow. flow is your function name
The reason that you have a problem is because flow is called without argument I think. You should read a little more about matlab functions. By the way, reynolds is not defined either.
I am afraid I cannot help you completely since I have not been doing fluid mechanics. However, I can tell you about functions.
A matlab function definition looks something like this:
function x0 = f(xGuess)
a = 2;
fcn =#(t) a*t.^3+t; % t must not be an input to f.
disp(fcn);
a = 3;
disp(fcn);
x0 = fsolve(fcn1,xGuess); % x0 is calculated here
The function can then ne called as myX0 = f(myGuess). When you define a matlab function with arguments and return values, you must tell matlab what to do with them. Matlab cannot guess that. In this function you tell matlab to use xGuess as an initial guess to fsolve, when solving the anonymous function fcn. Notice also that matlab does not assume that an undefined variable is an independent variable. You need to tell matlab that now I want to create an anonymous function fcn which have an independent variable t.
Observation 1: I use .^. This is since the function will take an argument an evaluate it and this argument can also be a vector. In this particulat case I want pointwise evaluation. This is not really necessary when using fsolve but it is good practice if f is not a matrix equation, since "vectorization" is often used in matlab.
Observation 2: notice that even if a changes its value the function does not change. This is since matlab passes the value of a variable when defining a function and not the variable itself. A c programmer would say that a variable is passed by its value and not by a pointer. This means that fcn is really defined as fcn = #(x) 2*t.^3+t;. Using the variable a is just a conveniance (constants can may also be complicated to find, but when found they are just a value).
Armed with this knowledge, you should be able to tackle the problem in front of you. Also, the recursive call to flow in your function will eventuallt cause a crash. When you write a function that calls itself like this you must have a stopping criterium, something to tell the program when to stop. As it is now, flow will call ifself in the last row, like z = fzero(#flow,f_initial) for 500 times and then crash. Alos it is possible as well to define functions with zero inputs:
function plancksConstant = h()
plancksConstant = 6.62606957e−34;
Where the call h or h() will return Plancks constant.
Good luck!

Function to find entries with same maximum value in a vector

In my project I need a function which returns the index of the largest element of a given vector. Just like max. For more than one entry with the same maximum value (which occurs frequently) the function should choose one randomly. Unlike max.
The function is a subfunction in a MATLAB Function Block in Simulink. And the whole Simulink model is compiled.
My basic idea was:
function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end
But I got problems with the comparison in find and with randi.
I found out about safe comparison here: Problem using the find function in MATLAB. Also I found a way to replace randi([1,imax],1): Implement 'randi' using 'rand' in MATLAB.
My Code now looks like this:
function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end
Still doesn't work. I understand that the length of index_max is unclear and causes problems. But I can not think of any way to know it before. Any ideas how to solve this?
Also, I'm shocked that ceil doesn't work when the code gets executed?? In debug mode there is no change to the input visible.
I thought about creating an array like: index_max = abs(vector - max(vector)) < tolerance; But not sure how that could help. Also, it doesn't solve my problem with the random selection.
Hopefully somebody has more ideas or at least could give me some hints!
I am using MATLAB R2012b (32bit) on a Windows7-64bit PC, with the Lcc-win32 C 2.4.1 compiler.
Edit:
Vector usually is of size 5x1 and contains values between -2000 and zero which are of type double, e.g. vector = [-1000 -1200 -1000 -1100 -1550]'. But I think such a simple function should work with any kind of input vector.
The call of length(index_max) causes an system error in MATLAB and forces me to shut it down. I guess this is due to the strange return I get from find. For a vector with all the same values the return from find is something like [1.000 2.000 1.000 2.000 0.000]' which doesn't make any sense to me at all.
function v= findOpt(v)
if isempty(v)
return;
end
v = find((max(v) - v) < 0.00001);
v = v(ceil(rand(1)*end));
end
I was indeed overloading, just like user664303 suggested! Since I can not use objects in my project, I wanted an function that behaves similar, so I wrote:
function varargout = table(mode, varargin)
persistent table;
if isempty(table) && ~strcmp(mode,'writeTable')
error(...)
end
switch mode
case 'getValue'
...
case 'writeTable'
table = ...
...
end
end
Wanted to avoid passing the dimensions for the table in every call and thought it would be enough if the first call initializes the Table with mode='writeTable'. Looks like this caused my problem.
No problems after changing to:
if isempty(table)
table = zeros(dim1,dim2,...)
end