summaryrefslogtreecommitdiff
path: root/Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl')
-rw-r--r--Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl201
1 files changed, 0 insertions, 201 deletions
diff --git a/Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl b/Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl
deleted file mode 100644
index 2356cd1d..00000000
--- a/Windows/spice/examples/tclspice/tcl-testbench3/differentiate.tcl
+++ /dev/null
@@ -1,201 +0,0 @@
-# differentiate.tcl --
-# Numerical differentiation
-#
-
-namespace eval ::math::calculus {
-}
-namespace eval ::math::optimize {
-}
-
-# deriv --
-# Return the derivative of a function at a given point
-# Arguments:
-# func Name of a procedure implementing the function
-# point Coordinates of the point
-# scale (Optional) the scale of the coordinates
-# Result:
-# List representing the gradient vector at the given point
-# Note:
-# The scale is necessary to create a proper step in the
-# coordinates. The derivative is estimated using central
-# differences.
-# The function may have an arbitrary number of arguments,
-# for each the derivative is determined - this results
-# in a list of derivatives rather than a single value.
-# (No provision is made for the function to be a
-# vector function! So, second derivatives are not
-# possible)
-#
-proc ::math::calculus::deriv {func point {scale {}} } {
-
- set epsilon 1.0e-12
- set eps2 [expr {sqrt($epsilon)}]
-
- #
- # Determine a scale
- #
- foreach c $point {
- if { $scale == {} } {
- set scale [expr {abs($c)}]
- } else {
- if { $scale < abs($c) } {
- set scale [expr {abs($c)}]
- }
- }
- }
- if { $scale == 0.0 } {
- set scale 1.0
- }
-
- #
- # Check the number of coordinates
- #
- if { [llength $point] == 1 } {
- set v1 [$func [expr {$point+$eps2*$scale}]]
- set v2 [$func [expr {$point-$eps2*$scale}]]
- return [expr {($v1-$v2)/(2.0*$eps2*$scale)}]
- } else {
- set result {}
- set idx 0
- foreach c $point {
- set c1 [expr {$c+$eps2*$scale}]
- set c2 [expr {$c-$eps2*$scale}]
-
- set v1 [eval $func [lreplace $point $idx $idx $c1]]
- set v2 [eval $func [lreplace $point $idx $idx $c2]]
-
- lappend result [expr {($v1-$v2)/(2.0*$eps2*$scale)}]
- incr idx
- }
- return $result
- }
-}
-
-# auxiliary functions --
-#
-proc ::math::optimize::unitVector {vector} {
- set length 0.0
- foreach c $vector {
- set length [expr {$length+$c*$c}]
- }
- scaleVector $vector [expr {1.0/sqrt($length)}]
-}
-proc ::math::optimize::scaleVector {vector scale} {
- set result {}
- foreach c $vector {
- lappend result [expr {$c*$scale}]
- }
- return $result
-}
-proc ::math::optimize::addVector {vector1 vector2} {
- set result {}
- foreach c1 $vector1 c2 $vector2 {
- lappend result [expr {$c1+$c2}]
- }
- return $result
-}
-
-# minimumSteepestDescent --
-# Find the minimum of a function via steepest descent
-# (unconstrained!)
-# Arguments:
-# func Name of a procedure implementing the function
-# point Coordinates of the starting point
-# eps (Optional) measure for the accuracy
-# maxsteps (Optional) maximum number of steps
-# Result:
-# Coordinates of a point near the minimum
-#
-proc ::math::optimize::minimumSteepestDescent {func point {eps 1.0e-5} {maxsteps 100} } {
-
- set factor 100
- set nosteps 0
- if { [llength $point] == 1 } {
- while { $nosteps < $maxsteps } {
- set fvalue [$func $point]
- set gradient [::math::calculus::deriv $func $point]
- if { $gradient < 0.0 } {
- set gradient -1.0
- } else {
- set gradient 1.0
- }
- set found 0
- set substeps 0
- while { $found == 0 && $substeps < 3 } {
- set newpoint [expr {$point-$factor*$gradient}]
- set newfval [$func $newpoint]
-
- #puts "factor: $factor - point: $point"
- #
- # Check that the new point has a lower value for the
- # function. Can we increase the factor?
- #
- #
- if { $newfval < $fvalue } {
- set point $newpoint
-
-#
-# This failed with sin(x), x0 = 1.0
-# set newpoint2 [expr {$newpoint-$factor*$gradient}]
-# set newfval2 [$func $newpoint2]
-# if { $newfval2 < $newfval } {
-# set factor [expr {2.0*$factor}]
-# set point $newpoint2
-# }
- set found 1
- } else {
- set factor [expr {$factor/2.0}]
- }
-
- incr substeps
- }
-
- #
- # Have we reached convergence?
- #
- if { abs($factor*$gradient) < $eps } {
- break
- }
- incr nosteps
- }
- } else {
- while { $nosteps < $maxsteps } {
- set fvalue [eval $func $point]
- set gradient [::math::calculus::deriv $func $point]
- set gradient [unitVector $gradient]
-
- set found 0
- set substeps 0
- while { $found == 0 && $nosteps < $maxsteps } {
- set newpoint [addVector $point [scaleVector $gradient -$factor]]
- set newfval [eval $func $newpoint]
-
- #puts "factor: $factor - point: $point"
- #
- # Check that the new point has a lower value for the
- # function. Can we increase the factor?
- #
- #
- if { $newfval < $fvalue } {
- set point $newpoint
- set found 1
- } else {
- set factor [expr {$factor/2.0}]
- }
-
- incr nosteps
- }
-
- #
- # Have we reached convergence?
- #
- if { abs($factor) < $eps } {
- break
- }
- incr nosteps
- }
- }
-
- return $point
-}
-