REM BITNET Simulation - made by Terry Newton
REM coded for Microsoft QBasic, 9/23/97
 
REM Uses 6 (simulated) bytes to connect 8 inputs to 6 outputs
REM Rules and bit-labeling simulate control of a microcore walking
REM robot of the type invented and patented by Mark Tilden,
REM specifically the two-motor type using four neurons and
REM a circuit to reverse one of the motors (or rewire the net)
REM More information available at...
REM  http://www.golden.net/~amiller/Microcore.htm (Andrew Miller)
REM  http://www2.xtdl.com/~bushbo/beam/FAQ.html (Brian Bush)
REM  http://www.nc5.infi.net/~wtnewton/otherwld/ (my page)
 
REM Program interface...
REM  B - Bad - apply training to network
REM  I - Input - enter input bits (string of 0/1)
REM  T - Train - train with random inputs and defined rules
REM  R - Reset - reset network bits
REM  Q - Quit - exit program
REM All bits displayed bit 0 to bit 7 left-right
REM While training, displays input status (BadIn and RealBadIn),
REM learning signal (Good or Bad) and good/bad ratio. Press any
REM key to return to menu
 
REM preset variables
ins = 8           'number of input nodes
outs = 6          'number of output nodes
learnrate = .5    'odds of changing matrix bit, between 0 and 1
tallyfreq = 10    'update frequency for correct percentage
REM following Must be 0 or 1
tdist = 1         '1=weighted random training, 0=flat
Interactive = 1   'if 0, starts training immediately
restrict = 1      'if 1, restrict photoins when training
REM uninit'd vars assumed to start at 0
 
DIM OutNode(outs), InNode(ins)
DIM Abit(outs, ins)
DIM BadIn(ins), BadOut(outs)
DIM RealBadIn(ins), RealBadOut(outs)
DIM ActiveIn(ins), RestrictIn(ins)
 
REM specs are arbitrary - bits can mean anything
REM but if desired output is too specific it won't
REM converge - just a single-layer net
 
REM An imaginary walker-bot...
REM Input bits:       Output bits:
REM  0 = Feeler L      0 = Reverse (+ and - of front motor)
REM  1 = Dark on L     1 = Node 1 - rear left   (+ rear motor)
REM  2 = Photo L>R     2 = Node 2 - front left  (+ front motor)
REM  3 = Photo L=R     3 = Node 3 - rear right  (- rear motor)
REM  4 = Photo L<R     4 = Node 4 - front right (- front motor)
REM  5 = Dark on R     5 = Double effect
REM  6 = Feeler R
REM  7 = Feeler front
REM Rules:
REM  0,1,5,6,7 = bad input bits (feelers or dark )
REM  0,5 = bad output bits if no bad input (reverse, effect)
REM  7 = real bad input bit
REM  0 = good output bits if real bad input (should go in reverse)
REM  0,1,2,4,5,6,7 = input bits that must produce some output
 
REM Net penalized if bad out bits when no bad input bits
REM or if no good out bits with real bad input.
REM This simulation does NOT take into account real-world
REM action and effect, only that the generated move is
REM within the defined bounds of "correctness". You can
REM act as the "world" by manually applying bad signals.
 
' bad input bits...  (anything goes if any set)
' feelers or darkness on either side
DATA 1,1,0,0,0,1,1,1
' bad output if input is good...
' shouldn't be in reverse or large effect
DATA 1,0,0,0,0,1
' really bad input...
' front feeler touching
DATA 0,0,0,0,0,0,0,1
' outputs that should be set if realbadinput...
' should go in reverse
DATA 1,0,0,0,0,0
' input bits that should produce some output...
' all but L=R
DATA 1,1,1,0,1,1,1,1
' input bits that should have only one bit set (if restrict)
' L<R, L=R and L>R
DATA 0,0,1,1,1,0,0,0
 
