This file contains a sample run of the Hopfield simulator.
Various properties of Hopfield networks are shown by example.

% # copy the files and compile it.
% cp /q1/ug/ics172ta/public/Hopfield/{Hopfield-sim.c,v1.mem} .
% scc Hopfield-sim.c -o Hopfield-sim 

% Hopfield-sim
Basic Net Simulator BSN.1, 17 Apr 89
Hopfield Net Simulator
SHoP> #
SHoP> # Don't forget - here's how to get help!
SHoP> #
SHoP> help
StepHop step the network synchronously
hop abrev for 'StepHop'
StorePats MFILE
  read the patterns in MFILE and set the T weights according to Hopfield's
  storage algorithm
store abrev for 'StorePats'
SetPat PAT_NO
    set the state of the network to that of pattern PAT_NO
set abrev for 'SetPat'
Flip FLIP_NO [SEED]
    select randomly FLIP_NO units, and flip their state. SEED is optional
    and used to be able to reproduce random changes.
f abrev for 'Flip'
ShowState print the state of the units in the network
sh abrev for 'ShowState'
ComparePat PAT_NO
    Compare the state of the network to that of pattern PAT_NO.
    places where they disagree are shown as a '*'
cp abrev for 'ComparePat'
ComparePats Compare the state of the network to that of every
    stored pattern.
cps abrev for 'ComparePats'
help print commands and their descriptions
h print commands and their descriptions
quit end the simulation
q end the simulation
source FILE
  read commands from FILE. They can be nested.
