Package aima.gui.applications.search.games

Source Code of aima.gui.applications.search.games.NQueensApp$NQueensEnvironment

package aima.gui.applications.search.games;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.swing.JButton;

import aima.core.agent.Action;
import aima.core.agent.Agent;
import aima.core.agent.Environment;
import aima.core.agent.EnvironmentState;
import aima.core.agent.Percept;
import aima.core.agent.impl.AbstractEnvironment;
import aima.core.environment.nqueens.AttackingPairsHeuristic;
import aima.core.environment.nqueens.NQueensBoard;
import aima.core.environment.nqueens.NQueensFunctionFactory;
import aima.core.environment.nqueens.NQueensGoalTest;
import aima.core.environment.nqueens.QueenAction;
import aima.core.search.framework.ActionsFunction;
import aima.core.search.framework.GraphSearch;
import aima.core.search.framework.Problem;
import aima.core.search.framework.Search;
import aima.core.search.framework.SearchAgent;
import aima.core.search.framework.TreeSearch;
import aima.core.search.informed.AStarSearch;
import aima.core.search.local.HillClimbingSearch;
import aima.core.search.local.Scheduler;
import aima.core.search.local.SimulatedAnnealingSearch;
import aima.core.search.uninformed.BreadthFirstSearch;
import aima.core.search.uninformed.DepthFirstSearch;
import aima.core.search.uninformed.DepthLimitedSearch;
import aima.core.search.uninformed.IterativeDeepeningSearch;
import aima.core.util.datastructure.XYLocation;
import aima.gui.framework.AgentAppController;
import aima.gui.framework.AgentAppEnvironmentView;
import aima.gui.framework.AgentAppFrame;
import aima.gui.framework.MessageLogger;
import aima.gui.framework.SimpleAgentApp;
import aima.gui.framework.SimulationThread;

/**
* Graphical n-queens game application. It demonstrates the performance of
* different search algorithms. An incremental problem formulation is supported
* as well as a complete-state formulation. Additionally, the user can make
* experiences with manual search.
*
* @author Ruediger Lunde
*/
public class NQueensApp extends SimpleAgentApp {

  /** List of supported search algorithm names. */
  protected static List<String> SEARCH_NAMES = new ArrayList<String>();
  /** List of supported search algorithms. */
  protected static List<Search> SEARCH_ALGOS = new ArrayList<Search>();

  /** Adds a new item to the list of supported search algorithms. */
  public static void addSearchAlgorithm(String name, Search algo) {
    SEARCH_NAMES.add(name);
    SEARCH_ALGOS.add(algo);
  }

  static {
    addSearchAlgorithm("Depth First Search (Graph Search)",
        new DepthFirstSearch(new GraphSearch()));
    addSearchAlgorithm("Breadth First Search (Tree Search)",
        new BreadthFirstSearch(new TreeSearch()));
    addSearchAlgorithm("Breadth First Search (Graph Search)",
        new BreadthFirstSearch(new GraphSearch()));
    addSearchAlgorithm("Depth Limited Search (8)",
        new DepthLimitedSearch(8));
    addSearchAlgorithm("Iterative Deepening Search",
        new IterativeDeepeningSearch());
    addSearchAlgorithm("A* search (attacking pair heuristic)",
        new AStarSearch(new GraphSearch(),
            new AttackingPairsHeuristic()));
    addSearchAlgorithm("Hill Climbing Search", new HillClimbingSearch(
        new AttackingPairsHeuristic()));
    addSearchAlgorithm("Simulated Annealing Search",
        new SimulatedAnnealingSearch(new AttackingPairsHeuristic(),
            new Scheduler(20, 0.045, 1000)));
  }

  /** Returns a <code>NQueensView</code> instance. */
  public AgentAppEnvironmentView createEnvironmentView() {
    return new NQueensView();
  }

  /** Returns a <code>NQueensFrame</code> instance. */
  @Override
  public AgentAppFrame createFrame() {
    return new NQueensFrame();
  }

  /** Returns a <code>NQueensController</code> instance. */
  @Override
  public AgentAppController createController() {
    return new NQueensController();
  }

  // ///////////////////////////////////////////////////////////////
  // main method

  /**
   * Starts the application.
   */
  public static void main(String args[]) {
    new NQueensApp().startApplication();
  }

  // ///////////////////////////////////////////////////////////////
  // some inner classes

  /**
   * Adds some selectors to the base class and adjusts its size.
   */
  protected static class NQueensFrame extends AgentAppFrame {
    private static final long serialVersionUID = 1L;
    public static String ENV_SEL = "EnvSelection";
    public static String PROBLEM_SEL = "ProblemSelection";
    public static String SEARCH_SEL = "SearchSelection";

