001    package aima.basic.vaccum;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    import java.util.Map;
006    
007    import aima.basic.AgentProgram;
008    import aima.basic.Percept;
009    import aima.basic.PerceptSequence;
010    import aima.util.Table;
011    
012    /**
013     * Artificial Intelligence A Modern Approach (2nd Edition): Figure 2.7, page 45.
014     * <code>
015     * function TABLE-DRIVEN-AGENT(percept) returns an action
016     *   static: percepts, a sequence, initially empty
017     *           table, a table of actions, indexed by percept sequences, initially fully specified
018     *           
019     *   append percept to end of percepts
020     *   action <- LOOKUP(percepts, table)
021     *   
022     *   return action
023     * </code>
024     * Figure 2.7 The TABLE-DRIVEN-AGENT program is invoked for each new percept and 
025     * returns an action each time. It keeps track of the percept sequence using its own private data
026     * structure.
027     */
028    
029    /**
030     * @author Ciaran O'Reilly
031     * 
032     */
033    public class TableDrivenAgentProgram extends AgentProgram {
034            // Used to define No Operations/Action is to be performed.
035            public static final String NO_OP = "NoOP";
036    
037            private PerceptSequence percepts = new PerceptSequence();
038    
039            private Table<PerceptSequence, String, String> table;
040    
041            private static final String ACTION = "action";
042    
043            // static: percepts, a sequence, initially empty
044            // table, a table of actions, indexed by percept sequences, initially fully
045            // specified
046            public TableDrivenAgentProgram(
047                            Map<PerceptSequence, String> perceptSequenceActions) {
048                    List<PerceptSequence> rowHeaders = new ArrayList<PerceptSequence>(
049                                    perceptSequenceActions.keySet());
050    
051                    List<String> colHeaders = new ArrayList<String>();
052                    colHeaders.add(ACTION);
053    
054                    table = new Table<PerceptSequence, String, String>(rowHeaders,
055                                    colHeaders);
056    
057                    for (PerceptSequence row : rowHeaders) {
058                            table.set(row, ACTION, perceptSequenceActions.get(row));
059                    }
060            }
061    
062            // function TABLE-DRIVEN-AGENT(percept) returns an action
063            @Override
064            public String execute(Percept percept) {
065                    // append percept to end of percepts
066                    percepts.append(percept);
067    
068                    // action <- LOOKUP(percepts, table)
069                    // return action
070                    return lookupCurrentAction();
071            }
072    
073            //
074            // PRIVATE METHODS
075            //
076            private String lookupCurrentAction() {
077                    String action;
078    
079                    action = table.get(percepts, ACTION);
080                    if (null == action) {
081                            action = NO_OP;
082                    }
083    
084                    return action;
085            }
086    }