;;;;;;;;;;;;;;;;;;;;;;;;
If your browser supports JAVA, you can display the data in a graph by checking the Graphic output box on the interface page.;;; ;;; This file contains the ACT-R model of the ;;; Roberts free recall experiment ;;; presented in Chapter 7 ;;; ;;; ACT-R version 4 required ;;; ;;; A WWW interface and a command line interface ;;; are provided. ;;; To run the command line version, call ;;; (do-roberts n) ;;; replacing n with the number of runs to ;;; simulate. ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This section contains the LISP functions to simulate ;;; the experiment, implement the interface, collect the ;;; data, and display the results ;;; ;;; The ACT-R Model starts further down ;;; ;;; Global variables (defvar *stop-it*) (defvar *history*) (defvar *items*) (defvar *data*) (defvar *index*) (defvar *counter*) (defvar *predictions*) (defvar *inc*) (defvar *results*) (defparameter *respond* .5) (defparameter *encode* .2) (defparameter *factor* 2) (defparameter *thresh* 2.9) (defparameter *noise* .85) (defparameter *rehearsal* 0.5) (defparameter *v* nil) (defparameter *text* t) (defparameter *graphic* nil) (defparameter *overlay* nil) (defparameter *runs* 1) (defparameter *roberts-contexts* '(l1 l2 l3 l4 l5 l6 l7 l8 l9 l10 l11 l12 l13 l14 l15 l16 l17 l18 l19 l20)) (defparameter *roberts-results* (make-array '(20) :initial-contents '(6.25 7.50 8.50 9.00 7.25 9.75 11.00 12.50 8.00 12.50 15.00 16.00 8.50 14.00 17.50 21.00 9.00 15.75 20.00 24.00))) (defparameter *roberts-headers* '(".5" " 1" " 2" " 4" " 8")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This section contains the interface for the WWW using the ;;; ACT-R on the Web application by Elmar Schwarz (defvar *WWW-interface*) (setf *WWW-interface* '((:heading "Roberts Experiment model" 2) (:table) (:table) "Noise (s): " (:string :sy *noise* .85) (:new-row) "Threshold: " (:string :sy *thresh* 2.9) (:new-row) "Factor (F):" (:string :sy *factor* 2) (:new-row) "Response time (sec.): " (:string :sy *respond* .5) (:new-row) "Encoding time (sec.): " (:string :sy *encode* .2) (:new-row) "Rehearsal time (sec.): " (:string :sy *rehearsal* .5) (:new-row) "Number of runs (1-20): " (:string :sy *runs* 1) (:table-end) (:table) (:checkbox "Trace" :sy *v* nil) (:new-row) (:checkbox "Text output" :sy *text* t) (:new-row) (:checkbox "Graphic output" :sy *graphic* nil) (:new-row) (:checkbox "Show simulation and experiment data on one graph" :sy *overlay* nil) (:table-end) (:table-end) (:new-para) (:button "Show Experiment Results" "(display-roberts-data *roberts-results* nil)") (:new-para) (:button "Run model" "(if (and (numberp *thresh*) (numberp *noise*) (numberp *noise*) (numberp *runs*) (numberp *encode*) (numberp *rehearsal*) (numberp *respond*)) (do-roberts (min 20 (max 1 *runs*))) (format *standard-output* \"All parameters must be numbers\"))") (:reset "Default values") (:button "Production Rules" "(let ((prods (no-output (pp)))) (dolist (x prods) (pp-fct (list x)) (spp-fct (list x)) (format *standard-output* \"~%\")))") (:button "Chunk types" "(chunk-type)") (:button "Chunks" "(dm)") (:new-para) "TIME and SIZE:" (:new-para) "- It usually takes less than 1 minute for 1 run of the model" (:new-line) "- The trace of 1 run is approximatly 400k (250 pages) in size" (:new-para))) ;;; reset-wme-number-roberts takes one parameter ;;; which is ignored, and sets the number of ;;; chunks to be 100 ;;; this function is hooked to the actr ;;; cycle-hook-fn, so that the number ;;; of chunks is always 100 ;;; to prevent problems with ia's ;;; changing for the different size lists (defun reset-wme-number-roberts (instantiation) (declare (ignore instantiation)) (setf *wme-number* 100)) ;;; display-roberts-data takes 1 parameter ;;; an array containg data for a simulation ;;; of the roberts experiment, and it displays ;;; a table showing the data from the array (defun display-roberts-data (data simulation) (when simulation (format *standard-output* "~%~%Parameters for run (~S ~S ~S ~S ~S ~S ~S)~%" *noise* *thresh* *factor* *respond* *encode* *rehearsal* *runs*)) (when *text* (format *standard-output* "~%~a data (number of items recalled):~%~%" (if simulation "Simulation" "Experimental")) (format *standard-output* " List Length~%") (format *standard-output* " 10 20 30 40~%") (format *standard-output* "delay (sec)~%") (dotimes (i 5) (format *standard-output* "~A " (nth i *roberts-headers*)) (dotimes (j 4) (format *standard-output* "~5,2F " (aref data (+ j (* i 4))))) (format *standard-output* "~%")) (when (and simulation *overlay*) (format *standard-output* "~%Experimental data (number of items recalled):~%~%") (format *standard-output* " List Length~%") (format *standard-output* " 10 20 30 40~%") (format *standard-output* "delay (sec)~%") (dotimes (i 5) (format *standard-output* "~A " (nth i *roberts-headers*)) (dotimes (j 4) (format *standard-output* "~5,2F " (aref *roberts-results* (+ j (* i 4))))) (format *standard-output* "~%"))) (unless *graphic* (format *standard-output* "~%
~%~%")))
(when *graphic*
(format *standard-output* "
")))
;;; set-roberts-parameters is used to set
;;; the parameters of the model before each run
;;; it is needed for the WWW interface
(defun set-roberts-parameters ()
(setf *cycle-hook-fn* #'reset-wme-number-roberts)
(sgp-fct (list :bll 0.5 :ans *noise* :rt *thresh* :er t :lf *factor* :v *v*))
(parameters-fct 'create-token (list :effort *encode*))
(parameters-fct 'rehearse-it (list :effort *rehearsal*))
(parameters-fct 'dump-it (list :a *rehearsal*))
(parameters-fct 'recall-a-word (list :effort *respond*)))
;;; setup-roberts takes 2 parameters
;;; a name for a word chunk, and
;;; the number of previous contexts that word occured
;;; in, and returns the list of chunk definitions
;;; for the previous contexts
(defun setup-roberts (word n)
(addwm-fct (list (list word 'isa 'word)))
(do ((count 0 (1+ count))
(result nil (cons `(,(gentemp "C") isa memory-token
context ,(nth count *roberts-contexts*)
name ,word) result)))
((= count n) result)))
;;; setup-roberts-materials takes one parameter
;;; the number of words to create, and
;;; generates the word chunks, and the
;;; previous context chunks for the words,
;;; and then sets the base levels for the items,
;;; and returns the list of word chunk
;;; names
(defun setup-roberts-materials (n)
(do ((count 0 (1+ count))
(items nil (append (setup-roberts (gentemp "I") 1) items)))
((= count n)
(eval `(addwm ,@items))
(setallbaselevels 10 -400)
(remove-duplicates (mapcar 'seventh items)))))
;;; do-roberts takes one parameter
;;; the number of runs to simulate,
;;; and runs the experiment
;;; that many times, displaying a table
;;; of the results when finished
(defun do-roberts (n)
(let ((final (make-array '(20) :initial-element 0)))
(do ((count 0 (1+ count)))
((equal count n) (setf *predictions* final) )
(let ((temp (conditions-roberts)))
(do ((j 0 (1+ j)))
((equal j 20) nil)
(do ((k 0 (1+ k)))
((equal k 40) nil)
(cond ((not (zerop (aref temp j k)))
(setf (aref final j) (1+ (aref final j)))))))))
(dotimes (i 20)
(setf (aref *predictions* i) (/ (aref *predictions* i) n)))
(display-roberts-data *predictions* t)))
;;; conditions-roberts takes no parameters
;;; and runs one simulation of each condition
;;; of the roberts experiment
;;; and returns the data array of the results
(defun conditions-roberts ()
(setf *data* (make-array '(20 40) :initial-element 0))
(reset) (run-roberts-experiment 10 .5 0)
(reset) (run-roberts-experiment 20 .5 1)
(reset) (run-roberts-experiment 30 .5 2)
(reset) (run-roberts-experiment 40 .5 3)
(reset) (run-roberts-experiment 10 1 4)
(reset) (run-roberts-experiment 20 1 5)
(reset) (run-roberts-experiment 30 1 6)
(reset) (run-roberts-experiment 40 1 7)
(reset) (run-roberts-experiment 10 2 8)
(reset) (run-roberts-experiment 20 2 9)
(reset) (run-roberts-experiment 30 2 10)
(reset) (run-roberts-experiment 40 2 11)
(reset) (run-roberts-experiment 10 4 12)
(reset) (run-roberts-experiment 20 4 13)
(reset) (run-roberts-experiment 30 4 14)
(reset) (run-roberts-experiment 40 4 15)
(reset) (run-roberts-experiment 10 8 16)
(reset) (run-roberts-experiment 20 8 17)
(reset) (run-roberts-experiment 30 8 18)
(reset) (run-roberts-experiment 40 8 19)
*data*)
;;; run-roberts-experiment takes 3 parameters,
;;; the number of words for the run, the amount
;;; of time for study (in seconds), and the index
;;; of this condition in the data array *data*
;;; it then runs one simulation of the experiment
;;; using the given number of words and study time
(defun run-roberts-experiment (n time index)
(set-roberts-parameters)
(setf *index* index)
(setf *inc* time)
(let* ((materials (setup-roberts-materials n)))
(setallbaselevels 500 -1000)
(reset-wme-number-roberts nil)
(reset-ia)
(setf *stop-it* 0)
(setf *items* (no-output (wm-fct materials)))
(setf *history* *items*)
(addwm (goal isa study-words context L0))
(wmfocus goal)
(run)
(setf *counter* 1)
(modwme goal position transfer)
(resetia)
(wmfocus goal)
(run)))
;;; analyze-roberts takes one parameter
;;; a word chunk, and updates the results
;;; array for the position of the word in
;;; the study list
(defun analyze-roberts (word)
(setf (aref *data* *index* (position word *history*)) *counter*)
(setf *counter* (1+ *counter*)))
;;; get-word-roberts takes no parameters
;;; and sets the time when the next
;;; study word will be presented
;;; and returns the current word
(defun get-word-roberts ()
(setf *stop-it* (+ *inc* *stop-it*))
(pop *items*))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ACT-R Model of the task
;;;
;;;
(clearall)
(chunk-type study-words first second third fourth position context)
(chunk-type memory-token name status context)
(chunk-type context)
(chunk-type word)
(chunk-type rehearse target)
(chunk-type output target)
(chunk-type recall-words context)
(chunk-type type-word position word)
(chunk-type dump-words first second third fourth position context)
; adds the contexts to working memory
(add-dm (l0 isa context)
(l1 isa context))
(sgp-fct (list :bll 0.5 :ans *noise* :rt *thresh* :er t :lf *factor* :v *v*))
(setallbaselevels 500 -1000)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Productions
;;;
(p high-first
"
IF the goal is to study words
and there is no word in the first position
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
first nil
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
first =newgoal
position first
!push! =newgoal
)
(parameters high-first :r .95)
(p high-second
"
IF the goal is to study words
and there is no word in the second position
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
second nil
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
second =newgoal
position first
!push! =newgoal
)
(parameters high-second :r .95)
(p high-third
"
IF the goal is to study words
and there is no word in the third position
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
third nil
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
third =newgoal
position first
!push! =newgoal
)
(parameters high-third :r .95)
(p high-fourth
"
IF the goal is to study words
and there is no word in the fourth position
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
fourth nil
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
fourth =newgoal
position first
!push! =newgoal
)
(parameters high-fourth :r .95)
(p attend-first
"
IF the goal is to study words
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
first =newgoal
position first
!push! =newgoal
)
(parameters attend-first :r .9)
(p attend-second
"
IF the goal is to study words
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
second =newgoal
position first
!push! =newgoal
)
(parameters attend-second :r .9)
(p attend-third
"
IF the goal is to study words
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
context =context
=goal>
third =newgoal
position first
!push! =newgoal
)
(parameters attend-third :r .9)
(p attend-fourth
"
IF the goal is to study words
and there are items to study
and a new word has been presented
THEN create a memory token chunk
mark the current goal with that
chunk
mark the current goal to start rehearsal
with the first item
and push the new chunk on the goal stack
"
=goal>
isa study-words
context =context
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
name =obj
=goal>
fourth =newgoal
position first
!push! =newgoal
)
(parameters attend-fourth :r .9)
(p create-token
"
IF the goal is a memory token
THEN store the word in the goal
and pop the goal
"
=goal>
isa memory-token
==>
!bind! =name (get-word-roberts)
=goal>
name =name
!pop!
)
(parameters-fct 'create-token (list :effort *encode*))
(p rehearse-it
"
IF the goal is to rehearse an item
and the item is a memory token
THEN pop the goal
"
=goal>
isa rehearse
target =token
=token>
isa memory-token
name =name
==>
!pop!
)
(parameters-fct 'rehearse-it (list :effort *rehearsal*))
(p skip-rehearsal
=goal>
isa rehearse
target =token
==>
!pop!
)
(parameters skip-rehearsal :r .5)
(p rehearse-first
"
IF the goal is to study words
and rehearse the first word
and there is an item in the first position
and the next word has not been presented
yet
THEN create a new goal to rehearse the
first item
and mark the current goal to process the
second item next
and push the new goal
"
=goal>
isa study-words
position first
first =token
!eval! (< (actr-time) *stop-it*)
==>
=subgoal>
isa rehearse
target =token
=goal>
position second
!push! =subgoal
)
(parameters rehearse-first :r .6)
(p rehearse-second
"
IF the goal is to study words
and rehearse the second word
and there is an item in the second position
and the next word has not been presented
yet
THEN create a new goal to rehearse the
second item
and mark the current goal to process the
third item next
and push the new goal
"
=goal>
isa study-words
position second
second =token
!eval! (< (actr-time) *stop-it*)
==>
=subgoal>
isa rehearse
target =token
=goal>
position third
!push! =subgoal
)
(parameters rehearse-second :r .6)
(p rehearse-third
"
IF the goal is to study words
and rehearse the third word
and there is an item in the third position
and the next word has not been presented
yet
THEN create a new goal to rehearse the
third item
and mark the current goal to process the
fourth item next
and push the new goal
"
=goal>
isa study-words
position third
third =token
!eval! (< (actr-time) *stop-it*)
==>
=subgoal>
isa rehearse
target =token
=goal>
position fourth
!push! =subgoal
)
(parameters rehearse-third :r .6)
(p rehearse-fourth
"
IF the goal is to study words
and rehearse the fourth word
and there is an item in the fourth position
and the next word has not been presented
yet
THEN create a new goal to rehearse the
fourth item
and mark the current goal to next process the
first item next
and push the new goal
"
=goal>
isa study-words
position fourth
fourth =token
!eval! (< (actr-time) *stop-it*)
==>
=subgoal>
isa rehearse
target =token
=goal>
position first
!push! =subgoal
)
(parameters rehearse-fourth :r .6)
(p skip-first
"
IF the goal is to study words
and rehearse the first word
and the next word has not been presented yet
THEN mark the goal to rehearse the second position next
"
=goal>
isa study-words
position first
!eval! (< (actr-time) *stop-it*)
==>
=goal>
position second
)
(parameters skip-first :r .3)
(p skip-second
"
IF the goal is to study words
and rehearse the second word
and the next word has not been presented yet
THEN mark the goal to rehearse the third position next
"
=goal>
isa study-words
position second
!eval! (< (actr-time) *stop-it*)
==>
=goal>
position third
)
(parameters skip-second :r .3)
(p skip-third
"
IF the goal is to study words
and rehearse the third word
and the next word has not been presented yet
THEN mark the goal to rehearse the fourth position next
"
=goal>
isa study-words
position third
!eval! (< (actr-time) *stop-it*)
==>
=goal>
position fourth
)
(parameters skip-third :r .3)
(p skip-fourth
"
IF the goal is to study words
and rehearse the fourth word
and the next word has not been presented yet
THEN mark the goal to rehearse the first position next
"
=goal>
isa study-words
position fourth
!eval! (< (actr-time) *stop-it*)
==>
=goal>
position first
)
(parameters skip-fourth :r .3)
(p wait
"
IF the goal is to study words
and no position is marked for rehearsal
and the next word has not been presented yet
THEN mark the goal to rehearse none of the positions
"
=goal>
isa study-words
position nil
!eval! (< (actr-time) *stop-it*)
==>
=goal>
position nil
)
(parameters wait :r .3 :effort .2)
(p start-recall
"
IF the goal is to study words
and it is time to start recalling
THEN create a new goal to dump the
words from the current goal
and create a new goal to recall words
focus on the recall words goal
and then push the dump words goal
"
=goal>
isa study-words
context =context
first =first
second =second
third =third
fourth =fourth
position transfer
==>
=newgoal1>
isa dump-words
first =first
second =second
third =third
fourth =fourth
position first
context =context
=newgoal2>
isa recall-words
context =context
!focus-on! =newgoal2
!push! =newgoal1
)
(p dump-it
"
IF the goal is to output an item
and that item is a memory token
THEN mark the item as recalled
and respond with the item
and pop the goal
"
=goal>
isa output
target =token
=token>
isa memory-token
name =name
==>
=token>
status recalled
!eval! (analyze-roberts =name)
!pop!
)
(parameters-fct 'dump-it (list :a *rehearsal*))
(p skip-dump
=goal>
isa output
==>
!pop!
)
(parameters skip-dump :r .5)
(p dump-first
"
IF the goal is to dump the word
in the first position
and there is an item in the first position
THEN mark the goal to dump the second position next
and create a new goal to output the first item
and push the new goal
"
=goal>
isa dump-words
position first
first =token
==>
=goal>
position second
=subgoal>
isa output
target =token
!push! =subgoal
)
(p dump-first-default
"
IF the goal is to dump the word
in the first position
THEN mark the goal to dump the item in the
second position
"
=goal>
isa dump-words
position first
==>
=goal>
position second
)
(parameters dump-first-default :r .5 )
(p dump-second
"
IF the goal is to dump the word
in the second position
and there is an item in the second position
THEN mark the goal to dump the third position next
and create a new goal to output the second item
and push the new goal
"
=goal>
isa dump-words
position second
second =token
==>
=goal>
position third
=subgoal>
isa output
target =token
!push! =subgoal
)
(p dump-second-default
"
IF the goal is to dump the word
in the second position
THEN mark the goal to dump the item in the
third position
"
=goal>
isa dump-words
position second
==>
=goal>
position third
)
(parameters dump-second-default :r .5)
(p dump-third
"
IF the goal is to dump the word
in the third position
and there is an item in the third position
THEN mark the goal to dump the fourth position next
and create a new goal to output the third item
and push the new goal
"
=goal>
isa dump-words
position third
third =token
==>
=goal>
position fourth
=subgoal>
isa output
target =token
!push! =subgoal
)
(p dump-third-default
"
IF the goal is to dump the word
in the third position
THEN mark the goal to dump the item in the
fourth position
"
=goal>
isa dump-words
position third
==>
=goal>
position fourth
)
(parameters dump-third-default :r .5)
(p dump-fourth
"
IF the goal is to dump the word
in the fourth position
and there is an item in the fourth position
THEN create a new goal to output the fourth item
and focus on the new goal
"
=goal>
isa dump-words
position fourth
fourth =token
==>
=subgoal>
isa output
target =token
!focus-on! =subgoal
)
(p dump-fourth-default
"
IF the goal is to dump the word
in the fourth position
THEN pop the goal
"
=goal>
isa dump-words
position fourth
context =context
==>
!pop!
)
(parameters dump-fourth-default :r .5)
(p recall-a-word
"
IF the goal is to recall words
and a memory token can be recalled
that has not been recalled previously,
and was in the current context
THEN mark the item as recalled
and respond with the word
"
=goal>
isa recall-words
context =context
=token>
isa memory-token
status nil
name =name
context =context
==>
=token>
status recalled
!eval! (analyze-roberts =name)
)
(parameters-fct 'recall-a-word (list :effort *respond*))
(p stop-recall
"
IF the goal is to recall words
THEN pop the goal
"
=goal>
isa recall-words
==>
!pop!
)
(parameters stop-recall :r .25)