I am developing a game in LWJGL. I have an item pickup code to add an item to the player's inventory, but whenever I call it, it adds the item to the slot (x) and the slot after slot (x). (x meaning any random number) I was hoping I could have some help debugging it.
The class add method is being called in:
package geniushour.gameobject.entity;
import static org.lwjgl.input.Keyboard.KEY_A;
import static org.lwjgl.input.Keyboard.KEY_D;
import static org.lwjgl.input.Keyboard.KEY_P;
import static org.lwjgl.input.Keyboard.KEY_SPACE;
import static org.lwjgl.input.Keyboard.isKeyDown;
import java.util.ArrayList;
import java.util.Random;
import geniushour.engine.Physics;
import geniushour.engine.time.Delay;
import geniushour.engine.time.Time;
import geniushour.game.Game;
import geniushour.game.Util;
import geniushour.game.type.ArmorType;
import geniushour.game.type.ClawType;
import geniushour.game.type.EntityType;
import geniushour.gameobject.GameObject;
import geniushour.gameobject.StatObject;
import geniushour.gameobject.item.Backpack;
import geniushour.gameobject.item.Item;
public class Player extends StatObject {
private Delay delay;
private boolean collide = false;
private int facingDirection = 0;
private int firstFree = 0;
private Random damageRandom;
private final int NORTH = 0;
private final int EAST = 1;
private final int SOUTH = 2;
private final int WEST = 3;
public Player(float x, float y){
super(true,0,6);
init(x,y,ENTITY_SIZE,ENTITY_SIZE,0.25f,1f,.25f,EntityType.PLAYER_ID.getID());
deleteBackpack();
setClaw(ClawType.BASIC);
setArmorType(ArmorType.SKIN);
setStrength(1, claw);
delay = new Delay(500); delay.terminate();
}
public void update(){
ArrayList<GameObject> items = Game.rectCollide(x, y, x+ENTITY_SIZE, y+ENTITY_SIZE);
for(GameObject go : items){
if(go.getType() == EntityType.ITEM_ID.getID()){
go.remove();
inv.add ((Item)go);
}
}
ArrayList<GameObject> wall = Game.rectCollide(x, y, x+ENTITY_SIZE, y+ENTITY_SIZE);
for(GameObject go : wall){
if(go.getType() == EntityType.BLOCK_ID.getID()){
if(Physics.checkCollision(this, go) != null){
collide = true;
}
else if(Physics.checkCollision(this, go) == null){
collide = false;
}
}
if(collide){
if(this.facingDirection == WEST){
move(1,0);
collide = false;
}
else if(this.facingDirection == EAST){
move(-1,0);
collide = false;
}
}
}
if(getCurrentHealth() <= 0){
addHP(-getCurrentHealth());
deleteBackpack(); //TODO: Backpack temp or not?
}
for(int i = 0; i < inv.getLength(); i++){
if(inv.get( i ) instanceof Backpack){
ownBackpack();
inv.remove(i);
inv.setSlots(27);
}
}
}
outputData(true);
}
public void getInput(){
if(!collide){
if(isKeyDown(KEY_A)){
move(-1,0);
}
if(isKeyDown(KEY_D)){
move(1,0);
}
if(isKeyDown(KEY_SPACE) && delay.over()){
attack();
}
if(isKeyDown(KEY_P)){
}
}
}
private void move(int magX, int magY){
if(magX == 1){
facingDirection = EAST;
}
if(magX == -1){
facingDirection = WEST;
}
x += getSpeed(armor) * magX * Time.getDelta();
y += getSpeed(armor) * magY * Time.getDelta();
}
private void attack(){
//Find GameObjects in Attack Range
ArrayList<GameObject> obj = new ArrayList<GameObject>();
switch(facingDirection){
case NORTH: obj = Game.rectCollide(x, y, x + ENTITY_SIZE, y + getCloseAttackRange());
break;
case EAST: obj = Game.rectCollide(x, y, x + getCloseAttackRange(), y + ENTITY_SIZE);
break;
case SOUTH: obj = Game.rectCollide(x, y - getCloseAttackRange() + ENTITY_SIZE, x + ENTITY_SIZE, y);
break;
case WEST: obj = Game.rectCollide(x - getCloseAttackRange() + ENTITY_SIZE, y, x, y + ENTITY_SIZE);
break;
}
//Find which GOs are Enemy Type
ArrayList<Enemy> enemies = new ArrayList<Enemy>();
for(GameObject go : obj){
if(go.getType() == EntityType.ENEMY_ID.getID()){
enemies.add((Enemy)go);
}
}
//Find closest existing enemy
if(enemies.size() > 0){
Enemy target = enemies.get(0);
if(enemies.size() > 1){
for(Enemy e : enemies){
if(Util.dist(x, y, e.getX(), e.getY()) < Util.dist(x, y, target.getX(), target.getY())){
target = e;
}
}
}
damageRandom = new Random();
double e = Math.pow(getStrength(claw), (Math.cbrt(damageRandom.nextInt(15)) + 1)) / (Math.sqrt(getStrength(claw) + 1));
target.damage((int) Math.round(e));
Util.writeLine(" : " + target.getCurrentHealth() + "/" + target.getMaxHP());
if(target.getCurrentHealth() <= 0){
addXP(100);
}
}
delay.start();
}
private void outputData(boolean ask){
if(ask){
for(int i = 0; i < inv.getLength(); i++){
Util.writeLine("Main Inv Slot "+i+": " + inv.get(i));
}
Util.writeLine("");
Util.writeLine("Backpack Owned: " + getBackpack());
Util.writeLine("");
Util.writeLine("Inventory Size: " + inv.getLength());
Util.writeLine("");
Util.writeLine("Health: "+getCurrentHealth());
Util.writeLine("");
Util.writeLine("End of Information Output");
}
}
}
The Class add() is defined in:
package geniushour.game.inventory;
import geniushour.game.Util;
import geniushour.gameobject.item.Item;
public class Inventory {
private Item[] items;
private int firstFree;
public Inventory(int size){
items = new Item[size];
firstFree = 0;
}
public boolean add(Item item){
for(int i = 0; i < items.length; i++){
if(get(i) == null){
firstFree = i;
break;
}
}
Util.writeLine(firstFree);
if(add(item, firstFree)){
firstFree++;
if(firstFree > items.length){
firstFree = items.length;
}
return true;
}
return false;
}
public boolean add(Item item, int index){
if(items[index] == null && index <= items.length){ // != or == ?
items[index] = item;
return true;
}
else{
return false;
}
}
public Item get(int index){
return items[index];
}
public void remove(int index){
items[index] = null;
if(index < firstFree){
firstFree = index;
}
if(firstFree < 0){
firstFree = 0;
}
}
public void remove(Item item){
for(int i = 0; i < items.length; i++){
if(items[i] == item){
remove(i);
return;
}
}
}
public Item[] getItemList(){
return items;
}
public int getLength(){
return items.length;
}
public void setSlots(int amt){
Item[] temp = new Item[items.length];
for(int i = 0; i < items.length; i++){
temp[i] = items[i];
}
items = new Item[amt];
for(int i = 0; i < temp.length; i++){
items[i] = temp[i];
}
temp = new Item[items.length];
}
}
Related
This question already has answers here:
What does "Could not find or load main class" mean?
(61 answers)
Closed 2 years ago.
I've been working on a project recently and I have come to the end of my compilation, moving out of Eclipse and into cmd. I have a single .java names PA3 containing multiple classes.
My task is to compile the program with:
javac PA3.java
And to run the program with the command:
java PA3 test.dat
where test.dat is a placeholder (no need to worry about that)
When I compile, all the classes compile properly as shown:
here
All I seem to run into is issues regarding
Error: Could not find or load main class PA3
Caused by: java.lang.ClassNotFoundException: PA3
And my code is below:
(Mind you it is messy and a little over the place at the moment)
'''
import linkedlist.MyPolygons;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PA3
{
//================================MAIN================================//
public static void main(String[] args)
{
MyPolygons.main(args);
};
}
class MyPolygons{
//================================MAIN================================//
public static void main(String[] args)
{
MyPolygons poly = Import(new ExtendedFile("src\\linkedlist\\text.txt"));
poly.display();
}
//Represent a node of the doubly linked list
class Node{
PlanarShape data;
String type;
Node previous;
Node next;
public Node(PlanarShape data, String type) {
this.data = data;
this.type = type;
}
}
//Represent the head and tail of the doubly linked list
Node head, tail = null;
public void sort()
{
Node current = head;
boolean changed = true;
while(changed)
{
changed = false;
Node next;
for(int i = 0; i < 50; i++)
{
current = head;
while((next = current.next) != null)
{
if(current.data.getArea(current.type) > next.data.getArea(next.type))
{
//System.out.println("Current.data: " + current.data.getArea(current.type) + " Next.data: " + next.data.getArea(next.type));
PlanarShape temp;
temp = current.data;
current.data = next.data;
next.data = temp;
String temps;
temps = current.type;
current.type = next.type;
next.type = temps;
current = next;
}
current = next;
}
}
}
}
//addNode() will add a node to the list
public void addNode(PlanarShape data, String type) {
//Create a new node
Node newNode = new Node(data, type);
//If list is empty
if(head == null) {
//Both head and tail will point to newNode
head = tail = newNode;
//head's previous will point to null
head.previous = null;
//tail's next will point to null, as it is the last node of the list
tail.next = null;
}
else {
//newNode will be added after tail such that tail's next will point to newNode
tail.next = newNode;
//newNode's previous will point to tail
newNode.previous = tail;
//newNode will become new tail
tail = newNode;
//As it is last node, tail's next will point to null
tail.next = null;
}
}
//display() will print out the nodes of the list
public void display()
{
//Node current will point to head
Node current = head;
if(head == null)
{
System.out.println("List is empty");
return;
}
System.out.println("Nodes of a Double linked list: ");
System.out.println("Unsorted List: ");
while(current != null)
{
System.out.print(current.type);
System.out.print("[");
//Prints each node by incrementing the pointer.
System.out.print(current.data);
if (current.type == "CIRC= ")
{
System.out.print(", ");
System.out.print(getRad());
}
System.out.println(String.format("]: %.2f", current.data.getArea(current.type)));
current = current.next;
}
sort();
System.out.println("Sorted List: ");
current = head;
while(current != null)
{
System.out.print(current.type);
System.out.print("[");
//Prints each node by incrementing the pointer.
System.out.print(current.data);
if (current.type == "CIRC= ")
{
System.out.print(", ");
System.out.print(PlanarShape.returnRadius());
}
System.out.println(String.format("]: %.2f", current.data.getArea(current.type)));
//System.out.println(current.data.originDistance());
current = current.next;
}
}
static float radius;
static float vertlength;
static PlanarShape PlanarShape = new PlanarShape();
public static MyPolygons Import(ExtendedFile f)
{
String[] lines = f.readLines();
MyPolygons poly = new MyPolygons();
for (int i = 0; i < lines.length; i++)
{
PlanarShape PlanarShape = new PlanarShape();
String[] array = lines[i].split(" ");
String shapetype = array[0];
switch(shapetype)
{
case "P":
for(int k = 2; k < array.length-1; k++)
{
float x = Float.parseFloat(array[k]);
k++;
float y = Float.parseFloat(array[k]);
PlanarShape.addVerticy(new Point(x, y));
vertlength = ((array.length-2)/2);
}
//Add nodes to the list
poly.addNode(PlanarShape, "POLY= ");
break;
case "C":
for(int k = 1; k < array.length-1; k++)
{
PlanarShape.addRadius(Float.parseFloat(array[array.length-1]));
float x = Float.parseFloat(array[k]);
k++;
float y = Float.parseFloat(array[k]);
PlanarShape.addVerticy(new Point(x, y));
}
poly.addNode(PlanarShape, "CIRC= ");
break;
case "S":
for(int k = 1; k < array.length-1; k++)
{
float x = Float.parseFloat(array[k]);
k++;
float y = Float.parseFloat(array[k]);
PlanarShape.addVerticy(new Point(x, y));
}
//Add nodes to the list
poly.addNode(PlanarShape, "SEMI= ");
break;
}
}
return poly;
}
public float getRad()
{
return PlanarShape.returnRadius();
}
public float getLength()
{
return vertlength;
}
}
#SuppressWarnings("serial")
class ExtendedFile extends File
{
public ExtendedFile(String pathname) {
super(pathname);
}
public String[] readLines()
{
try
{
FileReader fr = new FileReader(this);
BufferedReader br = new BufferedReader(fr);
Object[] buffer = br.lines().toArray();
String[] lines = Arrays.copyOf(buffer, buffer.length, String[].class);
fr.close(); br.close();
return lines ;
}
catch (IOException e)
{
return new String[0];
}
}
}
class Point
{
float x;
float y;
Point(float ex, float why)
{
x = ex;
y = why;
}
public String toString()
{
return String.format("(%.2f , %.2f)", x, y);
}
public float getX()
{
return x;
}
public float getY()
{
return y;
}
public double dto()
{
return Math.sqrt(Math.pow(x, 2)+Math.pow(y, 2));
}
}
class PlanarShape
{
List < Point > verticies = new ArrayList < Point > ();
float radius;
public void addRadius(float rad)
{
radius = rad;
}
public float returnRadius()
{
return radius;
}
public void addVerticy(Point toAdd)
{
verticies.add(toAdd);
}
public String toString()
{
String buffer = "";
for (int i = 0; i < verticies.size(); i++)
{
buffer += verticies.get(i).toString();
}
return buffer;
}
public Point[] getVerticies()
{
Object[] buffer = verticies.toArray();
return Arrays.copyOf(buffer, buffer.length, Point[].class);
}
public float polyarea;
public float circarea;
public float semiarea;
public float getArea(String type)
{
float area = 0;
switch(type)
{
case "POLY= ":
{
for(int n = 0; n < verticies.size(); n++)
{
area += verticies.get(n).getY()*verticies.get(n == verticies.size()-1?0:n+1).getX() - verticies.get(n).getX()*verticies.get(n == verticies.size()-1?0:n+1).getY();
}
if(area < 0)
{
area = -area;
}
area /= 2;
polyarea = area;
break;
}
case "CIRC= ":
{
float pi = 3.14159265359F;
float radius = returnRadius();
area = pi * radius * radius;
if(area < 0)
{
area = -area;
}
circarea = area;
break;
}
case "SEMI= ":
{
float x0 = verticies.get(0).getX();
float y0 = verticies.get(0).getY();
float x1 = verticies.get(1).getX();
float y1 = verticies.get(1).getY();
float y0y1;
if ((y0 - y1) < 0)
{
y0y1 = -(y0 - y1);
}
else
{
y0y1 = (y0 - y1);
}
float x0x1;
if ((x0 - x1) < 0)
{
x0x1 = -(x0 - x1);
}
else
{
x0x1 = (x0 - x1);
}
float x2 = x0 - y0y1;
float x3 = x0 + y0y1;
float y2 = y0 + x0x1;
float y3 = y0 - x0x1;
double diam = Math.sqrt((Math.pow((x2-x3), 2)) + ((Math.pow((y3 - y2), 2))));
float radius2 = ((float)diam)/2;
float pi = 3.14159265359F;
area = (pi * radius2 * radius2)/2;
if(area < 0)
{
area = -area;
}
break;
}
}
return area;
}
public float returnArea(String type)
{
switch(type)
{
case("POLY= "):
{
return polyarea;
}
case("CIRC= "):
{
return circarea;
}
case("SEMI= "):
{
return semiarea;
}
}
return 0;
}
}
class SemiCircle
{
List < Point > verticies = new ArrayList < Point > ();
public void addVerticy(Point toAdd)
{
verticies.add(toAdd);
}
public String toString()
{
String buffer = "";
for (int i = 0; i < verticies.size(); i++)
{
buffer += verticies.get(i).toString();
}
return buffer;
}
public Point[] getVerticies()
{
Object[] buffer = verticies.toArray();
return Arrays.copyOf(buffer, buffer.length, Point[].class);
}
public float getArea()
{
float area = 0;
for(int n = 0; n < verticies.size(); n++)
{
area += verticies.get(n).getY()*verticies.get(n == verticies.size()-1?0:n+1).getX() - verticies.get(n).getX()*verticies.get(n == verticies.size()-1?0:n+1).getY();
}
return area;
}
public double originDistance()
{
double distance;
distance = Math.sqrt((Math.pow((verticies.get(1).getX()),2))+(Math.pow((verticies.get(1).getY()),2)));
System.out.println(distance);
return distance;
}
}
class Polygon
{
List < Point > verticies = new ArrayList < Point > ();
public void addVerticy(Point toAdd)
{
verticies.add(toAdd);
}
public String toString()
{
String buffer = "";
for (int i = 0; i < verticies.size(); i++)
{
buffer += verticies.get(i).toString();
}
return buffer;
}
public Point[] getVerticies()
{
Object[] buffer = verticies.toArray();
return Arrays.copyOf(buffer, buffer.length, Point[].class);
}
public float getArea()
{
float area = 0;
for(int n = 0; n < verticies.size(); n++)
{
area += verticies.get(n).getY()*verticies.get(n == verticies.size()-1?0:n+1).getX() - verticies.get(n).getX()*verticies.get(n == verticies.size()-1?0:n+1).getY();
}
if(area < 0)
{
area = -area;
}
area /= 2;
return area;
}
public double originDistance()
{
double distance = Math.sqrt(Math.pow((verticies.get(1).getX()), 2)+Math.pow((verticies.get(1).getY()), 2));
System.out.println(distance);
return distance;
}
}
class Circle
{
List < Point > verticies = new ArrayList < Point > ();
public void addVerticy(Point toAdd)
{
verticies.add(toAdd);
}
public String toString()
{
String buffer = "";
for (int i = 0; i < verticies.size(); i++)
{
buffer += verticies.get(i).toString();
}
return buffer;
}
public Point[] getVerticies()
{
Object[] buffer = verticies.toArray();
return Arrays.copyOf(buffer, buffer.length, Point[].class);
}
public float getArea()
{
float pi = 3.14159265359F;
MyPolygons polygon = new MyPolygons();
float radius = polygon.getRad();
float area = 0;
area = pi * radius * radius;
if(area < 0)
{
area = -area;
}
return area;
}
public double originDistance()
{
double distance;
distance = Math.sqrt((Math.pow((verticies.get(0).getX()),2))+(Math.pow((verticies.get(0).getY()),2)));
System.out.println(distance);
return distance;
}
}
Edit: Removing the 'linkedlist.package' and pulling the .java and .text files, they still retain the same error when compiling and running
If you want to run files that are in a package, make sure all your java files that are part of the package are in a folder named the package name (i.e. linkedlist).
Then, in the directory outside your package folder, do:
javac linkedlist/*.java
java linkedlist.PA3
Trying to create a program that takes an image of a maze and outputs the maze with a highlighted solution but my implementation of A* is flawed.
I'm basing the algorithm on Wikipedia's pseudocode and Coding Train's implementation which is the inspiration for this project. I've compared the code for the algorithm and didn't notice anything out of the ordinary.
public class Main {
public static void main(String[] args) {
ImageConverter a = new ImageConverter("file path");
Node[][] nodes = a.to2Darray();
Solver solve = new Solver(nodes);
ArrayList<Node> solution = solve.aStar(new Node(0,1, 0),new Node(14,13,0));
System.out.println(solution);
a.toImage(nodes, solution);
}
}
public class Solver {
private Node[][] graph;
public Solver(Node[][] graph) {
this.graph = graph;
}
public ArrayList<Node> aStar(Node start, Node finish){ // solves maze using A*
ArrayList<Node> closeSet = new ArrayList<>();
ArrayList<Node> openSet = new ArrayList<>();
openSet.add(start);
ArrayList<Node> path = new ArrayList<>();
while (openSet.size()>0){
int bestF = 0;
for (int i = 0; i < openSet.size(); i++){ // find next least costly node
if (openSet.get(i).getF() < openSet.get(bestF).getF()){
bestF = i;
}
}
Node current = openSet.get(bestF);
if (current.equals(finish)){ // check if current node is end node
Node temp = current;
path.add(temp);
while(temp.getPrevious()!=null){
path.add(temp.getPrevious());
temp = temp.getPrevious();
}
return path;
}
openSet.remove(current);
closeSet.add(current);
ArrayList<Node> neighbors = current.getNeighbors();
for (int i = 0; i < neighbors.size(); i++){ // check neighbors
Node n = neighbors.get(i);
boolean isNewPath = false;
if (!closeSet.contains(n) && n.getState()!=1){
double tempG = current.getG()+heuristic(n,current);
if (openSet.contains(n)){
if (tempG < n.getG()){
n.setG(tempG);
isNewPath = true;
}
else{
n.setG(tempG);
openSet.add(n);
isNewPath = true;
}
}
if (isNewPath) {
n.setH(heuristic(n, finish));
n.setF(n.getG() + n.getH());
n.setPrevious(current);
}
}
}
}
return null; // no solution
}
private static double heuristic(Node end, Node finish) {
int y1 = end.getCol();
int x1 = end.getRow();
int y2 = finish.getCol();
int x2 = finish.getRow();
return Math.sqrt((x1-x2)*(x1-x2)+(y2-y1)*(y2-y1)); // order doesn't matter in because of squaring
}
}
public class Node {
private double f, g, h;
private int row, col; // row and col
private int state;
private ArrayList<Node> neighbors = new ArrayList<>();
private Node previous = null;
public Node(int r, int c, int state) {
this.state = state;
row = r;
col = c;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public double getF() {
return f;
}
public double getG() {
return g;
}
public double getH() {
return h;
}
public void setF(double f) {
this.f = f;
}
public void setG(double g) {
this.g = g;
}
public void setH(double h) {
this.h = h;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public void addNeighbor(Node b){
neighbors.add(b);
}
public void setPrevious(Node n){
previous = n;
}
public Node getPrevious(){
return previous;
}
#Override
public String toString(){
return "["+row+"]["+col+"]";
}
public ArrayList<Node> getNeighbors(){
return neighbors;
}
#Override
public boolean equals(Object o){
if (o ==this){
return true;
}
if (!(o instanceof Node)){
return false;
}
Node n = (Node) o;
return row == n.getRow() && col==n.getRow();
}
}
public class ImageConverter {
private BufferedImage image;
private int x;
private int y;
private String path;
public ImageConverter(String path) {
try {
image = ImageIO.read(new FileInputStream(path));
}
catch (IOException e) {
e.printStackTrace();
}
this.path = path;
this.x = image.getWidth(); // done for readability of to2Darray()
this.y = image.getHeight();
}
public Node[][] to2Darray() { // nested loop does [j][i] as [i][j] reflects along line from top left to bot right
Node[][] nodes = new Node[x][y];
for (int i = 0; i < nodes.length; i++){ // inital assignment/null pointer
for (int j = 0; j < nodes.length; j++){
nodes[i][j] = new Node(i,j,0); // the [j][i] thing doesn't matter here
}
}
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
Color t = new Color(image.getRGB(i, j));
if (t.equals(Color.BLACK)) {
nodes[j][i].setState(1); //black pixels are walls
}
else if (t.equals(Color.WHITE)) {
nodes[j][i].setState(0); //white pixels are paths
}
else { // is not black or white
try {
throw new Exception("Pixel at [" + i + "][" + j + "]" + " is not black or white");
}
catch (Exception e) {
System.out.println("Java threw an exception while throwing an exception. God help you" +
" if you ever see this. But if you do, there might be a pixel in the maze that is not b/w");
}
}
}
}
for (int row = 0; row < x; row++){ // add neighbors, if neighbor does not exist (out of bounds) it makes it null
for (int col = 0; col < y; col++){
try{
nodes[row][col].addNeighbor(nodes[row-1][col]); // Node to the top
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row][col+1]); // Node to the right
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row+1][col]); // Node to the bottom
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
try{
nodes[row][col].addNeighbor(nodes[row][col-1]); // Node to the left
}
catch (IndexOutOfBoundsException e){
nodes[row][col].addNeighbor(null);
}
}
}
return nodes;
}
public void toImage(Node[][] graph, ArrayList<Node> solution) { // converts to image and saves it at location from constructor
BufferedImage imageCopy = this.image;
int index = path.lastIndexOf("\\"); // change this to \\ if on Windows
File file = new File(path.substring(0, index) + "\\solved.png"); // remove the filename from filepath
final int RED = new Color(255, 0, 0).getRGB(); // for readability
final int BLACK = new Color(0, 0, 0).getRGB();
final int WHITE = new Color(255, 255, 255).getRGB();
/*for (int i = 0; i < x; i++) { // convert to BufferedImage
for (int j = 0; j < y; j++) {
if (graph[i][j].getState() == 0) { // empty path
image.setRGB(j, i, WHITE);
}
else if (graph[i][j].getState() == 1) { // wall
image.setRGB(j, i, BLACK);
}
if
}
}*/
for (int i = 0; i < x; i++) { // convert to BufferedImage
for (int j = 0; j < y; j++) {
System.out.println(i+" "+j);
if (solution.contains(graph[j][i])){
imageCopy.setRGB(i,j,RED);
}
}
}
try {
ImageIO.write(image, "png", file);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
In Main, solution should have an ArrayList<Node> of the Node objects that create the best path, however it returns null showing that it doesn't find a solution.
There is an error in the Node.equals() method:
return row == n.getRow() && col==n.getRow();
Should be
return row == n.getRow() && col==n.getCol();
Maybe that is the problem.
I'm trying to implement a rush hour solving algorithm using breadth first search to traverse a graph of the different paths, stopping when a solution has been found.
After numerous tests, I've come across a problem I have no idea how to solve. When there is a solution, the algorithm works very well, but when none can be found, it just endlessly cycles because it recreates "nodes" that contain the same information as older ones, instead of returning towards the older ones if the information is the same. How would I be able to make it stop when it figures out there are no more possibilities?
Here are the classes I am using for the solver:
This is the main class RushHour, the one I run.
package rush.hour;
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class RushHour
{
public static void main(String[] args)
{
String fileName = "Parking.txt";
String line;
int lineNumber = 0;
int numOfCars;
List<Car> carsList = new ArrayList<>();
try
{
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null)
{
lineNumber += 1;
// System.out.println(lineNumber);
System.out.println(line);
if (lineNumber == 15)
numOfCars = Integer.parseInt(
line.substring(line.length() - 1)) + 1;
if (lineNumber >= 17)
{
String[] splitLine = line.split(":");
char[] coordinates = splitLine[1].toCharArray();
int a = coordinates[3] - 48;
int b = coordinates[5] - 48;
int c = coordinates[10] - 48;
int d = coordinates[12] - 48;
Car car = new Car(lineNumber - 17, a, b, c, d);
carsList.add(car);
}
}
Parking parking = new Parking(carsList);
Graph graph = new Graph(parking);
List<Parking> sol = graph.bfs();
System.out.println("\n------------- Solution -------------");
for (Parking sols: sol)
{ // L = Left, D = Down, R = Right, U = Up
System.out.println(sols);
}
}
catch(FileNotFoundException ex)
{ex.printStackTrace();}
catch(IOException ex)
{ex.printStackTrace();}
}
}
And this is the "graph" that uses the adapted BFS
package rush.hour;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.util.Queue;
public class Graph
{
Parking posDepart;
public Graph(Parking parking)
{
posDepart = parking;
}
public List<Parking> bfs()
{
List<Parking> res = new ArrayList<>();
Queue<Parking> queue = new LinkedList<>();
queue.add(posDepart);
while (!queue.isEmpty())
{
Parking next = queue.remove();
if (next.isFinal())
{
res.add(next);
return next.getPath();
}
next.setChildren();
for (Parking child : next.children) {
queue.add(child);
}
}
return res;
}
}
This is the Graph's "node", it represents the disposition of the cars on the board
package rush.hour;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Parking
{
Parking father = null;
List<Car> carsList = new ArrayList<>();
boolean visited = false;
List<Parking> children = new ArrayList<>();
List<Character> move = new ArrayList<>();
public Parking(List<Car> list)
{
for (Car car: list)
carsList.add(car.clone());
}
public Parking(Parking vader,List<Character> mov)
{
for (Car car: vader.carsList)
carsList.add(car.clone());
father = vader;
move = mov;
}
public void getNextParkings(List<List<Character>> moves)
{
children.clear();
for (int i = 0; i < moves.size(); ++i)
{
List<Character> info = moves.get(i);
Parking nextParking = new Parking(this, info);
nextParking.carsList.get(info.get(0) - 48).move(info.get(1));
children.add(nextParking);
}
}
#Override
public String toString()
{
String res = "";
if (!move.isEmpty())
{
res += "Move made to reach this parking:";
res += move;
res += "\n";
}
for (Car car : carsList)
res += car.toString();
return res;
}
public boolean isFinal()
{
return carsList.get(0).isFinal();
}
public void setChildren()
{
if (children.isEmpty())
{
List<List<Character>> moves = getPossibleMoves();
getNextParkings(moves);
}
}
public List<List<Character>> getPossibleMoves()
{
List<List<Character>> res = new ArrayList<>();
List<List<Character>> moves;
for (Car car : carsList)
{
moves = car.getPossibleMoves();
for (int i = 0; i < moves.size(); ++i)
{
List<Character> move = moves.get(i);
if (!hasNeighbour(move.get(0),
move.get(1) - 48, move.get(2) - 48))
{
List<Character> foo = new ArrayList<>(2);
foo.add(car.getNumber());
foo.add(move.get(0));
res.add(foo);
}
}
}
return res;
}
public boolean hasNeighbour(char direction, int x, int y)
{
for (Car car : carsList)
{
if (direction == 'U')
if ((car.getX1() == x - 1 && car.getY1() == y) ||
(car.getX2() == x - 1 && car.getY2() == y))
return true;
if (direction == 'D')
if ((car.getX1() == x + 1 && car.getY1() == y) ||
(car.getX2() == x + 1 && car.getY2() == y))
return true;
if (direction == 'L')
if ((car.getX1() == x && car.getY1() == y - 1) ||
(car.getX2() == x && car.getY2() == y - 1))
return true;
if (direction == 'R')
if ((car.getX1() == x && car.getY1() == y + 1) ||
(car.getX2() == x && car.getY2() == y + 1))
return true;
}
return false;
}
public List<Parking> getPath()
{
Parking temp_father;
List<Parking> path = new LinkedList<>();
path.add(this);
temp_father = this.father;
while (temp_father != null)
{
path.add(0, temp_father);
temp_father = temp_father.father;
}
return path;
}
}
And finally the Car class, which probably isn't very important to the problem but still
package rush.hour;
import java.util.List;
import java.util.ArrayList;
public class Car
{
char orientation;
int carNumber;
int x1;
int x2;
int y1;
int y2;
#Override
public String toString()
{
return "Car n° : " + (carNumber) + " : [(" + (x1) + ", " + y1 + ')' +
" (" + (x2) + ", " + y2 + ")]" + "\n";
}
public Car clone()
{
Car c = new Car(carNumber, x1, y1, x2, y2);
return c;
}
public Car(int n, int a, int b, int c, int d)
{
carNumber = n;
if (a <= c)
{
x1 = a;
x2 = c;
}
else
{
x1 = c;
x2 = a;
}
if (b <= d)
{
y1 = b;
y2 = d;
}
else
{
y1 = d;
y2 = b;
}
if (x1 == x2)
orientation = 'H';
else
orientation = 'V';
}
public char getNumber()
{
return Integer.toString(carNumber).charAt(0);
}
public int getX1()
{
return x1;
}
public int getX2()
{
return x2;
}
public int getY1()
{
return y1;
}
public int getY2()
{
return y2;
}
public void move(char direction)
{
if (direction == 'U')
{
--x1;
--x2;
}
if (direction == 'D')
{
++x1;
++x2;
}
if (direction == 'L')
{
--y1;
--y2;
}
if (direction == 'R')
{
++y1;
++y2;
}
}
public boolean isFinal()
{
return y2 == 4 && carNumber == 0;
}
public List<List<Character>> getPossibleMoves()
{
List<List<Character>> res = new ArrayList<>();
if (orientation == 'H')
{
if (y1 != 0)
{
List<Character> foo = new ArrayList<>(2);
foo.add('L');
foo.add(Integer.toString(x1).charAt(0));
foo.add(Integer.toString(y1).charAt(0));
res.add(foo);
}
if (y2 != 4)
{
List<Character> foo = new ArrayList<>(2);
foo.add('R');
foo.add(Integer.toString(x2).charAt(0));
foo.add(Integer.toString(y2).charAt(0));
res.add(foo);
}
}
else
{
if (x1 != 0)
{
List<Character> foo = new ArrayList<>(2);
foo.add('U');
foo.add(Integer.toString(x1).charAt(0));
foo.add(Integer.toString(y1).charAt(0));
res.add(foo);
}
if (x2 != 4)
{
List<Character> foo = new ArrayList<>(2);
foo.add('D');
foo.add(Integer.toString(x2).charAt(0));
foo.add(Integer.toString(y2).charAt(0));
res.add(foo);
}
}
return res;
}
}
Excuse me if I've made some blatant styling/coding mistakes, I am more used to coding in Python/C++. Would there be a way to make this work?
You need to use some type of data structure to keep track of paths already traversed. A hash table would be ideal and would provide a worst case of O(n) depending upon implementation. Not very familiar with Java but in C++ I would use std::unordered_map with the first field being a state of your board and the second being the number of moves at that point. I have implemented this algorithm before, and that's the approach I took. Incredibly fast.
I'm doing the coursera NLP course and the first programming assignment is to build a Viterbi decoder. I think I'm really close to finishing it but there is some elusive bug which I cannot seem to be able to trace. Here is my code:
http://pastie.org/private/ksmbns3gjctedu1zxrehw
http://pastie.org/private/ssv6tc8dwnamn2qegdvww
So far I've debugged the "teaching" related functions so I can say that the parameters for the algorithms are being correctly estimated. Of particular interest is the viterbi() and findW() methods. The definition of the algorithm I'm using can be found here: http://www.cs.columbia.edu/~mcollins/hmms-spring2013.pdf on page 18.
One thing which I'm having hard time wrapping my head around is how am I supposed to update the backpointers for the special cases when K = {1, 2} (in my case this is 0 and 1, since I'm zero-indexing my array) respectively the parameters I'm using in those cases are q({TAGSET} | *, *) and q ({TAGSET} | *, {TAGSET}).
Hints rather than spoon-fed answers will also be highly appreciated!
Here's a simple implementation of viterbi decoder by Yusuke Shunyama =) http://cs.nyu.edu/yusuke/course/NLP/viterbi/Viterbi.java
/*
* Viterbi.java
* Toy Viterbi Decorder
*
* by Yusuke Shinyama <yusuke at cs . nyu . edu>
*
* Permission to use, copy, modify, distribute this software
* for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice
* appear in supporting documentation.
*/
import java.awt.*;
import java.util.*;
import java.text.*;
import java.awt.event.*;
import java.applet.*;
class Symbol {
public String name;
public Symbol(String s) {
name = s;
}
}
class SymbolTable {
Hashtable table;
public SymbolTable() {
table = new Hashtable();
}
public Symbol intern(String s) {
s = s.toLowerCase();
Object sym = table.get(s);
if (sym == null) {
sym = new Symbol(s);
table.put(s, sym);
}
return (Symbol)sym;
}
}
class SymbolList {
Vector list;
public SymbolList() {
list = new Vector();
}
public int size() {
return list.size();
}
public void set(int index, Symbol sym) {
list.setElementAt(sym, index);
}
public void add(Symbol sym) {
list.addElement(sym);
}
public Symbol get(int index) {
return (Symbol) list.elementAt(index);
}
}
class IntegerList {
Vector list;
public IntegerList() {
list = new Vector();
}
public int size() {
return list.size();
}
public void set(int index, int i) {
list.setElementAt(new Integer(i), index);
}
public void add(int i) {
list.addElement(new Integer(i));
}
public int get(int index) {
return ((Integer)list.elementAt(index)).intValue();
}
}
class ProbTable {
Hashtable table;
public ProbTable() {
table = new Hashtable();
}
public void put(Object obj, double prob) {
table.put(obj, new Double(prob));
}
public double get(Object obj) {
Double prob = (Double)table.get(obj);
if (prob == null) {
return 0.0;
}
return prob.doubleValue();
}
// normalize probability
public void normalize() {
double total = 0.0;
for(Enumeration e = table.elements() ; e.hasMoreElements() ;) {
total += ((Double)e.nextElement()).doubleValue();
}
if (total == 0.0) {
return; // div by zero!
}
for(Enumeration e = table.keys() ; e.hasMoreElements() ;) {
Object k = e.nextElement();
double prob = ((Double)table.get(k)).doubleValue();
table.put(k, new Double(prob / total));
}
}
}
class State {
public String name;
ProbTable emits;
ProbTable linksto;
public State(String s) {
name = s;
emits = new ProbTable();
linksto = new ProbTable();
}
public void normalize() {
emits.normalize();
linksto.normalize();
}
public void addSymbol(Symbol sym, double prob) {
emits.put(sym, prob);
}
public double emitprob(Symbol sym) {
return emits.get(sym);
}
public void addLink(State st, double prob) {
linksto.put(st, prob);
}
public double transprob(State st) {
return linksto.get(st);
}
}
class StateTable {
Hashtable table;
public StateTable() {
table = new Hashtable();
}
public State get(String s) {
s = s.toUpperCase();
State st = (State)table.get(s);
if (st == null) {
st = new State(s);
table.put(s, st);
}
return st;
}
}
class StateIDTable {
Hashtable table;
public StateIDTable() {
table = new Hashtable();
}
public void put(State obj, int i) {
table.put(obj, new Integer(i));
}
public int get(State obj) {
Integer i = (Integer)table.get(obj);
if (i == null) {
return 0;
}
return i.intValue();
}
}
class StateList {
Vector list;
public StateList() {
list = new Vector();
}
public int size() {
return list.size();
}
public void set(int index, State st) {
list.setElementAt(st, index);
}
public void add(State st) {
list.addElement(st);
}
public State get(int index) {
return (State) list.elementAt(index);
}
}
class HMMCanvas extends Canvas {
static final int grid_x = 60;
static final int grid_y = 40;
static final int offset_x = 70;
static final int offset_y = 30;
static final int offset_y2 = 10;
static final int offset_y3 = 65;
static final int col_x = 40;
static final int col_y = 10;
static final int state_r = 10;
static final Color state_fill = Color.white;
static final Color state_fill_maximum = Color.yellow;
static final Color state_fill_best = Color.red;
static final Color state_boundery = Color.black;
static final Color link_normal = Color.green;
static final Color link_processed = Color.blue;
static final Color link_maximum = Color.red;
HMMDecoder hmm;
public HMMCanvas() {
setBackground(Color.white);
setSize(400,300);
}
public void setHMM(HMMDecoder h) {
hmm = h;
}
private void drawState(Graphics g, int x, int y, Color c) {
x = x * grid_x + offset_x;
y = y * grid_y + offset_y;
g.setColor(c);
g.fillOval(x-state_r, y-state_r, state_r*2, state_r*2);
g.setColor(state_boundery);
g.drawOval(x-state_r, y-state_r, state_r*2, state_r*2);
}
private void drawLink(Graphics g, int x, int y0, int y1, Color c) {
int x0 = grid_x * x + offset_x;
int x1 = grid_x * (x+1) + offset_x;
y0 = y0 * grid_y + offset_y;
y1 = y1 * grid_y + offset_y;
g.setColor(c);
g.drawLine(x0, y0, x1, y1);
}
private void drawCenterString(Graphics g, String s, int x, int y) {
x = x - g.getFontMetrics().stringWidth(s)/2;
g.setColor(Color.black);
g.drawString(s, x, y+5);
}
private void drawRightString(Graphics g, String s, int x, int y) {
x = x - g.getFontMetrics().stringWidth(s);
g.setColor(Color.black);
g.drawString(s, x, y+5);
}
public void paint(Graphics g) {
if (hmm == null) {
return;
}
DecimalFormat form = new DecimalFormat("0.0000");
int nsymbols = hmm.symbols.size();
int nstates = hmm.states.size();
// complete graph.
for(int i = 0; i < nsymbols; i++) {
int offset_ymax = offset_y2+nstates*grid_y;
if (i < nsymbols-1) {
for(int y1 = 0; y1 < nstates; y1++) {
for(int y0 = 0; y0 < nstates; y0++) {
Color c = link_normal;
if (hmm.stage == i+1 && hmm.i0 == y0 && hmm.i1 == y1) {
c = link_processed;
}
if (hmm.matrix_prevstate[i+1][y1] == y0) {
c = link_maximum;
}
drawLink(g, i, y0, y1, c);
if (c == link_maximum && 0 < i) {
double transprob = hmm.states.get(y0).transprob(hmm.states.get(y1));
drawCenterString(g, form.format(transprob),
offset_x + i*grid_x + grid_x/2, offset_ymax);
offset_ymax = offset_ymax + 16;
}
}
}
}
// state circles.
for(int y = 0; y < nstates; y++) {
Color c = state_fill;
if (hmm.matrix_prevstate[i][y] != -1) {
c = state_fill_maximum;
}
if (hmm.sequence.size() == nsymbols &&
hmm.sequence.get(nsymbols-1-i) == y) {
c = state_fill_best;
}
drawState(g, i, y, c);
}
}
// max probability.
for(int i = 0; i < nsymbols; i++) {
for(int y1 = 0; y1 < nstates; y1++) {
if (hmm.matrix_prevstate[i][y1] != -1) {
drawCenterString(g, form.format(hmm.matrix_maxprob[i][y1]),
offset_x+i*grid_x, offset_y+y1*grid_y);
}
}
}
// captions (symbols atop)
for(int i = 0; i < nsymbols; i++) {
drawCenterString(g, hmm.symbols.get(i).name, offset_x+i*grid_x, col_y);
}
// captions (states in left)
for(int y = 0; y < nstates; y++) {
drawRightString(g, hmm.states.get(y).name, col_x, offset_y+y*grid_y);
}
// status bar
g.setColor(Color.black);
g.drawString(hmm.status, col_x, offset_y3+nstates*grid_y);
g.drawString(hmm.status2, col_x, offset_y3+nstates*grid_y+16);
}
}
class HMMDecoder {
StateList states;
int state_start;
int state_end;
public IntegerList sequence;
public double[][] matrix_maxprob;
public int[][] matrix_prevstate;
public SymbolList symbols;
public double probmax;
public int stage, i0, i1;
public boolean laststage;
public String status, status2;
public HMMDecoder() {
status = "Not initialized.";
status2 = "";
states = new StateList();
}
public void addStartState(State st) {
state_start = states.size(); // get current index
states.add(st);
}
public void addNormalState(State st) {
states.add(st);
}
public void addEndState(State st) {
state_end = states.size(); // get current index
states.add(st);
}
// for debugging.
public void showmatrix() {
for(int i = 0; i < symbols.size(); i++) {
for(int j = 0; j < states.size(); j++) {
System.out.print(matrix_maxprob[i][j]+" "+matrix_prevstate[i][j]+", ");
}
System.out.println();
}
}
// initialize for decoding
public void initialize(SymbolList syms) {
// symbols[syms.length] should be END
symbols = syms;
matrix_maxprob = new double[symbols.size()][states.size()];
matrix_prevstate = new int[symbols.size()][states.size()];
for(int i = 0; i < symbols.size(); i++) {
for(int j = 0; j < states.size(); j++) {
matrix_prevstate[i][j] = -1;
}
}
State start = states.get(state_start);
for(int i = 0; i < states.size(); i++) {
matrix_maxprob[0][i] = start.transprob(states.get(i));
matrix_prevstate[0][i] = 0;
}
stage = 0;
i0 = -1;
i1 = -1;
sequence = new IntegerList();
status = "Ok, let's get started...";
status2 = "";
}
// forward procedure
public boolean proceed_decoding() {
status2 = "";
// already end?
if (symbols.size() <= stage) {
return false;
}
// not started?
if (stage == 0) {
stage = 1;
i0 = 0;
i1 = 0;
matrix_maxprob[stage][i1] = 0.0;
} else {
i0++;
if (states.size() <= i0) {
// i0 should be reinitialized.
i0 = 0;
i1++;
if (states.size() <= i1) {
// i1 should be reinitialized.
// goto next stage.
stage++;
if (symbols.size() <= stage) {
// done.
status = "Decoding finished.";
return false;
}
laststage = (stage == symbols.size()-1);
i1 = 0;
}
matrix_maxprob[stage][i1] = 0.0;
}
}
// sym1: next symbol
Symbol sym1 = symbols.get(stage);
State s0 = states.get(i0);
State s1 = states.get(i1);
// precond: 1 <= stage.
double prob = matrix_maxprob[stage-1][i0];
DecimalFormat form = new DecimalFormat("0.0000");
status = "Prob:" + form.format(prob);
if (1 < stage) {
// skip first stage.
double transprob = s0.transprob(s1);
prob = prob * transprob;
status = status + " x " + form.format(transprob);
}
double emitprob = s1.emitprob(sym1);
prob = prob * emitprob;
status = status + " x " + form.format(emitprob) + "(" + s1.name+":"+sym1.name + ")";
status = status + " = " + form.format(prob);
// System.out.println("stage: "+stage+", i0:"+i0+", i1:"+i1+", prob:"+prob);
if (matrix_maxprob[stage][i1] < prob) {
matrix_maxprob[stage][i1] = prob;
matrix_prevstate[stage][i1] = i0;
status2 = "(new maximum found)";
}
return true;
}
// backward proc
public void backward() {
int probmaxstate = state_end;
sequence.add(probmaxstate);
for(int i = symbols.size()-1; 0 < i; i--) {
probmaxstate = matrix_prevstate[i][probmaxstate];
if (probmaxstate == -1) {
status2 = "Decoding failed.";
return;
}
sequence.add(probmaxstate);
//System.out.println("stage: "+i+", state:"+probmaxstate);
}
}
}
public class Viterbi extends Applet implements ActionListener, Runnable {
SymbolTable symtab;
StateTable sttab;
HMMDecoder myhmm = null;
HMMCanvas canvas;
Panel p;
TextArea hmmdesc;
TextField sentence;
Button bstart, bskip;
static final String initialHMM =
"start: go(cow,1.0)\n" +
"cow: emit(moo,0.9) emit(hello,0.1) go(cow,0.5) go(duck,0.3) go(end,0.2)\n" +
"duck: emit(quack,0.6) emit(hello,0.4) go(duck,0.5) go(cow,0.3) go(end,0.2)\n";
final int sleepmillisec = 100; // 0.1s
// setup hmm
// success:true.
boolean setupHMM(String s) {
myhmm = new HMMDecoder();
symtab = new SymbolTable();
sttab = new StateTable();
State start = sttab.get("start");
State end = sttab.get("end");
myhmm.addStartState(start);
boolean success = true;
StringTokenizer lines = new StringTokenizer(s, "\n");
while (lines.hasMoreTokens()) {
// foreach line.
String line = lines.nextToken();
int i = line.indexOf(':');
if (i == -1) break;
State st0 = sttab.get(line.substring(0,i).trim());
if (st0 != start && st0 != end) {
myhmm.addNormalState(st0);
}
//System.out.println(st0.name+":"+line.substring(i+1));
StringTokenizer tokenz = new StringTokenizer(line.substring(i+1), ", ");
while (tokenz.hasMoreTokens()) {
// foreach token.
String t = tokenz.nextToken().toLowerCase();
if (t.startsWith("go(")) {
State st1 = sttab.get(t.substring(3).trim());
// fetch another token.
if (!tokenz.hasMoreTokens()) {
success = false; // err. nomoretoken
break;
}
String n = tokenz.nextToken().replace(')', ' ');
double prob;
try {
prob = Double.valueOf(n).doubleValue();
} catch (NumberFormatException e) {
success = false; // err.
prob = 0.0;
}
st0.addLink(st1, prob);
//System.out.println("go:"+st1.name+","+prob);
} else if (t.startsWith("emit(")) {
Symbol sym = symtab.intern(t.substring(5).trim());
// fetch another token.
if (!tokenz.hasMoreTokens()) {
success = false; // err. nomoretoken
break;
}
String n = tokenz.nextToken().replace(')', ' ');
double prob;
try {
prob = Double.valueOf(n).doubleValue();
} catch (NumberFormatException e) {
success = false; // err.
prob = 0.0;
}
st0.addSymbol(sym, prob);
//System.out.println("emit:"+sym.name+","+prob);
} else {
// illegal syntax, just ignore
break;
}
}
st0.normalize(); // normalize probability
}
end.addSymbol(symtab.intern("end"), 1.0);
myhmm.addEndState(end);
return success;
}
// success:true.
boolean setup() {
if (! setupHMM(hmmdesc.getText()))
return false;
// initialize words
SymbolList words = new SymbolList();
StringTokenizer tokenz = new StringTokenizer(sentence.getText());
words.add(symtab.intern("start"));
while (tokenz.hasMoreTokens()) {
words.add(symtab.intern(tokenz.nextToken()));
}
words.add(symtab.intern("end"));
myhmm.initialize(words);
canvas.setHMM(myhmm);
return true;
}
public void init() {
canvas = new HMMCanvas();
setLayout(new BorderLayout());
p = new Panel();
sentence = new TextField("moo hello quack", 20);
bstart = new Button(" Start ");
bskip = new Button("Auto");
bstart.addActionListener(this);
bskip.addActionListener(this);
p.add(sentence);
p.add(bstart);
p.add(bskip);
hmmdesc = new TextArea(initialHMM, 4, 20);
add("North", canvas);
add("Center", p);
add("South", hmmdesc);
}
void setup_fallback() {
// adjustable
State cow = sttab.get("cow");
State duck = sttab.get("duck");
State end = sttab.get("end");
cow.addLink (cow, 0.5);
cow.addLink (duck, 0.3);
cow.addLink (end, 0.2);
duck.addLink (cow, 0.3);
duck.addLink (duck, 0.5);
duck.addLink (end, 0.2);
cow.addSymbol(symtab.intern("moo"), 0.9);
cow.addSymbol(symtab.intern("hello"), 0.1);
duck.addSymbol(symtab.intern("quack"), 0.6);
duck.addSymbol(symtab.intern("hello"), 0.4);
}
public void destroy() {
remove(p);
remove(canvas);
}
public void processEvent(AWTEvent e) {
if (e.getID() == Event.WINDOW_DESTROY) {
System.exit(0);
}
}
public void run() {
if (myhmm != null) {
while (myhmm.proceed_decoding()) {
canvas.repaint();
try {
Thread.sleep(sleepmillisec);
} catch (InterruptedException e) {
;
}
}
myhmm.backward();
canvas.repaint();
bstart.setLabel(" Start ");
bstart.setEnabled(true);
bskip.setEnabled(true);
myhmm = null;
}
}
public void actionPerformed(ActionEvent ev) {
String label = ev.getActionCommand();
if (label.equalsIgnoreCase(" start ")) {
if (!setup()) {
// error
return;
}
bstart.setLabel("Proceed");
canvas.repaint();
} else if (label.equalsIgnoreCase("proceed")) {
// next
if (! myhmm.proceed_decoding()) {
myhmm.backward();
bstart.setLabel(" Start ");
myhmm = null;
}
canvas.repaint();
} else if (label.equalsIgnoreCase("auto")) {
// skip
if (myhmm == null) {
if (!setup()) {
// error
return;
}
}
bstart.setEnabled(false);
bskip.setEnabled(false);
Thread me = new Thread(this);
me.setPriority(Thread.MIN_PRIORITY);
// start animation.
me.start();
}
}
public static void main(String args[]) {
Frame f = new Frame("Viterbi");
Viterbi v = new Viterbi();
f.add("Center", v);
f.setSize(400, 400);
f.show();
v.init();
v.start();
}
public String getAppletInfo() {
return "A Sample Viterbi Decoder Applet";
}
}
Here are some suggestions:
You should draw out the HMM lattice if you have any confusion about how transitions are occurring in your model.
For instance, you can view transitions to the first hidden state as originating from a single start hidden state, so the backpointer for k=0 would always have to point to this start state. In your code, you probably should not be looping over hidden states for k=0 in findW (which seems correct), but you probably should be looping for k=1.
Usually multiplying transition and emission probabilities in HMM inference lead to very small floating point values, which can lead to numerical errors. You should add log probabilities instead of multiplying probabilities.
To check viterbi or forward-backward implementations, I usually also write a brute force method and compare the output of each. If the brute-force and dynamic-programming algorithm match on short sequences, then that gives a reasonable measure of confidence that both are correct.
i try to implement this java applet source code into java application with using JFrame but it doesn't work. and i changed little bit to read file from my computer but it also doesn't work.
how can i convert this into application?
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.URL;
class Node {
int x;
int y;
int delta_plus; /* edge starts from this node */
int delta_minus; /* edge terminates at this node */
int dist; /* distance from the start node */
int prev; /* previous node of the shortest path */
int succ,pred; /* node in Sbar with finite dist. */
int w;
int h;
int pw;
int dx;
int dy;
String name;
}
class Edge {
int rndd_plus; /* initial vertex of this edge */
int rndd_minus; /* terminal vertex of this edge */
int delta_plus; /* edge starts from rndd_plus */
int delta_minus; /* edge terminates at rndd_minus */
int len; /* length */
String name;
}
public class Prim extends Applet implements MouseListener {
int n,m;
int u,snode; /* start node */
int pre_s_first, pre_s_last;
boolean isdigraph;
int iteration, step;
Node v[] = new Node[100];
Edge e[] = new Edge[200];
int findNode(String name) {
for (int i=0; i<n; i++)
if (v[i].name.equals(name))
return i;
return -1;
}
void input_graph(InputStream is) throws IOException {
int x,y,l;
String s;
Reader r = new BufferedReader(new InputStreamReader(is));
StreamTokenizer st = new StreamTokenizer(r);
st.commentChar('#');
st.nextToken(); n = (int)st.nval;
st.nextToken(); m = (int)st.nval;
st.nextToken(); s = st.sval;
isdigraph = "digraph".equals(s);
for (int i = 0; i<n; i++) {
Node node = new Node();
st.nextToken(); node.name = st.sval;
st.nextToken(); node.x = (int)st.nval;
st.nextToken(); node.y = (int)st.nval;
v[i] = node;
}
for (int i = 0; i<m; i++) {
Edge edge = new Edge();
st.nextToken(); edge.name = st.sval;
switch (st.nextToken()) {
case StreamTokenizer.TT_NUMBER:
edge.rndd_plus = (int)st.nval;
break;
case StreamTokenizer.TT_WORD:
edge.rndd_plus = findNode(st.sval);
break;
default:
break;
}
switch (st.nextToken()) {
case StreamTokenizer.TT_NUMBER:
edge.rndd_minus = (int)st.nval;
break;
case StreamTokenizer.TT_WORD:
edge.rndd_minus = findNode(st.sval);
break;
default:
break;
}
st.nextToken(); edge.len = (int)st.nval;
e[i] = edge;
}
for (int i=0; i<n; i++) {
v[i].succ = v[i].pred = -2;
v[i].prev = v[i].dist = -1;
v[i].pw = 0;
}
iteration = step = 0;
}
void rdb() {
int i,k;
for (i=0; i<n; i++)
v[i].delta_plus = v[i].delta_minus = -1;
for (i=0; i<m; i++)
e[i].delta_plus = e[i].delta_minus = -1;
for (i=0; i<m; i++) {
k = e[i].rndd_plus;
if (v[k].delta_plus == -1)
v[k].delta_plus = i;
else {
k = v[k].delta_plus;
while(e[k].delta_plus >= 0)
k = e[k].delta_plus;
e[k].delta_plus = i;
}
k = e[i].rndd_minus;
if (v[k].delta_minus == -1)
v[k].delta_minus = i;
else {
k = v[k].delta_minus;
while(e[k].delta_minus >= 0)
k = e[k].delta_minus;
e[k].delta_minus = i;
}
}
}
void append_pre_s(int i) {
v[i].succ = v[i].pred = -1;
if (pre_s_first<0)
pre_s_first = i;
else
v[pre_s_last].succ = i;
v[i].pred = pre_s_last;
pre_s_last = i;
}
void remove_pre_s(int i) {
int succ = v[i].succ;
int pred = v[i].pred;
if (succ>=0)
v[succ].pred = pred;
else
pre_s_last = pred;
if (pred>=0)
v[pred].succ = succ;
else
pre_s_first = succ;
}
void step1() { /* initialize */
u = snode;
for (int i=0; i<n; i++) {
v[i].succ = v[i].pred = -2;
v[i].prev = v[i].dist = -1;
}
v[u].succ = -3;
v[u].dist = 0;
pre_s_first = pre_s_last = -1;
}
void step2() { /* replace labels */
int i,j;
j = v[u].delta_plus;
while (j>=0) {
i = e[j].rndd_minus;
if ((v[i].succ>=-2)&&((v[i].dist<0)||
(v[i].dist>e[j].len))) {
if (v[i].dist<0)
append_pre_s(i);
v[i].dist = e[j].len;
v[i].prev = u; /* label */
}
j = e[j].delta_plus;
}
if (!isdigraph) {
j = v[u].delta_minus;
while (j>=0) {
i = e[j].rndd_plus;
if ((v[i].succ>=-2)&&((v[i].dist<0)||
(v[i].dist>e[j].len))) {
if (v[i].dist<0)
append_pre_s(i);
v[i].dist = e[j].len;
v[i].prev = u; /* label */
}
j = e[j].delta_minus;
}
}
v[u].succ = -4;
}
void step3() { /* find the shortest node in Sbar */
int i,rho;
rho = -1;
for (i = pre_s_first; i>=0; i = v[i].succ) {
if ((rho < 0)||(rho>v[i].dist)) {
rho = v[i].dist;
u = i;
}
}
remove_pre_s(u);
v[u].succ = -3;
}
void step4() {
v[u].succ = -4;
}
double weight(Node n, double x, double y) {
double w,z,xx,yy;
w = 0;
for (int j = n.delta_plus; j>=0; j=e[j].delta_plus) {
xx = (double)(v[e[j].rndd_minus].x - n.x);
yy = (double)(v[e[j].rndd_minus].y - n.y);
z = (x*xx+y*yy)/Math.sqrt((x*x+y*y)*(xx*xx+yy*yy))+1.0;
w += z*z*z*z;
}
for (int j = n.delta_minus; j>=0; j=e[j].delta_minus) {
xx = (double)(v[e[j].rndd_plus].x - n.x);
yy = (double)(v[e[j].rndd_plus].y - n.y);
z = (x*xx+y*yy)/Math.sqrt((x*x+y*y)*(xx*xx+yy*yy))+1.0;
w += z*z*z*z;
}
return w;
}
void init_sub() {
int x[] = {1, 0, -1, 1, 0, -1};
int y[] = {1, 1, 1, -1, -1, -1};
int i,j,k;
double w,z;
for (i=0; i<n; i++) {
k=0;
w=weight(v[i],(double)x[0],(double)y[0]);
for (j=1; j<6; j++) {
z=weight(v[i],(double)x[j],(double)y[j]);
if (z<w) {
w = z;
k = j;
}
}
v[i].dx = x[k];
v[i].dy = y[k];
}
}
public void init() {
try {
InputStream is;
is = new URL("input address").openStream();
input_graph(is);
try {
if (is != null)
is.close();
} catch(Exception e) {
}
} catch (FileNotFoundException e) {
System.err.println("File not found.");
} catch (IOException e) {
System.err.println("Cannot access file.");
}
String s = getParameter("start");
if (s != null)
snode = Integer.parseInt(s);
else
snode = 0;
setBackground(Color.white);
rdb();
init_sub();
addMouseListener(this);
}
public void paintNode(Graphics g, Node n, FontMetrics fm) {
String s;
int x = n.x;
int y = n.y;
int w = fm.stringWidth(n.name) + 10;
int h = fm.getHeight() + 4;
n.w = w;
n.h = h;
if (n.succ<-2)
g.setColor(Color.blue);
else if (n.succ==-2)
g.setColor(Color.gray);
else
g.setColor(Color.red);
g.drawRect(x-w/2,y-h/2,w,h);
if (n.succ==-4)
g.setColor(Color.cyan);
else if (n.succ==-3)
g.setColor(Color.pink);
else if (n.succ>-2)
g.setColor(Color.yellow);
else
g.setColor(getBackground());
g.fillRect(x-w/2+1,y-h/2+1,w-1,h-1);
g.setColor(Color.black);
g.drawString(n.name,x-(w-10)/2,(y-(h-4)/2)+fm.getAscent());
if (n.dist<0)
s = "";
else
s = ""+n.dist;
w = fm.stringWidth(s) + 10;
x += (h+1)*n.dx; y += (h+1)*n.dy;
g.setColor(getBackground());
g.fillRect(x-n.pw/2,y-h/2,n.pw,h);
n.pw = w;
if (n.succ<-2)
g.setColor(Color.blue);
else
g.setColor(Color.red);
g.drawString(s,x-(w-10)/2,y-(h-4)/2+fm.getAscent());
}
int [] xy(int a, int b, int w, int h) {
int x[] = new int[2];
if (Math.abs(w*b)>=Math.abs(h*a)) {
x[0] = ((b>=0)?1:-1)*a*h/b/2;
x[1] = ((b>=0)?1:-1)*h/2;
} else {
x[0] = ((a>=0)?1:-1)*w/2;
x[1] = ((a>=0)?1:-1)*b*w/a/2;
}
return x;
}
void drawArrow(Graphics g,int x1,int y1,int x2,int y2) {
int a = x1-x2;
int b = y1-y2;
if (isdigraph) {
double aa = Math.sqrt(a*a+b*b)/16.0;
double bb = b/aa;
aa = a/aa;
g.drawLine(x2,y2,x2+(int)((aa*12+bb*5)/13),y2+(int)((-aa*5+bb*12)/13));
g.drawLine(x2,y2,x2+(int)((aa*12-bb*5)/13),y2+(int)((aa*5+bb*12)/13));
}
g.drawLine(x1,y1,x2,y2);
}
public void paintEdge(Graphics g, Edge e, FontMetrics fm) {
Node v1 = v[e.rndd_plus];
Node v2 = v[e.rndd_minus];
int a = v1.x-v2.x;
int b = v1.y-v2.y;
int x1[] = xy(-a,-b,v1.w,v1.h);
int x2[] = xy(a,b,v2.w,v2.h);
if (v2.prev == e.rndd_plus) {
if ((v1.succ<-2)&&(v2.succ>=-2))
g.setColor(Color.red);
else
g.setColor(Color.blue);
} else {
g.setColor(Color.lightGray);
}
if ((!isdigraph)&&(v1.prev == e.rndd_minus)) {
if ((v2.succ<-2)&&(v1.succ>=-2))
g.setColor(Color.red);
else
g.setColor(Color.blue);
}
drawArrow(g,v1.x+x1[0],v1.y+x1[1],v2.x+x2[0],v2.y+x2[1]);
int w = fm.stringWidth("" + e.len);
int h = fm.getHeight();
g.setColor(getBackground());
g.fillRect((v1.x+v2.x-w)/2,(v1.y+v2.y-h)/2,w,h);
if ((v2.prev == e.rndd_plus)||
((!isdigraph)&&(v1.prev == e.rndd_minus)))
g.setColor(Color.black);
else
g.setColor(Color.lightGray);
g.drawString("" + e.len,(v1.x+v2.x-w)/2,(v1.y+v2.y-h)/2+fm.getAscent());
}
public void paint(Graphics g) {
FontMetrics fm = g.getFontMetrics();
for (int i=0; i<n; i++)
paintNode(g,v[i],fm);
for (int i=0; i<m; i++)
paintEdge(g,e[i],fm);
}
public void update(Graphics g) {
paint(g);
}
public void mousePressed(MouseEvent ev) {
if (iteration==0) {
step1();
iteration++;
step = 2;
} else if (iteration>=n) {
step4();
// iteration = 0;
} else {
if (step == 2) {
step2();
step = 3;
} else {
step3();
iteration++;
step = 2;
}
}
repaint();
}
public void mouseClicked(MouseEvent event) {}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
}
Here are some links for you to read:
Turning an Applet into a Standalone Application
Converting an Applet to an Application
And there are lots of others. (Google is your friend.)
If this doesn't help, feel free to ask a specific question.
You can try adding this:
public static void main(String[] args) {
Prim prim = new Prim() {
#Override
public String getParameter(String key) {
if ("start".equals(key)) {
return "0";
}
else {
return "";
}
}
};
prim.init();
}
BTW, you should put in a real value for URL("input address").