Version 0 of Mathematical workbench

Updated 2002-07-02 09:08:14

Arjen Markus At the third European Tcl/Tk meeting I presented a "mathematical workbench". This page shows a small example of this work. The idea is described in the abstract:

   A handheld calculator is a great way to do all kinds of ad hoc
   calculations. You do not write a C or Fortran program with hard-coded
   numbers to add them for balancing your books. In a similar way doing 
   mathematics - for instance solve some geometrical problem - requires
   a handheld calculator suitable for that type of calculations. 

   The essential ingredients are an interactive program that interprets
   dedicated commands, and a few conventions to make its use more or
   less uniform. 

   This paper describes the application of Tkcon and such a set of
   conventions to provide the interface. It illustrates the concepts
   with three different mathematical tools: complex numbers, ordinary
   differential equations and (statistical) optimisation.

The script below contains a few commands that illustrate the idea compactly:

  • You can define a function of x via func $expression
  • You can define the derivative of that function via deriv funcname
  • You can get the value of a function for a specific value

If you run the script from within Tkcon or a similar shell, you can experiment with it.

(Note: the full workbench contains much more convenient commands)


# functions.tcl -- # # Package for analysing real functions # (sample Workbench module) # # Notes: # This package provides basic analysis functionality for real # functions of one variable. # # Version information: # version 0.1: initial implementation, july 2002

package provide Functions 0.1

namespace eval ::Workbench {

   variable nextID 0

# uniqueID -- # Create a unique ID (private) # # Arguments: # expression Expression using "x" as independent variable # evaluating to the function value # # Result: # Name of a new command implementing the function # # Side effect: # Create a new command that takes one argument, x, and # returns the function value # proc uniqueID {typename} {

   variable nextID

   incr nextID

   return "${typename}##$nextID"

} } ;# End of namespace

namespace eval ::Functions {

   namespace export func deriv

# func -- # Create a new function # # Arguments: # expression Expression using "x" as independent variable # evaluating to the function value # # Result: # Name of a new command implementing the function # # Side effect: # Create a new command that takes one argument, x, and # returns the function value # proc func {expression} {

   set name [::Workbench::uniqueID "X-FUNCTION"]
   interp alias {} $name {} [namespace current]::xfunc_impl $expression
   return $name

}

# xfunc_impl -- # Implementation of an "x function" # # Arguments: # expression Expression using "x" (hidden via interp alias) # x Independent variable # # Result: # Function value # proc xfunc_impl {expression x} {

   expr $expression

}

# deriv -- # Create a new function that evaluates to the derivative of the given # function # # Arguments: # funcname Name (!) of the function # step Step for the numerical derivation # # Result: # Name of a new command implementing the function's derivative # # Side effect: # Create a new command that takes one argument, x, and # returns the original function's derivative # proc deriv {funcname {step 0.01} } {

   upvar $funcname fname
   set name [::Workbench::uniqueID "X-DERIVATIVE"]
   set expression [lindex [interp alias {} $fname] 1]
   interp alias {} $name {} [namespace current]::xderiv_impl $expression $step
   return $name

}

# xderiv_impl -- # Implementation of the derivative of an "x function" # # Arguments: # expression Expression using "x" (hidden via interp alias) # step Step size for numerical derivation # xv Independent variable # Result: # Value of derivative # proc xderiv_impl {expression step xv} {

   set x   [expr {$xv-$step}]
   set fx1 [expr $expression]
   set x   [expr {$xv+$step}]
   set fx2 [expr $expression]
   expr {($fx2-$fx1)/(2.0*$step)}

}

} ;# End of namespace

# # Import the functions procedures # namespace import ::Functions::*

# # Simple demo # if { file tail [info script] == [file tail $::argv0 } {

   puts "Simply a parabola: y = x^2"
   set f [func {$x*$x}]
   set df [deriv f]
   set x 0.0
   while { $x < 10.1 } {
      puts "[$f $x] [$df $x]"
      set x [expr {$x+1.0}]
   }

   puts "A more complex function"
   set f [func {sin($x)*$x}]
   set df [deriv f]
   set x 0.0
   while { $x < 10.1 } {
      puts "[$f $x] [$df $x]"
      set x [expr {$x+0.1}]
   }

}


Category Math