diff --git a/canvas.js b/canvas.js index 6900a66..c18dde3 100644 --- a/canvas.js +++ b/canvas.js @@ -1,41 +1,25 @@ var mlps = []; +var ogarganizer; +var editOrganizer; function setup() { createCanvas(1920, 1080); + organizer = new Organizer(); + editOrganizer = new EditOrganizer(createGraphics(1920, 1080)); mlps.push(new MLP(4, [3, 5, 1], 600, 100)); - // mlps.push(new MLP(3, [3, 2, 1], 500, 300)); - - // xs = [ - // [2.0, 3.0, -1.0], - // [3.0, -1.0, 0.5], - // [0.5, 1.0, 1.0], - // [1.0, 1.0, -1.0], - // ]; - // ys = [1.0, -1.0, -1.0, 1.0]; - // - // let k = 0; - // let intervalId = setInterval(() => { - // ypred = xs.map((x) => mlp.call(x)); - // let loss = new Value(0); - // for (let i = 0; i < ys.length; i++) { - // loss = loss.add(ypred[i].sub(new Value(ys[i])).pow(new Value(2))); - // } - // - // m.parameters().forEach((p) => (p.grad = 0.0)); - // loss.backprop(); - // m.parameters().forEach((p) => (p.data += -0.1 * p.grad)); - // - // k++; - // if (k >= 20) { - // clearInterval(intervalId); - // } - // }, 500); + mlps.push(new MLP(4, [3, 5, 1], 600, 100)); +} + +function setupPopup() { + organizer.disable(); } function draw() { - background(220); + background(255); mlps.forEach((m) => m.draw()); + + editOrganizer.draw(); } function mousePressed() { @@ -45,3 +29,35 @@ function mousePressed() { function mouseReleased() { mlps.forEach((mlp) => mlp.handleReleased()); } + +function doubleClicked() { + mlps.forEach((mlp) => mlp.handleDoubleClicked()); +} + +// mlps.push(new MLP(3, [3, 2, 1], 500, 300)); +// +// xs = [ +// [2.0, 3.0, -1.0], +// [3.0, -1.0, 0.5], +// [0.5, 1.0, 1.0], +// [1.0, 1.0, -1.0], +// ]; +// ys = [1.0, -1.0, -1.0, 1.0]; +// +// let k = 0; +// let intervalId = setInterval(() => { +// ypred = xs.map((x) => mlp.call(x)); +// let loss = new Value(0); +// for (let i = 0; i < ys.length; i++) { +// loss = loss.add(ypred[i].sub(new Value(ys[i])).pow(new Value(2))); +// } +// +// m.parameters().forEach((p) => (p.grad = 0.0)); +// loss.backprop(); +// m.parameters().forEach((p) => (p.data += -0.1 * p.grad)); +// +// k++; +// if (k >= 20) { +// clearInterval(intervalId); +// } +// }, 500); diff --git a/draggable.js b/draggable.js index e4d37ea..498fe7c 100644 --- a/draggable.js +++ b/draggable.js @@ -6,36 +6,39 @@ class Draggable { } over() { - if ( + this.rollover = mouseX > this.x && mouseX < this.x + this.w && mouseY > this.y && - mouseY < this.y + this.h - ) { - this.rollover = true; - } else { - this.rollover = false; - } + mouseY < this.y + this.h; } pressed(force = false) { - if (this.rollover || force) { + if (!(this.rollover || force)) return; + + if (!organizer.getDragActive() || force) { this.dragging = true; this.offsetX = this.x - mouseX; this.offsetY = this.y - mouseY; - isBusy = this.type == "layer" && !force; - if (this.type == "mlp") { - for (let i = 0; i < this.layers.length; i++) { - this.layers[i].pressed(true); - } + if (this.type === "mlp") { + this.layers.forEach((layer) => layer.pressed(true)); } + + organizer.setDragActive(true); + } + } + + doubleClicked() { + if (this.rollover && !editOrganizer.getSelected()) { + editOrganizer.enable(); + editOrganizer.setSelected(this); } } released() { this.dragging = false; - isBusy = false; + organizer.setDragActive(false); } updateCoordinates() { @@ -45,6 +48,6 @@ class Draggable { this.type == "layer" && this.updateNeuronsCoordinates(); } - this.type == "mlp" && this.updateLayersCoordinates(); + this.type == "mlp" && this.updateBorders(); // This is works because when you drag layer you also drag mlp } } diff --git a/editOrganizer.js b/editOrganizer.js new file mode 100644 index 0000000..4c49b5b --- /dev/null +++ b/editOrganizer.js @@ -0,0 +1,85 @@ +class EditOrganizer { + constructor(canvas) { + this.canvas = canvas; + this.enabled = false; + this.selected = null; + this.selectedCopy = null; + this.originX = (width - 500) / 2; + this.originY = 150; + this.w = 500; + this.h = 500; + this.setup(); + } + + setup() { + let button = createButton("Click me"); + button.position(50, 50); + button.mousePressed(() => { + this.disable(); + }); + } + + showSelected() { + this.selectedCopy.draw(); + } + + draw() { + this.canvas.fill(255); + this.canvas.rect(this.originX, this.originY, this.w, this.h); + this.selected && this.showSelected(); + this.enabled && image(this.canvas, 0, 0); + } + + getSelected() { + return this.selected; + } + + setSelected(layer) { + let x = this.originX + (this.w - layer.w) / 2; + let y = this.originY; + + this.selected = layer; + this.selectedCopy = new Layer( + layer.nin, + layer.nout, + x, + y - 100, + layer.label, + layer.act_func, + ); + + let cnv = this.canvas; + this.selectedCopy.show = () => { + let cpy = this.selectedCopy; + cnv.fill(255); + cnv.rect(cpy.x, cpy.y, 50, cpy.h); + cnv.fill(0); + cnv.text(cpy.label, cpy.x, cpy.y - 10); + cnv.fill(255); + }; + + this.selectedCopy.neurons.forEach((neuron) => { + neuron.show = () => { + cnv.fill(255); + cnv.circle(neuron.x, neuron.y, 25, 25); + cnv.fill(0); + cnv.text(neuron.output?.data.toFixed(2), neuron.x + 30, neuron.y); + cnv.text(neuron.output?.grad.toFixed(2), neuron.x + 30, neuron.y + 25); + fill(255); + }; + }); + } + + disable() { + this.enabled = false; + this.selected = null; + this.selectedCopy = null; + this.canvas.clear(); + } + + enable() { + this.canvas.background(0, 50); + + this.enabled = true; + } +} diff --git a/index.html b/index.html index 4f4e173..a3db0df 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,20 @@ -
+ + + +