Code organization Matlab [duplicate] - performance

This question already has answers here:
In MATLAB, can I have a script and a function definition in the same file?
(7 answers)
Closed 6 years ago.
I write some program at Matlab. I do it in .m file. And it's 300+ strings of code now, so it became not very comfortable for reading. My idea is to use it like in C++: I want to create local functions at the end of this file and put pieces of code into them. It would be easy to read and it would consist of some logical parts.
But I faced the fact that local functions can be created only in body of other function! So I can't create this:
x = 1;
y = 2;
z = myLocalFnc(x,y);
function res = myLocalFnc (a,b)
res = a.*b;
end
This generate error:
Function definitions are not permitted in this context.
I can do it by including the whole code into one function:
function myBigFcn
x = 1;
y = 2;
z = myLocalFnc(x,y);
end
function res = myLocalFnc (a,b)
res = a.*b;
end
But now all the variables became local and it return to workspace nothing.
Modify input/output for this function any time I create some variable - I don't think I walk the right way... Here are described advantages and disadvantages of this method.
I know I can create function in additional .m file, save it and use in my script - OK, but a lot of them are single-operation, I don't want to create so much new files.
My question is ARE any other methods of code organizing?

If you really want your main thing to be a script (I don't recommend this), you can put all the other functions in separate .m files and call those from within the script.
The other option, as you've noted is to put the entire contents of your "main" part into a function at the top of your code. You can return all the necessary values via the output arguments or save them to a .mat file if you need access to them later.
As a side note, the ability to put local functions within a script (what you're trying to do) is present in R2016b which will be released later this Fall.
Update
If you want an easy way to convert your code to a function. You can easily save all variables to a struct at the end of your function automatically and just return this struct.
function output = my_script_that_is_now_a_function(inputs)
% Do stuff
% Now save all variables in a struct and return it
tmpfile = tempname;
save(tmpfile);
output = load(tmpfile);
delete(tmpfile);
end

One option, if you don't mind saving a file locally, is to restructure your code into multiple functions (all in the same file) and pass the necessary variables as output. You then have a short script which calls this function and creates the necessary variables.
For example, say your script looks like this
numPoints = 5;
a = randn(numPoints);
b = sin(a);
c = a + b;
You could restructure it to look like
function data = main()
data.numPoints = 5;
data.a = getA(data.numPoints);
data.b = getB(data.a);
data.c = getC(data.a, data.b);
function a = getA(numPoints)
a = randn(numPoints);
function b = getB(a)
b = sin(a);
function c = getC(a, b)
c = a + b;
and create a script file which looks like
data = main();
You then have a struct called data which contains all of your variables. If you really want them to be contained in separate variables (i.e. not in a struct) then there are a couple of ways to do it. One is to unpack them manually,
a = data.a;
b = data.b;
c = data.c;
clear data;
Another is to save the struct, and then reload it (this has the advantage of keeping a copy of the workspace that you used for this fun of the function, for later analysis).
save('workspace.mat', '-struct', 'data');
load('workspace.mat');

Related

How I access value of diff_sol in given example(on terminal)? when I try it says diff_sol undefined

for j in 1:10
δ= y[j,:]
diff_prob = ODEProblem(Proteo_Deg, u0,t_span,δ)
diff_sol = solve(diff_prob)
end
A for loop creates a local scope, and so new variables that you introduce in a loop only exist within that loop.
A common way around this is to initialize the variable before the loop. (Outside of the REPL, you generally want to avoid global variables, so for eg. if this is in a script file, place both the initialization and then the loop within a function.) One thing to consider is what your goal with the loop is. Currently, you're computing 10 ODE solutions, but then throwing them out because they're all assigned to the same variable diff_sol. Maybe you want to save them in an array?
diff_solutions = Array{ODESolution}(undef, 10)
for j in 1:10
δ = y[j,:]
diff_prob = ODEProblem(Proteo_Deg, u0,t_span,δ)
diff_solutions[j] = solve(diff_prob)
end
Now, diff_solutions contains all 10 ODE solutions and is available to access outside of the loop too. If this is in a function, you can then return diff_solutions after the loop.

How can I pass multiple parameters to a parallel operation in Octave?

I wrote a function that acts on each combination of columns in an input matrix. It uses multiple for loops and is very slow, so I am trying to parallelize it to use the maximum number of threads on my computer.
I am having difficulty finding the correct syntax to set this up. I'm using the Parallel package in octave, and have tried several ways to set up the calls. Here are two of them, in a simplified form, as well as a non-parallel version that I believe works:
function A = parallelExample(M)
pkg load parallel;
# Get total count of columns
ct = columns(M);
# Generate column pairs
I = nchoosek([1:ct],2);
ops = rows(I);
slice = ones(1, ops);
Ic = mat2cell(I, slice, 2);
## # Non-parallel
## A = zeros(1, ops);
## for i = 1:ops
## A(i) = cmbtest(Ic{i}, M);
## endfor
# Parallelized call v1
A = parcellfun(nproc, #cmbtest, Ic, {M});
## # Parallelized call v2
## afun = #(x) cmbtest(x, M);
## A = parcellfun(nproc, afun, Ic);
endfunction
# function to apply
function P = cmbtest(indices, matrix)
colset = matrix(:,indices);
product = colset(:,1) .* colset(:,2);
P = sum(product);
endfunction
For both of these examples I generate every combination of two columns and convert those pairs into a cell array that the parcellfun function should split up. In the first, I attempt to convert the input matrix M into a 1x1 cell array so it goes to each parallel instance in the same form. I get the error 'C must be a cell array' but this must be internal to the parcellfun function. In the second, I attempt to define an anonymous function that includes the matrix. The error I get here specifies that 'cmbtest' is undefined.
(Naturally, the actual function I'm trying to apply is far more complex than cmbtest here)
Other things I have tried:
Put M into a global variable so it doesn't need to be passed. Seemed to be impossible to put a global variable in a function file, though I may just be having syntax issues.
Make cmbtest a nested function so it can access M (parcellfun doesn't support that)
I'm out of ideas at this point and could use help figuring out how to get this to work.
Converting my comments above to an answer.
When performing parallel operations, it is useful to think of each parallel worker that will result as separate and independent octave instances, which need to have appropriate access to all functions and variables they will require in order to do their independent work.
Therefore, do not rely on subfunctions when calling parcellfun from a main function, since this might lead to errors if the worker is unable to access the subfunction directly under the hood.
In this case, separating the subfunction into its own file fixed the problem.

Why make a variable immutable and create a new entry when redefining a variable?

In SML,if I am correct, variables are immutable by default. So when we try to redefine a variable
val y = 100;
val y = 0.6;
y
the environment will have two entries for y. The new entry hides the original entry.
Isn't it the same effect as if we modified the value in the original entry from 100 to 0.6?
If the original entry was created outside a function call, and the new entry was created in a function call, then when the function call returns, we can access the original entry.
If both entries were created in the same "scope", like the example above, is the original entry not accessible?
Effectively, isn't it the same in SML as in an imperative language such as C? What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
Thanks.
Isn't it the same effect as if we modified the value in the original entry from 100 to 0.6
No. Consider code that references the previous environment through use of a closure like
val x = 7
val f = fn () => x
val x = 8
val _ = print (Int.toString (f ())) (* prints 7 *)
If the original entry was created outside a function call, and the new entry was created in a function call, then when the function call returns, we can access the original entry.
Sure, its statically scoped.
If both entries were created in the same "scope", like the example above, is the original entry not accessible?
It is still accessible, just not by that identifier. Consider the example above.
What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
One use of this is changing the type of a variable while still using the same identifier (which you do in the example you post!). Take for instance (in C):
int i = 7;
i = 7.0;
Here, i will still be of type int. Cf., in SML:
val i : int = 7
val i : real = 7.0
I've added type annotations for illustration, but even without this has the same behaviour. After the second binding, i has type real.
To amend kopecs' answer:
What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
That is the wrong way to phrase the question. :) Immutability by default has many merits, but that would be off-topic.
The actual question is: Why does SML allow multiple bindings for the same variable in a single scope? Instead of making it an error?
And that's a fair question. There is no deep reason. It merely turns out to be convenient sometimes. For example, to avoid spurious identifier clashes when using open. Or to allow redefining previous definitions in an interactive session.

How do I parallelize for-loop in octave using pararrayfun (or any other function will also do)?

Well, I'm new to octave and i wanted to know how to implement parallel execution of for loop in octave.
I'm looking for parallel implementation of the below code (its not the exact code that I'm trying to execute, but something similar to this)
`%read a csv file
master_sheet = csv2cell('master_sheet.csv');
delta = 0.001;
nprocs= nproc();
%extract some values from the csv file and store it in the variables
a = master_sheet{34,2} ;
b = master_sheet{38,2} ;
c = master_sheet{39,2} ;
for i=0:1000
%%create variants of a,b and c by adding a delta value
a_adj = a +(i)*delta ;
b_adj = b +(i)*delta ;
c_adj = c +(i)*delta ;
%club all the above variables and put it to an array variable
array_abc = [a_adj, b_adj, c_adj];
%send this array as an argument/parameter to a function
%processingData() function would essentially perform some series of calculation and would write the
%results onto a file
processingData(array_abc);
endfor
Currently, I'm using parallel pkg (pararrayfun) to implement this, but if there is any other way(package) that could achieve the parallelization of for loop in octave, then I'm open to exploring that as well.
Thank you!

Returning multiple ints and passing them as multiple arguements in Lua

I have a function that takes a variable amount of ints as arguments.
thisFunction(1,1,1,2,2,2,2,3,4,4,7,4,2)
this function was given in a framework and I'd rather not change the code of the function or the .lua it is from. So I want a function that repeats a number for me a certain amount of times so this is less repetitive. Something that could work like this and achieve what was done above
thisFunction(repeatNum(1,3),repeatNum(2,4),3,repeatNum(4,2),7,4,2)
is this possible in Lua? I'm even comfortable with something like this:
thisFunction(repeatNum(1,3,2,4,3,1,4,2,7,1,4,1,2,1))
I think you're stuck with something along the lines of your second proposed solution, i.e.
thisFunction(repeatNum(1,3,2,4,3,1,4,2,7,1,4,1,2,1))
because if you use a function that returns multiple values in the middle of a list, it's adjusted so that it only returns one value. However, at the end of a list, the function does not have its return values adjusted.
You can code repeatNum as follows. It's not optimized and there's no error-checking. This works in Lua 5.1. If you're using 5.2, you'll need to make adjustments.
function repeatNum(...)
local results = {}
local n = #{...}
for i = 1,n,2 do
local val = select(i, ...)
local reps = select(i+1, ...)
for j = 1,reps do
table.insert(results, val)
end
end
return unpack(results)
end
I don't have 5.2 installed on this computer, but I believe the only change you need is to replace unpack with table.unpack.
I realise this question has been answered, but I wondered from a readability point of view if using tables to mark the repeats would be clearer, of course it's probably far less efficient.
function repeatnum(...)
local i = 0
local t = {...}
local tblO = {}
for j,v in ipairs(t) do
if type(v) == 'table' then
for k = 1,v[2] do
i = i + 1
tblO[i] = v[1]
end
else
i = i + 1
tblO[i] = v
end
end
return unpack(tblO)
end
print(repeatnum({1,3},{2,4},3,{4,2},7,4,2))

Resources