001 package aima.search.framework; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 import aima.basic.Agent; 006 import aima.basic.Percept; 007 import aima.util.Util; 008 009 /** 010 * Artificial Intelligence A Modern Approach (2nd Edition): Figure 3.1, page 61. 011 * <code> 012 * function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action 013 * inputs: percept, a percept 014 * static: seq, an action sequence, initially empty 015 * state, some description of the current world state 016 * goal, a goal, initially null 017 * problem, a problem formulation 018 * 019 * state <- UPDATE-STATE(state, percept) 020 * if seq is empty then do 021 * goal <- FORMULATE-GOAL(state) 022 * problem <- FORMULATE-PROBLEM(state, goal) 023 * seq <- SEARCH(problem) 024 * action <- FIRST(seq) 025 * seq <- REST(seq) 026 * </code> 027 * Figure 3.1 A simple problem-solving agent. It first formulates a goal and a problem, 028 * searches for a sequence of actions that would solve the problem, and then executes the actions 029 * one at a time. When this is complete, it formulates another goal and starts over. Note that 030 * when it is executing the sequence it ignores its percepts: it assumes that the solution it has 031 * found will always work. 032 */ 033 034 /** 035 * @author Ciaran O'Reilly 036 * 037 */ 038 public abstract class SimpleProblemSolvingAgent extends Agent { 039 040 // seq, an action sequence, initially empty 041 private List<String> seq = new ArrayList<String>(); 042 043 // 044 private boolean formulateGoalsIndefinitely = true; 045 046 private int maxGoalsToFormulate = 1; 047 048 private int goalsFormulated = 0; 049 050 public SimpleProblemSolvingAgent() { 051 formulateGoalsIndefinitely = true; 052 } 053 054 public SimpleProblemSolvingAgent(int maxGoalsToFormulate) { 055 formulateGoalsIndefinitely = false; 056 this.maxGoalsToFormulate = maxGoalsToFormulate; 057 } 058 059 // function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns an action 060 @Override 061 public String execute(Percept p) { 062 String action = NO_OP; 063 064 // state <- UPDATE-STATE(state, percept) 065 Object state = updateState(p); 066 // if seq is empty then do 067 if (0 == seq.size()) { 068 if (formulateGoalsIndefinitely 069 || goalsFormulated < maxGoalsToFormulate) { 070 if (goalsFormulated > 0) { 071 notifyViewOfMetrics(); 072 } 073 // goal <- FORMULATE-GOAL(state) 074 Object goal = formulateGoal(); 075 goalsFormulated++; 076 // problem <- FORMULATE-PROBLEM(state, goal) 077 Problem problem = formulateProblem(goal); 078 // seq <- SEARCH(problem) 079 seq.addAll(search(problem)); 080 if (0 == seq.size()) { 081 // Unable to identify a path 082 seq.add(NO_OP); 083 } 084 } else { 085 // Agent no longer wishes to 086 // achieve any more goals 087 die(); 088 notifyViewOfMetrics(); 089 } 090 } 091 092 if (seq.size() > 0) { 093 // action <- FIRST(seq) 094 action = Util.first(seq); 095 // seq <- REST(seq) 096 seq = Util.rest(seq); 097 } 098 099 return action; 100 } 101 102 // 103 // PROTECTED METHODS 104 // 105 protected abstract Object updateState(Percept p); 106 107 protected abstract Object formulateGoal(); 108 109 protected abstract Problem formulateProblem(Object goal); 110 111 protected abstract List<String> search(Problem problem); 112 113 protected abstract void notifyViewOfMetrics(); 114 }