I have started using the EJML library for representing matrices. I will use the SimpleMatrix. I did not find two important things which I need. Perhaps somebody can help me identify if the following operations are possible and if yes, how this can be done:
Is it possible to convert a matrix back to a 1D double array (double[]) or 2D double array (double[][]) without just looping through all elements which would be very inefficient? I did not find a method for that. For example, Jeigen library provides a conversion to a 1D array (but I don't know how this is internally done).
Is it possible to delete a row or column?
By the way, does somebody know how EJML compares to Jeigen for large matrices in terms of runtime? EJML provides much more functionality and is much better documented but I'm a bit afraid in terms of runtime.
The underlying array of a SimpleMatrix (it's always 1-dimensional to keep all elements in the same area in RAM) can be retrieved by first getting the underlying DenseMatrix64F and then getting the public data field of D1Matrix64F base class
// where matrix is a SimpleMatrix
double[] data = matrix.getMatrix().data;
I don't see a straightforward way to delete arbitrary rows, columns. One workaround is to use extractMatrix (it copies the underlying double[]) to get 2 parts of the original matrix and then combine them to a new matrix. E.g. to delete the middle column of this 2x3 matrix :
SimpleMatrix fullMatrix = new SimpleMatrix(new double[][]{{2, 3, 4}, {7, 8, 9}});
SimpleMatrix a = fullMatrix.extractMatrix(0, 2, 0, 1);
SimpleMatrix b = fullMatrix.extractMatrix(0, 2, 2, 3);
SimpleMatrix matrix = a.combine(0, 1, b);
Or to delete specifically the first column you can simply do:
SimpleMatrix matrix = fullMatrix.extractMatrix(0, 2, 1, 3);
Or to delete specifically the last column you can simply do (doesn't delete, copy underlying data[]):
matrix.getMatrix().setNumCols(matrix.numCols() - 1);
I will refer to this answer for benchmarks / performance of various java matrix libraries. The performance of ejml is excellent for small matrices and for say size 100 or more doesn't compete well with libraries backed by native C/C++ libraries (like Jeigen). As always, your mileage may vary.
Manos' answer to the first question did not work for me. This is what I did instead:
public double[][] matrix2Array(SimpleMatrix matrix) {
double[][] array = new double[matrix.numRows()][matrix.numCols()];
for (int r = 0; r < matrix.numRows(); r++) {
for (int c = 0; c < matrix.numCols(); c++) {
array[r][c] = matrix.get(r, c);
}
}
return array;
}
I don't know how it compares in performance to other methods, but it works fast enough for what I needed it for.
Related
How can I pass copy of int[][] array to verticle on it deployment?
I have a ServerVerticle from which deploy 5-10 ServiceVerticles.
Each of ServiceVerticle must use the same shared data structure - Map<Integer, Short[]> which can be 100-2000 Mb.
Problem - I can't create Local map with array as a value.
The only in-memory solution I see - pass copy of int[][] to each ServiceVerticle on it deployment and keep 5-10 copies of data.
P.S. This data structure must have as fast as possible lookup, so I dislike cluster-wide solutions like Hazelcast IMap.
While there isn't much freedom in the types you can use in a LocalMap you can use Buffers. A buffer is an optimized byte array and you can quickly adapt it to your use case. Using a Buffer also means you will have a compact in memory representation so you can save memory and any operations will be fast.
You only need to write a transformation from a 2D plane to a 1D line. For example say that you have the following array (2 x 3):
int[][] data = new int[] {
new int[] {1, 2, 3},
new int[] {4, 5, 6},
};
If you transform it to a buffer:
Buffer.buffer()
.appendInt(1).appendInt(2).appendInt(3)
.appendInt(4).appendInt(5).appendInt(6);
(You can later just use the byte representation, this is just to illustrate how it works).
Now you can refer to any x, y by doing:
int getInt(int x, int y) {
// transform from 2D to 1D
int pos = y * LENGTH + x;
// Where LENGTH is the the example: 3
// For safety assert on length
if (pos > buffer.length()) throw new ArrayIndexOutOfBoundsException();
// TODO: assert on min, max (x, y)
return buffer.getInt(pos);
}
I want to iterate just the half of an array in java. Is there any elegant way to shorten this up, eg with a for-each loop?
int[] array = {0,1,2,3,4,5};
for (int i = 0; i<array.length/2; i++)
{
System.out.println(array[i]);
}
If you converted the array into a list using the asList method of the Arrays class in Java, then you can use the forEach method in the List class in Java to print out each element of the list in one single line,
Arrays.asList(array).forEach(System.out::println);
To print only half the array, I'd suggest copying half the array into a new array using the copyOfRange method,
Integer[] newArray = Arrays.copyOfRange(array, 0, array.length/2);
Arrays.asList(newArray).forEach(System.out::println);
EDIT: Like Marko Topolnik pointed out, we're actually starting out with an array of primitive types instead of object types, so in order to use the asList method we're going to have to convert the array into an array of objects (from int to Integer using Integer[] integerArray = ArrayUtils.toObject(array);). However this just seems tedious/inefficient and OP asked for a shorter way so my suggestion would be to use Marko's method,
Arrays.stream(array).limit(array.length/2).forEach(System.out::println);
EDIT 2: Like Amber Beriwal pointed out, it should be noted that although the one-line solution above looks pretty due to its conciseness, it is still very inefficient/slow compared to the OP's original method. Therefore, I would like to reiterate Amber's comments that the OP and others should just stick with the original for-loop.
for (int i = 0; i < array.length/2; i++)
{
System.out.println(array[i]);
}
How about:
IntStream.range(0, array.length / 2).map(i -> array[i]).forEach(System.out::println);
One line, and no array copies.
Broken down:
IntStream.range(0, array.length / 2) //get the range of numbers 0 - (array length)/2
.map(i -> array[i]) //map from index to value
.forEach(System.out::println); //print result
The answer you have posted is good. Although, I couldn't find a better way to make it compact keeping the performance same, but performance can be improved. Remember following practices while coding:
Algorithm's memory requirement should be optimum
Algorithm's time i.e. performance should be optimum
Algorithm's complexity should not be too much. For significant gains in 1 & 2, this can be skipped.
Considering 1 & 2, lines of code comes at least priority.
Solution 1: This solution will be 4-5 times slower than your approach, plus Stream will take extra space.
Arrays.stream(array).limit(array.length/2).forEach(System.out::println);
Solution 2: This solution is faster than the above code and your code (based on my testing), but Stream will take extra space. Also, it is not compact.
Arrays.stream(array).limit(array.length / 2).forEach(new IntConsumer() {
#Override
public void accept(int value) {
System.out.println(value);
}
});
Solution 3: As suggested by you.
int[] array = new int[] { 0, 1, 2, 3, 4, 5 };
int limit = array.length / 2;
for (int i = 0; i < limit; i++) {
System.out.println(array[i]);
}
Recommendation: Don't go over to reduce the LOC at the stake of losing performance and memory. It is better to keep up with the solution that gives you best performance..
I have been at this for days. Our assignment requires that I override the equals() and, more importantly, hashCode(). Objects to be compared:
Two-dimensional int arrays.
Criteria of hashCode():
Any two-dim array layout that matches any rotated variant or the reflection of the rotated variant should have the same hashCode.
Visually, that would mean that if I had these two 2d arrays:
arr 1 arr2
[0, 0, 1] [1, 0, 0]
[1, 0, 0] [0, 0, 1]
[0, 0, 1] [1, 0, 0]
The two following print-statements would be identical, since arr2 is a reflection of arr1.
System.out.println(arr1.hashCode());
System.out.println(arr2.hashCode());
Now, I am quite helpless in how to implement this. I figured I would have to do something like this (pseudo):
int hashCode() {
lastHash = listOfArrays.last().hashCode()
variants = this.getHashVariants()
foreach (variants as v)
if (lastHash == v) return v
return this.SystemGeneratedHash()
}
There is just so much that can and will go wrong with this approach, but I'm stumped and this was all I could think of. The idea of making the hashCode()-function rely on an outside list feels really icky too. The lecture on the subject was abysmal, and search engines have not been in my favor as of yet.
Q: How can I make non-identical objects return the same hashCode as long as they match a certain requirement?
There are several possible solutions to this. Here are four, just off the top of my head -
Just return a constant.
Add up the numbers in all the cells and return that.
Take the absolute value of the determinant of the matrix.
Multiply each entry by the distance from the cell to the nearest corner, and add these up.
This is limited only by your imagination.
Well, honestly I would just use Arrays.hashCode(). You need your hashcode to be the same for any rotationally symetric array, so I would write a method which rotates your data 90 degrees, and one which reflects your data. At that point your code is something like:
public int hashCode() {
int[][] once = rotate(data);
int[][] twice = rotate(once);
int[][] thrice = rotate(twice);
int[][] flippedData = flip(data);
int[][] flippedOnce = flip(once);
int[][] flippedTwice = flip(twice);
int[][] flippedThrice = flip(thrice);
return Arrays.hashCode(data) + Arrays.hashCode(once) +
Arrays.hashCode(twice) + Arrays.hashCode(thrice) +
Arrays.hashCode(flippedData) + Arrays.hashCode(flippedOnce) +
Arrays.hashCode(flippedTwice) + Arrays.hashCode(flippedThrice);
}
That way, no matter the original orientation of your data, you still come up with the same ultimate hash code.
I'm doing a project in Java which includes (x,y) coordinates.
I have created a class of Cell which has protected integers X & Y;
Upon initialization, i do a for loop which sets an array of cell by multiplying the X & Y given by the user, say if X= 10 and Y = 10, i create an array of cells[100].
However, how can i search the array fast, without doing a for loop and checking each individual value very time?
Say I'm looking for the object that contains X=5 & y = 3.
I know i can go through with a for loop looking for object with values x and y, but i was wondering if there is a way to do a binary search and find "a bit faster" the object[i] that contains X=5 and Y=5.
Thank you very much.
The way to do this is to arrange the Cell objects in the array in a way so that there is a simple mapping from an X,Y coordinate to the Cell's index in the array.
For example, lets assume that X and Y go from 1 to 10. Suppose that we then arrange the Cells so that:
array[0] = Cell(1, 1);
array[1] = Cell(1, 2);
...
array[9] = Cell(1, 10);
array[10] = Cell(2, 1);
array[11] = Cell(2, 2);
...
array[99] = Cell(10, 10);
It should be easy to see that we can calculate the index of Cell(i,j) in the array and fetch the cell as follows:
public Cell getCell(Cell[] array, int i, int j) {
int index = (10 * (i - 1)) + (j - 1);
return array[index];
}
This is the approach that programming languages that support N-dimensional array types typically use to implement them.
This can be trivially modified to deal with cases where:
the constant 10 is something else
the matrix is not square,
the matrix has more than two dimensions
indexes run from 0 to N - 1 instead of 1 to N
etcetera
There are various other ways that you could represent 2-D matrices in Java. The simplest one is just using a Cell[][] cells which allows you to access cells as (for example) cells[i-1][j-1]. More complicated representations can be designed that use less space if the matrix is sparse (i.e. cells are missing) at the cost of more complex code and slower access times.
It sounds like (if you want to use binary search, anyway) you're setting element 0 to the Cell with x = 0, y = 0; element 1 to x = 0, y = 1, etc. If so you should be able to trivially compute the exact index of a given Cell:
// contains the Cell with x = desiredX, y = desiredY
yourArray[desiredX * X + desiredY];
If this is what you're doing, however, it'd probably be simpler to just make a 2-dimensional array:
yourArray = new Cell[X][Y];
...
yourArray[desiredX][desiredY];
the above two answers show the trivial method for getting the array index fast. id like to propose an alternative- use hashmaps with key, value pairings. the value could be objects. accessing hashmap elements run in constant time..
I've got an array array of size N. For every 3 indexes in it I want to take them out and declare and assign those values to another array of size 3. I then want to go back to that array and take the next 3 and put it in a different array of size 3. I'll iterate like this for 3 different arrays of size 3 a1,a2,a3 once this is done I want to empty a1,a2,a3 and re add the NEXT 3 values to the 3 arrays of size 3 repeating this on till we reach array.length
What would be the best / most efficient way of doing this?
As a general strategy I would not worry about efficiency at first.
Code it as explicitly as possible, and then write a load of unit tests confirming it works. The iteratively improve performance.
Its easier to make correct code fast than it is to make fast code correct.
for (int i=0; i<=N-9; i+=9) {
System.arrayCopy(arrayN, i, a1, 0, 3);
System.arrayCopy(arrayN, i+3, a2, 0, 3);
System.arrayCopy(arrayN, i+6, a3, 0, 3);
// presumably do other stuff here
}
That's a pretty brittle but fast way of doing it. Each time the previous values are overwritten, so no need to clear. If you do need to have arrayN clear, you can just Arrays.fill(arrayN, null) after the loop.
EDIT: For the less brittle answer, I'm going to assume you'd be inflating m x n arrays. Instead of hard coding a1, a2, ... am, make a 2D array a[m][n].
for (i=0; i<=N-m*n; i+=m*n) {
for (int j=0; j<m; j++) System.arrayCopy(arrayN, i+n*j, a[j], 0, n);
// presumably do other stuff here
}
and, as Adrian suggests in the comments, declare i outside the loop and use its value relative to N to deal with leftovers as appropriate.
Its very easy, you can do it in the following way....
It is code snippet below....
byte[] YourBigArray = new byte[SomeValue];
int temp = 0;
while(temp < YourBigArray.size - 1 )
{
System.arrayCopy(YourBigArray, temp, smallarray, 0, 3);
temp+=3;
}
Try this code and also see the documentation of arrayCopy function....
Enjoy.....
for(int i = 0; i < ##; i++){if(i%3==0){startNewArray}}