In order to preallocate memory in Matlab, I want to initialize my array of objects. How do I do this? - arrays

I have a class of objects known as blocks. Currently, I am creating an array of blocks using a for loop by simply tacking them unto an empty array
blockArray=[];
for ii=1:Size
blockArray=[blockArray block(....)];
end
In order to preallocate memory, how do I initialize an object array of blocks with dummy values?
For instance if instead of using block objects I used numbers, I could easily preallocate by using zeros(1,Size). Is there something similar that I could do?

The matlab documentation describes
To preallocate the object array, assign the last element of the array first. MATLABĀ® fills the first to penultimate array elements with default DocArrayExample objects.
So, to do this, instead of iterating over from 1:size, it is simpler to do...
blockArray = []
blockArray(size) = block(...)

The language does not really support this, there exists multiple solutions (or workarounds).
Replicating the first instance
When pushing the first element into the array, you can fill the whole array with this element to achieve a preallocation. This might look very bad, but it is actually the fastest possibility known to me.
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
if ii==1
%to do preallocation, fill it with your first element
blockArray(1:S)=e
else
blockArray(ii)=e
end
end
Use cell arrays
Obvious simple solution, you can put any class into the fields
blockArray=cell(S,1);
for ii=1:S
%assumption e is a scalar, otherwise the code is totally screwed
e=block(....)
blockArray{ii}=e
end
This solution is very simple but slower than the first. You also lose some functionality which is not available for cell arras
Let your class implement array functionality
classdef A
properties
arg1
out
end
methods
function obj = A(varargin)
if nargin==0
%null object constructor
elseif strcmpi(varargin{1},'createarray')
sz=varargin(2:end);
%preallocate
obj(sz{:})=A;
else
%standard constructor
obj.arg1=varargin{1};
obj.out=[1 2 3;];
end
end
end
end
Constructor with no input argument creates an "empty" or "null" object, this is used to preallocate so it should be empty.
Constructor with first parameter makearray creates an array
Otherwise your constructor should be called.
Usage:
%create an empty object
A
%create an array of size 2,3,4
A('createarray',2,3,4)
%use the standard constructor
A(2)
Biggest downside is you have to modify your classes. Never tested this solution, but it should be close to the first in performance.

Related

Why does `append(x[:0:0], x...)` copy a slice into a new backing array in Go?

