McCulloch-Pitts Neural Nets

In exploring parallel rewriting systems, I stumbled onto something like neural networks and it pushed me to dive deeper into the topic and learning how they worked. I was surprised how capable this nice little OISC was. I implemented a textual graph representation language and runtime in about 150 lines of C89, or about 300 lines of Uxn. I think this is relevant to the Malleable community due to it being a symbolic system which is popular with malleable systems, as well as people exploring portable and parallel computation models.

Neural nets use synthetic neurons as the base computational unit. A McCulloch-Pitts neuron uses threshold saturation, excitatory and inhibitory fibers.

Neurons

A neuron has incoming and outgoing connections to other neurons, it fires an output that stimulates or inhibits other neurons when it is not inhibited and the sum of its excitatory inputs is equal or higher than its threshold. A neuron with a threshold of zero will always fire.

A neuron connected by two excitatory fibers, one inhibitory fiber, with a threshold of two.

Neural networks are typically programmed with flow diagrams, I found those to be prone to clutter. Instead, this documentation will use a textual representation, which allows networks to be created more rapidly and precisely.

A neuron*. 

In a rule, a neuron is specified with a star suffix, an excitatory connection is separated by a colon, an inhibitory connection is separated by a semi-colon. A rule with no right-hand side will create live neurons with a threshold of one. A rule is terminated by a period, rules can be chained, everything else is ignored.

If I have matches*, and some kindling*:
	I can make a fire*: 
	and have some light*. 

But if it's raining*;
	I cannot make a fire*.

I have matches* and kindling*. 

Programming with Neural Nets

A program will most likely involve an initial pulse. Let’s say we want a program/1 to wake up two other neurons via excitatory fibers:

The program* will wake up:
	both hello* and world*. 

Let's start our program*. 

Neural nets have an inclination for recipe crafting that resembles rewriting languages, but do not incur the cost of searching and matching facts against a database, reagents in rules are wired directly between each other like state-machines.

Chores.
	- Cook dinner*
	- Clean dishes*
	- Shovel snow*
	: The chores are done*.

Once you're done*:
	you can go play*.

Removed snow*, did dinner* & dishes*.

Evaluation:

00 dishes/1 snow/1 dinner/1 
01 done/3 
02 play/1

Logic in neural nets is implemented by combining thresholds, inhibitory and excitatory fibers. Arity can be hardcoded by specifying it in the symbol name. Here are the implementation of a few logic gates:

Loops

Loops can be implemented by connecting neurons in a circle. In the following program, two such circles are created, notice how this makes use of anonymous neurons:

fizz*: 
	*: *: fizz*.
buzz*: 
	*: *: *: *: buzz*.

Initialize both fizz* & buzz*.

Evaluation:

..
10 */1 buzz/1 
11 */1 */1 
12 fizz/1 */1 
13 */1 */1 
14 */1 */1 
15 fizz/1 buzz/1 
16 */1 */1 
..

Tic Tac Toe

Let’s have a look at a an example declarative programming in which we define winning moves and gradually fire the neuron corresponding to player moves:

Winning states for X player.
xa* xb* xc*: *: win-x*.
xd* xe* xf*: *: win-x*.
xg* xh* xi*: *: win-x*.
xa* xe* xi*: *: win-x*.
xg* xe* xc*: *: win-x*.
xa* xd* xg*: *: win-x*.
xb* xe* xh*: *: win-x*.
xc* xf* xi*: *: win-x*.

Winning states for O player.
oa* ob* oc*: *: win-o*.
od* oe* of*: *: win-o*.
og* oh* oi*: *: win-o*.
oa* oe* oi*: *: win-o*.
og* oe* oc*: *: win-o*.
oa* od* og*: *: win-o*.
ob* oe* oh*: *: win-o*.
oc* of* oi*: *: win-o*.

Set move in the format xa, ob, xc, etc

	a | b | c
	--+---+--
	d | e | f
	--+---+--
	g | h | i .

Play oc*.
Play xb*.
Play oe*.
Play xh*.
Play og*.

Evaluation:

00 oc/1 xb/1 oe/1 xh/1 og/1 
01 */3 
02 win-o/1

Graphical View

Sometimes I like to use graphical emulators to test some program components. The upsite of this system is that it already has a well documented graphical representation, it’s helpful for certain types of problems.

Dynamic Notes

My goal with this is for it to replace my usage of makefiles, but I noticed it makes for pretty neat introspective note-taking.

Something fun to explore

passive.
    key*: key*.
    hold-key*: hold-key*.
    locked-door*: locked-door*.

actions.
    take-key*: hold-key* use-key/2*. 
        take-key*; key*.
    drop-key*: key*. 
        drop-key*; hold-key*.
    use-key*: unlocked-door*.
        use-key*; hold-key* locked-door*.

There is a key* on the ground, you see a locked-door*.

--

00 key/1 locked-door/1 take-key/1
?- take-key*.
01 hold-key/1 use-key/1
?- use-key*.
02 unlocked-door/1

So yeah, I hope this introduces some folks to the concept, if you’d like to learn more, Minsky’s Finite & Infinite Machines dive deeper into the topic.

1 Like