FOR i = 1 TO ins: READ BadIn(i): NEXT i
FOR i = 1 TO outs: READ BadOut(i): NEXT i
FOR i = 1 TO ins: READ RealBadIn(i): NEXT i
FOR i = 1 TO outs: READ RealBadOut(i): NEXT i
FOR i = 1 TO ins: READ ActiveIn(i): NEXT i
FOR i = 1 TO ins: READ RestrictIn(i): NEXT i

RANDOMIZE TIMER
 
resetbits:
CLS
REM randomize link bits
FOR i = 1 TO outs: FOR j = 1 TO ins
 Abit(i, j) = INT(RND(1) * 2)
NEXT j: NEXT i
REM randomize input bits
FOR i = 1 TO ins
 InNode(i) = INT(RND(1) * 2)
NEXT i
 
cycle = 0: ratio = 0
TotalGood = 0: TotalBad = 0
IF Interactive = 0 THEN GOTO NonInteractive
 
mainloop:
 
REM Print preset rules and other details
LOCATE 2, 3: PRINT "Bit-Net Simulation"
LOCATE 3, 27: PRINT "Inputs       Outputs             The labeling and"
LOCATE 4, 27: PRINT "----------- ------------------   rules simulate the"
LOCATE 5, 27: PRINT "Feeler L   | Engage Reverse      control of a two"
LOCATE 6, 27: PRINT "Dark on L  | Node 1 rear left    motor Tilden-style"
LOCATE 7, 27: PRINT "Photo L>R  | Node 2 front left   walking robot with"
LOCATE 8, 27: PRINT "Photo L=R  | Node 3 rear right   a reverse circuit."
LOCATE 9, 27: PRINT "Photo L<R  | Node 4 front right  Press <T> to train"
LOCATE 10, 27: PRINT "Dark on R  | Increase Effect     the network with"
LOCATE 11, 27: PRINT "Feeler R    ------------------   random inputs."
LOCATE 12, 27: PRINT "Front Feeler"
LOCATE 14, 27: PRINT "Undesirable input bits ----";
FOR i = 1 TO ins: PRINT BadIn(i); : NEXT i
LOCATE 15, 27: PRINT "Bad outputs with good in --";
FOR i = 1 TO outs: PRINT BadOut(i); : NEXT i
LOCATE 16, 27: PRINT "Really bad input bits -----";
FOR i = 1 TO ins: PRINT RealBadIn(i); : NEXT i
LOCATE 17, 27: PRINT "Target out if really bad --";
FOR i = 1 TO outs: PRINT RealBadOut(i); : NEXT i
LOCATE 18, 27: PRINT "Inputs that should output -";
FOR i = 1 TO ins: PRINT ActiveIn(i); : NEXT i
 
REM draw network
LOCATE 4, 1
PRINT "  ΙΝΝΝΝ Inputs ΝΝΝΝΝ»"
PRINT "  Ί "; : FOR i = 1 TO ins
 IF InNode(i) = 1 THEN PRINT "* ";  ELSE PRINT "  ";
NEXT i: PRINT "Ί"
PRINT "  ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ"
PRINT
PRINT "  ΙΝΝ Connections ΝΝ»"
FOR i = 1 TO outs
 PRINT "  Ί ";
 FOR j = 1 TO ins
  IF Abit(i, j) = 1 THEN PRINT "* ";  ELSE PRINT "  ";
 NEXT j: PRINT "Ί"
NEXT i
PRINT "  ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ"
 
REM run network
PRINT
PRINT "    ΙΝΝ Outputs ΝΝ»"
PRINT "    Ί ";
FOR i = 1 TO outs: T = 0
 FOR j = 1 TO ins
  T = T + Abit(i, j) * InNode(j)
 NEXT j
 IF T > 0 THEN OutNode(i) = 1 ELSE OutNode(i) = 0
 IF OutNode(i) = 1 THEN PRINT "* ";  ELSE PRINT "  ";
NEXT i: PRINT "Ί"
PRINT "    ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΌ"
 
