Path: utzoo!attcan!uunet!wuarchive!sdd.hp.com!ucsd!ucbvax!ucdavis!csusac!csuchico.edu!num44 From: num44@ecst.csuchico.edu (Terral Jamison) Newsgroups: comp.ai.neural-nets Subject: Re: Simple C Source Message-ID: <1990Oct26.174332.2537@ecst.csuchico.edu> Date: 26 Oct 90 17:43:32 GMT References: <945@heurikon.heurikon.com> <1990Oct24.024710.7346@murdoch.acc.Virginia.EDU> Sender: news@ecst.csuchico.edu (USENET) Organization: California State University, Chico Lines: 459 In article <1990Oct24.024710.7346@murdoch.acc.Virginia.EDU> jxo2f@hagar6c.acc.Virginia.EDU (Jose X Orellana) writes: > > I am also interested in some source code for a neural net. > > Jose X. Orellana (working on M.S.) > Systems Engineering Dpt. > University of Virginia > /* This program simulates a constraint satisfaction neural network for choosing tic-tac-toe moves as described in Volume 2 of the PDP books. The network is presented a description of the board and chooses the best move subject to predefined constraints. It requires an EGA or CGA to display a Hinton diagram of the element activation levels. Author : Gary Andriotakis Compiler : Microsoft Quick C Date : 5 January 1989 */ #include #include #include #include #define N 67 #define GAIN 0.1 #define SCALE 1.0/16.0 static float w[N][N], bias[N], a[N], e[N]; main() { int j,mark = -1,converged; time_t t; #ifdef DEBUG initialize(a,w,bias); #endif #ifndef DEBUG if(!_setvideomode(_ERESCOLOR)) { printf("EGA required\n"); exit(0); } srand((int)time(&t)); drawboard(); do { putmarkers(&e[9],mark); initialize(); boxes(a,N); do { j = randint(N); update(j); boxes(a,j); converged = ((j < 9) && (a[j] > 0.9)); } while(!converged && !kbhit()); if(converged) mark = j; else mark = -1; } while(converged || (kbhit() && getch() != 27)); _displaycursor(_GCURSORON); _setvideomode(_DEFAULTMODE); #endif } update(j) int j; { int i; float net; net = 0.0; for(i = 0; i < N; i++) net += w[i][j]*a[i]; net += bias[j]; net *= GAIN; net += e[j]; if(net > 0.0) a[j] += net*(1.0 - a[j]); else a[j] += net*a[j]; } initialize() { int i,j; /* initialize to zero */ for(i = 0; i < N; i++) { a[i] = 0.0; bias[i] = 0.0; for(j = 0; j < N; j++) w[i][j] = 0.0; } for(i = 0; i < 9; i++) { /* inhibit responses from occupied squares */ w[i+9][i] = -8.0; w[i+18][i] = -8.0; /* mutual inhibition to insure only one response */ for(j = 0; j < 9; j++) w[i][j] = -2.; /* self excitation to excourage self growth */ w[i][i] = 2.; } /* empty line detectors */ for(i = 0; i < 3; i++) { w[i+9][27] = -1.0; w[i+18][27] = -1.0; w[27][i] = 1.0; w[i+12][28] = -1.0; w[i+21][28] = -1.0; w[28][i+3] = 1.0; w[i+15][29] = -1.0; w[i+24][29] = -1.0; w[29][i+6] = 1.0; w[9+4*i][30] = -1.0; w[18+4*i][30] = -1.0; w[30][4*i] = 1.0; w[11+2*i][31] = -1.0; w[20+2*i][31] = -1.0; w[31][2+2*i] = 1.0; w[9+3*i][32] = -1.0; w[18+3*i][32] = -1.0; w[32][3*i] = 1.0; w[10+3*i][33] = -1.0; w[19+3*i][33] = -1.0; w[33][1+3*i] = 1.0; w[11+3*i][34] = -1.0; w[20+3*i][34] = -1.0; w[34][2+3*i] = 1.0; } /* friendly doubleton detectors */ for(i = 0; i < 3; i++) { w[i+9][35] = 1.0; w[i+18][35] = -2.0; w[35][i] = 5.0; w[i+12][36] = 1.0; w[i+21][36] = -2.0; w[36][i+3] = 5.0; w[i+15][37] = 1.0; w[i+24][37] = -2.0; w[37][i+6] = 5.0; w[9+4*i][38] = 1.0; w[18+4*i][38] = -2.0; w[38][4*i] = 5.0; w[11+2*i][39] = 1.0; w[20+2*i][39] = -2.0; w[39][2+2*i] = 5.0; w[9+3*i][40] = 1.0; w[18+3*i][40] = -2.0; w[40][3*i] = 5.0; w[10+3*i][41] = 1.0; w[19+3*i][41] = -2.0; w[41][1+3*i] = 5.0; w[11+3*i][42] = 1.0; w[20+3*i][42] = -2.0; w[42][2+3*i] = 5.0; } /* enemy doubleton detectors */ for(i = 0; i < 3; i++) { w[i+9][43] = -2.0; w[i+18][43] = 1.0; w[43][i] = 1.0; w[i+12][44] = -2.0; w[i+21][44] = 1.0; w[44][i+3] = 1.0; w[i+15][45] = -2.0; w[i+24][45] = 1.0; w[45][i+6] = 1.0; w[9+4*i][46] = -2.0; w[18+4*i][46] = 1.0; w[46][4*i] = 1.0; w[11+2*i][47] = -2.0; w[20+2*i][47] = 1.0; w[47][2+2*i] = 1.0; w[9+3*i][48] = -2.0; w[18+3*i][48] = 1.0; w[48][3*i] = 1.0; w[10+3*i][49] = -2.0; w[19+3*i][49] = 1.0; w[49][1+3*i] = 1.0; w[11+3*i][50] = -2.0; w[20+3*i][50] = 1.0; w[50][2+3*i] = 1.0; } /* friendly singleton detectors */ for(i = 0; i < 3; i++) { w[i+9][51] = 1.0; w[i+18][51] = -2.0; w[51][i] = 2.0; w[i+12][52] = 1.0; w[i+21][52] = -2.0; w[52][i+3] = 2.0; w[i+15][53] = 1.0; w[i+24][53] = -2.0; w[53][i+6] = 2.0; w[9+4*i][54] = 1.0; w[18+4*i][54] = -2.0; w[54][4*i] = 2.0; w[11+2*i][55] = 1.0; w[20+2*i][55] = -2.0; w[55][2+2*i] = 2.0; w[9+3*i][56] = 1.0; w[18+3*i][56] = -2.0; w[56][3*i] = 2.0; w[10+3*i][57] = 1.0; w[19+3*i][57] = -2.0; w[57][1+3*i] = 2.0; w[11+3*i][58] = 1.0; w[20+3*i][58] = -2.0; w[58][2+3*i] = 2.0; } /* enemy singleton detectors */ for(i = 0; i < 3; i++) { w[i+9][59] = -2.0; w[i+18][59] = 1.0; w[59][i] = 2.0; w[i+12][60] = -2.0; w[i+21][60] = 1.0; w[60][i+3] = 2.0; w[i+15][61] = -2.0; w[i+24][61] = 1.0; w[61][i+6] = 2.0; w[9+4*i][62] = -2.0; w[18+4*i][62] = 1.0; w[62][4*i] = 2.0; w[11+2*i][63] = -2.0; w[20+2*i][63] = 1.0; w[63][2+2*i] = 2.0; w[9+3*i][64] = -2.0; w[18+3*i][64] = 1.0; w[64][3*i] = 2.0; w[10+3*i][65] = -2.0; w[19+3*i][65] = 1.0; w[65][1+3*i] = 2.0; w[11+3*i][66] = -2.0; w[20+3*i][66] = 1.0; w[66][2+3*i] = 2.0; } /* biases */ for(i = 0; i < 9; i++) bias[i] = 0.0625; for(i = 0; i < 8; i++) { bias[i+27] = 0.5; bias[i+35] = -1.5; bias[i+43] = -1.5; bias[i+51] = -0.5; bias[i+59] = -0.5; } for(i = 0; i < N; i++) { bias[i] *= SCALE; for(j = 0; j < N; j++) w[i][j] *= SCALE; } #ifdef DEBUG for(i = 0; i < N; i++) { for(j = 0; j < N; j++) printf("%2.0f",w[i][j]); printf("%7.2f\n",bias[i]); } #endif } randint(n) int n; /* return a random integer in the range 0 to n-1 */ { return(rand() % n); } #define MAXSIZE 5 boxes(a,n) float a[]; int n; /* Draw boxes proportional to activation levels (a) ala Hinton diagrams. * If n equals N then draw all N boxes otherwise draw only the nth. */ { int i,j,k,x,y,x0,y0; int size,count; x0 = 5; y0 = 40; count = -1; for(k = 0; k < 3; k++) { x = x0; y = y0; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { x += 12; count++; if(n == N || n == count) { size = a[count]*MAXSIZE; _setcolor(0); _rectangle(_GFILLINTERIOR, x-MAXSIZE,y-MAXSIZE,x+MAXSIZE,y+MAXSIZE); _setcolor(15); _rectangle(_GBORDER,x-size,y-size,x+size,y+size); } } x = x0; y += 12; } x0 += 48; } y0 = 40; for(k = 0; k < 5; k++) { x = x0; y = y0; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { x += 12; if(i != 1 || j != 1) { count++; if(n == N || n == count) { size = a[count]*MAXSIZE; _setcolor(0); _rectangle(_GFILLINTERIOR, x-MAXSIZE,y-MAXSIZE,x+MAXSIZE,y+MAXSIZE); _setcolor(15); _rectangle(_GBORDER,x-size,y-size,x+size,y+size); } } } x = x0; y += 12; } x0 += 48; } } drawboard() { static char board[5][6] = {32,179,32,179,32,0, 196,197,196,197,196,0, 32,179,32,179,32,0, 196,197,196,197,196,0, 32,179,32,179,32,0}; int i; _clearscreen(_GCLEARSCREEN); for(i = 0; i < 5; i++) { _settextposition(i+8,37); _outtext(&board[i][0]); } _settextposition(2,2); _outtext("move x o empty 2x 2o 1x 1o"); _settextposition(19,5); _outtext("Use arrow keys to move cursor."); _settextposition(20,5); _outtext("ENTER will change the marker under the cursor. x is program, o is opponent."); _settextposition(21,5); _outtext("ESCAPE will start network."); _settextposition(22,5); _outtext("After network is started, any key will stop."); _settextposition(23,5); _outtext("ESCAPE while network is running will exit program"); } putmarkers(b,x) float b[]; /* board description vector for input to network */ int x; /* location of programs new move */ /* * puts x's and o's on the board * x is the programs marker, * o is the opponents marker */ { int i,row,col; static int board[9] = {0}; int c, c1; /* place the programs new move on the board */ if(x > -1) { _settextposition(8+2*(x/3),37+2*(x%3)); _outtext("x"); board[x] = 1; } /* get the users input to the new board description */ row = 8; col = 37; i = 0; _settextposition(row,col); _displaycursor(_GCURSORON); while((c = getch()) != 27) /* continue until escape is hit */ { switch(c) { case 13: /* enter key */ { board[i] = (board[i]+1)%3; if(board[i] == 0) _outtext(" "); else if(board[i] == 1) _outtext("x"); else _outtext("o"); _settextposition(row,col); break; } case 0: { c1 = getch(); switch(c1) { case 72: /* up arrow */ { if(row > 8) { row -= 2; i -= 3; _settextposition(row,col); break; } } case 75: /* left arrow */ { if(col > 37) { col -= 2; i--; _settextposition(row,col); break; } } case 77: /* right arrow */ { if(col < 41) { col += 2; i++; _settextposition(row,col); break; } } case 80: /* down arrow */ { if(row < 12) { row += 2; i += 3; _settextposition(row,col); break; } } } } } } _displaycursor(_GCURSOROFF); for(i = 0; i < 9; i++) { switch(board[i]) { case 0: { b[i] = 0.0; b[i+9] = 0.0; break; } case 1: { b[i] = 1.0; b[i+9] = 0.0; break; } case 2: { b[i] = 0.0; b[i+9] = 1.0; break; } } } } case 2: { b[i] = 0.0; b[i+9] = 1.0; break; }