A_star搜索我做错了什么?

时间:2016-02-07 17:31:08

标签: java search artificial-intelligence a-star

您好我正在实施基于WikiLink的A *搜索算法,但我根本没有得到我的搜索答案。关于我可能做错的任何提示和/或帮助

我得到一张包含污垢和障碍物的地图,我需要前往所有污垢颗粒并将它们移开并返回到我的起点

搜索功能

private void search_Astar(State start){ // we have confirmed a valid start state
    // needed vars
    Map<State, Integer> g_score = new HashMap<>();
    Map<State, Integer> f_score = new HashMap<>();
    Queue<State> openQueue = new PriorityQueue<State>(((State o1, State o2) -> f_score.get(o1) - f_score.get(o2)));
    HashSet<State> closedSet = new HashSet<>();
    // inits
    g_score.put(start, 0);
    f_score.put(start, start.heuristic());
    openQueue.add(start);
    // search
    while (!openQueue.isEmpty()){
        State current = openQueue.poll();
        if (current.isGoal()){
            // create path
            solutionStack.push(Actions.Turn_Off);
            while (current.takenAction != null){
                solutionStack.push(current.takenAction);
                current = current.parent;
            }
            return;
        }
        closedSet.add(current);
        for (String action:current.legalActions()){
            State child = current.CreateState(action);
            if (closedSet.contains(child)) continue;
            int tentativeG = g_score.get(current) + 1; // the cost to take an action
            if (!openQueue.contains(child)) openQueue.add(child);
            else if (tentativeG >= g_score.getOrDefault(child, Integer.MAX_VALUE)) continue;

            g_score.put(child, tentativeG);
            f_score.put(child, tentativeG + child.heuristic());
        }
    }
}

和国家级(抱歉为巨大的)

import java.util.ArrayList;
import java.util.Collection;

