Minimize Simplex method - java

I find topic about Simplex method here Alter Simplex Algorithm to Minimize on objective function NOT maximize
But answer didn`t help. When I change from
double[] variables = { 13.0, 23.0 };
to
double[] variables = { -13.0, -23.0 };
The program dont calculate(no Exception), it print first step and that`s all.
Could somebody help me with alter simplex method from maximize to minimize?
code:
import java.util.*;
public class Simplex
{
private static final double EPSILON = 1.0E-10;
private double[][] tableaux;
private int numOfConstraints;
private int numOfVariables;
private int[] basis;
/**
* Constructor for objects of class Simplex
*/
public Simplex()
{
double[][] thisTableaux = {
{ 5.0, 15.0 },
{ 4.0, 4.0 },
{ 35.0, 20.0 },
};
double[] constraints = { 480.0, 160.0, 1190.0 };
double[] variables = { -13.0, -23.0 };
numOfConstraints = constraints.length;
numOfVariables = variables.length;
tableaux = new double[numOfConstraints+1][numOfVariables+numOfConstraints+1];
//adds all elements from thisTableaux to tableaux
for(int i=0; i < numOfConstraints; i++)
{
for(int j=0; j < numOfVariables; j++)
{
tableaux[i][j] = thisTableaux[i][j];
}
}
//adds a slack variable for each variable there is and sets it to 1.0
for(int i=0; i < numOfConstraints; i++)
{
tableaux[i][numOfVariables+i] = 1.0;
}
//adds variables into the second [] of tableux
for(int j=0; j < numOfVariables; j++)
{
tableaux[numOfConstraints][j] = variables[j];
}
//adds constraints to first [] of tableaux
for(int k=0; k < numOfConstraints; k++)
{
tableaux[k][numOfConstraints+numOfVariables] = constraints[k];
}
basis = new int[numOfConstraints];
for(int i=0; i < numOfConstraints; i++)
{
basis[i] = numOfVariables + i;
}
show();
optimise();
assert check(thisTableaux, constraints, variables);
}
public void optimise() {
while(true) {
int q = findLowestNonBasicCol();
if(q == -1) {
break;
}
int p = getPivotRow(q);
if(p == -1) throw new ArithmeticException("Linear Program Unbounded");
pivot(p, q);
basis[p] = q;
}
}
public int findLowestNonBasicCol() {
for(int i=0; i < numOfConstraints + numOfVariables; i++)
{
if(tableaux[numOfConstraints][i] > 0) {
return i;
}
}
return -1;
}
public int findIndexOfLowestNonBasicCol() {
int q = 0;
for(int i=1; i < numOfConstraints + numOfVariables; i++)
{
if(tableaux[numOfConstraints][i] > tableaux[numOfConstraints][q]) {
q = i;
}
}
if(tableaux[numOfConstraints][q] <= 0) {
return -1;
}
else {
return q;
}
}
/**
* Finds row p which will be the pivot row using the minimum ratio rule.
* -1 if there is no pivot row
*/
public int getPivotRow(int q) {
int p = -1;
for(int i=0; i < numOfConstraints; i++) {
if (tableaux[i][q] <=0) {
continue;
}
else if (p == -1) {
p = i;
}
else if((tableaux[i][numOfConstraints+numOfVariables] / tableaux[i][q] < tableaux[p][numOfConstraints+numOfVariables] / tableaux[p][q])) {
p = i;
}
}

You might want to look into the Dual Simplex Method (or Duality Theory). If the standard form of the primal problem is:
Maximize = 13*X1 + 23*X2;
with constraints:
5*X1 + 15*X2 <= 480;
4*X1 + 4*X2 <= 160;
35*X1 + 20*X2 <= 1190;
X1 >= 0;
X2 >= 0;
Then the dual problem is:
Minimize = 480*Y1 + 160*Y2 + 1190*Y3;
with constraints:
5*Y1 + 4*Y2 + 35*Y3 >= 13;
15*Y1 + 4*Y2 + 20*Y3 >= 23;
Y1 >= 0;
Y2 >= 0;
Y3 >= 0;
I tested both of these problems in LINGO and get the same answer for both (Z = 800, X1 = 12, X2 = 28 -- Y1 = 1, Y2 = 2, Y3 = 0).

I guess the program did nothing because the initial solution is the optimal solution.

Related

Java, Class' s property is not updated when it is changed with method

App Link: Replit
I have a Neuron_ class
public class Neuron_ {
private double[] weights;
double learningRate;
public Neuron_ (int inputNeurons, double learningRate) {
this.weights = new double[inputNeurons];
this.learningRate = learningRate;
for (int i = 0; i < inputNeurons; i++) {
this.weights[i] = Math.random();
}
}
public double calculate(double[] inputs) {
double output = 0;
for(int i = 0; i < inputs.length; i++) {
output += inputs[i] * this.weights[i];
}
return output;
}
public void decreaseWeight(double[] inputs) {
for (int i = 0; i < this.weights.length; i++) {
this.weights[i] -= learningRate * inputs[i] ;
}
}
public void increaseWeight(double[] inputs) {
for (int i = 0; i < this.weights.length; i++) {
this.weights[i] += learningRate * inputs[i] ;
}
}
}
and I call increaseWeight and decreaseWeight methods from NeuralNetwork class
if(biggestIndex != correctIndex) {
System.out.println("Wrong output, changing weights");
for (int i = 0; i < this.neurons.length; i++) {
for (int j = 0; j < outputNeurons.length; j++) {
System.out.println("Changing weights for neuron " + i + " for output " + outputNeurons[j]);
if (j == correctIndex) {
this.neurons[i].increaseWeight(inputs);
} else if (j == biggestIndex) {
this.neurons[i].decreaseWeight(inputs);
}
}
}
}
neurons array is created like this
public NeuralNetwork_ (int inputNeurons, String[] outputNeurons, double learningRate) {
this.outputNeurons = outputNeurons;
this.neurons = new Neuron_[outputNeurons.length];
for(int i = 0; i<outputNeurons.length; i++) {
this.neurons[i] = new Neuron_(inputNeurons, learningRate);
}
}
When I call decreaseWeight and increaseWeight methods from another class, Logs show like they were changed but when I log weights at the beginning and at the end of the training, they were same every time.
weights array is not updating.
weights change, but finally the result is the same for maths ops.
Try modify you method with more log:
public void decreaseWeight(double[] inputs) {
double[] newWeights = new double[inputs.length];
for (int i = 0; i < this.weights.length; i++) {
newWeights[i] = this.weights[i] - learningRate;
}
this.weights = newWeights;
System.out.println("intermedial weights: " + Arrays.toString(this.weights));
}
public void increaseWeight(double[] inputs) {
double[] newWeights = new double[inputs.length];
for (int i = 0; i < this.weights.length; i++) {
newWeights[i] = this.weights[i] + learningRate;
}
this.weights = newWeights;
System.out.println("intermedial weights: " + Arrays.toString(this.weights));
}
and study the result.
For each neurons iterator you are increasing and then decreasing weights whith the same value, so finally neuron weights are the same

Issues with calculating the determinant of a matrix (in Java). It is alwys 0

I want to calculoate the determinant of a given NxN Matrix using the Laplace-Method. I already tried differnt approaches which always return a 0.
The class I used:
package Matrix;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class Matrix
{
double[][] array;
public static void init(Matrix a,int row , int column)
{
a.array = new double [row] [column];
for (int i = 0; i < row; i++)
{
for(int k = 0; k < column; k++)
{
a.array[i][k] = 0;
}
}
}
public static int getNRows(Matrix a)
{
return a.array.length;
}
public static int getNColumns(Matrix a)
{
return a.array[0].length;
}
public static void print(Matrix a)
{
for(int i = 0; i < getNRows(a);i++ )
{
for (int k = 0; k < getNColumns(a); k++)
{
System.out.print(a.array[i][k] + "\t");
}
System.out.println();
}
}
public static double det(Matrix a)
{
double det = 0;
det = a.array[0][0] * a.array[1][1] * a.array[2][2] + a.array[1][0] * a.array[2][1] * a.array[0][2] + a.array[2][0] * a.array[0][1] * a.array[1][2] - a.array[2][0] * a.array[1][1] * a.array[0][2] - a.array[1][0] * a.array[0][1] * a.array[2][2] - a.array[0][0] * a.array[2][1] * a.array[1][2];
return det;
public static Matrix transpose(Matrix a)
{
Matrix transposed = new Matrix();
Matrix.init(transposed, getNRows(a), getNColumns(a));
for(int i = 0; i < getNRows(a); i++)
{
for(int j = 0; j < getNColumns(a); j++)
{
transposed.array[j][i] = a.array[i][j];
}
}
return transposed;
}
public static Matrix subMatrix(Matrix a, int exclRow, int exclCol)
{
Matrix subMatrix = new Matrix();
Matrix.init(subMatrix, getNRows(a) - 1, getNColumns(a) - 1);
for(int i = 0; i < getNRows(a) - 1; i++)
{
for(int j = 0; j < getNColumns(a) - 1; j++)
{
if(i != exclRow && j != exclCol)
{
subMatrix.array[i][j] = a.array[i][j];
}
}
}
return subMatrix;
}
public static Matrix loadMatrix(String filename) throws Exception
{
Scanner sc = new Scanner(new BufferedReader(new FileReader(filename)));
Matrix result = new Matrix();
int row = 0;
int col = 0;
String[] line = sc.nextLine().trim().split("\t");
row = Integer.parseInt(line[0]);
col = Integer.parseInt(line[1]);
init(result, row, col);
int currentRow = 0;
while(sc.hasNextLine())
{
String[] line2 =sc.nextLine().trim().split("\t");
for(int i = 0; i < col; i++)
{
result.array[currentRow][i] = Double.parseDouble(line2[i]);
}
currentRow++;
}
return result;
}
/*public static double detN(Matrix a)
{
int colOfA = getNColumns(a);
int rowOfA = getNRows(a);
double value = 1;
if(colOfA != rowOfA)
{
return 0;
}
if(colOfA == 1 && rowOfA == 1)
{
return a.array[0][0];
}
else
{
for(int row = 0; row < rowOfA; row++)
{
value += Math.pow(-1, row) * a.array[row][0] * detN(subMatrix(a, row, 0));
}
}
return value;
}*/
public static double detN(Matrix a)
{
int colOfA = getNColumns(a);
int rowOfA = getNRows(a);
if(colOfA != rowOfA)
{
return 0;
}
if(rowOfA <= 3)
{
return det(a);
}
double value = 0;
for(int row = 0; row < rowOfA; row++)
{
if(row % 2 == 0)
{
value += a.array[row][0] * detN(subMatrix(a, row, 0));
}
else
{
value -= a.array[row][0] * detN(subMatrix(a, row, 0));
}
}
return value;
}
public static Matrix adjointN(Matrix a)
{
int rowOfA = getNRows(a);
int colOfA = getNColumns(a);
Matrix ret = new Matrix();
Matrix.init(ret, rowOfA, colOfA);
for(int row = 0; row < rowOfA; row++)
{
for(int col = 0; col < colOfA; col++)
{
ret.array[row][col] = detN(subMatrix(a, row, col));
}
ret = transpose(ret);
return ret;
}
return ret;
}
public static Matrix inverseN(Matrix a)
{
Matrix inverse = new Matrix();
Matrix.init(inverse, getNRows(a), getNColumns(a));
double pre = 1/detN(a);
inverse = adjointN(a);
for(int i = 0; i < getNRows(a); i++)
{
for(int j = 0; j < getNColumns(a); j++)
{
inverse.array[j][i] = inverse.array[i][j] * pre;
}
}
return inverse;
}
}
I have two versions for detN, which both yield the same result.
This isn't the entire class, because there are some functions that don't belong to this particular question
Here is an approach you could consider(the code is not fully debugged so take with a grain of salt). Finding the determinant is a recursive concept since you are always finding the determinant of a smaller matrix to get the final answer.
//Recursive base function
public static double det(int[][] matrix) {
if(matrix.length == 2)
return ((matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]));
double determinant = 0;
int mlength = matrix.length - 1;
int[][] newM = new int[mlength][mlength];
for(int i = 0; i < mlength + 1; i++) {
newM = newMatrix(matrix, i);
determinant = determinant + (Math.pow(-1, i) * matrix[0][i]) * det(newM);
}
return determinant;
}
//Format smaller matrix to use in further iteration of above det(int[][]) function
public static int[][] newMatrix(int[][] m, int column) {
int length = m.length - 1;
int[][] newMat = new int[length][length];
for(int i = 1; i < m.length; i++) {
for(int j = 0; j < column; j++)
newMat[i - 1][j] = m[i][j];
for(int k = column + 1; k < m.length; k++)
newMat[i - 1][k - 1] = m[i][k];
}
return newMat;
}
You can adapt to however your Matrix class works.
subMatrix is not really excluding the given row and column - it is just making them zero (not copying) and removing the last row and column...
Printing the matrix will help debug that.
one way: use additional indices for the destination matrix (the sub matrix). Only increment this if a value is really copied. Example: sub.array[k++][l++] = a.array[i][j] inside the if
loop over original matrix
Alternative: if one index is greater than or equal to the index that must be skipped, add 1 to the reading index:
var k = (i>=exclRow) ? i+1 : i;
var l = (j>=exclCol) ? j+1 : j;
sub.array[i][j = a.array[k][l];
code not intended to be complete, just ideas how to solve the problem

Finding the Minor Matrix

I have a Matrix class that has the following method
private Matrix matrixMinors()
{
double[][] matrixM = new double[matrix.length][matrix.length];
for(int i = 0; i < matrixM.length; i++)
for(int j = 0; j < matrixM.length; j++)
{
double[][] newone = new double[matrixM.length - 1][matrixM.length - 1];
for(int k = 0; k < newone.length; k++)
for(int h = 0; h < newone[0].length; h++)
if(k == i)
;
else if(h == j)
;
else
newone[k][h] = matrix[k][h];
test(newone, "little matrix"); //this just prints the matrix for debugging purposes
matrixM[i][j] = determinant(newone, newone.length);
}
test(matrixM, "minor matrix"); //this just prints the matrix for debugging purposes
return new Matrix(matrixM);
}
When printed the minor matrix has all zeros, any suggestions as to how to fix this.
Update:
My determinant method keeps printing only zeros, but I'm not sure if that's just because the data I'm giving it makes a zero determinant or my code is faulty.
private double determinant(double[][] mat, int size)
{
double det = 0;
if(size == 1)
det = mat[0][0];
else if (size == 2)
det = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
else
{
for(int j1 = 0; j1 < size; j1++)
{
double[][] m = new double[size-1][];
for(int k = 0; k < (size-1); k++)
m[k] = new double[size-1];
for(int i = 1; i < size; i++)
{
int j2 = 0;
for(int j = 0; j < size; j++)
{
if(j == j1)
continue;
m[i-1][j2] = mat[i][j];
j2++;
}
}
det += Math.pow(-1.0, 1.0 + j1 + 1.0) * mat[0][j1] * determinant(m, size - 1);
}
}
return det;
}
My first advice would be to replace the ugly if-else:
This one:
if(k == i)
;
else if(h == j)
;
else
newone[k][h] = matrix[k][h];
With:
if(k!=i && h!=j) {
System.out.println("test: "+matrix[k][h]);//to see if it enters here
newone[k][h] = matrix[k][h];
}
If the test is not printed, then the logic is wrong.
My second advice:
Write a UnitTest for your determinant method or at least check what it returns (a System.out could help). If it always returns 0, then the minor matrix is, of course, all zeros.
Edit:
You do not need to pass the size to determinant. You can simply use:
private double determinant(double[][] mat)
{
int size = mat.length;
I tested that method with a few matixes like this:
final double[][] mat = new double[][] { { 1, 0, 1 }, { 0, 1, 0 }, { 2, 0, 1 } };
final double det = determinant(mat, 3);
System.out.println("det: " + det);
The result was as expected.
Since newone is not as expected, here a Test class you can use:
public class TestMatrix
{
private static final double delta = 0.0001;
#Test
public void testDeterminant()
{
final double[][] mat = new double[][] { { 1.5, 2.7, 3.8 }, { -4.1, 5.4, -6.6 }, { 7.1, 8000, 9000 } };
final double det = Matrix.determinant(mat, 3);
assertEquals(126817.786, det, delta);
}
// TODO add other tests!
#Test
public void testNewOne() throws Exception
{
final double[][] matrix = { { 3, 0, 2 }, { 2, 0, -2 }, { 0, 1, 1 } };
final double[][] newOne = Matrix.newOne(matrix, 0, 0);
assertMatrix(new double[][] { { 0, -2 }, { 1, 1 } }, newOne);
}
private void assertMatrix(final double[][] ds, final double[][] newOne)
{
assertEquals(ds.length, newOne.length);
for (int i = 0; i < ds.length; i++)
{
assertEquals(ds[i].length, newOne[i].length);
for (int j = 0; j < ds[i].length; j++)
{
assertEquals(ds[i][j], newOne[i][j], delta);
}
}
}
}
I wrote a newOne method like this:
public static double[][] newOne(final double[][] matrix, final int i, final int j)
{
final double[][] newone = new double[matrix.length - 1][matrix.length - 1];
for(int k = 0; k < newone.length; k++)
{
for(int h = 0; h < newone[0].length; h++)
if (k != i && h != j)
{
newone[k][h] = matrix[k][h];
}
}
return newone;
}
Your matrixMinor would then be:
//...
for(int i = 0; i < matrixM.length; i++)
for(int j = 0; j < matrixM.length; j++)
{
double[][] newone = newOne(matrixM, i, j);
test(newone, "little matrix");
matrixM[i][j]=determinant(newone, newone.length);
}
//...
Then just change the method newOne until the UnitTest pass (a few more Tests wouldn't hurt, I just wrote one to show you how it can be done).

Alter Simplex Algorithm to Minimize on objective function NOT maximize [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I have created the following Simplex Algorithm that maximises on the objective function. I want the opposite to happen. In this example there are two variables and the algorithm must figure out what to multiply these two variables here (13.0 and 23.0) by in order to get the maximum possible result within the constraints set. I want the algorithm to figure out the lowest possible result instead.
My Code:
import java.util.*;
public class Simplex
{
private static final double EPSILON = 1.0E-10;
private double[][] tableaux;
private int numOfConstraints;
private int numOfVariables;
private int[] basis;
/**
* Constructor for objects of class Simplex
*/
public Simplex()
{
double[][] thisTableaux = {
{ 5.0, 15.0 },
{ 4.0, 4.0 },
{ 35.0, 20.0 },
};
double[] constraints = { 480.0, 160.0, 1190.0 };
double[] variables = { 13.0, 23.0 };
numOfConstraints = constraints.length;
numOfVariables = variables.length;
tableaux = new double[numOfConstraints+1][numOfVariables+numOfConstraints+1];
//adds all elements from thisTableaux to tableaux
for(int i=0; i < numOfConstraints; i++)
{
for(int j=0; j < numOfVariables; j++)
{
tableaux[i][j] = thisTableaux[i][j];
}
}
//adds a slack variable for each variable there is and sets it to 1.0
for(int i=0; i < numOfConstraints; i++)
{
tableaux[i][numOfVariables+i] = 1.0;
}
//adds variables into the second [] of tableux
for(int j=0; j < numOfVariables; j++)
{
tableaux[numOfConstraints][j] = variables[j];
}
//adds constraints to first [] of tableaux
for(int k=0; k < numOfConstraints; k++)
{
tableaux[k][numOfConstraints+numOfVariables] = constraints[k];
}
basis = new int[numOfConstraints];
for(int i=0; i < numOfConstraints; i++)
{
basis[i] = numOfVariables + i;
}
//show();
//optimise();
//assert check(thisTableaux, constraints, variables);
}
public void optimise() {
while(true) {
int q = findLowestNonBasicCol();
if(q == -1) {
break;
}
int p = getPivotRow(q);
if(p == -1) throw new ArithmeticException("Linear Program Unbounded");
pivot(p, q);
basis[p] = q;
}
}
public int findLowestNonBasicCol() {
for(int i=0; i < numOfConstraints + numOfVariables; i++)
{
if(tableaux[numOfConstraints][i] > 0) {
return i;
}
}
return -1;
}
public int findIndexOfLowestNonBasicCol() {
int q = 0;
for(int i=1; i < numOfConstraints + numOfVariables; i++)
{
if(tableaux[numOfConstraints][i] > tableaux[numOfConstraints][q]) {
q = i;
}
}
if(tableaux[numOfConstraints][q] <= 0) {
return -1;
}
else {
return q;
}
}
/**
* Finds row p which will be the pivot row using the minimum ratio rule.
* -1 if there is no pivot row
*/
public int getPivotRow(int q) {
int p = -1;
for(int i=0; i < numOfConstraints; i++) {
if (tableaux[i][q] <=0) {
continue;
}
else if (p == -1) {
p = i;
}
else if((tableaux[i][numOfConstraints+numOfVariables] / tableaux[i][q] < tableaux[p][numOfConstraints+numOfVariables] / tableaux[p][q])) {
p = i;
}
}
return p;
}
public void pivot(int p, int q) {
for(int i=0; i <= numOfConstraints; i++) {
for (int j=0; j <= numOfConstraints + numOfVariables; j++) {
if(i != p && j != q) {
tableaux[i][j] -= tableaux[p][j] * tableaux[i][q] / tableaux[p][q];
}
}
}
for(int i=0; i <= numOfConstraints; i++) {
if(i != p) {
tableaux[i][q] = 0.0;
}
}
for(int j=0; j <= numOfConstraints + numOfVariables; j++) {
if(j != q) {
tableaux[p][j] /= tableaux[p][q];
}
}
tableaux[p][q] = 1.0;
show();
}
public double result() {
return -tableaux[numOfConstraints][numOfConstraints+numOfVariables];
}
public double[] primal() {
double[] x = new double[numOfVariables];
for(int i=0; i < numOfConstraints; i++) {
if(basis[i] < numOfVariables) {
x[basis[i]] = tableaux[i][numOfConstraints+numOfVariables];
}
}
return x;
}
public double[] dual() {
double[] y = new double[numOfConstraints];
for(int i=0; i < numOfConstraints; i++) {
y[i] = -tableaux[numOfConstraints][numOfVariables];
}
return y;
}
public boolean isPrimalFeasible(double[][] thisTableaux, double[] constraints) {
double[] x = primal();
for(int j=0; j < x.length; j++) {
if(x[j] < 0.0) {
StdOut.println("x[" + j + "] = " + x[j] + " is negative");
return false;
}
}
for(int i=0; i < numOfConstraints; i++) {
double sum = 0.0;
for(int j=0; j < numOfVariables; j++) {
sum += thisTableaux[i][j] * x[j];
}
if(sum > constraints[i] + EPSILON) {
StdOut.println("not primal feasible");
StdOut.println("constraints[" + i + "] = " + constraints[i] + ", sum = " + sum);
return false;
}
}
return true;
}
private boolean isDualFeasible(double[][] thisTableaux, double[] variables) {
double[] y = dual();
for(int i=0; i < y.length; i++) {
if(y[i] < 0.0) {
StdOut.println("y[" + i + "] = " + y[i] + " is negative");
return false;
}
}
for(int j=0; j < numOfVariables; j++) {
double sum = 0.0;
for(int i=0; i < numOfConstraints; i++) {
sum += thisTableaux[i][j] * y[i];
}
if(sum < variables[j] - EPSILON) {
StdOut.println("not dual feasible");
StdOut.println("variables[" + j + "] = " + variables[j] + ", sum = " + sum);
return false;
}
}
return true;
}
private boolean isOptimal(double[] constraints, double[] variables) {
double[] x = primal();
double[] y = dual();
double value = result();
double value1 = 0.0;
for(int j=0; j < x.length; j++) {
value1 += variables[j] * x[j];
}
double value2 = 0.0;
for(int i=0; i < y.length; i++) {
value2 += y[i] * constraints[i];
}
if(Math.abs(value - value1) > EPSILON || Math.abs(value - value2) > EPSILON) {
StdOut.println("value = " + value + ", cx = " + value1 + ", yb = " + value2);
return true;
}
return true;
}
private boolean check(double[][] thisTableaux, double[] constraints, double [] variables) {
return isPrimalFeasible(thisTableaux, constraints) && isDualFeasible(thisTableaux, variables) && isOptimal(constraints, variables);
}
}
If you need any more info just ask. Any help appreciated thanks.
If you want to minimize f(x), this is equivalent to maximizing -f(x), so if your posted code solves maximization problems correctly, you can use it to minimize any objective function f(x) simply by maximizing its additive inverse -f(x).
Note that you do not change the constraints, only the objective function.
For example, minimizing f(x) = 3x + 5, x >= 1 is equivalent to maximizing -f(x) = -3x -5, x >= 1.
min[f(x), x>=1] = f(1) = 8 = -(-8) = -[-f(1)] = -max[-f(x), x>=1].
In general, min[f(x)] = f(Xmin) = -[-f(Xmax)] = -max[-f(x)] and Xmin = Xmax.
In the above example, min[f(x)] = -max[-f(x)] = 8 and Xmin = Xmax = 1.
In the particular example you give, you would simply need to change the line
double[] variables = { 13.0, 23.0 };
to
double[] variables = { -13.0, -23.0 };
The values of the variables returned should then be the same as for the minimum of the case where
double[] variables = { 13.0, 23.0 };
and multiplying the value of the objective function by -1 will give the minimum of the objective for the case where
double[] variables = { 13.0, 23.0 };

Calculating matrix determinant

I am trying to calculate the determinant of a matrix (of any size), for self coding / interview practice. My first attempt is using recursion and that leads me to the following implementation:
import java.util.Scanner.*;
public class Determinant {
double A[][];
double m[][];
int N;
int start;
int last;
public Determinant (double A[][], int N, int start, int last){
this.A = A;
this.N = N;
this.start = start;
this.last = last;
}
public double[][] generateSubArray (double A[][], int N, int j1){
m = new double[N-1][];
for (int k=0; k<(N-1); k++)
m[k] = new double[N-1];
for (int i=1; i<N; i++){
int j2=0;
for (int j=0; j<N; j++){
if(j == j1)
continue;
m[i-1][j2] = A[i][j];
j2++;
}
}
return m;
}
/*
* Calculate determinant recursively
*/
public double determinant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * determinant(m, N-1);
}
}
return res;
}
}
So far it is all good and it gives me a correct result. Now I would like to optimise my code by making use of multiple threads to calculate this determinant value.
I tried to parallelize it using the Java Fork/Join model. This is my approach:
#Override
protected Double compute() {
if (N < THRESHOLD) {
result = computeDeterminant(A, N);
return result;
}
for (int j1 = 0; j1 < N; j1++){
m = generateSubArray (A, N, j1);
ParallelDeterminants d = new ParallelDeterminants (m, N-1);
d.fork();
result += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * d.join();
}
return result;
}
public double computeDeterminant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * computeDeterminant(m, N-1);
}
}
return res;
}
/*
* Main function
*/
public static void main(String args[]){
double res;
ForkJoinPool pool = new ForkJoinPool();
ParallelDeterminants d = new ParallelDeterminants();
d.inputData();
long starttime=System.nanoTime();
res = pool.invoke (d);
long EndTime=System.nanoTime();
System.out.println("Seq Run = "+ (EndTime-starttime)/100000);
System.out.println("the determinant valaue is " + res);
}
However after comparing the performance, I found that the performance of the Fork/Join approach is very bad, and the higher the matrix dimension, the slower it becomes (as compared to the first approach). Where is the overhead? Can anyone shed a light on how to improve this?
Using This class you can calculate the determinant of a matrix with any dimension
This class uses many different methods to make the matrix triangular and then, calculates the determinant of it. It can be used for matrix of high dimension like 500 x 500 or even more. the bright side of the this class is that you can get the result in BigDecimal so there is no infinity and you'll have always the accurate answer. By the way, using many various methods and avoiding recursion resulted in much faster way with higher performance to the answer. hope it would be helpful.
import java.math.BigDecimal;
public class DeterminantCalc {
private double[][] matrix;
private int sign = 1;
DeterminantCalc(double[][] matrix) {
this.matrix = matrix;
}
public int getSign() {
return sign;
}
public BigDecimal determinant() {
BigDecimal deter;
if (isUpperTriangular() || isLowerTriangular())
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
else {
makeTriangular();
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
}
return deter;
}
/* receives a matrix and makes it triangular using allowed operations
on columns and rows
*/
public void makeTriangular() {
for (int j = 0; j < matrix.length; j++) {
sortCol(j);
for (int i = matrix.length - 1; i > j; i--) {
if (matrix[i][j] == 0)
continue;
double x = matrix[i][j];
double y = matrix[i - 1][j];
multiplyRow(i, (-y / x));
addRow(i, i - 1);
multiplyRow(i, (-x / y));
}
}
}
public boolean isUpperTriangular() {
if (matrix.length < 2)
return false;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < i; j++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public boolean isLowerTriangular() {
if (matrix.length < 2)
return false;
for (int j = 0; j < matrix.length; j++) {
for (int i = 0; j > i; i++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public BigDecimal multiplyDiameter() {
BigDecimal result = BigDecimal.ONE;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
if (i == j)
result = result.multiply(BigDecimal.valueOf(matrix[i][j]));
}
}
return result;
}
// when matrix[i][j] = 0 it makes it's value non-zero
public void makeNonZero(int rowPos, int colPos) {
int len = matrix.length;
outer:
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (matrix[i][j] != 0) {
if (i == rowPos) { // found "!= 0" in it's own row, so cols must be added
addCol(colPos, j);
break outer;
}
if (j == colPos) { // found "!= 0" in it's own col, so rows must be added
addRow(rowPos, i);
break outer;
}
}
}
}
}
//add row1 to row2 and store in row1
public void addRow(int row1, int row2) {
for (int j = 0; j < matrix.length; j++)
matrix[row1][j] += matrix[row2][j];
}
//add col1 to col2 and store in col1
public void addCol(int col1, int col2) {
for (int i = 0; i < matrix.length; i++)
matrix[i][col1] += matrix[i][col2];
}
//multiply the whole row by num
public void multiplyRow(int row, double num) {
if (num < 0)
sign *= -1;
for (int j = 0; j < matrix.length; j++) {
matrix[row][j] *= num;
}
}
//multiply the whole column by num
public void multiplyCol(int col, double num) {
if (num < 0)
sign *= -1;
for (int i = 0; i < matrix.length; i++)
matrix[i][col] *= num;
}
// sort the cols from the biggest to the lowest value
public void sortCol(int col) {
for (int i = matrix.length - 1; i >= col; i--) {
for (int k = matrix.length - 1; k >= col; k--) {
double tmp1 = matrix[i][col];
double tmp2 = matrix[k][col];
if (Math.abs(tmp1) < Math.abs(tmp2))
replaceRow(i, k);
}
}
}
//replace row1 with row2
public void replaceRow(int row1, int row2) {
if (row1 != row2)
sign *= -1;
double[] tempRow = new double[matrix.length];
for (int j = 0; j < matrix.length; j++) {
tempRow[j] = matrix[row1][j];
matrix[row1][j] = matrix[row2][j];
matrix[row2][j] = tempRow[j];
}
}
//replace col1 with col2
public void replaceCol(int col1, int col2) {
if (col1 != col2)
sign *= -1;
System.out.printf("replace col%d with col%d, sign = %d%n", col1, col2, sign);
double[][] tempCol = new double[matrix.length][1];
for (int i = 0; i < matrix.length; i++) {
tempCol[i][0] = matrix[i][col1];
matrix[i][col1] = matrix[i][col2];
matrix[i][col2] = tempCol[i][0];
}
} }
This Class Receives a matrix of n x n from the user then calculates it's determinant. It also shows the solution and the final triangular matrix.
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Scanner;
public class DeterminantTest {
public static void main(String[] args) {
String determinant;
//generating random numbers
/*int len = 300;
SecureRandom random = new SecureRandom();
double[][] matrix = new double[len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
matrix[i][j] = random.nextInt(500);
System.out.printf("%15.2f", matrix[i][j]);
}
}
System.out.println();*/
/*double[][] matrix = {
{1, 5, 2, -2, 3, 2, 5, 1, 0, 5},
{4, 6, 0, -2, -2, 0, 1, 1, -2, 1},
{0, 5, 1, 0, 1, -5, -9, 0, 4, 1},
{2, 3, 5, -1, 2, 2, 0, 4, 5, -1},
{1, 0, 3, -1, 5, 1, 0, 2, 0, 2},
{1, 1, 0, -2, 5, 1, 2, 1, 1, 6},
{1, 0, 1, -1, 1, 1, 0, 1, 1, 1},
{1, 5, 5, 0, 3, 5, 5, 0, 0, 6},
{1, -5, 2, -2, 3, 2, 5, 1, 1, 5},
{1, 5, -2, -2, 3, 1, 5, 0, 0, 1}
};
*/
double[][] matrix = menu();
DeterminantCalc deter = new DeterminantCalc(matrix);
BigDecimal det = deter.determinant();
determinant = NumberFormat.getInstance().format(det);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
System.out.printf("%15.2f", matrix[i][j]);
}
System.out.println();
}
System.out.println();
System.out.printf("%s%s%n", "Determinant: ", determinant);
System.out.printf("%s%d", "sign: ", deter.getSign());
}
public static double[][] menu() {
Scanner scanner = new Scanner(System.in);
System.out.print("Matrix Dimension: ");
int dim = scanner.nextInt();
double[][] inputMatrix = new double[dim][dim];
System.out.println("Set the Matrix: ");
for (int i = 0; i < dim; i++) {
System.out.printf("%5s%d%n", "row", i + 1);
for (int j = 0; j < dim; j++) {
System.out.printf("M[%d][%d] = ", i + 1, j + 1);
inputMatrix[i][j] = scanner.nextDouble();
}
System.out.println();
}
scanner.close();
return inputMatrix;
}}
The main reason the ForkJoin code is slower is that it's actually serialized with some thread overhead thrown in. To benefit from fork/join, you need to 1) fork all instances first, then 2) wait for the results. Split your loop in "compute" into two loops: one to fork (storing instances of ParallelDeterminants in, say, an array) and another to collect the results.
Also, I suggest to only fork at the outermost level and not in any of the inner ones. You don't want to be creating O(N^2) threads.
There is a new method of calculating the determinant of the matrix you can read more from here
and I've implemented a simple version of this with no fancy optimization techniques or library in plain simple java and I've tested against methods described previously and it was faster on average by a factor of 10
public class Test {
public static double[][] reduce(int row , int column , double[][] mat){
int n=mat.length;
double[][] res = new double[n- 1][n- 1];
int r=0,c=0;
for (int i = 0; i < n; i++) {
c=0;
if(i==row)
continue;
for (int j = 0; j < n; j++) {
if(j==column)
continue;
res[r][c] = mat[i][j];
c++;
}
r++;
}
return res;
}
public static double det(double mat[][]){
int n = mat.length;
if(n==1)
return mat[0][0];
if(n==2)
return mat[0][0]*mat[1][1] - (mat[0][1]*mat[1][0]);
//TODO : do reduce more efficiently
double[][] m11 = reduce(0,0,mat);
double[][] m1n = reduce(0,n-1,mat);
double[][] mn1 = reduce(n-1 , 0 , mat);
double[][] mnn = reduce(n-1,n-1,mat);
double[][] m11nn = reduce(0,0,reduce(n-1,n-1,mat));
return (det(m11)*det(mnn) - det(m1n)*det(mn1))/det(m11nn);
}
public static double[][] randomMatrix(int n , int range){
double[][] mat = new double[n][n];
for (int i=0; i<mat.length; i++) {
for (int j=0; j<mat[i].length; j++) {
mat[i][j] = (Math.random()*range);
}
}
return mat;
}
public static void main(String[] args) {
double[][] mat = randomMatrix(10,100);
System.out.println(det(mat));
}
}
there is a little fault in the case of the determinant of m11nn if happen to be zero it will blow up and you should check for that. I've tested on 100 random samples it rarely happens but I think it worth mentioning and also using a better indexing scheme can also improve the efficiency
This is a part of my Matrix class which uses a double[][] member variable called data to store the matrix data.
The _determinant_recursivetask_impl() function uses a RecursiveTask<Double> object with the ForkJoinPool to try to use multiple threads for calculation.
This method performs very slow compared to matrix operations to get an upper/lower triangular matrix. Try to compute the determinant of a 13x13 matrix for example.
public class Matrix
{
// Dimensions
private final int I,J;
private final double[][] data;
private Double determinant = null;
static class MatrixEntry
{
public final int I,J;
public final double value;
private MatrixEntry(int i, int j, double value) {
I = i;
J = j;
this.value = value;
}
}
/**
* Calculates determinant of this Matrix recursively and caches it for future use.
* #return determinant
*/
public double determinant()
{
if(I!=J)
throw new IllegalStateException(String.format("Can't calculate determinant of (%d,%d) matrix, not a square matrix.", I,J));
if(determinant==null)
determinant = _determinant_recursivetask_impl(this);
return determinant;
}
private static double _determinant_recursivetask_impl(Matrix m)
{
class determinant_recurse extends RecursiveTask<Double>
{
private final Matrix m;
determinant_recurse(Matrix m) {
this.m = m;
}
#Override
protected Double compute() {
// Base cases
if(m.I==1 && m.J==1)
return m.data[0][0];
else if(m.I==2 && m.J==2)
return m.data[0][0]*m.data[1][1] - m.data[0][1]*m.data[1][0];
else
{
determinant_recurse[] tasks = new determinant_recurse[m.I];
for (int i = 0; i <m.I ; i++) {
tasks[i] = new determinant_recurse(m.getSubmatrix(0, i));
}
for (int i = 1; i <m.I ; i++) {
tasks[i].fork();
}
double ret = m.data[0][0]*tasks[0].compute();
for (int i = 1; i < m.I; i++) {
if(i%2==0)
ret += m.data[0][i]*tasks[i].join();
else
ret -= m.data[0][i]*tasks[i].join();
}
return ret;
}
}
}
return ForkJoinPool.commonPool().invoke(new determinant_recurse(m));
}
private static void _map_impl(Matrix ret, Function<Matrix.MatrixEntry, Double> operator)
{
for (int i = 0; i <ret.I ; i++) {
for (int j = 0; j <ret.J ; j++) {
ret.data[i][j] = operator.apply(new Matrix.MatrixEntry(i,j,ret.data[i][j]));
}
}
}
/**
* Returns a new Matrix that is sub-matrix without the given row and column.
* #param removeI row to remove
* #param removeJ col. to remove
* #return new Matrix.
*/
public Matrix getSubmatrix(int removeI, int removeJ)
{
if(removeI<0 || removeJ<0 || removeI>=this.I || removeJ>=this.J)
throw new IllegalArgumentException(String.format("Invalid element position (%d,%d) for matrix(%d,%d).", removeI,removeJ,this.I,this.J));
Matrix m = new Matrix(this.I-1, this.J-1);
_map_impl(m, (e)->{
int i = e.I, j = e.J;
if(e.I >= removeI) ++i;
if(e.J >= removeJ) ++j;
return this.data[i][j];
});
return m;
}
// Constructors
public Matrix(int i, int j) {
if(i<1 || j<1)
throw new IllegalArgumentException(String.format("Invalid array dimensions: (%d,%d)", i, j));
I = i;
J = j;
data = new double[I][J];
}
}
int det(int[][] mat) {
if (mat.length == 1)
return mat[0][0];
if (mat.length == 2)
return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
int sum = 0, sign = 1;
int newN = mat.length - 1;
int[][] temp = new int[newN][newN];
for (int t = 0; t < newN; t++) {
int q = 0;
for (int i = 0; i < newN; i++) {
for (int j = 0; j < newN; j++) {
temp[i][j] = mat[1 + i][q + j];
}
if (q == i)
q = 1;
}
sum += sign * mat[0][t] * det(temp);
sign *= -1;
}
return sum;
}

Categories

Resources