    public NQueensFrame() {
      setTitle("N-Queens Application");
      setSelectors(new String[] { ENV_SEL, PROBLEM_SEL, SEARCH_SEL },
          new String[] { "Select Environment",
              "Select Problem Formulation", "Select Search" });
      setSelectorItems(ENV_SEL, new String[] { "4 Queens", "8 Queens",
          "16 Queens", "32 Queens" }, 1);
      setSelectorItems(PROBLEM_SEL, new String[] { "Incremental",
          "Complete-State" }, 0);
      setSelectorItems(SEARCH_SEL, (String[]) SEARCH_NAMES
          .toArray(new String[] {}), 0);
      setEnvView(new NQueensView());
      setSize(800, 600);
    }
  }

  /**
   * Displays the informations provided by a <code>NQueensEnvironment</code>
   * on a panel.
   */
  protected static class NQueensView extends AgentAppEnvironmentView
      implements ActionListener {
    private static final long serialVersionUID = 1L;
    protected JButton[] squareButtons;
    protected int currSize = -1;

    protected NQueensView() {
    }

    @Override
    public void setEnvironment(Environment env) {
      super.setEnvironment(env);
      showState();
    }

    /** Agent value null indicates a user initiated action. */
    @Override
    public void agentActed(Agent agent, Action action,
        EnvironmentState resultingState) {
      showState();
      notify((agent == null ? "User: " : "") + action.toString());
    }

    @Override
    public void agentAdded(Agent agent, EnvironmentState resultingState) {
      showState();
    }

    /**
     * Displays the board state by labeling and coloring the square buttons.
     */
    protected void showState() {
      NQueensBoard board = ((NQueensEnvironment) env).getBoard();
      if (currSize != board.getSize()) {
        currSize = board.getSize();
        removeAll();
        setLayout(new GridLayout(currSize, currSize));
        squareButtons = new JButton[currSize * currSize];
        for (int i = 0; i < currSize * currSize; i++) {
          JButton square = new JButton("");
          square.setMargin(new Insets(0, 0, 0, 0));
          square
              .setBackground((i % currSize) % 2 == (i / currSize) % 2 ? Color.WHITE
                  : Color.LIGHT_GRAY);
          square.addActionListener(this);
          squareButtons[i] = square;
          add(square);
        }
      }
      for (int i = 0; i < currSize * currSize; i++)
        squareButtons[i].setText("");
      Font f = new java.awt.Font(Font.SANS_SERIF, Font.PLAIN, Math.min(
          getWidth(), getHeight())
          * 3 / 4 / currSize);
      for (XYLocation loc : board.getQueenPositions()) {
        JButton square = squareButtons[loc.getXCoOrdinate()
            + loc.getYCoOrdinate() * currSize];
        square.setForeground(board.isSquareUnderAttack(loc) ? Color.RED
            : Color.BLACK);
        square.setFont(f);
        square.setText("Q");
      }
      validate();
    }

    /**
     * When the user presses square buttons the board state is modified
     * accordingly.
     */
    @Override
    public void actionPerformed(ActionEvent ae) {
      for (int i = 0; i < currSize * currSize; i++) {
        if (ae.getSource() == squareButtons[i]) {
          NQueensController contr = (NQueensController) getController();
          XYLocation loc = new XYLocation(i % currSize, i / currSize);
          contr.modifySquare(loc);
        }
      }
    }
  }

  /**
   * Defines how to react on standard simulation button events.
   */
  protected static class NQueensController extends AgentAppController {

    protected NQueensEnvironment env = null;
    protected SearchAgent agent = null;
    protected boolean boardDirty;

    /** Prepares next simulation. */
    @Override
    public void clear() {
      prepare(null);
    }

    /**
     * Creates an n-queens environment and clears the current search agent.
     */
    @Override
    public void prepare(String changedSelector) {
      AgentAppFrame.SelectionState selState = frame.getSelection();
      NQueensBoard board = null;
      switch (selState.getValue(NQueensFrame.ENV_SEL)) {
      case 0: // 4 x 4 board
        board = new NQueensBoard(4);
        break;
      case 1: // 8 x 8 board
        board = new NQueensBoard(8);
        break;
      case 2: // 8 x 8 board
        board = new NQueensBoard(16);
        break;
      case 3: // 32 x 32 board
        board = new NQueensBoard(32);
        break;
      }
      env = new NQueensEnvironment(board);
      if (selState.getValue(NQueensFrame.PROBLEM_SEL) == 1)
        for (int i = 0; i < board.getSize(); i++)
          board.addQueenAt(new XYLocation(i, 0));
      boardDirty = false;
      agent = null;
      frame.getEnvView().setEnvironment(env);
    }

