It will be convenient to use a vector to represent the activations and a matrix (a vector of vectors) to represent the weights in the network. These, along with the number of units in the network, which never changes after the network is created, can be global variables if you wish. Units are referenced by their indeces in the activation vector and the weight matrix. Since we will be using images as inputs to the network, it will be convenient to represent them, and the units in the network, in terms of x and y coordinates, even though these values are irrelevant to the behavior of the network.
init which takes the two dimensions
of the input images (width and height)
and initializes the
activation vector and the weight matrix accordingly
(the activation vector holds width * height values
and the weight matrix holds the square of that).
Initial activations are random (either -1 or +1) and initial weights
are 0.0.
Make sure that you create a separate
vector for each row of the weight matrix rather than re-using the
same vector for each row.
activation of a unit with a given index and return
or update the weight of a pair of units with given
indeces.
Note: the weights must be symmetric.
This means you can either maintain two copies of each weight (one from
unit i to unit j, the other from unit j
to unit i) or maintain only one copy but allow it to be
accessed from both directions.
print-net,
print-weights, and print-pattern,
which pretty-print network activation and weights and the values
in input patterns.
input-to-unit which calculates the input
to a given unit i.
This is just the sum of the products of the activations of the other
units and the weights connecting them to i.
The unit should not receive input from itself.
update1 which updates the activation
of a given unit i.
This simply calls input-to-unit, and if it returns a value greater
than
0.0, the activation is set to 1; otherwise it is set to -1.
update1 should return #t if the activation
has changed, #f if it hasn't.
update which, one a time, randomly
selects a unit from the network and updates it (using update1)
until it has selected twice
as many units are there are units in the network.
update should return #t if any unit changes
its activation in the process.
input-pattern which takes an input
pattern and activates the network with it.
An input pattern is a vector of -1s, +1s, and 0s.
The -1s and +1s are copied as activations in the corresponding
units of the network.
The 0s leave the activations of the corresponding units unspecified;
these units should have their activations set randomly to +1 or -1.
run which takes an input pattern,
activates the network with it (calling input-pattern)
and then repeatedly calls
update until it returns #f, that is, until
no units change their activation on a given set of updates.
learn1 which takes a training
pattern, an input pattern with only -1s and +1s, calculates the
outer product of the pattern vector with itself, and adds the values
in the outer product to the corresponding weights in the weight
matrix.
Note that for each pair of units, the product needs to be calculated
only once.
learn which takes a set of
training patterns, adjusts the weight matrix for each using
learn1, and then normalizes the weights by dividing
each by the number of training patterns.