Skip to content

Understanding the "Hello World!" Model

githubjimmyd edited this page Sep 28, 2023 · 15 revisions

At this point you should have successfully run the "Hello World!" model in Python ACT-R. If not, go back to Running "Hello World!" in Python ACT-R

In this lesson, we will go over the code in this model so you understand it. If you don't know how to program any Python, that's fine, this tutorial will tell you what you need. If you already know Python, please understand that in Python ACT-R many normal Python functions have been redefined, so things might not always work the way you are used to.

You should have already downloaded the code, but if not, here it is:

Hello World! Python ACT-R code

The First Line

Let's look at line 1.

from python_actr import *              ## Imports the code you need to run Python ACT-R

This code goes at the beginning of every model. It tells the Python interpreter that this file is a Python ACT-R model and it should use Python ACT-R to run it. It means "use all of the code from python_actr." The "*" means "everything."

After that you see

## Imports the code you need to run Python ACT-R

This is known as a "comment." it is text that is there to help the programmer/modeller understand the code, but the computer ignores it. When you see a "#", the rest of the line is a comment.

There is another use for comments, and that is to "comment out" code. That is, while you are debugging you might want to keep a line of code around, but not have it interpreted for now. You put a "#" before it, and it renders that line a comment.

Because these are different uses of the comment feature, sometimes you will see a single "#" for commenting out code, and "##" for comments that are not code and are there for explanation.

Lines 3-4

Lines three and four are these:

class MyAgent(ACTR):                   ## Each agent will be an instance of the class MyAgent,
                                       ##    which is a subclass of the class ACTR

Python ACT-R is written with an "object-oriented" programming style. This means there are categories, called classes, and members of those categories, called instances.

In this case, we are defining a class called "MyAgent" that inherits the properties of something called "ACTR." We won't worry about this "ACTR" parent class.

On line 13 we will make an instance of this class, called tim. But for now, we are just going to specify what is true for all instances of this class.

Line 6

Line six is

focus=Buffer()                     ## There is a memory buffer called focus

Here we are defining a new variable called "focus." It is an instance of the object "Buffer." This means that in the Python ACT-R code there is a class definition of a memory buffer, and we are creating an instance of it for MyAgent (and calling it "focus.")

Line 7

focus.set('greeting:hello')        ## We set the focus to the task of greeting.

Now that "focus" is an instance of a memory buffer, we can take advantage of the methods and attributes defined for all Buffers. An attribute is a piece of data, and a method is a piece of code that can run. In this line, we are using the method "set" set the current goal to the value "greeting:hello".

What is "greeting:hello"? In ACT-R's declarative memory, we have slots and values. For example, a slot might be "name" and the value might be "Corey." A slot is like a variable that can take multiple values. In this case, we the slot is "greeting" and the value is "hello." This is our first "chunk." A chunk is described in code by having two symbols with a colon in between.

This is going to function as a goal for our agent. In other words, the agent has a goal to greet someone, and instead of greeting them with something else, like "how's the rain on the rhubarb?" it will greet with "hello." The focus buffer will hold the agent's current goal.

Lines 9-11

    def hello(focus='greeting:hello'): ## if focus buffer has this thing in it
        print("hello world!")          ## print something
        focus.set('greeting:stop')     ## change chunk in focus buffer. Required for it to stop.

On these lines we define a method for the class. This is how we define "productions" for the production system. A production is a data structure in artificial intelligence that has two parts: a left-hand side and a right-hand side.

The left-hand side of a production describes the conditions under which the production can possibly "fire." Any production whose left-hand side matches the current state of the environment and memory is said to "match." A production system will fire one of the productions that match.

When a production fires, it executes the commands of the right-hand side. So a production is an "IF-DO" description, like "if there is peanut butter and you are hungry, eat it."

On line 9 we define the production with the name "hello." Further, we define the left-hand side in the parentheses.

In this case, the left-hand side, the condition under which the production can match, is

focus='greeting:hello'

Which means that the production will match on the condition that the value of "focus" (defined on line 6) happens to equal "greeting:hello". We set it to be so on line 7, so this production will match.

On lines 10 and 11 we have the right-hand side of the "hello" production, which consists of two commands.

        print("hello world!")          ## print something

Line 10 simply outputs the text "hello world!" to the console. This is meant to be a place holder for our agent saying or typing something.

        focus.set('greeting:stop')     ## change chunk in focus buffer. Required for it to stop.

Line 11 changes what the goal of the agent is. The goal was to say greet with a hello, but now that it has done that, it's time to remove, or "pop" that goal. We do this by replacing it with another goal, to stop.

Note that we redefine focus.set just like we did on line 7. But in this case, we define it as "greeting:stop". Once the focus is no longer "greeting:hello" the hello production will not match and the agent will not do anything (as there is no other production with "greeting:stop" as its left-hand side.)

Line 13

Here we actually create our agent, tim. The agent tim is an instance of the class MyAgent, which we defined on line 3.

tim=MyAgent()                          ## Create an instance of MyAgent called tim

The parentheses are there to take in any additional information that MyAgent might need to create an instance. Because it doesn't need any information, these parentheses are empty.

Line 14

Line 14 takes the agent tim and runs the model.

tim.run()                              ## Now tim has a focus and something to do, so run tim.

This is how you make an agent do anything: you activate the run() method. When you do this, Python ACT-R will look at matching productions and fire them until there is nothing left to do.

Next: (coming soon)

Back to the Tutorials main page.