i'm making a school project wehere we have to implement the A* algorithm to solthe the 8-puzzle problem. When creating a Node and adding it to the queue, there is no problem, but when I create a second one, and try to add it to the queue, it can't compate them both, to check wich has the lowest f-cost.
private class Node implements Comparable<Node>{
private Node parent;
private int distance;
private int moves;
private Board board;
public Node(Node parent, Board board, int moves) {
this.parent = parent;
this.board = board;
this.moves = moves;
distance = board.manhattan();
}
#Override
public int compareTo(Node node) {
return this.moves + this.distance - node.moves - node.distance;
}
}
this is the class where I create my Node's.
Now when trying to test if this works, I created a slamm JUnit test to see if it would work, but I get the error that my Node class cannot be cast to a comparable.
Here is the code of the test I'm trying to run:
import java.util.PriorityQueue;
import org.junit.Test;
public class UnitTests {
private PriorityQueue<Node> closedPQ = new PriorityQueue<Node>();
#Test
public void pqTest() {
int N = 3, counter = 1;
int[][] tiles = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tiles[i][j] = counter++;
}
}
tiles[2][2] = 0;
tiles[1][1] = 6;
tiles[1][2] = 5;
Board initial = new Board(tiles);
tiles[1][1] = 5;
tiles[1][2] = 6;
Board initial2 = new Board(tiles);
System.out.println(initial.manhattan());
System.out.println(initial2.manhattan());
closedPQ.add(new Node(null, initial, 0));
closedPQ.add(new Node(null, initial2, 0));
Node n = closedPQ.remove();
System.out.println(n.distance);
}
}
First u just make a new board, and then change some nubers to get different costs. The error i get is when I try to add the second Node to the PQ. Anyone got an idea of how to fix this? I'm expecting that the Node with the smallest f ost is returned to me at the remove operation. This is the second Node I add to the queue, because its manhatten-score is 0, while the firsts Node's board has a manhatten-score of 0.
The Failure trace I get is:
java.lang.ClassCastException: gna.UnitTests$Node cannot be cast to java.lang.Comparable
at java.util.PriorityQueue.siftUpComparable(Unknown Source)
at java.util.PriorityQueue.siftUp(Unknown Source)
at java.util.PriorityQueue.offer(Unknown Source)
at java.util.PriorityQueue.add(Unknown Source)
at gna.UnitTests.pqTest(UnitTests.java:100)
Related
I've implemented a BFS algorithm from my textbook and I am trying to modify it to throw an exception when it discovers a non-connected graph. My BFS using an array of boolean to store if a node has been reached or not. After running the BFS from the root node I thought I could iterate through the array and check if each node was reached. My code throws an exception every time and I cannot figure out why. Any guidance would be appreciated thanks!
Code:
private int bfs(Graph G, int s) {
int d = 0;
Queue<Integer> q = new Queue<>();
int distTo[] = new int[G.V()], max = 0;
boolean[] marked = new boolean[G.V()];
int[] edgeTo = new int[G.V()];
for(int v = 0; v < G.V(); v++) {
distTo[s] = Integer.MAX_VALUE;
marked[s] = true;
distTo[s] = 0;
q.enqueue(s);
}
while(!q.isEmpty()) {
d = q.dequeue();
for(int w : G.adj(d)) {
if(!marked[w]) {
edgeTo[w] = d;
distTo[w] = distTo[d] + 1;
marked[w] = true;
q.enqueue(w);
}
}
for(boolean x : marked) {
if(x == false) throw new RuntimeException("not a connected graph.");
}
}
return d;
}
You check for connectivity after processing each vertex. Only in the simplest graphs will the test succeed after the first vertex.
Instead you should seed the queue with one vertex and move the for loop testing for connectivity out of the while loop.
What's wrong with my recursion logic?
I'm trying to find the size of an m-ary tree. An MTree Node's children is represented by an ArrayList I implemented. My logic was to have a for loop as big as m so I could check every child.
public AnyType element;
public int m; // MTreeNode will have m children at most
public static ArrayList<MTreeNode> children;
public MTreeNode(AnyType element, int m, ArrayList<MTreeNode> children){
this.element = element;
this.m = m;
this.children = children;
public static int size(MTreeNode<?> t){
int nodes = 0;
if(t == null)
return 0;
else{
for(int i = 0; i < t.m; i++){
size(t.children.get(i));
}
return 1 + nodes;
}
}
I'm getting my error at
size(t.children.get(i));
I'm trying to learn Prim's algorithm and I'm using this website to do so, but I'm having trouble making the code part of it run. I'm confused with what goes in public static int Prims(Vector<Vector<node>> adjList) and how to get the code to compile and run. (New to java so excuse me if its a silly question).
edit: This is the code I'm trying to run:
class node implements Comparable<node> {
int weight, index;
public node(int weight, int index) {
this.weight = weight;
this.index = index;
}
public int compareTo(node e) {
return weight - e.weight;
}
}public static int Prims(Vector<Vector<node>> adjList) {
// Current cost of MST.
int cost = 0;
int n = adjList.size();
PriorityQueue<node> pq = new PriorityQueue<node>();
// Keep track if each node is visited.
boolean visited[] = new boolean[n];
for (int i = 0; i < n; i++) {
visited[i] = false;
}
// Number of nodes visited.
int inTree = 1;
// Mark starting node as visited.
visited[0] = true;
// Add all edges of starting node.
for (int i = 0; i < adjList.get(0).size(); i++) {
pq.add(adjList.get(0).get(i));
}
// Keep going until all nodes visited.
while (!pq.isEmpty() && inTree < n) {
// Get the edge with the smallest weight.
node cur = pq.poll();
// Skip if node already used.
if (visited[cur.index]) {
continue;
}
inTree++;
visited[cur.index] = true;
cost += cur.weight;
// Add all the edges of the new node to the priority queue.
for (int i = 0; i < adjList.get(cur.index).size(); i++) {
pq.add(adjList.get(cur.index).get(i));
}
}
// Graph not connected if number of nodes used is less than total nodes.
if (inTree < n) {
return -1;
}
return cost;
}
Your method public static int Prims(Vector<Vector<node>> adjList) does not appear to be a member of a class. It needs to be. The leading } on the line
}public static int Prims(Vector<Vector<node>> adjList) {
should probable be moved to the end of the file.
If you do not use an IDE to compile and run a code you need to issue the following commands:
javac MyCode.java
java MyCode
where I suppose your code resides in a file named MyCode.java and there is no package defined.
I had an assignment to create a Kruskal algorithm, which went fine there was a nice tutorial online, but I'm having difficulty trying to add the edges to all of my nodes with the assigned weights. Here is what I'm doing and hopefully you guys can help me out.
main function
public static void main(String[] args) {
int maximumVertices = 50;
Random ran = new Random();
Graph g = new Graph(maximumVertices);
for(int i=0; i<maximumVertices-1; i++){
int weight = ran.nextInt(50);
int connectedNode = ran.nextInt(10); //the idea here is to create random connections between nodes
g.addVertex(i);
g.addBidirectionalEdge(i, connectedNode, weight);
g.addBidirectionalEdge(i+1, connectedNode, weight);
System.out.println(Arrays.toString((g.getAdjacentVertexNumbers(i))));
}
Kruskal k = new Kruskal(g);
List<Edge> mst = k.getMSTEdges();
System.out.println ("Minimum Spanning Tree Edges are:");
ListIterator<Edge> it = mst.listIterator();
while(it.hasNext()){
Edge e = (Edge)it.next();
System.out.println ("v" + e.getFrom().getVertexNo() + " --- v" + e.getTo().getVertexNo());
}
Kruskal class
public class Kruskal {
private Graph graph;
private int[] sets; //represent set for vertices
public Kruskal(Graph g) {
this.graph = g;
this.sets = new int[g.getTotalNumberOfVertices()];
}
private void makeSet(Vertex v){
this.sets[v.getVertexNo()] = v.getVertexNo(); //simply set the set name to each vertex no
}
private int findSet(Vertex v){
return this.sets[v.getVertexNo()]; //gets the set name/number of a vertex
}
private void union(Vertex u, Vertex v){
int findWhat, replaceWith;
if(u.getVertexNo() < v.getVertexNo()){
findWhat = this.sets[v.getVertexNo()];
replaceWith = this.sets[u.getVertexNo()];
}
else{
findWhat = this.sets[u.getVertexNo()];
replaceWith = this.sets[v.getVertexNo()];
}
//make both sets same
for(int i=0; i<this.sets.length; i++){
if(this.sets[i] == findWhat){
this.sets[i] = replaceWith;
}
}
}
private void sortEdges(Edge[] edges){
for(int i=0; i<edges.length-1; i++){
for(int j=i+1; j<edges.length; j++){
if(edges[i].getWeight() > edges[j].getWeight()){
Edge tmp = edges[i];
edges[i] = edges[j];
edges[j] = tmp;
}
}
}
}
//runs the main kruskal algorithm
public List<Edge> getMSTEdges(){
//holds the MST edges
List<Edge> mstEdges = new ArrayList<Edge>();
Vertex[] vertices = this.graph.getVertices();
for(int i=0; i<vertices.length; i++){
this.makeSet(vertices[i]);
}
//get all bi-directional edges
Edge[] edges = this.graph.getAllBidirectionalEdges();
//sort the edges w.r.t their weights in non-decreasing order
this.sortEdges(edges);
for(int i=0; i<edges.length; i++){
//for each each, in sorted order
Edge e = edges[i];
if(this.findSet(e.getFrom()) != this.findSet(e.getTo())){
//if the vertices it connects are not in the same set
//this edge is an MST edge
mstEdges.add(e);
//now, both vertices should have same set
this.union(e.getFrom(), e.getTo());
}
}
return mstEdges;
}
}
Graph class
public class Graph {
private final int DEFAULT_EDGE_COST = 1;
private Vertex[] vertices = null; //list of all vertices in the graph
private int totalVertices = 0; //keeps count of vertices
private int[][] adjMatrix = null; //keeps the edges of the graph using adjacency matrix
private int[] adjacentVertCount = null; //keeps count of adjacent vertices for each vertex
public Graph(int maxVertices) {
this.vertices = new Vertex[maxVertices]; //initialize vertices array
this.adjMatrix = new int[maxVertices][maxVertices]; //initialize adjacency matrix
this.adjacentVertCount = new int[maxVertices]; //initialize adjacent vertices count
for(int i=0; i<maxVertices; i++){
this.adjacentVertCount[i] = 0; //set adjacent vertex count to 0 initially
for(int j=0; j<maxVertices; j++){
this.adjMatrix[i][j] = -1; //set adjacency list to -1 initially
}
}
}
public Graph(){
//default Max amount of vertices: 100 [0-99]
this(100);
}
//add a new vertex with vertexNo and data
public void addVertex(int vertexNo, Object data){
this.vertices[vertexNo] = new Vertex(vertexNo, data);
this.totalVertices++;
}
//add a new vertex with vertexNo only
public void addVertex(int vertexNo){
this.addVertex(vertexNo, null);
}
//add a uni-directional edge with cost
public void addEdge(int fromVertexNo, int toVertexNo, int cost){
this.adjMatrix[fromVertexNo][toVertexNo] = cost;
this.adjacentVertCount[fromVertexNo]++;
}
//add a bi-directional edge with cost
public void addBidirectionalEdge(int vertex1, int vertex2, int cost){
this.addEdge(vertex1, vertex2, cost);
this.addEdge(vertex2, vertex1, cost);
}
//add a bi-directional edge with cost
public void addBidirectionalEdge(Vertex v1, Vertex v2, int cost){
this.addBidirectionalEdge(v1.getVertexNo(), v2.getVertexNo(), cost);
}
//get the total vertices count in the graph
public int getTotalNumberOfVertices(){
return this.totalVertices;
}
//get adjacent vertex numbers for a given vertexNo
public int[] getAdjacentVertexNumbers(int vertexNo){
int[] ret = new int[this.adjacentVertCount[vertexNo]];
int index = 0;
for(int i=0; i<this.adjMatrix[vertexNo].length; i++){
if(this.adjMatrix[vertexNo][i] >= 0){
ret[index++] = i;
}
}
return ret;
}
//get adjacent vertex numbers for a given vertex
public int[] getAdjacentVertexNumbers(Vertex vert){
return this.getAdjacentVertexNumbers(vert.getVertexNo());
}
//get adjacent vertices for a given vertexNo
public Vertex[] getAdjacentVertices(int vertexNo){
Vertex[] ret = new Vertex[this.adjacentVertCount[vertexNo]];
int index = 0;
for(int i=0; i<this.adjMatrix[vertexNo].length; i++){
if(this.adjMatrix[vertexNo][i] >= 0){
ret[index++] = this.vertices[i];
}
}
return ret;
}
//get adjacent vertices for a given vertex
public Vertex[] getAdjacentVertices(Vertex vert){
return this.getAdjacentVertices(vert.getVertexNo());
}
//gets the edge/path cost from adjacency list for two given vertexNo
public int getEdgeCost(int fromVertNo, int toVertNo){
return this.adjMatrix[fromVertNo][toVertNo];
}
//gets the edge/path cost from adjacency list for two given vertices
public int getEdgeCost(Vertex fromVert, Vertex toVert){
return this.getEdgeCost(fromVert.getVertexNo(), toVert.getVertexNo());
}
//gets all vertices
public Vertex[] getVertices(){
return this.vertices;
}
//returns all the edges of the graph
//needed for edge traversing algorithms
public Edge[] getAllEdges(){
int totalEdges = 0;
for(int i=0; i<this.adjacentVertCount.length; i++){
totalEdges += this.adjacentVertCount[i];
}
Edge[] edges = new Edge[totalEdges];
int index = 0;
for(int i=0; i<this.vertices.length; i++){
for(int j=0; j<this.vertices.length; j++){
if(this.adjMatrix[i][j] >= 0){
edges[index++] = new Edge(this.vertices[i], this.vertices[j], this.adjMatrix[i][j]);
}
}
}
return edges;
}
public Edge[] getAllBidirectionalEdges(){
int totalEdges = 0;
for(int i=0; i<this.adjacentVertCount.length; i++){
totalEdges += this.adjacentVertCount[i];
}
totalEdges /= 2;
Edge[] edges = new Edge[totalEdges];
int index = 0;
for(int i=0; i<this.vertices.length; i++){
for(int j=i+1; j<this.vertices.length; j++){
if(this.adjMatrix[i][j] >= 0){
edges[index++] = new Edge(this.vertices[i], this.vertices[j], this.adjMatrix[i][j]);
}
}
}
return edges;
}
}
Error:
Exception in thread "main" java.lang.NullPointerException
at Kruskal.makeSet(Kruskal.java:15)
at Kruskal.getMSTEdges(Kruskal.java:62)
at Main.main(Main.java:51)
I get the edges to print out nicely however when I implement the k.getMSTEdges() if gives me null pointers and doesn't like it.
However when I hardcode it, for example g.addBidrectionalEdge(0,2,8) and so on it works so I know its something about the main here that I'm not right on. Thanks again for all your help!
This seems to be your problem:
for(int i=0; i<maximumVertices-1; i++)
Change it to
for(int i=0; i<maximumVertices; i++)
This is from where you create your graph.
Otherwise, you only create 49 vertices, and then when you try to access the 50th one, there is NULL data. Or at least, I'm assuming that Vertex initializes some data to NULL
I have implemented a one point crossover as follows;
public void onePointCrossover(Individual indi) {
if (SGA.rand.nextDouble() < pc) {
int xoverpoint = SGA.rand.nextInt(length);
int tmp;
for (int i=xoverpoint; i<length; i++){
tmp = chromosome[i];
chromosome[i] = indi.chromosome[i];
indi.chromosome[i] = tmp;
}
}
}
One point crossover - crossover point is selected, binary string from beginning of chromosome to the crossover point is copied from one parent, the rest is copied from the second parent.
Parent 1 = chromosome and Parent 2 = indi.
I am turning the parents into children inplace.
I now need to also do a two point crossover but having some trouble, this is what I have so far but I believe the bottom half of the code is doing the same thing as a one point crossover rather than swapping the middle sections.
public void twoPointCrossover(Individual indi) {
if (SGA.rand.nextDouble() < pc) {
int xoverpoint = SGA.rand.nextInt(length);
int xoverpoint2 = SGA.rand.nextInt(length);
int tmp;
if (xoverpoint > xoverpoint2){
tmp = xoverpoint;
xoverpoint = xoverpoint2;
xoverpoint2 = tmp;
}
for (int i=xoverpoint; i<xoverpoint2; i++){
tmp = chromosome[i];
chromosome[i] = indi.chromosome[i];
indi.chromosome[i] = tmp;
}
}
}
}
This does not seem right and any help will be appreciated so much! Thanks!
You should check for i < (or <=) xoverpoint2 rather than i<length in the loop.
I'm working on the same problem now. Here is my solution:
// Two-Point Crossover function
public Genome twoPtCrossover(Genome partner) {
Genome child = new Genome(partner.genome.length);
int crosspoint1 = xd.nextInt(genome.length);
int crosspoint2 = xd.nextInt(genome.length);
// Ensure crosspoints are different...
if (crosspoint1 == crosspoint2){
if(crosspoint1 == 0){
crosspoint2++;
} else {
crosspoint1--;
}
}
// .. and crosspoint1 is lower than crosspoint2
if (crosspoint2 < crosspoint1) {
int temp = crosspoint1;
crosspoint1 = crosspoint2;
crosspoint2 = temp;
}
for (int i = 0; i < genome.length; i++) {
if (i < crosspoint1 || i > crosspoint2)
child.genome[i] = genome[i];
else
child.genome[i] = partner.genome[i];
}
return child;
}