;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ACT-R Button Press Model
;;; works with ACT-R 4.0 (2/6/97 or newer)
;;;
;;; coded by: Dan Bothell
;;; 
;;; This file contains an ACT-R model
;;; of the Myers, Fort, Katz, and Suydam (1963)
;;; choice experiment.
;;;
;;; In the experiment subjects were to 
;;; press one of two buttons on each
;;; trial, and were informed after 
;;; choosing whether it was the correct
;;; button.  The correct button to press
;;; was randomly chosen on each trial, 
;;; with a probability p for button 1
;;; and 1-p for button 2.
;;; 
;;; One group of subjects was paid 10 cents for
;;; each correct answer, and another group was not.
;;; 
;;; A command line interface, 
;;; and a WWW interface are included.
;;;
;;; To use the command line interface,
;;; set the parameters with setf, and then
;;; call (button-press-myers n) to simulate n button
;;; presses. 
;;;
;;;
;;; To use the WWW interface, you need to run
;;; the ACT-R on the Web application (follow the
;;; instructions provided with it), or use a
;;; web browser to connect to a site that has
;;; the model installed.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Global Variables 
   

(defvar *act-r-button-press* 1)   ;; set by the model to the current button pressed (0 for button 1, 1 for button 2)

;;; the rest are the parameters for the model, and are set by the interfaces

(defvar *choice-g*)
(defvar *egn*)
(defvar *choice-g-paid*)
(defvar *v* nil)
(defvar *text*)
(defvar *graphic*)
(defvar *overlay*)

(setf *choice-g* 2.86)
(setf *egn* 1.64)
(setf *choice-g-paid* 4.66)
(setf *text* t)
(setf *graphic* nil)
(setf *overlay* nil)

