Skip to content

Commit

Permalink
random checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
alltom committed Dec 28, 2013
1 parent 03b8057 commit 72c2f97
Show file tree
Hide file tree
Showing 4 changed files with 370 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
64 changes: 64 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// 2013-12-28
// (revisited in Jamaica after having read it sometime fall semester?)

// http://groups.csail.mit.edu/mac/users/gjs/propagators/

// python: https://github.com/lucastx/propagator.py

Porcelain:
a = cell();
b = cell();
addContent(a, 3);
addContent(b, 2);
answer = cellExpression(add, a, b);
run();
console.log(answer.content());

/*
(d@ propagator boundary-cell ...)
diagramApply(cell, ...)
Attaches a propagator to the given boundary cells. By convention, cells used
as outputs go last. As a Scheme procedure, d@ does not return a useful value.

(e@ propagator boundary-cell ...)
output = expressionApply(cell, ...)
Attaches the given propagator to a boundary consisting of the given boundary
cells augmented with an additional, synthesized cell. The synthesized cell
goes last, because that is the conventional position for an output cell.
Returns the synthesized cell as the Scheme return value of e@.

This:
(define-cell x)
(define-cell y)
(define-cell z)
(d@ p:* x y z)
is equivalent to this:
(define-cell x)
(define-cell y)
(define-cell z (e@ p:* x y))

deposit/examine propagators
put one cell into another cell

p:when
takes an input cell and propagates only when it's true
(TODO: I don't understand conditionals or recursion yet)

makeInterval(3, 5) -> cell
intervalLow(interval) -> low value
intervalHigh(interval) -> high value
isInterval(thing) -> bool

Partial Information Structures:
equivalent? - used to tell whether a cell has changed
merge - "What do I need to do to the network in order to make it reflect the discovery that these two information structures are about the same object?"
Record: that object is best described by this information structure
These two information structures cannot describe the same object.
Record this information structure and connect these two cells with synchronizing propagators
contradictory?

premise
worldView is a collection of believed premises
contingency - information that the given info is contingent on the given list of premises
truthManagementSystem([contingency]) - seems really important, but I don't get it yet
*/
2 changes: 0 additions & 2 deletions README.md

This file was deleted.

305 changes: 305 additions & 0 deletions propagators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
var _ = require("underscore");

function Scheduler() {
var self = {};
var propagatorsEverAlerted = [];
var alertedPropagators = [];
var lastValueOfRun;

self.alertPropagators = function (propagators) {
propagatorsEverAlerted = _.union(propagatorsEverAlerted, propagators);
alertedPropagators = _.union(alertedPropagators, propagators);
};

self.alertPropagator = function (propagator) {
self.alertPropagators([propagator]);
};

self.alertAllPropagators = function () {
alertPropagators(propagatorsEverAlerted);
};

self.addPropagator = function (neighbors, toDo) {
_.each(neighbors, function (cell) {
cell.addNeighbor(toDo);
});
self.alertPropagator(toDo);
}

self.run = function () {
while (alertedPropagators.length > 0) {
console.log("tick")
alertedPropagators.pop()();
}
return lastValueOfRun = "done";
};

return self;
}

// content is optional
function Cell(scheduler, content) {
var self = {};
var neighbors = [];
var content = content;

self.content = function () {
return content;
};

self.addContent = function (increment) {
var answer = merge(content, increment);

if (!equivalent(content, answer)) {
content = answer;
scheduler.alertPropagators(neighbors);
}
};

self.addNeighbor = function (neighbor) {
neighbors = _.union(neighbors, [neighbor]);
scheduler.alertPropagator(neighbor);
};

return self;
}

function addCompoundPropagator(scheduler, neighbors, toBuild) {
var done = false;
scheduler.addPropagator(neighbors, toDo);

function toDo() {
if (!done) {
if (_.any(neighbors, getContent)) {
done = true;
toBuild();
}
}

function getContent(cell) {
return cell.content();
}
}
}

