Matlab convert 4x4 into many 2x2 outputs assigned to one variable - algorithm

Could some one please provide a solution to turn this same outcome into one variable and limit the lines of code please. Im having trouble on how to work this algorithm.

Don't create dynamic variable names with numbers as part of the name. These variables will be hard to work with downstream in your code. Instead, you could use multi-dimensional arrays or perhaps cell arrays, which would allow you to use simple indexing downstream. E.g., here is a cell array approach:
[m n] = size(test_gray);
m2 = 2*ones(m/2,1);
n2 = 2*ones(n/2,1);
newarray = mat2cell(test_gray,m2,n2)
Now you can get at the individual 2x2 matrices with simple indexing into newarray.

Related

Julia - How do I add a matrix to a list of matrices

I'm new to Julia, and I am currently working on a model where I need to add a matrix to list of matrices. I am trying to accomplish this with:
push!(BranchDomainNew, BranchDomain[k])
Where BranchDomainNew is a 1x7 matrix (3D) made up of matrices. I am trying to append BranchDomain[k] (another matrix of the same dimensions) to this list. Ultimately, my goal is to have BranchDomainNew be 8 matrices long, with the last index containing BranchDomain[k].
Here's the error I keep getting:
MethodError: no method matching push!(::Matrix{Any}, ::Matrix{Bool})
I also tried using append!(), which unfortunately also did not work - I got the same error (except append! instead of push!). I'd love to know why these methods don't work for this, and how I can accomplish this goal. Also, I am working with version v"1.7.2". Thanks
You cannot push! or append! elements to a matrix, because matrices are 2-dimensional entities, and adding single elements could ruin its shape, and is therefore not allowed. You can instead concatenate rows or columns using hcat or vcat.
But it looks like what you really should use is a Vector, not a 1xN Matrix.
So make sure that BranchDomainNew is a Vector of matrices, instead of a Matrix of matrices. Then you can push! and append! all you like.
You did not show how you made your matrix, but it is possible that you did something like this:
BranchDomainNew = [mat1 mat2 mat3] # create 1x3 Matrix
when you should have done
BranchDomainNew = [mat1, mat2, mat3] # create length 3 Vector
It is a common mistake for many new Julia users to use 1xN or Nx1 matrices, when they should actually use a length-N vector. For example, they often initialize arrays as zeros(N, 1), when they should use zeros(N)
The difference is important, and in almost all cases a vector is better.

Using Linked List to represent a Matrix Class

I'm having trouble initializing the linked list for the matrix based on the parameters I input. So if I input the parameters (3,3) it should actually make make 4x4 so I can use the first column and first row for indexing. and the left top corner node as an entry point.
def __init__(self, m, n, default=0):
self._head = MatrixNode(None)
for node in range(m - 1):
node = MatrixNode(0)
node._right = node
for node in range(n - 1):
node = MatrixNode(0)
node._down = node
this is what I have so far but I'm sure its horrible.
At first, it may be useful to know, what a MatrixNode is. I guess you just want to store a value there?
Then i see two linear loops, while a matrix is a n*m data structure. Are you sure, your loops do not need to be nested to initialize your structure correctly?
For linked lists i would expect something like row.next = nextrow and row.startnode.next = nextnode, i do not see anything like this here.
Having this said, i want to ask you, if you really want to implement a matrix yourself, and in such an object oriented (inefficient!) way.
You can use two-dimensional arrays (a=[[1,2], [3,4]];a[0][0]==1) or a good implementation from a numerics library like numpy/scipy.
There you have numpy.array for storing n-dimensional data (with nice addressing like matrix[1,2] and similiar syntax to matlab) or numpy.matrix which is like an array with some methods overloaded for matrix operations (i.e. matrix-matrix multiplication of arrays is pointwise and for matrices it's the usual matrix multiplication).
You are right, its horrible :)
First things first, a linked list is a very bad way of representing a matrix.
If you want to represent a matrix, start with a list of lists, and work from there if that's not enough (see other answer mentioning numpy, for example)
If you want to learn to use linked lists, choose a better example.
Then: you are re-using the variable name "node" for different things:
Your loop index. The code for node in range(...) will assign an integer from the range to node in every iteration.
Then you assign a new MatrixNode to node, and then you set the node's neighbor (_right or _down) to be not the actual neighbor, but itself (node._right = node).
You also never save your nodes that you create inside the loops anywhere, so they will be garbage-collected.
And you never use the optional argument default.

sub2ind all x and y coordinates of a matrix

