Version 3 of Constructing a Bwise Graph from a Maxima Formula

Updated 2010-02-12 03:27:29 by theover

Maxima is a Free and Open Source mathematical language running on a LISP interpreter for which there are Tcl bindings and a Tk interface, I've a few pages on how to use it with tcl, and in this case I'd like to make maxima formulas, for instance for signal processing, into a graph by using tcl and maxima combined.

An example formula is an addition of variables and numbers, like:

  output = in1 + (3 + in2)

for no particular reason, in this example, which could be seen as a single bwise block with three inputs and one output, the main operator is addition. Of course this is often the case, but a random mathematical function or formula (lets assume with one output or result or result variable) often as an addition as top level operator.

What I'd like to do, and automatically too is to make blocks for each level of the formula evaluation, in the above case in1 +() and 3+in2.

In Tcl I did something of the kind once (constructing a bwise graph from a formula), but I didn't like it enough, so I don't go into that, but I want to do some work on getting a random maxima formula correctly decomposed in blocks. I can already do the converse at "string=formula" level with substitutions.

The idea is to use a maxima formula deconstruction function, repeatedly driven from tcl and than have bwise automatically create and place the blocks.

First, to seperate a maxima stated formula (any formula in principle) into components:

 proc domaximapart { {m} } {
    set t "display2d:false;partswitch:true;\n$m;"
    # return [string range [exec maxima << $t | tail -2  ] 6 end-7]
    return [string range [exec maxima -q << $t ] 43 end-7]
    #return [exec maxima --real-quiet << $t ]
 } 

 proc maxcompo1 { {a} } {

   set o [domaximapart part($a,0)]
   if [string equal \{\" [string range $o 0 1 ]] { set o [string range $o 2 end] }
   if [string equal \"\} [string range $o end-1 end]] { set o [string range $o 0 end-2] }

   set i 1
   while {![string equal [set k [domaximapart part($a,$i)]]  "end"]  & $i<40} {
 #     puts $i,$k
 #     flush stdout
 #     update
      lappend o $k
      incr i
   }
   if {$i>= 40} {return error}
   return $o
 } 

The above formula gives the result:

 % maxcompo1 {in1 + (3 + in2)}
 + in2 in1 3

An addition operator (first argument) with 3 arguments. Another example, where maxima will do computations and simplfications first (like it normally always does), before doing the argument seperation:

 % foreach i [maxcompo1 {diff(sin(x)^2-1^2,x)}] {puts $i}
 *
 2
 cos(x)
 sin(x)

a multiplication of three components.

Now we can repeatedly call this function, apply it recursively or looped on its output list elements, make nicenames for the standard operators (probably Tk doesn't like labels like + and /) create blocks for each operator with the right number of input connectors, and connect them in the right structure, according to the basic functional decomposition.

 proc newop { {op {+}} {nin {2}} {name {}} {in {in}} {out {out}} {width {40}} {height {}} {tags {}} {x {10}} {y {10}} } {
   if {$name == {}} {
      switch -- $op + {set name add} - {set name sub} \/ {set name div} * {set name mul} default {set name $op}
      uplevel #0 {if {[info exists proccount] == "0"} {set proccount 0} ;}
      global proccount
      incr proccount
      set name $name$proccount
   }

   set inp "\{"
   set f  "\{set $name.out \""
   if {$nin == 1} {
    append inp " in"
    append f  "\($op\(\$\{$name.in\})"
   } {
    append inp " in0"
    append f  " ( (\$\{$name.in0\})"
   }
   for {set i 1} {$i < $nin} {incr i} {
      append inp " in$i"
      append f  " $op (\$\{$name.in$i\})"
   }
   append f  ")\"\}"
   append inp " \} "
   puts   "$f $name $inp $out $width {} {} $x $y"

   eval "newproc $f $name $inp $out $width {} {} $x $y"
 }