Index: /trunk/optimizer/examples/simple.tcl
===================================================================
--- /trunk/optimizer/examples/simple.tcl	(revision 898)
+++ /trunk/optimizer/examples/simple.tcl	(revision 898)
@@ -0,0 +1,56 @@
+# ----------------------------------------------------------------------
+#  EXAMPLE:  Rappture optimization
+#
+#  This script shows the core of the Rappture optimization loop.
+#  It represents a simple skeleton of the much more complicated
+#  Rappture GUI, but it drives enough of the optimization process
+#  to drive development and testing.
+#
+#  Run this as:  tclsh simple.tcl ?-tool path/to/tool.xml?
+#
+# ======================================================================
+#  AUTHOR:  Michael McLennan, Purdue University
+#  Copyright (c) 2008  Purdue Research Foundation
+#
+#  See the file "license.terms" for information on usage and
+#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# ======================================================================
+package require Itcl
+package require Rappture
+package require RapptureGUI
+package require RapptureOptimizer
+
+# ----------------------------------------------------------------------
+#  Create a Tool object based on the tool.xml file...
+# ----------------------------------------------------------------------
+Rappture::getopts argv params {
+    value -tool tool.xml
+}
+
+# open the XML file containing the tool parameters
+if {![file exists $params(-tool)]} {
+    puts stderr "can't find tool \"$params(-tool)\""
+    exit 1
+}
+set xmlobj [Rappture::library $params(-tool)]
+
+set installdir [file dirname $params(-tool)]
+if {"." == $installdir} {
+    set installdir [pwd]
+}
+
+set tool [Rappture::Tool ::#auto $xmlobj $installdir]
+
+# ----------------------------------------------------------------------
+#  Create an optimization context and configure the parameters used
+#  for optimization...
+# ----------------------------------------------------------------------
+Rappture::optimizer optim -tool $tool -using pgapack
+
+optim add number input.number(temperature) -min 200 -max 400
+optim add number input.number(Ef) -min 0 -max 1.1
+optim configure -popsize 500 -maxruns 5
+
+set status [optim perform -updatecommand {puts "checking"}]
+
+puts "done: $status"
Index: /trunk/optimizer/examples/tool.xml
===================================================================
--- /trunk/optimizer/examples/tool.xml	(revision 898)
+++ /trunk/optimizer/examples/tool.xml	(revision 898)
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<run>
+    <tool>
+        <about>Press Simulate to view results.</about>
+        <command>tclsh @tool/fermi.tcl @driver</command>
+    </tool>
+    <input>
+        <number id="temperature">
+            <about>
+                <label>Ambient temperature</label>
+                <description>Temperature of the environment.</description>
+            </about>
+            <units>K</units>
+            <min>0K</min>
+            <max>500K</max>
+            <default>300K</default>
+            <preset>
+                <value>300K</value>
+                <label>300K (room temperature)</label>
+            </preset>
+            <preset>
+                <value>77K</value>
+                <label>77K (liquid nitrogen)</label>
+            </preset>
+            <preset>
+                <value>4.2K</value>
+                <label>4.2K (liquid helium)</label>
+            </preset>
+        </number>
+        <number id="Ef">
+            <about>
+                <label>Fermi Level</label>
+                <description>Energy at center of distribution.</description>
+            </about>
+            <units>eV</units>
+            <min>-10eV</min>
+            <max>10eV</max>
+            <default>0eV</default>
+        </number>
+    </input>
+</run>
+
Index: /trunk/optimizer/src/Makefile.in
===================================================================
--- /trunk/optimizer/src/Makefile.in	(revision 897)
+++ /trunk/optimizer/src/Makefile.in	(revision 898)
@@ -396,14 +396,4 @@
 	  fi; \
 	done
-	# Uncomment when you are ready to install tcl rappture library bindings
-	#$(TCLSH_PROG) $(srcdir)/tclconfig/mkindex.tcl $(DESTDIR)$(pkglibdir)/scripts
-	$(INSTALL_DATA) init.tcl $(DESTDIR)$(pkglibdir)/init.tcl
-	@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
-	  if test -f $(srcdir)/$$p; then \
-	    destp=`basename $$p`; \
-	    echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
-	    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
-	  fi; \
-	done
 	@if test "x$(SHARED_BUILD)" = "x1"; then \
 	    echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
Index: /trunk/optimizer/src/configure.in
===================================================================
--- /trunk/optimizer/src/configure.in	(revision 897)
+++ /trunk/optimizer/src/configure.in	(revision 898)
@@ -74,6 +74,6 @@
 TEA_ADD_SOURCES([rp_optimizer.c rp_tcloptions.c rp_optimizer_tcl.c plugin_pgapack.c])
 TEA_ADD_HEADERS([])
-TEA_ADD_INCLUDES([])
-TEA_ADD_CFLAGS([])
+TEA_ADD_INCLUDES([-Ipgapack/pgapack/include])
+TEA_ADD_CFLAGS([-DWL=32])
 TEA_ADD_STUB_SOURCES([])
 # uncomment this and mkindex.tcl line in makefile when you are ready to
@@ -81,4 +81,5 @@
 #TEA_ADD_TCL_SOURCES([scripts/exec.tcl scripts/value.tcl init.tcl ../../tcl/scripts/library.tcl ../../tcl/scripts/result.tcl])
 TEA_ADD_TCL_SOURCES([])
+TEA_ADD_LIBS([-Lpgapack/pgapack/lib/linux -lpgaO])
 
 #--------------------------------------------------------------------
Index: unk/optimizer/src/pgapack/pgapack/config.status
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/config.status	(revision 897)
+++ 	(revision )
@@ -1,111 +1,0 @@
-#!/bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host mo.local:
-#
-# ./configure -arch linux -mpiinc /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -mpilib /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a
-
-for arg
-do
-  case "$arg" in
-    -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    echo running ${CONFIG_SHELL-/bin/sh} ./configure -arch linux -mpiinc /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -mpilib /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a
-    exec ${CONFIG_SHELL-/bin/sh} ./configure -arch linux -mpiinc /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -mpilib /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a ;;
-    *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;;
-  esac
-done
-
-trap 'rm -f Makefile source/Makefile test/Makefile test/Makefile 	  examples/Makefile examples/c/Makefile examples/fortran/Makefile 	  examples/mgh/Makefile; exit 1' 1 3 15
-RANLIB='ranlib'
-CC='cc'
-FC='f77'
-CFLAGS='-O '
-FFLAGS='-w'
-CPPFLAGS='-I/Volumes/Data_mo/GENES/Software/pgapack/include -I/Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -Dlinux -DWL=32 -DFORTRANUNDERSCORE -DOPTIMIZE '
-FORTWRAP='$(PGA_LIB_DIR)/f2c.o: f2c.c $(HEADERS)\
-	$(COMPILE.c) f2c.c'
-HEADERS='/Volumes/Data_mo/GENES/Software/pgapack/include/pgapack.h'
-LDFLAGS='-s  -L/Volumes/Data_mo/GENES/Software/pgapack/lib/linux  -lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm'
-PARALLEL='1'
-PGA_LIB_DIR='../lib/linux'
-PGA_LIB='pgaO'
-OBJS='$(PGA_LIB_DIR)/binary.o        \\\
-      $(PGA_LIB_DIR)/char.o          \\\
-      $(PGA_LIB_DIR)/cmdline.o       \\\
-      $(PGA_LIB_DIR)/create.o        \\\
-      $(PGA_LIB_DIR)/cross.o         \\\
-      $(PGA_LIB_DIR)/debug.o         \\\
-      $(PGA_LIB_DIR)/duplcate.o      \\\
-      $(PGA_LIB_DIR)/evaluate.o      \\\
-      $(PGA_LIB_DIR)/fitness.o       \\\
-      $(PGA_LIB_DIR)/hamming.o       \\\
-      $(PGA_LIB_DIR)/heap.o          \\\
-      $(PGA_LIB_DIR)/integer.o       \\\
-      $(PGA_LIB_DIR)/mutation.o      \\\
-      $(PGA_LIB_DIR)/parallel.o      \\\
-      $(PGA_LIB_DIR)/pga.o           \\\
-      $(PGA_LIB_DIR)/pop.o           \\\
-      $(PGA_LIB_DIR)/random.o        \\\
-      $(PGA_LIB_DIR)/real.o          \\\
-      $(PGA_LIB_DIR)/report.o        \\\
-      $(PGA_LIB_DIR)/restart.o       \\\
-      $(PGA_LIB_DIR)/select.o        \\\
-      $(PGA_LIB_DIR)/stop.o          \\\
-      $(PGA_LIB_DIR)/system.o        \\\
-      $(PGA_LIB_DIR)/user.o          \\\
-      $(PGA_LIB_DIR)/utility.o $(PGA_LIB_DIR)/f2c.o'
-MPICOMP=''
-RM='/bin/rm -f'
-SHELL='/bin/sh'
-LIBS='-lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm'
-srcdir='.'
-DEFS=''
-prefix=''
-exec_prefix=''
-prsub=''
-extrasub=''
-
-top_srcdir=$srcdir
-
-CONFIG_FILES=${CONFIG_FILES-"Makefile source/Makefile test/Makefile test/Makefile \
-	  examples/Makefile examples/c/Makefile examples/fortran/Makefile \
-	  examples/mgh/Makefile"}
-for file in .. ${CONFIG_FILES}; do if test "x$file" != x..; then
-  srcdir=$top_srcdir
-  # Remove last slash and all that follows it.  Not all systems have dirname.
-  dir=`echo $file|sed 's%/[^/][^/]*$%%'`
-  if test "$dir" != "$file"; then
-    test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
-    test ! -d $dir && mkdir $dir
-  fi
-  echo creating $file
-  rm -f $file
-  echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file
-  sed -e "
-$prsub
-$extrasub
-s%@RANLIB@%$RANLIB%g
-s%@CC@%$CC%g
-s%@FC@%$FC%g
-s%@CFLAGS@%$CFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@FORTWRAP@%$FORTWRAP%g
-s%@HEADERS@%$HEADERS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@PARALLEL@%$PARALLEL%g
-s%@PGA_LIB_DIR@%$PGA_LIB_DIR%g
-s%@PGA_LIB@%$PGA_LIB%g
-s%@OBJS@%$OBJS%g
-s%@MPICOMP@%$MPICOMP%g
-s%@RM@%$RM%g
-s%@SHELL@%$SHELL%g
-s%@LIBS@%$LIBS%g
-s%@srcdir@%$srcdir%g
-s%@DEFS@%$DEFS%
-" $top_srcdir/${file}.in >> $file
-fi; done
-
-
-exit 0
Index: unk/optimizer/src/pgapack/pgapack/examples/c/Makefile
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/examples/c/Makefile	(revision 897)
+++ 	(revision )
@@ -1,61 +1,0 @@
-# Generated automatically from Makefile.in by configure.
-CC          = cc
-PRECFLAGS   = -O 
-CPPFLAGS    = -I/Volumes/Data_mo/GENES/Software/pgapack/include -I/Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -Dlinux -DWL=32 -DFORTRANUNDERSCORE -DOPTIMIZE 
-FC          = f77
-RM          = /bin/rm -f
-LDFLAGS     = -s  -L/Volumes/Data_mo/GENES/Software/pgapack/lib/linux  -lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm
-SHELL       = /bin/sh
-
-#    "$@" expands to the target; "$?" expands to the dependency list
-CFLAGS      = -o $@ $? $(PRECFLAGS)
-
-LINK.c      = @echo "  Compiling $@" ; $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
-
-default:
-	@make classic
-	@make dejong
-	@make example
-	@make maxbit
-	@make maxchar
-	@make maxint
-	@make name
-	@make namefull
-	@make udtstr
-	@make sampleOptimization
-
-classic: classic.c
-	$(LINK.c)
-
-dejong: dejong.c
-	$(LINK.c)
-
-example: example.c
-	$(LINK.c)
-
-maxbit: maxbit.c
-	$(LINK.c)
-
-maxchar: maxchar.c
-	$(LINK.c)
-
-maxint: maxint.c
-	$(LINK.c)
-
-name: name.c
-	$(LINK.c)
-
-namefull: namefull.c
-	$(LINK.c)
-
-udtstr: udtstr.c
-	$(LINK.c)
-
-sampleOptimization: sampleOptimization.c
-	$(LINK.c)
-clean: 
-	@$(RM) classic dejong example maxbit maxchar maxint name namefull \
-	       udtstr *.o
-
-
-
Index: unk/optimizer/src/pgapack/pgapack/examples/fortran/Makefile
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/examples/fortran/Makefile	(revision 897)
+++ 	(revision )
@@ -1,53 +1,0 @@
-# Generated automatically from Makefile.in by configure.
-FC           = f77
-PREFFLAGS    = -w
-RM           = /bin/rm -f
-LDFLAGS      = -s  -L/Volumes/Data_mo/GENES/Software/pgapack/lib/linux  -lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm
-SHELL        = /bin/sh
-
-#    "$@" expands to the target; "$?" expands to the dependency list
-FFLAGS      = -o $@ $? $(PREFFLAGS)
-
-LINK.f       = if test -n "$(FC)"; \
-                   then echo "  Compiling $@" ; $(FC) $(FFLAGS) $(LDFLAGS); \
-               else \
-                   echo "$@: Fortran compiler unavailable"; fi
-
-default:
-	@make classic
-	@make dejong
-	@make example
-	@make maxbit
-	@make maxchar
-	@make maxint 
-	@make name
-	@make namefull
-
-
-classic: classic.f
-	@$(LINK.f)
-
-dejong: dejong.f
-	@$(LINK.f)
-
-example: example.f
-	@$(LINK.f)
-
-maxbit: maxbit.f
-	@$(LINK.f)
-
-maxchar: maxchar.f
-	@$(LINK.f)
-
-maxint: maxint.f
-	@$(LINK.f)
-
-name: name.f
-	@$(LINK.f)
-
-namefull: namefull.f
-	@$(LINK.f)
-
-clean: 
-	@$(RM) classic dejong example maxbit maxchar maxint name namefull *.o
-
Index: unk/optimizer/src/pgapack/pgapack/examples/mgh/Makefile
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/examples/mgh/Makefile	(revision 897)
+++ 	(revision )
@@ -1,56 +1,0 @@
-# Generated automatically from Makefile.in by configure.
-FC        = f77
-PREFFLAGS = -w
-RM        = /bin/rm -f
-LDFLAGS   = -s  -L/Volumes/Data_mo/GENES/Software/pgapack/lib/linux  -lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm
-
-SHELL     = /bin/sh
-RANLIB    = ranlib
-MGHDIR    = .
-
-FFLAGS    = -o $@ $(PREFFLAGS)
-
-COMPILE.f = @$(FC) $(FFLAGS) -c
-
-OBJS = grdfcn77.o hesfcn77.o objfcn77.o ssqfcn77.o ssqjac77.o vecfcn77.o \
-       vecjac77.o
-
-default:
-	@echo "Compiling mgh library"
-	@make tprobs.a
-	@echo "Compiling mgh testprog"
-	@make testprog
-
-tprobs.a: $(OBJS)
-	@ar ruv tprobs.a $(OBJS)
-	@$(RANLIB) tprobs.a
-
-gradfcn77.o: gradfcn77.f
-	$(COMPILE.f) gradfcn77.f
-
-hesfcn77.o: hesfcn77.f
-	$(COMPILE.f) hesfcn77.f
-
-objfcn77.o: objfcn77.f
-	$(COMPILE.f) objfcn77.f
-
-ssqfcn77.o: ssqfcn77.f
-	$(COMPILE.f) ssqfcn77.f
-
-ssqjac77.o: ssqjac77.f
-	$(COMPILE.f) ssqjac77.f
-
-vecfcn77.o: vecfcn77.f
-	$(COMPILE.f) vecfcn77.f
-
-vecjac77.o: vecjac77.f
-	$(COMPILE.f) vecjac77.f
-
-testprog: testprog.f
-	@if test ! -f "$(MGHDIR)/tprobs.a"; then\
-		cd $(MGHDIR); make tprobs;\
-	fi
-	@$(FC) $(FFLAGS) testprog.f $(MGHDIR)/tprobs.a $(LDFLAGS)
-
-clean:
-	@$(RM) $(OBJS) tprobs.a testprog
Index: unk/optimizer/src/pgapack/pgapack/source/Makefile
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/source/Makefile	(revision 897)
+++ 	(revision )
@@ -1,130 +1,0 @@
-# Generated automatically from Makefile.in by configure.
-CC          = cc
-PRECFLAGS   = -O 
-CPPFLAGS    = -I/Volumes/Data_mo/GENES/Software/pgapack/include -I/Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -Dlinux -DWL=32 -DFORTRANUNDERSCORE -DOPTIMIZE 
-HEADERS     = /Volumes/Data_mo/GENES/Software/pgapack/include/pgapack.h
-PGA_LIB_DIR = ../lib/linux
-PGA_LIB     = pgaO
-RM          = /bin/rm -f
-OBJS        = $(PGA_LIB_DIR)/binary.o        \
-      $(PGA_LIB_DIR)/char.o          \
-      $(PGA_LIB_DIR)/cmdline.o       \
-      $(PGA_LIB_DIR)/create.o        \
-      $(PGA_LIB_DIR)/cross.o         \
-      $(PGA_LIB_DIR)/debug.o         \
-      $(PGA_LIB_DIR)/duplcate.o      \
-      $(PGA_LIB_DIR)/evaluate.o      \
-      $(PGA_LIB_DIR)/fitness.o       \
-      $(PGA_LIB_DIR)/hamming.o       \
-      $(PGA_LIB_DIR)/heap.o          \
-      $(PGA_LIB_DIR)/integer.o       \
-      $(PGA_LIB_DIR)/mutation.o      \
-      $(PGA_LIB_DIR)/parallel.o      \
-      $(PGA_LIB_DIR)/pga.o           \
-      $(PGA_LIB_DIR)/pop.o           \
-      $(PGA_LIB_DIR)/random.o        \
-      $(PGA_LIB_DIR)/real.o          \
-      $(PGA_LIB_DIR)/report.o        \
-      $(PGA_LIB_DIR)/restart.o       \
-      $(PGA_LIB_DIR)/select.o        \
-      $(PGA_LIB_DIR)/stop.o          \
-      $(PGA_LIB_DIR)/system.o        \
-      $(PGA_LIB_DIR)/user.o          \
-      $(PGA_LIB_DIR)/utility.o $(PGA_LIB_DIR)/f2c.o
-SHELL       = /bin/sh
-RANLIB      = ranlib
-
-CFLAGS      = -o $@ -c $(PRECFLAGS)
-COMPILE.c   = $(CC) $(CFLAGS) $(CPPFLAGS)
-
-########################################################
-#                    The Target                        #
-########################################################
-
-$(PGA_LIB_DIR)/lib$(PGA_LIB).a: $(OBJS)
-	ar ruv $(PGA_LIB_DIR)/lib$(PGA_LIB).a $(OBJS)
-	$(RANLIB) $(PGA_LIB_DIR)/lib$(PGA_LIB).a
-
-########################################################
-#                    The Source code                   #
-########################################################
-
-$(PGA_LIB_DIR)/binary.o: binary.c $(HEADERS)
-	$(COMPILE.c) binary.c
-
-$(PGA_LIB_DIR)/char.o: char.c $(HEADERS)
-	$(COMPILE.c) char.c
-
-$(PGA_LIB_DIR)/cmdline.o: cmdline.c $(HEADERS)
-	$(COMPILE.c) cmdline.c
-
-$(PGA_LIB_DIR)/create.o: create.c $(HEADERS)
-	$(COMPILE.c) create.c
-
-$(PGA_LIB_DIR)/cross.o: cross.c $(HEADERS)
-	$(COMPILE.c) cross.c
-
-$(PGA_LIB_DIR)/debug.o: debug.c $(HEADERS)
-	$(COMPILE.c) debug.c
-
-$(PGA_LIB_DIR)/duplcate.o: duplcate.c $(HEADERS)
-	$(COMPILE.c) duplcate.c
-
-$(PGA_LIB_DIR)/evaluate.o: evaluate.c $(HEADERS)
-	$(COMPILE.c) evaluate.c
-
-$(PGA_LIB_DIR)/fitness.o: fitness.c $(HEADERS)
-	$(COMPILE.c) fitness.c
-
-$(PGA_LIB_DIR)/f2c.o: f2c.c $(HEADERS)
-	$(COMPILE.c) f2c.c
-
-$(PGA_LIB_DIR)/hamming.o: hamming.c $(HEADERS)
-	$(COMPILE.c) hamming.c
-
-$(PGA_LIB_DIR)/heap.o: heap.c $(HEADERS)
-	$(COMPILE.c) heap.c
-
-$(PGA_LIB_DIR)/integer.o: integer.c $(HEADERS)
-	$(COMPILE.c) integer.c
-
-
-
-$(PGA_LIB_DIR)/mutation.o: mutation.c $(HEADERS)
-	$(COMPILE.c) mutation.c
-
-$(PGA_LIB_DIR)/parallel.o: parallel.c $(HEADERS)
-	$(COMPILE.c) parallel.c
-
-$(PGA_LIB_DIR)/pga.o: pga.c $(HEADERS)
-	$(COMPILE.c) pga.c
-
-$(PGA_LIB_DIR)/pop.o: pop.c $(HEADERS)
-	$(COMPILE.c) pop.c
-
-$(PGA_LIB_DIR)/random.o: random.c $(HEADERS)
-	$(COMPILE.c) random.c
-
-$(PGA_LIB_DIR)/real.o: real.c $(HEADERS)
-	$(COMPILE.c) real.c
-
-$(PGA_LIB_DIR)/report.o: report.c $(HEADERS)
-	$(COMPILE.c) report.c
-
-$(PGA_LIB_DIR)/restart.o: restart.c $(HEADERS)
-	$(COMPILE.c) restart.c
-
-$(PGA_LIB_DIR)/select.o: select.c $(HEADERS)
-	$(COMPILE.c) select.c
-
-$(PGA_LIB_DIR)/stop.o: stop.c $(HEADERS)
-	$(COMPILE.c) stop.c
-
-$(PGA_LIB_DIR)/system.o: system.c $(HEADERS)
-	$(COMPILE.c) system.c
-
-$(PGA_LIB_DIR)/user.o: user.c $(HEADERS)
-	$(COMPILE.c) user.c
-
-$(PGA_LIB_DIR)/utility.o: utility.c $(HEADERS)
-	$(COMPILE.c) utility.c
Index: unk/optimizer/src/pgapack/pgapack/test/Makefile
===================================================================
--- /trunk/optimizer/src/pgapack/pgapack/test/Makefile	(revision 897)
+++ 	(revision )
@@ -1,28 +1,0 @@
-# Generated automatically from Makefile.in by configure.
-CC          = cc
-FC          = f77
-PRECFLAGS   = -O 
-PREFFLAGS   = -w
-CPPFLAGS    = -I/Volumes/Data_mo/GENES/Software/pgapack/include -I/Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/include/ -Dlinux -DWL=32 -DFORTRANUNDERSCORE -DOPTIMIZE 
-RM          = /bin/rm -f
-LDFLAGS     = -s  -L/Volumes/Data_mo/GENES/Software/pgapack/lib/linux  -lpgaO  /Volumes/Data_mo/GENES/Software/mpich-1.2.7p1/lib/libmpich.a -lm
-SHELL       = /bin/sh
-
-#    "$@" expands to the target; "$?" expands to the dependency list
-CFLAGS      = -o $@ $? $(PRECFLAGS)
-FFLAGS      = -o $@ $? $(PREFFLAGS)
-
-LINK.c      = @echo "  Compiling $@" ; $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
-LINK.f      = @if test -n "$(FC)"; \
-                  then echo "  Compiling $@" ; $(FC) $(FFLAGS) $(LDFLAGS); \
-              else \
-                  echo "$@: Fortran compiler unavailable"; fi
-
-default:
-	@make instverf 
-
-instverf: instverf.c
-	$(LINK.c)
-
-clean: 
-	@$(RM) instverf instverf.o
Index: /trunk/optimizer/src/plugin_pgapack.c
===================================================================
--- /trunk/optimizer/src/plugin_pgapack.c	(revision 897)
+++ /trunk/optimizer/src/plugin_pgapack.c	(revision 898)
@@ -14,14 +14,49 @@
  * ======================================================================
  */
+#include "pgapack.h"
 #include "rp_optimizer_plugin.h"
 
 typedef struct PgapackData {
-    int foo;                        /* data used by Pgapack... */
+    int operation;       /* operation <=> PGA_MINIMIZE/PGA_MAXIMIZE */
+    int maxRuns;         /* maximum runs <=> PGASetMaxGAIterValue() */
+    int popSize;         /* population size <=> PGASetPopSize() */
+    int popRepl;         /* replacement <=> PGASetPopReplacementType() */
 } PgapackData;
 
+RpCustomTclOptionParse RpOption_ParseOper;
+RpCustomTclOptionGet RpOption_GetOper;
+RpTclOptionType RpOption_Oper = {
+    "pga_operation", RpOption_ParseOper, RpOption_GetOper, NULL
+};
+
+RpCustomTclOptionParse RpOption_ParsePopRepl;
+RpCustomTclOptionGet RpOption_GetPopRepl;
+RpTclOptionType RpOption_PopRepl = {
+    "pga_poprepl", RpOption_ParsePopRepl, RpOption_GetPopRepl, NULL
+};
+
 RpTclOption PgapackOptions[] = {
-  {"-foo", RP_OPTION_INT, NULL, Rp_Offset(PgapackData,foo)},
-  {NULL, NULL, NULL, 0}
+  {"-maxruns", RP_OPTION_INT, Rp_Offset(PgapackData,maxRuns)},
+  {"-operation", &RpOption_Oper, Rp_Offset(PgapackData,operation)},
+  {"-poprepl", &RpOption_PopRepl, Rp_Offset(PgapackData,popRepl)},
+  {"-popsize", RP_OPTION_INT, Rp_Offset(PgapackData,popSize)},
+  {NULL, NULL, 0}
 };
+
+static double PgapEvaluate _ANSI_ARGS_((PGAContext *ctx, int p, int pop));
+static void PgapCreateString _ANSI_ARGS_((PGAContext *ctx, int, int, int));
+static int PgapMutation _ANSI_ARGS_((PGAContext *ctx, int, int, double));
+static void PgapCrossover _ANSI_ARGS_((PGAContext *ctx, int, int, int,
+    int, int, int));
+static void PgapPrintString _ANSI_ARGS_((PGAContext *ctx, FILE*, int, int));
+static void PgapCopyString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
+static int PgapDuplicateString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
+static MPI_Datatype PgapBuildDT _ANSI_ARGS_((PGAContext *ctx, int, int));
+
+static void PgapLinkContext2Env _ANSI_ARGS_((PGAContext *ctx,
+    RpOptimEnv *envPtr));
+static RpOptimEnv* PgapGetEnvForContext _ANSI_ARGS_((PGAContext *ctx));
+static void PgapUnlinkContext2Env _ANSI_ARGS_((PGAContext *ctx));
+
 
 /*
@@ -38,7 +73,101 @@
 {
     PgapackData *dataPtr;
+
     dataPtr = (PgapackData*)malloc(sizeof(PgapackData));
-    dataPtr->foo = 1;
+    dataPtr->operation = PGA_MINIMIZE;
+    dataPtr->maxRuns = 10000;
+    dataPtr->popRepl = PGA_POPREPL_BEST;
+    dataPtr->popSize = 200;
+
     return (ClientData)dataPtr;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapackRun()
+ *
+ * This routine is called to kick off an optimization run.  Sets up
+ * a PGApack context and starts invoking runs.
+ * ----------------------------------------------------------------------
+ */
+RpOptimStatus
+PgapackRun(envPtr, evalProc)
+    RpOptimEnv *envPtr;           /* optimization environment */
+    RpOptimEvaluator *evalProc;   /* call this proc to run tool */
+{
+    PgapackData *dataPtr =(PgapackData*)envPtr->pluginData;
+    PGAContext *ctx;
+
+    /* pgapack requires at least one arg -- the executable name */
+    /* fake it here by just saying something like "rappture" */
+    int argc = 1; char *argv[] = {"rappture"};
+
+    ctx = PGACreate(&argc, argv, PGA_DATATYPE_USER, envPtr->numParams,
+        dataPtr->operation);
+
+    PGASetMaxGAIterValue(ctx, dataPtr->maxRuns);
+    PGASetPopSize(ctx, dataPtr->popSize);
+    PGASetPopReplaceType(ctx, dataPtr->popRepl);
+
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_CREATESTRING, PgapCreateString);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_MUTATION, PgapMutation);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_CROSSOVER, PgapCrossover);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_PRINTSTRING, PgapPrintString);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_COPYSTRING, PgapCopyString);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_DUPLICATE, PgapDuplicateString);
+    PGASetUserFunction(ctx, PGA_USERFUNCTION_BUILDDATATYPE, PgapBuildDT);
+
+    envPtr->evalProc = evalProc;  /* call this later for evaluations */
+
+    /*
+     * We need a way to convert from a PGAContext to our RpOptimEnv
+     * data.  This happens when Pgapack calls routines like
+     * PgapCreateString, passing in the PGAContext, but nothing else.
+     * Call PgapLinkContext2Env() here, so later on we can figure
+     * out how many parameters, names, types, etc.
+     */
+    PgapLinkContext2Env(ctx, envPtr);
+
+    PGASetUp(ctx);
+    PGARun(ctx, PgapEvaluate);
+    PGADestroy(ctx);
+
+    PgapUnlinkContext2Env(ctx);
+
+    return RP_OPTIM_SUCCESS;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapackEvaluate()
+ *
+ * Called by PGApack whenever a set of input values needs to be
+ * evaluated.  Passes the values on to the underlying Rappture tool,
+ * launches a run, and computes the value of the fitness function.
+ * Returns the value for the fitness function.
+ * ----------------------------------------------------------------------
+ */
+double
+PgapEvaluate(ctx, p, pop)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p;            /* sample #p being run */
+    int pop;          /* identifier for this population */
+{
+    double fit = 0.0;
+    RpOptimEnv *envPtr;
+    RpOptimParam *paramPtr;
+    RpOptimStatus status;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
+
+    status = (*envPtr->evalProc)(envPtr, paramPtr, envPtr->numParams, &fit);
+
+    if (status != RP_OPTIM_SUCCESS) {
+        fprintf(stderr, "==WARNING: run failed!");
+        PgapPrintString(ctx, stderr, p, pop);
+    }
+
+    return fit;
 }
 