I am a quite newbie on matlab and i have a simple issue that is disturbing me,
I want to know if its possible to covert all the subscripts of a matrix to linear indices.
when using SUB2IND i must inform de x and y coordinates, but i want to convert all at the same time.
i can use function FIND which returns two vectors x and y and this way i can use SUB2IND succesfully, but FIND only returns the x and y coordinates of nonzero elements.
is there a smart way to do this?
If you want all of the elements of an array A as linear subscripts, this can be done simply via:
IND = 1:numel(A);
This works for any size or dimension array.
More on array indexing in Matlab, including the difference between linear indexing and logical indexing. When you use find you're essentially using logical indexing to obtain linear indexing. The find function can be used to reliably obtain all of your linear indices, via IND = find(A==A);, but this is horrendously inefficient.
you don't need to convert, just use a single number \ 1-D vector when accessing elements of your matrix. For example, given a 5x5 matrix M
M=magic(5);
you can access the last element using M(5,5) or using M(25) ...
similarly M(21:25) will give you the info of M(1,5),M(2,5),...M(5,5).

General programming, 2d array, whats wrong with a double for loop?

This is a general programming question.
I have seen on a lot of posts that iterating through a 2d array via a double for loop is "horrible" "ugly" etc... Why is this?
Are arrays not an efficient data structure compared to dictionaries and such, and also is not a double for loop more efficient than a foreach or other alternative?
Also if your using a 2d array you are often dealing with a 2d coordinate system. The x and y positions are already "built in" to the data structure as the indexes of the arrays (so you dont need to add ,say, a tuple as a dictionary key) and by changing the for loop paramaters you can very cheaply iterate through different parts of your grid while totally ignoring the parts you dont want to iterate through. For example to avoid the "outer" rows and columns you could do..
for (int x = 1; x < Grid.GetLength(0)-1; x++)
{
for (int y = 1; y < Grid.GetLength(1)-1; y++)
{
Grid[x,y].DoSomething();
}
}
With a foreach you'd iterate through everything in the collection and then have something to check whether it is in the coordinate range you want.
Nothing wrong with 2 loops for iterating a 2D array, as long as this is what you really need to do.
One thing to note is performance - in general, the looping should follow the layout of the array in memory. E.g., if the 2D array is stored as a 1D memory buffer where row n is stored after row n-1 (this is the common implementation in general purpose languages), the external loop should go through the rows and internal one through the columns. This way cache misses are minimized.
In general, effectiveness of array access compared to other methods completely depends on particular language implementation. Usually, the array would be the most primitive data structure, resulting in the fastest access. BTW, dictionary is a generalization of array concept.

fast way to invert or dot kxnxn matrix

Is there a fast way to calculate the inverse of a kxnxn matrix using numpy (the inverse being calculated at each k-slice)? In other words, is there a way to vectorize the following code:
>>>from numpy.linalg import inv
>>>a-random(4*2*2).reshape(4,2,2)
>>>b=a.copy()
>>>for k in range(len(a)):
>>> b[k,:,:] = inv(a[k,:,:])
First about getting the inverse. I have looked into both np.linalg.tensorinv and np.linalg.tensorsolve.
I think unfortunately tensorinv will not give you what you want. It needs the array to be "square". This excludes what you want to do, because their definition of square is that np.prod(a[:i]) == np.prod(a[i:]) where i is 0, 1 or 2 (one of the axes of the array in general); this can be given as the third argument ind of tensorinv. This means that if you have a general array of NxN matrices of length M, you need to have e.g. (for i = 1) NxN == NxM, which is not true in general (it actually is true in your example, but it does not give the correct answer anyway).
Now, maybe something is possible with tensorsolve. This would however involve some heavy construction work on the a matrix-array before it is passed as the first argument to tensorsolve. Because we would want b to be the solution of the "matrix-array equation" a*b = 1 (where 1 is an array of identity matrices) and 1 would have the same shape as a and b, we cannot simply supply the a you defined above as the first argument to tensorsolve. Rather, it needs to be an array with shape (M,N,N,M,N,N) or (M,N,N,N,M,N) or (M,N,N,N,N,M). This is necessary, because tensorsolve would multiply with b over these last three axes and also sum over them so that the result (the second argument to the function) is again of shape (M,N,N).
Then secondly, about dot products (your title suggests that's also part of your question). This is very doable. Two options.
First: this blog post by James Hensman gives some good suggestions.
Second: I personally like using np.einsum better for clarity. E.g.:
a=np.random.random((7,2,2))
b=np.random.random((7,2,2))
np.einsum('ijk,ikl->ijl', a,b)
This will matrix-multiply all 7 "matrices" in arrays a and b. It seems to be about 2 times slower than the array-method from the blog post above, but it's still about 70 times faster than using a for loop as in your example. In fact, with larger arrays (e.g. 10000 5x5 matrices) the einsum method seems to be slightly faster (not sure why).
Hope that helps.

Resources