    /**
     * Creates a new search agent and adds it to the current environment if
     * necessary.
     */
    protected void addAgent() throws Exception {
      if (agent != null && agent.isDone()) {
        env.removeAgent(agent);
        agent = null;
      }
      if (agent == null) {
        int pSel = frame.getSelection().getValue(
            NQueensFrame.PROBLEM_SEL);
        int sSel = frame.getSelection().getValue(
            NQueensFrame.SEARCH_SEL);
        ActionsFunction af;
        if (pSel == 0)
          af = NQueensFunctionFactory.getIActionsFunction();
        else
          af = NQueensFunctionFactory.getCActionsFunction();
        Problem problem = new Problem(env.getBoard(), af,
            NQueensFunctionFactory.getResultFunction(),
            new NQueensGoalTest());
        Search search = SEARCH_ALGOS.get(sSel);
        agent = new SearchAgent(problem, search);
        env.addAgent(agent);
      }
    }

    /** Checks whether simulation can be started. */
    @Override
    public boolean isPrepared() {
      int problemSel = frame.getSelection().getValue(
          NQueensFrame.PROBLEM_SEL);
      return problemSel == 1
          || (agent == null || !agent.isDone())
          && (!boardDirty || env.getBoard()
              .getNumberOfQueensOnBoard() == 0);
    }

    /** Starts simulation. */
    @Override
    public void run(MessageLogger logger) {
      logger.log("<simulation-log>");
      try {
        addAgent();
        while (!agent.isDone() && !frame.simulationPaused()) {
          Thread.sleep(200);
          env.step();
        }
      } catch (InterruptedException e) {
        // nothing to do...
      } catch (Exception e) {
        e.printStackTrace(); // probably search has failed...
      }
      logger.log(getStatistics());
      logger.log("</simulation-log>\n");
    }

    /** Executes one simulation step. */
    @Override
    public void step(MessageLogger logger) {
      try {
        addAgent();
        env.step();
      } catch (Exception e) {
        e.printStackTrace(); // probably search has failed...
      }
    }

    /** Updates the status of the frame after simulation has finished. */
    public void update(SimulationThread simulationThread) {
      if (simulationThread.isCanceled()) {
        frame.setStatus("Task canceled.");
      } else if (frame.simulationPaused()) {
        frame.setStatus("Task paused.");
      } else {
        frame.setStatus("Task completed.");
      }
    }

    /** Provides a text with statistical information about the last run. */
    private String getStatistics() {
      StringBuffer result = new StringBuffer();
      Properties properties = agent.getInstrumentation();
      Iterator<Object> keys = properties.keySet().iterator();
      while (keys.hasNext()) {
        String key = (String) keys.next();
        String property = properties.getProperty(key);
        result.append("\n" + key + " : " + property);
      }
      return result.toString();
    }

    public void modifySquare(XYLocation loc) {
      boardDirty = true;
      String atype;
      if (env.getBoard().queenExistsAt(loc))
        atype = QueenAction.REMOVE_QUEEN;
      else
        atype = QueenAction.PLACE_QUEEN;
      env.executeAction(null, new QueenAction(atype, loc));
      agent = null;
      frame.updateEnabledState();
    }
  }

  /** Simple environment maintaining just the current board state. */
  public static class NQueensEnvironment extends AbstractEnvironment {
    NQueensBoard board;

    public NQueensEnvironment(NQueensBoard board) {
      this.board = board;
    }

    public NQueensBoard getBoard() {
      return board;
    }

    /**
     * Executes the provided action and returns null.
     */
    @Override
    public EnvironmentState executeAction(Agent agent, Action action) {
      if (action instanceof QueenAction) {
        QueenAction act = (QueenAction) action;
        XYLocation loc = new XYLocation(act.getX(), act.getY());
        if (act.getName() == QueenAction.PLACE_QUEEN)
          board.addQueenAt(loc);
        else if (act.getName() == QueenAction.REMOVE_QUEEN)
          board.removeQueenFrom(loc);
        else if (act.getName() == QueenAction.MOVE_QUEEN)
          board.moveQueenTo(loc);
        if (agent == null)
          updateEnvironmentViewsAgentActed(agent, action, null);
      }
      return null;
    }

    /** Returns null. */
    @Override
    public EnvironmentState getCurrentState() {
      return null;
    }

    /** Returns null. */
    @Override
    public Percept getPerceptSeenBy(Agent anAgent) {
      return null;
    }
  }
}
TOP

Related Classes of aima.gui.applications.search.games.NQueensApp$NQueensEnvironment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.