IF Interactive = 0 THEN
 cycle = cycle + 1
 IF cycle > tallyfreq THEN
  ratio = INT(TotalGood / (TotalGood + TotalBad) * 1000) / 1000
  TotalGood = 0: TotalBad = 0: cycle = 0
 END IF
 PRINT
 IF realbadins = 1 THEN
       PRINT "  RealBad  ";
 ELSE
  IF badins = 1 THEN
       PRINT "  BadIn    ";
  ELSE
       PRINT "           ";
  END IF
 END IF
 IF bad = 0 THEN
  PRINT "OK  ";
  TotalGood = TotalGood + 1
 ELSE
  PRINT "Bad ";
  TotalBad = TotalBad + 1
 END IF
 percent$ = STR$(INT(ratio * 100))
 PRINT percent$; "%             "
 RETURN
END IF
 
PRINT : PRINT " Bad Input Train Reset Quit..."
getin: a$ = LCASE$(INKEY$)
IF a$ = "b" THEN GOTO bad
IF a$ = "i" THEN GOTO inputnodes
IF a$ = "t" THEN Interactive = 0: GOTO NonInteractive
IF a$ = "r" THEN GOTO resetbits
IF a$ = "q" THEN SYSTEM
GOTO getin
 
inputnodes:
INPUT " Enter Input Bits (ex. 11001011) >", a$
a$ = LEFT$(a$ + "0000000000000000", ins)
FOR j = 1 TO ins
 IF MID$(a$, j, 1) = "1" THEN InNode(j) = 1
 IF MID$(a$, j, 1) = "0" THEN InNode(j) = 0
NEXT j
CLS
GOTO mainloop
 
bad:
FOR i = 1 TO outs: FOR j = 1 TO ins
 IF InNode(j) = 1 AND OutNode(i) = 0 AND RND(1) < learnrate THEN Abit(i, j) = 1
 IF InNode(j) = 1 AND OutNode(i) = 1 AND RND(1) < learnrate THEN Abit(i, j) = 0
NEXT j: NEXT i
IF Interactive = 0 THEN RETURN
GOTO mainloop
 
NonInteractive:
IF INKEY$ <> "" THEN Interactive = 1: GOTO mainloop
 
REM generate random input pattern...
dorandom:
FOR i = 1 TO ins
 IF tdist = 0 THEN
  InNode(i) = INT(RND(1) * 2)
 ELSE
  InNode(i) = INT(RND(1) * RND(1) * 2)
 END IF
NEXT i
 
REM check pattern (if restrict)
inputok = 1
IF restrict = 1 THEN
 T = 0
 FOR i = 1 TO ins
  IF RestrictIn(i) = 1 THEN T = T + InNode(i)
 NEXT i
 IF T <> 1 THEN inputok = 0
END IF
IF inputok = 0 THEN GOTO dorandom
 
REM run network...
GOSUB mainloop
 
REM evaluate results...
badins = 0
FOR i = 1 TO ins
 IF InNode(i) = 1 AND BadIn(i) = 1 THEN badins = 1
NEXT i
realbadins = 0
FOR i = 1 TO ins
 IF InNode(i) = 1 AND RealBadIn(i) = 1 THEN realbadins = 1
NEXT i
IF badins = 0 THEN
 bad = 0
 FOR i = 1 TO outs
  IF OutNode(i) = 1 AND BadOut(i) = 1 THEN bad = 1
 NEXT i
END IF
IF realbadins = 1 THEN
 bad = 1
 FOR i = 1 TO outs
  IF OutNode(i) = 1 AND RealBadOut(i) = 1 THEN bad = 0
 NEXT i
END IF
 
REM train against 0 out with activebits on input
activeinput = 0
activeoutput = 0
FOR i = 1 TO ins
 IF ActiveIn(i) = 1 AND InNode(i) = 1 THEN activeinput = 1
NEXT i
IF activeinput = 1 THEN
 FOR i = 1 TO outs
  IF OutNode(i) = 1 THEN activeoutput = 1
 NEXT i
 IF activeoutput = 0 THEN bad = 1
END IF
 
IF bad = 1 THEN GOSUB bad
GOTO NonInteractive
 
REM end of code
 