On Go's slice tricks wiki and Go libraries (e.g., this example), you sometimes see code like the following to copy a slice into a new backing array.
// In a library at the end of a function perhaps...
return append(whateverSlice[:0:0], whateverSlice...)
// In an assignment, as in the wiki example...
b = append(a[:0:0], a...)
Here's what I think I understand:
All of the items in the slice that is the second parameter to append are copied over to a new backing array.
In the first parameter to append, the code uses a full slice expression. (We can rewrite the first parameter as a[0:0:0], but the first 0 will be supplied if omitted. I assume that's not relevant to the larger meaning here.)
Based on the spec, the resulting slice should have the same type as the original, and it should have a length and capacity of zero.
(Again, not directly relevant, but I know that you can use copy instead of append, and it's a lot clearer to read.)
However, I still can't fully understand why the syntax append(someSlice[:0:0], someSlice...) creates a new backing array. I was also initially confused why the append operation didn't mess with (or truncate) the original slice.
Now for my guesses:
I'm assuming that all of this is necessary and useful because if you just assign newSlice := oldSlice, then changes to the one will be reflected in the other. Often, you won't want that.
Because we don't assign the result of the append to the original slice (as is normal in Go), nothing happens to the original slice. It isn't truncated or changed in any way.
Because the length and capacity of anySlice[:0:0] are both zero, Go must create a new backing array if it's going to assign the elements of anySlice to the result. Is this why a new backing array is created?
What would happen if anySlice... had no elements? A snippet on the Go Playground suggests that if you use this append trick on an empty slice, the copy and the original initially have the same backing array. (Edit: as a commenter explains, I misunderstood this snippet. The snippet shows that the two items are initially the same, but neither has a backing array yet. They both point initially to a generic zero value.) Since the two slices both have a length and capacity of zero, the minute you add anything to one of them, that one gets a new backing array. Therefore, I guess, the effect is still the same. Namely, the two slices cannot affect each other after the copy is made by append.
This other playground snippet suggests that if a slice has more than zero elements, the append copy method leads immediately to a new backing array. In this case, the two resulting slices come apart, so to speak, immediately.
I am probably worrying way too much about this, but I'd love a fuller explanation of why the append(a[:0:0], a...) trick works the way it does.
Because the length and capacity of anySlice[:0:0] are both zero, Go must create a new backing array if it's going to assign the elements of anySlice to the result. Is this why a new backing array is created?
Because capacity is 0, yes.
https://pkg.go.dev/builtin#go1.19.3#append
If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated.
cap=0 is NOT sufficient for non-empty slice, allocating a new array is necessary.

Can't resize my array to a smaller size

I defined this StackOfStringsArray class that contains one array instance #stringArray and an array index variable, and as below I defined a resize method in it to make #stringArray resizable. I knew Ruby's array is natively sizeable, but I want to implement mine.
In addition, when I did the experiment in irb I could do it successfully (new a sized array and assign it to the StackOfStringsArray object's #stringArray, and I could see the #stringArray did have same size as the new array), but by using this resize method I can just make it becomes bigger size array but not smaller one, even though I'm sure it does go into this resize method.
Could some Ruby ninja help out? Thanks so much.
class StackOfStringsArray
attr_accessor :stringArray, :index
def initialize(size)
#stringArray = Array.new(size)
#index = 0
end
def resize(size)
copy = Array.new(size)
#stringArray.each_with_index do |element, index|
copy[index] = element
end
#stringArray = copy
end
end
... I can just make it becomes bigger size array but not smaller one...
... I knew Ruby's array is natively sizeable ...
That is the root of your problem. You iterate the old, bigger array and the new copy resizes to accomodate all of its elements. To fix this, take no more than size elements from the old array.
Since this is a challenge you imposed upon yourself, I'm not giving you the actual code. This hint should be enough, I hope.

Preallocate memory for object array

I have a self defined class ClassA, and I want to create an empty object array of size N to store N ClassA objects.
Right now I am using an empty cell array cellarrayA = cell(N,1), and putting each object into the cell, like cellarrayA(n) = ClassA(input(n)). And once they're all done I turn the cell array into object array using objarrayA = [cellarrayA{:}].
It works (Matlab does not complain) but I don't think it actually preallocate the right amount of memory, because how can a cell array know the size of my object before it's created? The size of my object could be fairly large, on the order of 1MB (but it could vary). I would guess I might be suffering the same performance penalty just as if I'm not preallocating anything at all, although I won't be able to verify it. So how can I preallocate the object array, instead of using the cell array?
Normally, this is what I do in order to achieve class array "preallocation":
1) I define a constructor in my class that accepts no input arguments, as follows:
classdef MyClass
properties
MyProperty
end
methods
function obj = MyClass()
% ...
end
end
end
2) I use the repmat function in order to instantiate an array of MyClass instances:
classes = repmat(MyClass(),10,1);
3) If necessary, I loop over the array initializing the properties of instance with the proper values:
A = [ ... ]; % 10-by-1 matrix with numerical values
for i = 1:numel(classes)
classes(i).MyProperty = A(i);
end
If every instance can be initialized with the same default property values, I use the approach in Step 2 calling a constructor that is able to assign them properly instead:
classes = repmat(MyClass('default_property_value'),10,1);
You should by no means use this approach if your MyClass inherits from the handle class:
classdef MyClass < handle
% ...
end
otherwise the process will produce an array of copies of the same handle. Also, this method must not be intended as a true memory preallocation process, since it works by replicating a copy of a single allocated instance of the class over and over. For sure, this will make Matlab stop crying about a missing preallocation, if this is your main concern. And for sure this will retun an array of objects.