so abrev for 'source'
SHoP> #
SHoP> # First we bring into the program several (4) memory
SHoP> # patterns to work with from the test data file "v1.mem".
SHoP> # You can, of course, develop your own patterns (just
SHoP> # make sure they're the same size).  These patterns are
SHoP> # used by the program to compute the "T" matrix mentioned
SHoP> # in class and Hopfield's papers.  The T matrix stores the
SHoP> # interconnection weights of the network of units.
SHoP> #
SHoP> StorePats v1.mem
reading patterns
10010101011000001000011100000010001111101001101010 : pat 0
01100000110100100011000010000100011000000011111111 : pat 1
00100001011100110101010101011100101000101101010100 : pat 2
01000100101110011100010011011111010111111111001101 : pat 3
SHoP> #
SHoP> # Upon reading the patterns in, the simulator initializes
SHoP> # the states of the network units to 0.  The vector of
SHoP> # unit states is called the (system) state.  The Hopfield
SHoP> # algorithm will use the T matrix and the unit states
SHoP> # to compute new unit states via the performance rule.
SHoP> #
SHoP> ShowState
00000000000000000000000000000000000000000000000000
SHoP> #
SHoP> # Now we examine the stability of the network in a few
SHoP> # ways.  First, we set the state to match one
SHoP> # of the patterns (namely pattern number 0).  We then
SHoP> # verify that the state does not deviate from this
SHoP> # "memory" after performing the Hopfield update procedure
SHoP> # once.  This verifies that the pattern is stored in 
SHoP> # memory.  ComparePat gives the number of positions
SHoP> # which agree followed by the pattern. The StepHop 
SHoP> # command executes the performance rule once for each 
SHoP> # unit.
SHoP> #
SHoP> SetPat 0
SHoP> ShowState
10010101011000001000011100000010001111101001101010
SHoP> StepHop
SHoP> ShowState
10010101011000001000011100000010001111101001101010
SHoP> ComparePat 0
10010101011000001000011100000010001111101001101010 : 50
SHoP> #
SHoP> # Next we will examine the stability of a slightly perturbed
SHoP> # state.  We will flip two bits at random in the unit states
SHoP> # to see if the memory can be recovered (the second argument
SHoP> # to Flip is a seed for the random number generator - its
SHoP> # used explicitly here to ensure reproduceable results.  
SHoP> # Since the interconnection weights haven't changed, we should 
SHoP> # be able to reconstruct the original state matching the memory 
SHoP> # (i.e., if the perturbed state is close enough in the phase 
SHoP> # space).  The program will do this by following the phase space
SHoP> # gradient.  Asterisks are used to indicate mismatching pattern
SHoP> # positions.
SHoP> #
SHoP> Flip 2 1
SHoP> ShowState
10000101011000001000011100000010001111101001101000
SHoP> ComparePat 0
100*01010110000010000111000000100011111010011010*0 : 48
SHoP> StepHop
SHoP> ComparePat 0
10010101011000001000011100000010001111101001101010 : 50
SHoP> #
SHoP> # And we see above that the original memory has been
SHoP> # returned to normal by only one step of the Hopfield
SHoP> # procedure.
SHoP> #
SHoP> # Memory complements are also stable.  Let's flip
SHoP> # all bit positions and see if that is the case.
SHoP> #
SHoP> Flip 50 5
SHoP> ComparePat 0
************************************************** : 0 
SHoP> StepHop
SHoP> ShowState
01101010100111110111100011111101110000010110010101
SHoP> ComparePat 0
************************************************** : 0 
SHoP> #
SHoP> # Lets examine more closely the operation of memory
SHoP> # reconstruction.  We set the memory to hold pattern
SHoP> # number 1.
SHoP> #
SHoP> SetPat 1
SHoP> ShowState
01100000110100100011000010000100011000000011111111
SHoP> ComparePats
****0*0**1**00*0*0**0****0000**00*1****0*0*11*1*1* : 21 
01100000110100100011000010000100011000000011111111 : 50 
0*10000**1*1001*0**10*0***0**100**1000*0***1*1*1** : 27 
01*00*001**1*0******0*001*0**1**01********11**11*1 : 22 
SHoP> #
SHoP> # We now flip 5 bits to see if that can be recovered.
SHoP> #
SHoP> Flip 5 1
SHoP> ShowState
01110000110100100111000110000100011000000011101101
SHoP> ComparePat 1
011*0000110100100*11000*100001000110000000111*11*1 : 45 
SHoP> StepHop
SHoP> ComparePat 1
01100000110100100011000010000100011000000011111111 : 50 
SHoP> StepHop
SHoP> ComparePat 1
01100000110100100011000010000100011000000011111111 : 50 
SHoP> #
SHoP> # Obviously, the memory has been recovered despite
SHoP> # 5 random changes.  How about 10 (which is 20% loss)?
SHoP> #
SHoP> Flip 10 3
SHoP> ShowState
01000011110100100010000010100101111010000010011111
SHoP> ComparePats
**0*0**1*1**00*0*0*00****0*00*****1*1**0*0****1*1* : 19 
01*000**11010010001*000010*0010**110*000001**11111 : 40 
0**000*1*1*1001*0***0*0******10*1*10*0*0****01*1** : 23 
01000***1**1*0*****00*001****1*1*1**1*****1*0*11*1 : 22 
SHoP> StepHop
SHoP> ComparePats
******0********0*0*******0000***0********0**1*1*** : 11 
0110*0001*01**100011*0001000010*01*0000*001*1111*1 : 40 
0*10*00****1**1*0**1**0***0**10****000*******1*10* : 19 
01*0**0010*11*********001*0**1*1010****1**1***1101 : 24 
SHoP> StepHop
SHoP> ComparePats
********************************0*************1*** :  2 
0110*0*01*01**1*0*11*0001****10*01*0000*0*1**111*1 : 31 
0*10*0*****1**1101*1**0**1*1110****000***1**01*10* : 24 
01*0***010*11**1*1****0011*111*1010****1*11*0*1101 : 29 
SHoP> StepHop
SHoP> ComparePats
************************************************** :  0 
0110*0*01*01**1*0*11*0001****10**1*0000*0*1**1*1*1 : 29 
0*10*0*****1**1101*1**0**1*1110*1**000***1**01010* : 26 
01*0***010*11**1*1****0011*111*1*10****1*11*0**101 : 27 
SHoP> #
SHoP> # Note that the network has converged to the complement
SHoP> # of pattern number 0 instead of the starting state which
SHoP> # matched pattern 1 exactly.  Apparently, the 10 random 
SHoP> # changes created a state which was closer to that memory
SHoP> # than pattern 1 in the phase space.
SHoP> #
SHoP> # Finally, let's examine the system to find if any
SHoP> # spurious memories have been stored.  To check this
SHoP> # we set the state to match pattern 3 and flip 20 unit
SHoP> # states at random.  We then interate the Hopfield update
SHoP> # procedure until the state stabilizes (i.e., doesn't 
SHoP> # change).
SHoP> # 
SHoP> SetPat 3
SHoP> ShowState
01000100101110011100010011011111010111111111001101
SHoP> Flip 20 7
SHoP> ShowState
11101011100101011101010111111101000010111100011111
SHoP> ComparePat 3
0*0*01*010*11**11**001**1*011111*10**1***1110**1*1 : 30 
SHoP> ShowState
11101011100101011101010111111101000010111100011111
SHoP> StepHop
SHoP> ShowState
01001110101111011100110011111111110111111110000101
SHoP> StepHop
SHoP> ShowState
01001110101111011100110011111111010111111110000101
SHoP> StepHop
SHoP> ShowState
01001110101111011100110011111111010111111110001101
SHoP> StepHop
SHoP> ShowState
01001110101111011100110011111111010111111110001101
SHoP> #
SHoP> # At this point the state has stabilized.  Now
SHoP> # we compare the state with the 4 memory patterns
SHoP> # to see if it matches any.
SHoP> #
SHoP> ComparePats
**0**1****1***0*1*00*1********1*0**1111*1****01*** : 17 
01*0***01**1**********001****1**01********1***11*1 : 16 
0**0******11***1*10**10**1*111********1*11**0**10* : 19 
0100*1*010111*011100*10011*1111101011111111*001101 : 44 
SHoP> #
SHoP> # None of the input patterns match, so we have found
SHoP> # a spurious memory.
SHoP> #
SHoP> # We're done for now so let's ...
SHoP> #
SHoP> quit

%
