;;;;;;;;;;;;;;;;;;;;;;;;
;;; ;;; ;;; Requires ACT-R 4.0 ;;; ;;; to run the model call ;;; (do-jacoby-experiment n) ;;; where n is the number of runs ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; 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 *deep-words*) (defvar *shallow-words*) (defvar *prebuffer-words*) (defvar *postbuffer-words*) (defvar *distract-words*) (defvar *study-words*) (defvar *stop-it*) (defvar *answered*) (defvar *condition*) (defvar *which-test*) (defvar *which-condition*) (defvar *test-word*) (defvar *correct-answer*) (defvar *low-ia*) (defvar *high-ia*) (defvar *an*) (defvar *rt*) (defvar *v*) (defvar *factor*) (defvar *penalty*) (defvar *runs*) (defvar *respond*) (defvar *encode*) (defvar *rehearse*) (setf *respond* .5) (setf *encode* .2) (setf *rehearse* 2.0) (setf *penalty* 15) (setf *factor* .5) (setf *low-ia* .4) (setf *high-ia* 3.8) (setf *an* .45) (setf *rt* 0.1) (setf *v* nil) (setf *runs* 1) (defparameter *letters-for-jacoby* #(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)) (defparameter *jacoby-results* (make-array '(3 3) :initial-contents '((.51 .45 .30)(.60 .47 .29)(.33 .43 .26)))) (defparameter *total-jacoby* (make-array '(3 3) :initial-contents '((40 40 80) (40 40 80) (40 40 80)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; 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 "Process Dissociation Model" 2) (:hidden :sy *low-ia* .4) (:hidden :sy *high-ia* 3.8) (:table) (:table) "Noise (s): " (:string :sy *an* .45) (:new-row) "Threshold: " (:string :sy *rt* 0.1) (:new-row) "Scale factor (F): " (:string :sy *factor* .5) (:new-row) "Mismatch Penalty:" (:string :sy *penalty* 1.5) (: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* 2) (: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" "(display-jacoby-results *jacoby-results* nil)") (:new-para) (:button "Run model" "(progn (when (numberp *penalty*) (setf *penalty* (* 10 *penalty*))) (if (and (numberp *penalty*) (numberp *an*) (numberp *rt*) (numberp *factor*) (numberp *runs*) (numberp *encode*) (numberp *rehearse*) (numberp *respond*)) (progn (do-jacoby-experiment (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 90k (60 pages) in size" (:new-para))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This section contains the LISP code ;;; to simulate the experiment, and ;;; display the results ;;; generate-n-unique-pairs-jacoby takes one ;;; parameter, the number of letter pairs to generate, ;;; and returns the list containig n distinct ;;; letter pairs (defun generate-n-unique-pairs-jacoby (n) (do ((count 0) (pairs nil) (pair (cons (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* (random 26))) ) (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* (random 26))))) (cons (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* (random 26))) ) (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* (random 26))))))) ((= count n) pairs) (unless (member pair pairs :test #'(lambda (x y) (and (equal (car x) (car y)) (equal (cdr x) (cdr y))))) (setf pairs (cons pair pairs)) (incf count)))) ;;; generate-words-jacoby creates the chunks ;;; for the letters, sets the similarity ;;; between each one and the - (used to represent ;;; a missing letter) to 1 ;;; then generates the 4 letter 'words' to use ;;; for the stimuli by combinding distinct pairs ;;; such that no two words have the same first and third letters ;;; or the same second and fourth letters ;;; the chunks for the words are then created and ;;; the ia between the word and its first letter is set to *high-ia* ;;; and the ia between the word and the rest of the letters ;;; is set to *low-ia* ;;; next the list of words is broken into the separate ;;; lists for the different parts of the experiment, ;;; and finally the baselevel activations are set for the ;;; words and for the letters (defun generate-words-jacoby () (dotimes (i 26) (add-dm-fct (list (list (intern (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* i)))) 'isa 'letter))) (setsimilarities-fct (list (list (intern (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* i)))) '- 1)))) (let ((words nil)) (do ((1-2-pairs (generate-n-unique-pairs-jacoby 164) (cdr 1-2-pairs)) (3-4-pairs (generate-n-unique-pairs-jacoby 328) (cddr 3-4-pairs))) ((null 1-2-pairs) words) (let* ((first-pair (car 1-2-pairs)) (second-pair (car 3-4-pairs)) (third-pair (second 3-4-pairs)) (word1 (intern (string-upcase (format nil "~a~a~a~a" (subseq (car first-pair) 4) (subseq (cdr first-pair) 4) (subseq (car second-pair) 4) (subseq (cdr second-pair) 4))))) (word2 (intern (string-upcase (format nil "~a~a~a~a" (subseq (car first-pair) 4) (subseq (cdr first-pair) 4) (subseq (car third-pair) 4) (subseq (cdr third-pair) 4)))))) (add-dm-fct (list (list word1 'isa 'word 'first (intern (car first-pair)) 'second (intern (cdr first-pair)) 'third (intern (car second-pair)) 'fourth (intern (cdr second-pair)))) :reset-ia nil) (add-dm-fct (list (list word2 'isa 'word 'first (intern (car first-pair)) 'second (intern (cdr first-pair)) 'third (intern (car third-pair)) 'fourth (intern (cdr third-pair)))) :reset-ia nil) (setia-fct (list (list word1 (intern (car second-pair)) 100))) (setia-fct (list (list word1 (intern (cdr first-pair)) 100))) (setia-fct (list (list word1 (intern (cdr second-pair)) 100))) (setia-fct (list (list word1 (intern (car first-pair)) 100))) (setia-fct (list (list word1 '- .1))) (setia-fct (list (list word2 (intern (car third-pair)) 100))) (setia-fct (list (list word2 (intern (cdr first-pair)) 100))) (setia-fct (list (list word2 (intern (cdr third-pair)) 100))) (setia-fct (list (list word2 (intern (car first-pair)) 100))) (setia-fct (list (list word2 '- .1))) (setia-fct (list (list (intern (car second-pair)) word1 *low-ia*))) (setia-fct (list (list (intern (cdr first-pair)) word1 *low-ia*))) (setia-fct (list (list (intern (cdr second-pair)) word1 *low-ia*))) (setia-fct (list (list (intern (car first-pair)) word1 *high-ia*))) (setia-fct (list (list '- word1 .1))) (setia-fct (list (list (intern (car third-pair)) word2 *low-ia*))) (setia-fct (list (list (intern (cdr first-pair)) word2 *low-ia*))) (setia-fct (list (list (intern (cdr third-pair)) word2 *low-ia*))) (setia-fct (list (list (intern (car first-pair)) word2 *high-ia*))) (setia-fct (list (list '- word2 .1))) (setia-fct (list (list word1 word1 100))) (setia-fct (list (list word2 word2 100))) (setf words (append (list word1) words (list word2))))) (setf *deep-words* (subseq words 0 40)) (setf *shallow-words* (subseq words 40 80)) (setf *prebuffer-words* (subseq words 80 82)) (setf *postbuffer-words* (subseq words 82 84)) (setf *distract-words* (subseq words 84 164)) (setf *study-words* (append *prebuffer-words* (permut-for-jacoby (append *deep-words* *shallow-words*)) *postbuffer-words*)) (setallbaselevels 6 -1000) (dotimes (i 26) (setbaselevels-fct (list (list (intern (string-upcase (format nil "LET-~a" (aref *letters-for-jacoby* i)))) 200 -1000)))))) ;;; permut-for-jacoby takes one parameter ;;; a list, and returns the same list in ;;; a random order (defun permut-for-jacoby (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 :count 1)) (cond ((null lis) (return result))))) ;;; do-jacoby-experiment takes one parameter, the ;;; number of runs throught the experiment ;;; to simulate, and then runs n simulations ;;; in both the same and different condition ;;; and displays the results (defun do-jacoby-experiment (n) (setf *answered* (make-array '(3 3) :initial-element 0)) (dotimes (count n) (run-implicit-jacoby-experiment 'indirect) (run-implicit-jacoby-experiment 'inclusion) (run-implicit-jacoby-experiment 'exclusion)) (dotimes (i 3) (dotimes (j 3) (setf (aref *answered* i j) (* 1.0 (/ (aref *answered* i j) (* n (aref *total-jacoby* i j))))))) (display-jacoby-results *answered* t)) (defun set-implicit-jacoby-parameters () (sgp-fct (list :al nil :bll .5 :era t :pm t :mp *penalty* :ans *an* :rt *rt* :lf *factor* :v *v*)) (parameters-fct 'complete-word-indirect (list :effort *respond*)) (parameters-fct 'rehearse-word-deep (list :effort *rehearse*)) (parameters-fct 'attend (list :effort *encode*)) (parameters-fct 'complete-word-inclusion-2 (list :effort *respond*)) (parameters-fct 'complete-word-inclusion-4 (list :effort *respond* :r .5)) (parameters-fct 'complete-word-exclusion-4 (list :effort *respond* :r .75))) ;;; run-implicit-ht-experiment takes one parameter ;;; which specifies the type of fragment to display ;;; in test 2 for the incorrect responses from test 1 ;;; if same is t then the same fragment is shown, if ;;; it is nil then the opposite fragment is shown ;;; first the list of words is studied, ;;; then the two test phases are run (defun run-implicit-jacoby-experiment (cond) (let ((count)) (case cond (indirect (setf *which-condition* 0)) (inclusion (setf *which-condition* 1)) (exclusion (setf *which-condition* 2))) (setf *condition* cond) (reset) (set-implicit-jacoby-parameters) (no-output (generate-words-jacoby)) (setf *stop-it* 0) (add-dm-fct '((goal isa study-words)) :reset-ia nil) (wmfocus goal) (run) (setf count 0) (dolist (x (permut-for-jacoby (append *distract-words* *shallow-words* *deep-words*))) (mod-chunk-fct 'newgoal (list 'first (eval `(chunk-slot-value ,x first)) 'second (eval `(chunk-slot-value ,x second)) 'third '- 'fourth '- )) (actr-time-fct (- (+ count 336) (actr-time))) (setf count (+ count 5)) (wmfocus newgoal) (setbaselevels (newgoal 2)) (setf *test-word* (car (no-output (dm-fct (list x))))) (setf *correct-answer* nil) (cond ((member x *deep-words*) (setf *which-test* 0)) ((member x *shallow-words*) (setf *which-test* 1)) (t (setf *which-test* 2))) (run)))) ;;; get-word-for-jacoby takes no parameters, ;;; and sets the stopping time, and returns the next word (defun get-word-for-jacoby () (let ((word (pop *study-words*))) (setf *stop-it* (+ 4.0 *stop-it*)) (car (no-output (wm-fct (list word)))))) ;;; jacoby-exp-response (defun jacoby-exp-response (word) (cond ((equal word *test-word*) (setf (aref *answered* *which-condition* *which-test*) (1+ (aref *answered* *which-condition* *which-test*)))))) ;;; display-jacoby-results (defun display-jacoby-results (data sim) (when sim (format *standard-output* "~%~%Parameters for run: (~S ~S ~S ~S ~S ~S ~S ~S)~%" *an* *rt* *factor* (/ *penalty* 10) *respond* *encode* *rehearse* *runs*)) (format *standard-output* "~%~a data:~%~%" (if sim "Simulation" "Experimental")) (format *standard-output* " Study Processing~%") (format *standard-output* "Performance Measure Semantic Nonsemantic New~%") (format *standard-output* "~%Test~%") (format *standard-output* "Indirect ~5,2F ~5,2F ~5,2F~%" (aref data 0 0) (aref data 0 1) (aref data 0 2)) (format *standard-output* "Inclusion ~5,2F ~5,2F ~5,2F~%" (aref data 1 0) (aref data 1 1) (aref data 1 2)) (format *standard-output* "Exclusion ~5,2F ~5,2F ~5,2F~%" (aref data 2 0) (aref data 2 1) (aref data 2 2)) (format *standard-output* "~%Estimate~%") (format *standard-output* "Controlled ~5,2F ~5,2F~%" (- (aref data 1 0) (aref data 2 0)) (- (aref data 1 1) (aref data 2 1))) (format *standard-output* "Automatic ~5,2F ~5,2F~%~%" (/ (aref data 2 0) (- 1 (- (aref data 1 0) (aref data 2 0)))) (/ (aref data 2 1) (- 1 (- (aref data 1 1) (aref data 2 1)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This section contains the ACT-R productions ;;; and memory definitions for the simulation (clearall) (sgp :v nil) ;; chunks for study items (chunk-type word first second third fourth tag) (chunk-type letter) ;; chunks for goals (chunk-type study-words word) (chunk-type memory-token item context) (chunk-type rehearse-word word) (chunk-type complete-words first second third fourth target answer) (add-dm (- isa letter) (list isa chunk) (newgoal isa complete-words)) ;;; productions (p attend " IF the goal is to study words and the time has not expired and there are words to study THEN create and push a goal to rehearse the current word " =goal> isa study-words word nil !eval! *study-words* ==> =goal> word (!eval! (get-word-for-jacoby ))) (parameters-fct 'attend (list :effort *encode*)) (p push-rehearse =goal> isa study-words word =word =word> isa word first =f second =s third =t fourth =fo =f> isa letter =s> isa letter =t> isa letter =fo> isa letter ==> =goal> word nil =memory-token> isa memory-token item =word context list =newgoal> isa rehearse-word word =word !push! =newgoal ) (p rehearse-word-deep " IF the goal is to rehearse a word and the word and all of its letters can be retrieved and there is still time to rehearse it THEN report that it is being rehearsed " =goal> isa rehearse-word word =word !eval! (member =word *deep-words*) ;(car (get-name-fct (list =word))) =word> isa word =context> isa memory-token item =word context list !eval! (< (actr-time) *stop-it*) ==> !output! ("Rehearsing ~S.~%" =word) ) (parameters-fct 'rehearse-word-deep (list :effort *rehearse*)) (p rehearse-skip " IF the goal is to rehearse a word THEN do nothing " =goal> isa rehearse-word !eval! (< (actr-time) *stop-it*) ==> ) (parameters rehearse-skip :r .5 :effort 1.0) (p done-rehearsing " IF the goal is to rehearse a word and the time has passed THEN pop the goal " =goal> isa rehearse-word word =word =word> isa word !eval! (>= (actr-time) *stop-it*) ==> !pop! ) (p complete-word-indirect " IF the goal is to complete a word and the letters and a word composed of those letters can be retrieved and the word matches the presented word THEN respond with the word and pop the goal " =goal> isa complete-words first =f second =s third =t fourth =fo !eval! (equal *condition* 'indirect) =f> isa letter =s> isa letter =t> isa letter =fo> isa letter =word> isa word first =f second =s third =t fourth =fo tag nil ==> !output! ("completes word as ~S~%" =word) !eval! (jacoby-exp-response =word) !pop! ) (parameters-fct 'complete-word-indirect (list :effort *respond*)) (p complete-word-inclusion-1 =goal> isa complete-words first =f second =s third =t fourth =fo target nil !eval! (equal *condition* 'inclusion) =f> isa letter =s> isa letter =t> isa letter =fo> isa letter =word> isa word first =f second =s third =t fourth =fo tag nil ==> =word> tag t =goal> target =word answer =word) (p complete-word-inclusion-2 =goal> isa complete-words first =f second =s third =t fourth =fo target =word !eval! (equal *condition* 'inclusion) =token> isa memory-token item =word context list ==> =goal> target nil answer nil !output! ("completes word as ~S~%" =word) !eval! (jacoby-exp-response =word) !pop! ) (parameters-fct 'complete-word-inclusion-2 (list :effort *respond*)) (p complete-word-inclusion-3 =goal> isa complete-words first =f second =s third =t fourth =fo target =word !eval! (equal *condition* 'inclusion) =f> isa letter =s> isa letter =t> isa letter =fo> isa letter =word1> isa word first =f second =s third =t fourth =fo tag nil ==> =word1> tag t =goal> target =word1) (parameters complete-word-inclusion-3 :r .75) (p complete-word-inclusion-4 =goal> isa complete-words first =f second =s third =t fourth =fo answer =word !eval! (equal *condition* 'inclusion) ==> =goal> answer nil target nil !output! ("completes word as ~S~%" =word) !eval! (jacoby-exp-response =word) !pop! ) (parameters-fct 'complete-word-inclusion-4 (list :effort *respond* :r .5)) (p complete-word-exclusion-1 =goal> isa complete-words first =f second =s third =t fourth =fo target nil !eval! (equal *condition* 'exclusion) =f> isa letter =s> isa letter =t> isa letter =fo> isa letter =word> isa word first =f second =s third =t fourth =fo tag nil ==> !output! ("~s" =word) =word> tag t =goal> target =word) (p complete-word-exclusion-2 =goal> isa complete-words first =f second =s third =t fourth =fo target =word !eval! (equal *condition* 'exclusion) =token> isa memory-token item =word context list ==> =goal> target nil) (p complete-word-exclusion-4 =goal> isa complete-words first =f second =s third =t fourth =fo target =word !eval! (equal *condition* 'exclusion) ==> =goal> target nil !output! ("completes word as ~S~%" =word) !eval! (jacoby-exp-response =word) !pop! ) (parameters-fct 'complete-word-exclusion-4 (list :effort *respond* :r .75)) (p cant-complete " IF the goal is to complete a word THEN pop the goal " =goal> isa complete-words target nil ==> !pop! ) (parameters cant-complete :r .5 :effort 15)