What is the best way to empty a Vector or Array in AS3?

What is the most efficient way to empty an Array or Vector in ActionScript 3?
I've always just re-initialized them:
vector = new Vector.<T>();
array = [];
It doesn't look like there's an empty() function or anything similar.
Is there a better way?
Re-initializing the array is fine in most cases, since the garbage collector will just sweep up the old array. Still, if you want to empty an array without creating a new one you can set array.length = 0
Another option is to use the splice method.
Array::splice documentation
For an array the following call empties it:
array.splice(0);
For a vector the second parameter is enforced, so the call becomes:
vector.splice(0, vector.length);

matlab initialize array of objects

I am playing around with OOP in MATLAB, and I have the following constructor:
function obj = Squadron(num_fighters, num_targets, time_steps)
if nargin == 0
num_targets = 100;
time_steps = 100;
num_fighters = 10;
end
obj.num_shooters = num_fighters;
for iShooter = 1:obj.num_shooters
a(iShooter) = Shooter(num_targets, time_steps);
end
obj.ShooterArray = a;
obj.current_detections = zeros(num_fighters, num_targets);
end
That temporary variable 'a' smells terrible. Is there a better way to initialize an array of objects, I wish there was a push/pop method. I am sure there is a better way to do this.
Looks like you are trying to create an array of handle objects (Shooters) and store it inside the property of another handle object (a Squardron). I have had a very similar problem discussion that might help you.
In short: What you are doing might not be pretty - but might be pretty good already.
When creating an array in Matlab it is usually a good Idea to do some pre-allocation to reserve memory which speeds up performance significantly.
In a normal case something like this:
a=zeros(1,1000);
for n=1:1000
a(n)=n;
end
(here a=1:1000; would be even better)
For objects the pre-allocation works by assigning one of the objects to the very last field in the array. Matlab then fills the other fields before that with objects (handles) that it creates by calling the constructor of that object with no arguments (see Matlab help). Hence a pre-allocation for objects could look like this:
a(1,1000)=ObjectConstructor();
for n=1:1000
a(n)=ObjectConstructor();
end
or simply
for n=1000:-1:1
a(n)=ObjectConstructor();
end
Making sure Shooter can be called with no arguments you should be able to do something like:
for iShooter = obj.num_shooters:-1:1
obj.ShooterArray(iShooter) = Shooter(num_targets, time_steps);
end
However, it turns out that for some reason this direct storing of an array of objects in another object's property creates very bad performance. (Probably the array pre-allocation does not work well in this case). Hence using an auxiliary variable and allocating the full array at once to the property is in this case is a good idea to increase performance.
I would try:
for iShooter = obj.num_shooters:-1:1
a(iShooter) = Shooter(num_targets, time_steps);
end
obj.ShooterArray = a;
Again - for more detail see this discussion
There are a couple of ways to handle this situation...
Building object arrays in the constructor:
You could modify your Shooter class such that when you pass arrays of values it creates an array of objects. Then you could initialize ShooterArray like so:
obj.ShooterArray = Shooter(repmat(num_targets,1,num_fighters),...
repmat(time_steps,1,num_fighters));
Replicating instances of a value class:
If Shooter is a value class, and each object is going to be exactly the same (i.e. you don't initialize any of its default properties to random values), then you can create just one object and replicate it using REPMAT:
obj.ShooterArray = repmat(Shooter(num_targets,time_steps),1,num_fighters);
Unfortunately, if Shooter is a subclass of the handle class, you can't just replicate it as you can with a value class. You would actually be replicating references to just one object, when you really need a number of separate objects each with their own unique reference. In such a case, your current code is likely the best solution.

Resources