I am solving a very large optimization problem. The objective function and constraint function needs numerous data. Currently I am passing the data as a structure to them.
myFS(X, Dat, g_Index, f_Index) % Dat is a structure which includes many variables
Do you think it's an efficient way to reduce the elapsed time?
What better alternatives do exist?
Is this what the given answer, regarding to class definition, means?
%% First we define the class in a separate file:
classdef myDataStructure < handle
properties
NRES;
NOBJ;
NVAR;
end
methods
function obj = myDataStructure()
end
end
end
%% In another file where the main program is, we initialize the class.
Dat = myDataStructure();
%% Initialize
Dat.NRES = 1;
Dat.NOBJ = 1;
Dat.NVAR = 1;
[myF, Dat_updated] = BBB(Dat);
%% Here we define the function and use the class
function [f, CalssDat] = BBB(CalssDat)
x = CalssDat.NRES;
y = CalssDat.NOBJ;
z = CalssDat.NVAR;
f = x + y + z;
CalssDat.NOBJ = 2;
end
As far as I know, MATLAB does not actually copy the content of the data you pass to a function until the point when you modify it in the function itself - in which case it makes a local copy and that takes some CPU time.
Therefore, as long as Dat doesn't change inside myFS(), what you are doing now does not add any CPU overhead. In case you do change the values of Dat inside myFS() and want to return it, I can think of two ways to optimise it:
You can declare myFS() as: function [Dat, anythingElse] = myFs(X,Dat,g_Index, f_Index), which should prevent matlab from making a local copy.
Another approach is to use a class that derives from handle and have Dat be a member of that. This way, whenever you pass the object containing Dat, you only pass the object handle and not a copy of the object itself.
Example of the second approach:
classdef myDataStructure < handle
properties
p1FromDat;
p2FromDat;
% .
% .
% .
pNFromDat;
end
methods
function obj = myDataStructure()
% Add initialization code here if you want. Otherwise p1FromDat
% ... pNFromDat are accessible from outside
end
end
end
Than, in your code:
Dat = myDataStructure();
Dat.p1FromDat = 1;
Dat.p2FromDat = 1;
And in your myFs() you use Dat exactly the same way as you used before.
Because myDataStructure derives from handle, the data inside will not be copied when you pass Dat around.
Do be careful with this, because when you change Dat in myFS(), the values will be changed outside the scope of myFS() as well.
Related
I am working on a MATLAB program where I will have a class, here represented as Dummy, and a function which is supposed to create and save a set of Dummy objects, say to the current folder. How can I do this? I thought about creating a matfile containing the constructor arguments for each Dummy object, as done in the code example below. However, save expects a string, so my code doesn't work.
classdef Dummy < handle
properties
foo
end
methods
function D = Dummy(foo)
D.foo = foo;
end
end
end
function generateDummies(n)
for i = 1:n
Df = matfile(strcat('Df',int2str(i)),'Writable',true);
Df.foo = i;
save(Df); %(?)
end
end
Any help would be greatly appreciated!
I am working on a GUI in matlab and I'm using a variable called top to store everything. I have an update function that is in one area that updates other areas, but I don't like that it bleeds my topvariable into it, but I can't find a way to just pass the reference to the top variable so that it can still mutate what needs to be mutated.
Is there a pass by reference or some equivalent in matlab?
Edit:
For example I want to move this function to a place where top is inaccessible, but it needs a current top to do it's job, if I were to pass top by reference to the file that makes this I could still access top:
function update_Screens_Callback(~,~)
% Look to see if each check box is marked and if it is add it to seen.
seen = [];
for i=1:10
top.screens{i}.Visible='off';
end
for i=1:4
if(top.sets{i,1}.Value==top.sets{i,1}.Max)
seen = [seen i];
end
end
for i=1:6
if(top.sets{i,2}.Value==top.sets{i,2}.Max)
seen = [seen,i+4];
end
end
tmp = size(seen);
tmp = tmp(2);
sizes = getSizes(tmp);
for i=1:tmp
index = seen(i);
top.screens{index}.Visible = 'on';
top.screens{index}.Position = sizes{i};
end
end
Generally speaking, function calls in MATLAB pass arguments by value, but there is an exception where internal optimization effectively results in passes by reference. When a function returns an argument - e.g. a large matrix - as in
function top = updategui(top)
top(42, 42) = 42;
end
and if you assign the argument as part of the invocation as in x = updategui(x);, MATLAB will recognize that copying top is unnecessary and will pass top by reference.
However, I don't think "passing by reference" will help you solve your specific problem. Much of your question sounds more related to scope than to abstraction or passing by reference vs. by value. For example, it is common practice to share variables across GUI components via setappdata.
Such behavior can be achieved in object oriented matlab. Just create an object as subclass from handle. (Here's some documentation)
classdef myHelper < handle
properties
x
end
end
you can then use it like:
a = myHelper
a.x = important_data
and give a to all your functions.
As example:
a = myHelper
a.x = 1
b = a
b.x = 2
a.x
you will see that a was also updated.
I am a beginner in matlab and learn about the following question online and was having trouble solving it. I have a 1 x 20 matrix called current_load that I need to update periodically. This matrix resides in the main workspace of Matlab (as shown in the code bellow).
current_loads = zeros(1, 20);
for col=1:20
current_loads(1,col)=10; %// Initially give all nodes a current value of 10
end
Object = HandleObject(current_load);%To pass by reference
recursive_remove(Object, 0);
In order to pass current_load by reference, I have created the following class HandleObject.m
classdef HandleObject < handle
properties
Object=[];
end
methods
function obj=HandleObject(receivedObject)
obj.Object=receivedObject;
end
end
end
This matrix will be passed to a function call recursive_remove (shown bellow).
function recursive_remove( current_load, val )
current_load.object = new matrix;
if(val<10)
current_load.object(1,3) = 2+val; %Not the correct way of using current_load ??
end
recursive_remove( current_load, current_load.object (1,3) )
end
Intention here is to modify current_load variable in this function and later I can see these same changes from the main. But This code doesn't work since I don't know how to pass by reference. I need to pass by reference since I am calling this recursively without returning to the main to make it overwrite its variable at the caller. Please show with an example if possible.
If you really need this feature, you can look into turning your HandleObject class into a Singleton like this:
classdef HandleObject < handle
properties
Object=[];
end
methods(Static)
function obj = Instance(receivedObject)
persistent uniqueInstance
try
if isempty(uniqueInstance)
obj = HandleObject(receivedObject);
uniqueInstance = obj;
else
obj = uniqueInstance;
end
catch ME
disp(ME.getReport);
end
end
end
methods
function obj=HandleObject(receivedObject)
obj.Object=receivedObject;
end
end
end
Your recursive function would become a bit simpler then:
function recursive_remove(val )
current_load = HandleObject.Instance();
current_load.object = new matrix;
if(val<10)
current_load.object(1,3) = 2+val;
end
recursive_remove(current_load.object (1,3) )
end
And to create an instance of your HandleObject class, you do something like:
Object = HandleObject.Instance(current_load);
Hope this helps you further.
Can I pass a variable by ref to a function in Matlab?
I want to do something such as this:
function change(x)
x=x+1;
end
and call it like this:
x=1;
change(x)
% x should be 2 now.
The usual style for doing this is to have the same name appear in both the input and output parameter lists:
function [x] = change(x)
x=x+1;
end
x = 1;
x = change(x);
% now 2
For example, the standard function setfield works this way.
In addition, handle objects (e.g. graphic handles) are effectively passed by reference -- the handle numeric value is passed by value, so you can't substitute a different object, but any changes made to the handle object in the function will be visible to the caller.
Since you do not describe your usecase I cannot estimate whether it is worth to define your own handle class but there are situations where you may benefit from the object oriented way.
Your basic example would look something like this:
Define your handle class in a separate file called cnt.m (make sure you inherit from the handle class):
classdef cnt < handle
properties (SetAccess = private)
% a private member variable.
c = 0;
end
methods
function h = cnt(c_init)
% CNT constructs a cnt handle
% CNT()
% CNT(INIT)
if nargin > 0
h.c = c_init;
end
end
function change(h)
% CHANGE increment by one
h.c = h.c+1
end
end
end
Then you can do something like this:
x = cnt();
x.change();
and you can also do something like this:
function change2(cnt_obj)
cnt_obj.change()
and call this function then like so:
change2(x)
which will then do what you are asking for.
The later is the reason why you should inherit from handle. If you create an ordinary value class the call to change2 would create a copy of the actual input object.
Please note that for the simple use case you describe doing something like this is STUPID OVERHEAD. Use this only in case you have good reason to.
I am having some difficulty designing a subclass of dataset in Matlab (R2010b). I am experienced programming Matlab, but new to using its OOP features. My constructor seems to be fine, but when I try to build some methods that access data in the dataset, I can't seem to get it to work. Here is an example:
classdef mydataset < dataset
properties
end
methods
function [obj] = mydataset(obs,array)
% obs is N x 1 cell array of strings
% array is N x 2 double array
obj = obj#dataset({array,'Field1','Field2'},'ObsNames',obs)
end
function [val] = computeValue(obj)
col = obj.Field1;
% I get an error above regardless of how I try to access the dataset.
% e.g. col = double(obj(obs,'Field1')) also does not work.
% Some more code using col to determine val
end
end
end
In my method computeValue, I am trying to access the data in the dataset using dataset syntax, i.e. on the command line I could access Field1 using ".". It complains there is no method, property, or field Field1 for class mydataset. If I try the alternate syntax
col = double(obj(:,'Field1'));
it complains about the size of obj, e.g. "Index exceeds matrix dimensions".
I found a workaround using subsref:
methods
function [val] = computeValue(obj)
s.type = '.';
s.subs = 'Field1';
col = subsref(obj,s);
% Some more code using col to determine val
end
end
Although the workaround works, it is not very convenient and largely defeats the purpose of wanting a subclass of dataset. Is there some attribute or something simple I am missing?
Thank you very much.
Eric
Can you post the complete code of your class. I suppose you didn't declare your property "factor" and try to access it.
Your class should look like this :
classdef MyClass
properties
factor;
end
methods
function obj = MyClass(factor)
% The constructor set the property factor
obj.factor = factor;
end
function val = computeValue(obj)
col = obj.factor;
% ...
end
end
end