I am trying to make a program that finds the maximum possible determinant of an n*n binary [0,1] matrix. The problem with my current code is that after 4x4, the numbers are too long for a 'long' to hold. The code below is what I use to generate the matrices.
for (int j = 0; j < Math.pow(2, Math.pow(dim, 2)); j++) { //for each possible matrix
int[][] matrix = new int[dim][dim];//make a 2d i*i matrix
long t = Long.valueOf(Long.toBinaryString(j)); //line 58
//format the string so its length = # of elements in the matrix
String format = "%0" + (dim * dim) + "d";
String s = String.format(format, t);
//fill matrix
int counter = 0;
for (int k = 0; k < dim; k++) {//for each row
for (int l = 0; l < dim; l++) {//for each column
matrix[k][l] = s.charAt(counter) - 48; //the -48 is for ascii conversions
counter++;
}// end l
}// end k -- matrix is filled
The error I get when I go over a 4*4:
Exception in thread "main" java.lang.NumberFormatException: For input string: "10000000000000000000"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:444)
at java.lang.Long.valueOf(Long.java:540)
at determinants.Determinants.findMaxBinDet(Determinants.java:58)
at determinants.Determinants.main(Determinants.java:38)
What else can I do to parse the number into binary?
It appears you want to create with all the combinations of 0 and 1 in the cells. A much simpler approach is
for (long j = 0, limit = 1<<(dim*dim); j < limit; j++) { //for each possible matrix
int[][] matrix = new int[dim][dim];//make a 2d i*i matrix
//fill matrix
for (int k = 0, counter = 0; k < dim; k++) {//for each row
for (int l = 0; l < dim; l++, counter++) {//for each column
matrix[k][l] = (j >>> counter) & 1;
}
}
This will only work up to 7x7 matrixes but since generating all 8x8 combination is like to take more than a lifetime, you need another approach for that.
Related
I have a m x n matrix mat and I need to return an array of all the elements of the array in a diagonal order.
Input: mat = [[1,2,3],
[4,5,6],
[7,8,9]]
Output: [1,2,4,7,5,3,6,8,9]
public int[] findDiagonalOrder(int[][] mat){
int rows = mat.length;
int cols = mat[0].length;
int[] result = new int[rows * cols];
for(int i = 0; i <= rows - 1; i++){
for (int j = 0; j <= cols - 1; j++) {
while(i >= 0) {
i = i - 1;
j = j + 1;
from this point I dont know what should I do. Do you have any tips / advices how to continue to solve it myself?
I'm trying to figure out how to solve this problem by myself.
I'm trying to start from the first row and first column and then continue to traverse the array diagonally.
I have a string containing the following:
String text = "abcdefghijkl"
I want to put it in a 2d array so there will be 4 rows of 3
this is currently what I have, its not working correctly though:
char boxChar[][] = new char[4][3];
int j,i;
for (i = 0; i<4; i++)
{
for (j=0; j<3; j++)
{
boxChar[i][j] = text.charAt((i+1)*(j));
}
}
return boxChar[row][col];
It looks like you got the indexes mixed up. I added some print statements to your original code with a modification to get the right char in your charAt instruction.
String text = "abcdefghijkl";
char boxChar[][] = new char[4][3];
int j,i;
for (i = 0; i<4; i++)
{
for (j=0; j<3; j++)
{
boxChar[i][j] = text.charAt(i*3+j);
System.out.print(boxChar[i][j]);
}
System.out.println();
}
Sometimes it can be helpful to jot it down on a piece of paper if it's not lining up how you expected.
With your input string, the positions on a 1d array are
a b c d e f g h i j k l
0 1 2 3 4 5 6 7 8 9 10 11
As you loop through to get the box array (matrix), your outer loop indicates that you want four rows and three columns, in other words
a b c
d e f
g h i
j k l
so for the first element, a, its position is (0,0), b is at (0,1) and so on. Your charAt(position) has to map the 2d positions to their corresponding 1d positions.
Just the wrong indexing, otherwise you're good:
String text = "abcdefghijkl";
int rows = 4;
int cols = 3;
char boxChar[][] = new char[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
boxChar[i][j] = text.charAt((i * cols) + j);
}
}
//return boxChar[row][col];
System.out.println(boxChar[0]);
System.out.println(boxChar[1]);
System.out.println(boxChar[2]);
System.out.println(boxChar[3]);
I have 256 binary matrices B(x,y) and I try to pool them in the group of 8 matrices. Considering a single pixel at a particular position (x,y), a set of binary values from matrices in the pool consisting of 8 matrices can be used to construct a binary code of 8 bits. The following formula illustrates that :
see the formula
The pool of 256 matrices in the group of 8 matrices will result in 32 matrices. I wrote the code in java and the code run properly, but I want to reduce the time complexity, where it takes about 30 seconds to get the result!
The size of each matrix is 300 X 100,what I can change or use to get the same result with much less time??
//index-Strat
int start = 0;
//index-end
int end = 7;
//pool evey eghit matrices togather, and produces 32 matrices
for (int j = 0; j < 32; j++)
{
//call the pooling function
Mat bit - 8 = new Mat();
bit - 8 = pool(start, end);
//add 8-bit matrix to pool array
p.add(bit - 8);
//increamt the indexs to pool the next 8 matrix
start = end + 1;
end = start + 7;
}
//---------------------------
Mat pool(int s, int e)
{
Mat bit - 8 = new Mat(binary.get(0).size(), binary.get(0).type());
//apply the Bit Plane
for (int i = 0; i < bit - 8. rows(); i++)
{
for (int j = 0; j < bit - 8. cols(); j++)
{
double[] sum = new double[1];
for (int k = 0; k < 8; k++)
{
double[] v = new double[1];
v = binary.get(s + k).get(i, j);
double new_value = v[0] * Math.pow(2, k);
sum[0] = sum[0] + new_value;
}
bit - 8. put(i, j, sum);
}
return bit - 8
}
I doubt that it fully explains your long computation time, but you can avoid a lot of object allocations in pool(int, int) by allocating the v and sum array outside the nested for loops, and using int[] instead:
int[] v = new int[1];
int[] sum = new int[1];
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
sum[0] = 0;
for (int k = 0; k < 8; ++k) {
binary.get(s + k).get(i, j, v);
sum[0] += v[0] << k;
}
bitMinus8.put(i, j, sum);
}
}
This reduces the number of allocated arrays from (rows*cols)*(8 + 2) to just 2.
Object creation is reasonably cheap, but avoiding repeated creation can speed things up.
Note that saying:
double[] v = new double[1];
v = <something>;
is redundant: you allocate a new array, and then immediately overwrite it, discarding the allocated array. You can simply write:
double[] v = <something>;
Looking at the docs, I believe that you can also avoid the explicit element-wise sum:
Mat bitMinus8 = new Mat(binary.get(0).size(), binary.get(0).type());
for (int k = 0; k < 8; ++k) {
Core.addWeighted(binary.get(s + k), 1 << k, bitMinus8, 1, 0, bitMinus8);
}
I am doing an N Queens Program in Java. I was able to print all the solutions where each Queen is on a different row and column. Now I need to keep track of the diagonals for collisions. So there are 2n-1 diagonal lines on a 2D array. The algorithm wants us to there are 2n-1 negative diagonal lines and 2n - 1 positive diagonal lines on the chessboard. There is an array of size 2n-1, called d1, that keeps track of the number of queens, i.e., the number of collisions, on each of the 2n-1 negative diagonal lines. If there are k queens on the mth negative diagonal line, there are k-1 collisions on this diagonal line. The
number k is written into the mth element of the d1 array. Similarly, we choose another array with size 2n-1, called d2, for 2n-1 positive diagonal lines.
Here is my method for D2, but I am completely lost. I know that all the up diagonals are row + col, but that is it.
public void D2(){
int[] upDiag = new int[2*board.length - 1];
int numberOfCollisions = 0;
for(int row = 0; row < board.length; row++){
for(int col = 0; col < board.length; col++){
if(isQueen(row, col)){
upDiag[numberOfCollisions++];
}
}
}
}
I've written a three-part series on the Eight-Queens/N-Queens Problem.
Here's a general outline of the problem, and a recursive solution.
Here's a genetic algorithm solution.
Here's a simulated annealing solution.
For the collision checking itself, something like this works very well:
double assessFitness(Integer[] candidate) {
int collisions = 0;
final int MAXIMUM_COLLISIONS = calculateMaxCollisions();
for (int i = 0; i < GRID_SIZE - 1; i++) {
for (int j = i + 1; j < GRID_SIZE; j++) {
if ((candidate[i].equals(candidate[j])) || j - i == Math.abs(candidate[i] - candidate[j]))
collisions++;
}
}
return (MAXIMUM_COLLISIONS - collisions) / (double) MAXIMUM_COLLISIONS;
}
Note that this is adapted from my genetic algorithm solution. I do explain why I return a value that scales from 0 to 1 in the blog article, but in your case a slight modification would yield the result you're looking for:
int countCollisions(Integer[] candidate) {
int collisions = 0;
final int MAXIMUM_COLLISIONS = calculateMaxCollisions();
for (int i = 0; i < GRID_SIZE - 1; i++) {
for (int j = i + 1; j < GRID_SIZE; j++) {
if ((candidate[i].equals(candidate[j])) || j - i == Math.abs(candidate[i] - candidate[j]))
collisions++;
}
}
return collisions;
}
In order for this to work, you do need to calculate the maximum allowable number of collisions for your N-Queens problem.
private int calculateMaxCollisions() {
int sum = 0;
for (int i = GRID_SIZE - 1; i > 0; i--) {
sum += i;
}
return sum;
}
I am having a really hard time creating a method to raise a matrix to the power. I tried using this
public static int powerMethod(int matrix, int power) {
int temp = matrix ;
for (int i = power; i == 1; i--)
temp = temp * matrix ;
return temp ;
but the return is WAYYY off. Only the first (1,1) matrix element is on point.
I tried using that method in a main like so
// Multiplying matrices
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
for (l = 0; l < row; l++)
{
sum += matrix[i][l] * matrix[l][j] ;
}
matrix[i][j] = sum ;
sum = 0 ;
}
}
// Solving Power of matrix
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++)
matrixFinal[power][i][j] = Tools.powerMethod(matrix[i][j], power) ;
}
Where "power", "row", and "column" is an int that the user enters.
Any ideas how I can do this??
Thanks!!!
You have a lot of issues here.
First, your matrix squaring algorithm has a (common) error. You have:
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
for (l = 0; l < row; l++) {
sum += matrix[i][l] * matrix[l][j] ;
}
matrix[i][j] = sum ;
sum = 0 ;
}
}
However, you need to store the result in a temporary second matrix, because when you do matrix[i][j] = sum, it replaces the value at that position with the output, then later results end up being incorrect. Also I suggest initializing sum to 0 first, since it appears you declare it outside of this loop, and initializing it first protects you against any arbitrary value sum may have before going into the loop. Furthermore, it is not immediately clear what you mean by row and column -- make sure you are iterating over the entire matrix. E.g.:
int temp[][] = new int[matrix.length];
for (i = 0; i < matrix.length; i++) {
temp[i] = new int[matrix[i].length];
for (j = 0; j < matrix[i].length; j++) {
sum = 0 ;
for (l = 0; l < matrix.length; l++) {
sum += matrix[i][l] * matrix[l][j] ;
}
temp[i][j] = sum ;
}
}
// the result is now in 'temp', you could do this if you wanted:
matrix = temp;
Note that matrix.length and matrix[i].length are fairly interchangeable above if the matrix is square (which it must be, in order to be multiplied by itself).
Secondly, your multiplication squares a matrix. This means if you repeatedly apply it, you keep squaring the matrix every time, which means you will only be able to compute powers that are themselves powers of two.
Your third issue is your final bit doesn't make much sense:
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++)
matrixFinal[power][i][j] = Tools.powerMethod(matrix[i][j], power) ;
}
It's not immediately clear what you are trying to do here. The final part seems to be trying to raise individual elements to a certain power. But this is not the same as raising a matrix to a power.
What you need to do is define a proper matrix multiplication method that can multiply two arbitrary matrices, e.g.:
int[][] multiplyMatrices (int[][] a, int[][] b) {
// compute and return a x b, similar to your existing multiplication
// algorithm, and of course taking into account the comments about
// the 'temp' output matrix above
}
Then computing a power becomes straightforward:
int[][] powerMatrix (int[][] a, int p) {
int[][] result = a;
for (int n = 1; n < p; ++ n)
result = multiplyMatrices(result, a);
return result;
}
Why not just use Math.pow?
import java.lang.Math;
Then you just have to do
matrixFinal[power][i][j] = (int) Math.pow(matrix[i][j],power); //might have to cast this to an int