Matlab: Slicing matrix inside a containers.Map always requires intermediate referencing? - matlab

Prologue:
I am in the process of designing/prototyping a piece of code in Matlab.
As at the moment it is not clear to me which matrices should be returned by my functions, I chose, as a general approach, to bind my returned values in containers.Map (as I would do e.g. in python).
Hence, the general setting is
function output = myfoo(args)
output = containers.Map;
...some stuff
output('outname1') = ...
output('outname2') = ...
end
this approach should have the advantage of allowing me to add more returned data without messing up the other code too much or break backwards compatibility.
Issue:
How to deal in a elegant way with matrix slicing?
Say that I need to do something like
output('outname1')(2:end) = ...
(which gives an error as two indexes are not allowed and a boring workaround like
temp = output('outname1')
temp(2:end) = ...
output('outname1') = temp
is required).
Question:
Is there a proficient way to deal with this, avoiding all this referencing/copying job?

No, there is no way to do it without a temporary variable. The only case in which a double index is valid in Matlab is for a cell array. In that case, you can use
output{...}(...)
However, in any other case, a double index results in an error.

Related

Is there generator/iterator like that in python for map keys in matlab to save memory?

I have a large Map in matlab and want to traverse all the keys of it.
But I can only store a cell for the keys first and traverse the cell, which calls for memory to store all the keys.
While in python, the generator/iterator can sequentially give the indexes or entries of list back in loops, which does not cost much memory.
In matlab, I tried for loop:
% Let MAP is a containers.Map with 10000000 keys.
keys = MAP.keys;
for keyIdx = 1:size(keys,2)
MAP(keys{1,keyIdx});
end
While in python, the for loop with iterator:
% Let MAP is a dictionary with 10000000 keys.
for key in MAP.iterkeys():
MAP[key]
So, is there generator/iterator like that in python in matlab to save memory when I process the maps?
To answer your main question: No. There is no generator in MATLAB.
Also, the Python code you wrote does not use a Python generator.
The memory footprint of both snippets are similar.
But I think I did not get the details about your question....
Last:
you can use numel(keys) instead of size(keys, 2) since keys is of one dimension
you can use MAP(keys{keyIdx}) instead of MAP(keys{1, keyIdx})
MATLAB uses the lazy copy or copy-on-write machinism. This means that when you do
B = A;
both A and B point to the same memory until you try to modify one of the arrays, at which point MATLAB will copy the data so that modifying one doesn’t affect the other copy.
This means also that, given a Containers.Map object map,
keys = map.keys
will not copy the keys, but instead keys will share data with the keys as they are stored inside the map.
Note that
keys = map.keys;
for keyIdx = 1:numel(keys)
value = map(keys{keyIdx})
end
is the same as
for key = map.keys
value = map(key{1})
end
and the same as
for value = map.values
value = value{1}
end
In none of these cases is data copied!
(I am guessing at the syntax, as I’m typing on my phone right now, I think the {1} indexing is required here, but I might be wrong about it.)

Avoid repeat calling simulation/function with same arguments

This is a general algorithm question, but my primary environment is Matlab.
I have a function
out=f(arg1,arg2,,.....)
which takes a long time to execute and is expensive to compute (i.e. cluster time). A given argument argn can be a string, integer, vector, and even a function handle
For this reason, I want to avoid calling f(args) for the same argument values. Inside my program, this can occur in ways that are not necessarily controllable by the programmer.
So, I want to call f() once for each possible value of args, and save the results to disk. Then, whenever it is called the next time, check if there is currently a result for those argument values. If so, I would load it from disk.
My current idea is to create a cell variable, with one row for each function call. In the first column is out. In column 2:N are the values of argn, and check the equivalence of each individually.
Since the variable types of the arguments vary, how would I go about doing this?
Is there a better algorithm?
More generally, how do people deal with saving simulation results to disk and storing metadata? (other than cramming everything into a filename!)
You can implement a function that looks something like this:
function result = myfun(input)
persistent cache
if isempty(cache)
cachedInputs = [];
cachedOutputs = [];
cache = {cachedInputs, cachedOutputs};
end
[isCached, idx] = ismember(input, cache{1});
if isCached
result = cache{2}(idx);
else
result = doHardThingOnCluster(input);
cache{1}(end+1) = input;
cache{2}(end+1) = result;
end
This simple example assumes that your inputs and outputs are both scalar numbers that can be stored in an array. If you have to deal with strings, or anything more complicated, you could use a cell array for caching rather than an array. Or in fact, maybe a containers.Map might be even better. Alternatively, if you have to cache really massive results, you might be better off saving it to a file and caching the file name, then loading the file in if you find it's been cached.
Hope that helps!

