#!/usr/local/bin/wish -f # # /*-----------------------------------------------------------------------*\ # | | # | Robotics 95 -- Final Course Project | # | | # | By : Omri Weisman & Ziv Pollack | # | | # | Perceptron -- A Classic Neural Network Implementation | # | | # \*-----------------------------------------------------------------------*/ # # File name : prcpt # # The perceptron performs classification by dividing the input space into two # regions with a line. # # When the window opens, you can create positive points on the board by clicking # the left mouse button, and negative points by clicking the right mouse button. # When you're finished placing points, you can click on the "Start" button to # allow the network to try and learn your input points, generalize its knowledge, # and show you the result by drawing the line on the board. The line represents the # border which seperates the plane into two regions - a region where the NN's # output will be True and a region where the NN's output will be False. # # This file is the Tk interface of the Perceptron program. It uses a helper # program written in C to perform the actual NN learning, and acts as its GUI. # # Constants # set LIMIT 100 ;# Limit of points allowed # Main Window # wm title . "Perceptron" wm minsize . 560 550 #option add *activeBackground green # Headers # frame .header1 -borderwidth 5; pack .header1 label .header1.l -text "The Perceptron - A Neural Network Implementation" ; pack .header1.l frame .header2 -borderwidth 5 ; pack .header2 label .header2.l -text "By Omri Weisman and Ziv Pollack" ; pack .header2.l # Buttons # frame .buttons -borderwidth 15 ; pack .buttons -side bottom -fill x button .buttons.quit -text " Quit " -command exit button .buttons.start -text " Start " -command Start button .buttons.clear -text " Clear " -command Clear entry .buttons.mousepos -width 7 -bd 2 -relief raised -textvariable mousepos entry .buttons.statusbar -width 30 -bd 2 -relief raised -textvariable status pack .buttons.start .buttons.clear .buttons.statusbar .buttons.mousepos -side left pack .buttons.quit -side right # The Clipboard # This is a frame that holds the board and the rulers # frame .clip ; pack .clip # The Board # This is the board upon which the points are drawn # canvas .clip.board -width 360 -height 360 -bd 5 -relief raised -bg white pack .clip.board -anchor e bind .clip.board {set mousepos "%x %y"} ;# Show mouse position when moved bind .clip.board {Button1 %x %y} ;# Create positive point bind .clip.board {Button3 %x %y} ;# Create negative point bind .clip.board {set mousepos ""} # Vertical Ruler # Just a graphic feature # canvas .clip.c1 -width 2.5c -height 11.5c pack .clip.c1 -side left -before .clip.board .clip.c1 create line 1.5c 0c 1c 0c 1c 10c 1.5c 10c for {set i 0} {$i < 10} {incr i} { set x [expr $i+0] .clip.c1 create line 1c ${x}c 1.4c ${x}c .clip.c1 create line 1c $x.25c 1.2c $x.25c .clip.c1 create line 1c $x.5c 1.3c $x.5c .clip.c1 create line 1c $x.75c 1.2c $x.75c .clip.c1 create text 1.4c $x.4c -text [expr 35*$i] -anchor sw } # vertical frame on right side, # to balance with the ruler on the left # frame .clip.c3 -width 2.5c -height 11.5c pack .clip.c3 -side right -before .clip.board # Horizental Ruler # Another graphic feature # canvas .clip.c2 -width 10.1c -height 1.5c pack .clip.c2 -side bottom -after .clip.board .clip.c2 create line 0c 0.5c 0c 1c 10c 1c 10c 0.5c for {set i 0} {$i < 10} {incr i} { set x [expr $i+0] .clip.c2 create line ${x}c 1c ${x}c 0.6c .clip.c2 create line $x.25c 1c $x.25c 0.8c .clip.c2 create line $x.5c 1c $x.5c 0.7c .clip.c2 create line $x.75c 1c $x.75c 0.8c .clip.c2 create text $x.01c .5c -text [expr 35*$i] -anchor sw } # Global Variables # set list1 "" ;# List of points for which the result should be True set list2 "" ;# List of points for which the result should be False set mark_list "" ;# List of graphic marks that should be deleted when "Clear" is requested set seperator "" ;# The seperator line that is drawn when "Start" is pressed. set counter 0 ;# Counts how many points are there # Procedure Start # This procedure starts the calculation. It saves the points to a temporary # file, calls upon the helper program to perform the actual learning and # receives its output from the standard output. If the result is 4 numbers, # they are interpreted as 2 x-y pairs and a line is drawn, otherwise it is # assumed that some problem occured. # proc Start {} { global list1 list2 seperator say "Starting..." set fileID [open /tmp/perceptron-input w 0644] ;# Write data into file puts $fileID [expr [llength $list1]/2] foreach item $list1 { puts $fileID $item } puts $fileID [expr [llength $list2]/2] foreach item $list2 { puts $fileID $item } close $fileID foreach item $seperator { .clip.board delete $item } ;# Delete previous seperator line catch {exec -keepnewline perceptron.out} result ;# Execute the helper program if { [llength $result] == 4 } { say "Perceptron learning complete" ;# If succesful, draw line set seperator [.clip.board create line [lindex $result 0] [lindex $result 1]\ [lindex $result 2] [lindex $result 3]] } else { say "The Perceptron failed to learn" } } # Procedure Button1 # This procedure creates a new positive point at the location x,y when the # left mouse button is clicked. It also draws a '+' there. # proc Button1 {x y} { global mark_list list1 counter LIMIT if { $counter >= $LIMIT } { say "No more points allowed" } else { set line1 [.clip.board create line [expr $x-3] $y [expr $x+4] $y] set line2 [.clip.board create line $x [expr $y-3] $x [expr $y+4]] lappend mark_list $line1 $line2 lappend list1 $x $y set counter [expr $counter + 1] say "Created Positive input at $x:$y" } } # Procedure Button3 # This procedure creates a new negative point at the location x,y when the # right mouse button is clicked. It also draws a '-' there. # proc Button3 {x y} { global mark_list list2 counter LIMIT if { $counter >= $LIMIT } { say "No more points allowed" } else { set line1 [.clip.board create line [expr $x-3] $y [expr $x+4] $y] lappend mark_list $line1 lappend list2 $x $y set counter [expr $counter + 1] say "Created Negative input at $x:$y" } } # Procedure Clear # Clear all marks from the board and reset variables # proc Clear {} { global list1 list2 mark_list seperator counter foreach item [concat $mark_list $seperator] { .clip.board delete $item } set list1 "" set list2 "" set mark_list "" set counter 0 say "" } # Procedure Say # print a message on the status bar. # proc say {message} { global status set status $message }