JSFiddle - React, Tailwind, and code Playground

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<div>ρ:
    <input id="rho" type="text" value="1.2" size="5">
    <button id="step">step</button>
    <button id="reset">reset</button>
</div>
<div style="background-color: #eee; font-family: monospace">
    <span id="terminal">
        Ready
    </span>
</div>

CSS

body {
    background-color: white;
}
.axis path, .axis line {
    fill: none;
    stroke: black;
    shape-rendering: crispEdges;
}
.axis text {
    font-family: sans-serif;
    font-size: 11px;
}
.draggable {
    cursor: pointer;
}

JavaScript

'use strict';

// 学習パターンを識別関数に適用して誤識別した場合、パーセプトロンの学習規則に基づき重みを調整する
//   ws : 拡張重みベクトル
//   xs : 拡張特徴ベクトル
//   c  : クラス (0 or 1)
//   rho: 学習係数ρ
function learn(ws, xs, c, rho) {
  var g = dot(ws, xs); // 識別関数gを計算
  if (c == 0 && g <= 0) { // クラスω1を誤識別
    madd(ws, rho, xs); // w' = w + ρx
    return true;
  } else if (c != 0 && g >= 0) { // クラスω2を誤識別
    madd(ws, -rho, xs); // w' = w - ρx
    return true;
  }
  return false;
}

// 内積
function dot(a, b) {
  var l = 0;
  for (var i = 0; i < a.length; ++i)
    l += a[i] * b[i];
  return l;
}

// 係数付き加算
function madd(a, p, b) {
  for (var i = 0; i < a.length; ++i)
    a[i] += p * b[i];
}

// 学習パターン
var dataset = [
  [0, 1.2],
  [0, 0.2],
  [0, -0.2],
  [1, -0.5],
  [1, -1.0],
  [1, -1.5]
];

// 拡張重みベクトル
var ws = [-7, 2]; //[11, 5];

// D3.js関連
var width = 600,
    height = 600,
    padding = 30;

// 重みベクトルの軌跡
var plots = [];

// 原点からの距離
function dist(x, y) {
  return Math.sqrt(x * x + y * y);
}

// 描画
function draw() {
  d3.select('svg').remove();

  var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);

  var xScale = d3.scale.linear()
    .domain([-12, 12])
    .range([padding, width - padding]);

  var yScale = d3.scale.linear()
    .domain([-12, 12])
    .range([height - padding, padding]);

  // パターンの座標を計算
  function patternX(d1, r) {
    return xScale(r / dist(d1, 1));
  }

  function patternY(d1, r) {
    return yScale(-r / dist(d1, 1) * d1);
  }

  var lines, nodes;

  // パターンをドラッグ時のイベント
  var dragPattern = (function() {
    var dragX, dragY;
    return d3.behavior.drag()
      .on('dragstart', function(d, i) {
        d3.event.sourceEvent.stopPropagation();
        dragX = xScale(13 / dist(d[1], 1));
        dragY = yScale(-13 / dist(d[1], 1) * d[1]);
      })
      .on('drag', function(d, i) {
        dragX += d3.event.dx;
        dragY += d3.event.dy;
        var x = xScale.invert(dragX);
        var y = yScale.invert(dragY);
        d[1] = -y / x;
       ...