I want to use the MATLab Function imresize in a Java project. For this I search the sourcecode of this function or an equal class in Java.
I want to resize an double[][] with an scale factor of 0.4 to an new double[][].
I found already an SourceCode, but this Code uses an Matlab.sum function, which I don't have:
import java.util.ArrayList;
import java.util.List;
public class MatlabResize {
private static final double TRIANGLE_KERNEL_WIDTH = 2;
public static double[][] resizeMatlab(double[][] data, double scale) {
int out_x = (int)Math.ceil(data[0].length * scale);
int out_y = (int)Math.ceil(data.length * scale);
double[][][] weights_indizes = contribution(data.length, out_y, scale, TRIANGLE_KERNEL_WIDTH);
double[][] weights = weights_indizes[0];
double[][] indices = weights_indizes[1];
final double[][] result = new double[out_y][data[0].length];
double value = 0;
for (int p=0; p<result[0].length; p++) {
for (int i=0; i<weights.length; i++) {
value = 0;
for (int j=0; j<indices[0].length; j++) {
value += weights[i][j] * data[(int)indices[i][j]][p];
}
result[i][p] = value;
}
}
weights_indizes = contribution(data[0].length, out_x, scale, TRIANGLE_KERNEL_WIDTH);
weights = weights_indizes[0];
indices = weights_indizes[1];
final double[][] result2 = new double[result.length][out_x];
for (int p=0; p<result.length; p++) {
for (int i=0; i<weights.length; i++) {
value = 0;
for (int j=0; j<indices[0].length; j++) {
value += weights[i][j] * result[p][(int)indices[i][j]];
}
result2[p][i] = value;
}
}
return result2;
}
private static double[][][] contribution(int length, int output_size, double scale, double kernel_width) {
if (scale < 1.0) {
kernel_width = kernel_width/scale;
}
final double[] x = new double[output_size];
for (int i=0; i<x.length; i++) {
x[i] = i+1;
}
final double[] u = new double[output_size];
for (int i=0; i<u.length; i++) {
u[i] = x[i]/scale + 0.5*(1 - 1/scale);
}
final double[] left = new double[output_size];
for (int i=0; i<left.length; i++) {
left[i] = Math.floor(u[i] - kernel_width/2);
}
int P = (int)Math.ceil(kernel_width) + 2;
final double[][] indices = new double[left.length][P];
for (int i=0; i<left.length; i++) {
for (int j=0; j<=P-1; j++) {
indices[i][j] = left[i] + j;
}
}
double[][] weights = new double[u.length][indices[0].length];
for (int i=0; i<u.length; i++) {
for (int j=0; j<indices[i].length; j++) {
weights[i][j] = u[i] - indices[i][j];
}
}
if (scale < 1.0) {
weights = triangleAntiAliasing(weights, scale);
} else {
weights = triangle(weights);
}
double[] sum = Matlab.sum(weights, 2);
for (int i=0; i<weights.length; i++) {
for (int j=0; j<weights[i].length; j++) {
weights[i][j] = weights[i][j] / sum[i];
}
}
for (int i=0; i<indices.length; i++) {
for (int j=0; j<indices[i].length; j++) {
indices[i][j] = Math.min(Math.max(indices[i][j], 1.0), length);
}
}
sum = Matlab.sum(weights, 1);
int a = 0;
final List<Integer> list = new ArrayList<Integer>();
for (int i=0; i<sum.length; i++) {
if (sum[i] != 0.0) {
a++;
list.add(i);
}
}
final double[][][] result = new double[2][weights.length][a];
for (int i=0; i<weights.length; i++) {
for (int j=0; j<list.size(); j++) {
result[0][i][j] = weights[i][list.get(j)];
}
}
for (int i=0; i<indices.length; i++) {
for (int j=0; j<list.size(); j++) {
result[1][i][j] = indices[i][list.get(j)]-1; //java indices start by 0 and not by 1
}
}
return result;
}
private static double[][] triangle(final double[][] x) {
for (int i=0; i<x.length; i++) {
for (int j=0; j<x[i].length; j++) {
if (-1.0 <= x[i][j] && x[i][j] < 0.0) {
x[i][j] = x[i][j] + 1;
} else if (0.0 <= x[i][j] && x[i][j] < 1.0) {
x[i][j] = 1 - x[i][j];
} else {
x[i][j] = 0;
}
}
}
return x;
}
private static double[][] triangleAntiAliasing(final double[][] x, final double scale) {
for (int i=0; i<x.length; i++) {
for (int j=0; j<x[i].length; j++) {
x[i][j] = x[i][j] * scale;
}
}
for (int i=0; i<x.length; i++) {
for (int j=0; j<x[i].length; j++) {
if (-1.0 <= x[i][j] && x[i][j] < 0.0) {
x[i][j] = x[i][j] + 1;
} else if (0.0 <= x[i][j] && x[i][j] < 1.0) {
x[i][j] = 1 - x[i][j];
} else {
x[i][j] = 0;
}
}
}
for (int i=0; i<x.length; i++) {
for (int j=0; j<x[i].length; j++) {
x[i][j] = x[i][j] * scale;
}
}
return x;
}
}
My Sum function, which NOW work: :)
public class Matlab {
public static double[] sum(double[][] weights, int i) {
double[] des;
switch (i) {
case 1:
des = new double[weights[0].length];
for (int k = 0; k < weights[0].length; k++) {
double sum =0;
for(int j = 0; j<weights.length;j++){
sum += weights[j][k];
}
des[k]=sum;
}
return des;
case 2:
des = new double[weights.length];
for(int j = 0; j<weights.length;j++){
double sum =0;
for (int k = 0; k < weights[j].length; k++) {
sum += weights[j][k];
}
des[j]=sum;
}
return des;
return null;
}
}
Related
it contains two java classes: TwoDMethods.java and TwoDTest.java
for TwoDMethods.java
The fill method fills the entire array with randomly-selected double values
between 0.0 and 100.0
The toString method returns a string representation of the two-dimensional
array, with the rows separated by "\n" and the columns vertically aligned
The sumColumns method returns a one-dimensional array containing the sum
of each column of the given two-dimensional array
The sumRows method returns a one-dimensional array containing the sum of
each row of the given two-dimensional array
The minValue method returns the smallest number in the given array
The maxValue method returns the largest number in the given array
I finished TwoDMethods.java but I am not sure how to write TwoDTest.java
and all methods should be static but the toString method always goes wrong when I add static.
For example, in TwoDTest.java using the following command:
java TwoDTest 3 4
the output will be:
toString() result:
41.23 72.99 8.60 38.62
70.32 52.00 38.63 90.60
72.98 6.54 94.50 91.34
Column sums:
184.53 131.54 141.73 220.56
Row sums:
161.45 251.55 265.36
Smallest number: 6.54
Largest number: 94.50
this is TwoDMethods.java:
public class TwoDMethods {
static int row, col;
static double sumRow, sumCol;
static double[][] array = new double[row][col];
public static void fill() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
array[i][j] = (double) (Math.random() * 100.00);
}
}
public String toString() {
String method2 ="";
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
method2 += String.format("%8.2f", array[row][col]) + " ";
}
method2 += "\n";
}
return method2;
}
public static double[] sumRows() {
double[] rowArray = new double[row];
for (int i = 0; i < row; i++) {
sumRow = 0;
for (int j = 0; j < col; j++) {
sumRow = sumRow + array[i][j];
}
rowArray[i] = sumRow;
}
return rowArray;
}
public static double[] sumColumns() {
double[] colArray = new double[col];
for (int i = 0; i < col; i++) {
sumCol = 0;
for (int j = 0; j < row; j++) {
sumCol = sumCol + array[j][i];
}
colArray[i] = sumCol;
}
return colArray;
}
public static double minValue() {
double minValue = array[0][0];
for (int j = 0; j < array.length; j++) {
for (int i = 0; i < array[j].length; i++) {
if (array[j][i] < minValue) {
minValue = array[j][i];
}
}
}
return minValue;
}
public static double maxValue() {
double maxValue = array[0][0];
for (int j = 0; j < array.length; j++) {
for (int i = 0; i < array[j].length; i++) {
if (array[j][i] > maxValue) {
maxValue = array[j][i];
}
}
}
return maxValue;
}
}
I suggest not to make the methods static nor the members of class TwoDMethods. Here is my suggested code. It is basically your code with occurrences of static removed plus I added a constructor. The constructor initializes the class members. Note that you had an error in method toString in this line:
method2 += String.format("%8.2f", array[row][col]) + " ";
It should be:
method2 += String.format("%8.2f", array[i][j]) + " ";
I changed it in the below code.
public class TwoDMethods {
int row, col;
double sumRow, sumCol;
double[][] array = new double[row][col];
public TwoDMethods(int numRows, int numColumns) {
row = numRows;
col = numColumns;
array = new double[row][col];
}
public void fill() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
array[i][j] = (double) (Math.random() * 100.00);
}
}
public String toString() {
String method2 = "";
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
method2 += String.format("%8.2f", array[i][j]) + " ";
}
method2 += "\n";
}
return method2;
}
public double[] sumRows() {
double[] rowArray = new double[row];
for (int i = 0; i < row; i++) {
sumRow = 0;
for (int j = 0; j < col; j++) {
sumRow = sumRow + array[i][j];
}
rowArray[i] = sumRow;
}
return rowArray;
}
public double[] sumColumns() {
double[] colArray = new double[col];
for (int i = 0; i < col; i++) {
sumCol = 0;
for (int j = 0; j < row; j++) {
sumCol = sumCol + array[j][i];
}
colArray[i] = sumCol;
}
return colArray;
}
public double minValue() {
double minValue = array[0][0];
for (int j = 0; j < array.length; j++) {
for (int i = 0; i < array[j].length; i++) {
if (array[j][i] < minValue) {
minValue = array[j][i];
}
}
}
return minValue;
}
public double maxValue() {
double maxValue = array[0][0];
for (int j = 0; j < array.length; j++) {
for (int i = 0; i < array[j].length; i++) {
if (array[j][i] > maxValue) {
maxValue = array[j][i];
}
}
}
return maxValue;
}
}
And here is the class you requested, TwoDTest.
public class TwoDTest {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("Usage: TwoDTest row cols");
}
else {
int numRows = Integer.parseInt(args[0]);
int numColumns = Integer.parseInt(args[1]);
TwoDMethods twoD = new TwoDMethods(numRows, numColumns);
twoD.fill();
System.out.print(twoD);
System.out.println("Column sums:");
double[] sumColumns = twoD.sumColumns();
for (double sum : sumColumns) {
System.out.printf("%8.2f ", sum);
}
System.out.println();
System.out.println("Row sums:");
double[] sumRows = twoD.sumRows();
for (double sum : sumRows) {
System.out.printf("%8.2f ", sum);
}
System.out.println();
System.out.println("Smallest number: " + twoD.minValue());
System.out.println("Largest number: " + twoD.maxValue());
}
}
}
I launch class TwoDTest as follows:
java TwoDTest 3 4
And I get the following output:
96.83 11.96 50.86 43.26
89.06 84.86 30.68 59.61
63.51 96.09 49.93 32.19
Column sums:
249.39 192.92 131.47 135.05
Row sums:
202.90 264.21 241.72
Smallest number: 11.962167522763945
Largest number: 96.82621497529537
I was trying to solve a XOR problem, but the output always converged to 0.5, so i tried a simpler problem like NOT and the same thing happened.
I really don't know what's going on, i checked the code a million times and everything seems to be right, when i debugged it saving the neural network info I saw that the either the weight values or the biases values were getting really large. To do that I followed the 3 blue 1 brown youtube series about neural network and some other videos, too.
this is my code:
PS: I put the entire code here but I think the main problem is inside the bakpropag function
class NeuralNetwork {
int inNum, hiddenLayersNum, outNum, netSize;
int[] hiddenLayerSize;
Matrix[] weights;
Matrix[] biases;
Matrix[] sums;
Matrix[] activations;
Matrix[] error;
Matrix inputs;
long samples = 0;
float learningRate;
//Constructor------------------------------------------------------------------------------------------------------
NeuralNetwork(int inNum, int hiddenLayersNum, int[] hiddenLayerSize, int outNum, float learningRate) {
this.inNum = inNum;
this.hiddenLayersNum = hiddenLayersNum;
this.hiddenLayerSize = hiddenLayerSize;
this.outNum = outNum;
this.netSize = hiddenLayersNum + 1;
this.learningRate = learningRate;
//output layer plus the hidden layer size
//Note: I'm not adding the input layer because it doesn't have weights
weights = new Matrix[netSize];
//no biases added to the output layer
biases = new Matrix[netSize - 1];
sums = new Matrix[netSize];
activations = new Matrix[netSize];
error = new Matrix[netSize];
initializeHiddenLayer();
initializeOutputLayer();
}
//Initializing Algorithms------------------------------------------------------------------------------------------
void initializeHiddenLayer() {
for (int i = 0; i < hiddenLayersNum; i++) {
if (i == 0) {//only the first hidden layer takes the inputs
weights[i] = new Matrix(hiddenLayerSize[i], inNum);
} else {
weights[i] = new Matrix(hiddenLayerSize[i], hiddenLayerSize[i - 1]);
}
biases[i] = new Matrix(hiddenLayerSize[i], 1);
sums[i] = new Matrix(hiddenLayerSize[i], 1);
activations[i] = new Matrix(hiddenLayerSize[i], 1);
error[i] = new Matrix(hiddenLayerSize[i], 1);
}
}
void initializeOutputLayer() {
//the output layer takes the last hidden layer activation values
weights[netSize - 1] = new Matrix(outNum, hiddenLayerSize[hiddenLayerSize.length - 1]);
activations[netSize - 1] = new Matrix(outNum, 1);
sums[netSize - 1] = new Matrix(outNum, 1);
error[netSize - 1] = new Matrix(outNum, 1);
for (Matrix m : weights) {
for (int i = 0; i < m.i; i++) {
for (int j = 0; j < m.j; j++) {
m.values[i][j] = random(-1, 1);
}
}
}
for (Matrix m : biases) {
for (int i = 0; i < m.i; i++) {
for (int j = 0; j < m.j; j++) {
m.values[i][j] = 1;
}
}
}
for (Matrix m : sums) {
for (int i = 0; i < m.i; i++) {
for (int j = 0; j < m.j; j++) {
m.values[i][j] = 0;
}
}
}
}
//Calculation------------------------------------------------------------------------------------------------------
void calculate(float[] inputs) {
this.inputs = new Matrix(0, 0);
this.inputs = this.inputs.arrayToCollumn(inputs);
sums[0] = (weights[0].matrixMult(this.inputs)).sum(biases[0]);
activations[0] = sigM(sums[0]);
for (int i = 1; i < netSize - 1; i++) {
sums[i] = weights[i].matrixMult(activations[i - 1]);
activations[i] = sigM(sums[i]).sum(biases[i]);
}
//there's no biases in the output layer
//And the output layer uses sigmoid function
sums[netSize - 1] = weights[netSize - 1].matrixMult(activations[netSize - 1 - 1]);
activations[netSize - 1] = sigM(sums[netSize - 1]);
}
//Sending outputs--------------------------------------------------------------------------------------------------
Matrix getOuts() {
return activations[netSize - 1];
}
//Backpropagation--------------------------------------------------------------------------------------------------
void calcError(float[] exp) {
Matrix expected = new Matrix(0, 0);
expected = expected.arrayToCollumn(exp);
//E = (output - expected)
error[netSize - 1] = this.getOuts().diff(expected);
samples++;
}
void backPropag(int layer) {
if (layer == netSize - 1) {
error[layer].scalarDiv(samples);
for (int i = layer - 1; i >= 0; i--) {
prevLayerCost(i);
}
weightError(layer);
backPropag(layer - 1);
} else {
weightError(layer);
biasError(layer);
if (layer != 0)
backPropag(layer - 1);
}
}
void weightError(int layer) {
if (layer != 0) {
for (int i = 0; i < weights[layer].i; i++) {
for (int j = 0; j < weights[layer].j; j++) {
float changeWeight = 0;
if (layer != netSize - 1)
changeWeight = activations[layer - 1].values[j][0] * deriSig(sums[layer].values[i][0]) * error[layer].values[i][0];
else
changeWeight = activations[layer - 1].values[j][0] * deriSig(sums[layer].values[i][0]) * error[layer].values[i][0];
weights[layer].values[i][j] += -learningRate * changeWeight;
}
}
} else {
for (int i = 0; i < weights[layer].i; i++) {
for (int j = 0; j < weights[layer].j; j++) {
float changeWeight = this.inputs.values[j][0] * deriSig(sums[layer].values[i][0]) * error[layer].values[i][0];
weights[layer].values[i][j] += -learningRate * changeWeight;
}
}
}
}
void biasError(int layer) {
for (int i = 0; i < biases[layer].i; i++) {
for (int j = 0; j < biases[layer].j; j++) {
float changeBias = 0;
if (layer != netSize - 1)
changeBias = deriSig(sums[layer].values[i][0]) * error[layer].values[i][0];
biases[layer].values[i][j] += -learningRate * changeBias;
}
}
}
void prevLayerCost(int layer) {
for (int i = 0; i < activations[layer].i; i++) {
for (int j = 0; j < activations[layer + 1].j; j++) {//for all conections of that neuron to the next layer
if (layer != netSize - 1)
error[layer].values[i][0] += weights[layer + 1].values[j][i] * deriSig(sums[layer + 1].values[j][0]) * error[layer + 1].values[j][0];
else
error[layer].values[i][0] += weights[layer + 1].values[j][i] * deriSig(sums[layer + 1].values[j][0]) * error[layer + 1].values[j][0];
}
}
}
//Activation Functions---------------------------------------------------------------------------------------------
Matrix reLUM(Matrix m) {
Matrix temp = m.copyM();
for (int i = 0; i < temp.i; i++) {
for (int j = 0; j < temp.j; j++) {
temp.values[i][j] = ReLU(m.values[i][j]);
}
}
return temp;
}
float ReLU(float x) {
return max(0, x);
}
float deriReLU(float x) {
if (x <= 0)
return 0;
else
return 1;
}
Matrix sigM(Matrix m) {
Matrix temp = m.copyM();
for (int i = 0; i < temp.i; i++) {
for (int j = 0; j < temp.j; j++) {
temp.values[i][j] = sig(m.values[i][j]);
}
}
return temp;
}
float sig(float x) {
return 1 / (1 + exp(-x));
}
float deriSig(float x) {
return sig(x) * (1 - sig(x));
}
//Saving Files-----------------------------------------------------------------------------------------------------
void SaveNeuNet() {
for (int i = 0; i < weights.length; i++) {
weights[i].saveM("weights\\weightLayer" + i);
}
for (int i = 0; i < biases.length; i++) {
biases[i].saveM("biases\\biasLayer" + i);
}
for (int i = 0; i < activations.length; i++) {
activations[i].saveM("activations\\activationLayer" + i);
}
for (int i = 0; i < error.length; i++) {
error[i].saveM("errors\\errorLayer" + i);
}
}
}
and this is the Matrix code:
class Matrix {
int i, j, size;
float[][] values;
Matrix(int i, int j) {
this.i = i;
this.j = j;
this.size = i * j;
values = new float[i][j];
}
Matrix sum (Matrix other) {
if (other.i == this.i && other.j == this.j) {
for (int x = 0; x < this.i; x++) {
for (int z = 0; z < this.j; z++) {
values[x][z] += other.values[x][z];
}
}
return this;
}
return null;
}
Matrix diff(Matrix other) {
if (other.i == this.i && other.j == this.j) {
for (int x = 0; x < this.i; x++) {
for (int z = 0; z < this.j; z++) {
values[x][z] -= other.values[x][z];
}
}
return this;
}
return null;
}
Matrix scalarMult(float k) {
for (int i = 0; i < this.i; i++) {
for (int j = 0; j < this.j; j++) {
values[i][j] *= k;
}
}
return this;
}
Matrix scalarDiv(float k) {
if (k != 0) {
for (int i = 0; i < this.i; i++) {
for (int j = 0; j < this.j; j++) {
values[i][j] /= k;
}
}
return this;
} else
return null;
}
Matrix matrixMult(Matrix other) {
if (this.j != other.i)
return null;
else {
Matrix temp = new Matrix(this.i, other.j);
for (int i = 0; i < temp.i; i++) {
for (int j = 0; j < temp.j; j++) {
for (int k = 0; k < this.j; k++) {
temp.values[i][j] += this.values[i][k] * other.values[k][j];
}
}
}
return temp;
}
}
Matrix squaredValues(){
for (int i = 0; i < this.i; i++){
for (int j = 0; j < this.j; j++){
values[i][j] = sq(values[i][j]);
}
}
return this;
}
void printM() {
for (int x = 0; x < this.i; x++) {
print("| ");
for (int z = 0; z < this.j; z++) {
print(values[x][z] + " | ");
}
println();
}
}
void saveM(String name) {
String out = "";
for (int x = 0; x < this.i; x++) {
out += "| ";
for (int z = 0; z < this.j; z++) {
out += values[x][z] + " | ";
}
out += "\n";
}
saveStrings("outputs\\" + name + ".txt", new String[] {out});
}
Matrix arrayToCollumn(float[] array) {
Matrix temp = new Matrix(array.length, 1);
for (int i = 0; i < array.length; i++)
temp.values[i][0] = array[i];
return temp;
}
Matrix arrayToLine(float[] array) {
Matrix temp = new Matrix(1, array.length);
for (int j = 0; j < array.length; j++)
temp.values[0][j] = array[j];
return temp;
}
Matrix copyM(){
Matrix temp = new Matrix(i, j);
for (int i = 0; i < this.i; i++){
for (int j = 0; j < this.j; j++){
temp.values[i][j] = this.values[i][j];
}
}
return temp;
}
}
As I said, the outputs are always converging to 0.5 instead of the actual value 1 or 0
I rewrote the code and it is working now! I have no idea what was wrong with the code before but this one works:
class NeuralNetwork {
int netSize;
float learningRate;
Matrix[] weights;
Matrix[] biases;
Matrix[] activations;
Matrix[] sums;
Matrix[] errors;
NeuralNetwork(int inNum, int hiddenNum, int[] hiddenLayerSize, int outNum, float learningRate) {
netSize = hiddenNum + 1;
this.learningRate = learningRate;
weights = new Matrix[netSize];
biases = new Matrix[netSize - 1];
activations = new Matrix[netSize];
sums = new Matrix[netSize];
errors = new Matrix[netSize];
initializeMatrices(inNum, hiddenNum, hiddenLayerSize, outNum);
}
//INITIALIZING MATRICES
void initializeMatrices(int inNum, int hiddenNum, int[] layerSize, int outNum) {
for (int i = 0; i < hiddenNum; i++) {
if (i == 0)
weights[i] = new Matrix(layerSize[0], inNum);
else
weights[i] = new Matrix(layerSize[i], layerSize[i - 1]);
biases[i] = new Matrix(layerSize[i], 1);
activations[i] = new Matrix(layerSize[i], 1);
errors[i] = new Matrix(layerSize[i], 1);
sums[i] = new Matrix(layerSize[i], 1);
weights[i].randomize(-1, 1);
biases[i].randomize(-1, 1);
activations[i].randomize(-1, 1);
}
weights[netSize - 1] = new Matrix(outNum, layerSize[layerSize.length - 1]);
activations[netSize - 1] = new Matrix(outNum, 1);
errors[netSize - 1] = new Matrix(outNum, 1);
sums[netSize - 1] = new Matrix(outNum, 1);
weights[netSize - 1].randomize(-1, 1);
activations[netSize - 1].randomize(-1, 1);
}
//---------------------------------------------------------------------------------------------------------------
void forwardPropag(float[] ins) {
Matrix inputs = new Matrix(0, 0);
inputs = inputs.arrayToCollumn(ins);
sums[0] = (weights[0].matrixMult(inputs)).sum(biases[0]);
activations[0] = sigM(sums[0]);
for (int i = 1; i < netSize - 1; i++) {
sums[i] = (weights[i].matrixMult(activations[i - 1])).sum(biases[i]);
activations[i] = sigM(sums[i]);
}
//output layer does not have biases
sums[netSize - 1] = weights[netSize - 1].matrixMult(activations[netSize - 2]);
activations[netSize - 1] = sigM(sums[netSize - 1]);
}
Matrix predict(float[] inputs) {
forwardPropag(inputs);
return activations[netSize - 1].copyM();
}
//SUPERVISED LEARNING - BACKPROPAGATION
void train(float[] inps, float[] expec) {
Matrix expected = new Matrix(0, 0);
expected = expected.arrayToCollumn(expec);
errors[netSize - 1] = predict(inps).diff(expected);
calcErorrPrevLayers();
adjustWeights(inps);
adjustBiases();
for (Matrix m : errors){
m.reset();
}
}
void calcErorrPrevLayers() {
for (int l = netSize - 2; l >= 0; l--) {
for (int i = 0; i < activations[l].i; i++) {
for (int j = 0; j < activations[l + 1].i; j++) {
errors[l].values[i][0] += weights[l + 1].values[j][i] * dSig(sums[l + 1].values[j][0]) * errors[l + 1].values[j][0];
}
}
}
}
void adjustWeights(float[] inputs) {
for (int l = 0; l < netSize; l++) {
if (l == 0) {
//for ervery neuron n in the first layer
for (int n = 0; n < activations[l].i; n++) {
//for every weight w of the first layer
for (int w = 0; w < inputs.length; w++) {
float weightChange = inputs[w] * dSig(sums[l].values[n][0]) * errors[l].values[n][0];
weights[l].values[n][w] += -learningRate * weightChange;
}
}
} else {
//for ervery neuron n in the first layer
for (int n = 0; n < activations[l].i; n++) {
//for every weight w of the first layer
for (int w = 0; w < activations[l - 1].i; w++) {
float weightChange = activations[l - 1].values[w][0] * dSig(sums[l].values[n][0]) * errors[l].values[n][0];
weights[l].values[n][w] += -learningRate * weightChange;
}
}
}
}
}
void adjustBiases() {
for (int l = 0; l < netSize - 1; l++) {
//for ervery neuron n in the first layer
for (int n = 0; n < activations[l].i; n++) {
float biasChange = dSig(sums[l].values[n][0]) * errors[l].values[n][0];
biases[l].values[n][0] += -learningRate * biasChange;
}
}
}
//ACTIVATION FUNCTION
float sig(float x) {
return 1 / (1 + exp(-x));
}
float dSig(float x) {
return sig(x) * (1 - sig(x));
}
Matrix sigM(Matrix m) {
Matrix temp = m.copyM();
for (int i = 0; i < m.i; i++) {
for (int j = 0; j < m.j; j++) {
temp.values[i][j] = sig(m.values[i][j]);
}
}
return temp;
}
}
currently I am trying to implement a CPLEX exact solution for the Asymmetric Capacitated Vehicle Routing Problem with the MTZ sub-tour elimination constraints.
My problems occurs when I try to implement Lazy Constraint Callbacks. More specifically I get a null pointer exception. There are almost no tutorials for implementing callbacks, so your help will be deeply appreciated.
This is my code:
CVRP class
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import ilog.concert.*;
import ilog.cplex.*;
public class ACVRP {
// euclidean distance method
public static double distance(int x1, int y1, int x2, int y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
public static void solveModel() {
int n = 32; // number of customers
int k = 5; // number of vehicles
int c = 100; // capacity of vehicles
int datacoords[][] = new int[n][2];
double[][] node = new double[n][n]; // dissimilarity matrix
int[] demand = new int[n]; // demand of every customer
try {
// load matrixes
FileReader frd = new FileReader("demands.txt");
FileReader frcoords = new FileReader("coords.txt");
BufferedReader brd = new BufferedReader(frd);
BufferedReader brcoords = new BufferedReader(frcoords);
String str;
int counter = 0;
while ((str = brd.readLine()) != null) {
String[] splitStr = str.trim().split("\\s+");
demand[counter] = Integer.parseInt(splitStr[1]);
counter++;
}
counter = 0;
while ((str = brcoords.readLine()) != null) {
String[] splitStr = str.trim().split("\\s+");
datacoords[counter][0] = Integer.parseInt(splitStr[1]);
datacoords[counter][1] = Integer.parseInt(splitStr[2]);
counter++;
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
node[i][j] = distance(datacoords[i][0],datacoords[i][1],datacoords[j][0],datacoords[j][1]);
// if (i == j ){
// node[i][j] = 99999999;
// }
}
}
brd.close();
brcoords.close();
IloCplex cplex = new IloCplex();
// variables
IloIntVar[][] x = new IloIntVar[n][];
for (int i = 0; i < n; i++) {
x[i] = cplex.boolVarArray(n);
for (int j = 0; j < n; j++) {
x[i][j].setName("x." + i + "." + j );
}
}
// mtz variables
IloNumVar[] u = cplex.numVarArray(n, 0, Double.MAX_VALUE);
for (int j = 0; j < n; j++) {
u[j].setName("u." + j);
}
//objective
IloLinearNumExpr conObj = cplex.linearNumExpr();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ( i != j ){
conObj.addTerm(node[i][j], x[i][j]) ;
}
}
}
cplex.addMinimize(conObj);
// constraints
for (int i = 1; i < n; i++) {
IloLinearNumExpr equation1 = cplex.linearNumExpr();
for (int j = 0; j < n; j++) {
if (i!=j) {
equation1.addTerm(1.0, x[i][j]);
}
}
cplex.addEq(equation1, 1.0);
}
for (int j = 1; j < n; j++) {
IloLinearNumExpr equation2 = cplex.linearNumExpr();
for (int i = 0; i < n; i++) {
if (i!=j) {
equation2.addTerm(1.0, x[i][j]);
}
}
cplex.addEq(equation2, 1.0);
}
IloLinearNumExpr equation3 = cplex.linearNumExpr();
for (int i = 1; i < n; i++) {
equation3.addTerm(1.0, x[i][0]);
}
cplex.addEq(equation3, k);
IloLinearNumExpr equation4 = cplex.linearNumExpr();
for (int j = 1; j < n; j++) {
equation4.addTerm(1.0, x[0][j]);
}
cplex.addEq(equation4, k);
cplex.use(new LazyContstraintMTZ(n, c, demand, x, u, cplex));
//parameters
//cplex.setParam(IloCplex.Param.TimeLimit,50);
//cplex.setParam(IloCplex.Param.Preprocessing.Reduce, 0);
// cplex.setParam(IloCplex.Param.RootAlgorithm, IloCplex.Algorithm.Primal);
// solve model
cplex.solve();
cplex.exportModel("model.lp");
System.out.println(cplex.getBestObjValue());
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
if (cplex.getValue(x[i][j]) != 0) {
System.out.println("name: " + x[i][j].getName() + " value: " + cplex.getValue(x[i][j]));
}
}
}
}
// end
cplex.end();
} catch (IloException | NumberFormatException | IOException exc) {
exc.printStackTrace();
}
}
}
class for lazy constraint :
import ilog.concert.*;
import ilog.cplex.*;
public class LazyContstraintMTZ extends IloCplex.LazyConstraintCallback {
int n; // number of customers
int c; // capacity of vehicles
int[] demand; // demand of every customer
IloIntVar[][] x;
IloNumVar[] u;
IloCplex cplex;
IloRange[] rng;
//constructor
LazyContstraintMTZ(int n, int c, int[] demand, IloIntVar[][] x, IloNumVar[] u, IloCplex cplex){
this.n = n;
this.c = c;
this.demand = demand;
this.x = x;
this.u = u;
this.cplex = cplex;
}
protected void main() throws IloException {
// Get the current x solution
// double[][] sol = new double[n][n];
// for (int i = 0; i < n; i++) {
// for (int j = 0; j < n; j++) {
// sol[i][j] = cplex.getValue(x[i][j]);
// }
// }
for (int i = 1; i < n; i++) {
for (int j = 1; j < n; j++) {
if (i!=j && demand[i]+demand[j]<=c){
IloLinearNumExpr equation5 = cplex.linearNumExpr();
equation5.addTerm(1.0, u[i]);
equation5.addTerm(-1.0, u[j]);
equation5.addTerm(c, x[i][j]);
rng[i].setExpr(equation5);
rng[i].setBounds(Double.MIN_VALUE, c-demand[j]);
cplex.addLazyConstraint(rng[i]);
}
}
}
for (int i = 1; i < n; i++) {
IloLinearNumExpr equation6 = cplex.linearNumExpr();
equation6.addTerm(1.0, u[i]);
rng[i].setExpr(equation6);
rng[i].setBounds(demand[i], c);
cplex.addLazyConstraint(rng[i]);
}
}
}
As far as I can tell, rng is never initialized in your callback class. So it is always null and as soon as you attempt to set an element in it, you will get that NullPointerException.
Note that you don't even need that array. Instead of
rng[i].setExpr(equation5);
rng[i].setBounds(Double.MIN_VALUE, c-demand[j]);
cplex.addLazyConstraint(rng[i]);
you can just write
IloRange rng = cplex.range(Double.MIN_VALUE, equation5, c - demand[j]);
cplex.addLazyConstraint(rng);
(and similarly for equation6).
Also note that Double.MIN_VALUE is likely not what you want. This gives the smallest representable number larger than 0. I guess what you want is Double.NEGATIVE_INFINITY to specify a range without lower bound. In that case you could also just write
IloRange rng = cplex.le(equation5, c - demand[j]);
Trying to write a method that swaps the rows of a 2D array in order of increasing row sum.
For example, if I have the following 2d array:
int [][] array = {4,5,6},{3,4,5},{2,3,4};
I would want it to output an array as so:
{2 3 4}, {3 4 5}, {4 5 6}
Methodology:
a.) take the sums of each row and make a 1D array of the sums
b.) do a bubble sort on rowSum array
c.) swap the rows of the original array based on the bubble sort swaps made
d.) then print the newly row sorted array.
Here's my code so far:
public void sortedArrayByRowTot() {
int [][] tempArray2 = new int [salaryArray.length [salaryArray[0].length];
for (int i = 0; i < tempArray2.length; i++) {
for (int j = 0; j < tempArray2[i].length; j++) {
tempArray2[i][j] = salaryArray[i][j];
}
}
int [] rowSums = new int [tempArray2.length];
int sum = 0;
for (int i = 0; i < tempArray2.length; i++) {
for (int j = 0; j < tempArray2[i].length; j++) {
sum += tempArray2[i][j];
}
rowSums[i] = sum;
sum = 0;
}
int temp;
int i = -1;
for(int j = rowSums.length; j > 0; j--){
boolean isSwap = false;
for (i = 1; i < j; i++) {
if(rowSums[i-1] > rowSums[i]) {
temp = rowSums[i-1];
rowSums[i-1] = rowSums[i];
rowSums[i] = temp;
isSwap = true;
}
}
if(!isSwap){
break;
}
}
for (int k = 0; k < tempArray2.length; k++) {
temp = tempArray2[i-1][k];
tempArray2[i-1][k] = tempArray2[i][k];
tempArray2[i][k] = temp;
}
for (int b = 0; b < tempArray2.length; b++) {
for (int c = 0; c < tempArray2[b].length; c++) {
System.out.print(tempArray2[b][c] + " ");
}
}
}
}
Not sure if I am doing part c of my methodology correctly?
It keeps saying "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2"
As #shmosel said, you can do it like this:
public static void sortedArrayByRowTot() {
int [][] array = {{4,5,6},{3,4,5},{2,3,4}};
Arrays.sort(array, Comparator.comparingInt(a -> IntStream.of(a).sum()));
}
I was able to solve my question. Thanks.
public void sortedArrayByRowTot() {
//Creates tempArray2 to copy salaryArray into
int [][] tempArray2 = new int [salaryArray.length][salaryArray[0].length];
//Copies salaryArray into tempArray2
for (int i = 0; i < salaryArray.length; i++) {
for (int j = 0; j < salaryArray[i].length; j++) {
tempArray2[i][j] = salaryArray[i][j];
}
}
//Creates rowSum array to store sum of each row
int [] rowSums = new int [tempArray2.length];
for (int i = 0; i < tempArray2.length; i++) {
for (int j = 0; j < tempArray2[0].length; j++) {
rowSums[i] += tempArray2[i][j];
}
}
//Modified Bubble Sort of rowSum array (highest to lowest values)
int temp;
int i = 0;
for(int j = rowSums.length; j > 0; j--){
boolean isSwap = false;
for (i = 1; i < j; i++) {
if(rowSums[i-1] < rowSums[i]) {
temp = rowSums[i-1];
rowSums[i-1] = rowSums[i];
rowSums[i] = temp;
isSwap = true;
//swaps rows in corresponding tempArray2
int [] temp2 = tempArray2[i-1];
tempArray2[i-1] = tempArray2[i];
tempArray2[i] = temp2;
}
}
if(!isSwap){
break;
}
}
//Prints sorted array
System.out.println("Sorted array: ");
for (i = 0; i < tempArray2.length; i++) {
for (int j = 0; j < tempArray2[i].length; j++) {
System.out.print("$"+ tempArray2[i][j] + " ");
}
System.out.println();
}
}
You may try this way. That I have solved.
public class Solution{
public static void sortedArrayByRowTot() {
int [][] salaryArray = { {4,5,6},{3,4,5},{2,3,4} };
int [][] tempArray2 = new int [salaryArray.length][salaryArray[0].length];
for (int i = 0; i < salaryArray.length; i++) {
for (int j = 0; j < salaryArray[i].length; j++) {
tempArray2[i][j] = salaryArray[i][j];
}
}
// Buble Sort to store rowSums
int [] rowSums = new int [tempArray2.length];
for (int i = 0; i < tempArray2.length; i++) {
for (int j = 0; j < tempArray2[0].length; j++) {
rowSums[i] += tempArray2[i][j];
}
}
//Buble Sort by Rows Sum (Lowest Value to Highest)
int temp;
int i = 0;
for(int j = rowSums.length; j > 0; j--){
boolean isSwap = false;
for (i = 1; i < j; i++) {
if(rowSums[i-1] > rowSums[i]) {
temp = rowSums[i-1];
rowSums[i-1] = rowSums[i];
rowSums[i] = temp;
isSwap = true;
//swaps rows in corresponding tempArray2
int [] temp2 = tempArray2[i-1];
tempArray2[i-1] = tempArray2[i];
tempArray2[i] = temp2;
}
}
if(!isSwap){
break;
}
}
/** No Need.
for (int k = 0; k < tempArray2.length; k++) {
temp = tempArray2[i-1][k];
tempArray2[i-1][k] = tempArray2[i][k];
tempArray2[i][k] = temp;
}
*/
for (int b = 0; b < tempArray2.length; b++) {
for (int c = 0; c < tempArray2[b].length; c++) {
System.out.print(tempArray2[b][c] + " ");
}
}
}
public static void main(String[] args) {
sortedArrayByRowTot();
}
}
I have a class which is :
public class CCTest {
public double f;
public double[][][] x;
public double counter;
};
and i have assigned random number to x,
CCTest[] cls = new CCTest[5];
for (int i = 0; i < cls.length; i++) {
cls[i] = new CCTest();
}
for (int i = 0; i < (Size = 5); i++) {
cls[i].x = new double[this.c][this.D][this.Size];
for (int j = 0; j < this.D; j++) {
cls[i].x = getRandomX(this.c, this.D, this.Size);
}
}
then I tried to display the result using :
public static void display(double[][][] array) {
int rows = array.length;
int columns = array[0].length;
int depth = array[0][0].length;
for (int d = 0; d < depth; d++) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
System.out.print(array[r][c][d] + " ");
}
System.out.println();
}
System.out.println();
}
}
The Random Generation method is :
public static double[][][] getRandomX(int x, int y, int z) {
double[][][] result = new double[x][y][z];
Random r = new Random();
for (int i = 0; i < z; i++) {
for (int j = 0; j < y; j++) {
for (int k = 0; k < x; k++) {
result[k][j][i] = r.nextDouble();
}
}
}
return result;
}
but the output is empty [] , any idea please
The inner loop : for (int j = 0; j < this.D; j++) {...} is useless so you can remove this.The display and getRandomX() functions are fine. Try this in main , works in my environment:
CCTest[] cls = new CCTest[5];
for (int i = 0; i < cls.length; i++) {
cls[i] = new CCTest();
}
for (int i = 0; i < (Size = 5); i++) {
cls[i].x = new double[c][D][S];
cls[i].x = getRandomX(c, D, S);
}
for (int i = 0; i < (Size = 5); i++) {
display(cls[0].x);
}
Your display method should rather look like:
public static void display(double[][][] array) {
for (int x = 0; x < array.length; x++) {
for (int y = 0; y < array[x].length; y++) {
for (int z = 0; z < array[x][y].length; z++) {
System.out.println(array[x][y][z]);
}
}
}
}
There is another question which comes to my mind. What is getRandomX? You haven't shown us. I'd use the following:
public static double[][][] getRandom3DArray(double[][][] array) {
Random r = new Random();
for (int x = 0; x < array.length; x++) {
for (int y = 0; y < array[x].length; y++) {
for (int z = 0; z < array[x][y].length; z++) {
array[x][y][z] = r.nextDouble();
}
}
}
return array;
}
You're mistaking rows with depth in your display.