Say, we have a class Car
classdef Car < handle
properties
wheels = 4;
end
methods
function obj = Car()
end
end
end
We can create ten cars like so
cars = Car.empty();
for ii = 1:10
cars(end+1) = Car;
end
However, one can make an empty array of cars first
>> cars = Car.empty(0,10)
cars =
0x10 Car array with properties:
wheels
What I do not understand: If one now puts a single car in it, the array seems to shrink to a single element
>> cars(1) = Car
cars =
Car with properties:
wheels: 4
So, does allocating such an empty array make any sense? What are the use cases?
First of all, note that your question is not directly related to custom classes - you can do this with any MATLAB variable type. For example,
>> a = double.empty(0,10)
a =
Empty matrix: 0-by-10
So your questions are
What I do not understand: If one now puts a single car in it, the array seems to shrink to a single element
Well no, it has grown to a single element. I guess there is an ambiguity here, in that you might expect it to grow not to a 1x1 array but to a 1x10 array, with the other nine elements that weren't directly assigned being set to default (i.e. zero in the case of doubles or other numbers, or to a default element in the case of a custom class). However, I think the only thing to say there is that that's not what MATLAB does.
does allocating such an empty array make any sense? What are the use cases?
The use cases are very few in general, really just edge cases. The capability of having arrays of with zero-length dimensions is obviously required to be there for consistency, but an array of 0x10 is rarely much different in behaviour from an array of 0x0.
If I have an array that may vary in height but will always be 10 wide, I might predefine it as 0x10 rather than 0x0, just to leave myself a reminder in the code of that fact.
Also note that there are differences in behaviour between [] and double.empty(0,0). For example
>> a = rand(4,2)
a =
0.83625 0.19468
0.58508 0.12698
0.44332 0.8509
0.51858 0.3673
>> a(2,:) = []
a =
0.83625 0.19468
0.44332 0.8509
0.51858 0.3673
>> a(2,:) = double.empty(0,0)
Subscripted assignment dimension mismatch.
>> a(2,:) = double.empty(0,2)
Improper assignment with rectangular empty matrix.
This is because = [] is a special piece of MATLAB syntax that is used for deleting rows, rather than literally constructing the empty array and then assigning it. So there's another use case there, i.e. preventing accidental deletion of rows.
This is not a problem related to object programming but a normal behavior which is more general in Matlab.
For instance:
>> a = NaN(0,10);
>> a(1) = 5;
>> a
a =
5
When you define an array of size 0xn Matlab does not allocate any memory to it, since there is no element. So a call to empty(0,10) should not be considered as a pre-allocation.
When you define the first element of the array, you force a resizing, and during resizing Matlab always adopts the minimal possible size for the array.
The empty syntax is useful to define an array that will be filled by aggregation in a loop with the end+1 syntax, for instance:
a = NaN(0,2);
for i = 1:10
a(end+1,:) = [i i^2];
end
Best,
Related
Working in MATLAB R2017a. I'm trying to optimise a piece of code I'm working on. It uses arrays to store field values on a grid.
In order to create a specific function in a field array I originally used the straight forward method of two for loops iterating over all the array elements. But i know for loops are slow so since then I came back and tried my best to remove them. However I could only manage to remove one of the loops; leaving me with this:
for n = 1:1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp * (1/(1+exp(-(t-stepuppos)))) * exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg))*exp(-((t-((ztemp-...
THzstartz)/vg))^2)/(bt^2));
end
The important bit here is the last 5 lines, but I figured the stuff before might be important for context. I've removed the for loop looping over the x coordinates. I want to vectorize the z/k for loop but I can't figure out how to distinguish between the dimensions with the array oporators.
Edit: THzamp, stepuppos, bx, bt, THzstartz, THzstartx are all just scalars, they control the function (Ez0) I'm trying to create. dX and t are also just scalars. Ez0 is a square array of size Ng.
What I want to achieve is to remove the for loop that loops over k, so that that the values of ztemp are defined in a vector (like xtemps already is), rather than individually in the loop. However, I don't know how I'd write the definition of Ez0 in that case.
First time posting here, if I'm doing it wrong let me know. If you need more info just ask.
It isn't clear if n is used in the other headers and as stated in the comments your sizes aren't properly defined so you'll have to ensure the sizes are correct.
However, you can give this vectorize code a try.
n = 1:K
%%% define initial pertubation
t=n*dt;
% create array for source Ez field.
xtemps = (1:Ng)*dX;
for k = 1:Ng
ztemp = k*dX;
Ez0(k,:) = THzamp .* (1./(1+exp(-(t-stepuppos)))) .* exp(-((xtemps-...
THzstartx).^2)./(bx^2)) .* (t-((ztemp-THzstartz)/vg)).*exp(-((t-((ztemp-...
THzstartz)/vg)).^2)/(bt.^2));
end
So now t has the size K you'll need to ensure stepupposand (ztemp-THzstartz)/vg) have the same size K. Also you can take a look at vectors vs array operators here.
I've been learning Julia by trying to write a simple rigid body simulation, but I'm still somewhat confused about the assignment and mutating of variables.
I'm storing the points making up the shape of a body into an array of arrays where one vector holds the x,y,z coordinates of a point. For plotting the body with PyPlot the points are first transformed from local coordinates into world coordinates and then assigned to three arrays which hold the x, y, and z coordinates for the points respectively. I would like to have the three arrays only reference the array of arrays values instead of having copies of the values.
The relevant part of my code looks like this
type Rigidbody
n::Integer
k::Integer
bodyXYZ::Array{Array{Float64,1},2}
worldXYZ::Array{Array{Float64,1},2}
worldX::Array{Float64,2}
worldY::Array{Float64,2}
worldZ::Array{Float64,2}
Rotmat::Array{Float64,2}
x::Array{Float64,1}
end
# body.worldXYZ[1,1] = [x; y; z]
# and body.worldX[1,1] should be body.worldXYZ[1,1][1]
function body_to_world(body::Rigidbody)
for j in range(1, body.k)
for i in range(1, body.n)
body.worldXYZ[i,j] = body.x + body.Rotmat*body.bodyXYZ[i,j]
body.worldX[i,j] = body.worldXYZ[i,j][1]
body.worldY[i,j] = body.worldXYZ[i,j][2]
body.worldZ[i,j] = body.worldXYZ[i,j][3]
end
end
return nothing
end
After calling the body_to_world() and checking the elements with === they evaluate to true but if I then for example set
body.worldXYZ[1,1][1] = 99.999
the change is not reflected in body.worldX. The problem is probably something trivial but as can be seen from my code, I am a beginner and could use some help.
body.worldX[i,j] = body.worldXYZ[i,j][1]
You're setting a number to a number here. Numbers are not mutable, so body.worldX[i,j] won't refer back to body.worldXYZ[i,j][1]. What you're thinking of is that the value of an array will be a reference, but numbers don't have references, just the value themselves.
However, I would venture to say that if you're doing something like that, you're going about the problem wrong. You should probably be using types somewhere. Remember, types in Julia give good performance, so don't be afraid of them (and immutable types should be almost perfectly optimized after carneval's PR, so there's really no need to be afraid). Instead, I would make world::Array{Point,2} where
immutable Point{T}
x::T
y::T
z::T
end
Then you can get body.world[i,j].x for the x coordinate, etc. And then for free you can use map((i,j)->Ref(body.world[i,j].x),size(body.world)...) to get an array of references to the x's.
Or, you should be adding dispatches to your type. For example
import Base: size
size(RigidBody) = (n,k)
now size(body) outputs (n,k), as though it's an array. You can complete the array interface with getindex and setindex!. This kind of adding dispatches to your type will help clean up the code immensely.
The point of indexing is mainly to get the value. In MATLAB,
for a cell array, there is content indexing ({}), and thus cell indexing (()) is only for selecting a subset from the cell array, right?
Is there anything other advanced usage for it? Like using it as
a pointer and pass it to a function?
There is a heavily simplified answer. {}-indexing returns you the content, ()-indexing creates a subcell with the indexed elements. Let's take a simple example:
>> a=x(2)
a =
[2]
>> class(a)
ans =
cell
>> b=x{2}
b =
2
>> class(b)
ans =
double
Now continue with non-scalar elements. For the ()-indexing everything behaves as expected, you receive a subcell with the elements:
>> a=x(2:3)
a =
[2] [3]
The thing really special to Matlab is using {}-indexing with non-scalar indices. It returns a Comma-Separated List with all the contents. Now what is happening here:
>> b=x{2:3}
b =
2
The Comma-Separated List behaves similar to a function with two return arguments. You want only one value, only one value is assigned. The second value is lost. You can also use this to assign multiple elements to individual lists at once:
>> [a,b]=x{2:3} %old MATLAB versions require deal here
a =
2
b =
3
Now finally to a very powerful use case of comma separated lists. Assume you have some stupid function foo which requires many input arguments. In your code you could write something like:
foo(a,b,c,d,e,f)
Or, assuming you have all parameters stored in a cell:
foo(a{1},a{2},a{3},a{4},a{5},a{6})
Alternatively you can call the function using a comma separated list. Assuming a has 6 elements, this line is fully equivalent to the previous:
foo(a{:}) %The : is a short cut for 1:end, index the first to the last element
The same technique demonstrated here for input arguments can also be used for output arguments.
Regarding your final question about pointers. Matlab does not use pointers and it has no supplement for it (except handle in oop Matlab), but Matlab is very strong in optimizing the memory usage. Especially using Copy-on-write makes it unnecessary to have pointers in most cases. You typically end up with functions like
M=myMatrixOperation(M,parameter,parameter2)
Where you input your data and return it.
Updated Question; Original below.
I am trying to create an array which represents a grid of cells, which have tuples containing the walls they are surrounded by.
I have come up with this:
rooms(Array) ->
Size = array:size(Array),
if
Size == ?HSIZE * ?VSIZE ->
Array;
true ->
HFactor = Size rem ?VSIZE,
VFactor = Size div ?HSIZE,
Room = {1+HFactor+11*VFactor,
7+HFactor+11*VFactor,
12+HFactor+11*VFactor,
6+HFactor+11*VFactor},
rooms(array:set(Size, Room, Array))
end.
When I run this with rooms(array:new()). I get the following array back:
{array,25,100,undefined,
{{{1,7,12,6},
{2,8,13,7},
{3,9,14,8},
{4,10,15,9},
{5,11,16,10},
{12,18,23,17},
{13,19,24,18},
{14,20,25,19},
{15,21,26,20},
{16,22,27,21}},
{{23,29,34,28},
{24,30,35,29},
{25,31,36,30},
{26,32,37,31},
{27,33,38,32},
{34,40,45,39},
{35,41,46,40},
{36,42,47,41},
{37,43,48,42},
{38,44,49,43}},
{{45,51,56,50},
{46,52,57,51},
{47,53,58,52},
{48,54,59,53},
{49,55,60,54},
undefined,undefined,undefined,undefined,undefined},
10,10,10,10,10,10,10,10}}
Which is quite close to the desired result, but there are two things I can't quite put my finger on (The numbers are correct). Why does it look like it is split up into multiple subarrays? What are those undefineds and 10's doing there? These are mostly due to my lack of erlang knowledge, because array:get produces the expected results, but I couldn't find anything which explains where they come from.
Original Question
rooms(Array) ->
Size = array:size(Array),
if
Size == 5 ->
Array;
Size rem 5 == 0 ->
rooms(array:set(Size, array:new(), Array));
true ->
In_Array = array:get(array:size(Array), Array),
In_Size = array:size(In_Array),
Room = {1+In_Size+11*In_Size,
7+In_Size+11*In_Size,
12+In_Size+11*In_Size,
6+In_Size+11*In_Size},
New_In = array:set(In_Size, Room, In_Array),
rooms(array:set(Size, New_In, Array))
end.
I call it with rooms(array:new()). but the result is
** exception error: bad argument
in function array:size/1 (array.erl, line 317)
in call from framework_kamer:rooms/1 (framework_kamer.erl, line 195)
Which makes sense because In_Array is not an array, but undefined. However, I can't figure out why.
Side question, is there an easier/cleaner/better way to do this?
You are (in the second call of the recursion) trying
In_Array = array:get(array:size(Array), Array),
As array is zero-indexed this will always fail, as the access will be always be off by one. Change this line to
In_Array = array:get(array:size(Array) - 1, Array),
and you are fine.
A few comments on your code:
Conventional variable naming in Erlang would be CamelCase without underscores (i.e. InArray)
Expressing a 2-dimensional array as nested arrays is almost never a good idea. Linearalise it by writing simple wrappers that recalculate a one-dimensional index from x and y as index = y * max_x + x.
Is there any way to "vector" assign an array of struct.
Currently I can
edges(1000000) = struct('weight',1.0); //This really does not assign the value, I checked on 2009A.
for i=1:1000000; edges(i).weight=1.0; end;
But that is slow, I want to do something more like
edges(:).weight=[rand(1000000,1)]; //with or without the square brackets.
Any ideas/suggestions to vectorize this assignment, so that it will be faster.
Thanks in advance.
This is much faster than deal or a loop (at least on my system):
N=10000;
edge(N) = struct('weight',1.0); % initialize the array
values = rand(1,N); % set the values as a vector
W = mat2cell(values, 1,ones(1,N)); % convert values to a cell
[edge(:).weight] = W{:};
Using curly braces on the right gives a comma separated value list of all the values in W (i.e. N outputs) and using square braces on the right assigns those N outputs to the N values in edge(:).weight.
You can try using the Matlab function deal, but I found it requires to tweak the input a little (using this question: In Matlab, for a multiple input function, how to use a single input as multiple inputs?), maybe there is something simpler.
n=100000;
edges(n)=struct('weight',1.0);
m=mat2cell(rand(n,1),ones(n,1),1);
[edges(:).weight]=deal(m{:});
Also I found that this is not nearly as fast as the for loop on my computer (~0.35s for deal versus ~0.05s for the loop) presumably because of the call to mat2cell. The difference in speed is reduced if you use this more than once but it stays in favor of the for loop.
You could simply write:
edges = struct('weight', num2cell(rand(1000000,1)));
Is there something requiring you to particularly use a struct in this way?
Consider replacing your array of structs with simply a separate array for each member of the struct.
weights = rand(1, 1000);
If you have a struct member which is an array, you can make an extra dimension:
matrices = rand(3, 3, 1000);
If you just want to keep things neat, you could put these arrays into a struct:
edges.weights = weights;
edges.matrices = matrices;
But if you need to keep an array of structs, I think you can do
[edges.weight] = rand(1, 1000);
The reason that the structs in your example don't get initialized properly is that the syntax you're using only addresses the very last element in the struct array. For a nonexistent array, the rest of them get implicitly filled in with structs that have the default value [] in all their fields.
To make this behavior clear, try doing a short array with clear edges; edges(1:3) = struct('weight',1.0) and looking at each of edges(1), edges(2), and edges(3). The edges(3) element has 1.0 in its weight like you want; the others have [].
The syntax for efficiently initializing an array of structs is one of these.
% Using repmat and full assignment
edges = repmat(struct('weight', 1.0), [1 1000]);
% Using indexing
% NOTE: Only correct if variable is uninitialized!!!
edges(1:1000) = struct('weight', 1.0); % QUESTIONABLE
Note the 1:1000 instead of just 1000 when indexing in to the uninitialized edges array.
There's a problem with the edges(1:1000) form: if edges is already initialized, this syntax will just update the values of selected elements. If edges has more than 1000 elements, the others will be left unchanged, and your code will be buggy. Or if edges is a different type, you could get an error or weird behavior depending on its existing datatype. To be safe, you need to do clear edges before initializing using the indexing syntax. So it's better to just do full assignment with the repmat form.
BUT: Regardless of how you initialize it, an array-of-structs like this is always going to be inherently slow to work with for larger data sets. You can't do real "vectorized" operations on it because your primitive arrays are all broken up in to separate mxArrays inside each struct element. That includes the field assignment in your question – it is not possible to vectorize that. Instead, you should switch a struct-of-arrays like Brian L's answer suggests.
You can use a reverse struct and then do all operations without any errors
like this
x.E(1)=1;
x.E(2)=3;
x.E(2)=8;
x.E(3)=5;
and then the operation like the following
x.E
ans =
3 8 5
or like this
x.E(1:2)=2
x =
E: [2 2 5]
or maybe this
x.E(1:3)=[2,3,4]*5
x =
E: [10 15 20]
It is really faster than for_loop and you do not need other big functions to slow your program.