@@ -57,5 +186,503 @@
 {
     PgapackData *dataPtr = (PgapackData*)cdata;
-    dataPtr->foo = 0;
     free(dataPtr);
 }
+
+/*
+ * ======================================================================
+ *  ROUTINES FOR MANAGING DATA STRINGS
+ * ======================================================================
+ * PgapCreateString()
+ *
+ * Called by pgapack to create the so-called "string" of data used for
+ * an evaluation.
+ * ----------------------------------------------------------------------
+ */
+void
+PgapCreateString(ctx, p, pop, initFlag)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p;            /* sample #p being run */
+    int pop;          /* identifier for this population */
+    int initFlag;     /* non-zero => fields should be initialized */
+{
+    int n, ival;
+    double dval;
+    RpOptimEnv *envPtr;
+    RpOptimParam *oldParamPtr, *newParamPtr;
+    PGAIndividual *newData;
+    RpOptimParamNumber *numPtr;
+    RpOptimParamString *strPtr;
+
+    envPtr = PgapGetEnvForContext(ctx);
+
+    newData = PGAGetIndividual(ctx, p, pop);
+    newData->chrom = malloc(envPtr->numParams*sizeof(RpOptimParam));
+    newParamPtr = (RpOptimParam*)newData->chrom;
+
+    for (n=0; n < envPtr->numParams; n++) {
+        oldParamPtr = envPtr->paramList[n];
+        newParamPtr[n].name = oldParamPtr->name;
+        newParamPtr[n].type = oldParamPtr->type;
+        switch (oldParamPtr->type) {
+        case RP_OPTIMPARAM_NUMBER:
+            newParamPtr[n].value.dval = 0.0;
+            break;
+        case RP_OPTIMPARAM_STRING:
+            newParamPtr[n].value.sval.num = -1;
+            newParamPtr[n].value.sval.str = NULL;
+            break;
+        default:
+            panic("bad parameter type in PgapCreateString()");
+        }
+    }
+
+    if (initFlag) {
+        for (n=0; n < envPtr->numParams; n++) {
+            switch (newParamPtr[n].type) {
+            case RP_OPTIMPARAM_NUMBER:
+                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
+                dval = PGARandom01(ctx,0);
+                newParamPtr[n].value.dval =
+                    (numPtr->max - numPtr->min)*dval + numPtr->min;
+                break;
+            case RP_OPTIMPARAM_STRING:
+                strPtr = (RpOptimParamString*)envPtr->paramList[n];
+                ival = (int)floor(PGARandom01(ctx,0) * strPtr->numValues);
+                envPtr->paramList[n]->value.sval.num = ival;
+                envPtr->paramList[n]->value.sval.str = strPtr->values[ival];
+                break;
+            default:
+                panic("bad parameter type in PgapCreateString()");
+            }
+        }
+    }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapMutation()
+ *
+ * Called by pgapack to perform random mutations on the input data
+ * used for evaluation.
+ * ----------------------------------------------------------------------
+ */
+int
+PgapMutation(ctx, p, pop, mr)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p;            /* sample #p being run */
+    int pop;          /* identifier for this population */
+    double mr;        /* probability of mutation for each gene */
+{
+    int count = 0;    /* number of mutations */
+
+    int n, ival;
+    RpOptimEnv *envPtr;
+    RpOptimParam *paramPtr;
+    RpOptimParamNumber *numPtr;
+    RpOptimParamString *strPtr;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
+
+    for (n=0; n < envPtr->numParams; n++) {
+        if (PGARandomFlip(ctx, mr)) {
+            /* won the coin toss -- change this parameter */
+            count++;
+
+            switch (paramPtr[n].type) {
+            case RP_OPTIMPARAM_NUMBER:
+                /* bump the value up/down a little, randomly */
+                if (PGARandomFlip(ctx, 0.5)) {
+                    paramPtr[n].value.dval += 0.1*paramPtr[n].value.dval;
+                } else {
+                    paramPtr[n].value.dval -= 0.1*paramPtr[n].value.dval;
+                }
+                /* make sure the resulting value is still in bounds */
+                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
+                if (paramPtr[n].value.dval > numPtr->max) {
+                    paramPtr[n].value.dval = numPtr->max;
+                }
+                if (paramPtr[n].value.dval < numPtr->min) {
+                    paramPtr[n].value.dval = numPtr->min;
+                }
+                break;
+
+            case RP_OPTIMPARAM_STRING:
+                ival = paramPtr[n].value.sval.num;
+                if (PGARandomFlip(ctx, 0.5)) {
+                    ival += 1;
+                } else {
+                    ival -= 1;
+                }
+                strPtr = (RpOptimParamString*)envPtr->paramList[n];
+                if (ival < 0) ival = 0;
+                if (ival >= strPtr->numValues) ival = strPtr->numValues-1;
+                paramPtr[n].value.sval.num = ival;
+                paramPtr[n].value.sval.str = strPtr->values[ival];
+                break;
+
+            default:
+                panic("bad parameter type in PgapMutation()");
+            }
+        }
+    }
+    return count;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapCrossover()
+ *
+ * Called by pgapack to perform cross-over mutations on the input data
+ * used for evaluation.
+ * ----------------------------------------------------------------------
+ */
+void
+PgapCrossover(ctx, p1, p2, pop1, c1, c2, pop2)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p1;           /* sample # for parent of input string1 */
+    int p2;           /* sample # for parent of input string2 */
+    int pop1;         /* population containing p1 and p2 */
+    int c1;           /* sample # for child of input string1 */
+    int c2;           /* sample # for child of input string2 */
+    int pop2;         /* population containing c1 and c2 */
+{
+    int n;
+    RpOptimEnv *envPtr;
+    RpOptimParam *parent1, *parent2, *child1, *child2;
+    double pu;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    parent1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
+    parent2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop1)->chrom;
+    child1  = (RpOptimParam*)PGAGetIndividual(ctx, c1, pop2)->chrom;
+    child2  = (RpOptimParam*)PGAGetIndividual(ctx, c2, pop2)->chrom;
+
+    pu = PGAGetUniformCrossoverProb(ctx);
+
+    for (n=0; n < envPtr->numParams; n++) {
+        if (PGARandomFlip(ctx, pu)) {
+            /* child inherits from parent */
+            memcpy(&child1[n], &parent1[n], sizeof(RpOptimParam));
+            memcpy(&child2[n], &parent2[n], sizeof(RpOptimParam));
+        } else {
+            /* crossover */
+            memcpy(&child1[n], &parent2[n], sizeof(RpOptimParam));
+            memcpy(&child2[n], &parent1[n], sizeof(RpOptimParam));
+        }
+    }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapPrintString()
+ *
+ * Called by pgapack to format the values for a particular string of
+ * input data.
+ * ----------------------------------------------------------------------
+ */
+void
+PgapPrintString(ctx, fp, p, pop)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    FILE *fp;         /* write to this file pointer */
+    int p;            /* sample #p being run */
+    int pop;          /* identifier for this population */
+{
+    int n;
+    RpOptimEnv *envPtr;
+    RpOptimParam *paramPtr;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
+
+    for (n=0; n < envPtr->numParams; n++) {
+        fprintf(fp, "#%4d: ", n);
+        switch (paramPtr[n].type) {
+        case RP_OPTIMPARAM_NUMBER:
+            fprintf(fp, "[%11.7g] (%s)\n", paramPtr[n].value.dval,
+                paramPtr[n].name);
+            break;
+        case RP_OPTIMPARAM_STRING:
+            fprintf(fp, "[%d]=\"%s\" (%s)\n", paramPtr[n].value.sval.num,
+                paramPtr[n].value.sval.str, paramPtr[n].name);
+            break;
+        default:
+            panic("bad parameter type in PgapPrintString()");
+        }
+    }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapCopyString()
+ *
+ * Called by pgapack to copy one input string to another.
+ * ----------------------------------------------------------------------
+ */
+void
+PgapCopyString(ctx, p1, pop1, p2, pop2)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p1;           /* source sample # being run */
+    int pop1;         /* population containing p1 */
+    int p2;           /* destination sample # being run */
+    int pop2;         /* population containing p1 */
+{
+    int n;
+    RpOptimEnv *envPtr;
+    RpOptimParam *src, *dst;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    src = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
+    dst = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
+
+    for (n=0; n < envPtr->numParams; n++) {
+        dst[n].type = src[n].type;
+        switch (src[n].type) {
+        case RP_OPTIMPARAM_NUMBER:
+            dst[n].value.dval = src[n].value.dval;
+            break;
+        case RP_OPTIMPARAM_STRING:
+            dst[n].value.sval.num = src[n].value.sval.num;
+            dst[n].value.sval.str = src[n].value.sval.str;
+            break;
+        default:
+            panic("bad parameter type in PgapCopyString()");
+        }
+    }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapDuplicateString()
+ *
+ * Called by pgapack to compare two input strings.  Returns non-zero if
+ * the two are duplicates and 0 otherwise.
+ * ----------------------------------------------------------------------
+ */
+int
+PgapDuplicateString(ctx, p1, pop1, p2, pop2)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p1;           /* sample #p being run */
+    int pop1;         /* population containing p1 */
+    int p2;           /* sample #p being run */
+    int pop2;         /* population containing p1 */
+{
+    int n;
+    RpOptimEnv *envPtr;
+    RpOptimParam *param1, *param2;
+
+    envPtr = PgapGetEnvForContext(ctx);
+    param1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
+    param2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
+
+    for (n=0; n < envPtr->numParams; n++) {
+        if (param1[n].type != param2[n].type) {
+            return 0;  /* different! */
+        }
+        switch (param1[n].type) {
+        case RP_OPTIMPARAM_NUMBER:
+            if (param1[n].value.dval != param2[n].value.dval) {
+                return 0;  /* different! */
+            }
+            break;
+        case RP_OPTIMPARAM_STRING:
+            if (param1[n].value.sval.num != param2[n].value.sval.num) {
+                return 0;  /* different! */
+            }
+            break;
+        default:
+            panic("bad parameter type in PgapDuplicateString()");
+        }
+    }
+    return 1;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * PgapCopyString()
+ *
+ * Called by pgapack to copy one input string to another.
+ * ----------------------------------------------------------------------
+ */
+MPI_Datatype
+PgapBuildDT(ctx, p, pop)
+    PGAContext *ctx;  /* pgapack context for this optimization */
+    int p;            /* sample # being run */
+    int pop;          /* population containing sample */
+{
+    panic("MPI support not implemented!");
+    return NULL;
+}
+
+/*
+ * ======================================================================
+ *  OPTION:  -operation <=> PGA_MINIMIZE / PGA_MAXIMIZE
+ * ======================================================================
+ */
+int
+RpOption_ParseOper(interp, valObj, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    Tcl_Obj *valObj;     /* set option to this new value */
+    ClientData cdata;    /* save in this data structure */
+    int offset;          /* save at this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
+    if (strcmp(val,"minimize") == 0) {
+        *ptr = PGA_MINIMIZE;
+    }
+    else if (strcmp(val,"maximize") == 0) {
+        *ptr = PGA_MAXIMIZE;
+    }
+    else {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+            "bad value \"", val, "\": should be minimize, maximize",
+            (char*)NULL);
+        return TCL_ERROR;
+    }
+    return TCL_OK;
+}
+
+int
+RpOption_GetOper(interp, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    ClientData cdata;    /* get from this data structure */
+    int offset;          /* get from this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    switch (*ptr) {
+    case PGA_MINIMIZE:
+        Tcl_SetResult(interp, "minimize", TCL_STATIC);
+        break;
+    case PGA_MAXIMIZE:
+        Tcl_SetResult(interp, "maximize", TCL_STATIC);
+        break;
+    default:
+        Tcl_SetResult(interp, "???", TCL_STATIC);
+        break;
+    }
+    return TCL_OK;
+}
+
+/*
+ * ======================================================================
+ *  OPTION:  -poprepl <=> PGASetPopReplacementType()
+ * ======================================================================
+ */
+int
+RpOption_ParsePopRepl(interp, valObj, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    Tcl_Obj *valObj;     /* set option to this new value */
+    ClientData cdata;    /* save in this data structure */
+    int offset;          /* save at this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
+    if (*val == 'b' && strcmp(val,"best") == 0) {
+        *ptr = PGA_POPREPL_BEST;
+    }
+    else if (*val == 'r' && strcmp(val,"random-repl") == 0) {
+        *ptr = PGA_POPREPL_RANDOM_REP;
+    }
+    else if (*val == 'r' && strcmp(val,"random-norepl") == 0) {
+        *ptr = PGA_POPREPL_RANDOM_NOREP;
+    }
+    else {
+        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+            "bad value \"", val, "\": should be best, random-norepl,"
+            " or random-repl", (char*)NULL);
+        return TCL_ERROR;
+    }
+    return TCL_OK;
+}
+
+int
+RpOption_GetPopRepl(interp, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    ClientData cdata;    /* get from this data structure */
+    int offset;          /* get from this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    switch (*ptr) {
+    case PGA_POPREPL_BEST:
+        Tcl_SetResult(interp, "best", TCL_STATIC);
+        break;
+    case PGA_POPREPL_RANDOM_REP:
+        Tcl_SetResult(interp, "random-repl", TCL_STATIC);
+        break;
+    case PGA_POPREPL_RANDOM_NOREP:
+        Tcl_SetResult(interp, "random-norepl", TCL_STATIC);
+        break;
+    default:
+        Tcl_SetResult(interp, "???", TCL_STATIC);
+        break;
+    }
+    return TCL_OK;
+}
+
+/*
+ * ======================================================================
+ *  ROUTINES FOR CONNECTING PGACONTEXT <=> RPOPTIMENV
+ * ======================================================================
+ * PgapLinkContext2Env()
+ *   This routine is used internally to establish a relationship between
+ *   a PGAContext token and its corresponding RpOptimEnv data.  The
+ *   PGA routines don't provide a way to pass the RpOptimEnv data along,
+ *   so we use these routines to find the correspondence.
+ *
+ * PgapGetEnvForContext()
+ *   Returns the RpOptimEnv associated with a given PGAContext.  If the
+ *   link has not been established via PgapLinkContext2Env(), then this
+ *   routine returns NULL.
+ *
+ * PgapUnlinkContext2Env()
+ *   Breaks the link between a PGAContext and its RpOptimEnv.  Should
+ *   be called when the PGAContext is destroyed and is no longer valid.
+ * ----------------------------------------------------------------------
+ */
+static Tcl_HashTable *Pgacontext2Rpenv = NULL;
+
+void
+PgapLinkContext2Env(ctx, envPtr)
+    PGAContext *ctx;      /* pgapack context for this optimization */
+    RpOptimEnv *envPtr;   /* corresponding Rappture optimization data */
+{
+    Tcl_HashEntry *ctxEntry;
+    int newEntry;
+
+    if (Pgacontext2Rpenv == NULL) {
+        Pgacontext2Rpenv = (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable));
+        Tcl_InitHashTable(Pgacontext2Rpenv, TCL_ONE_WORD_KEYS);
+    }
+    ctxEntry = Tcl_CreateHashEntry(Pgacontext2Rpenv, (char*)ctx, &newEntry);
+    Tcl_SetHashValue(ctxEntry, (ClientData)envPtr);
+}
+
+RpOptimEnv*
+PgapGetEnvForContext(ctx)
+    PGAContext *ctx;
+{
+    Tcl_HashEntry *entryPtr;
+
+    if (Pgacontext2Rpenv) {
+        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
+        if (entryPtr) {
+            return (RpOptimEnv*)Tcl_GetHashValue(entryPtr);
+        }
+    }
+    return NULL;
+}
+
+void
+PgapUnlinkContext2Env(ctx)
+    PGAContext *ctx;
+{
+    Tcl_HashEntry *entryPtr;
+
+    if (Pgacontext2Rpenv) {
+        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
+        if (entryPtr) {
+            Tcl_DeleteHashEntry(entryPtr);
+        }
+    }
+}
Index: /trunk/optimizer/src/rp_optimizer.c
===================================================================
--- /trunk/optimizer/src/rp_optimizer.c	(revision 897)
+++ /trunk/optimizer/src/rp_optimizer.c	(revision 898)
@@ -33,12 +33,13 @@
  */
 RpOptimEnv*
-RpOptimCreate(pluginData, cleanupPtr)
+RpOptimCreate(pluginData, cleanupProc)
     ClientData pluginData;        /* special data created for this env */
-    RpOptimCleanup *cleanupPtr;   /* routine to clean up pluginData */
+    RpOptimCleanup *cleanupProc;  /* routine to clean up pluginData */
 {
     RpOptimEnv *envPtr;
     envPtr = (RpOptimEnv*)malloc(sizeof(RpOptimEnv));
-    envPtr->pluginData = pluginData;
-    envPtr->cleanupPtr = cleanupPtr;
+    envPtr->pluginData  = pluginData;
+    envPtr->cleanupProc = cleanupProc;
+    envPtr->toolData    = NULL;
 
     envPtr->numParams = 0;
@@ -106,5 +107,5 @@
     numPtr->base.name = strdup(name);
     numPtr->base.type = RP_OPTIMPARAM_NUMBER;
-    numPtr->base.value.num = 0.0;
+    numPtr->base.value.dval = 0.0;
     numPtr->min = -DBL_MAX;
     numPtr->max = DBL_MAX;
@@ -134,6 +135,8 @@
     strPtr->base.name = strdup(name);
     strPtr->base.type = RP_OPTIMPARAM_STRING;
-    strPtr->base.value.str = NULL;
+    strPtr->base.value.sval.num = -1;
+    strPtr->base.value.sval.str = NULL;
     strPtr->values = NULL;
+    strPtr->numValues = 0;
 
     RpOptimAddParam(envPtr, (RpOptimParam*)strPtr);
@@ -194,85 +197,4 @@
 /*
  * ----------------------------------------------------------------------
- * RpOptimPerform()
- *
- * Used to perform an optimization in the given context.  Each run is
- * performed by calling an evaluation function represented by a
- * function pointer.  If an optimum value is found within the limit
- * on the number of runs, then this procedure returns RP_OPTIM_SUCCESS.
- * Values for the optimum input parameters are returned through the
- * paramList within the context.  If the optimization fails, this
- * function returns RP_OPTIM_FAILURE.
- * ----------------------------------------------------------------------
- */
-RpOptimStatus
-RpOptimPerform(envPtr, evalFuncPtr, maxRuns)
-    RpOptimEnv *envPtr;               /* context for this optimization */
-    RpOptimEvaluator *evalFuncPtr;    /* function called to handle run */
-    int maxRuns;                      /* limit on number of runs,
-                                       * or 0 for no limit */
-{
-    RpOptimStatus status = RP_OPTIM_UNKNOWN;
-
-    int n, nruns, ival, nvals;
-    double dval, fitness;
-    RpOptimParamNumber *numPtr;
-    RpOptimParamString *strPtr;
-    RpOptimStatus runStatus;
-
-    if (envPtr->numParams == 0) {    /* no input parameters? */
-        return RP_OPTIM_FAILURE;     /* then we can't optimize! */
-    }
-
-    /*
-     * Call the evaluation function a number of times with different
-     * values and perform the optimization.
-     */
-    nruns = 0;
-    while (status == RP_OPTIM_UNKNOWN) {
-        /*
-         * Pick random values for all inputs.
-         */
-        for (n=0; n < envPtr->numParams; n++) {
-            switch (envPtr->paramList[n]->type) {
-                case RP_OPTIMPARAM_NUMBER:
-                    numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
-                    dval = drand48();
-                    envPtr->paramList[n]->value.num =
-                        (numPtr->max - numPtr->min)*dval + numPtr->min;
-                    break;
-                case RP_OPTIMPARAM_STRING:
-                    strPtr = (RpOptimParamString*)envPtr->paramList[n];
-                    for (nvals=0; strPtr->values[nvals]; nvals++)
-                        ;  /* count values */
-                    ival = (int)floor(drand48() * nvals);
-                    envPtr->paramList[n]->value.str = strPtr->values[ival];
-                    break;
-            }
-        }
-
-        /*
-         * Call the evaluation function to get the fitness value.
-         */
-        runStatus = (*evalFuncPtr)(envPtr->paramList, envPtr->numParams,
-            &fitness);
-
-        if (runStatus == RP_OPTIM_SUCCESS) {
-            /*
-             * Is the fitness function any better?
-             * Change the input values here based on fitness.
-             *  ...
-             */
-        }
-
-        if (++nruns >= maxRuns && maxRuns > 0) {
-            status = RP_OPTIM_FAILURE;  /* reached the limit of runs */
-        }
-    }
-
-    return status;
-}
-
-/*
- * ----------------------------------------------------------------------
  * RpOptimDelete()
  *
@@ -292,6 +214,6 @@
         RpOptimCleanupParam(envPtr->paramList[n]);
     }
-    if (envPtr->cleanupPtr) {
-        (*envPtr->cleanupPtr)(envPtr->pluginData);
+    if (envPtr->cleanupProc) {
+        (*envPtr->cleanupProc)(envPtr->pluginData);
     }
     free(envPtr->paramList);
Index: /trunk/optimizer/src/rp_optimizer.h
===================================================================
--- /trunk/optimizer/src/rp_optimizer.h	(revision 897)
+++ /trunk/optimizer/src/rp_optimizer.h	(revision 898)
@@ -32,4 +32,23 @@
 
 /*
+ * During each optimization, a function of the following type is
+ * called again and again to evaluate input parameters and compute
+ * the fitness function.
+ */
+typedef enum {
+    RP_OPTIM_SUCCESS=0, RP_OPTIM_UNKNOWN, RP_OPTIM_FAILURE, RP_OPTIM_ABORTED
+} RpOptimStatus;
+
+struct RpOptimEnv;   /* defined below */
+struct RpOptimParam;
+
+typedef RpOptimStatus (RpOptimEvaluator) _ANSI_ARGS_((
+    struct RpOptimEnv *envPtr, struct RpOptimParam *values, int numValues,
+    double *fitnessPtr));
+
+typedef RpOptimStatus (RpOptimHandler) _ANSI_ARGS_((
+    struct RpOptimEnv *envPtr, RpOptimEvaluator *evalProc));
+
+/*
  * This is the basic definition for each parameter within an optimization.
  * Each parameter has a name, type, and value.  The value is important
@@ -41,10 +60,16 @@
 } RpOptimParamType;
 
+typedef struct RpDiscreteString {
+    int num;                        /* integer representing this string */
+    char *str;                      /* actual string selected */
+} RpDiscreteString;
+
 typedef struct RpOptimParam {
     char *name;                     /* name of this parameter */
     RpOptimParamType type;          /* paramter type -- number, string, etc */
     union {
-        double num;                 /* slot for number value */
-        char *str;                  /* slot for string value */
+        double dval;                /* slot for number value */
+        int ival;                   /* slot for integer value */
+        RpDiscreteString sval;      /* slot for string value */
     } value;
 } RpOptimParam;
@@ -65,4 +90,5 @@
     RpOptimParam base;              /* basic parameter info */
     char **values;                  /* array of allowed values */
+    int numValues;                  /* number of allowed values */
 } RpOptimParamString;
 
@@ -72,6 +98,8 @@
  */
 typedef struct RpOptimEnv {
+    RpOptimEvaluator *evalProc;     /* called during optimization to do run */
     ClientData pluginData;          /* data created by plugin init routine */
-    RpOptimCleanup *cleanupPtr;     /* cleanup routine for pluginData */
+    RpOptimCleanup *cleanupProc;    /* cleanup routine for pluginData */
+    ClientData toolData;            /* data used during tool execution */
     RpOptimParam **paramList;       /* list of input parameters to vary */
     int numParams;                  /* current number of parameters */
@@ -80,20 +108,8 @@
 
 /*
- * During each optimization, a function of the following type is
- * called againa and again to evaluate input parameters and compute
- * the fitness function.
- */
-typedef enum {
-    RP_OPTIM_SUCCESS=0, RP_OPTIM_UNKNOWN, RP_OPTIM_FAILURE
-} RpOptimStatus;
-
-typedef RpOptimStatus (RpOptimEvaluator)_ANSI_ARGS_((RpOptimParam **values,
-    int numValues, double *fitnessPtr));
-
-/*
  *  Here are the functions in the API:
  */
 EXTERN RpOptimEnv* RpOptimCreate _ANSI_ARGS_((ClientData pluginData,
-    RpOptimCleanup *cleanupPtr));
+    RpOptimCleanup *cleanupProc));
 
 EXTERN RpOptimParam* RpOptimAddParamNumber _ANSI_ARGS_((RpOptimEnv *envPtr,
@@ -108,7 +124,4 @@
 EXTERN void RpOptimDeleteParam _ANSI_ARGS_((RpOptimEnv *envPtr, char *name));
 
-EXTERN RpOptimStatus RpOptimPerform _ANSI_ARGS_((RpOptimEnv *envPtr,
-    RpOptimEvaluator *evalFuncPtr, int maxRuns));
-
 EXTERN void RpOptimDelete _ANSI_ARGS_((RpOptimEnv *envPtr));
 
Index: /trunk/optimizer/src/rp_optimizer_plugin.h
===================================================================
--- /trunk/optimizer/src/rp_optimizer_plugin.h	(revision 897)
+++ /trunk/optimizer/src/rp_optimizer_plugin.h	(revision 898)
@@ -30,8 +30,9 @@
  */
 typedef struct RpOptimPlugin {
-    char *name;                    /* name of this package for -using */
-    RpOptimInit *initPtr;          /* initialization routine */
-    RpOptimCleanup *cleanupPtr;    /* cleanup routine */
-    RpTclOption *optionSpec;       /* specs for config options */
+    char *name;                   /* name of this package for -using */
+    RpOptimInit *initProc;        /* initialization routine */
+    RpOptimHandler *runProc;      /* handles the core optimization */
+    RpOptimCleanup *cleanupProc;  /* cleanup routine */
+    RpTclOption *optionSpec;      /* specs for config options */
 } RpOptimPlugin;
 
Index: /trunk/optimizer/src/rp_optimizer_tcl.c
===================================================================
--- /trunk/optimizer/src/rp_optimizer_tcl.c	(revision 897)
+++ /trunk/optimizer/src/rp_optimizer_tcl.c	(revision 898)
@@ -26,9 +26,10 @@
  */
 RpOptimInit PgapackInit;
+RpOptimHandler PgapackRun;
 RpOptimCleanup PgapackCleanup;
 extern RpTclOption PgapackOptions;
 
 static RpOptimPlugin rpOptimPlugins[] = {
-    {"pgapack", PgapackInit, PgapackCleanup, &PgapackOptions},
+    {"pgapack", PgapackInit, PgapackRun, PgapackCleanup, &PgapackOptions},
     {NULL, NULL, NULL},
 };
@@ -39,4 +40,10 @@
 } RpOptimPluginData;
 
+typedef struct RpOptimToolData {
+    Tcl_Interp *interp;             /* interp handling this tool */
+    Tcl_Obj *toolPtr;               /* command for tool object */
+    Tcl_Obj *updateCmdPtr;          /* command used to look for abort */
+} RpOptimToolData;
+
 /*
  * ----------------------------------------------------------------------
@@ -45,12 +52,12 @@
  */
 RpTclOption rpOptimNumberOpts[] = {
-  {"-min", RP_OPTION_DOUBLE, NULL, Rp_Offset(RpOptimParamNumber,min)},
-  {"-max", RP_OPTION_DOUBLE, NULL, Rp_Offset(RpOptimParamNumber,max)},
-  {NULL, NULL, NULL, 0}
+  {"-min", RP_OPTION_DOUBLE, Rp_Offset(RpOptimParamNumber,min)},
+  {"-max", RP_OPTION_DOUBLE, Rp_Offset(RpOptimParamNumber,max)},
+  {NULL, NULL, 0}
 };
 
 RpTclOption rpOptimStringOpts[] = {
-  {"-values", RP_OPTION_LIST, NULL, Rp_Offset(RpOptimParamString,values)},
-  {NULL, NULL, NULL, 0}
+  {"-values", RP_OPTION_LIST, Rp_Offset(RpOptimParamString,values)},
+  {NULL, NULL, 0}
 };
 
@@ -61,4 +68,7 @@
     Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
 static void RpOptimInstanceCleanup _ANSI_ARGS_((ClientData cdata));
+static RpOptimStatus RpOptimizerPerformInTcl _ANSI_ARGS_((RpOptimEnv *envPtr,
+    RpOptimParam *values, int numValues, double *fitnessPtr));
+static int RpOptimizerUpdateInTcl _ANSI_ARGS_((RpOptimEnv *envPtr));
 
 #ifdef BUILD_Rappture
@@ -111,4 +121,8 @@
     RpOptimPlugin *usingPluginPtr = &rpOptimPlugins[0];
 
+    /* no good default for the tool being optimized */
+    Tcl_Obj *toolPtr = NULL;
+
+    /* no name for this object by default */
     char *name = NULL;
 
@@ -116,4 +130,6 @@
     RpOptimPlugin* pluginPtr;
     RpOptimPluginData* pluginDataPtr;
+    RpOptimToolData* toolDataPtr;
+
     int n;
     char *option, autoname[32], *sep;
@@ -174,8 +190,19 @@
             n += 2;
         }
+        else if (strcmp(option,"-tool") == 0) {
+            if (n+1 >= objc) {
+                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "missing value for option \"", option, "\"",
+                    (char*)NULL);
+                return TCL_ERROR;
+            }
+            toolPtr = objv[n+1];
+            Tcl_IncrRefCount(toolPtr);
+            n += 2;
+        }
         else {
             Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
                 "bad option \"", option, "\": should be ",
-                "-using", (char*)NULL);
+                "-tool, -using", (char*)NULL);
             return TCL_ERROR;
         }
@@ -198,8 +225,14 @@
     pluginDataPtr->pluginDefn = usingPluginPtr;
     pluginDataPtr->clientData = NULL;
-    if (usingPluginPtr->initPtr) {
-        pluginDataPtr->clientData = (*usingPluginPtr->initPtr)();
+    if (usingPluginPtr->initProc) {
+        pluginDataPtr->clientData = (*usingPluginPtr->initProc)();
     }
     envPtr = RpOptimCreate((ClientData)pluginDataPtr, RpOptimInstanceCleanup);
+
+    toolDataPtr = (RpOptimToolData*)malloc(sizeof(RpOptimToolData));
+    toolDataPtr->interp = interp;
+    toolDataPtr->toolPtr = toolPtr;
+    toolDataPtr->updateCmdPtr = NULL;
+    envPtr->toolData = (ClientData)toolDataPtr;
 
     Tcl_CreateObjCommand(interp, name, RpOptimInstanceCmd,
@@ -224,6 +257,19 @@
 {
     RpOptimEnv *envPtr = (RpOptimEnv*)cdata;
+    RpOptimToolData *toolDataPtr;
     int n;
     ClientData paramdata;
+
+    if (envPtr->toolData) {
+        toolDataPtr = (RpOptimToolData*)envPtr->toolData;
+        if (toolDataPtr->toolPtr) {
+            Tcl_DecrRefCount(toolDataPtr->toolPtr);
+        }
+        if (toolDataPtr->updateCmdPtr) {
+            Tcl_DecrRefCount(toolDataPtr->updateCmdPtr);
+        }
+        free(toolDataPtr);
+        envPtr->toolData = NULL;
+    }
 
     for (n=0; n < envPtr->numParams; n++) {
@@ -252,5 +298,6 @@
  *      <name> get ?<glob>? ?-option?
  *      <name> configure ?-option? ?value -option value ...?
- *      <name> perform ?-maxruns <num>? ?-abortvar <varName>?
+ *      <name> perform ?-tool <tool>? ?-updatecommand <varName>?
+ *      <name> using
  *
  *  The "add" command is used to add various parameter types to the
@@ -268,10 +315,13 @@
     RpOptimEnv* envPtr = (RpOptimEnv*)cdata;
     RpOptimPluginData* pluginDataPtr = (RpOptimPluginData*)envPtr->pluginData;
-
-    int n, j, nmatches;
+    RpOptimToolData* toolDataPtr = (RpOptimToolData*)envPtr->toolData;
+
+    int n, j, nvals, nmatches;
     char *option, *type, *path;
     RpOptimParam *paramPtr;
+    RpOptimParamString *strPtr;
+    RpOptimStatus status;
     RpTclOption *optSpecPtr;
-    Tcl_Obj *rval, *rrval;
+    Tcl_Obj *rval, *rrval, *toolPtr, *updateCmdPtr;
 
     if (objc < 2) {
@@ -314,4 +364,10 @@
                 return TCL_ERROR;
             }
+
+            /* list of values just changed -- patch up the count */
+            strPtr = (RpOptimParamString*)paramPtr;
+            for (nvals=0; strPtr->values[nvals]; nvals++)
+                ; /* count the values */
+            strPtr->numValues = nvals;
         }
         else {
@@ -496,13 +552,99 @@
 
     /*
-     * OPTION:  perform ?-maxruns num? ?-abortvar name?
+     * OPTION:  perform ?-tool name? ?-updatecommand name?
      */
     else if (*option == 'p' && strcmp(option,"perform") == 0) {
+        /* use this tool by default */
+        toolPtr = toolDataPtr->toolPtr;
+
+        /* no -updatecommand by default */
+        updateCmdPtr = NULL;
+
+        n = 2;
+        while (n < objc) {
+            option = Tcl_GetStringFromObj(objv[n], (int*)NULL);
+            if (n+1 >= objc) {
+                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "missing value for option \"", option, "\"",
+                    (char*)NULL);
+                return TCL_ERROR;
+            }
+            if (strcmp(option,"-tool") == 0) {
+                toolPtr = objv[n+1];
+                n += 2;
+            }
+            else if (strcmp(option,"-updatecommand") == 0) {
+                updateCmdPtr = objv[n+1];
+                n += 2;
+            }
+            else {
+                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                    "bad option \"", option, "\": should be -tool,"
+                    " -updatecommand", (char*)NULL);
+                return TCL_ERROR;
+            }
+        }
+
+        /*
+         * Must have a tool object at this point, or else we
+         * don't know what to optimize.
+         */
+        if (toolPtr == NULL) {
+            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+                "tool being optimized not specified via -tool option",
+                (char*)NULL);
+            return TCL_ERROR;
+        }
+
+        Tcl_IncrRefCount(toolPtr);
+        if (updateCmdPtr) {
+            Tcl_IncrRefCount(updateCmdPtr);
+            toolDataPtr->updateCmdPtr = updateCmdPtr;
+        }
+
+        /* call the main optimization routine here */
+        status = (*pluginDataPtr->pluginDefn->runProc)(envPtr,
+            RpOptimizerPerformInTcl);
+
+        Tcl_DecrRefCount(toolPtr);
+        if (updateCmdPtr) {
+            Tcl_DecrRefCount(updateCmdPtr);
+            toolDataPtr->updateCmdPtr = NULL;
+        }
+
+        switch (status) {
+        case RP_OPTIM_SUCCESS:
+            Tcl_SetResult(interp, "success", TCL_STATIC);
+            break;
+        case RP_OPTIM_FAILURE:
+            Tcl_SetResult(interp, "failure", TCL_STATIC);
+            break;
+        case RP_OPTIM_ABORTED:
+            Tcl_SetResult(interp, "aborted", TCL_STATIC);
+            break;
+        case RP_OPTIM_UNKNOWN:
+        default:
+            Tcl_SetResult(interp, "???", TCL_STATIC);
+            break;
+        }
+        return TCL_OK;
+    }
+
+    /*
+     * OPTION:  using
+     */
+    else if (*option == 'u' && strcmp(option,"using") == 0) {
+        if (objc > 2) {
+            Tcl_WrongNumArgs(interp, 1, objv, "using");
+            return TCL_ERROR;
+        }
+        Tcl_SetResult(interp, pluginDataPtr->pluginDefn->name, TCL_STATIC);
+        return TCL_OK;
     }
 
     else {
         Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
-            "bad option \"", option, "\": should be add, perform",
-            (char*)NULL);
+            "bad option \"", option, "\": should be add, configure, "
+            "get, perform, using", (char*)NULL);
         return TCL_ERROR;
     }
