K-means clustering using Java - java

I found the following code on the Internet. I think there is a problem in type conversion.
I tried to solving some of it but still there are few that elude me.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Cluster {
public List points;
public Point centroid;
public int id;
//Creates a new Cluster
public Cluster(int id) {
this.id = id;
this.points = new ArrayList();
this.centroid = null;
}
public List getPoints() {
return points;
}
public void addPoint(Point point) {
points.add(point);
}
public void setPoints(List points) {
this.points = points;
}
public Point getCentroid() {
return centroid;
}
public void setCentroid(Point centroid) {
this.centroid = centroid;
}
public int getId() {
return id;
}
public void clear() {
points.clear();
}
public void plotCluster() {
System.out.println("[Cluster: " + id+"]");
System.out.println("[Centroid: " + centroid + "]");
System.out.println("[Points: \n");
for(Point p : points) {
System.out.println(p);
}
System.out.println("]");
}
}
public class Point {
private double x = 0;
private double y = 0;
private int cluster_number = 0;
public Point(double x, double y)
{
this.setX(x);
this.setY(y);
}
public void setX(double x) {
this.x = x;
}
public double getX() {
return this.x;
}
public void setY(double y) {
this.y = y;
}
public double getY() {
return this.y;
}
public void setCluster(int n) {
this.cluster_number = n;
}
public int getCluster() {
return this.cluster_number;
}
//Calculates the distance between two points.
protected static double distance(Point p, Point centroid) {
return Math.sqrt(Math.pow((centroid.getY() - p.getY()), 2) + Math.pow((centroid.getX() - p.getX()), 2));
}
//Creates random point
protected static Point createRandomPoint(int min, int max) {
Random r = new Random();
double x = min + (max - min) * r.nextDouble();
double y = min + (max - min) * r.nextDouble();
return new Point(x,y);
}
protected static List createRandomPoints(int min, int max, int number) {
List points = new ArrayList(number);
for(int i = 0; i < number; i++) {
points.add(createRandomPoint(min,max));
}
return points;
}
public String toString() {
return "("+x+","+y+")";
}
}
public class KMeans {
//Number of Clusters. This metric should be related to the number of points
private int NUM_CLUSTERS = 3;
//Number of Points
private int NUM_POINTS = 15;
//Min and Max X and Y
private static final int MIN_COORDINATE = 0;
private static final int MAX_COORDINATE = 10;
private List points;
private List clusters;
public KMeans() {
this.points = new ArrayList();
this.clusters = new ArrayList();
}
public static void main(String[] args) {
KMeans kmeans = new KMeans();
kmeans.init();
kmeans.calculate();
}
//Initializes the process
public void init() {
//Create Points
points = Point.createRandomPoints(MIN_COORDINATE,MAX_COORDINATE,NUM_POINTS);
//Create Clusters
//Set Random Centroids
for (int i = 0; i < NUM_CLUSTERS; i++) {
Cluster cluster = new Cluster(i);
Point centroid = Point.createRandomPoint(MIN_COORDINATE,MAX_COORDINATE);
cluster.setCentroid(centroid);
clusters.add(cluster);
}
//Print Initial state
plotClusters();
}
private void plotClusters() {
for (int i = 0; i < NUM_CLUSTERS; i++) {
Cluster c = clusters.get(i);
c.plotCluster();
}
}
//The process to calculate the K Means, with iterating method.
public void calculate() {
boolean finish = false;
int iteration = 0;
// Add in new data, one at a time, recalculating centroids with each new one.
while(!finish) {
//Clear cluster state
clearClusters();
List lastCentroids = getCentroids();
//Assign points to the closer cluster
assignCluster();
//Calculate new centroids.
calculateCentroids();
iteration++;
List currentCentroids = getCentroids();
//Calculates total distance between new and old Centroids
double distance = 0;
for(int i = 0; i < lastCentroids.size(); i++) {
distance += Point.distance(lastCentroids.get(i),currentCentroids.get(i));
}
System.out.println("#################");
System.out.println("Iteration: " + iteration);
System.out.println("Centroid distances: " + distance);
plotClusters();
if(distance == 0) {
finish = true;
}
}
}
private void clearClusters() {
for(Cluster cluster : clusters) {
cluster.clear();
}
}
private List getCentroids() {
List centroids = new ArrayList(NUM_CLUSTERS);
for(Cluster cluster : clusters) {
Point aux = cluster.getCentroid();
Point point = new Point(aux.getX(),aux.getY());
centroids.add(point);
}
return centroids;
}
private void assignCluster() {
double max = Double.MAX_VALUE;
double min = max;
int cluster = 0;
double distance = 0.0;
for(Point point : points) {
min = max;
for(int i = 0; i < NUM_CLUSTERS; i++) {
Cluster c = clusters.get(i);
distance = Point.distance(point, c.getCentroid());
if(distance < min){
min = distance;
cluster = i;
}
}
point.setCluster(cluster);
clusters.get(cluster).addPoint(point);
}
}
private void calculateCentroids() {
for(Cluster cluster : clusters) {
double sumX = 0;
double sumY = 0;
List list = cluster.getPoints();
int n_points = list.size();
for(Point point : list) {
sumX += point.getX();
sumY += point.getY();
}
Point centroid = cluster.getCentroid();
if(n_points > 0) {
double newX = sumX / n_points;
double newY = sumY / n_points;
centroid.setX(newX);
centroid.setY(newY);
}
}
}
}
I got the following erros. How to resolve them:
java:45: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
clusters.add(cluster);
^
where E is a type-variable:
E extends Object declared in interface List
/tmp/java_kmNqUn/KMeans.java:54: error: incompatible types: Object cannot be converted to Cluster
Cluster c = clusters.get(i);
^
/tmp/java_kmNqUn/KMeans.java:84: error: incompatible types: Object cannot be converted to Point
distance += Point.distance(lastCentroids.get(i),currentCentroids.get(i));
^
/tmp/java_kmNqUn/KMeans.java:98: error: incompatible types: Object cannot be converted to Cluster
for(Cluster cluster : clusters) {
^
/tmp/java_kmNqUn/KMeans.java:105: error: incompatible types: Object cannot be converted to Cluster
for(Cluster cluster : clusters) {
^
/tmp/java_kmNqUn/KMeans.java:108: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
centroids.add(point);
^
where E is a type-variable:
E extends Object declared in interface List
/tmp/java_kmNqUn/KMeans.java:119: error: incompatible types: Object cannot be converted to Point
for(Point point : points) {
^
/tmp/java_kmNqUn/KMeans.java:122: error: incompatible types: Object cannot be converted to Cluster
Cluster c = clusters.get(i);
^
/tmp/java_kmNqUn/KMeans.java:130: error: cannot find symbol
clusters.get(cluster).addPoint(point);
^
symbol: method addPoint(Point)
location: class Object
/tmp/java_kmNqUn/KMeans.java:135: error: incompatible types: Object cannot be converted to Cluster
for(Cluster cluster : clusters) {
^
/tmp/java_kmNqUn/KMeans.java:141: error: incompatible types: Object cannot be converted to Point
for(Point point : list) {
^
/tmp/java_kmNqUn/Point.java:61: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
points.add(createRandomPoint(min,max));
^
where E is a type-variable:
E extends Object declared in interface List
/tmp/java_kmNqUn/Cluster.java:27: warning: [unchecked] unchecked call to add(E) as a member of the raw type List
points.add(point);
^
where E is a type-variable:
E extends Object declared in interface List
/tmp/java_kmNqUn/Cluster.java:54: error: incompatible types: Object cannot be converted to Point
for(Point p : points) {
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
10 errors
4 warnings*
please guide me...

You should avoid using a type List without any type parameters. You should instead use a List<SomeType> (replacing SomeType with the relevant type).

Using a strongly typed generic List with a type parameter is the best way of doing it. If, however, you are forced to use an older version of Java that does not support generics, you could cast the cluster objects like this: Cluster c = (Cluster)clusters.get(i);

Related

Calculating distance between non directly-connected nodes in matrix

I made a adjacency matrix for cities and connecting between them. And for example A-B, B-C, C-D. Now I am wonder if I can calculate distance between cities that aren't connected. Is it possible to calculate distance in matrix between non connected nodes and find path?
Cities class
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class GraphCities {
private List<String> cities;
private int[][] matrix;
Scanner s = new Scanner(System.in);
public GraphCities() {
this.cities = new LinkedList<String>();
}
public void addCity(String name) {
if (!cities.contains(name)) {
cities.add(name);
} else {
System.out.println("City " + name + " is already added.");
}
}
public void makeGraph() {
System.out
.println("Distance between cities, if they aren't connected insert -1");
matrix = new int[cities.size()][cities.size()];
for (int i = 0; i < matrix.length; i++) {
for (int j = i; j < matrix.length; j++) {
if (i == j) {
matrix[i][j] = 0;
} else {
System.out.println("Distance from "
+ cities.get(i) + " to " + cities.get(j));
int distance = s.nextInt();
matrix[i][j] = distance;
matrix[j][i] = distance;
}
}
}
}
public void show() {
String show = "\t";
for (int i = 0; i < cities.size(); i++) {
show += cities.get(i) + "\t";
}
show += "\n";
for (int i = 0; i < matrix.length; i++) {
show += cities.get(i) + "\t";
for (int j = 0; j < matrix.length; j++) {
if (matrix[i][j] != -1) {
show += matrix[i][j] + "\t";
} else {
show += "-\t";
}
}
show += "\n";
}
System.out.println(show);
}
}
Main method
public class Main {
public static void main(String[] args) {
GraphCities c = new GraphCities();
c.addCity("A");
c.addCity("B");
c.addCity("C");
c.addCity("D");
c.addCity("E");
c.makeGraph();
System.out.println();
c.show();
}
}
This is my output when i run main method and i think everything is ok.
A B C D E
A 0 50 - - -
B 50 0 30 - -
C - 30 0 40 -
D - - 40 0 20
E - - - 20 0
Now I want to calculate distance from A to D, but i haven't any idea how to do it. I will appreciate any help. Thanks!
To find the shortest path in a weighted graph (each part of the route has a different weight) you can use Dijkstra's Shortest Path Algorithm.
The following code is a one-file mcve. It can be copy-pasted into one file (Main.java) , and executed.
(This answer is base on the code posted before editing the question)
Please note the comments:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
AdjList aList = new AdjList();
CityNode a = new CityNode("A");
CityNode b = new CityNode("B");
CityNode c = new CityNode("C");
CityNode d = new CityNode("D");
CityNode e = new CityNode("E");
aList.addCity(a);
aList.addCity(b);
aList.addCity(c);
aList.addCity(d);
aList.addCity(e);
aList.connectCities(a, b, 50);
aList.connectCities(b, c, 30);
aList.connectCities(c, d, 40);
aList.connectCities(d, e, 20);
aList.show();
FindPath findPath = new FindPath();
System.out.println(findPath.calculateShortestPath(aList, a, e)); //prints 140 as expected
//add some complexity
CityNode f = new CityNode("F");
aList.addCity(f);
aList.connectCities(b, f, 10);
aList.connectCities(f, d, 10);
System.out.println(findPath.calculateShortestPath(aList, a, e));//prints 90 as expected
}
}
class FindPath{
//map to hold distances of all node from origin. at the end this map should contain
//the shortest distance between origin (from) to all other nodes
Map<CityNode, Integer> distances;
//using Dijkstra algorithm
public int calculateShortestPath(AdjList aList, CityNode from, CityNode to) {
//a container to hold which cities the algorithm has visited
Set<CityNode> settledCities = new HashSet<>();
//a container to hold which cities the algorithm has to visit
Set<CityNode> unsettledCities = new HashSet<>();
unsettledCities.add(from);
//map to hold distances of all node from origin. at the end this map should contain
//the shortest distance between origin (from) to all other nodes
distances = new HashMap<>();
//initialize map with values: 0 distance to origin, infinite distance to all others
//infinite means no connection between nodes
for(CityNode city :aList.getCities()){
int distance = city.equals(from) ? 0 : Integer.MAX_VALUE;
distances.put(city, distance);
}
while (unsettledCities.size() != 0) {
//get the unvisited city with the lowest distance
CityNode currentCity = getLowestDistanceCity(unsettledCities);
//remove from unvisited, add to visited
unsettledCities.remove(currentCity); settledCities.add(currentCity);
Map<CityNode, Integer> connectedCities = currentCity.getConnectedCities();
for( CityNode city : connectedCities.keySet()){
//check if new distance is shorted than the previously found distance
if(distances.get(currentCity) + connectedCities.get(city) < distances.get(city)){
//if so, keep the shortest distance found
distances.put(city, distances.get(currentCity) + connectedCities.get(city));
//if city has not been visited yet, add it to unsettledCities
if(! settledCities.contains(city)) {
unsettledCities.add(city);
}
}
}
}
return distances.get(to);
}
private CityNode getLowestDistanceCity(Set <CityNode> unsettledCities) {
return unsettledCities.stream()
.min((c1,c2)-> Integer.compare(distances.get(c1), distances.get(c2)))
.orElse(null);
}
}
class CityNode {
private static int counter =0;
private final String name;
//assign unique id to each node. safer than to rely on unique name
private final int id = counter ++;
//map to hold all connected cities and distance to each
private final Map<CityNode, Integer> connectedCities;
public CityNode(String name) {
super();
this.name = name;
connectedCities = new HashMap<>();
}
public String getName() {
return name;
}
//not null safe. distance must not be negative
public void connect(CityNode connectTo, int distance) {
if(connectTo.equals(this)) throw new IllegalArgumentException("Node can not connect to istself");
connectedCities.put(connectTo, distance);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder(name);
sb.append(connectedCities.keySet().isEmpty() ? " not connected" : " conntected to: " );
for ( CityNode city : connectedCities.keySet()) {
sb.append(city.getName()).append("-")
.append(connectedCities.get(city)).append("km ");
}
return sb.toString();
}
public int getId() {
return id;
}
public Map<CityNode, Integer> getConnectedCities(){
return connectedCities;
}
#Override
public boolean equals(Object o) {
if(o == null ||!(o instanceof CityNode)) return false;
CityNode c = (CityNode) o;
return c.getName().equalsIgnoreCase(name) && id == c.getId();
}
#Override
public int hashCode() {
int hash = 31 * 7 + id;
return name == null ? hash : name.hashCode();
}
}
class AdjList {
//use set which prevents duplicate entries
private final Set<CityNode> citiesList;
public AdjList() {
citiesList = new HashSet<>();
}
//adds city if is not already present. returns true if city was added
public boolean addCity(CityNode city) {
return citiesList.add(city);
}
//not null safe
public void connectCities(CityNode city1, CityNode city2, int distance) {
//assuming undirected graph
city1.connect(city2, distance);
city2.connect(city1, distance);
}
public CityNode getCityByName(String name) {
for (CityNode city : citiesList) {
if (city.getName().equalsIgnoreCase(name))
return city;
}
return null;
}
public void show() {
for (CityNode city : citiesList) {
System.out.println(city);
}
}
//get a copy of cities list
public Collection<CityNode> getCities(){
return new ArrayList<>(citiesList);
}
}
If you need a version of getLowestDistanceCity which does not use Stream use :
private CityNode getLowestDistanceCity(Set <CityNode> unsettledCities) {
CityNode lowestDistanceCity = null;
int lowestDistance = Integer.MAX_VALUE;
for (CityNode city: unsettledCities) {
int nodeDistance = distances.get(city);
if (nodeDistance < lowestDistance) {
lowestDistance = nodeDistance;
lowestDistanceCity = city;
}
}
return lowestDistanceCity;
}
Edit: an implementation using adjacency matrix could look like this:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class DijkstraAdjacencyMatrix {
public static void main(String[] args) {
Set<CityNode> cities = new HashSet<>();
CityNode a = new CityNode("A");
CityNode b = new CityNode("B");
CityNode c = new CityNode("C");
CityNode d = new CityNode("D");
CityNode e = new CityNode("E");
cities.addAll(List.of(a,b,c,d,e));
CitiesGraph graph = new CitiesGraph(cities);
graph.connectCities(a, b, 50);
graph.connectCities(b, c, 30);
graph.connectCities(c, d, 40);
graph.connectCities(d, e, 20);
graph.show();
FindPath findPath = new FindPath();
System.out.println(findPath.calculateShortestPath(graph, a, e)); //prints 140 as expected
//to add some complexity we need to construct a new CitiesGraph. It is not reusable
CityNode f = new CityNode("F");
cities.add(f);
graph = new CitiesGraph(cities);
graph.connectCities(a, b, 50);
graph.connectCities(b, c, 30);
graph.connectCities(c, d, 40);
graph.connectCities(d, e, 20);
graph.connectCities(b, f, 10);
graph.connectCities(f, d, 10);
graph.show();
System.out.println(findPath.calculateShortestPath(graph, a, e));//prints 90 as expected
}
}
class FindPath{
//map to hold distances of all node from origin. at the end this map should contain
//the shortest distance between origin (from) to all other nodes
Map<CityNode, Integer> distances;
//using Dijkstra algorithm
public int calculateShortestPath(CitiesGraph graph, CityNode from, CityNode to) {
//a container to hold which cities the algorithm has visited
Set<CityNode> settledCities = new HashSet<>();
//a container to hold which cities the algorithm has to visit
Set<CityNode> unsettledCities = new HashSet<>();
unsettledCities.add(from);
//map to hold distances of all node from origin. at the end this map should contain
//the shortest distance between origin (from) to all other nodes
distances = new HashMap<>();
//initialize map with values: 0 distance to origin, infinite distance to all others
//infinite means no connection between nodes
for(CityNode city :graph.getCities()){
int distance = city.equals(from) ? 0 : Integer.MAX_VALUE;
distances.put(city, distance);
}
while (unsettledCities.size() != 0) {
//get the unvisited city with the lowest distance
CityNode currentCity = getLowestDistanceCity(unsettledCities);
//remove from unvisited, add to visited
unsettledCities.remove(currentCity); settledCities.add(currentCity);
Collection<CityNode> connectedCities = graph.getCitiesConnectedTo(currentCity);
//iterate over connected city to update distance to each
for( CityNode city : connectedCities){
//check if new distance is shorted than the previously found distance
int distanceToCity = graph.getDistanceBetween(city, currentCity);
if(distanceToCity <= 0) {
continue;
}
if(distances.get(currentCity) + distanceToCity < distances.get(city)){
//if so, keep the shortest distance found
distances.put(city,distances.get(currentCity) + distanceToCity);
//if city has not been visited yet, add it to unsettledCities
if(! settledCities.contains(city)) {
unsettledCities.add(city);
}
}
}
}
return distances.get(to);
}
private CityNode getLowestDistanceCity(Set <CityNode> unsettledCities) {
return unsettledCities.stream()
.min((c1,c2)-> Integer.compare(distances.get(c1), distances.get(c2)))
.orElse(null);
}
}
class CityNode {
private static int counter =0;
private final String name;
//assign unique id to each node. safer than to rely on unique name
private final int id = counter ++;
public CityNode(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder("City ");
sb.append(name).append(" (id=").append(id).append(")");
return sb.toString();
}
public int getId() {
return id;
}
#Override
public boolean equals(Object o) {
if(o == null || !(o instanceof CityNode)) return false;
CityNode c = (CityNode) o;
return c.getName().equalsIgnoreCase(name) && id == c.getId();
}
#Override
public int hashCode() {
int hash = 31 * 7 + id;
return name == null ? hash : name.hashCode();
}
}
class CitiesGraph{
//use set which prevents duplicate entries
private final Set<CityNode> cities;
private final int[][] adjacencyMatrix;
private static final int NOT_CONNECTED = -1;
public CitiesGraph(Set<CityNode> cities) {
this.cities = cities;
adjacencyMatrix = new int[cities.size()][cities.size()];
//initialize matrix
for(int row = 0; row < adjacencyMatrix.length ; row++){
for(int col = 0; col < adjacencyMatrix[row].length ; col++){
adjacencyMatrix[row][col] = row == col ? 0 : NOT_CONNECTED ;
}
}
}
public void connectCities(CityNode city1, CityNode city2, int distance) {
//assuming undirected graph
adjacencyMatrix[city1.getId()][city2.getId()] = distance;
adjacencyMatrix[city2.getId()][city1.getId()] = distance;
}
public int getDistanceBetween(CityNode city1, CityNode city2) {
return adjacencyMatrix[city1.getId()][city2.getId()];
}
public Collection<CityNode> getCitiesConnectedTo(CityNode city) {
Collection<CityNode> connectedCities = new ArrayList<>();
//iterate over row representing city's connections
int column = 0;
for(int distance : adjacencyMatrix[city.getId()]){
if(distance != NOT_CONNECTED && distance > 0) {
connectedCities.add(getCityById(column));
}
column++;
}
return connectedCities;
}
public CityNode getCityById(int id) {
for (CityNode city : cities) {
if (city.getId() == id) return city;
}
return null;
}
public void show() {
for(int[] row : adjacencyMatrix){
System.out.println(Arrays.toString(row));
}
}
//get a copy of cities list
public Collection<CityNode> getCities(){
return new ArrayList<>(cities);
}
}

Can't locate the problems in this simple Genetic Algorithm program

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.

Java BoundingBox program

I'm beginner with programming in Java. I would make an application to count max Point, min Point, width and height. I write in eclipse.
I become this error:
Exception in thread "main" java.lang.NullPointerException
at BoundingBox.height(BoundingBox.java:50)
at App.main(App.java:39)`
and my printed points looks like
Point#659e0bfd
Point#2a139a55
Point#15db9742
How should the method toString looks like in this code?
Point
public class Point {
private double x;
private double y;
public Point(double xnew, double ynew) {
x = xnew;
y = ynew;
}
public double getX() {
return x;
}
public void setX(double xnew) {
x = xnew;
}
public double getY() {
return y;
}
public void setY(double ynew) {
y = ynew;
}
}
BoundingBox
import java.util.List;
public class BoundingBox {
private static Point minPoint;
private static Point maxPoint;
public BoundingBox(List<Point> manyPoints) {
double minX = manyPoints.get(0).getX();
double maxX = manyPoints.get(0).getX();
double minY = manyPoints.get(0).getY();
double maxY = manyPoints.get(0).getY();
for (int i = 0; i < manyPoints.size(); i++) {
Point test = manyPoints.get(i);
test.getX();
if (test.getX() < minX) {
minX = test.getX();
}
if (test.getX() > maxX) {
maxX = test.getX();
}
if (test.getY() < minY) {
minY = test.getY();
}
if (test.getY() > maxY) {
maxY = test.getY();
}
minPoint = new Point(minX, minY);
maxPoint = new Point(maxX, maxY);
}
}
public static double width() {
double a = (maxPoint.getX() - minPoint.getX());
return a;
}
public static double height() {
System.out.println("minPoint = " + minPoint);
System.out.println("maxPoint = " + maxPoint);
double b = (maxPoint.getY() - minPoint.getY());
return b;
}
public Point getMaxPoint() {
return maxPoint;
}
public Point getMinPoint() {
return minPoint;
}
}
Application
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class App {
public static void main(String[] args) {
Point p1 = new Point(10.681,-48.857);
Point p2 = new Point(96.980,20.724);
Point p3 = new Point(66.647,-66.558);
Point p4 = new Point(-2.674,-58.571);
Point p5 = new Point(40.11,-12.342);
Point p6 = new Point(27.782,46.809);
Point p7 = new Point(54.759,-46.709);
Point p8 = new Point(-33.89,-90.787);
Point p9 = new Point(15.84,-67.553);
Point p10 = new Point(19.481,51.331);
List<Point> list1 = new ArrayList<Point>(); // Create ArrayList and add Points
list1.add(p1);
list1.add(p2);
list1.add(p3);
list1.add(p4);
list1.add(p5);
list1.add(p6);
list1.add(p7);
list1.add(p8);
list1.add(p9);
list1.add(p10);
Iterator<Point> itr = list1.iterator( );
while ( itr.hasNext( ) ) {
System.out.println( itr.next( ) );
}
double c = BoundingBox.height();
double d = BoundingBox.width();
System.out.println(" The Points: " + list1 );
System.out.println(" BoundingBox have " + c + "height and" + d + "width." );
System.out.println(" The max Point is " );
System.out.println(" The min Point is " );
}
}
Your variables:
private static Point minPoint;
private static Point maxPoint;
are initialized in BoundingBox constructor, but in your App you don't invoke it, so they are null. Just do the following:
new BoundingBox(list1);
double c = BoundingBox.height();
double d = BoundingBox.width();
and NullPointerException will disappear.
You never created an instance of the BoundingBox class before you tried to call the height() and width() functions so you're a receiving the null pointer exception on the line
double a = (maxPoint.getX() - minPoint.getX());
when it's trying to call maxPoint.getX() and minPoint.getX() since there's no values stored inside the variables

Null Pointer Exception in LinkedList Hash Table

So I'm creating a hash table with LinkedLists using the multiplication method. As an instance variable I define the LinkedList "T" that I'll be using, and in the constructor of the class I specify the size of T. However, every time I run my Driver testing class, I get NullPointerExceptions on everything I try to reference anything in T[]. Am I overlooking something? I've spent over an hour trying to figure it out.
ChainedHashTable class:
public class ChainedHashTable
{
private LinkedList<Integer>[] T;
private int m;
private double A;
public ChainedHashTable(int n)
{
for (m = 1; m < n; m *= 2);
T = new LinkedList[m];
Random random = new Random();
int s = random.nextInt(Integer.MAX_VALUE);
A = (s * 1.00) / Integer.MAX_VALUE;
}
public void insert(Integer key)
{
T[hash(key)].add(Integer.valueOf(key));
}
public void delete(int key)
{
T[hash(key)].remove(Integer.valueOf(key));
}
public Integer search(int key)
{
int n = T[hash(key)].indexOf(key);
if (n == -1)
return -1;
else
return T[hash(key)].get(n);
}
private int hash(int key)
{
System.out.println((int)(m * ((key * A) % 1)));
return (int)(m * ((key * A) % 1));
}
public void printTable()
{
for (int i = 0; i < T.length; i++)
{
System.out.println("index: " + i + " " + T[i]);
}
}
}
Driver class:
public class Driver
{
public static void main(String[] args)
{
ChainedHashTable test1 = new ChainedHashTable(20);
test1.printTable();
test1.insert(4);
test1.insert(54);
test1.insert(6);
test1.insert(3);
test1.insert(26);
test1.insert(54);
test1.insert(11);
test1.insert(10);
test1.insert(76);
test1.insert(42);
test1.insert(41);
test1.insert(32);
test1.insert(87);
test1.insert(76);
test1.insert(72);
test1.insert(57);
test1.insert(29);
test1.insert(16);
test1.insert(92);
test1.insert(64);
test1.printTable();
}
}
You are creating an array of references to type LinkedList and setting them to their initial state, which is null.
T = new LinkedList[m];
T now is an array of the computed size m. You need to initialize the objects inside of the array.
T = new LinkedList[m];
for (int i = 0; i < m; i++) {
T[i] = new LinkedList<>();
}

Collections.sort compile error - incompatible types

I have been developing an implementation of the neighbourhood algorithm in Java for a physics project I am working on. I'm brand new to Java so I apologize for any idiocy that results.
I have been getting the error
''
incompatible types
found : void
required: java.util.List<VoronoiPoint>
'' on line 22 from the Java compiler in attempting to compile the program shown below. I cannot figure out why the variable ''thelist'' somehow turns into a void when I declared it to be of type List<VoronoiPoint>. If anybody can explain to me what is going on it would be much appreciated!
import java.lang.Double;
import java.util.*;
public class VoronoiTiling
{
public static void main(String args[])
{
Integer n = 10; //Number of dimensions of model parameter space
Integer ns = 20; //Number of points per iteration
Integer nr = 4; //Number of cells to populate
Integer iterations = 5; //Number of iterations
List<VoronoiPoint> thelist = VoronoiList.startlist(ns,n);
//System.out.println(thelist);
//System.out.println(thelist.get(1).misfit);
for (Integer i=0 ; i<thelist.size() ; i++)
{
thelist.get(i).setmisfit();
}
List<VoronoiPoint> orderedlist = Collections.sort(thelist);
Double distance = EuclidianDistance((thelist.get(1)).location,(thelist.get(2)).location);
System.out.println(distance);
}
public static Double EuclidianDistance(Double[] point1, Double[] point2)
{
Double distance=0.0;
for (int i = 0; i < point1.length; i++)
{
distance = distance + Math.pow((point1[i]-point2[i]),2);
}
return Math.sqrt(distance);
}
}
The other classes I used are here:
The VoronoiList class:
import java.util.*;
public class VoronoiList
{
public static List<VoronoiPoint> startlist(Integer ns, Integer n)
{
List<VoronoiPoint> thestartlist = new ArrayList<VoronoiPoint>();
for (int i = 0; i < ns; i++)
{
thestartlist.add(new VoronoiPoint(0.,n));
}
return thestartlist;
}
}
The VoronoiPoint class:
import java.util.Random;
public class VoronoiPoint implements Comparable<VoronoiPoint>
{
Double[] location;
private Random generator = new Random();
Double misfit = -1.;
//***************************************************************
public VoronoiPoint(Double misfit, Integer n)
{
location = new Double[n];
ParameterBoundaries boundaries = new ParameterBoundaries(n);
for(int i = 0; i < n; i++)
{
location[i] = boundaries.getboundaries(2*i)+2*generator.nextDouble();
}
}
//***************************************************************
//public Double[] getlocation()
//{
//return location;
//}
public void setlocationi(Integer i, Double j)
{
location[i] = j;
}
//***************************************************************
public void setmisfit()
{
Integer n = location.length;
Double tempmisfit = 0.0;
for(Integer i = 0; i < n; i++)
{
tempmisfit = tempmisfit + Math.pow((location[i]),2);
}
misfit = Math.sqrt(tempmisfit); // Temporarily just distance to centre
}
//public Double getmisfit()
//{
//return misfit;
//}
public int compareTo(VoronoiPoint b)
{
if (this.misfit<b.misfit) return -1;
else if (this.misfit==b.misfit) return 0;
return 1;
}
}
And the parameter boundaries class:
public class ParameterBoundaries
{
private Double[] boundaries; /*Set to 2n where n is dimensions of parameter space,
* it just makes it easier*/
public ParameterBoundaries(Integer n)
{
boundaries = new Double[2*n];
for(Integer i = 0; i<n; i++)
{
boundaries[2*i] = -1.0;
boundaries[2*i+1] = 1.0;
}
}
public Double getboundaries(Integer i)
{
return boundaries[i];
}
}
Collections.sort(..) sorts the original list. It doesn't return a new list. (Its return type is void)
Your code is wrong. Collections.sort() is an in-place sort function; it modifies the given list argument and returns nothing (void).

Categories

Resources