function functionCallPropagator(scheduler, f) {
return Cell(scheduler, function (scheduler, cells) {
var inputs = cells.slice(0, cells.length - 1);
var output = cells[cells.length - 1];
scheduler.addPropagator(inputs, toDo);

function toDo() {
var answer = f.apply(undefined, _.map(inputs, getContent));
output.addContent(answer);

function getContent(cell) {
return cell.content();
}
}
});
}

function merge(content, increment) {
if (increment == undefined) {
return content;
} else {
return increment; // TODO
}
}

function equivalent(a, b) {
return a === b;
}

function requireAll(f) {
return function () {
if (_.all(arguments, function (value) { return value != undefined })) {
return f.apply(this, arguments);
}
};
}

// (d@ propagator boundary-cell ...)
// propagator is a cell containing a propagator constructor for attaching propagators
function diagramApply(scheduler, propagator, boundaryCells) {
if (propagator.content()) {
propagator.content()(scheduler, boundaryCells);
} else {
scheduler.addPropagator([propagator], function () {
if (propagator.content()) {
propagator.content()(scheduler, boundaryCells);
}
});
}
}

// (e@ propagator boundary-cell ...)
// like d@, but synthesizes an output cell and returns it
function expressionApply(scheduler, propagator, boundaryCells) {
var output = Cell(scheduler);
diagramApply(scheduler, propagator, boundaryCells.concat(output));
return output;
}

