REM BITNET Simulation - made by Terry Newton REM coded for Microsoft QBasic, 9/28/97 REM X version - super fast convergence by not choosing REM bad moves when training... this modification REM applies the badmove rules even with manual training so REM some comments about it being general are no longer true REM Uses 7 (simulated) bytes to connect 8 inputs to 7 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 = 7 '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 LR 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 to train" LOCATE 10, 27: PRINT "Dark on R | Double effect the network with" LOCATE 11, 27: PRINT "Feeler R | Quadruple effect random inputs." LOCATE 12, 27: PRINT "Front Sw ------------------" 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 IF BadOut(i) = 1 AND BadIn(j) = 0 THEN Abit(i,j) = 0 ' cheat, 1 would be wrong 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