public class State {
// keep track of position and orientation
public Orientation orientation;
public Position position;
public boolean turned_on;

// track world state
private Collection<Position> dirt;
private Collection<Position> obstacles;
private Position size;

// variables for detirmining goal state and heuristic
private Position home;

// for calculating G
public State parent;
public String takenAction;

public State(Position position, Orientation orientation, boolean turned_on, Collection dirt, Collection obs, Position home,
             Position size, State parent, String action) {
    this.position = position;
    this.orientation = orientation;
    this.turned_on = turned_on;
    this.dirt = dirt;
    this.obstacles = obs;
    this.home = home;
    this.size = size;
    this.parent = parent;
    this.takenAction = action;
}

public int G(){
    State curr = parent;
    int total = 0;
    while (curr != null){
        total += 1;
        curr = parent.parent;
    }
    return total;
}

public String toString() {
    return "State{position: " + position + ", orientation: " + orientation + ", on:" + turned_on + "}";
}

@Override
public int hashCode(){
    int hashVal = 23;
    hashVal = ((hashVal + position.x) << 5) - (hashVal + position.x);
    hashVal = ((hashVal + position.y) << 5) - (hashVal + position.y);
    if(turned_on){
        hashVal += 1243;
    }
    if (orientation == Orientation.NORTH){
        hashVal += 12;
    }else if (orientation == Orientation.EAST){
        hashVal += 2234;
    }else if (orientation == Orientation.WEST){
        hashVal += 32345;
    }
    return hashVal + dirt.size();
}

@Override
public boolean equals(Object o){
    if (o instanceof State){
        State other = (State)o;
        if(!other.position.equals(this.position)){
            return false;
        }else if( other.turned_on != this.turned_on){
            return false;
        }else if( other.orientation != this.orientation){
            return false;
        }else if (other.dirt.size() != this.dirt.size()){
            return false;
        } else{
            return true;
        }
    }else {
        return false;
    }
}

/**
 * check to see if current node is a valid goal node
 *
 * @return true if valid, false otherwise
 */
public Boolean isGoal(){
    return dirt.isEmpty() && position.equals(home);
}

/**
 * Calculate all legal moves from current state
 *
 * @return Collection of legal actions (as string)
 */
public Collection<String> legalActions(){
    Collection<String> actions = new ArrayList<String>();
    if (!turned_on){
        actions.add(Actions.Turn_On);
    }else{
        // no reason we couldn't turn
        actions.add(Actions.Turn_Left);
        actions.add(Actions.Turn_Right);
        if (dirt.contains(position)){
            actions.add(Actions.Suck);
        }

        // check if we can move forward
        // ATTENTION this must be at bottom of function
        if (orientation == Orientation.NORTH){
            for (Position o: obstacles) {
                if (o.y == position.y + 1 && o.x == position.x || position.y == size.y){
                    return actions;
                }
            }
            // we have checked every obstacle and we would not collide
            actions.add(Actions.Go);
        }else if (orientation == Orientation.SOUTH){
            for (Position o: obstacles) {
                if (o.y == position.y - 1 && o.x == position.x || position.y == 1){
                    return actions;
                }
            }
            actions.add(Actions.Go);
        }else if (orientation == Orientation.WEST){
            for (Position o: obstacles) {
                if (o.x == position.x - 1 && o.y == position.y|| position.x == 1){
                    return actions;
                }
            }
            actions.add(Actions.Go);
        }else {
            // we are pointing east
            for (Position o: obstacles) {
                if (o.x == position.x + 1 && o.y == position.y|| position.x == size.x){
                    return actions;
                }
            }
            actions.add(Actions.Go);
        }
    }
    return actions;
}

/**
 * return a value to determine how optimal this state is
 *
 * evaluation methood: number of dirt left times a constant
 * which is the added to the distance to the closest dirt
 * if there are no dirts left it is the mannhatan distance to home
 *
 * note: should add state depth?
 * @return int
 */
public int heuristic(){
    int h = 0;
    for (Position p:obstacles){
        h += mannhatandist(p);
    }
    h += mannhatandist(home);
    return h + dirt.size();
}

private int mannhatandist(Position p){
    return Math.abs(p.x - position.x) + Math.abs(p.y - position.y);
}

private int distToClosest(){
    int min = Integer.MAX_VALUE;
    if (dirt.isEmpty()){
        int dist = Math.abs(home.x - position.x) + Math.abs(home.y - position.y);
        return dist;
    }
    for (Position p: dirt) {
        int dist = Math.abs(p.x - position.x) + Math.abs(p.y - position.y);
        min = Math.min(min, dist);
    }
    if (!turned_on) min++;
    return min;
}

public State CreateState(String action) {

    //Copy the "old" values from the current state.
    //Before any action done, the "new" state has the same values.
    Position new_position = new Position(position.x, position.y);
    Orientation new_orientation = orientation;
    boolean new_turned_on = turned_on;
    Collection new_dirt = new ArrayList(dirt);
    State new_parent = this;

    //If the action is to turn the robot on, the turned_on variable for the new state takes the value "true".
    if(action == "TURN_ON") {
        new_turned_on = true;
    }
    //If the action is to turn the robot on, the turned_on variable for the new state takes the value "true".
    else if(action == "TURN_OFF") {
        new_turned_on = false;
    }
    //If the action is to suck, the current position needs to be taken out of the new state's dirt collection.
    else if(action == "SUCK") {
        new_dirt.remove(position);
    }
    //If the action is to go it depends on the orientation of the robot how the position of the new state will change.
    else if(action == "GO") {
        //If it's facing north, the y position increases by one, considering the old state and so on.
        if(orientation == Orientation.NORTH) {
            new_position.y++;
        }
        else if(orientation == Orientation.EAST) {
            new_position.x++;
        }
        else if(orientation == Orientation.SOUTH) {
            new_position.y--;
        }
        else {
            new_position.x--; 
        }
    }
    //If the action is to turn left it depends on the orientation of the robot in the current state what the new orientation will be.
    else if(action == "TURN_LEFT") {
        if(orientation == Orientation.NORTH) {
            new_orientation = Orientation.WEST;
        }
        else if(orientation == Orientation.EAST) {
            new_orientation = Orientation.NORTH;
        }
        else if(orientation == Orientation.SOUTH) {
            new_orientation = Orientation.EAST;
        }
        else {
            new_orientation = Orientation.SOUTH;
        }
    }
    //If the action is to turn right it depends on the orientation of the robot in the current state what the new orientation will be.
    else if(action == "TURN_RIGHT") {
        if(orientation == Orientation.NORTH) {
            new_orientation = Orientation.EAST;
        }
        else if(orientation == Orientation.EAST) {
            new_orientation = Orientation.SOUTH;
        }
        else if(orientation == Orientation.SOUTH) {
            new_orientation = Orientation.WEST;
        }
        else {
            new_orientation = Orientation.NORTH;
        }
    }

    //Make a new state from the new variables that have been changed according to the action done.
    State new_state = new State(new_position, new_orientation, new_turned_on, new_dirt, obstacles, home, size, new_parent, action);
    return new_state;
}
}

1 个答案:

答案 0 :(得分:0)

我现在已经修好了。问题是我的启发式不一致。我已修改它,现在正确执行

我不会分享我的答案,因为这是针对学校项目的,因为学校的自动反作弊系统可能会检测到这一点,我会将我的学校用户名添加到此评论中(dagur13)

P.S。当我收到项目成绩时,我会发布更新的代码