function main() {
var scheduler = Scheduler();

function requiredCells(cells, f) {
return function () {
if (_.all(cells, function (cell) { return cell.content() != undefined })) {
return f.apply(this, arguments);
}
};
}

function foo(inputCells, f) {
return function () {
if (_.all(inputCells, function (cell) { return cell.content() != undefined })) {
return f.apply(this, _.map(inputCells, function (cell) { return cell.content() }));
}
};
}

// var pAdd = Cell(scheduler, function (scheduler, cells) {
// var inputs = cells.slice(0, 2), answer = cells[2];
// // scheduler.addPropagator(inputs, foo(inputs, function (a, b) { cells[2].addContent(a + b) }));
// scheduler.addPropagator(cells.slice(0, 2), foo(cells, function (a, b) { cells[2].addContent(a + b) }));
// });

// propagators
var pId = functionCallPropagator(scheduler, requireAll(function (a) { return a }));
var pNot = functionCallPropagator(scheduler, requireAll(function (a) { return !a }));
var pAdd = functionCallPropagator(scheduler, requireAll(function (a, b) { return a + b }));
var pSubtract = functionCallPropagator(scheduler, requireAll(function (a, b) { return a - b }));
var pMultiply = functionCallPropagator(scheduler, requireAll(function (a, b) { return a * b }));
var pDivide = functionCallPropagator(scheduler, requireAll(function (a, b) { return a / b }));
var pSwitch = functionCallPropagator(scheduler, function (control, input) { if (control) return input });
var pConditional = functionCallPropagator(scheduler, function (control, consequent, alternate) { if (control) { return consequent } else { return alternate } });
// TODO: pConditionalRouter
// TODO: pDeposit
// TODO: pExamine
// var cId = functionCallPropagator(scheduler, requireAll(function (a) { return a }));

var cId = Cell(scheduler, function (scheduler, cells) {
diagramApply(scheduler, pId, [cells[0], cells[1]]);
diagramApply(scheduler, pId, [cells[1], cells[0]]);
});

var cAdd = Cell(scheduler, function (scheduler, cells) {
diagramApply(scheduler, pAdd, [cells[0], cells[1], cells[2]]);
diagramApply(scheduler, pSubtract, [cells[2], cells[1], cells[0]]);
diagramApply(scheduler, pSubtract, [cells[2], cells[0], cells[1]]);
});
var cSubtract = Cell(scheduler, function (scheduler, cells) {
diagramApply(scheduler, cAdd, [cells[1], cells[2], cells[0]]);
});

var cMultiply = Cell(scheduler, function (scheduler, cells) {
diagramApply(scheduler, pMultiply, [cells[0], cells[1], cells[2]]);
diagramApply(scheduler, pDivide, [cells[2], cells[1], cells[0]]);
diagramApply(scheduler, pDivide, [cells[2], cells[0], cells[1]]);
});
var cDivide = Cell(scheduler, function (scheduler, cells) {
diagramApply(scheduler, cMultiply, [cells[1], cells[2], cells[0]]);
});

// var control = Cell(scheduler);
// var consequent = Cell(scheduler, 1);
// var alternate = Cell(scheduler, 2);
// var output = Cell(scheduler);
// diagramApply(scheduler, pConditional, [control, consequent, alternate, output]);
// scheduler.run();
// console.log(output.content()); // 2
// control.addContent(true);
// scheduler.run();
// console.log(output.content()); // 1
// control.addContent(false);
// scheduler.run();
// console.log(output.content()); // 2

// var control = Cell(scheduler);
// var input = Cell(scheduler, 1);
// var output = Cell(scheduler);
// diagramApply(scheduler, pSwitch, [control, input, output]);
// scheduler.run();
// console.log(output.content()); // undefined
// control.addContent(false);
// scheduler.run();
// console.log(output.content()); // undefined
// control.addContent(true);
// scheduler.run();
// console.log(output.content()); // 1

// var a = Cell(scheduler, 1);
// var b = Cell(scheduler, 2);
// var op = Cell(scheduler);
// var answer = Cell(scheduler);
// diagramApply(scheduler, op, [a, b, answer]);
// scheduler.run();
// console.log(answer.content()); // undefined
// diagramApply(scheduler, pId, [pAdd, op]);
// scheduler.run();
// console.log(answer.content()); // 3

// // w - ((x + y) * z) = 2 - ((3 + 4) * 5) = -33
// var w = Cell(scheduler);
// var x = Cell(scheduler);
// var y = Cell(scheduler);
// var z = Cell(scheduler);
// w.addContent(2);
// x.addContent(3);
// y.addContent(4);
// z.addContent(5);
// var answer = expressionApply(scheduler, subtract, [w, expressionApply(scheduler, multiply, [expressionApply(scheduler, add, [x, y]), z])]);
// scheduler.run();
// console.log(answer.content());

// var a = Cell(scheduler);
// var b = Cell(scheduler);
// a.addContent(3);
// b.addContent(2);
// var answer = expressionApply(scheduler, add, [a, b]);
// diagramApply(scheduler, subtract, [answer, a, b]);
// diagramApply(scheduler, subtract, [answer, b, a]);
// console.log("before:\t" + a.content() + " + " + b.content() + " = " + answer.content());
// scheduler.run();
// console.log("after:\t" + a.content() + " + " + b.content() + " = " + answer.content());

var a = Cell(scheduler);
var b = Cell(scheduler, 2);
diagramApply(scheduler, cId, [a, b]);
scheduler.run();
console.log(a.content()); // 2

// var a = Cell(scheduler);
// var b = Cell(scheduler, 2);
// var answer = Cell(scheduler, 3);
// diagramApply(scheduler, cSubtract, [a, b, answer]);
// scheduler.run();
// console.log(a.content()); // 5

// var a = Cell(scheduler);
// var b = Cell(scheduler, 2);
// var answer = Cell(scheduler, 3);
// diagramApply(scheduler, cAdd, [a, b, answer]);
// scheduler.run();
// console.log(a.content()); // 1

// var a = Cell(scheduler, 1);
// var b = Cell(scheduler, 2);
// var answer = Cell(scheduler);
// diagramApply(scheduler, pAdd, [a, b, answer]);
// scheduler.run();
// console.log(answer.content()); // 3

// var cell1 = Cell(scheduler);
// var cell2 = Cell(scheduler);
// var cell3 = Cell(scheduler);
// var prop1 = adder(scheduler, [cell1, cell2, cell3]);
// var prop2 = subtracter(scheduler, [cell3, cell2, cell1]);
// var prop3 = subtracter(scheduler, [cell3, cell1, cell2]);
// console.log(cell1.content() + " + " + cell2.content() + " = " + cell3.content());
// scheduler.run();
// console.log(cell1.content() + " + " + cell2.content() + " = " + cell3.content());
}
main();

0 comments on commit 72c2f97

Please sign in to comment.