Requirements
- Knowledge of the CST Core
- Knowledge of the SOAR rules
- (Optional) Install the DemoCST using SOAR
SOAR processing cycle
SOAR is a well-established cognitive architecture that has been developed for over 40 years. It is defined as a general cognitive architecture that integrates knowledge-intensive reasoning, reactive execution, hierarchical reasoning, planning, and learning (Laird 2012). Due to the importance of this architecture, a binding was developed for its use within CST.
The SOAR processing cycle can be seen in figure below. For it to function, the system’s programmer/user must define a set of rules, and in the case of using an external simulator, handle the processing of input and output, which is the method of communication between SOAR and the external environment. We provide the environment's information through the Input, which is represented in the Working Memory (WM) by the input-link, and the result is provided through the Output, represented by the output-link.
Example program DemoCST with SOAR
You can download an example usind the SOAR Binding in CST. In this example we control a creature that eats food and gets jewels in the simulated environment WS3D.
After downloading you can run the simultador running the script.sh and the program using the "Play" button in your Java IDE. You can use this program example to follow our tutorial.
Creating the SoarCodelet
CST-bindings provides the class JSoarCodelet that enables connection with SOAR via the input-link and output-link, and allows the definition of SOAR rules. These rules must be created by the user and require additional study to understand. In this tutorial, we will show how to use SOAR in a CST based project.
To create a SoarCodelet class that inherits from JSoarCodelet:
public class SoarCodelet extends JSoarCodelet {
It is also necessary to create the initializer. It receives agentName (the name of the agent controlled by the architecture), productionPath (path to the file that contains the SOAR rules, with .soar extension), and startSOARDebugger (indicates whether the SOARDebugger should be initialized).
The initSoarPlugin() method uses these parameters and is responsible for initializing SOAR.
public class SoarCodelet extends JSoarCodelet {
public SoarCodelet(String agentName, File productionPath, Boolean startSOARDebugger) {
initSoarPlugin(agentName, productionPath, startSOARDebugger);
this.name = "SoarCodelet";
}
This is how the class looks like without implementations:
public class SoarCodelet extends JSoarCodelet {
public SoarCodelet(String agentName, File productionPath, Boolean startSOARDebugger) {
initSoarPlugin(agentName, productionPath, startSOARDebugger);
this.name = "SoarCodelet";
}
@Override
public void accessMemoryObjects() {
}
@Override
public void calculateActivation() {
}
@Override
public void proc() {
}
}
Defining the input-link
To execute SOAR cognitive cycles, we must first define the input-link:
@Override
public void proc() {
setInputLinkIdea(inputLinkIdea);
...
}
The method receives the input-link in the format of an Idea, which is the knowledge representation format used by CST. An example of creating the input-link:
private Idea inputLinkIdea;
...
Idea creatureIdea = new Idea("CREATURE");
Idea positionIdea = new Idea("POSITION");
Idea creaturePositionXIdea = new Idea("X", c.getPosition().getX());
Idea creaturePositionYIdea = new Idea("Y", c.getPosition().getY());
positionIdea.add(creaturePositionXIdea);
positionIdea.add(creaturePositionYIdea);
creatureIdea.add(positionIdea);
inputLinkIdea.add(creatureIdea);
Executing the SOAR cycle
To execute a complete SOAR processing cycle, we run the following command in the proc() method, first checking whether it is not in debug mode (in this mode, we want to execute each step of the cycle individually instead of the entire cycle):
@Override
public void proc() {
setInputLinkIdea(inputLinkIdea);
if (getDebugState() == 0) {
getJsoar().step();
}
...
}
JSoarCodelet class provides other public methods that can be used to run each step of the cycle individually, but here we use step() to run the entire cycle.
Retrieving the output-link
After its execution, we can access the Output, or the output-link. It is also represented as an Idea and can be obtained using the following method:
@Override
public void proc() {
setInputLinkIdea(inputLinkIdea);
if (getDebugState() == 0) {
getJsoar().step();
}
Idea soarOutputLink = getJsoar().getOutputLinkIdea();
...
}
To access the contents of the output-link, we must use the standard methods for accessing Ideas:
- Using the get(String path) method by passing the path to the Idea as a parameter, using a dot (.) for each level when accessing a child Idea:
Idea moveIdea = outputLinkIdea.get("COMMAND.MOVE");
- Using getL() to retrieve all Idea children:
List<Idea> ideaL = outputLinkIdea.getL();
- Using getValue() to get the value of the Idea:
- Generally, in the case of the input-link and output-link, the root Idea (the first Idea) has a null value, since it usually only contains children:
Object ideaValue = outputLinkIdea.getValue();
Instantiating the SoarCodelet
This is how we instantiate the SoarCodelet (usually in an AgentMind class):
public class AgentMindJSoar extends Mind {
...
public static final String SOAR_FILE_RULES_PATH = "/rules/soar-rules.soar";
...
public AgentMindJSoar(Creature creature, String name) {
...
try {
NativeUtils.loadFileFromJar(SOAR_FILE_RULES_PATH);
} catch (IOException ex) {
Logger.getLogger(AgentMindJSoar.class.getName()).log(Level.SEVERE, null, ex);
}
JSoarCodelet soarCodelet = new SoarCodelet(creature.getName(), new File(SOAR_RULES_PATH), false);
...
}
This allows the use of this JSoarCodelet within the agent’s mind. Its function depends on the rules created in the SOAR rules, and it can work as a decision-maker creating reactive behavior. It can also perform planning toward a goal through deliberative reasoning. SOAR also has other functionalities that can be used to improve the cognitive process, such as episodic memory, learning, among other functions. More about can be found in the SOAR website.
Visualizing SOAR
Some information about the JSoarCodelet, such as the input-link and output-link used, can be viewed through a specific tab in the MindViewer. To do this, it is necessary to register this codelet in the "Planning" group – it must be exactly this text, as that is how the MindViewer identifies whether there is a JSoarCodelet.
JSoarCodelet soarCodelet = new SoarCodelet(creature.getName(), new File(SOAR_RULES_PATH), false);
soarCodelet.addInput(inputLinkMO);
soarCodelet.addOutput(outputLinkMO);
insertCodelet(soarCodelet);
registerCodelet(soarCodelet,"Planning");
This is how the MindViewer visualization appears, in the Plans Subsystem tab:
You can also enter in debug state of SOAR, running each step and visualizing the WMEs and the selected Operators. For that you can use the tools:
This is how you see the MindViewer in the Debug State of SOAR:
Debugging SOAR Rules
This is an alternative for a JSoar debugger, developed as a personal project by professor Ricardo Gudwin. You can donwload directly the .jar file from the latest version, and then run in terminal (changing the version if its the case):
java -jar JSoarDebugger-0.0.3.jar
This is how the Debugger looks like, they have a default rules as an example mac.soar. We can observe the empty Input Link, the working memory elements in the Working Memory and the plan in the Output Link.
In this Debugger you can Load files with your Soar Rules and the Input-link (if necessary):
You can run each step of the SOAR cycle or run the entiry cycle (until HALT in SOAR Rules) using the blue buttons in the top left.
Conclusion
By concluding this trail, you have studied how to use SOAR inside CST. Now you can use this in your own project.
References
(Laird 2012) J. Laird. The Soar Cognitive Architecture. MIT Press, 2012.