14

I have an array of objects in MATLAB and I've called their constructors in a loop:

antsNumber  = 5;
for counter = 1: antsNumber
    ant(counter) = TAnt(source, target);
end

MATLAB warns me to use preallocation to speed up the process. I do know the benefits of preallocation but I don't know how to do that for objects.

Kamran Bigdely
  • 7,946
  • 18
  • 66
  • 86
  • 1
    Closely related question: http://stackoverflow.com/questions/591495/matlab-preallocate-a-non-numeric-vector – gnovice Mar 24 '10 at 18:43

4 Answers4

11

Here are a few options, which require that you design the class constructor for TAnt so that it is able to handle a no input argument case:

  • You can create a default TAnt object (by calling the constructor with no input arguments) and replicate it with REPMAT to initialize your array before entering your for loop:

    ant = repmat(TAnt(),1,5);  %# Replicate the default object
    

    Then, you can loop over the array, overwriting each default object with a new one.

  • If your TAnt objects are all being initialized with the same data, and they are not derived from the handle class, you can create 1 object and use REPMAT to copy it:

    ant = repmat(TAnt(source,target),1,5);  %# Replicate the object
    

    This will allow you to avoid looping altogether.

  • If TAnt is derived from the handle class, the first option above should work fine but the second option wouldn't because it would give you 5 copies of the handle for the same object as opposed to 5 handles for distinct objects.

gnovice
  • 125,304
  • 15
  • 256
  • 359
  • it virtually works but before that it should be modified to ant = repmat(TAnt(source,target),0,5) – Kamran Bigdely Mar 24 '10 at 18:59
  • @Kamran: That would give you an empty array (0-by-5). For preallocation, you really want to create a default array of the *same size* as what you will end up with (1-by-5). – gnovice Mar 24 '10 at 19:08
  • It seems so but the "(0,5)" works! when I try to use (1,5) it causes an error. – Kamran Bigdely Mar 24 '10 at 19:51
  • none of them works... it says: Expression or statement is incomplete or incorrect. – Kamran Bigdely Mar 24 '10 at 22:26
  • @Kamran: Since you haven't given any details about your `TAnt` class, I would have to guess that your errors are due to the fact that you didn't design your class constructor to handle a no input argument case. You must do this for these solutions to work. See this link: http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brd2m9e-1.html#bripq7u-1 – gnovice Mar 25 '10 at 03:07
  • it is not working for planeModel object. X = repmat(planeModel([0 0 1 0]),0,5); gives an error – Pedro77 Nov 04 '16 at 18:49
  • The links to the documentation are not working anymore. The content of the links can be found here: https://web.archive.org/web/20120306193932/http://www.mathworks.com/help/techdoc/matlab_oop/brd2m9e-1.html – Vasco Mar 31 '21 at 08:58
6

The following link might be of help:

http://www.mathworks.com/help/techdoc/matlab_oop/brd4btr.html#brd4nrh
Web archive of dead link

New link:
http://de.mathworks.com/help/matlab/matlab_oop/creating-object-arrays.html

embert
  • 7,336
  • 10
  • 49
  • 78
Waleed Al-Balooshi
  • 6,318
  • 23
  • 21
  • Thanks, it was massively helpful. I added ant = TAnt.empty(antsNumber,0) and it works! – Kamran Bigdely Mar 24 '10 at 18:50
  • According to the link, the answer is ant = TAnt.empty(antsNumber, 0) – Kamran Bigdely Mar 24 '10 at 19:04
  • 7
    @Kamran: Your solution using the `empty` method of an object may work in the sense that it makes MATLAB stop yelling at you about preallocation, but it isn't really preallocation because it is still an *empty* array. Take note of this statement in the documentation Waleed linked to, under the heading "Assigning Values to an Empty Array": "If you make an assignment to a property value, MATLAB calls the SimpleClass constructor to grow the array to the required size." Note the word **grow**, indicating that the array changes size when assigned to, which is what preallocation is meant to avoid. – gnovice Mar 24 '10 at 20:23
  • 5
    @Kamran: as pointed out by gnovice, using the static method `empty` does not really perform preallocation. Instead you should add the following line before the for loop: `ant(antsNumber) = TAnt(source, target);` provided you have a default constructor with nargin=0 (which is called for the elements in `ant(1:antsNumber-1)`) – Amro Mar 24 '10 at 22:35
1

The warning it gives is superfluous, unless you are doing computational heavy stuff, I would ignore it.

The reason why it's giving you the error, is because it has to find new space. Say, I give you a list of seven objects, and I tell you that you need to place them all in a row, I then go off, and give you a few more things you need to put somewhere. I then give you an eighth object and tell you to put it right after the seventh. Because you have stuff where the eighth object is, you either have to move it out of the way, or you have to move all seven objects. Matlab, is telling you it would be faster if you were to tell it beforehand that you want to put 5 things in there, rather than just giving it things one by one, having to look for a new spot each time. You can do that by adding this line to the top of your code:

ant = [1:5];

There are also other ways to do this too.

Leif Andersen
  • 21,580
  • 20
  • 67
  • 100
0

Not sure if I got your problem right, but if you want to initialize an array of your self-defined class "TAnt", here is how I would do it

  1. For TAnt's constructor method, put something like:

function obj = TAnt(source, target)
         if nargin > 0
              obj.mySource = source;
              obj.myTarget = target;
         else
              obj.mySource = defaultValue;
              obj.myTarget = defaultValue;
         end
    end

Then to initialize/pre allocate an array of default TAnt objects,

ants(1,n) =  TAnt();  % n is the length of your ants array
Min
  • 1