;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; This file contains the ACT-R model of the
;;; mirror effect as 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-mirror 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
(defparameter *mirror-contexts* '(l1 l2 l3 l4 l5 l6 l7 l8 l9 l10
l11 l12 l13 l14 l15 l16 l17 l18 l19 l20))
(defvar *stop-it*)
(defvar *items*)
(defvar *ht*)
(defvar *lt*)
(defvar *p*)
(defvar *t*)
(defvar *hf*)
(defvar *lf*)
(defvar *data*)
(defvar *thresh*)
(defvar *penalty*)
(defvar *noise*)
(defvar *runs*)
(defvar *v*)
(defvar *factor*)
(defvar *respond*)
(defvar *encode*)
(defvar *rehearse*)
(setf *factor* 2)
(setf *thresh* 1.8)
(setf *penalty* 20)
(setf *noise* .5)
(setf *runs* 1)
(setf *v* nil)
(setf *respond* .5)
(setf *encode* .2)
(setf *rehearse* .5)
(defparameter *mirror-results* #3a(((613 387) (281 719)) ((704 296) (228 772))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; 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 "Glanzer and Adams Experiment model" 2)
(:table)
(:table)
"Noise (s): " (:string :sy *noise* .5) (:new-row)
"Threshold: " (:string :sy *thresh* 1.8) (:new-row)
"Factor (F):" (:string :sy *factor* 2) (:new-row)
"Penalty: " (:string :sy *penalty* 2.0) (: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 *rehearse* .5) (:new-row)
"Number of runs (1-20): " (:string :sy *runs* 1)
(:table-end)
(:table)
(:checkbox "Trace" :sy *v* nil) (:new-row)
(:table-end)
(:table-end)
(:new-para)
(:button "Show Experiment Results" "(progn
(format *standard-output* \"~%~%Experimental data:~%\")
(mirror-results *mirror-results*))")
(:new-para)
(:button "Run model" "(progn
(when (numberp *penalty*)
(setf *penalty* (* 10 *penalty*)))
(if (and (numberp *thresh*) (numberp *penalty*)
(numberp *noise*) (numberp *factor*)
(numberp *runs*) (numberp *respond*)
(numberp *encode*) (numberp *rehearse*))
(do-mirror (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 about 1 minute for 1 run of the model"
(:new-line)
"- The trace of 1 run is approximatly 120k (80 pages) in size"
(:new-para)))
;;; set-mirror-params is used to set
;;; the parameters of the model before each run
;;; it is needed for the WWW interface
(defun set-mirror-params ()
(sgp-fct (list :bll .5 :ans *noise* :mp *penalty*
:pm t :rt *thresh* :lf *factor* :v *v*))
(parameters-fct 'reject-a-word-2 (list :r .5 :effort *respond*))
(parameters-fct 'accept-word (list :effort *respond*))
(parameters-fct 'attend-test (list :a *encode* :effort *encode*))
(parameters-fct 'rehearse-token (list :effort *rehearse*))
(parameters-fct 'attend (list :effort *encode*)))
;;; mirror-setup takes 2 parameters
;;; a word and the number of previous
;;; contexts for that word
;;; and adds a chunk for that word
;;; and returns a list of chunk
;;; definitions for the previous
;;; memory tokens
(defun mirror-setup (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 *mirror-contexts*)
name ,word) result)))
((= count n) result)))
;;; do-mirror takes one parameter
;;; the number of runs of the
;;; simulation, and then runs the simulation
;;; that many times, and reports the
;;; results
(defun do-mirror (n)
(setf *data* (make-array '(2 2 2) :initial-element 0))
(do ((count 0 (1+ count)))
((= count n) (progn (format *standard-output* "~%~%Simulation parameters: (~S ~S ~S ~S ~S ~S ~S ~S)~%~%Simulation data:~%"
*noise* *thresh* *factor* (/ *penalty* 10) *respond* *encode* *rehearse* n)
(mirror-results *data*)))
(reset)
(set-mirror-params)
(run-mirror-experiment)))
;;; mirror-results takes one parameter, the data
;;; array for the mirror experiment, and
;;; displays the summary of the data
(defun mirror-results (data)
(let ((high-hits (aref data 0 0 0))
(high-h-presented (+ (aref data 0 0 1) (aref data 0 0 0)))
(high-falses (aref data 0 1 0))
(high-f-presented (+ (aref data 0 1 0) (aref data 0 1 1)))
(low-hits (aref data 1 0 0))
(low-h-presented (+ (aref data 1 0 1) (aref data 1 0 0)))
(low-falses (aref data 1 1 0))
(low-f-presented (+ (aref data 1 1 0) (aref data 1 1 1))))
(format *standard-output* "~% Hits False Alarms~%")
(format *standard-output* "Low Freq. ~3,1F% ~3,1F%~%" (* 100 (/ low-hits low-h-presented))
(* 100 (/ low-falses low-f-presented)))
(format *standard-output* "High Freq. ~3,1F% ~3,1F%~%" (* 100 (/ high-hits high-h-presented))
(* 100 (/ high-falses high-f-presented)))))
;;; mirror-setup-materials takes no parameters
;;; and generates the memory chunks for the words,
;;; and the previous memory tokens for those words
;;; and sets the base levels for everything to 10
;;; occurences with a creation time of 400 units
;;; ago and returns a list of all the word chunks
(defun mirror-setup-materials ()
(do ((count 0 (1+ count))
(high nil (append (mirror-setup (gentemp "H") 5) high))
(low nil (append (mirror-setup (gentemp "L") 2)low))
(rest nil (cond ((>= count 48) rest)
(t (append (mirror-setup (gentemp "R") 1) rest)))))
((= count 100)
(eval `(addwm ,@(append high low rest)))
(setallbaselevels 10 -400)
(list (remove-duplicates (mapcar 'seventh high))
(remove-duplicates (mapcar 'seventh low))
(mapcar 'seventh rest )))))
;;; run-mirror-experiment takes no parameters
;;; and generates the items needed for the
;;; experiment, and then runs 1 simulation
(defun run-mirror-experiment ()
(let* ((materials (mirror-setup-materials))
(buffer-front (nthcdr 24 (third materials)))
(buffer-back (nthcdr 24 (reverse (third materials))))
(study-high (nthcdr 50 (first materials)))
(test-high (nthcdr 50 (reverse (first materials))))
(study-low (nthcdr 50 (second materials)))
(test-low (nthcdr 50 (reverse (second materials))))
(study (append buffer-front
(permut-mirror (append study-high study-low))
buffer-back))
(test (permut-mirror (append study-high test-high study-low test-low))))
(setsimilarities (l0 l1 .9)(l0 l2 .9)(l0 l3 .9)(l0 l4 .9)(l0 l5 .9)
(l1 l2 .9)(l1 l3 .9)(l1 l4 .9)(l1 l5 .9)
(l2 l3 .9)(l2 l4 .9)(l2 l5 .9)
(l3 l4 .9)(l3 l5 .9)(l4 l5 .9))
(setf *stop-it* 0)
(setf *ht* (no-output (wm-fct study-high)))
(setf *hf* (no-output (wm-fct test-high)))
(setf *lt* (no-output (wm-fct study-low)))
(setf *lf* (no-output (wm-fct test-low)))
(setf *items* (no-output (wm-fct study)))
(addwm (goal isa study-words context L0))
(wmfocus goal)
(run)
(setf *items* (no-output (wm-fct test)))
(addwm (newgoal isa recognize-words context L0))
(wmfocus newgoal)
(run)))
;;; permut-mirror takes one parameter
;;; a list, and returns a permuted
;;; copy of the list
(defun permut-mirror (lis)
(do ((result (list (nth (random (length lis)) lis))
(cons (nth (random (length lis)) lis) result)))
((null lis) result)
(setf lis (remove (car result) lis))
(cond ((null lis) (return result)))))
;;; analyze-mirror takes 2 parameters
;;; a word chunk and a response
;;; the response is analyzed, and the results
;;; stored in the global data array
(defun analyze-mirror (word response)
(let ((i)(j))
(cond ((member word *ht*)(setf i 0)(setf j 0))
((member word *hf*)(setf i 0)(setf j 1))
((member word *lt*)(setf i 1)(setf j 0))
((member word *lf*)(setf i 1)(setf j 1)))
(cond ((eq response 'yes) (setf (aref *data* i j 0) (1+ (aref *data* i j 0))))
(t (setf (aref *data* i j 1) (1+ (aref *data* i j 1)))))))
;;; get-word-mirror takes no parameters
;;; and increments the time to the next
;;; word presentation, and returns
;;; the word chunk for the word that
;;; is either being shown for study or for test
(defun get-word-mirror ()
(setf *stop-it* (1+ *stop-it*))
(pop *items*))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ACT-R Model of the task
;;;
;;;
(clearall)
(sgp-fct (list :bll .5 :ans *noise* :mp *penalty*
:pm t :rt *thresh* :lf *factor* :v nil))
(chunk-type study-words count context)
(chunk-type memory-token name time count context)
(chunk-type context)
(chunk-type word)
(chunk-type read-instruction)
(chunk-type recognize-words context target)
(chunk-type type-word position word)
(chunk-type spelling word position value)
(chunk-type rehearsal-fact count name)
;; add the contexts to working memory
(add-dm (l0 isa context)
(l1 isa context)
(l2 isa context)
(l3 isa context)
(l4 isa context)
(l5 isa context))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Productions
;;;
(p attend
"
IF the goal is to study words
and there are items to study
and there is a new word presented
THEN create a memory token of the current context
mark it in the goal
and push the memory token on the goal stack
"
=goal>
isa study-words
context =context
!eval! *items*
!eval! (>= (actr-time) *stop-it*)
==>
=newgoal>
isa memory-token
context =context
=goal>
count =newgoal
!push! =newgoal
)
(parameters-fct 'attend (list :effort *encode*))
(p create-token
"
IF the goal is a memory toke
THEN store the word chunk in the goal
and create a rehearsal fact for this word
and focus on the rehearsal fact
"
=goal>
isa memory-token
==>
!bind! =name (get-word-mirror)
=goal>
name =name
=token>
isa rehearsal-fact
name =name
!focus-on! =token
)
(p initialize-count
"
IF the goal is a rehearsal fact
THEN mark the count in the goal to 0
and pop the goal
"
=goal>
isa rehearsal-fact
==>
=goal>
count 0
!pop!
)
(parameters initialize-count :r .5)
(p recognize-count
"
IF the goal is a rehearsal fact
and a rehearsal fact with the same
name cam be recalled
THEN set the count of the goal to
the count in the recalled fact
"
=goal>
isa rehearsal-fact
name =name
=mem>
isa rehearsal-fact
name =name
count =count
==>
=goal>
count =count
!pop!
)
(p rehearse-token
"
IF the goal is to study words
and the next word has not yet been presented
and a memory token for the current context
can be recalled
and a rehearsal fact for that word with
an count less than 3 can be recalled
THEN
increment the count of the rehearsal fact
"
=goal>
isa study-words
count =n
context =context
!eval! (< (actr-time) *stop-it*)
=memory>
isa memory-token
name =name
context =context
=token>
isa rehearsal-fact
count =count
name =name
- count 3
==>
=token>
count (!eval! (1+ =count))
)
(parameters-fct 'rehearse-token (list :effort *rehearse*))
(p rehearse-skip
"
IF the goal is to study words
and the next word has not yet been presented
THEN do nothing
"
=goal>
isa study-words
count =n
context =context
!eval! (< (actr-time) *stop-it*)
==>
)
(parameters rehearse-skip :r .5)
(p attend-test
"
IF the goal is to recognize words
and there are words to be presented
THEN mark the goal to get the word
"
=goal>
isa recognize-words
target nil
!eval! *items*
==>
=goal>
target t
)
(parameters-fct 'attend-test (list :a *encode* :effort *encode*))
(p probe-token
"
IF the goal is to get a word to recognize
THEN mark the goal with the word to check
"
=goal>
isa recognize-words
target t
==>
=goal>
target (!eval! (get-word-mirror))
)
(p accept-word
"
IF the goal is to recognize a word
and a memory token of the word
in the current context can be recalled
THEN respond yes
and mark the goal as responded
"
=goal>
isa recognize-words
target =word
- target t
context =context
=token>
isa memory-token
name =word
context =context
==>
!eval! (analyze-mirror =word 'yes)
=goal>
target nil
)
(parameters-fct 'accept-word (list :effort *respond*))
(p reject-a-word-2
"
IF the goal is to recognize a word
THEN respond no
and mark the goal as responded
"
=goal>
isa recognize-words
target =word
context =context
==>
!eval! (analyze-mirror =word 'no)
=goal>
target nil
)
(parameters-fct 'reject-a-word-2 (list :r .5 :effort *respond*))