package aima.core.search.framework; import java.util.ArrayList; import java.util.List; import aima.core.agent.Action; import aima.core.agent.Percept; import aima.core.agent.State; import aima.core.agent.impl.AbstractAgent; import aima.core.agent.impl.NoOpAction; import aima.core.search.framework.problem.Problem; import aima.core.util.Util; /** * Artificial Intelligence A Modern Approach (3rd Edition): Figure 3.1, page 67.<br> * <br> * * <pre> * function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action * persistent: seq, an action sequence, initially empty * state, some description of the current world state * goal, a goal, initially null * problem, a problem formulation * * state <- UPDATE-STATE(state, percept) * if seq is empty then * goal <- FORMULATE-GOAL(state) * problem <- FORMULATE-PROBLEM(state, goal) * seq <- SEARCH(problem) * if seq = failure then return a null action * action <- FIRST(seq) * seq <- REST(seq) * return action * </pre> * * Figure 3.1 A simple problem-solving agent. It first formulates a goal and a * problem, searches for a sequence of actions that would solve the problem, and * then executes the actions one at a time. When this is complete, it formulates * another goal and starts over.<br> * * @author Ciaran O'Reilly * @author Mike Stampone */ public abstract class SimpleProblemSolvingAgent extends AbstractAgent { // seq, an action sequence, initially empty private List<Action> seq = new ArrayList<Action>(); // private boolean formulateGoalsIndefinitely = true; private int maxGoalsToFormulate = 1; private int goalsFormulated = 0; /** * Constructs a simple problem solving agent which will formulate goals * indefinitely. */ public SimpleProblemSolvingAgent() { formulateGoalsIndefinitely = true; } /** * Constructs a simple problem solving agent which will formulate, at * maximum, the specified number of goals. * * @param maxGoalsToFormulate * the maximum number of goals this agent is to formulate. */ public SimpleProblemSolvingAgent(int maxGoalsToFormulate) { formulateGoalsIndefinitely = false; this.maxGoalsToFormulate = maxGoalsToFormulate; } // function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action @Override public Action execute(Percept p) { Action action = NoOpAction.NO_OP; // state <- UPDATE-STATE(state, percept) updateState(p); // if seq is empty then do if (0 == seq.size()) { if (formulateGoalsIndefinitely || goalsFormulated < maxGoalsToFormulate) { if (goalsFormulated > 0) { notifyViewOfMetrics(); } // goal <- FORMULATE-GOAL(state) Object goal = formulateGoal(); goalsFormulated++; // problem <- FORMULATE-PROBLEM(state, goal) Problem problem = formulateProblem(goal); // seq <- SEARCH(problem) seq.addAll(search(problem)); if (0 == seq.size()) { // Unable to identify a path seq.add(NoOpAction.NO_OP); } } else { // Agent no longer wishes to // achieve any more goals setAlive(false); notifyViewOfMetrics(); } } if (seq.size() > 0) { // action <- FIRST(seq) action = Util.first(seq); // seq <- REST(seq) seq = Util.rest(seq); } return action; } // // PROTECTED METHODS // protected abstract State updateState(Percept p); protected abstract Object formulateGoal(); protected abstract Problem formulateProblem(Object goal); protected abstract List<Action> search(Problem problem); protected abstract void notifyViewOfMetrics(); }