Why we use matrices instead of just arrays?
If I create an array of vertices of a 3d model and I want to move each vertex left well
ArrayList<Vertex> vertex = fillVertecis();
for(Vertex vertex: vertices){
vertex.x += 2;
}
//or avoiding creating all those objects
float[] vertices = fillVertecis();
//asumming we arrange the array like so [x1,y1,z1,x2,y2,z2....]
int x = 0;
int y = 1;
int z = 2;
for(int i = 0; i < vertices.lenght/3; i+= 3){
vertices[i+x] += 1;
}
sure I'm looping through all vertex but don't we have to do the same using matrices?
What advantages do we have using matrices instead of arrays?
What advantages do we have using matrices instead of arrays?
Clarity of purpose.
Ease of manipulation.
Abstraction of implementation.
...
Try applying rotation or scaling to your vertices and you'll see the benefit of 4x4 matrices and homogeneous transformations over arrays.
Related
I have two containers: a 2-dimensional NxN matrix and a 1-dimensional array which is the transposed 1D "version" of the matrix (so for a 5x5 array, I will have a 25 element array with the same values). I want to implement a query function that will take 2D coordinates as arguments but will be doing work on the equivalent 1D array.
In order to keep algorithm efficiency strictly non-quadratic I want to access only the array and not the matrix.
I've checked other questions but they all talk about converting the whole matrix to an array through nested for-loops. I don't want to do this, as that would take quadratic time to run. Instead, I want the conversion to be on-demand for a given coordinate through a query function/method. In other words for a given number of N columns/rows:
transpose(int i, int j) {
int result;
result = i * N + j;
return result;
}
This is the formula I'm using but it is not correct. For example if I want to access the element in the {5,5} position the result would be 5*5 + 5 = 30, which is greater than 25 (which would be the total number of elements for 5x5 matrix).
Thanks in advance.
If you have a 2d array and a 1d array having same elements,then the following will be true
2d[i][j]=1d[i*number_of_columns+j]
I am assuming from your post that you already have created a 1d array out of a 2d one.
Note i and j are indices and rememeber indices begin from 0
EDIT:If you are accessing an element at [5][5] (as last element)it means your array is of order 6 by 6 and not 5 by 5.So your 1d array will have 6*6=36 elements and not 25.
You can use the deepToString() method to output a 2D array to a String. This can make it easier to do things such as sort() for example.
Assuming a declared int mat2d[m][n]; with m rows and n columns, you can convert it like
int * mat1d = new int[m * n];
int k = 0;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++i)
mat1d[k++] = mat2d[i][j];
If you just want to convert between 1D and 2D coordinates, serve yourself and make functions from this:
const int width = 10;
// from 1D coordinate to 2D coordinate
int coord_1d = 25;
int coord_x = coord_1d % width;
int coord_y = coord_1d / width;
// from 2D coordinate to 1D coordinate
coord_1d = coord_x + coord_y * width;
Your question is quite confusing, you said that you don't want nested loops, here is a just-one-loop conversion
int[][] a={
{1,2,3,4,5,6},
{4,5,6,7,8,9},
{7,8,9,1,2,3},
{1,2,3,4,5,6}
};
int[]b=new int[a.length*a[0].length];
int x=0;
for(int i=0, j=0;i<a.length&&j<a[0].length;i=(j==a[0].length-1?i+1:i),j=(j+1)%a[0].length)
b[x++]=a[i][j];
System.out.println(Arrays.toString(b));
If you want the conversion to be based on coordinates, by changing i and j values in the for loop to such coordinates will allow you to convert to array only a subset of your matrix
I have a huge sparse matrix (about 500K x 500K entries, with approximately 1% of the values being non-zero.
I'm using #mikera's Vectorz library.
t is a SparseRowMatrix composed of SparseIndexedVector rows.
For this chunk of the matrix, I am computing weights for (i,j) where j>i, putting them into an array of double, then creating the SparseIndexedVector for the row from that array. I was trying to cache the weights so that for the parts of the row where j<i, I could look up the previously computed value for (j,i) and put that value in for (i,j), but that took too much memory. So I am now trying to basically just compute and fill in the upper triangle for that chunk of the matrix, and then "symmetrify" it later. The chunk is from n1 x n1 to n2 x n2 (where n2 - n1 =~ 100K).
Conceptually, this is what I need to do:
for (int i = n1; i < n2; i++) {
for (int j = i + 1; j < n2; j++) {
double w = t.get(i, j);
if (w > 0) {
t.set(j, i, w);
}
}
}
But the "random access" get and set operations are quite slow. I assume unsafeGet would be faster.
Would it improve my performance to do the j-loop as my outer loop and convert the row back to a double array, then add elements and then create a new SparseIndexedVector from that array and replaceRow it back in? Something like:
for (j = n1 + 1; j < n2; j++) {
double[] jRowData = t.getRow(j).asDoubleArray();
for (i = 1; i < j-1; i++) {
double w = t.unsafeGet(i,j);
if (w > 0) {
jRowData[i] = w;
}
}
SparseIndexedVector jRowVector = SparseIndexedVector.createLength(n);
jRowVector.setElements(jRowData);
t.replaceRow(j, jRowVector);
}
Would something like that likely be more efficient? (I haven't tried it yet, as testing things on such large arrays takes a long time, so I'm trying to get an idea of what is "likely" to work well first. I've tried various incarnations on a smaller array (1K x 1K), but I've found that what is faster on a small array is not necessarily the same as what is faster on a large array.)
Is there another approach I should take instead?
Also, since memory is also a large concern for me, would it be helpful at the end of the outer loop to release the array memory explicitly? Can I do that by adding jRowData = null;? I assume that would save time on GC but I'm not all that clear on how memory management works in Java (7 if it matters).
Thanks in advance for any suggestions you can provide.
A matrix is symmetric if m[x,y] is equal to m[y,x] for all x and y, so if you know that the matrix must be symmetric, storing both m[x,y] and m[y,x] is redundant.
You can avoid storing both by rearranging the inputs if they meet a certain condition:
void set(int row, int col, double value) {
if(col < row) {
//call set again with transposed col/row
return set(col, row, value);
//we now know that we're in the top half of the matrix, proceed like normal
...
}
Do something similar for the get method:
double get(int row, int col) {
if(col < row) {
//call get again with transposed col/row
return get(col, row);
//we now know that we're in the top half of the matrix, proceed like normal
...
return value;
}
This technique will allow you to both avoid storing redundant values, and force the matrix to be symmetric without having to do any extra processing.
The la4j library guarantees O(log n) (where the n is a dimension) performance for both get/set operations on sparse matrices like CRSMatrix or CCSMatrix. You can perform a small experiment - just compile your code from conceptual box and run it with la4j:
for (int i = n1; i < n2; i++) {
for (int j = i + 1; j < n2; j++) {
double w = t.get(i, j);
if (w > 0) {
t.set(j, i, w);
}
}
}
You said you have to handle 500K x 500K matrices. For this size you can expect log_2(500 000) ~ 18 internal binary search iterations will be performed at each call to get/set operations.
Just think about 18 loop iterations on a moderl JVM and modern CPU.
Hope this helps. Have fun.
I am making a Pac-Man game and I am currently working on the ghosts AI. I am planning on using Dijkstra's algorithm for the pathfinding. My problem is that when my game is loaded the vertices for the graph are stored in a matrix. I am trying to assign each vertex all of its edges like this
for(int x = 0; x<40; x++)
{
for(int y = 0; y<40; y++)
{
Vertex vertex = map[x][y];
vertex.adjacencies = new Edge[]{new Edge(map[x-1][y], 1), new Edge(map[x+1][y], 1), new Edge(map[x][y-1], 1), new Edge(map[x][y+1], 1)};
}
}
the problem is that it sometimes throws an array out of bounds exception. How would I fix this without putting in tons of if statements to check if the current vertex is on the edge of the graph?
One easy way is to include a non-traversable border around the edges.
For example, if your actual map is 40x40, you can declare a 42x42 array. Rows 0 and n would be non-traversable, as would be columns 0 and n.
You'd still need to handle cylindrical travel of the pacman between left and right sides.
You should start your loop with a "border" of 1, like this:
for(int x = 1; x < 39; x++)
because, when you create your edges with map[x-1][y] with a x started to 0, it take -1 as array index, so it throw an Array Out of Bounds exception.
I'm working on an OpenGL project in Java, and it has come to point where I'd like to create the transformation matrices in my own code, so i can use them to do world-to-screen point transformations, and vice versa. I've created a Matrix class with support for transformations, and that is all working quite nicely. However, I'm having trouble actually figuring out how to create an inverse transform.
So my question is this:
Given an arbitrary affine (4x4) transformation matrix, how do you create the inverse transformation matrix? Are some matrices uninvertible? What are the limitations and caveats of inverting a transformation matrix?
From my research, I've heard various methods of doing so, with the simplest being to transpose then negate the matrix. However, this doesn't seem to be actually working. I've heard that this method doesn't work on some matrices, and even that some matrices are uninvertible.
I'm looking for more than just a "plug in this equation" answer, because I'd actually like to understand what's going on when I invert a matrix. This also excludes "just use this library" answers. I might move to a matrix library in the future, but for now I'd like to create it myself.
Edit: Before anyone asks, this is NOT homework. This is a personal project.
Edit: Apparently there's a whole list of strategies for calculating inverse matrices here: http://en.wikipedia.org/wiki/Invertible_matrix
Here is some code that I used in my Computer Graphics course, basically I used the Gauss Jordan elimination for calculating the inverse of a matrix. For a matrix to be invertible its determinant value must be not equal to zero. I have not handled that case in my code though, I am not going to do it all for you.
Matrix4* Matrix4::FindInverse(Matrix4 &a){
int n = R;
int i = 0;
int j = 0;
float pivot = 0;
Matrix4* invA = NULL;
//TODO: Check whether the matrix is invertible.Else Return
invA = new Matrix4();
invA->SetMatrix4(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);
for(i = 0; i < n; i++){
pivot = a.v[i][i];
if(pivot != 1.0 and pivot != 0){
for(int t = i; t < n; t++){
a.v[i][t] = a.v[i][t]/pivot;
invA->v[i][t] = invA->v[i][t]/pivot;
}
}
//Update to the new pivot which must be 1.0
pivot = a.v[i][i];
for(j = 0; j < n; j++){
if( j==i ){
continue;
}
else{
float l = a.v[j][i]/pivot;
for(int m = 0; m < n; m++){
a.v[j][m] = a.v[j][m] - l * a.v[i][m];
invA->v[j][m] = invA->v[j][m] - (l * invA->v[i][m]);
}
}
}
}
return invA;
}
I am using adjacency matrix to represent all the vertex of my weighted unidirectional large graph. In this graph no edge connects a vertex to itself. This makes all the diagonal elements of my adjacency matrix null. As my graph is large so in adjacency matrix i need not to save any elements in left triangle. Below is a small sample graph with adjacency matrix.
In an unidirectional graph left triangle is just mirror image of right triangle. i.e. adjacency_matrix[i][j], adjacency_matrix[j][i] are same. so why to store the left triangle. for a large graph this trick can save so much memory. At the same time diagonal elements are also zero since no edge connects a vertex to itself. i.e. adjacency_matrix[i][i] are zero.
But how can i implement this? can 2D array be used here?
Java doesn't really have 2D arrays, although there is syntatic sugar for allocating an array of arrays.
You probably just want:
int[][] weight = new int[N][];
for (int i = 0; i < N; i++) weight[i] = new int[N-1-i];
That will allocate the triangle you want. Then just index row r, col c at weight[r][c-r-1].
The other option is just to use a single array with
int[] weight = new int[N*(N-1)/2];
The indexing can be a bit more complicated to compute, but less allocation and pointer overhead.
You can use a jagged array.
int[][] matrix = new int[N][];
for (int i = 1; i <= N; i++) {
matrix[i] = new int[N - i + 1];
for (int j = 1; j <= N - i + 1; j++)
matrix[i][j] = edgeValue;
}
Basically you allocate for each row as much as you need.
P.S Maybe I messed up some boundaries here, but you should still get the main point:)