OSDN Git Service

Added a sample implementation of Perceptron neural network by dennco engine.
authortkawata <tkawata@users.sourceforge.jp>
Sat, 26 May 2012 13:57:07 +0000 (22:57 +0900)
committertkawata <tkawata@users.sourceforge.jp>
Sat, 26 May 2012 13:57:07 +0000 (22:57 +0900)
Samples/Samples/Sample5_SimplePerceptron.ng/Container/2/2_a.xhtml [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/1/1_a.xhtml [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/1/dstyle.css [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/2/2_a.xhtml [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/2/dstyle.css [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/3/3_a.xhtml [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/Container/3/dstyle.css [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/property.xml [new file with mode: 0644]
Samples/Samples/Sample5_SimplePerceptron/ui/index.html [new file with mode: 0644]

diff --git a/Samples/Samples/Sample5_SimplePerceptron.ng/Container/2/2_a.xhtml b/Samples/Samples/Sample5_SimplePerceptron.ng/Container/2/2_a.xhtml
new file mode 100644 (file)
index 0000000..d511b3a
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head><title>Dennco - test1</title>
+<link rel="stylesheet" type="text/css" href="dstyle.css" />  
+</head>
+
+<body>
+
+<a define="cell"  name="cell1">
+<a parameter="cellcode"  href="#PerceptronCellCode"> </a>
+<a parameter="connection" href="../3/3_a.xhtml#cell1output" receptor="output"></a>
+</a>
+
+<a define="cellcode"  name="PerceptronCellCode" type="B">
+<pre parameter="script"> 
+<![CDATA[
+
+var threshold = 0.5;
+
+var wights = new Array();
+var correctedWights = new Array();
+var u0wight = 0;
+var correctedU0wight = 0;
+var units = new Array();
+var learned = false;
+
+function doInit()
+{
+       for (var r in this.cell.receptors)
+       {
+               if (r.match(/^u[0-9][0-9]$/)
+               {
+                       var index = Number(r.substring(1));
+                       this.units[index] = r;
+                       this.wights[index] = 0;
+                       this.correctedWights[index] = 0;
+               }
+       }
+}
+
+function doTick(time)   
+{
+       //process for output
+       var sum = 1 * u0wight;  
+       for (var index in units)
+       {
+               sum += this.cell.receptors[units[index]] * wights[index];
+       }
+       var output = sum < this.threshold ? 0 : 1;
+       this.cell.axonValue  = output;
+       
+       //process for learn 
+       var learn = this.cell.receptors.learn;
+       var exp   = this.cell.receptors.expected;
+       var rate  = this.cell.receptors.learningRate;   
+
+       if (learn == 1)
+       {
+               if (!this.learned)
+               {
+                       if (exp != output)
+                       {
+                               var correctionRate = rate * (exp - output);
+                               correctedU0wight = u0wight + u0wight * correctionRate;
+                               for (var index in units)
+                               {
+                                       correctedWights[index] = wights[index] + (wights[index] * correctionRate);
+                               }
+                       }
+                       this.learned = true;
+               }
+       }
+       else
+       {
+               if (this.learned)
+               {
+               
+               
+               }
+               this.learned = false;
+       }
+}
+]]>
+</pre>
+</a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/1/1_a.xhtml b/Samples/Samples/Sample5_SimplePerceptron/Container/1/1_a.xhtml
new file mode 100644 (file)
index 0000000..26e1e09
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head><title>Input layer for perceptron cell</title>
+<link rel="stylesheet" type="text/css" href="dstyle.css" />  
+</head>
+<body>
+
+<a define="cell"  name="cell1v1input">
+<a parameter="cellcode"  type="I"> </a>
+<a parameter="connection" href="../2/2_a.xhtml#cell1" receptor="v01"></a>
+</a>
+
+<a define="cell"  name="cell1v2input">
+<a parameter="cellcode"  type="I"> </a>
+<a parameter="connection" href="../2/2_a.xhtml#cell1" receptor="v02"></a>
+</a>
+
+<a define="cell"  name="cell1learn" >
+<a parameter="cellcode"  type="I"> </a>
+<a parameter="connection" href="../2/2_a.xhtml#cell1" receptor="learn"></a>
+</a>
+
+<a define="cell"  name="cell1desired" >
+<a parameter="cellcode"  type="I"> </a>
+<a parameter="connection" href="../2/2_a.xhtml#cell1" receptor="desired"></a>
+</a>
+
+<a define="cell"  name="cell1rate" >
+<a parameter="cellcode"  type="I"> </a>
+<a parameter="connection" href="../2/2_a.xhtml#cell1" receptor="learningRate"></a>
+</a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/1/dstyle.css b/Samples/Samples/Sample5_SimplePerceptron/Container/1/dstyle.css
new file mode 100644 (file)
index 0000000..5a10ecb
--- /dev/null
@@ -0,0 +1,51 @@
+
+a[define] {
+       border-top:    1px solid gray;
+       text-indent:   1em;
+       display:       block;
+       margin-top:    32px;
+       margin-bottom: 8px;
+} 
+
+a[define="cellcode"]:before {
+       content:       "Definition of CellCode : " attr(name)      "  (type:" attr(type) ")" ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+
+
+a[define="cell"]:before {
+       content:       "Definition of Cell : " attr(name)  ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+         
+a[parameter="cellcode"]:before {
+       content:       "CellCode : " attr(href)  attr(type); 
+       display:       inline;
+}
+
+a[parameter="cellcode"] {
+       text-indent:   1em;
+       display:       block;
+}
+
+a[parameter="connection"]:before {
+       content:       "-> " attr(href)  "(" attr(receptor) ")"; 
+       display:       inline;
+}
+
+a[parameter="connection"] {
+       text-indent:   2em;
+       display:       block;
+}
+
+[parameter="script"] { 
+        border:             1px solid gray;
+        background-color:   #f0f0cc;
+        margin-left:        2em;
+}
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/2/2_a.xhtml b/Samples/Samples/Sample5_SimplePerceptron/Container/2/2_a.xhtml
new file mode 100644 (file)
index 0000000..4c6d5d2
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head><title>Perceptron</title>
+<link rel="stylesheet" type="text/css" href="dstyle.css" />  
+</head>
+
+<body>
+
+<a define="cell"  name="cell1">
+<a parameter="cellcode"  href="#PerceptronCellCode"> </a>
+<a parameter="connection" href="../3/3_a.xhtml#cell1output" receptor="output"></a>
+<pre parameter="script"> 
+<![CDATA[
+       this.inputReceptors = ["v01", "v02"];
+       this.wights         = [0,0];
+]]>
+</pre>
+</a>
+
+<a define="cellcode"  name="PerceptronCellCode" type="B">
+<pre parameter="script"> 
+<![CDATA[
+
+var inputReceptors;   // This should be initialized by custom script in cell
+var wights;           // This should be initialized by custom script in cell
+
+var threshold        = 0.5;
+var correctedWights  = new Array();
+var v0wight          = 0;
+var v0CorrectedWight = 0;
+var learned          = false;
+var corrected        = false;
+
+function doInit()
+{
+       //setup
+       for (var i = 0; i < this.wights.length; i++)
+               this.correctedWights[i] = this.wights[i];
+}
+
+function doTick(time)   
+{
+       //process for output
+       var sum = 1 * this.v0wight;     
+       for (var i = 0; i < this.inputReceptors.length; i++) {
+               sum += this.cell.receptors[this.inputReceptors[i]] * this.wights[i];
+       }
+       var output = sum <= this.threshold ? 0 : 1;
+       this.cell.axonValue  = output;
+       
+       //process for learning
+       var learn   = this.cell.receptors.learn;
+       var desired = this.cell.receptors.desired;
+       var rate    = this.cell.receptors.learningRate; 
+
+       if (learn == 1)
+       {
+               if (!this.learned) {
+                       print("v1:" + this.cell.receptors.v01.toFixed(2) + "  v2:" + this.cell.receptors.v02.toFixed(2) + "  output:" + output.toFixed(2) + "  desired:" + desired.toFixed(2));
+                       if (desired != output) {
+                               var correction = rate * (desired - output);
+                               this.v0correctedWight = this.v0wight + correction;
+                               for (var i = 0; i < this.inputReceptors.length ; i++) {
+                                       this.correctedWights[i] = this.wights[i] + correction * this.cell.receptors[this.inputReceptors[i]];
+                               }
+                               this.corrected = true;
+                       }
+                       this.learned = true;
+               }
+       }
+       else
+       {
+               if (this.learned && this.corrected) {
+                       print("Corrected:");
+                       print("    v00: wight " + this.v0wight.toFixed(3) + " -> " + this.v0correctedWight.toFixed(3));
+                       this.v0wight = this.v0correctedWight;
+                       for (var i = 0; i < this.inputReceptors.length; i++) {
+                               print("    " + this.inputReceptors[i] + ": wight " + this.wights[i].toFixed(3) + " -> " + this.correctedWights[i].toFixed(3));
+                               this.wights[i] = this.correctedWights[i];
+                       }
+               }
+               this.corrected = false;
+               this.learned = false;
+       }
+}
+]]>
+</pre>
+</a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/2/dstyle.css b/Samples/Samples/Sample5_SimplePerceptron/Container/2/dstyle.css
new file mode 100644 (file)
index 0000000..5a10ecb
--- /dev/null
@@ -0,0 +1,51 @@
+
+a[define] {
+       border-top:    1px solid gray;
+       text-indent:   1em;
+       display:       block;
+       margin-top:    32px;
+       margin-bottom: 8px;
+} 
+
+a[define="cellcode"]:before {
+       content:       "Definition of CellCode : " attr(name)      "  (type:" attr(type) ")" ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+
+
+a[define="cell"]:before {
+       content:       "Definition of Cell : " attr(name)  ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+         
+a[parameter="cellcode"]:before {
+       content:       "CellCode : " attr(href)  attr(type); 
+       display:       inline;
+}
+
+a[parameter="cellcode"] {
+       text-indent:   1em;
+       display:       block;
+}
+
+a[parameter="connection"]:before {
+       content:       "-> " attr(href)  "(" attr(receptor) ")"; 
+       display:       inline;
+}
+
+a[parameter="connection"] {
+       text-indent:   2em;
+       display:       block;
+}
+
+[parameter="script"] { 
+        border:             1px solid gray;
+        background-color:   #f0f0cc;
+        margin-left:        2em;
+}
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/3/3_a.xhtml b/Samples/Samples/Sample5_SimplePerceptron/Container/3/3_a.xhtml
new file mode 100644 (file)
index 0000000..359a568
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head><title>Output layer for perceptron cell</title>
+<link rel="stylesheet" type="text/css" href="dstyle.css" />  
+</head>
+<body>
+
+<a define="cell"  name="cell1output">
+<a parameter="cellcode"  type="O"> </a>
+</a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Samples/Samples/Sample5_SimplePerceptron/Container/3/dstyle.css b/Samples/Samples/Sample5_SimplePerceptron/Container/3/dstyle.css
new file mode 100644 (file)
index 0000000..5a10ecb
--- /dev/null
@@ -0,0 +1,51 @@
+
+a[define] {
+       border-top:    1px solid gray;
+       text-indent:   1em;
+       display:       block;
+       margin-top:    32px;
+       margin-bottom: 8px;
+} 
+
+a[define="cellcode"]:before {
+       content:       "Definition of CellCode : " attr(name)      "  (type:" attr(type) ")" ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+
+
+a[define="cell"]:before {
+       content:       "Definition of Cell : " attr(name)  ;
+       font-size:     large;
+       font-weight:   bold;
+       display:       inline;
+       white-space:   pre;
+}
+         
+a[parameter="cellcode"]:before {
+       content:       "CellCode : " attr(href)  attr(type); 
+       display:       inline;
+}
+
+a[parameter="cellcode"] {
+       text-indent:   1em;
+       display:       block;
+}
+
+a[parameter="connection"]:before {
+       content:       "-> " attr(href)  "(" attr(receptor) ")"; 
+       display:       inline;
+}
+
+a[parameter="connection"] {
+       text-indent:   2em;
+       display:       block;
+}
+
+[parameter="script"] { 
+        border:             1px solid gray;
+        background-color:   #f0f0cc;
+        margin-left:        2em;
+}
diff --git a/Samples/Samples/Sample5_SimplePerceptron/property.xml b/Samples/Samples/Sample5_SimplePerceptron/property.xml
new file mode 100644 (file)
index 0000000..1ddd0c8
--- /dev/null
@@ -0,0 +1,8 @@
+<dennco>
+
+<TickIntervalSec>0.02</TickIntervalSec>
+<UIPath>/ui/index.html</UIPath>
+<EnableHTTPServer>no</EnableHTTPServer> <!-- not implemented yet -->
+<EnableSerialServer>no</EnableSerialServer>
+
+</dennco>
\ No newline at end of file
diff --git a/Samples/Samples/Sample5_SimplePerceptron/ui/index.html b/Samples/Samples/Sample5_SimplePerceptron/ui/index.html
new file mode 100644 (file)
index 0000000..905593b
--- /dev/null
@@ -0,0 +1,614 @@
+<html>
+<head>
+<title>Dennco Sample5 - SimplePerceptron</title>
+<script type="text/javascript">
+
+try {
+       if (!engine)
+       {
+               alert("This page is expected to be executed on 'dennco engine'. This won't work properly on a browser.");
+       }
+}
+catch(e)
+{
+       alert("This page is expected to be executed on 'dennco engine'. This won't work properly on a browser.");
+}
+
+//dennco interfaces
+var CELLV1INPUT =      "/1/1_a.xhtml#cell1v1input";
+var CELLV2INPUT =      "/1/1_a.xhtml#cell1v2input";
+var CELLOUTPUT =       "/3/3_a.xhtml#cell1output";
+var CELLRATE =                 "/1/1_a.xhtml#cell1rate";
+var CELLLEARN =        "/1/1_a.xhtml#cell1learn";
+var CELLDESIRED =      "/1/1_a.xhtml#cell1desired";
+
+//status
+var isInsideGraph = false;
+var point_v1;
+var point_v2;
+
+//layour
+var WIDTH=400;
+var HEIGHT=400;
+var GRAPH_X0 = 30;
+var GRAPH_Y0 = 370;
+var GRAPH_WIDTH = 360;
+var GRAPH_HEIGHT = 360;
+var GRAPH_S = 8;
+var GRAPH_V1MIN = - 2;
+var GRAPH_V1MAX = 2;
+var GRAPH_V2MIN = - 2;
+var GRAPH_V2MAX = 2;
+
+//window.addEventListener("load", uiInit, false);
+
+var testTimerId = null;
+//
+var learnTimerId = null;
+var isLearning = false;
+var isPrepareForNextSample = false;
+var learnCount = 0;
+var learnDesired = 0;
+var learnGood = 0;
+
+function updateTestIO()
+{
+       engine.setValue(CELLV1INPUT, point_v1);
+       engine.setValue(CELLV2INPUT, point_v2);
+       document.getElementById("testOutput").value = engine.getValue(CELLOUTPUT);
+}
+
+function learnSample()
+{
+       engine.setValue(CELLRATE,Number((document.getElementById("learningRateTextInput")).value));
+       
+       if (isPrepareForNextSample)
+       {
+               isPrepareForNextSample = false;
+               
+               var output = engine.getValue(CELLOUTPUT);
+               if (output == learnDesired)
+               {
+                       learnGood ++;
+               }
+               engine.setValue(CELLLEARN, 0);
+               learnCount ++;
+       }
+       else
+       {
+               var list = document.getElementById("lerningItems");
+               var nextIndex = list.selectedIndex + 1;
+               if (nextIndex >= list.options.length)
+                       nextIndex = 0;
+               list.selectedIndex = nextIndex;
+               var v = list.options[nextIndex].value.split(",");
+               drawLearnPoints();
+               learnDesired = v[2];
+               engine.setValue(CELLV1INPUT, v[0]);
+               engine.setValue(CELLV2INPUT, v[1]);
+               engine.setValue(CELLDESIRED, v[2]);
+               engine.setValue(CELLLEARN, 1);
+
+               isPrepareForNextSample = true;
+       }
+       
+       var message = "Learning.. " + learnCount + "/ 50 \rGood:" + learnGood + "   Corrected:" + (learnCount - learnGood);
+               
+       if (message.length > 0)
+               document.getElementById("learnStatusMessage").innerText = message;
+       
+       if (learnCount >= 50)
+               stopLearn();
+}
+
+function learnButtonClicked()
+{
+       if (!isLearning)
+       {
+               startLearn();
+       }
+       else
+       {
+               stopLearn();
+       }
+}
+
+function startLearn()
+{
+       if (document.getElementById("lerningItems").options.length == 0)
+       {
+               alert("No sample to learn");
+               return;
+       }
+
+       isLearning = true;
+       setLearnModeUIEnable(false);
+       document.getElementById("learnButton").value = "Stop";
+       
+       if (learnTimerId != null)
+       {
+               clearInterval(learnTimerId);
+       }
+       learnCount = 0;
+       learnDesired = 0;
+       learnGood = 0;
+       learnTimerId = setInterval("learnSample()", 50);
+}
+
+function stopLearn()
+{
+       engine.setValue(CELLLEARN, 0);
+       isLearning = false;
+       setLearnModeUIEnable(true);
+       document.getElementById("learnButton").value = "Start to learn";
+
+       if (learnTimerId != null)
+       {
+               clearInterval(learnTimerId);
+               learnTimerId = null;
+       }
+}
+
+function startTestMode()
+{
+       stopTimer();
+       testTimerId = setInterval("updateTestIO()",20);
+}
+
+function stopTestMode()
+{
+       stopTimer();
+}
+
+function setLearnModeUIEnable(enable)
+{
+       document.getElementById("mode").disabled = !enable;             
+//     document.getElementById("v1Input").disabled = !enable;          
+//     document.getElementById("v2Input").disabled = !enable;          
+//     document.getElementById("cursorValue").disabled = !enable;              
+//     document.getElementById("lerningItems").disabled = !enable;             
+//     document.getElementById("learningRateRangeInput").disabled = !enable;           
+//     document.getElementById("learningRateTextInput").disabled = !enable;            
+}
+
+function uiInit()
+{
+       var canvasHolder = document.getElementById("canvasHolder");
+       canvasHolder.addEventListener("mousemove", mouseMoveHandler, true);
+       canvasHolder.addEventListener("mousedown", mouseDownHandler, false);
+       canvasHolder.addEventListener("mouseup", mouseUpHandler, false);
+       drawGraphBase();
+       pointColor = "red";
+       
+       addLearnPoint(0,0,1);
+       addLearnPoint(0,1,1);
+       addLearnPoint(1,0,1);
+       addLearnPoint(1,1,0);
+}
+
+function stopTimer()
+{
+       if (testTimerId != null)
+       {
+               clearInterval(testTimerId);
+               testTimerId = null;
+       }
+       if (learnTimerId != null)
+       {
+               clearInterval(learnTimerId);
+               learnTimerId = null;
+       }
+}
+
+function addLearnPointFromUI()
+{
+       var v1 = Number(document.getElementById("v1Input").value);
+       var v2 = Number(document.getElementById("v2Input").value);
+       var d = Number(document.getElementById("cursorValue").value);
+
+       addLearnPoint(v1,v2,d);
+}
+
+function addTestPointFromUI()
+{
+       var v1 = Number(document.getElementById("testV1Input").value);
+       var v2 = Number(document.getElementById("testV2Input").value);
+       var o = Number(document.getElementById("testOutput").value);
+       
+       addTestPoint(v1,v2,o);
+}
+
+function addLearnPoint(v1,v2,d)
+{      
+       
+       var text = "v1:" + v1 + " v2:" + v2 + " d:" + d;
+       var value = v1 +"," + v2 + "," + d;
+       
+       var list = document.getElementById("lerningItems");
+       
+       var opt = document.createElement("option");
+       opt.value = value;
+       opt.text = text;
+       list.options.add(opt, list.options.length);
+       list.selectedIndex = list.options.length -1;
+       drawLearnPoints();
+}
+
+function addTestPoint(v1,v2,o)
+{
+       var text = "v1:" + v1 + "   v2:" + v2 + "   output:" + o;
+       var value = v1 +"," + v2 + "," + o;
+       
+       var list = document.getElementById("testItems");
+       var opt = document.createElement("option");
+       opt.value = value;
+       opt.text = text;
+       list.options.add(opt, list.options.length);
+       list.selectedIndex = list.options.length -1;
+       drawTestPoint(v1,v2,o);
+}
+
+function removeSelectedPoint()
+{
+       var list = document.getElementById("lerningItems");
+       var index = list.selectedIndex;
+       if (index >= 0)
+       {
+               var list = document.getElementById("lerningItems");
+               list.remove(index);
+
+               drawLearnPoints();
+       }
+}
+
+function pointToCanvas(v1,v2)
+{
+       var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+       var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+       
+       var x = (v1 - GRAPH_V1MIN) / xrange * GRAPH_WIDTH + GRAPH_X0;
+       var y = GRAPH_Y0 - (v2 - GRAPH_V2MIN) / yrange * GRAPH_HEIGHT;
+
+       return {x:x, y:y};
+}
+
+function drawGraphBase()
+{
+       var can = document.getElementById("canvasLayer1");
+       var context = can.getContext("2d");
+       context.fillStyle = "black";
+       context.strokeStyle = "rgb(0, 10, 0)";
+       context.beginPath();
+       context.lineWidth = 1;
+       context.moveTo(GRAPH_X0,GRAPH_Y0 - GRAPH_HEIGHT);
+       context.lineTo(GRAPH_X0,GRAPH_Y0);
+       context.lineTo(GRAPH_X0 + GRAPH_WIDTH,GRAPH_Y0);
+       context.stroke();
+       
+       var xstep = GRAPH_WIDTH / GRAPH_S;
+       var ystep = GRAPH_HEIGHT / GRAPH_S;
+       
+       var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+       var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+       
+       context.font = "10px sans-serif";
+       
+       for (var i = 1; i <= GRAPH_S; i++)
+       {
+               hp = GRAPH_X0 + i * xstep;
+               vp = GRAPH_Y0 - i * ystep;
+               
+               context.beginPath();
+               context.lineWidth = 1;
+               context.moveTo(hp ,GRAPH_Y0 - 5);
+               context.lineTo(hp ,GRAPH_Y0);
+               context.stroke();
+
+               context.beginPath();
+               context.lineWidth = 1;
+               context.moveTo(GRAPH_X0, vp);
+               context.lineTo(GRAPH_X0 + 5, vp);
+               context.stroke();
+
+               var ux =  GRAPH_V1MIN + xrange / GRAPH_S * i;
+               var uy =  GRAPH_V2MIN + yrange / GRAPH_S * i;
+               
+               context.textAlign = "center";
+               context.textBaseline = "top";
+               context.fillText(ux, hp, GRAPH_Y0 + 2);
+               
+               context.textAlign = "right";
+               context.textBaseline = "middle";
+               context.fillText(uy, GRAPH_X0 - 3, vp);
+       }
+       
+       context.textAlign = "right";
+       context.textBaseline = "bottom";
+       context.fillText(GRAPH_V2MIN, GRAPH_X0 - 3, GRAPH_Y0);
+
+       context.textAlign = "left";
+       context.textBaseline = "top";
+       context.fillText(GRAPH_V1MIN, GRAPH_X0, GRAPH_Y0 + 2);
+}
+
+
+function drawCursor()
+{
+       var can = document.getElementById("canvasLayer4");
+       var context = can.getContext("2d");
+
+       context.clearRect(0, 0, WIDTH, HEIGHT);
+
+       var cp = pointToCanvas(point_v1, point_v2);
+
+       if ((document.getElementById("mode")).value == "learn" ) 
+       {
+               document.getElementById("v1Input").value = point_v1;
+               document.getElementById("v2Input").value = point_v2;
+               context.strokeStyle = (document.getElementById("cursorValue").value == "0") ? "blue" : "red";
+               context.beginPath();
+               context.lineWidth = 0;
+               context.moveTo(cp.x-5 ,cp.y);
+               context.lineTo(cp.x+5 ,cp.y);
+               context.stroke();
+
+               context.beginPath();
+               context.lineWidth = 0;
+               context.moveTo(cp.x ,cp.y-5);
+               context.lineTo(cp.x ,cp.y+5);
+               context.stroke();
+       }
+       else
+       {
+               document.getElementById("testV1Input").value = point_v1;
+               document.getElementById("testV2Input").value = point_v2;
+               var c = Number(document.getElementById("testOutput").value) == 0 ? "blue" : "red";
+               context.strokeStyle = c;
+               context.fillStyle = c;
+               context.fillRect(cp.x-4,cp.y-4,8,8);
+       }
+}
+
+function drawLearnPoints()
+{
+       var can = document.getElementById("canvasLayer2");
+       var context = can.getContext("2d");
+       context.clearRect(0, 0, WIDTH, HEIGHT);
+       
+       var learnMode = (document.getElementById("mode")).value == "learn";
+       var list = document.getElementById("lerningItems");
+       for (var i = 0; i < list.length; i++)
+       {
+               var v = list.options[i].value.split(",");
+               var cp = pointToCanvas(v[0], v[1]);
+               context.strokeStyle = (v[2] == 0) ? "blue" : "red";
+               
+               if (learnMode) 
+               {
+                       context.beginPath();
+                       context.lineWidth = 0;
+                       context.moveTo(cp.x-4 ,cp.y-4);
+                       context.lineTo(cp.x+4 ,cp.y+4);
+                       context.stroke();
+                       context.beginPath();
+                       context.lineWidth = 0;
+                       context.moveTo(cp.x-4 ,cp.y+4);
+                       context.lineTo(cp.x+4 ,cp.y-4);
+                       context.stroke();
+                       
+                       if (list.selectedIndex == i)
+                       {
+                               context.strokeRect(cp.x-5 ,cp.y-5,10,10);
+                       }
+               }
+               else
+               {
+                       context.beginPath();
+                       context.lineWidth = 0;
+                       context.moveTo(cp.x-2 ,cp.y-2);
+                       context.lineTo(cp.x+2 ,cp.y+2);
+                       context.stroke();
+                       context.beginPath();
+                       context.lineWidth = 0;
+                       context.moveTo(cp.x-2 ,cp.y+2);
+                       context.lineTo(cp.x+2 ,cp.y-2);
+                       context.stroke();
+               }
+       }
+}
+
+function clearTestPoints()
+{
+       var can = document.getElementById("canvasLayer3");
+       var context = can.getContext("2d");
+       context.clearRect(0, 0, WIDTH, HEIGHT);
+
+       var list = document.getElementById("testItems");
+       
+       while(list.options.length > 0)
+       {
+               list.options.remove(list.options.length - 1);
+       }
+       drawCursor();
+}
+
+function drawTestPoint(v1,v2,output)
+{
+       var can = document.getElementById("canvasLayer3");
+       var context = can.getContext("2d");
+       
+       var cp = pointToCanvas(v1, v2);
+       
+       var c = (output == 0) ? "blue" : "red";
+       context.strokeStyle = c;
+       context.fillStyle = c;
+               
+       context.fillRect(cp.x-3 ,cp.y-3,6,6);
+}
+
+
+function mouseMoveHandler(e)
+{
+       var rect = e.target.getBoundingClientRect();
+       var x = e.clientX - rect.left;
+       var y = e.clientY - rect.top;
+       
+       if (x < GRAPH_X0 || x > GRAPH_X0 + GRAPH_WIDTH || y < GRAPH_Y0 - GRAPH_HEIGHT || y > GRAPH_Y0)
+       {
+               isInsideGraph = false;
+               return;
+       }
+       isInsideGraph = true;
+       
+       var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+       var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+       
+       point_v1 = Number((x - GRAPH_X0) / GRAPH_WIDTH * xrange + GRAPH_V1MIN).toFixed(2);
+       point_v2 = Number((GRAPH_Y0 - y) / GRAPH_HEIGHT * yrange + GRAPH_V2MIN).toFixed(2);
+       
+       drawCursor();
+}
+
+function mouseDownHandler()
+{
+       if (isInsideGraph)
+       {
+               if ((document.getElementById("mode")).value == "learn")
+                       addLearnPointFromUI();
+               else
+                       addTestPointFromUI();
+       }
+}
+
+function mouseUpHandler()
+{
+}
+
+function modeChanged()
+{
+       if ((document.getElementById("mode")).value == "learn")
+       {
+               //learning mode
+               (document.getElementById("testModePanel")).style.zIndex = 1;
+               (document.getElementById("lerningModePanel")).style.zIndex = 2;
+               stopTestMode();
+       }
+       else
+       {
+               //test mode
+               (document.getElementById("testModePanel")).style.zIndex = 2;
+               (document.getElementById("lerningModePanel")).style.zIndex = 1;
+               startTestMode();
+       }       
+       clearTestPoints();
+       drawLearnPoints();
+}
+
+function rateRangeInputChanged()
+{
+       var newValue = (Number((document.getElementById("learningRateRangeInput")).value)/100.0).toFixed(2);
+       if ((Number(document.getElementById("learningRateTextInput")).value) != newValue)
+               (document.getElementById("learningRateTextInput")).value = newValue;
+}
+
+function rateTextInputChanged()
+{
+       var newValue = (Number((document.getElementById("learningRateTextInput")).value)*100).toFixed(0);
+       if ((Number(document.getElementById("learningRateRangeInput")).value) != newValue)
+               (document.getElementById("learningRateRangeInput")).value = newValue;
+}
+
+</script>
+</head>
+<body onLoad="uiInit();" onUnload="stopTimer();" >
+
+<table border="0" cellspacing="0" cellpadding="0">
+<tr valign="top">
+<td rowspan="2">
+<div id="canvasHolder" style="position:relative; width:400px; height:400px; border:1px solid #c3c3c3;">
+<canvas id="canvasLayer1" style="z-index: 1;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer2" style="z-index: 2;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer3" style="z-index: 3;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer4" style="z-index: 4;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+</div>
+</td>
+
+<td rowspan="2" width="20"></td>
+
+<td height="15">
+<select id="mode" size="1" style="font-size: large; width:320; height:100%" onChange="modeChanged()">
+<option value="learn">Learning mode
+<option value="test">Testing mode
+</select>
+</td>
+
+<tr>
+<td valign="top">
+<!--- control panels -->
+<div style="position:relative;" >
+<div id="lerningModePanel" style="z-index: 2;position:absolute;left:0px;top:0px;background-color:#f0f0f0;width:320;height:375">
+<table border="0" >
+<tr >
+<td>V1</td><td><input type="text" size="6", style="text-align:right; width:100%"  id="v1Input"/></td><td><button style="width:100" id="addButton" onClick="addLearnPointFromUI()">Add</button></td>
+</tr>
+<tr>
+<td>V2</td><td><input type="text" size="6", style="text-align:right; width:100%" id="v2Input"/></td><td></td>
+</tr>
+<tr>
+<td>Desired</td><td><SELECT id="cursorValue" style="width:100%" SIZE="1" ><option value="0">0 (BLUE)<option value="1">1 (RED)</SELECT></td><td></td>
+</tr>
+
+<tr>
+<td colspan="2"><SELECT id="lerningItems" SIZE="6" style="width:200;font-family:monospace;" onChange="drawLearnPoints()"></SELECT></td>
+<td  valign="top"><button style="width:100" id="removeButton" onClick="removeSelectedPoint()">Remove</button></td>
+</tr>
+
+<tr>
+<td>
+Learning rate
+</td>
+<td colspan="2" valign="middle">
+<input type="range" MIN="0" MAX="100" value="10" id="learningRateRangeInput" onChange="rateRangeInputChanged()"/><input type="text" size="5", style="text-align:right;"  id="learningRateTextInput" onChange="rateTextInputChanged()" value="0.1"/>
+</td>
+</tr>
+
+<tr>
+<td colspan="3"><input type="button" style="width:300;height:50" id="learnButton" value="Start to learn" onClick="learnButtonClicked()"/></td>
+</tr>
+<tr>
+<td colspan="3"><p id="learnStatusMessage"> </p></td>
+</table>
+
+</div>
+
+<div id="testModePanel" style="z-index: 1;position:absolute;left:0px;top:0px;background-color:#f0f0f0;;width:320;height:375">
+
+<table border="0" >
+<tr >
+<td>V1</td><td><input type="text" size="6", style="text-align:right; width:100%"  id="testV1Input" disabled="true"/></td>
+</tr>
+<tr>
+<td>V2</td><td><input type="text" size="6", style="text-align:right; width:100%" id="testV2Input" disabled="true"/></td><td></td>
+</tr>
+<tr>
+<td>Out</td><td><input type="text" size="6", style="text-align:right; width:100%" id="testOutput" disabled="true"/></td><td></td>
+</tr>
+<tr>
+<td colspan="2"><SELECT id="testItems" SIZE="10" style="width:300; font-family:monospace;" ></SELECT></td>
+</tr>
+</table>
+
+</div>
+</div>
+
+</td>
+</td>
+</tr>
+</table>
+<p>Sample implementation of Perceptron with dennco engine. See: <a href="javascript:void(0)" onclick="window.open('http://en.wikipedia.org/wiki/Perceptron');">http://en.wikipedia.org/wiki/Perceptron</a> for the detail information about Perceptron.</P>
+</body>
+</html>