@@ -535,6 +677,6 @@
 
     /* call a specialized cleanup routine to handle the rest */
-    if (pluginDataPtr->pluginDefn->cleanupPtr) {
-        (*pluginDataPtr->pluginDefn->cleanupPtr)(pluginDataPtr->clientData);
+    if (pluginDataPtr->pluginDefn->cleanupProc) {
+        (*pluginDataPtr->pluginDefn->cleanupProc)(pluginDataPtr->clientData);
     }
     pluginDataPtr->clientData = NULL;
@@ -543,2 +685,59 @@
     free((char*)pluginDataPtr);
 }
+
+/*
+ * ------------------------------------------------------------------------
+ *  RpOptimizerPerformInTcl()
+ *
+ *  Invoked as a call-back within RpOptimPerform() to handle each
+ *  optimization run.  Launches a run of a Rappture-based tool using
+ *  the given values and computes the value for the fitness function.
+ *
+ *  Returns RP_OPTIM_SUCCESS if the run was successful, along with
+ *  the value in the fitness function in fitnessPtr.  If something
+ *  goes wrong with the run, it returns RP_OPTIM_FAILURE.
+ * ------------------------------------------------------------------------
+ */
+static RpOptimStatus
+RpOptimizerPerformInTcl(envPtr, values, numValues, fitnessPtr)
+    RpOptimEnv *envPtr;       /* optimization environment */
+    RpOptimParam *values;     /* incoming values for the simulation */
+    int numValues;            /* number of incoming values */
+    double *fitnessPtr;       /* returns: computed value of fitness func */
+{
+    printf("running...\n");
+    *fitnessPtr = 0.0;
+    return RP_OPTIM_SUCCESS;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ *  RpOptimizerUpdateInTcl()
+ *
+ *  Invoked as a call-back within RpOptimPerform() to update the
+ *  application and look for an "abort" signal.  Evaluates a bit of
+ *  optional code stored in the optimization environment.  Returns 0
+ *  if everything is okay, and non-zero if the user wants to abort.
+ * ------------------------------------------------------------------------
+ */
+static int
+RpOptimizerUpdateInTcl(envPtr)
+    RpOptimEnv *envPtr;       /* optimization environment */
+{
+    RpOptimToolData *toolDataPtr = (RpOptimToolData*)envPtr->toolData;
+    int status;
+
+    if (toolDataPtr->updateCmdPtr) {
+        status = Tcl_GlobalEvalObj(toolDataPtr->interp,
+            toolDataPtr->updateCmdPtr);
+
+        if (status == TCL_ERROR) {
+            Tcl_BackgroundError(toolDataPtr->interp);
+            return 0;
+        }
+        if (status == TCL_BREAK || status == TCL_RETURN) {
+            return 1;  /* abort! */
+        }
+    }
+    return 0;  /* keep going... */
+}
Index: /trunk/optimizer/src/rp_tcloptions.c
===================================================================
--- /trunk/optimizer/src/rp_tcloptions.c	(revision 897)
+++ /trunk/optimizer/src/rp_tcloptions.c	(revision 898)
@@ -23,4 +23,10 @@
  *  Built-in types:
  */
+RpCustomTclOptionParse RpOption_ParseBoolean;
+RpCustomTclOptionGet RpOption_GetBoolean;
+RpTclOptionType RpOption_Boolean = {
+    "boolean", RpOption_ParseBoolean, RpOption_GetBoolean, NULL
+};
+
 RpCustomTclOptionParse RpOption_ParseInt;
 RpCustomTclOptionGet RpOption_GetInt;
@@ -175,4 +181,34 @@
 /*
  * ======================================================================
+ *  BOOLEAN
+ * ======================================================================
+ */
+int
+RpOption_ParseBoolean(interp, valObj, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    Tcl_Obj *valObj;     /* set option to this new value */
+    ClientData cdata;    /* save in this data structure */
+    int offset;          /* save at this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    if (Tcl_GetBooleanFromObj(interp, valObj, ptr) != TCL_OK) {
+        return TCL_ERROR;
+    }
+    return TCL_OK;
+}
+
+int
+RpOption_GetBoolean(interp, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    ClientData cdata;    /* get from this data structure */
+    int offset;          /* get from this offset in cdata */
+{
+    int *ptr = (int*)(cdata+offset);
+    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(*ptr));
+    return TCL_OK;
+}
+
+/*
+ * ======================================================================
  *  INTEGER
  * ======================================================================
@@ -335,2 +371,43 @@
     *(char***)(cdata+offset) = NULL;
 }
+
+/*
+ * ======================================================================
+ *  CHOICES
+ * ======================================================================
+ */
+int
+RpOption_ParseChoices(interp, valObj, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    Tcl_Obj *valObj;     /* set option to this new value */
+    ClientData cdata;    /* save in this data structure */
+    int offset;          /* save at this offset in cdata */
+{
+    char **ptr = (char**)(cdata+offset);
+    char *value = Tcl_GetStringFromObj(valObj, (int*)NULL);
+    *ptr = strdup(value);
+    return TCL_OK;
+}
+
+int
+RpOption_GetChoices(interp, cdata, offset)
+    Tcl_Interp *interp;  /* interpreter handling this request */
+    ClientData cdata;    /* get from this data structure */
+    int offset;          /* get from this offset in cdata */
+{
+    char *ptr = (char*)(cdata+offset);
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(ptr,-1));
+    return TCL_OK;
+}
+
+void
+RpOption_CleanupChoices(cdata, offset)
+    ClientData cdata;    /* cleanup in this data structure */
+    int offset;          /* cleanup at this offset in cdata */
+{
+    char **ptr = (char**)(cdata+offset);
+    if (*ptr != NULL) {
+        free((char*)(*ptr));
+        *ptr = NULL;
+    }
+}
Index: /trunk/optimizer/src/rp_tcloptions.h
===================================================================
--- /trunk/optimizer/src/rp_tcloptions.h	(revision 897)
+++ /trunk/optimizer/src/rp_tcloptions.h	(revision 898)
@@ -49,5 +49,4 @@
     char *optname;             /* name of option: -switch */
     RpTclOptionType *typePtr;  /* type of this switch */
-    ClientData extraInfo;      /* extra data needed for switch type */
     int offset;                /* location of data within struct */
 } RpTclOption;
