Given a model with an array x of connectors where its size is unspecified, e.g.
connector con
...
end con;
model test
con x[:];
end test;
How can x be instantiated with a specific size, e.g. something like this?
test t(x = ?);
...
equation
connect(t.x[1], a);
connect(t.x[2], b);
...
Why do you need unspecified dimension? You can do something like this:
connector con
...
end con;
model test
constant Integer dim = 1;
con x[dim];
end test;
// usage
test(dim = 10);
...
equation
connect(t.x[1], a);
connect(t.x[2], b);
...
Related
I have a question regarding the timing when accessing / reassigning variables either from a matlab struct or a matlab variable (any array):
Imagine the scenario that you have one function that creates ten variables (arrays of different dimensions and sizes). This function is getting called within another function that will need these variables produced.
Now, because getting ten variables from a function looks messy, I thought about storing these ten variables in a struct instead, and change my initial function so that it outputs only one struct (with ten fields) instead of ten variables.
Because timing is crucial for me (it's code for an EEG experiment), I wanted to make sure, that the struct approach is not slower, so I wrote the following test function.
function test_timingStructs
%% define struct
strct.a=1; strct.b=2; strct.c=3;
%% define "loose" variables
a = 1; b = 2; c = 3;
%% How many runs?
runs = 1000;
%% time access to struct
x = []; % empty variable
tic
for i=1:runs
x = strct.a; x = strct.b; x = strct.c;
end
t_struct = toc;
%% time access to "loose variables"
x = []; % empty variable
tic
for i=1:runs
x = a; x = b; x = c;
end
t_loose = toc;
%% Plot results
close all; figure;
bar(cat(2,t_struct,t_loose));
set(gca,'xticklabel', {'struct', 'loose variable'})
xlabel('variable type accessed', 'fontsize', 12)
ylabel(sprintf('time (ms) needed for %d accesses to 3 different variables', runs), 'fontsize', 12)
title('Access timing: struct vs "loose" variables', 'fontsize', 15)
end
According to the results, accessing a structure to get the values of a field is considerably slower than just accessing a variable. Can I make this assumption based on the test that I have done?
Is there another way to neatly "package" the ten variables without losing time when I want to access them?
In theory, yes, the access to data within a struct is going to be slower than access to data stored in a variable. This is just the overhead that the higher level datatype incurs.
BUT
In your tests, you are only measuring the access time of the data within the two data structures. When you are using variables, simply assigning one variable to another takes very little time because MATLAB uses copy-on-write and does not actually make a copy of the data in memory until it is modified.
As a result, the test that you have written isn't very useful for determining the actual cost of using a struct because I'm sure your function does something with the data that it receives. As soon as you modify the data, MATLAB will make a copy of the data and peform the requested operation. So to determine what the performance penalty of a struct is, you should time your actual function rather than the no-op function that you're using.
A slightly more realistic test
I have written a test below which compares the struct and variable access where the called function does and does not modify the data.
function timeaccess
sz = round(linspace(1, 200, 100));
[times1, times2, times3, times4] = deal(zeros(size(sz)));
for k = 1:numel(sz)
n = sz(k);
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times1(k) = timeit(#()access_struct(S));
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times2(k) = timeit(#()access_struct2(S));
a = rand(n); b = rand(n); c = rand(n);
times3(k) = timeit(#()access_vars(a, b, c));
a = rand(n); b = rand(n); c = rand(n);
times4(k) = timeit(#()access_vars2(a, b, c));
end
figure
hax1 = subplot(1,2,1);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times2 * 1000, 'DisplayName', 'Struct w/o modification')
plot(sz, times4 * 1000, 'DisplayName', 'Variables w/o modification')
legend(findall(hax1, 'type', 'line'))
hax2 = subplot(1,2,2);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times1 * 1000, 'DisplayName', 'Struct w modification')
plot(sz, times3 * 1000, 'DisplayName', 'Variables w modification')
legend(findall(hax2, 'type', 'line'))
saveas(gcf, 'data_manipulation.png')
legend()
end
function [a, b, c] = access_struct(S)
a = S.a + 1;
b = S.b + 2;
c = S.c + 3;
end
function [a, b, c] = access_struct2(S)
a = S.a;
b = S.b;
c = S.c;
end
function [d, e, f] = access_vars(a, b, c)
d = a + 1;
e = b + 1;
f = c + 1;
end
function [d, e, f] = access_vars2(a, b, c)
d = a;
e = b;
f = c;
end
The results
As you can see, the struct is slower for just assigning a variable to another variable, but as soon as I perform an operation (here I have the very simple operation of adding a constant to each variable), the effect of the access time is negligible.
Summary
Based on the test above, I would assume that the time difference between the two is going to be negligible for your use case. Even if the struct is a little slower, it may be a cleaner design and result in more readable / maintainable code and may be worth the difference in performance.
If you're very concerned about performance, it may be worth looking into a C/C++ mex function to do some of the heavy lifting for you or switch to a more performant language than MATLAB.
I'm trying to create a function that reads in a field of a structure to create a vector of fields. I have a structure of the form:
subject(i).stride(j).strideLength
and there are 10 subjects, about 10 strides per subject. I can create a long vector of the strideLength of all subjects, all strides with code like this:
k = 1;
for i=1:10
for j=1:size(subject(i).stride, 2)
varVector(k) = subject(i).stride(j).strideLength;
k = k + 1;
end
end
however, there are a lot of different fields I want to do this with, and I'd like to do it with a function that I can call like this:
x(1) = groupData(strideLength);
but I can't figure out the syntax to append strideLength to subject(i).stride(j). within the above loop in a function. This is what I hoped would work and didn't:
function [varVector] = groupData(var)
%groupData returns a concatenated vector of a given variable (speed, etc.)
k = 1;
for i=1:10
for j=1:size(subject(i).stride, 2)
varVector(k) = subject(i).stride(j).var;
k = k + 1;
end
end
end
Any thoughts on how to do this right? Thanks in advance!
In your groupData function, pass in the field/variable name as a string
x(1) = groupData('strideLength');
Then in the body of the code, access this field as follows
varVector(k) = subject(i).stride(j).(var);
Try the above and see what happens!
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
Being new to MATLAB, I am trying to write a class where, if one of two properties changes value, a third property is automatically recalculated.
It seems events and listeners are made for this, but I just can't get the hang of their basic implementation.
My latest attempt is this
% when property a or b is altered, c will automatically be recalculated
classdef myclass < handle
properties
a = 1;
b = 2;
c
end
events
valuechange
end
methods
function obj = myclass()
addlistener(obj,'valuechange', obj.calc_c(obj))
end
function set_a(obj, input)
obj.a = input;
notify(obj, valuechange)
end
function set_b(obj, input)
obj.b = input;
notify(obj, valuechange)
end
function calc_c(obj)
obj.c = obj.a + obj.b
end
end
end
Which returns following error
Error using myclass/calc_c
Too many output arguments.
Error in myclass (line 18)
addlistener(obj,'valuechange', obj.calc_c(obj))
What am I doing wrong?
Don't you want instead to define c as Dependent, so that every time you use it you are sure that it has been updated?
Something like this
classdef myclass < handle
properties
a
b
end
properties (Dependent)
c
end
methods
function x = get.x(obj)
%Do something to get sure x is consistent
x = a + b;
end
end
Suppose I have the following class:
classdef myClass < handle
properties
A = 1
end
methods
function obj = myClass(val)
obj.A = val;
end
end
end
Say I instantiate an instance of this class, then manipulate it slightly and then copy it. As it's a handle class, the "copy" is really just another instance of the same object:
>> q = myClass(10);
>> q.A = 15;
>> w = q;
>> disp(w.A)
15
But I would like to watch A without needing to instantiate myClass. Naively doing
>> value = w.A
doesn't work, since this just copies the value; changning w.A later on will not change value.
Is there a way to provide a "pointer" or "reference" to w.A without having to create a separate handle class? I'd rather keep the notation w.A rather than something like w.A.value (with me having to create the handle class to contain that value).
EDIT: I am using this functionality in order to help encapsulate my code for use with my research lab. I am designing an interface between MATLAB and Arduino to control air and ground vehicles; I was hoping to access stuff like "vehicle.pwmMax", "vehicle.flightCeiling", etc, to encapsulate the underlying object: "vehicle.Globals.pwmMax.value", etc.
You could do this by with a PropertyReference class
classdef PropertyReference < handle
%PropertyReference Reference to a property in another object
properties
sourceHandle
sourceFieldName
end
properties (Dependent = true)
Value
end
methods
function obj = PropertyReference (source, fieldName)
obj.sourceHandle = source;
obj.sourceFieldName = fieldName
end
function value = get.Value( obj )
value = obj.sourceHandle.(obj.sourceFieldName);
end
function set.Value( obj, value )
obj.sourceHandle.(obj.sourceFieldName) = value;
end
function disp( obj )
disp(obj.Value);
end
end
end
Continuing your example, you could then use PropertyReference as follows:
q = myClass(10);
>> q.A = 15;
>> ref = PropertyReference(q,'A');
>> disp(ref)
15
>> q.A = 42;
>> disp(ref)
42
Usage of the PropertyReference class is a bit awkward but the original class remains unchanged.
EDIT - Added disp function overload as per strictlyrude27 comment
I don't think there is anything that will do exactly as you want, given all your constraints.
However, I'm not really clear on your notational issues. Why do you want to retain the notation w.A while you are considered about value not changing? Keeping the notation w.A similar is not a real issue.
Using some modified code, I can produce following execution:
>> q = myClass(10);
>> q.A = 15;
>> w = q;
>> w.A
15
>> value = w.Aref;
>> value()
15
>> w.A = 20;
>> value()
ans =
20
But there is no way around the notation value() as that is the turning point of the implementation; which I think is the closest you can get to what you want. You get the behavior above when you use the following code to implement myClass:
classdef myClass < handle
properties
A = 1;
end
methods
function obj = myClass(val)
obj.A = val;
end
function a = Aref(obj)
a = #()(obj.A);
end
end
end
So you see that the Aref method actually returns a function handle which fetches the value from the object. This also means that this reference is read-only!
Also note that you will have to instantiate a myClass instance before you are able to get the value of A (where would you get the value of A from otherwise?). This instance does not have to be visible inside your current workspace (e.g. another function scope), since the myClass instance is stored within the function handle value.
Drawback of this method is that you only get a read-only reference, you will have to use the call value() to get the actual value instead of the function handle (so that changes the notation, but not the one you wanted to keep (or at least it can be made so by substituting A in my code by Aval and renaming Aref to A). Another drawback is that resolving value might be a bit slower than simply resolving a variable (whether that's a problem will depend on your usage of value()).
If you want some of the notations changed, this can be done by using dependent properties:
classdef myClass < handle
properties (Access=private)
Aval = 1;
end
properties (Dependent)
A;
end
methods
function obj = myClass(val)
obj.A = val;
end
function a = get.A(obj)
a = #()(obj.Aval);
end
function set.A(obj,value)
obj.Aval = value;
end
end
end
The equivalent execution of above is given by:
>> q = myClass(10);
>> q.A = 15;
>> w = q;
>> w.A()
15
>> value = w.A;
>> value()
15
>> w.A = 20;
>> value()
ans =
20
edit: I thought of another way to implement this, which is simpler (i.e. just keep the class of your original post) but it requires you to change the code in other places. The basic idea behind it is the same as the first ones, but without encapsulating it in the object itself (which makes the object cleaner, IMHO).
>> q = myClass(10);
>> q.A = 15;
>> w = q;
>> w.A()
15
>> value = #()(w.A);
>> value()
15
>> w.A = 20;
>> value()
ans =
20
Since you are working with a handle class, both q and w in your example refer to the same object in memory; they are themselves a "pointer"/"reference" to the object they represent.
So continuing your example, if you make changes to one, it will be reflected in the other.
>> q = myClass(10);
>> w = q;
>> q.A = 99;
>> disp(w.A)
99
Also note that you are not creating another instance of the class when you call w = q;. Compare the following examples in terms of memory space:
>> q = myClass(rand(7000));
>> m = memory; disp(m.MemUsedMATLAB)
792870912
>> w = q;
>> m = memory; disp(m.MemUsedMATLAB)
792834048
Against:
>> q = myClass(rand(7000));
>> w = myClass(rand(7000));
??? Error using ==> rand
Out of memory. Type HELP MEMORY for your options.
EDIT
Playing around with this, I came up with the following hackish solution.
First we create a wrapper function around the class constructor. It creates an object as usual, plus it returns a function handle that acts as a read-only accessor to a closure variable synced with the original object property using a "PostSet" events listener.
The only change to the original class is to add the SetObservable property attribute:
myClass.m
classdef myClass < handle
properties (SetObservable)
A
end
methods
function obj = myClass(val)
obj.A = val;
end
end
end
myClassWrapper.m
function [w A] = myClassWrapper(varargin)
w = myClass(varargin{:});
A = #getWA;
%# closure variable
a = w.A;
%# add listener to when w.A changes
addlistener(w, 'A', 'PostSet',#changeCallback);
function val = getWA()
%# return the value of the closure variable
val = a;
end
function changeCallback(obj,ev)
%# update the closure variable
a = ev.AffectedObject.A;
%#fprintf('Value Changed to %g\n',a)
end
end
Now we can use the wrapper as:
>> [w a] = myClassWrapper(10);
>> a()
ans =
10
>> w.A = 99;
>> a()
ans =
99