home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- **** ****
- **** lf.c ****
- **** ****
- **** Copyright (C) A. Dwelly and W.W. Armstrong, 1990. ****
- **** ****
- **** All rights reserved. ****
- **** ****
- **** This is an experimentors package, and demonstration of the adaptive ****
- **** logic network package based on work done by Prof. W. W. Armstrong ****
- **** and others in the Department of Computing Science, University of ****
- **** Alberta, and previous work at the Universite de Montreal, and at ****
- **** AT&T Bell Laboratories, Holmdel, N. J. The software demonstrates ****
- **** that networks consisting of many layers of linear threshold ****
- **** elements can indeed be effectively trained. ****
- **** ****
- **** License: ****
- **** A royalty-free license is granted for the use of this software for ****
- **** NON-COMMERCIAL PURPOSES ONLY. The software may be copied and ****
- **** modified provided this notice appears in its entirety and unchanged ****
- **** in all copies, whether changed or not. Persons modifying the code ****
- **** are requested to state the date, the changes made and who made them ****
- **** in the modification history. ****
- **** ****
- **** Warranty: ****
- **** No warranty of any kind is provided with this software. ****
- **** This software is not supported. Neither the authors, nor the ****
- **** University of Alberta, its officers, agents, servants or employees ****
- **** shall be liable or responsible in any way for any damage to ****
- **** property or direct personal or consequential injury of any nature ****
- **** whatsoever that may be suffered or sustained by any licensee, user ****
- **** or any other party as a consequence of the use or disposition of ****
- **** this software. ****
- **** ****
- **** Patent: ****
- **** The use of a digital circuit which transmits a signal indicating ****
- **** heuristic responsibility is protected by U. S. Patent 3,934,231 ****
- **** and others assigned to Dendronic Decisions Limited of Edmonton, ****
- **** W. W. Armstrong, President. ****
- **** ****
- **** A royalty-free license is granted for the use of this patent to ****
- **** run this software for NON-COMMERCIAL PURPOSES ONLY and the ****
- **** extension of this patent license to modified versions of this ****
- **** software is granted provided the purpose is NON-COMMERCIAL ONLY. ****
- **** ****
- **** Modification history: ****
- **** ****
- **** 90.09.05 Initial implementation, A.Dwelly ****
- **** 91.04.15 Port to PC and minor bug fixes, R. Manderscheid ****
- **** 91.05.20 Windows Port & Windows Extensions, M. Thomas ****
- **** ****
- *****************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <windows.h>
- #include "atree.h"
- #include "lf.h"
-
- #define Printf(str,fmt1,fmt2) sprintf(szBuffer,str,fmt1,fmt2)
-
- #define VERBOSITY 0
- #define CORRECTION_FACTOR 10000
- #define CODOMAIN (prog.dimensions - 1)
-
- prog_type prog;
-
- LPBIT_VEC domain_set;
- LPBIT_VEC codomain_set;
- LPATREE far * far *forest;
-
- extern FILE *yyin;
- extern int line_no;
- extern bool test_size_flag;
- extern bool train_size_flag;
- extern bool largest_flag;
- extern bool smallest_flag;
-
- void NEAR PASCAL
- prog_init()
- {
- atree_init();
- train_size_flag = FALSE;
- test_size_flag = FALSE;
- largest_flag = FALSE;
- smallest_flag = FALSE;
- prog.vote = 1;
- }
-
- void NEAR PASCAL
- read_prog(fp)
-
- FILE *fp;
-
- {
- yyin = fp;
- line_no = 1;
-
- if (yyparse() == -1)
- prog.error = TRUE;
- }
-
- BOOL NEAR PASCAL
- process_prog(HWND hwnd)
-
- {
- int i;
- int j;
- int nv;
- LPBIT_VEC far *concat;
- LPBIT_VEC bool_res;
-
- /*
- * When this function is called, the program has been read in, and
- * the relevant details have been stored in the global structure
- * 'prog'. We have some semantic processing to do, then the trees
- * can be trained as specified.
- */
-
- /* Quantize the dimensions */
-
- prog.width_sum = 0;
- domain_set = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(bit_vec) *
- prog.trainset_sz);
- MEMCHECK(domain_set);
- codomain_set = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(bit_vec) *
- prog.trainset_sz);
- MEMCHECK(codomain_set);
-
- for (i = 0; i < prog.dimensions; i++)
- {
- if (!largest_flag)
- {
- prog.largest[i] = prog.train_table[i][0];
-
- for (j = 1; j < prog.trainset_sz; j++)
- {
- if (prog.train_table[i][j] > prog.largest[i])
- {
- prog.largest[i] = prog.train_table[i][j];
- }
- }
-
- for (j = 1; j < prog.testset_sz; j++)
- {
- if (prog.test_table[i][j] > prog.largest[i])
- {
- prog.largest[i] = prog.test_table[i][j];
- }
- }
- }
- if (!smallest_flag)
- {
- prog.smallest[i] = prog.train_table[i][0];
-
- for (j = 1; j < prog.trainset_sz; j++)
- {
- if (prog.train_table[i][j] < prog.smallest[i])
- {
- prog.smallest[i] = prog.train_table[i][j];
- }
- }
-
- for (j = 1; j < prog.testset_sz; j++)
- {
- if (prog.test_table[i][j] < prog.smallest[i])
- {
- prog.smallest[i] = prog.test_table[i][j];
- }
- }
- }
-
- /* Check for constant columns */
-
- if (prog.largest[i] == prog.smallest[i])
- {
- char szBuffer[80];
- wsprintf(szBuffer,"Semantics error: column %d of function definition is a constant",i);
- MessageBox(hwnd, szBuffer, "LF ERROR", MB_OK);
- return(FALSE);
- }
-
- /* Correct largest value */
-
- if (prog.string_width[i] > 1)
- {
- prog.largest[i] += 1/(CORRECTION_FACTOR * prog.quant[i]);
- }
-
- /* prog.width_sum is the bit width of the domain of the function */
-
- if (i < CODOMAIN)
- {
- prog.width_sum += prog.string_width[i];
- }
-
- prog.quant_step[i] = (prog.largest[i] - prog.smallest[i])/
- prog.quant[i];
-
- if (prog.string_width[i] > 1)
- {
- prog.random_walk[i] = atree_rand_walk(prog.quant[i] + 1,
- prog.string_width[i],
- prog.walk_step[i]);
- }
- else
- {
- /* one of the columns is boolean */
-
- prog.random_walk[i] = NULL;
- }
- } /* for (i...) */
-
- /*
- * random_walk[i] covers the dimension i.
- * we now create the training set of bit vectors.
- */
-
- concat = (LPBIT_VEC far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned)(CODOMAIN) * sizeof(LPBIT_VEC));
- MEMCHECK(concat);
-
- for (i = 0; i < prog.trainset_sz; i++)
- {
- for (j = 0; j < CODOMAIN; j++)
- {
- if (prog.string_width[j] > 1)
- {
- nv = (int)floor((prog.train_table[j][i] - prog.smallest[j])/
- prog.quant_step[j]);
- concat[j] = prog.random_walk[j] + nv;
- }
- else
- {
- /* boolean data */
-
- bool_res = bv_create(1);
- bv_set(0,bool_res,prog.train_table[j][i] != 0);
- concat[j] = bool_res;
- }
- }
- domain_set[i] = *(bv_concat(CODOMAIN, concat));
- }
- /* And the codomain set */
- for (i = 0; i < prog.trainset_sz; i++)
- {
- if (prog.string_width[CODOMAIN] > 1)
- {
- nv = (int) floor((prog.train_table[CODOMAIN][i] -
- prog.smallest[CODOMAIN])/
- prog.quant_step[CODOMAIN]);
- codomain_set[i] = prog.random_walk[prog.dimensions -1][nv];
- }
- else
- {
- bool_res = bv_create(1);
- bv_set(0,bool_res,prog.train_table[CODOMAIN][i] != 0);
- codomain_set[i] = *bool_res;
- }
- }
-
-
- /*
- * For each tree (the number of bits in the ranges bit_string -
- * create a tree and train it.
- */
-
- forest = (LPATREE far * far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(LPATREE far *) *
- prog.string_width[CODOMAIN]);
- MEMCHECK(forest);
-
- for (i = 0; i < prog.string_width[CODOMAIN]; i++)
- {
- forest[i] = (LPATREE far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(LPATREE) * prog.vote);
- MEMCHECK(forest[i]);
- }
-
- /* parallelism here ? */
-
- for (i = 0; i < prog.string_width[CODOMAIN]; i++)
- {
- for (j = 0; j < prog.vote; j++)
- {
- forest[i][j] = atree_create(prog.width_sum,prog.tree_sz);
- (void) atree_train(forest[i][j],domain_set, codomain_set,
- i, prog.trainset_sz, prog.max_correct,
- prog.max_epochs, VERBOSITY);
- }
- }
-
- return(TRUE);
- }
-
-
- void NEAR PASCAL
- test_prog(HWND hwnd, LPSTR szOutFile)
-
- {
- /* Test the forest against the test set */
-
- int i;
- int j;
- int k;
- LPBIT_VEC result;
- LPBIT_VEC far *concat;
- int nv;
- LPBIT_VEC test_vec;
- int cl;
- int closest;
- int closest_bit_diff;
- int weight;
- LPBIT_VEC bool_res;
- int hOut; /* file Handle */
- char szBuffer[80];
-
- /* Create room for the results */
-
- result = (LPBIT_VEC )WinMem_Malloc(LMEM_MOVEABLE,(unsigned)sizeof(bit_vec)*prog.testset_sz);
- MEMCHECK(result);
-
- test_vec = (LPBIT_VEC )WinMem_Malloc(LMEM_MOVEABLE,(unsigned)sizeof(bit_vec)*prog.testset_sz);
- MEMCHECK(test_vec);
-
- for (i = 0; i < prog.testset_sz; i++)
- {
- result[i] = *(bv_create(prog.string_width[CODOMAIN]));
- }
-
- /* Create test set inputs */
-
- concat = (LPBIT_VEC far *) WinMem_Malloc(LMEM_MOVEABLE,(unsigned)(CODOMAIN) *
- sizeof(LPBIT_VEC ));
- MEMCHECK(concat);
- for (i = 0; i < prog.testset_sz; i++)
- {
- for (j = 0; j < CODOMAIN; j++)
- {
- if (prog.string_width[j] > 1)
- {
- nv = (int)floor((prog.test_table[j][i] - prog.smallest[j])/
- prog.quant_step[j]);
- prog.test_table_quant[j][i] = nv;
- concat[j] = prog.random_walk[j] + nv;
- }
- else
- {
- bool_res = bv_create(1);
- bv_set(0,bool_res,prog.test_table[j][i] != 0);
- concat[j] = bool_res;
- }
- }
- test_vec[i] = *(bv_concat(CODOMAIN, concat));
-
- nv = (int)floor((prog.test_table[CODOMAIN][i] -
- prog.smallest[CODOMAIN])/ prog.quant_step[CODOMAIN ]);
- prog.test_table_quant[CODOMAIN][i] = nv;
- }
-
- /* Now test each tree in turn */
-
- for (i = 0; i < prog.string_width[CODOMAIN]; i++)
- {
- for (j = 0; j < prog.testset_sz; j++)
- {
- weight = 0;
- for (k = 0; k < prog.vote; k++)
- {
- if (atree_eval(forest[i][k], test_vec + j))
- {
- weight++;
- }
- bv_set(i,result + j, weight > (prog.vote / 2));
- }
- }
- }
-
- /* Now calculate the nearest vector in the codomains random walk */
-
- /* open output file */
-
- if ((hOut = _lcreat(szOutFile, 0)) == -1)
- {
- wsprintf(szBuffer,"Cannot open %s ", szOutFile);
- MessageBox(hwnd, szBuffer, "LF File Error", MB_OK);
- return;
- }
-
- if (prog.string_width[CODOMAIN] > 1)
- {
- for (i = 0; i < prog.testset_sz; i++)
- {
- closest_bit_diff = prog.string_width[CODOMAIN];
- closest = 0;
- for (j = 0; j < prog.quant[CODOMAIN]; j++)
- {
- if ((cl = bv_diff(result + i,prog.random_walk[CODOMAIN] + j)) < closest_bit_diff)
- {
- closest_bit_diff = cl;
- closest = j;
- }
- }
-
- for (j = 0; j < prog.dimensions; j++)
- {
- Printf("%f %d \t",prog.test_table[j][i],prog.test_table_quant[j][i]);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- Printf("%f %d \r\n",(closest * prog.quant_step[CODOMAIN]) + prog.smallest[CODOMAIN],closest);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- }
- else
- {
- for (i = 0; i < prog.testset_sz; i++)
- {
- for (j = 0; j < prog.dimensions; j++)
- {
- Printf("%f %d \t",prog.test_table[j][i],prog.test_table_quant[j][i]);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- Printf("%f %d \r\n",(float) bv_extract(0,result + i),bv_extract(0,result + i));
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- }
-
- _lclose((int)hOut); /* close output file */
- }
-
-
- BOOL NEAR PASCAL
- main(HWND hwnd, LPSTR szInFile, LPSTR szOutFile)
-
- {
- FILE *fp;
- PSTR szFileName;
-
- /* Initialise the default values for the program */
-
- prog_init();
-
- if (szInFile == NULL)
- {
- MessageBox(hwnd, "No Input File Specified", "LF File Error", MB_OK);
- return(FALSE);
- }
- if (szOutFile == NULL)
- {
- MessageBox(hwnd, "No Output File Specified", "LF File Error", MB_OK);
- return(0);
- }
-
- /* Read the input file */
-
- lstrcpy((LPSTR)szFileName, szInFile); /* fopen needs near pointer */
-
- if ((fp = fopen(szFileName,"r")) == NULL)
- {
- char szBuffer[80];
- wsprintf(szBuffer,"Can't open %s ", szInFile);
- MessageBox(NULL, szBuffer, "LF File Error", MB_OK);
- return (FALSE);
- }
- else
- {
- read_prog(fp);
- (void) fclose(fp);
- }
-
- /* Train the trees as specified if there were no syntax errors */
-
- if (!prog.error)
- {
-
- MessageBox(hwnd, "Processing program", "LF", MB_OK);
- if(!process_prog(hwnd))
- {
- return(FALSE);
- }
- }
-
- /* Execute the trees as specified */
-
- if (!prog.error)
- {
- MessageBox(hwnd, "Testing program", "LF", MB_OK);
- test_prog(hwnd, szOutFile);
- }
-
- /* Finish */
-
- return(TRUE);
- }
-