@@ -56,4 +55,7 @@
  *  Built-in types defined in rp_tcloptions.c
  */
+extern RpTclOptionType RpOption_Boolean;
+#define RP_OPTION_BOOLEAN &RpOption_Boolean
+
 extern RpTclOptionType RpOption_Int;
 #define RP_OPTION_INT &RpOption_Int
@@ -67,4 +69,7 @@
 extern RpTclOptionType RpOption_List;
 #define RP_OPTION_LIST &RpOption_List
+
+extern RpTclOptionType RpOption_Choices;
+#define RP_OPTION_CHOICES &RpOption_Choices
 
 /*
Index: /trunk/optimizer/tests/aaa.test
===================================================================
--- /trunk/optimizer/tests/aaa.test	(revision 897)
+++ /trunk/optimizer/tests/aaa.test	(revision 898)
@@ -43,5 +43,5 @@
 test aaa-1.4 {optimizer creation takes certain args} {
   list [catch {Rappture::optimizer -foo} result] $result
-} {1 {bad option "-foo": should be -using}}
+} {1 {bad option "-foo": should be -tool, -using}}
 
 test aaa-1.5 {optimizer creation: -using requires a value} {
@@ -55,5 +55,5 @@
 test aaa-1.7 {optimizer creation: extra args are processed} {
   list [catch {Rappture::optimizer -using pgapack -foo bar} result] $result
-} {1 {bad option "-foo": should be -using}}
+} {1 {bad option "-foo": should be -tool, -using}}
 
 test aaa-1.8 {optimizer can be destroyed without dumping core} {
Index: /trunk/optimizer/tests/pgapack.test
===================================================================
--- /trunk/optimizer/tests/pgapack.test	(revision 898)
+++ /trunk/optimizer/tests/pgapack.test	(revision 898)
@@ -0,0 +1,70 @@
+# ----------------------------------------------------------------------
+#  TESTS FOR:  pgapack module in Rappture::optimizer
+#
+#  This file contains a collection of tests for Tcl commands driving
+#  the RapptureOptimizer package.  This part covers the "pgapack"
+#  plug-in module.
+#
+# ======================================================================
+#  AUTHOR:  Michael McLennan, Purdue University
+#  Copyright (c) 2008  Purdue Research Foundation
+#
+#  See the file "license.terms" for information on usage and
+#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# ======================================================================
+#
+# Load the tcltest package...
+if {[lsearch [namespace children] ::tcltest] < 0} {
+    package require tcltest 2
+    namespace import -force ::tcltest::*
+}
+
+test aaa-0.1 {RapptureOptimizer package can be loaded} {
+    set status [catch {package require RapptureOptimizer} result]
+    if {$status != 0} {
+        # must not be installed yet -- use build version
+        lappend auto_path ../src
+        set status [catch {package require RapptureOptimizer} result]
+    }
+    list $status $result
+} {0 1.0}
+
+# ----------------------------------------------------------------------
+test pgapack-1.1 {default plugin is pgapack} {
+  Rappture::optimizer opt
+  opt using
+} {pgapack}
+
+test pgapack-1.2 {plugin has configuration options} {
+  opt configure
+} {-maxruns 10000 -operation minimize -poprepl best -popsize 200}
+
+test pgapack-1.3 {plugin configuration option values can be queried} {
+  opt configure -popsize
+} {200}
+
+test pgapack-1.4 {plugin configuration options can be modified} {
+  opt configure -popsize 1000 -operation maximize
+  opt configure
+} {-maxruns 10000 -operation maximize -poprepl best -popsize 1000}
+
+test pgapack-1.5 {options/values must be in pairs when changing them} {
+  list [catch {opt configure -operation minimize -poprepl} result] $result
+} {1 {missing value for option "-poprepl"}}
+
+test pgapack-1.6 {only certain options are recognized} {
+  list [catch {opt configure -foo} result] $result
+} {1 {bad option "-foo": should be -maxruns, -operation, -poprepl, -popsize}}
+
+test pgapack-1.7 {custom poprepl option works properly} {
+  list [catch {opt configure -poprepl random-repl} result] $result \
+       [opt configure -poprepl]
+} {0 {} random-repl}
+
+test pgapack-1.8 {custom poprepl option catches errors} {
+  list [catch {opt configure -poprepl foo} result] $result
+} {1 {bad value "foo": should be best, random-norepl, or random-repl}}
+
+# cleanup
+::tcltest::cleanupTests
+return
