;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
If your browser supports JAVA, you can display the data in a graph by checking the Graphic output box on the interface page.;;; ;;; ACT-R 4.0 model to solve the Tower of ;;; Hanoi task using the strategy taught to ;;; subjects by Ruiz ;;; ;;; (1) The overall goal of solving a n-pyramid problem is ;;; decomposed into the subgoals of getting the n disk ;;; to its peg and then a n-1 pyramid into its location. ;;; ;;; (2) To get the n disk to a peg, one tries to get the ;;; largest disk blocking its move out of the way. ;;; to run the model call ;;; (solve-tower-ruiz-time) ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This section contains the LISP functions ;;; implement the interface. ;;; ;;; The ACT-R Model starts further down ;;; (defvar *move-time*) (defvar *subgoal-time*) (defvar *v*) (defvar *data*) (defvar *text*) (defvar *graphic*) (defvar *overlay*) (defvar *last-time*) (setf *v* nil) (setf *move-time* 1.12) ;; 1.12040993 (setf *subgoal-time* 0.69) ;; 0.68912651 (setf *data* nil) (setf *text* t) (setf *graphic* nil) (setf *overlay* nil) (defparameter *towerruiz-exp* '(3.9 2.1 2 1.1 3.2 1 1.3 1.7 3.5 1.4 2.2 1.1 2.1 1.3 1.2 1 3.1 1.4 2.2 1 2.9 1.1 1 0.9 2.5 1.2 1.8 0.9 1.3 0.8 0.7)) (defvar *WWW-interface*) (setf *WWW-interface* '((:heading "Tower of Hanoi Model for Ruiz (1987)" 2) (:table) (:table) "Movement time (sec.):" (:string :sy *move-time* 1.12) (:new-row) "Subgoal time (sec.):" (:string :sy *subgoal-time* .69) (: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-ruiz-data *towerruiz-exp* nil)") (:new-para) (:button "Run model" "(if (and (numberp *move-time*) (numberp *subgoal-time*)) (solve-tower-ruiz-time) (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 to run the model" (:new-line) "- The trace of 1 run is approximatly 10k (6 pages) in size")) (defun save-ruiz-times (instantiation) (when (or (equal 'move (production-name (instantiation-production instantiation))) (equal 'final-move (production-name (instantiation-production instantiation)))) (setf *data* (cons (- (actr-time) *last-time*) *data*)) (setf *last-time* (actr-time)))) (defun solve-tower-ruiz-time () (setf *data* nil) (setf *last-time* 0) (reset) (setf *cycle-hook-fn* 'save-ruiz-times) (sgp-fct (list :ct t :lt t :ot t :v *v*)) (parameters-fct 'final-move (list :effort *move-time*)) (parameters-fct 'subgoal-blocker (list :effort *subgoal-time*)) (parameters-fct 'move (list :effort *move-time*)) (run) (display-ruiz-data (reverse *data*) t)) (defun display-ruiz-data (data simulation) (when simulation (format *standard-output* "~%~%Parameters for run: (~S ~S)~%" *move-time* *subgoal-time*)) (when *text* (format *standard-output* "~%~%~a move times:~%" (if simulation "Simulation" "Experimental")) (format *standard-output* "~%Move Number Time (sec.)~%") (dotimes (i (length data)) (format *standard-output* "~6d~14,2f~%" (+ i 1) (nth i data))) (format *standard-output* "~%") (when (and simulation *overlay*) (format *standard-output* "~%~%Experimental move times:~%") (format *standard-output* "~%Move Number Time (sec.)~%") (dotimes (i (length data)) (format *standard-output* "~6d~14,2f~%" (+ i 1) (nth i *towerruiz-exp*))) (format *standard-output* "~%")) (unless *graphic* (format *standard-output* "~%
~%~%")))
(when *graphic*
(format *standard-output* "
")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ACT-R model of solving Tower of Hanoi Problems
;;;
(clearall)
(chunk-type disk size peg state)
(chunk-type peg name)
(chunk-type tower-task largest from to)
(chunk-type move-disk disk to from other test)
(chunk-type countfact first then)
;;; add chunks to specify the initial conditions
;;; and the goal conditions for each disk
(add-dm
(disk1c ISA disk size 1 peg a state current)
(disk2c ISA disk size 2 peg a state current)
(disk3c ISA disk size 3 peg a state current)
(disk4c ISA disk size 4 peg a state current)
(disk5c ISA disk size 5 peg a state current)
(disk1g ISA disk size 1 peg c state goal)
(disk2g ISA disk size 2 peg c state goal)
(disk3g ISA disk size 3 peg c state goal)
(disk4g ISA disk size 4 peg c state goal)
(disk5g ISA disk size 5 peg c state goal)
(fact01 ISA countfact first 0 then 1)
(fact12 ISA countfact first 1 then 2)
(fact23 ISA countfact first 2 then 3)
(fact34 ISA countfact first 3 then 4)
(fact45 ISA countfact first 4 then 5)
(fact56 ISA countfact first 5 then 6)
(a ISA peg name a)
(b ISA peg name b)
(c ISA peg name c)
(current isa chunk)
(goal ISA tower-task largest 5 from a to c))
(goal-focus goal)
(p start-tower
"
IF the goal is to move a pyramid of size =size to peg =end
and =size is greater than 1
THEN set a subgoal to move the disk of size =size to peg =end
and change the goal to move a pyramid of six =size - 1 to peg =end
"
=goal>
isa tower-task
largest =size
- largest 1
from =start
to =end
=other>
isa peg
- name =start
- name =end
=countfact>
isa countfact
first =new
then =size
==>
=goal>
largest =new
from =other
=newgoal>
isa move-disk
disk =size
from =start
to =end
other =other
test =new
!push! =newgoal
!output! ("i am going to solve a ~s tower problem" =size)
)
(p final-move
"
IF the goal is to move a tower of size 1 to peg x
THEN move disk 1 to peg x
and pop the goal
"
=goal>
isa tower-task
largest =size
largest 1
=gdisk>
isa disk
size 1
peg =gpeg
state goal
=cdisk>
isa disk
size 1
peg =cpeg
state current
==>
!pop!
!output! ("i am moving disk ~s from peg ~s to peg ~s" =size =gpeg =cpeg)
)
(parameters-fct 'final-move (list :effort *move-time*))
(p subgoal-blocker
"
IF the goal is to move a disk to peg =to
and =other is the other peg
and =size is the largest blocking disk
THEN set a subgoal to move the disk of size =size to =other
and change the goal to check the disk of size =new
"
=goal>
isa move-disk
test =size
other =other
from =from
to =to
=disk>
isa disk
size =size
state current
peg =start
=fact>
isa countfact
first =new
then =size
=peg>
isa peg
- name =start
- name =other
==>
=goal>
test =new
=newgoal>
isa move-disk
disk =size
test =new
from =start
to =other
other =peg
!push! =newgoal
!output! ("my goal is to move ~s from ~s to ~s" =size =start =other)
)
(parameters-fct 'subgoal-blocker (list :effort *subgoal-time*))
(p move
"
IF the goal is to move a disk of size =size to peg =to
and there are no blocking disks
THEN move disk =disk to peg =to
and pop the goal
"
=goal>
isa move-disk
test 0
from =from
to =to
disk =size
=disk>
isa disk
size =size
==>
=disk>
peg =to
!pop!
!output! ("i am moving disk ~s from ~s to ~s" =size =from =to)
)
(parameters-fct 'move (list :effort *move-time*))