So the basic overall function of the code is to take in the the array and sort in ascending order. I get no errors within my code but I believe something is wrong. I have made some test cases and some have failed and I have a feeling in the recursivesort method I am doing something wrong. I have done multiple debugging walk through and just cant find where is the problem?
public class RecursiveSorter {
private int[] sortedArray;
private int[] array;
public RecursiveSorter() {
array = new int[1];
}
public RecursiveSorter(int[] a) {
array = a;
}
public void setArray(int[] a) {
array = a;
}
public int[] getSortedArray() {
return sortedArray;
}
public int[] getOriginalArray() {
return array;
}
public int[] sort() {
sortedArray = array;
recursiveSort(sortedArray.length - 1);
return sortedArray;
}
public int[] recursiveSort(int endIndex) {
if (endIndex >= 0) {
int m = getMaxIndex(endIndex, sortedArray);
swap(m, endIndex, sortedArray);
recursiveSort(endIndex-1);
}
return sortedArray;
}
public int getMaxIndex(int endIndex, int[] a) {
int max = a[0];
int maxIndex = 0;
for (int i = 1; i < endIndex; i++) {
if (a[i] > max) {
max = a[i];
maxIndex = i;
}
}
return maxIndex;
}
public void swap(int src, int dest, int[] a) {
int temp = a[dest];
a[dest] = src;
a[src] = temp;
}
public String toString() {
return "Original: " + prettyPrint(getOriginalArray()) + "\n" +
"Sorted: " + prettyPrint(getSortedArray());
}
private String prettyPrint(int[] a) {
String s = "";
for (int i : a)
s += i + " ";
return s;
}
public static void main(String[] args) {
// Automate running, but not testing
int[] array = {5, 67, 12, 20};
RecursiveSorter s = new RecursiveSorter(array);
s.sort();
System.out.println(s); // uses Sorter.toString
}
}
Swap method has error:
a[dest] = src;
Should be:
a[dest] = a[src];
Also this line will not copy array, so you have the array and sortedArray referencing same array object.
sortedArray = array;
Replace it with:
sortedArray = Arrays.copyOf(array, array.length);
Also in method getMaxIndex is missing equals sign:
for (int i = 1; i < endIndex; i++) {
Should be:
for (int i = 1; i <= endIndex; i++) {
1-you have to clone (or to copy) the array to the sortedArray.
2-The swap method was not correct.
3-The first call of the method recursiveSort should be parametrized by the last index of the array so sortedArray.length - 1.
public class RecursiveSorter {
private int[] sortedArray;
private int[] array;
public RecursiveSorter() {
array = new int[1];
}
public RecursiveSorter(int[] a) {
array = a;
}
public void setArray(int[] a) {
array = a;
}
public int[] getSortedArray() {
return sortedArray;
}
public int[] getOriginalArray() {
return array;
}
public void sort() {
sortedArray = array.clone();
System.out.println(this);
recursiveSort(sortedArray.length - 1); //Should subtract by length
}
public void recursiveSort(int endIndex) {
System.out.println("Sorting with param : "+endIndex);
if (endIndex >= 0) {
int m = getMaxIndex(endIndex, sortedArray);
swap(m, endIndex);
System.out.println(this);
recursiveSort(endIndex - 1);
}
}
public int getMaxIndex(int endIndex, int[] a) {
int max = a[0];
int maxIndex = 0;
for (int i = 1; i <= endIndex; i++) {
if (a[i] > max) {
max = a[i];
maxIndex = i;
System.out.println("Max index : " + i);
}
}
return maxIndex;
}
public void swap(int src, int dest) {
System.out.println("Swap : "+src+" to "+dest);
int temp = sortedArray[dest];
sortedArray[dest] = sortedArray[src];
sortedArray[src] = temp;
}
public String toString() {
return "Original: " + prettyPrint(getOriginalArray()) + "\n"
+ "Sorted: " + prettyPrint(getSortedArray());
}
private String prettyPrint(int[] a) {
String s = "";
for (int i : a) {
s += i + " ";
}
return s;
}
public static void main(String[] args) {
// Automate running, but not testing
int[] array = {5, 67, 12, 20};
RecursiveSorter s = new RecursiveSorter(array);
s.sort();
//System.out.println(s); // uses Sorter.toString
}
}
Related
hi so im currently trying to get past this error in my code, if anyone could explain where I went wrong, would be greatly appreciated.
public class Lab07vst100SD
{
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
}
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>();
size = s;
}
public void addData()
{
String [] name = {"Tom","Ann","Bob","Jan","Joe","Sue","Jay","Meg","Art","Deb"};
int[] age = {21,34,18,45,27,19,30,38,40,35};
double[] gpa = {1.685,3.875,2.5,4.0,2.975,3.225,3.65,2.0,3.999,2.125};
for(int i = 0; i < name.length; i++)
{
students.add(new Student(name[i], age[i], gpa[i]));
}
size = students.size();
}
public void selectionSort ()
{
for(int h = 0; h < students.size(); h++)
{
int index = h;
Student least = students.get(h);
for (int t = 0; t < size; t++) {
if (students.get(t).equals(least)) {
least = students.get(t);
index = t;
}
Student temp = students.get(h);
students.set(h, least);
students.set(t, temp);
}
}
}
public int linearSearch (String str)
{
// new arraylist
ArrayList<String> names = new ArrayList<String>();
for (int q = 0; q < size; q++) {
names.add(students.get(q).getName());
}
//comparison
for (int y = 0; y < size; y++) {
if (names.get(y).equals(str))
return y;
}
return -1;
};
public int binarySearch (String str) {
// new arraylist and variables
ArrayList<String> names = new ArrayList<String>();
Boolean found = false;
int lo = 0;
int hi = size;
int mid = (lo + hi) / 2;
//for loop for to transverse the array.
for (int m = 0; m < size; m++) {
names.add(students.get(m).getName());
}
while (lo <= hi && !found) {
if (names.get(mid).compareTo(str) == 0)
{
found = true;
return mid;
}
if (names.get(mid).compareTo(str) < 0) {
lo = mid + 1;
mid = (lo + hi) / 2;
}
else {
hi = mid -1;
mid = (lo + hi) / 2;
}
}
if (found)
return mid;
else
return -1;
}
public String toString() {
String temp = "";
for (int s = 0; s < students.size(); s++) {
temp += students.get(s);
}
return temp;
}
}
also, I should mention this uses the student class.
here
public class Student
{
private String name;
private int age;
private double gpa;
public Student (String n, int a, double g)
{
name = n;
age = a;
gpa = g;
}
public String getName() {
return name; }
public int getAge() {
return age; }
public double getGPA() {
return gpa; }
public String toString()
{
String temp = name + " " + age + " " + gpa + "\n";
return temp;
}
}
the school class calls to the student class.
this is what comes back.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at School.linearSearch(Lab07vst100SD.java:78)
at Lab07vst100SD.main(Lab07vst100SD.java:16)
I'm completely confused on why this is happening, I think it may have to do with the ArrayList, other than that, I'm not sure.
please help, and thank you
p.s. I'm new so please bear with my horrible format.
You need call addData:
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
bhs.addData(); // here
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
...
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>(); // Here, it can throw IndexOutOfBoundsException
size = s;
}
...
Please see https://www.tutorialspoint.com/java/util/arraylist_add_index.htm
The capacity of ArrayList must be initialized before ArrayList.add method
.
I have to find a missing element from the array where array has got values from <0, N>.
For example: int tablica[] = {0, 1, 2, 3, 5};, missing number is 4.
I have got 3 implementations of this code, but...
Only one gives me output, why?
Why naiveFindMissing() and optimalFindMissing() don't give any output?
public class Zad2_Selftraining {
public static void main(String[] args) {
findMissing();
naiveFindMissing();
optimalFindMissing();
}
public static void findMissing() {
int tablica[] = {0, 1, 2, 3, 5};
for(int i = 0; i<tablica.length;i++ ){
if (tablica[i] != i){
System.out.println("Missing: " + i);
return;
}
}
System.out.println("Everything is correct");
return;
}
private static int naiveFindMissing() {
int array[] = {0,1,2,4,5,6,7};
int missing = 0;
boolean elementFound;
for (int elementToFind = 0; elementToFind <= array.length; elementToFind++) {
elementFound = false;
for (int elementInArray : array) {
if (elementToFind == elementInArray) {
elementFound = true;
break;
}
}
if (!elementFound) {
missing = elementToFind;
break;
}
}
return missing;
}
private static int optimalFindMissing() {
int array[] = {0,1,2,4,5,6,7};
int expectedSum = (array.length + 1) * array.length / 2;
int actualSum = 0;
for (int element : array) {
actualSum += element;
}
return expectedSum - actualSum;
}
}
Because you have System.out.println statement only in first method. The other two methods just return result without printing it
I have a problem with implementation of merge sort in java. I am looking for the error almost week unfortunately without result. ArrayList at the entrance is the same as the output.
import java.util.ArrayList;
import java.util.Scanner;
public class MergeSort
{
private ArrayList<Integer> basicArrayList = new ArrayList<Integer>();
ArrayList<Integer> arrayListA = new ArrayList<Integer>();
ArrayList<Integer> arrayListB = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
private int firstIndexOfArrayList = 0;
private int lastIndexOfArrayListA;
private int lastIndexOfArrayListB;
public void Scal(ArrayList<Integer> basicArrayList, int p, int q, int r) {
this.firstIndexOfArrayList = p;
this.lastIndexOfArrayListA = q;
this.lastIndexOfArrayListB = r;
int numberOfElementsArrayListA = lastIndexOfArrayListA
- firstIndexOfArrayList + 1;
int numberOfElementsArrayListB = lastIndexOfArrayListB
- lastIndexOfArrayListA;
for (int i = 0; i < numberOfElementsArrayListA; i++) {
arrayListA.set(i, basicArrayList.get(firstIndexOfArrayList + i));
}
for (int j = 0; j < numberOfElementsArrayListB; j++) {
arrayListB.set(j, basicArrayList.get(lastIndexOfArrayListA + j));
}
arrayListA.add(Integer.MAX_VALUE);
arrayListB.add(Integer.MAX_VALUE);
int i = 0;
int j = 0;
for (int k = firstIndexOfArrayList; k <= lastIndexOfArrayListB; k++) {
if (arrayListA.get(i) <= arrayListB.get(j)) {
basicArrayList.set(k, arrayListA.get(i));
i = i + 1;
} else {
basicArrayList.set(k, arrayListB.get(j));
j = j + 1;
}
}
}
public void MergeSort(ArrayList basicArrayList, int p, int r) {
this.firstIndexOfArrayList = p;
this.lastIndexOfArrayListB = r;
if (firstIndexOfArrayList < lastIndexOfArrayListB) {
int lastIndexOfArrayListA = (firstIndexOfArrayList + lastIndexOfArrayListB) / 2;
MergeSort(basicArrayList, firstIndexOfArrayList,
lastIndexOfArrayListA);
MergeSort(basicArrayList, lastIndexOfArrayListA + 1,
lastIndexOfArrayListB);
Scal(basicArrayList, firstIndexOfArrayList,
lastIndexOfArrayListA,
lastIndexOfArrayListB);
}
}
public void setSize() {
System.out.println("Enter the number of elements to sort: ");
this.lastIndexOfArrayListB = input.nextInt();
}
public int getSize() {
return lastIndexOfArrayListB;
}
public void setData() {
System.out.println("Enter the numbers: ");
for (int i = 0; i < lastIndexOfArrayListB; i++) {
int number;
number = input.nextInt();
basicArrayList.add(number);
}
}
public void getTable() {
System.out.println(basicArrayList.toString());
}
public static void main(String[] args) {
MergeSort output = new MergeSort();
output.setSize();
output.setData();
output.MergeSort(output.basicArrayList,
output.firstIndexOfArrayList, (output.getSize() - 1));
output.getTable();
}
}
In terms of fixing your code I had a crack at it and as far as I can tell this seems to work. To do this a lot of your code had to be changed but it does now sort all Integers properly
import java.util.ArrayList;
import java.util.Scanner;
public class MergeSort
{
private ArrayList<Integer> basicArrayList = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
private int numbersToSort;
public void doMergeSort(int firstIndexOfArrayList,int lastIndexOfArrayListB, ArrayList<Integer> arrayList)
{
if(firstIndexOfArrayList<lastIndexOfArrayListB && (lastIndexOfArrayListB-firstIndexOfArrayList)>=1)
{
int mid = (lastIndexOfArrayListB + firstIndexOfArrayList)/2;
doMergeSort(firstIndexOfArrayList, mid, arrayList);
doMergeSort(mid+1, lastIndexOfArrayListB, arrayList);
Scal(firstIndexOfArrayList,mid,lastIndexOfArrayListB, arrayList);
}
}
public void Scal(int firstIndexOfArrayList,int lastIndexOfArrayListA,int lastIndexOfArrayListB, ArrayList<Integer> arrayList)
{
ArrayList<Integer> mergedSortedArray = new ArrayList<Integer>();
int leftIndex = firstIndexOfArrayList;
int rightIndex = lastIndexOfArrayListA+1;
while(leftIndex<=lastIndexOfArrayListA && rightIndex<=lastIndexOfArrayListB)
{
if(arrayList.get(leftIndex)<=arrayList.get(rightIndex))
{
mergedSortedArray.add(arrayList.get(leftIndex));
leftIndex++;
}
else
{
mergedSortedArray.add(arrayList.get(rightIndex));
rightIndex++;
}
}
while(leftIndex<=lastIndexOfArrayListA)
{
mergedSortedArray.add(arrayList.get(leftIndex));
leftIndex++;
}
while(rightIndex<=lastIndexOfArrayListB)
{
mergedSortedArray.add(arrayList.get(rightIndex));
rightIndex++;
}
int i = 0;
int j = firstIndexOfArrayList;
while(i<mergedSortedArray.size())
{
arrayList.set(j, mergedSortedArray.get(i++));
j++;
}
}
public void setSize()
{
System.out.println("Enter the number of elements to sort: ");
this.numbersToSort = input.nextInt();
}
public int getSize()
{
return numbersToSort;
}
public void setData()
{
System.out.println("Enter the numbers: ");
for (int i = 0; i < numbersToSort; i++)
{
int number;
number = input.nextInt();
basicArrayList.add(number);
}
}
public void getTable()
{
System.out.println(basicArrayList.toString());
}
public void runSort(ArrayList<Integer> arrayList)
{
doMergeSort(0, this.numbersToSort-1, arrayList);
}
public static void main(String[] args)
{
MergeSort output = new MergeSort();
output.setSize();
output.setData();
output.runSort(output.basicArrayList);
output.getTable();
}
}
Try this code. The following code takes an ArrayList input and outputs an ArrayList as well so it still works along the same basis of your code. The actual sort is handled in a different class MergeSort and is passes into ForMergeSort. Hope this helps
MergeSort.java
public class MergeSort
{
private int[] array;
private int[] tempMergArr;
private int length;
public void sort(int[] inputArr)
{
}
public int[] getSortedArray(int[] inputArr)
{
this.array = inputArr;
this.length = inputArr.length;
this.tempMergArr = new int[length];
doMergeSort(0, length - 1);
for(int i=0;i<length;i++)
{
int correctNumber = i+1;
System.out.println("Value "+correctNumber+" of the sorted array which was sorted via the Merge Sort is: "+inputArr[i]);
}
return inputArr;
}
private void doMergeSort(int lowerIndex, int higherIndex)
{
if (lowerIndex < higherIndex)
{
int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
doMergeSort(lowerIndex, middle);
doMergeSort(middle + 1, higherIndex);
mergeParts(lowerIndex, middle, higherIndex);
}
}
private void mergeParts(int lowerIndex, int middle, int higherIndex)
{
for (int i = lowerIndex; i <= higherIndex; i++)
{
tempMergArr[i] = array[i];
}
int i = lowerIndex;
int j = middle + 1;
int k = lowerIndex;
while (i <= middle && j <= higherIndex)
{
if (tempMergArr[i] <= tempMergArr[j])
{
array[k] = tempMergArr[i];
i++;
}
else
{
array[k] = tempMergArr[j];
j++;
}
k++;
}
while (i <= middle)
{
array[k] = tempMergArr[i];
k++;
i++;
}
}
}
ForMergeSort.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class ForMergeSort
{
ArrayList<Integer> arrayList = new ArrayList<Integer>();
ArrayList<Integer> sortedArrayList = new ArrayList<Integer>();
MergeSort mS = new MergeSort();
public void buildArrayList()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter the number of elements to sort: ");
int toSort = input.nextInt();
System.out.println("Enter the numbers: ");
for(int i =0; i<toSort; i++)
{
int number = input.nextInt();
arrayList.add(number);
}
}
public void runMergeSort(ArrayList<Integer> arrayList)
{
int[] arrayOfValues = new int[arrayList.size()];
int i = 0;
for(int a:arrayList)
{
arrayOfValues[i] = a;
i++;
}
MergeSort mS = new MergeSort();
for(int intOfArray:mS.getSortedArray(arrayOfValues))
{
sortedArrayList.add(intOfArray);
}
System.out.println(sortedArrayList.toString());
}
public static void main(String[] args)
{
ForMergeSort fMS = new ForMergeSort();
fMS.buildArrayList();
fMS.runMergeSort(fMS.arrayList);
}
}
I have written a simple genetic algorithm program in java. What it is does is maximize the decimal value represented by the bits in the chromosome. Somehow mutation is not working as expected, e.g. causing two genes to mutate when just one is to change. The print statements I have included there show which to mutate, but in addition to that some more chromosomes get mutated. I can't figure out what the problem is :-(
Here are my java classes.
Gene.java
public class Gene {
private int value;
public Gene() {
value = Math.random() < 0.5 ? 0 : 1;
}
public Gene(int value) {
if (value != 0 && value != 1) {
throw new IllegalArgumentException("value must be either 0 or 1");
}
else {
this.value = value;
}
}
public void mutate() {
value = 1 - value;
}
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.List;
public class Chromosome implements Comparable {
private ArrayList<Gene> genes;
private final int chromosomeLength;
public Chromosome(int length) {
this.genes = new ArrayList<>();
this.chromosomeLength = length > 0 ? length : 16;
for (int i = 0; i < chromosomeLength; i++) {
this.genes.add(i, new Gene());
}
}
public List<Gene> getAllele(int fromIndex, int toIndex) {
return new ArrayList<>(genes.subList(fromIndex, toIndex));
}
public void setAllele(int fromIndex, List<Gene> allele) {
int lastIndex = fromIndex + allele.size();
if (lastIndex > chromosomeLength) {
throw new IndexOutOfBoundsException("the allele exceeds beyond the size of the chromosome");
}
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
}
public int getChromosomeLength() {
return chromosomeLength;
}
public void setGeneAt(int index, Gene gene) {
genes.set(index, gene);
}
public Gene getGeneAt(int index) {
return genes.get(index);
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
#Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((Gene g) -> chromosome.append(g));
return chromosome.toString();
}
#Override
public int compareTo(Object anotherChromosome) {
Chromosome c = (Chromosome) anotherChromosome;
return this.value() - c.value();
}
}
GenePool.java
import java.util.ArrayList;
import java.util.Arrays;
public class GenePool {
private final ArrayList<Chromosome> genePool;
private final int genePoolSize;
private final int chromosomeLength;
private final double crossOverRate;
private final double mutationRate;
private int[] crossPoints;
public GenePool(int numOfChromosome, int chromosomeLength, double crossOverRate, double mutationRate) {
this.genePoolSize = numOfChromosome;
this.chromosomeLength = chromosomeLength > 0 ? chromosomeLength : 16;
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
crossPoints = new int[1];
crossPoints[0] = this.chromosomeLength / 2;
genePool = new ArrayList<>();
for (int i = 0; i < numOfChromosome; i++) {
genePool.add(new Chromosome(chromosomeLength));
}
}
public int getGenePoolSize() {
return genePoolSize;
}
public Chromosome getChromosomeAt(int index) {
return genePool.get(index);
}
public void setChromosomeAt(int index, Chromosome c) {
genePool.set(index, c);
}
public int getChromosomeLength() {
return chromosomeLength;
}
public Chromosome[] crossOver(Chromosome c1, Chromosome c2) {
Chromosome[] offsprings = new Chromosome[2];
offsprings[0] = new Chromosome(c1.getChromosomeLength());
offsprings[1] = new Chromosome(c1.getChromosomeLength());
Chromosome[] parentChromosomes = {c1, c2};
int selector = 0;
for (int i = 0, start = 0; i <= crossPoints.length; i++) {
int crossPoint = i == crossPoints.length ? c1.getChromosomeLength() : crossPoints[i];
offsprings[0].setAllele(start, parentChromosomes[selector].getAllele(start, crossPoint));
offsprings[1].setAllele(start, parentChromosomes[1 - selector].getAllele(start, crossPoint));
selector = 1 - selector;
start = crossPoint;
}
return offsprings;
}
public void mutateGenePool() {
int totalGeneCount = genePoolSize * chromosomeLength;
System.out.println("Mutating genes:");
for (int i = 0; i < totalGeneCount; i++) {
double prob = Math.random();
if (prob < mutationRate) {
System.out.printf("Chromosome#: %d\tGene#: %d\n", i / chromosomeLength, i % chromosomeLength);
genePool.get(i / chromosomeLength).getGeneAt(i % chromosomeLength).mutate();
}
}
System.out.println("");
}
public int getLeastFitIndex() {
int index = 0;
int min = genePool.get(index).value();
int currentValue;
for (int i = 1; i < genePoolSize; i++) {
currentValue = genePool.get(i).value();
if (currentValue < min) {
index = i;
min = currentValue;
}
}
return index;
}
public void saveFittest(ArrayList<Chromosome> offsprings) {
// sort in ascending order
offsprings.sort(null);
offsprings.stream().forEach((offspring) -> {
int leastFitIndex = getLeastFitIndex();
if (offspring.value() > genePool.get(leastFitIndex).value()) {
genePool.set(leastFitIndex, offspring);
}
});
}
public void evolve(int noOfGeneration) {
for (int generation = 1; generation <= noOfGeneration; generation++) {
System.out.println("Generation :" + generation);
ArrayList<Integer> selection = new ArrayList<>();
for (int i = 0; i < genePoolSize; i++) {
if (Math.random() <= crossOverRate) {
selection.add(i);
}
}
if (selection.size() % 2 == 1) {
selection.remove(selection.size() - 1);
}
ArrayList<Chromosome> offsprings = new ArrayList<>();
for (int i = 0; i < selection.size(); i += 2) {
int index1 = selection.get(i);
int index2 = selection.get(i + 1);
offsprings.addAll(Arrays.asList(crossOver(genePool.get(index1), genePool.get(index2))));
}
System.out.println("Before saving the offsprings");
displayChromosomes(genePool, "GenePool");
displayChromosomes(offsprings, "Offsprings");
saveFittest(offsprings);
System.out.println("Before mutation:");
displayChromosomes(genePool, "GenePool");
mutateGenePool();
System.out.println("After mutation:");
displayChromosomes(genePool, "GenePool");
System.out.println("\n\n");
}
}
public void displayChromosomes(ArrayList<Chromosome> geneList, String name) {
System.out.println(name);
if (geneList.isEmpty()) {
System.out.println("Empty list");
}
geneList.stream().forEach((c) -> {
System.out.println(c + " -> " + c.value());
});
System.out.println("");
}
}
GADemo.java
public class GADemo {
public static void main(String[] args) {
GenePool gp = new GenePool(6, 8, 0.25, 0.01);
gp.evolve(10);
}
}
After evolving for a number of generations, the chromosomes all tend to become exactly the same, or very similar. And the problem is that that value is not the maximum for that many bits, and sometimes even a small value. For example, for 8 bits the values should (tend to) approach 255, but this doesn't do so in my code. Someone please provide a hint where/how to look for and solve the problem.
Focus on these lines and imagine the references. These are from setAllele()
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
You are basically copying the reference from one onto the other. They are the same Gene so whatever mutation you do on those genes, will also affect even other Chromosomes.
You must produce a deep copy here.
Initially each chromosome has an own list of genes. But when you do the crossover operation you set gene objects from one chromosome into the gene list of other chromosome.
When you evolve the system, the number of shared genes will rise and therefore ultimately all chromosomes will share the same genes. No matter how you mutate a gene the chromosomes are not affected.
EDIT:
As Incognito also answered the setAllele method seems to be the culprit where gene sharing starts. You may want to introduce a method in the gene class where you can set its value given another gene.
I am playing around with an ArrayList and trying to get it to grow twice it's size every time it exceeds it's size. Here is my add method:
public class ArrayExpander
{
private int size;
private int noOfItems;
private Object[] store;
private final int INITIALSIZE = 2;
public ArrayExpander()
{
store = new Object[INITIALSIZE];
noOfItems = 0;
size = INITIALSIZE;
}
public void add(Object obj)
{
growBufferIfNecessary();
store[size++] = obj;
/*for (int i = size - 1; i < store.length; i++)
{
store[i] = store[i - 1];
store[i] = obj;
}*/
}
public String toString()
{
String temp = "[" + store[0];
for (int i = 1; i < size; i++)
{
temp = temp + "," + store[i];
}
temp = temp + "]";
return temp;
}
private void growBufferIfNecessary()
{
if (size == store.length)
{
Object[] newStore = new Object[2 * store.length];
for (int i = 0; i < store.length; i++)
{
newStore[i] = store[i];
}
store = newStore;
}
}
public static void main(String[] args)
{
ArrayExpander ae = new ArrayExpander();
//System.out.println(ae);
ae.add("a");
ae.add("b");
System.out.println(ae);
ae.add("c");
ae.add("d");
ae.add("e");
ae.add("f");
ae.add("g");
ae.add("h");
System.out.println(ae);
ae.add("i");
System.out.println(ae);
}
}
Here is my output:
[null,null]
[null,null,a,b]
[null,null,a,b,c,d,e,f,g,h]
[null,null,a,b,c,d,e,f,g,h,i]
I can't figure out why I am getting the null statements. The first line should be a,b and then the arraylist should double in size and be a,b,c,d. I have it set for final int INITIALSIZE = 2.
The output I am looking for is
[a,b]
[a,b,c,d]
[a,b,c,d,e,f,g,h]
[a,b,c,d,e,f,g,h,i,null,null,null,null,null,null,null]
This code will work for you. size should be referring to the size of your array while noOfItems refers to the number of items in your array. You were kind of mixing the 2 up. I only changed a couple things in your add() and growBufferIfNecessary().
public class ArrayExpander
{
private int size;
private int noOfItems;
private Object[] store;
private final int INITIALSIZE = 2;
public ArrayExpander()
{
store = new Object[INITIALSIZE];
noOfItems = 0;
size = INITIALSIZE;
}
public void add(Object obj)
{
growBufferIfNecessary();
store[noOfItems++] = obj;
}
public String toString()
{
String temp = "[" + store[0];
for (int i = 1; i < size; i++)
{
temp = temp + "," + store[i];
}
temp = temp + "]";
return temp;
}
private void growBufferIfNecessary()
{
if (noOfItems == size)
{
size = 2 * size;
Object[] newStore = new Object[size];
for (int i = 0; i < store.length; i++)
{
newStore[i] = store[i];
}
store = newStore;
}
}
public static void main(String[] args)
{
ArrayExpander ae = new ArrayExpander();
//System.out.println(ae);
ae.add("a");
ae.add("b");
System.out.println(ae);
ae.add("c");
ae.add("d");
ae.add("e");
ae.add("f");
ae.add("g");
ae.add("h");
System.out.println(ae);
ae.add("i");
System.out.println(ae);
}
}
Try this. If you notice I replaced size in a couple spots with noOfItems. You were really close you just needed to change a couple things.
Manually copying arrays with loops is such a pain, use System.arraycopy(Object,int,Object,int,int) like
private int size = 0;
private Object[] store = new Object[INITIALSIZE];
private void growBufferIfNecessary() {
if (size >= store.length) {
Object[] newStore = new Object[2 * store.length];
System.arraycopy(store, 0, newStore, 0, store.length);
store = newStore;
}
}
I eliminated noOfItems. You don't need it, your add method is just
public void add(Object obj) {
growBufferIfNecessary();
store[size++] = obj;
}
Finally, your toString() could use Arrays.copyOf(T[], int) like
#Override
public String toString() {
return Arrays.toString(Arrays.copyOf(store, size));
}
And then I got your expected output
[a, b]
[a, b, c, d, e, f, g, h]
[a, b, c, d, e, f, g, h, i]