Can you call a matrix from a string

I have to make a call to read in a matrix with a name that is created from a strcat, in Matlab. For example
person = 2;
Index_XNY = strcat('Index_X',num2str(person),'Y');
Big_Index = find(Index_XNY(1,:)==1);
This works if I replace Index_XNY with Index_X2Y for this example.
I have tried a number of different things to obtain Big_Index, but so far I have not been successful. Can this be done, as there is a large collection of data elements that need to be called.
You can use the eval function to evaluate a Matlab expression in a string:
expr = strcat('find(Index_X',num2str(person),'Y(1,:)==1)');
Big_Index = eval(expr);
Of course, a lot of alternative ways to do this with eval function exist, depending on how much you would like to put into the string and how much would be left out.

How can I make the value of an expression equal to a second return value of another expression

Is there an idiomatic way in Matlab to bind the value of an expression to the nth return value of another expression?
For example, say I want an array of indices corresponding to the maximum value of a number of vectors stored in a cell array. I can do that by
function I = max_index(varargin)
[~,I]=max(varargin{:});
cellfun(#max_index, my_data);
But this requires one to define a function (max_index) specific for each case one wants to select a particular return value in an expression. I can of course define a generic function that does what I want:
function y = nth_return(n,fun,varargin)
[vals{1:n}] = fun(varargin{:});
y = vals{n};
And call it like:
cellfun(#(x) nth_return(2,#max,x), my_data)
Adding such functions, however, makes code snippets less portable and harder to understand. Is there an idiomatic to achieve the same result without having to rely on the custom nth_return function?
This is as far as I know not possible in another way as with the solutions you mention. So just use the syntax:
[~,I]=max(var);
Or indeed create an extra function. But I would also suggest against this. Just write the extra line of code, in case you want to use the output in another function. I found two earlier questions on stackoverflow, which adress the same topic, and seem to confirm that this is not possible.
Skipping outputs with anonymous function in MATLAB
How to elegantly ignore some return values of a MATLAB function?
The reason why the ~ operator was added to MATLAB some versions ago was to prevent you from saving variables you do not need. If there would be a syntax like the one you are searching for, this would not have been necessary.

matlab: is there a way to import/promote variables from a structure to the current workspace?

function y = myfunc(param)
C = param.C;
L = param.L;
Kp = param.Kp;
Ki = param.Ki;
...
Is there a way to generalize the above code? I know how to generalize the structure access using fieldnames() and getfield(), but not how to set variables without calling eval() (which is evil).
for n = fieldnames(param)'
name = n{1};
value = param.(name);
do_something_with(name,value); % ????
never mind, I figured it out; this helper function works:
function vars_pull(s)
for n = fieldnames(s)'
name = n{1};
value = s.(name);
assignin('caller',name,value);
end
The only way to create a variable whose name is determined at run-time is to use a function like eval, evalin, feval, or assignin. (assignin is the least evil choice BTW, at least you don't need to convert your value to a string and back.)
However, I question why you want to do that, why not just access the values through the input structure as you need them. If you want to save typing (speaking from experience, as I am extremely lazy), I usually name my input parameter structure something short, like p. The throughout my code I just access the fields directly, (e.g. p.Kp, and after a while I don't even see the p. anymore.) This also makes it easy to pass the structure into subfunctions as needed.
You can use the excellent submission at FileExchange:
V2STRUCT - Pack & Unpack variables to & from structures with enhanced functionality
Here's a workaround: save the structure to a .mat file using the '-struct' option, and then immediately reload it. Here's an example for struct variable X:
save('deleteme.mat','-struct','X');
load('deleteme.mat');
delete('deleteme.mat');
It's kludgey, but actually pretty fast, at least with an SSD.