;;; p button1 = .6 .7 .8 (no pay) p button1 = .6 .7 .8 (10 cent condition)
(defparameter *myers-data* '(.616 .753 .871 .713 .868 .951))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; 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 "Myers, Fort, Katz, and Suydam (1963) Experiment Model" 2)
        (:table)
        
        (:table)
        "Noise variance (sigma squared): " (:string :sy *egn*          1.64)  (:new-row)
        "G (unpaid): "                     (:string :sy *choice-g*     2.86)    (:new-row)
        "G (paid): "                       (:string :sy *choice-g-paid* 4.66) (:new-row)
        "Presses per condition (max 1000): "  (:string :sy *button-press-runs* 500)
        (: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-myers *myers-data* nil)")
        (:new-para)
        (:button "Run model" "(if (and (numberp *choice-g-paid*) (numberp *choice-g*) (numberp *egn*) (numberp *button-press-runs*))
                                  (button-press-myers (min 1000 (max *button-press-runs* 1)))
                                  (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 a run of 500 presses per condition"
        (:new-line)
        "- The trace of 1 run of 500 presses per condition is approximatly 250k (175 pages) in size"))



;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; button-press-myers takes one parameter which specifies how many button presses to 
;;; perform per condition of a simulation of the Myers et al experiment.
;;;  First, the ACT-R parameters are set according to the values given in
;;; the global variables (as set by the interface). Then, the model is called to
;;; press a button, and the button press is recorded.
;;; After all of the button presses have been done a summary of the experiment results 
;;; is displayed.

(defun button-press-myers (n)
  (let ((result nil)
        (b1-pressed 0))
    
    (dotimes (i 2)
      
      (dolist (b1-p '( .6 .7 .8 ))
        
        (when *v* (format *standard-output* "~%~%Probability of button1= ~S (~S):~%~%" b1-p (if (= i 0) 'unpaid 'paid)))
        
        (reset)
        
        (sgp-fct (list :ol t
                       :era t
                       :er t
                       :mt nil
                       :lt nil
                       :g  (if (= i 0) *choice-g* *choice-g-paid*)
                       :egn *egn*
                       :v *v*))
        
        (parameters-fct 'choose-button-1 
                        (list
                         :r b1-p 
                         :q 1 
                         :a .05 
                         :b 0))
        
        (parameters-fct 'choose-button-2 
                        (list
                         :r (- 1 b1-p) 
                         :q 1 
                         :a .05 
                         :b 0))
        
        (setf b1-pressed 0)
        
        (dotimes (i n)
          (wmfocus goal)
          (run)
          
          (when (=  *act-r-button-press* 0 ) (incf b1-pressed)))
        (setf result (cons (/ b1-pressed n) result))))
      
      (format *standard-output* "~%~%Simulation parameters: (~S ~S ~S ~S)~%" *egn* *choice-g* *choice-g-paid* n)
      
      (display-myers (reverse result) t)))
  


;;; display-myers takes two parameters
;;; the results data to display and a flag to specify if the
;;; data is for a simulation
;;; and outputs a display of % choice for button 1,
;;; in either text, a graph (on the web),
;;; or both, depending on the settings of *text* and *graphic*


(defun display-myers (data simulation)
  
  (when *text*
    (format *standard-output* "~%~%~a data:~%" (if simulation "Simulation" "Experimental"))
    (format t "~%         p of Button 1        button 1 chosen~%")  
    (do ((unpaid t nil)
         (x data (cdr x))
         (p '(.6 .7 .8 .6 .7 .8) (cdr p)))
        ((null x))
      (when (= (car p) .6)
        (format *standard-output* "~s~%" (if unpaid 'unpaid 'paid)))

      (format *standard-output* "         ~7,1F              ~9,3F~%" (car p) (car x)))

    (format *standard-output* "~%")
    
    (when (and simulation *overlay*)
      (format *standard-output* "~%~%Experimental data:~%")
      (format t "~%         p of Button 1        button 1 chosen~%")  
      (do ((unpaid t nil)
           (x *myers-data* (cdr x))
           (p '(.6 .7 .8 .6 .7 .8) (cdr p)))
          ((null x))
        (when (= (car p) .6)
          (format *standard-output* "~s~%" (if unpaid 'unpaid 'paid)))
        
        (format *standard-output* "         ~7,1F              ~9,3F~%" (car p) (car x)))
      
      (format *standard-output* "~%"))
    
    (unless *graphic* (format *standard-output* 
                              "~%</pre>If your browser supports JAVA, you 
                               can display the data in a graph by checking 
                               the Graphic output box on the interface page.<pre>~%~%")))
  (when *graphic*
    (format *standard-output* " 
        <applet 
        code = \"DansGraphs.class\" 
        width = 400 
        height = 400> 

        <PARAM name=\"title\" value=\"Data for Myers et al\">
        <PARAM name=\"longestline\" value=\"3\">
        <PARAM name=\"numlines\" value=\"~S\">
        <PARAM name=\"xmin\" value=\".6\">
        <PARAM name=\"xmax\" value=\".8\">
        <PARAM name=\"ymax\" value=\"1.0\">
        <PARAM name=\"ymin\" value=\".4\">
        <PARAM name=\"ydiv\" value=\".1\">
        <PARAM name=\"xspacing\" value=\"0.1\">
        <PARAM name=\"yspacing\" value=\"0.2\">
        <PARAM name=\"xval0\" value=\".6;.7;.8;\">
        <PARAM name=\"xval1\" value=\".6;.7;.8;\">
        <PARAM name=\"xname\" value=\"p of Button 1\">
        <PARAM name=\"yname\" value=\"Button 1 chosen\">
        <PARAM name=\"lcolor0\" value=\"0\">
        <PARAM name=\"lcolor1\" value=\"1\">
        <PARAM name=\"lstyle0\" value=\"~s\">
        <PARAM name=\"lstyle1\" value=\"~s\">
        <PARAM name=\"name0\" value=\"~a\">
        <PARAM name=\"name1\" value=\"~a\">" 
            (if (and simulation *overlay*) 4 2)
            (if simulation 2 6553)
            (if simulation 2 6553)
            (if simulation "Simulation Data (unpaid)" "Experiment Data (unpaid)")
            (if simulation "Simulation Data (paid)" "Experiment Data (paid)"))
    
    (format *standard-output* "<PARAM name=\"yval0\" value=\"")
    
    (dotimes (i 3)
      (format *standard-output* "~f;" (nth i data)))
    
    (format *standard-output* "\">")

    (format *standard-output* "<PARAM name=\"yval1\" value=\"")
    
    (dotimes (i 3)
      (format *standard-output* "~f;" (nth (+ i 3) data)))
    
    (format *standard-output* "\">")


    
    (when (and *overlay* simulation)
      (format *standard-output* "
        <PARAM name=\"lcolor2\" value=\"0\">
        <PARAM name=\"lcolor3\" value=\"1\">
        <PARAM name=\"lstyle2\" value=\"6553\">
        <PARAM name=\"lstyle3\" value=\"6553\">
        <PARAM name=\"xval2\" value=\".6;.7;.8;\">
        <PARAM name=\"xval3\" value=\".6;.7;.8;\">
        <PARAM name=\"yval2\" value=\"")
      
      (dotimes (i 3)
        (format *standard-output* "~f;" (nth i *myers-data*)))
      
      (format *standard-output* "\"> 
          <PARAM name=\"name2\" value=\"Experiment Data (unpaid)\">"))

      (format *standard-output* "<PARAM name=\"yval3\" value=\"")
      
      (dotimes (i 3)
        (format *standard-output* "~f;" (nth (+ i 3) *myers-data*)))
      
      (format *standard-output* "\"> 
          <PARAM name=\"name3\" value=\"Experiment Data (paid)\">")


    (format *standard-output* "
             <HR> Your browser does not support JAVA, so you cannot view the graphs.~%
             </HR></applet>")))




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; The rest of the file contains the 
;;; actual ACT-R model to guess the button to press.
;;; There are 2 productions, one to press button 1, and
;;; one to press button 2.  When the goal is set to
;;; press a button, either one can fire.  The one which
;;; fires is based on the (noisy) PG-C values for the productions.
;;;
   
(clearall)

(sgp :g 1.0 :era t :egn .5 :v nil :pl nil)

(chunk-type press-button "The type for the only goal")

(add-dm (goal 
        "The goal is to press a button" 
        isa press-button))


(p choose-button-1
" 
   IF the goal is to press a button 
   THEN press button 1
      and pop the goal
"
   =goal>
      isa press-button
==>
  !output! ("~%pressed: button 1  ~%")

  !eval! (setf *act-r-button-press* 0)

  !pop!
)

(parameters choose-button-1 :r .5 :q 1.0 :a .2 :b 0)


(p choose-button-2
" 
   IF the goal is to press a button
   THEN press button 2
      and pop the goal
"
   =goal>
      isa press-button
==>
   !output! ("~%pressed: button 2  ~%")

   !eval! (setf *act-r-button-press* 1)

   !pop!
)

(parameters choose-button-2 :r .5 :q 1.0 :a .2 :b 0)