I am developing the game that named Lights Out. So for solving this, i have to compute the answer of AX = B in modules 2. So, for this reason i choose jscience library. In this game the size of A is 25×25 matrix, X and B are both 25×1 matrix. I wrote the code such below :
AllLightOut.java class :
public class AllLightOut {
public static final int SIZE = 5;
public static double[] Action(int i, int j) {
double[] change = new double[SIZE * SIZE];
int count = 0;
for (double[] d : Switch(new double[SIZE][SIZE], i, j))
for (double e : d)
change[count++] = e;
return change;
}
public static double[][] MatrixA() {
double[][] mat = new double[SIZE * SIZE][SIZE * SIZE];
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
mat[i * SIZE + j] = Action(i, j);
return mat;
}
public static SparseVector<ModuloInteger> ArrayToDenseVectorModule2(
double[] array) {
List<ModuloInteger> list = new ArrayList<ModuloInteger>();
for (int i = 0; i < array.length; i++) {
if (array[i] == 0)
list.add(ModuloInteger.ZERO);
else
list.add(ModuloInteger.ONE);
}
return SparseVector.valueOf(DenseVector.valueOf(list),
ModuloInteger.ZERO);
}
public static SparseMatrix<ModuloInteger> MatrixAModule2() {
double[][] mat = MatrixA();
List<DenseVector<ModuloInteger>> list = new ArrayList<DenseVector<ModuloInteger>>();
for (int i = 0; i < mat.length; i++) {
List<ModuloInteger> l = new ArrayList<ModuloInteger>();
for (int j = 0; j < mat[i].length; j++) {
if (mat[i][j] == 0)
l.add(ModuloInteger.ZERO);
else
l.add(ModuloInteger.ONE);
}
list.add(DenseVector.valueOf(l));
}
return SparseMatrix.valueOf(DenseMatrix.valueOf(list),
ModuloInteger.ZERO);
}
public static double[][] Switch(double[][] action, int i, int j) {
action[i][j] = action[i][j] == 1 ? 0 : 1;
if (i > 0)
action[i - 1][j] = action[i - 1][j] == 1 ? 0 : 1;
if (i < action.length - 1)
action[i + 1][j] = action[i + 1][j] == 1 ? 0 : 1;
if (j > 0)
action[i][j - 1] = action[i][j - 1] == 1 ? 0 : 1;
if (j < action.length - 1)
action[i][j + 1] = action[i][j + 1] == 1 ? 0 : 1;
return action;
}
}
And the main class is as follow :
public class Main {
public static void main(String[] args) {
double[] bVec = new double[] { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0 };
SparseMatrix<ModuloInteger> matA = AllLightOut.MatrixAModule2();
SparseVector<ModuloInteger> matB = AllLightOut
.ArrayToDenseVectorModule2(bVec);
ModuloInteger.setModulus(LargeInteger.valueOf(2));
Vector<ModuloInteger> matX = matA.solve(matB);
System.out.println(matX);
}
}
I ran this program for about 30 minutes, but it had not result. Does my code include a fatal error or wrong ? Why it takes too long ?
Thanks for your attention 🙂
EDIT
The slowdown happening in this line Matrix<ModuloInteger> matX = matA.inverse();. Note that the JScience benchmark result, speed for this library is very high, but i don’t know why my program ran too slow!
EDIT2
Please note that when i try to SIZE = 3, i get the answer truly. For example:
MatA :
{{1, 1, 0, 1, 0, 0, 0, 0, 0}, {1, 1, 1, 0, 1, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 1, 0, 0, 0}, {1, 0, 0, 1, 1, 0, 1, 0, 0}, {0, 1, 0, 1, 1, 1, 0, 1, 0}, {0, 0, 1, 0, 1, 1, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 0, 1, 1, 1}, {0, 0, 0, 0, 0, 1, 0, 1, 1}}
MatB :
{1, 1, 1, 1, 1, 1, 1, 0, 0}
MatC :
{0, 0, 1, 1, 0, 0, 0, 0, 0}
But when i try SIZE = 5, slowdown occurred.
That would be because the coefficient matrix
matAis not invertible forSIZE == 5(or 4, 9, 11, 14, 16, …?).I’m a bit surprised the library didn’t detect that and throw an exception. If the library tries to invert the matrix in
solve(), that would have the same consequences.A consequence of the singularity of the coefficient matrix for some sizes is that not all puzzles for these sizes are solvable, and the others have multiple solutions.
Since we’re calculating modulo 2, we can use bits or
booleans to model our states/toggles, usingXORfor addition and&for multiplication. I have cooked up a simple solver using Gaussian elimination, maybe it helps you (I haven’t spent much time thinking about the design, so it’s not pretty):