this is a continuation of this post. I must calculate many times some statistics(Max, mean, min, median and std dev) of arrays and I have a performance issue given the sort of my arrays in the method calcMaxMinMedian.
Given, I could not improve much further the summary statistics of an array performance. I am trying now to understand strategies and work arounds to parallelize my upper calls or any other smart thoughts.
I have seen this doc but I am not familiar
As well as this (post)[https://stackoverflow.com/questions/20375176/should-i-always-use-a-parallel-stream-when-possible/20375622].
I tried using parallel streams, however probably given my SharedResource, the actual performance using the for loop was worse.
Time (s) functionUsingForLoop173
Time (s) functionUsingParallelStream194
Do anyone have an idea of what could I try to parallelize or any other thoughts on how to improve the overrall performance?
Here is what I tried:
public class MaxMinMedianArrayUtils {
int[] sharedStaticResource={1,5,5};//Shared resource across
/**
* Return an array with summary statistics. Max, mean,std dev,median,min.
* Throw an IllegalArgumentException if array is empty.
*
* #param a array.
* #return array returning Max(0), mean(1),std dev(2),median(3),min(4) in
* respective
* positions.
*/
public static double[] getSummaryStatistics(double[] a) {
double[] summary = new double[5];
if (a.length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (a.length == 1) {
summary[0] = a[0];
summary[1] = a[0];
summary[2] = 0;
summary[3] = a[0];
summary[4] = a[0];
} else {
double[] meandStd = calcMeanSDSample(a);
summary[1] = meandStd[0];//Mean
summary[2] = meandStd[1];//Standard Deviation
double[] maxMinMedian = calcMaxMinMedian(a);
summary[0] = maxMinMedian[0];//Max
summary[4] = maxMinMedian[1];//Min
summary[3] = maxMinMedian[2];//Median
}
return summary;
}
public static double[] calcMeanSDSample(double numArray[]) {
int length = numArray.length;
double[] meanStd = new double[2];
if (length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (length == 1) {
meanStd[0] = numArray[0];
meanStd[1] = 0.0;
} else {
double sum = 0.0, standardDeviation = 0.0;
for (double num : numArray) {
sum += num;
}
meanStd[0] = sum / length;
for (double num : numArray) {
standardDeviation += Math.pow(num - meanStd[0], 2);
}
meanStd[1] =
Math.sqrt(standardDeviation / ((double) length - 1.0));//-1
// because it is
// for sample
}
return meanStd;
}
public static double[] calcMaxMinMedian(double[] a) {
double[] maxMinMedian = new double[3];
if (a.length == 0) {
throw new IllegalArgumentException(
"Array is empty, please " + "verify" + " the values.");
} else if (a.length == 1) {
for (int i = 0; i < 3; i++) {
maxMinMedian[i] = a[0];
}
} else {
Arrays.sort(a);
maxMinMedian[0] = a[a.length - 1];
maxMinMedian[1] = a[0];
maxMinMedian[2] = (a.length % 2 != 0) ? (double) (a[a.length / 2]) :
(double) ((a[(a.length - 1) / 2] + a[a.length / 2]) / 2.0);
}
return maxMinMedian;
}
public static void main(String[] args) {
int numVals = 1000;
// double[] ar = new double[numVals];
int numCalculations = 2 * 1000 * 1 * 1000;
// int numCalculations = 2 * 1000;
MaxMinMedianArrayUtils maxMinMedianArrayUtils=
new MaxMinMedianArrayUtils();
Instant start = Instant.now();
double[][] statsPerCalculation=
maxMinMedianArrayUtils.functionUsingForLoop(numVals,
numCalculations);
Instant end = Instant.now();
long totalTime = Duration.between(start, end).toSeconds();
System.out.println("Time (s) functionUsingForLoop" + totalTime);
Instant start3 = Instant.now();
double[][] statsPerCalculation3=
maxMinMedianArrayUtils.functionUsingParallelStream(numVals,
numCalculations);
Instant end3 = Instant.now();
long totalTime3 = Duration.between(start3, end3).toSeconds();
System.out.println("Time (s) functionUsingParallelStream" + totalTime3);
}
private double[][] functionUsingForLoop(int numVals,
int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] statsPerCalculation= new double[numCalculations][5];//Each
// line
// stores
// the stats of the array generated in the numCalculations loop
for (int i = 0; i < numCalculations; i++) {//Complete independent
// calculations that I want to parallelize
double[]array=functionSimulateCalculations(numVals);
double[] stats = getSummaryStatistics(array);
for(int s = 0; s < stats.length; s++) {//Copy
statsPerCalculation[i][s] = stats[s];
}
}
return statsPerCalculation;
}
private double[][] functionUsingParallelStream(int numVals,
int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] statsPerCalculation= new double[numCalculations][5];//Each
// line
// stores
// the stats of the array generated in the numCalculations loop
double[][] finalStatsPerCalculation = statsPerCalculation;
IntStream.range(0,numCalculations).parallel().forEach((i)->{
double[] array=functionSimulateCalculations(numVals);
double[] stats = getSummaryStatistics(array);
for(int s = 0; s < stats.length; s++) {
finalStatsPerCalculation[i][s] = stats[s];
}
}
);
return statsPerCalculation;
}
private double[] functionSimulateCalculations(int numVals) {
double[] ar=new double[numVals];
for (int k = 0; k < numVals; k++) {//To simulate the
// actual function of my
// use case
ar[k] = Math.random()*sharedStaticResource[0];
}
return ar;
}
} // Utility
Part of your issue is that you are computing your randomised the data samples inside the tests, but have contention with the singleton random number generation in parallel threads. Also this means that you have no means of validating that the parallel algorithm matches the serial results.
Refactor your tests so that inputs are pre-computed once - you don't care about timing this step:
private double[][] generateInputData(int numVals, int numCalculations) {
// calculations that is used to get some values, but is not modified.
double[][] inputs = new double[numCalculations][];// Each
for (int i = 0; i < numCalculations; i++) {
inputs[i] = functionSimulateCalculations(numVals);
}
return inputs;
}
Then you can run both tests on same inputs:
private double[][] functionUsingForLoop(double[][]arrays) {
// calculations that is used to get some values, but is not modified.
int numCalculations = arrays.length;
double[][] statsPerCalculation = new double[numCalculations][5];// Each
for (int i = 0; i < numCalculations; i++) {
double[] stats = getSummaryStatistics(arrays[i]);
for (int s = 0; s < stats.length; s++) {
statsPerCalculation[i][s] = stats[s];
}
}
return statsPerCalculation;
}
private double[][] functionUsingParallelStream(double[][]arrays) {
int numCalculations = arrays.length;
double[][] statsPerCalculation = new double[numCalculations][5];// Each
double[][] finalStatsPerCalculation = statsPerCalculation;
IntStream.range(0, numCalculations).parallel().forEach((i) -> {
double[] stats = getSummaryStatistics(arrays[i]);
for (int s = 0; s < stats.length; s++) {
finalStatsPerCalculation[i][s] = stats[s];
}
});
return statsPerCalculation;
}
Finally make your main() do some warmups, initialise the arrays, time each section and compare the results:
for (int numCalculations : new int[] { 1, 2, 8, 8, 2 * 1000, 2* 10000, 2*1000*1*1000 } ) {
double[][] arrays = maxMinMedianArrayUtils.generateInputData(numVals, numCalculations);
// ...
double[][] statsPerCalculation= maxMinMedianArrayUtils.functionUsingForLoop(arrays);
// ...
double[][] statsPerCalculation3= maxMinMedianArrayUtils.functionUsingParallelStream(arrays);
// ...
// COMPARE the results
if (statsPerCalculation3.length != statsPerCalculation.length)
throw new RuntimeException("Results not same!");
for (int i = statsPerCalculation3.length - 1; i >= 0; i--) {
// System.out.println("statsPerCalculation ["+i+"]="+Arrays.toString(statsPerCalculation[i]));
// System.out.println("statsPerCalculation3["+i+"]="+Arrays.toString(statsPerCalculation3[i]));
for (int v = statsPerCalculation3[i].length - 1; v >= 0; v--) {
if (Math.abs(statsPerCalculation3[i][v]-statsPerCalculation[i][v]) > 0.0000000000001)
throw new RuntimeException("Results not same at ["+i+"]["+v+"]");
}
}
}
At this point, you'll see quite different trend in the results, parallel stream version a lot quicker than non-parallel.
I am trying to calculate running time of two methods using new Date().getTime(). the two methods follow same algorithm,and one of them increase some steps,however the method with less steps take more time .
I am confusing of that. here is the two methods:
This the first method use less steps and take more time:
public void encryptFiles(List<BloomFilter> bfList1) {
Matrix matrix2 = new Matrix(400,400);
Matrix matrix3 = new Matrix(400,400);
matrix2.setMat(value1);
matrix3.setMat(value2);
a2 = matrix2.transpose();
b2 = matrix3.transpose();
startTime2 = new Date().getTime();
for (BloomFilter bfList2 : bfList1) {
Random raa = new Random();
int g1 = raa.nextInt();
double m1 = (double) ((double) Math.round(g1 * 10) / 10.0);
List<double[]> res1 = new ArrayList<>();
double[] e1 = new double[400];
double[] k1 = new double[400];
Vector<Double> j = new Vector<Double>(400);
Vector<Double> h = new Vector<Double>(400);
//System.out.println("bloom filter in bloom filter list:" + Arrays.toString(bfList2.getBitSet().data));
String bfName = bfList2.getName();
for (int i = 0; i < s.size(); i++) {
if (s.get(i) == 1) {
j.add( (double) bfList2.getBitSet().getWord(i));
h.add((double) bfList2.getBitSet().getWord(i));
} else {
j.add(0.5 * (bfList2.getBitSet().getWord(i))+m1);
h.add(0.5 * (bfList2.getBitSet().getWord(i))+m1 );
}
}
for (int u = 0; u < 400; u++) {
for (int y = 0; y < 400; y++) {
e1[u] += a2[u][y]*j.get(y);
k1[u] += b2[u][y]*h.get(y);
}
}
res1.add(e1);
res1.add(k1);
hasssh.put(bfName,res1 );
}
encryptedBFListInTime = (new Date().getTime())-startTime2;
encryptedBFListInTime /= 1000.0;
System.out.println("encrypt files only in "+encryptedBFListInTime);
}
and the following is the second method use more steps but less time:
public BloomFilterIndex encryptTree(BloomFilterIndex tree) {
startTime9 = new Date().getTime();
for(int m = 0; m < tree.root.children.size(); m++){
BloomFilterIndex.BFINode<Integer> n =(BloomFilterIndex.BFINode<Integer>)tree.root.children.get(m);
encrypt(n);
}
end = new Date().getTime() - startTime9;
//end1 = end - startTime9;
end /= 1000.0;
System.out.println("encrypt node in :"+end);
return tree;
}
calling the following method :
public void encrypt(BloomFilterIndex.BFINode<Integer> root) {
List<double[]> ress = new ArrayList<>();
if (!root.isLeaf()) {
c = new double[root.value.size()];
// c = new double[4];
for (int i = 0; i < root.value.size(); i++) {
// for(int i = 0; i < 4; i++){
c[i] = root.value.getBitSet().getWord(i);
}
ress.add(c);
root.value = null;
root.value2 = ress;
for (BloomFilterIndex.BFINode<Integer> g : root.children) {
encrypt(g);
}
} else {
//String bfName1 = root.value.getName();
double[] y = new double[400];
double[] z = new double[400];
Random r = new Random();
Integer g1 = r.nextInt();
double m5 = (double) ((double) Math.round(g1 * 10) / 10.0);
Vector<Double> m6 = new Vector<Double>(400);
Vector<Double> n1 = new Vector<Double>(400);
for (int i = 0; i < s.size(); i++) {
// for(int i = 0;i < 400; i++) {
if (s.get(i) == 1) {
m6.add((double) root.value.getBitSet().getWord(i));
n1.add((double) root.value.getBitSet().getWord(i));
} else {
m6.add(0.5 * (root.value.getBitSet().getWord(i)) + m5);
n1.add(0.5 * (root.value.getBitSet().getWord(i)) + m5);
}
}
for (int i = 0; i < 400; i++) {
for (int j = 0; j < 400; j++) {
y[i] += a2[i][j] * m6.get(j);
z[i] += b2[i][j] * n1.get(j);
}
}
ress.add(y);
ress.add(z);
root.value = null;
root.value2 = ress;
// hasssh1.put(bfName1, ress);
}
}
where is the problem please.
The run time depends on the critical sections of the code. To determine the critical sections, remember that the are contained in the most deeply nested for or while loops. Other lines of code only execute once!
In the second method you call the helper method from WITHIN the for loop! This means that you are executing ALL the for loops and nested for loops in the helper method tree.root.children.size() times, because the helper method is being called that many times!
When thinking of nested loops, multiply! e.g.,
for (int i= 0; i < 5; i++) {
for (int j= 0; j < 5; j++) {
DOTHING();
}
}
DOTHING will execute 25 times! Why?
The outer loop executes 5 times!
The nested loop executes 5 times!
5 x 5 = 25 times!
You calling that helper method and all of its nested for loops from within a for loop is like having another nested loop added on. This is the difference between n * n execution and n * n * n or n^2 vs n^3! I hope this helps!
I need to find the mean, median, mode, and range from an input file.
[input file has the numbers{60,75,53,49,92,71}]
I don't know how to print the calculations from the range out or calculate the mode.
It's pretty bad, I'm very new to Java.
It would be great if anyone could help me with it.
import java.io.*;
import java.util.*;
public class grades {
public static double avg(double[] num) {
double total = 0;
int j = 0;
for (; j < num.length; j++) {
total += num[j];
}
return (total / j);
}
public double getRange(double[] numberList) {
double initMin = numberList[0];
double initMax = numberList[0];
for (int i = 1; i <= numberList.length; i++) {
if (numberList[i] < initMin) initMin = numberList[i];
if (numberList[i] > initMax) initMax = numberList[i];
double range = initMax - initMin;
}
return range;
}
public static void main(String[] args) throws IOException {
double[] num = new double[12];
File inFile = new File("data.txt");
Scanner in = new Scanner(inFile);
for (int i = 0; i < num.length && in.hasNext(); i++) {
num[i] = in.nextDouble();
// System.out.println(num[i]);
}
double avg = grades.avg(num);
System.out.println("Arithmetic Mean = " + avg);
System.out.printf("Median = %.2f%n", grades.getMedian(num));
System.out.println("Range = " + range);
}
public static double getMedian(double[] num) {
int pos = (int) num.length / 2;
return num[pos];
}
}
I don't know how to print the calculations from the range out or calculate the mode.
You have already written a function to calculate the Range. Here is how you can print the Range.
System.out.println("Range = " + getRange(num));
Here is a quick code snippet to calculate the Mode:
public static double calculateMode(final double[] numberList) {
double[] cnts = new double[numberList.length];
double mode = 0, max = 0;
for (int i = 0; i < numberList.length; i++) {
/* Update Count Counter */
cnts[numberList[i]]++;
/* Check */
if (max < cnts[numberList[i]]) {
/* Update Max */
max = cnts[numberList[i]];
/* Update Mode */
mode = numberList[i];
}
}
/* Return Result */
return mode;
}
try sorting the element into an array.it will give following results:
[49,53,60,71,75,92]
suppose you stored it in array A.
int arrLength=A.length();
for(i=0,sum=0;i<arrlength;i++)
sum=sum+A[i]
mean=sum/arrLength;
median=A[arrLength/2]
I think you didn't sort the elements before finding median.
Do same thing to calculate range.It will be easier , I feel
I have a big problem. I try to create a neural network and want to train it with a backpropagation algorithm. I found this tutorial here http://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/ and tried to recreate it in Java. And when I use the training data he uses, I get the same results as him.
Without backpropagation my TotalError is nearly the same as his. And when I use the back backpropagation 10 000 time like him, than I get the nearly the same error. But he uses 2 Input Neurons, 2 Hidden Neurons and 2 Outputs but I'd like to use this neural network for OCR, so I need definitely more Neurons. But if I use for example 49 Input Neurons, 49 Hidden Neurons and 2 Output Neurons, It takes very long to change the weights to get a small error. (I believe it takes forever.....). I have a learningRate of 0.5. In the constructor of my network, I generate the neurons and give them the same training data like the one in the tutorial and for testing it with more neurons, I gave them random weights, inputs and targets. So can't I use this for many Neurons, does it takes just very long or is something wrong with my code ? Shall I increase the learning rate, the bias or the start weight?
Hopefully you can help me.
package de.Marcel.NeuralNetwork;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Random;
public class Network {
private ArrayList<Neuron> inputUnit, hiddenUnit, outputUnit;
private double[] inHiWeigth, hiOutWeigth;
private double hiddenBias, outputBias;
private double learningRate;
public Network(double learningRate) {
this.inputUnit = new ArrayList<Neuron>();
this.hiddenUnit = new ArrayList<Neuron>();
this.outputUnit = new ArrayList<Neuron>();
this.learningRate = learningRate;
generateNeurons(2,2,2);
calculateTotalNetInputForHiddenUnit();
calculateTotalNetInputForOutputUnit();
}
public double calcuteLateTotalError () {
double e = 0;
for(Neuron n : outputUnit) {
e += 0.5 * Math.pow(Math.max(n.getTarget(), n.getOutput()) - Math.min(n.getTarget(), n.getOutput()), 2.0);
}
return e;
}
private void generateNeurons(int input, int hidden, int output) {
// generate inputNeurons
for (int i = 0; i < input; i++) {
Neuron neuron = new Neuron();
// for testing give each neuron an input
if(i == 0) {
neuron.setInput(0.05d);
} else if(i == 1) {
neuron.setOutput(0.10d);
}
inputUnit.add(neuron);
}
// generate hiddenNeurons
for (int i = 0; i < hidden; i++) {
Neuron neuron = new Neuron();
hiddenUnit.add(neuron);
}
// generate outputNeurons
for (int i = 0; i < output; i++) {
Neuron neuron = new Neuron();
if(i == 0) {
neuron.setTarget(0.01d);
} else if(i == 1) {
neuron.setTarget(0.99d);
}
outputUnit.add(neuron);
}
// generate Bias
hiddenBias = 0.35;
outputBias = 0.6;
// generate connections
double startWeigth = 0.15;
// generate inHiWeigths
inHiWeigth = new double[inputUnit.size() * hiddenUnit.size()];
for (int i = 0; i < inputUnit.size() * hiddenUnit.size(); i += hiddenUnit.size()) {
for (int x = 0; x < hiddenUnit.size(); x++) {
int z = i + x;
inHiWeigth[z] = round(startWeigth, 2, BigDecimal.ROUND_HALF_UP);
startWeigth += 0.05;
}
}
// generate hiOutWeigths
hiOutWeigth = new double[hiddenUnit.size() * outputUnit.size()];
startWeigth += 0.05;
for (int i = 0; i < hiddenUnit.size() * outputUnit.size(); i += outputUnit.size()) {
for (int x = 0; x < outputUnit.size(); x++) {
int z = i + x;
hiOutWeigth[z] = round(startWeigth, 2, BigDecimal.ROUND_HALF_UP);
startWeigth += 0.05;
}
}
}
private double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
private void calculateTotalNetInputForHiddenUnit() {
// calculate totalnetinput for each hidden neuron
for (int s = 0; s < hiddenUnit.size(); s++) {
double net = 0;
int x = (inHiWeigth.length / inputUnit.size());
// calculate toAdd
for (int i = 0; i < x; i++) {
int v = i + s * x;
double weigth = inHiWeigth[v];
double toAdd = weigth * inputUnit.get(i).getInput();
net += toAdd;
}
// add bias
net += hiddenBias * 1;
net = net *-1;
double output = (1.0 / (1.0 + (double)Math.exp(net)));
hiddenUnit.get(s).setOutput(output);
}
}
private void calculateTotalNetInputForOutputUnit() {
// calculate totalnetinput for each hidden neuron
for (int s = 0; s < outputUnit.size(); s++) {
double net = 0;
int x = (hiOutWeigth.length / hiddenUnit.size());
// calculate toAdd
for (int i = 0; i < x; i++) {
int v = i + s * x;
double weigth = hiOutWeigth[v];
double outputOfH = hiddenUnit.get(s).getOutput();
double toAdd = weigth * outputOfH;
net += toAdd;
}
// add bias
net += outputBias * 1;
net = net *-1;
double output = (double) (1.0 / (1.0 + Math.exp(net)));
outputUnit.get(s).setOutput(output);
}
}
private void backPropagate() {
// calculate ouputNeuron weigthChanges
double[] oldWeigthsHiOut = hiOutWeigth;
double[] newWeights = new double[hiOutWeigth.length];
for (int i = 0; i < hiddenUnit.size(); i += 1) {
double together = 0;
double[] newOuts = new double[hiddenUnit.size()];
for (int x = 0; x < outputUnit.size(); x++) {
int z = x * hiddenUnit.size() + i;
double weigth = oldWeigthsHiOut[z];
double target = outputUnit.get(x).getTarget();
double output = outputUnit.get(x).getOutput();
double totalErrorChangeRespectOutput = -(target - output);
double partialDerivativeLogisticFunction = output * (1 - output);
double totalNetInputChangeWithRespect = hiddenUnit.get(x).getOutput();
double puttedAllTogether = totalErrorChangeRespectOutput * partialDerivativeLogisticFunction
* totalNetInputChangeWithRespect;
double weigthChange = weigth - learningRate * puttedAllTogether;
// set new weigth
newWeights[z] = weigthChange;
together += (totalErrorChangeRespectOutput * partialDerivativeLogisticFunction * weigth);
double out = hiddenUnit.get(x).getOutput();
newOuts[x] = out * (1.0 - out);
}
for (int t = 0; t < newOuts.length; t++) {
inHiWeigth[t + i] = (double) (inHiWeigth[t + i] - learningRate * (newOuts[t] * together * inputUnit.get(t).getInput()));
}
hiOutWeigth = newWeights;
}
}
}
And my Neuron Class:
package de.Marcel.NeuralNetwork;
public class Neuron {
private double input, output;
private double target;
public Neuron () {
}
public void setTarget(double target) {
this.target = target;
}
public void setInput (double input) {
this.input = input;
}
public void setOutput(double output) {
this.output = output;
}
public double getInput() {
return input;
}
public double getOutput() {
return output;
}
public double getTarget() {
return target;
}
}
Think about it: you have 10,000 propagations through 49->49->2 neurons. Between the input layer and the hidden layer, you have 49 * 49 links to propagate through, so parts of your code are being executed about 24 million times (10,000 * 49 * 49). That is going to take time. You could try 100 propogations, and see how long it takes, just to give you an idea.
There are a few things that can be done to increase performance, like using a plain array instead of an ArrayList, but this is a better topic for the Code Review site. Also, don't expect this to give drastic improvements.
Your back propagation code has complexity of O(h*o + h^2) * 10000, where h is the number of hidden neurons and o is the number of output neurons. Here's why.
You have a loop that executes for all of your hidden neurons...
for (int i = 0; i < hiddenUnit.size(); i += 1) {
... containing another loop that executes for all the output neurons...
for (int x = 0; x < outputUnit.size(); x++) {
... and an additional inner loop that executes again for all the hidden neurons...
double[] newOuts = new double[hiddenUnit.size()];
for (int t = 0; t < newOuts.length; t++) {
... and you execute all of that ten thousand times. Add on top of this O(i + h + o) [initial object creation] + O(i*h + o*h) [initial weights] + O(h*i) [calculate net inputs] + O(h*o) [calculate net outputs].
No wonder it's taking forever; your code is littered with nested loops. If you want it to go faster, factor these out - for example, combine object creation and initialization - or reduce the number of neurons. But significantly cutting the number of back propagation calls is the best way to make this run faster.
I have a Matlab code of bat algorithm and I write java version of this algorithm
Bat algorithm is a simple optimization algorithm for finding the minimum of any function
here is the matlab code and my java version of this code
My java version of this algorithm can't find the optimum result like matlab version
and I can't find where is my mistake in converting the code from matlab to java
Can anyone help me where is my mistake?
import java.util.Random;
public class Bat
{
private int n;
private float A, r;
private float Qmin, Qmax;
private int d;
private int NofGen;
private float fmin;
private int fminIndex;
private float Fnew;
private int loopCounter;
private float Q[], V[][], Sol[][], UL_bound[][], fitness[], S[][], Best[];
private Random myRand;
public Bat(
int NBats,
float loudness,
float pulseRate,
float minFreq,
float maxFreq,
int NofGeneration,
int dimension
)
{
n = NBats;
A = loudness;
r = pulseRate;
Qmin = minFreq;
Qmax = maxFreq;
NofGen = NofGeneration;
d = dimension;
S = new float[n][d];
Best = new float[d];
UL_bound = new float[2][d];
//default bounds
for(int i = 0 ; i < d ; i++)
{
UL_bound[0][i] = -10000;
UL_bound[1][i] = 10000;
}
loopCounter = 0;
myRand = new Random();
Q = new float[n];
for(int i = 0 ; i < n ; i++)
Q[i] = 0;
V = new float[n][d];
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < d ; j++)
V[i][j] = 0;
}
public void intial()
{
Sol = new float[n][d];
for(int i = 0 ; i < n ; i++)
for(int j = 0 ; j < d ; j++)
{
float t = myRand.nextFloat();
//(upper -lower)*rand + lower
Sol[i][j] = t * (UL_bound[1][j] - UL_bound[0][j]) + UL_bound[0][j];
}
fitness = new float[n];
for(int i = 0 ; i < n ; i++)
fitness[i] = function(Sol[i]);
//finding fmin
fmin = fitness[0];
fminIndex = 0;
for(int i = 0 ; i < n ; i++)
{
if (fitness[i] < fmin)
{
fmin = fitness[i];
fminIndex = i;
}
}
//setting best
for(int j = 0 ; j < d ; j++)
Best[j] = Sol[fminIndex][j];
}
public void start()
{
while(loopCounter < NofGen)
{
for(int i = 0 ; i < n ; i++)
{
Q[i] = Qmin + (Qmin - Qmax)* myRand.nextFloat();
for(int j = 0 ; j < d ; j++)
V[i][j] = V[i][j] + (Sol[i][j]-Best[j])*Q[i];
for(int j = 0 ; j < d ; j++)
S[i][j] = Sol[i][j] + V[i][j];
Sol[i] = simpleBounds(Sol[i]);
if(myRand.nextFloat() > r)
for(int j = 0 ; j < d ; j++)
S[i][j] = (float) (Best[j] + (.001 * myRand.nextFloat()) );
Fnew = function(S[i]);
if(Fnew <= fitness[i] && myRand.nextFloat() < A)
{
for(int j = 0 ; j < d ; j++)
Sol[i][j] = S[i][j];
fitness[i] = Fnew;
}
if(Fnew <= fmin)
{
fmin = Fnew;
for(int j = 0 ; j < d ; j++)
Best[j] = S[i][j];
}
}
loopCounter++;
}
}
public float[] simpleBounds(float p[])
{
for(int i = 0 ; i < d ; i++)
{
if(p[i] < UL_bound[0][i])
p[i] = UL_bound[0][i];
if(p[i] > UL_bound[1][i])
p[i] = UL_bound[1][i];
}
return p;
}
float function(float p[])
{
// Sphere function with fmin=0 at (0,0,...,0)
float sum = 0;
for(int i = 0 ; i < p.length ; i++)
sum = sum + p[i]*p[i];
return sum;
}
public float printResult()
{
System.out.println("After " + loopCounter + "Repeats :");
for(int i = 0 ; i < d ; i++)
System.out.print(Best[i] + ", ");
System.out.println ( "F(x) = " + fmin);
return fmin;
}
public void set_UL_Bound(int n, float L, float U)
{
if( n < d && n >= 0)
{
UL_bound[0][n] = L;
UL_bound[1][n] = U;
}
}
}
and this is the matlab versian
function [best,fmin,N_iter]=bat_algorithm(para)
% Display help
help bat_algorithm.m
% Default parameters
if nargin<1, para=[20 1000 0.5 0.5]; end
n=para(1); % Population size, typically 10 to 40
N_gen=para(2); % Number of generations
A=para(3); % Loudness (constant or decreasing)
r=para(4); % Pulse rate (constant or decreasing)
% This frequency range determines the scalings
% You should change these values if necessary
Qmin=0; % Frequency minimum
Qmax=2; % Frequency maximum
% Iteration parameters
N_iter=0; % Total number of function evaluations
% Dimension of the search variables
d=5; % Number of dimensions
% Lower limit/bounds/ a vector
Lb=-3*ones(1,d);
% Upper limit/bounds/ a vector
Ub=6*ones(1,d);
% Initializing arrays
Q=zeros(n,1); % Frequency
v=zeros(n,d); % Velocities
% Initialize the population/solutions
for i=1:n,
Sol(i,:)=Lb+(Ub-Lb).*rand(1,d);
Fitness(i)=Fun(Sol(i,:));
end
% Find the initial best solution
[fmin,I]=min(Fitness);
best=Sol(I,:);
for t=1:N_gen,
% Loop over all bats/solutions
for i=1:n,
Q(i)=Qmin+(Qmin-Qmax)*rand;
v(i,:)=v(i,:)+(Sol(i,:)-best)*Q(i);
S(i,:)=Sol(i,:)+v(i,:);
% Apply simple bounds/limits
Sol(i,:)=simplebounds(Sol(i,:),Lb,Ub);
% Pulse rate
if rand>r
% The factor 0.001 limits the step sizes of random walks
S(i,:)=best+0.001*randn(1,d);
end
% Evaluate new solutions
Fnew=Fun(S(i,:));
% Update if the solution improves, or not too loud
if (Fnew<=Fitness(i)) & (rand<A) ,
Sol(i,:)=S(i,:);
Fitness(i)=Fnew;
end
% Update the current best solution
if Fnew<=fmin,
best=S(i,:);
fmin=Fnew;
end
end
N_iter=N_iter+n;
end
% Output/display
disp(['Number of evaluations: ',num2str(N_iter)]);
disp(['Best =',num2str(best),' fmin=',num2str(fmin)]);
% Application of simple limits/bounds
function s=simplebounds(s,Lb,Ub)
% Apply the lower bound vector
ns_tmp=s;
I=ns_tmp<Lb;
ns_tmp(I)=Lb(I);
% Apply the upper bound vector
J=ns_tmp>Ub;
ns_tmp(J)=Ub(J);
% Update this new move
s=ns_tmp;
function z=Fun(u)
% Sphere function with fmin=0 at (0,0,...,0)
z=sum(u.^2);
%%%%% ============ end ====================================
The diff between two codes
In Matlab code:
S(i,:)=best+0.001*randn(1,d);
randn=>standard normal distribution.
While in Java code:
S[i][j] = (float) (Best[j] + (.001 * myRand.nextFloat()) );
java.util.Random.nextFloat()=>uniformly distributed float value between 0.0 and 1.0.
I was looking for the solution in C# and stumbled up on this. It was enough to get the job done. Here is the solution in C# translated from the java with variables renamed and an additional fitness function for finding the solution of two x,y equations xy=6 and x+y = 5. Also included is finding the square root of .3 :
using System;
namespace BatAlgorithmC
namespace BatAlgorithmC
{
class Program
{
static void Main(string[] args)
{
// Mybat x = new Mybat(100, 1000, 0.5, 0.5, 5, Mybat.sphere);
// Mybat x = new Mybat(1000, 1000, 0.5, 0.5, 1, Mybat.squareRoot);
Mybat x = new Mybat(1000, 1000, 0.5, 0.5, 2, Mybat.RootOfXYEquations);
Console.WriteLine("Hit any key to continue.");
Console.ReadLine();
}
}
public class Mybat
{
/**
* #param args the command line arguments
*/
public int _numberOfBats, _generations, Qmin, Qmax, N_iter, _dimension;
public double _volume, _pulseRate, min, max, fnew, fmin;
public double[][] _lowerBound, _upperBound, _velocity, _solution, S;
public double[] _fitness, _tempSolution, _bestSolution, Q;
public Random random;
//public static void main(String[] args) {
// Mybat x = new Mybat(20,1000,0.5,0.5,5, Mybat.sphere);
//}
public static void initJagged(double[][] array, int n, int d)
{
for (int i = 0; i < n; i++) array[i] = new double[d];
}
public Mybat(
int bats,
int generations,
double loud,
double pulse,
int dimension,
Func<double[], int, double> function
)
{
//initialization of variables
_numberOfBats = bats;
_generations = generations;
_volume = loud;
_pulseRate = pulse;
_dimension = dimension;
Random random = new Random();
//plan to change later and added as parameter
min = -15;
max = 15;
fmin = 0;
//decleration for the bounds
_lowerBound = new double[1][];
_upperBound = new double[1][];
Q = new double[_numberOfBats]; // frequency
_velocity = new double[_numberOfBats][]; //velocity
initJagged(_velocity, _numberOfBats, _dimension);
initJagged(_lowerBound, 1, _dimension);
initJagged(_upperBound, 1, _dimension);
//initialize solution array
_solution = new double[_numberOfBats][];
S = new double[_numberOfBats][];
_fitness = new double[_numberOfBats]; // fitness container
_bestSolution = new double[_dimension];
_tempSolution = new double[_dimension]; //temporary holder for a row in array _solution
initJagged(_solution, _numberOfBats, _dimension);
initJagged(S, _numberOfBats, _dimension);
for (int i = 0; i < _numberOfBats; i++)
{
// for minimal coding : added initialize Q[]array with '0' as element
Q[i] = 0;
for (int x = 0; x < _dimension; x++)
{
// for minimal coding : added initialize _velocity[][] array with '0' as element
_velocity[i][x] = 0;
//find random double values from LB to UB
_solution[i][x] = (random.NextDouble()*(max - min)) + min;
_tempSolution[x] = _solution[i][x];
//Console.WriteLine("sol["+i+"]["+x+"] = "+_solution[i][x]); //test line
//Console.WriteLine(rand.nextDouble()); //test line
}
_fitness[i] = function(_tempSolution, _dimension);
//initialize best and the fmin
if (i == 0 || fmin > _fitness[i])
{
fmin = _fitness[i];
for (int x = 0; x < _dimension; x++)
{
_bestSolution[x] = _solution[i][x];
}
}
Console.WriteLine("fitness[" + i + "]" + _fitness[i]); //test
}
Console.WriteLine("fmin = " + fmin); //test
// special note to these variables (below)
// change if required for maximum effectivity
Qmin = 0;
Qmax = 2;
N_iter = 1; //number of function evaluation
// bat proper
for (int loop = 0; loop < N_iter; loop++)
{
// loop over all bats/solutions
for (int nextBat = 0; nextBat < _numberOfBats; nextBat++)
{
Q[nextBat] = Qmin + ((Qmin - Qmax)*random.NextDouble());
// loop for velocity
for (int vel = 0; vel < _dimension; vel++)
{
_velocity[nextBat][vel] = _velocity[nextBat][vel] +
((_solution[nextBat][vel] - _bestSolution[vel])*Q[nextBat]);
}
//new solutions
for (int nextDimension = 0; nextDimension < _dimension; nextDimension++)
{
S[nextBat][nextDimension] = _solution[nextBat][nextDimension] +
_velocity[nextBat][nextDimension];
}
/**
* RESERVED SPOT for the QUESTIONABLE AREA ON THE
* MATLAB CODE (i think it is not needed for the java equivalent)
*/
// pulse rate
if (random.NextDouble() > _pulseRate)
{
for (int nextDimension = 0; nextDimension < _dimension; nextDimension++)
{
S[nextBat][nextDimension] = _bestSolution[nextDimension] + (0.001*random.NextGaussian());
}
}
//putting current row of _solution to a temp array
for (int nextDimension = 0; nextDimension < _dimension; nextDimension++)
{
_tempSolution[nextDimension] = S[nextBat][nextDimension];
}
fnew = function(_tempSolution, _dimension);
// update if solution is improved, and not too loud
if ((fnew <= _fitness[nextBat]) && (random.NextDouble() < _volume))
{
for (int x = 0; x < _dimension; x++)
{
_solution[nextBat][x] = S[nextBat][x];
_fitness[nextBat] = fnew;
}
}
//update current best solution
if (fnew <= fmin)
{
for (int nextDimension = 0; nextDimension < _dimension; nextDimension++)
{
_bestSolution[nextDimension] = S[nextBat][nextDimension];
fmin = fnew;
}
}
}
}
Console.WriteLine(" ");
Console.WriteLine("new fitness");
for (int i = 0; i < _numberOfBats; i++)
{
Console.WriteLine("fitness[" + i + "]" + _fitness[i]);
}
for (int nextDimension = 0; nextDimension < _dimension; nextDimension++)
{
Console.WriteLine("best[" + nextDimension + "]" + _bestSolution[nextDimension]);
}
Console.WriteLine("Fmin = " + fmin);
}
//possible that this function is not needed in java
public void set_bounds(int x, double L, double U)
{
//double temp_Lb[x];
//double temp_Ub[x];
for (int i = 0; i < x; i++)
{
_lowerBound[0][i] = L;
_upperBound[0][i] = U;
}
}
public static double sphere(double[] value, int d)
{
// sphere function where fmin is at 0
double result = 0;
for (int i = 0; i < d; i++)
{
result += (value[i]*value[i]);
}
return result;
}
public static double squareRoot(double[] value, int d)
{
// find the square root of .3
double result = 0;
for (int i = 0; i < d; i++)
{
result += Math.Abs(.3 - (value[i]*value[i]));
}
return result;
}
public static double RootOfXYEquations(double[] value, int d)
{
// solve for x and y xy = 6 and x+y = 5
double result = 0;
result += Math.Abs(5 - (value[0] + value[1]));
result += Math.Abs(6 - (value[0] * value[1]));
return result;
}
}
static class MathExtensiionns
{
public static double NextGaussian(this Random rand)
{
double u1 = rand.NextDouble(); //these are uniform(0,1) random doubles
double u2 = rand.NextDouble();
double mean = 0, stdDev = 1;
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + stdDev * randStdNormal; //random normal(mean,stdDev^2)
return randNormal;
}
}
}
this will be my first time here at stack overflow so i will say sorry beforehand if my response will be a bit ambiguous and has many problems. i just hope that this answer of mine will help future visitors on this thread who wants to study bat algo via java.
anyway, i did look at your code since i am studying bat algorithm at the moment.
tried running it and it does gives far off results compared to the matlab version.
what i noticed is that you just "literally" tried to convert the matlab code without fully understanding each matlab lines. i wanted to point out all of the stuff you missed but i am feeling lazy right now so i will just leave my version of bat algorithm in java.
NOTE: i just made a running bat algorithm in java. not an efficient, fully debugged, matlab's java-equivalent bat algorithm.
import java.util.Random;
public class Mybat {
/**
* #param args the command line arguments
*/
public int n, N_gen, Qmin, Qmax, N_iter, d;
public double A,r,min,max,fnew,fmin;
public double Lb[][],Ub[][],Q[],v[][],Sol[][],S[][],fitness[],temp[],best[];
public Random random;
public static void main(String[] args) {
Mybat x = new Mybat(20,1000,0.5,0.5,5);
}
public Mybat(
int bats,
int generations,
double loud,
double pulse,
int dimension
){
//initialization of variables
n=bats;
N_gen = generations;
A = loud;
r = pulse;
d = dimension;
Random rand = new Random();
//plan to change later and added as parameter
min = -15;
max = 15;
fmin = 0;
//decleration for the bounds
Lb = new double[1][d];
Ub = new double[1][d];
Q = new double[n]; // frequency
v = new double[n][d]; //velocity
//initialize solution array
Sol = new double[n][d];
S = new double[n][d];
fitness = new double[n]; // fitness container
best =new double[d];
temp = new double[d]; //temporary holder for a row in array Sol
for(int i=0;i<n;i++){
// for minimal coding : added initialize Q[]array with '0' as element
Q[i] = 0;
for(int x=0;x<d;x++){
// for minimal coding : added initialize v[][] array with '0' as element
v[i][x] = 0;
//find random double values from LB to UB
Sol[i][x]= (rand.nextDouble()*(max - min)) + min;
temp[x] = Sol[i][x];
//System.out.println("sol["+i+"]["+x+"] = "+Sol[i][x]); //test line
//System.out.println(rand.nextDouble()); //test line
}
fitness[i] = function(temp);
//initialize best and the fmin
if(i==0 || fmin > fitness[i]){
fmin = fitness[i];
for(int x=0;x<d;x++){
best[x] = Sol[i][x];
}
}
System.out.println("fitness["+i+"]"+fitness[i]); //test
}
System.out.println("fmin = "+fmin); //test
// special note to these variables (below)
// change if required for maximum effectivity
Qmin = 0;
Qmax = 2;
N_iter = 1; //number of function evaluation
// bat proper
for(int loop=0;loop<N_iter;loop++){
// loop over all bats/solutions
for(int i=0;i<n;i++){
Q[i] = Qmin+((Qmin-Qmax)*rand.nextDouble());
// loop for velocity
for(int vel=0;vel<d;vel++){
v[i][vel] = v[i][vel]+((Sol[i][vel]-best[vel])*Q[i]);
}
//new solutions
for(int x=0;x<d;x++){
S[i][x] = Sol[i][x] + v[i][x];
}
/**
* RESERVED SPOT for the QUESTIONABLE AREA ON THE
* MATLAB CODE (i think it is not needed for the java equivalent)
*/
// pulse rate
if(rand.nextDouble()>r){
for(int x=0;x<d;x++){
S[i][x] = best[x]+(0.001*rand.nextGaussian());
}
}
//putting current row of Sol to a temp array
for(int x=0;x<d;x++){
temp[x] = S[i][x];
}
fnew = function(temp);
// update if solution is improved, and not too loud
if((fnew<=fitness[i]) && (rand.nextDouble()<A)){
for(int x=0;x<d;x++){
Sol[i][x] = S[i][x];
fitness[i] = fnew;
}
}
//update current best solution
if(fnew<=fmin){
for(int x=0;x<d;x++){
best[x] = S[i][x];
fmin = fnew;
}
}
}
}
System.out.println(" ");
System.out.println("new fitness");
for(int i=0;i<n;i++){
System.out.println("fitness["+i+"]"+fitness[i]);
}
System.out.println("Fmin = "+fmin);
}
//possible that this function is not needed in java
public void set_bounds(int x, double L, double U){
//double temp_Lb[x];
//double temp_Ub[x];
for(int i=0; i<x; i++){
Lb[0][i] = L;
Ub[0][i] = U;
}
}
public double function(double value[]){
// sphere function where fmin is at 0
double result = 0;
for(int i=0;i<d;i++){
result += (value[i]*value[i]);
}
return result;
}
}