home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- **** ****
- **** atree.c ****
- **** ****
- **** Copyright (C) A. Dwelly and W.W. Armstrong, 1990. ****
- **** ****
- **** All rights reserved. ****
- **** ****
- **** This is the program file for the "research" version 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.31 Port to Windows & Windows Extensions, M. Thomas ****
- **** ****
- *****************************************************************************/
-
- #pragma inline
-
- /*****************************************************************************
- **** ****
- **** Include Files ****
- **** ****
- *****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <windows.h>
- #include "atree.h"
-
- #define assert(exp)\
- {\
- if (!(exp))\
- {\
- char szBuffer[30]; \
- wsprintf(szBuffer, "%s, Line %d",\
- __FILE__, __LINE__);\
- MessageBox (NULL, szBuffer, "Assertion Failed",\
- MB_OK | MB_ICONSTOP);\
- }\
- }
-
- /*****************************************************************************
- **** ****
- **** Constants ****
- **** ****
- *****************************************************************************/
-
- #define AND 0
- #define RIGHT 1
- #define LEFT 2
- #define OR 3
-
- #define TRUE 1 /* As usual */
- #define FALSE 0
- #define UNEVALUATED 2 /* We complete the lattice of boolean functions */
- #define ATREE_ERROR -1 /* Don't want conflict with Windows.h ERROR */
- #define BOTTOM UNEVALUATED /* Synonyms */
- #define TOP ATREE_ERROR
- #define LEFTLEAF 0xF0 /* masks for leaf_flag and cmp_flag */
- #define RIGHTLEAF 0x0F
-
- #define MAX_RETRY 50 /* No. of retrys before an error in atree_rand_walk */
-
- /* Initialisation values */
-
- #define MAXSET 63
- #define ABOVEMID 32
- #define BELOWMID 31
- #define MINSET 0
-
- /* memory manager constants */
-
- #define SEGLENGTH 65536L /* 64K */
- #define NUMSEGS 64 /* can manage up to 4096K */
-
- /*
- * Tricky Macros
- */
-
- #define Printf(str,fmt) {\
- char string[] = str; \
- wsprintf(szBuffer,string,fmt);\
- }
-
- /* Public and private procedures */
-
- #define public
- #define private static
-
- /* Infinite loops - for EVER */
-
- #define EVER (;;)
-
- /* Printing out the boolean lattice */
-
- #define PRINTBOOL(b) if (b == TRUE) {Printf("1",0);} else if (b == FALSE)\
- {Printf("0",0);} else if (b == UNEVALUATED) {Printf("U",0);} else \
- if (b == ATREE_ERROR) {Printf("E",0);} else {Printf("?",0);}
-
- /* Verbosity */
-
- #define VERBOSE(level,s) if (verbosity >= level) {s ;}
-
- /* Byte size in bits.*/
-
- #define BYTE (sizeof(char)*8)
-
- /* Tree evaluation macros */
-
- #define EVAL(slf,side) ( (slf & (tree -> leaf_flag)) ? \
- ( (slf & (tree -> cmp_flag)) ? \
- !bv_extract(tree -> side.leaf,vec): \
- bv_extract(tree -> side.leaf,vec) ) : \
- atree_eval(tree -> side.child,vec) )
-
- #define LEFTEVAL (tree -> sig_left = EVAL(LEFTLEAF,left))
-
- #define RIGHTEVAL (tree -> sig_right = EVAL(RIGHTLEAF,right))
-
- /*
- * Types
- */
-
- typedef int bool; /*
- * Only TRUE, FALSE, UNEVALUATED or ATREE_ERROR
- * are used in these variables
- */
-
- /*
- * some static variables needed by the atree memory manager
- */
-
- /* HANDLE to each segment */
- static HANDLE seg[NUMSEGS];
-
- /* memory free in each segment */
- static WORD freemem[NUMSEGS];
-
- /*
- * Preliminary Private Procedure Declarations
- */
-
- private void NEAR PASCAL WinMem_Init();
- private LPATREE NEAR PASCAL build_tree(LPINT, char far *,int,int,LPATREE);
- private void NEAR PASCAL print_tree(LPATREE, int, int, int);
- private bool NEAR PASCAL train(LPATREE, LPBIT_VEC, bool);
- private void NEAR PASCAL adapt(LPATREE, LPBIT_VEC, bool);
- private char NEAR PASCAL node_function(LPATREE);
-
-
- /*
- * LibMain Procedure to initialize DLL
- */
-
- #pragma argsused
-
- long FAR PASCAL VerbosityWndProc(HWND, WORD, WORD, LONG);
-
- HANDLE hInst;
- char szVerbLine1[60];
- char szVerbLine2[60];
- short cyChar;
-
- int FAR PASCAL LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine)
-
- {
-
- WNDCLASS wndclass;
-
- hInst = hInstance;
-
- wndclass.style = CS_NOCLOSE;
- wndclass.lpfnWndProc = VerbosityWndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon(hInstance, "atreeico");
- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = "VERBOSITY";
-
- RegisterClass(&wndclass);
-
- if (wHeapSize > 0)
- UnlockData(0);
-
- return 1;
-
- }
-
- long FAR PASCAL VerbosityWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
- {
- static short cxChar, cxCaps;
- char szBuffer[10];
- HDC hdc;
- short i;
- PAINTSTRUCT ps;
- TEXTMETRIC tm;
-
- switch (message)
- {
- case WM_CREATE:
- hdc = GetDC(hwnd);
-
- GetTextMetrics(hdc, &tm);
- cxChar = tm.tmAveCharWidth;
- cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
- cyChar = tm.tmHeight + tm.tmExternalLeading ;
-
- ReleaseDC(hwnd,hdc);
- return 0;
-
- case WM_PAINT:
-
- hdc = BeginPaint(hwnd, &ps);
-
- TextOut (hdc, 5 * cxChar, cyChar * 6, szVerbLine1, lstrlen(szVerbLine1));
- TextOut (hdc, 5 * cxChar, cyChar * 7, szVerbLine2, lstrlen(szVerbLine2));
-
- EndPaint(hwnd, &ps);
-
- return 0;
-
- case WM_DESTROY:
- /* PostQuitMessage(0);*/
- return 0;
- }
-
- return DefWindowProc(hwnd,message, wParam, lParam);
- }
-
- /*****************************************************************************
- *****************************************************************************
- **** ****
- **** Public Routines ****
- **** ****
- *****************************************************************************
- *****************************************************************************/
-
-
- /*****************************************************************************
- **** ****
- **** void FAR PASCAL atree_init() ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Initialises various global variables, and makes an initial call to ****
- **** the random number seed routine. Checks to make sure Windows is in ****
- **** protect mode. ****
- **** ****
- *****************************************************************************/
-
- public void FAR PASCAL
- atree_init()
- {
- DWORD c;
-
- c = GetTickCount();
- (void) srand((int) c);
-
- c = GetWinFlags();
- if (!(c & WF_PMODE))
- {
- MessageBox(NULL, "Atree software cannot run\nin Windows Real Mode!",
- "Not in Protected Mode!", MB_OK | MB_ICONSTOP);
- exit(0);
- }
- }
-
- /*****************************************************************************
- **** ****
- **** LPBIT_VEC atree_rand_walk(num,width,p) ****
- **** ****
- **** int num; ****
- **** int width; ****
- **** int p; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Creates an array of _num_ binary vectors, of _width_ bits where ****
- **** each is _p_ bits away from its neighbours in Hamming space. Each ****
- **** vector is unique. ****
- **** This routine returns NULL if it's unable to find enough vectors. ****
- *****************************************************************************/
-
- #pragma warn -pia
-
- public LPBIT_VEC FAR PASCAL
- atree_rand_walk(num,width,p)
-
- int num;
- int width;
- int p;
-
- {
- /*
- * An initial vector is produced with random bits, and each subsequent
- * vector in the random walk just has _p_ bits flipped. In order to
- * guarantee that each vector is unique, it is checked against
- * a chained list of vectors of the same bit sum. If it is not already
- * in the chain it is appended to the end, or else the vector is discarded
- * and the process repeats itself.
- */
-
- LPBIT_VEC bv_set; /* An array of bit vectors */
- LPBIT_VEC pckd_vec; /* The packed unique ? vector */
- bool unique; /* Uniqueness flag set during testing */
- LPINT bit_sum_chain; /* Pointers to vectors of equivalent bit sums */
- LPINT next_vec; /* Chain array */
- LPSTR unpckd_vec; /* An unpacked vector */
- LPSTR this_vec; /* An unpacked vector */
- LPSTR mark_vec; /* TRUE where a bit has been flipped */
- int i;
- int j;
- int old_bit_sum; /* Last number of TRUE bits in vector */
- int bit_sum; /* Current number of TRUE bits in vector */
- int retrys; /* Number of attempts to find a unique vec */
- int victim; /* The bit just twiddled */
- int current_vec; /* Part of the chain */
-
- assert(num > 0);
- assert(width > 0);
- assert(p != 0);
- assert(p <= width);
-
- /* Assign space in memory */
-
- bv_set = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) num * sizeof(bit_vec));
- MEMCHECK(bv_set);
-
- bit_sum_chain = (LPINT) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) (width+1) * sizeof(int));
- MEMCHECK(bit_sum_chain);
-
- next_vec = (LPINT) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) num * sizeof(int));
- MEMCHECK(next_vec);
-
- unpckd_vec = (LPSTR) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) width * sizeof(char));
- MEMCHECK(unpckd_vec);
-
- this_vec = (LPSTR) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) width * sizeof(char));
- MEMCHECK(this_vec);
-
- mark_vec = (LPSTR) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) width * sizeof(char));
- MEMCHECK(mark_vec);
-
- /* Clear bit_sum_chain */
-
- for (i = 0; i <= width; i++)
- {
- bit_sum_chain[i] = -1;
- }
-
- /* Clear next_vec */
-
- for (i = 0; i < num; i++)
- {
- next_vec[i] = -1;
- }
-
- /* Create initial vector and bit sum */
-
- old_bit_sum = 0;
- for (i = 0; i < width; i++)
- {
- if (unpckd_vec[i] = RANDOM(2))
- {
- old_bit_sum++;
- }
- }
-
- bv_set[0] = *(bv_pack(unpckd_vec,width));
- bit_sum_chain[old_bit_sum] = 0;
-
- /* Random walk */
-
- for (i = 1; i < num; i++)
- {
-
- /* allow multitasking */
- Windows_Interrupt(1000);
-
- retrys = 0;
- unique = FALSE;
- while ((!unique) && (retrys < MAX_RETRY))
- {
- retrys++;
-
- /* Make a new vector */
-
- bit_sum = old_bit_sum;
- for (j = 0; j < width; j++)
- {
- this_vec[j] = unpckd_vec[j];
- mark_vec[j] = FALSE;
- }
-
- for (j = 0; j < p; j++)
- {
- do
- {
- victim = RANDOM(width);
- }
- while (mark_vec[victim]);
-
- mark_vec[victim] = TRUE;
- this_vec[victim] = !this_vec[victim];
- if (this_vec[victim] == FALSE)
- {
- bit_sum--;
- }
- else
- {
- bit_sum++;
- }
- }
-
- pckd_vec = bv_pack(this_vec,width);
-
- /* Compare it with the existing ones of equal bit length */
-
- if (bit_sum_chain[bit_sum] == -1)
- {
- /* There are no other vectors with this bit sum, so ... */
-
- unique = TRUE;
- bv_set[i] = *pckd_vec;
- bit_sum_chain[bit_sum] = i;
- next_vec[i] = -1;
- }
- else
- {
- current_vec = bit_sum_chain[bit_sum];
- for EVER /* We break out of here inside the loop */
- {
- if (bv_equal(&(bv_set[current_vec]),pckd_vec))
- {
- /* This vector already exists, unique = FALSE; */
- break;
- }
- else
- {
- if (next_vec[current_vec] == -1)
- {
- unique = TRUE;
- bv_set[i] = *pckd_vec;
- next_vec[current_vec] = i;
- next_vec[i] = -1;
- break;
- }
- else
- {
- current_vec = next_vec[current_vec];
- }
- }
- } /* for EVER */
- } /* if (bit_sum_chain...) */
- } /* while ((!unique... ))*/
-
- /*
- * If Unique is TRUE at this point, we have a unique
- * vector stored, we have to set up old_bit sum and unpckd_vec
- * for the next vector.
- * If unique is FALSE, we have tried to create a unique vector
- * MAX_RETRY times, and failed. We therefore signal an error.
- */
-
- if (unique)
- {
- for (j = 0; j < width; j++)
- {
- unpckd_vec[j] = this_vec[j];
- }
- old_bit_sum = bit_sum;
- }
- else
- {
- error("random walk failed");
- }
- } /* for */
-
-
- /* Free space in memory */
-
- WinMem_Free((LPSTR)bit_sum_chain);
- WinMem_Free((LPSTR)next_vec);
- WinMem_Free((LPSTR)unpckd_vec);
- WinMem_Free((LPSTR)this_vec);
- WinMem_Free((LPSTR)mark_vec);
-
- /* Return final vector */
-
- return(bv_set);
- }
-
- #pragma warn .pia
-
- /*****************************************************************************
- **** ****
- **** LPATREE atree_create(numvars,leaves) ****
- **** ****
- **** int numvars; ****
- **** int leaves; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Creates an Armstrong tree with _leaves_ number of leaves connected ****
- **** to _numvars_ variables and their complements. The number of ****
- **** leaves should probably be at least twice _numvars_. ****
- **** The node functions and the connections are picked at random. ****
- **** ****
- *****************************************************************************/
-
- public LPATREE FAR PASCAL
- atree_create(numvars,leaves)
-
- int numvars;
- int leaves;
-
- {
- LPATREE tree;
- LPINT connection;
- char far *complemented;
- char comp;
- int numvarscount;
- int a;
- int b;
- int tmpi;
- char tmpb;
- int i;
-
- assert(leaves > 2);
- assert(numvars > 0);
-
- /* Assign the memory to hold first part of tree, place as low in memory as possible */
-
- if ((leaves - 1) >= (SEGLENGTH / sizeof(atree)))
- tree = (LPATREE) GlobalWire(GlobalAlloc(GMEM_MOVEABLE,(DWORD)SEGLENGTH));
-
- else
- tree = (LPATREE) GlobalWire(GlobalAlloc(GMEM_MOVEABLE,((DWORD)leaves - 1) * sizeof(atree)));
-
- MEMCHECK(tree);
-
- /*
- * Create a list of bit inputs and shuffle, complemented inputs
- * are marked with a TRUE in the complemented array.
- */
-
- connection = (LPINT) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) sizeof(int) * leaves);
- MEMCHECK(connection);
- complemented = (char far *) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) sizeof(int) * leaves);
- MEMCHECK(complemented);
-
- comp = 0x00;
- for (i = 0; i < leaves; i++)
- {
- numvarscount = i % numvars;
- if (numvarscount == 0)
- {
- comp = ~(comp);
- }
- connection[i] = numvarscount;
- complemented[i] = comp;
- }
-
- /* Shuffle */
-
- for (i = 0; i < leaves; i++)
- {
- a = RANDOM(leaves);
- b = RANDOM(leaves);
- tmpi = connection[a];
- connection[a] = connection[b];
- connection[b] = tmpi;
- tmpb = complemented[a];
- complemented[a] = complemented[b];
- complemented[b] = tmpb;
- }
-
- /* Build tree */
-
- (void) build_tree(connection,complemented,0,leaves - 1,tree);
- /*
-
- /* Free memory */
-
- WinMem_Free((LPSTR)connection);
- WinMem_Free((LPSTR)complemented);
-
- /* Return results */
-
- return(tree);
- }
-
- /*****************************************************************************
- **** ****
- **** BOOL atree_eval(tree,vec) ****
- **** ****
- **** LPATREE tree; ****
- **** LPBIT_VEC vec; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Applies the _tree_ to the bit vector _vec_ and returns the result, ****
- **** 1 for true, and 0 for false. ****
- *****************************************************************************/
-
- #pragma warn -pia
-
- public BOOL FAR PASCAL
- atree_eval(tree,vec)
-
- LPATREE tree;
- LPBIT_VEC vec;
-
- {
- bool result;
-
- /*
- * We recursively work our way down the tree.
- * Since the && and || operators in C are lazy,
- * we automatically get the parsimony (ugly word) that we
- * want.
- */
-
- switch (tree -> function)
- {
- case AND:
- tree -> sig_right = UNEVALUATED;
- result = LEFTEVAL && RIGHTEVAL;
- break;
-
- case RIGHT:
- tree -> sig_left = UNEVALUATED;
- result = RIGHTEVAL;
- break;
-
- case LEFT:
- tree -> sig_right = UNEVALUATED;
- result = LEFTEVAL;
- break;
-
- case OR:
- tree -> sig_right = UNEVALUATED;
- result = LEFTEVAL || RIGHTEVAL;
- break;
- }
-
- return(result);
- }
-
- #pragma warn .pia
-
- /*****************************************************************************
- **** ****
- **** BOOL atree_train(tree,tset,correct_result,bit_col,tset_size, ****
- **** no_correct,epochs,verbosity) ****
- **** ****
- **** LPATREE tree; ****
- **** LPBIT_VEC tset; ****
- **** LPBIT_VEC correct_result; ****
- **** int bit_col; ****
- **** int tset_size; ****
- **** int no_correct; ****
- **** int epochs; ****
- **** int verbosity; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** This routine is the heart of the library. It takes an atree _tree_ ****
- **** to be trained, an array of input vectors _tset_, an array of ****
- **** vectors, _correct_result_ where each bit column holds a correct bit ****
- **** result for each vector in _tset_. [Note: Only a single vector is ****
- **** actually required here, but doing it this way make life convenient ****
- **** for training collections of trees for real numbers] An integer ****
- **** _bit_col_ denoting the column to be trained on. Another integer ****
- **** _test_size gives the size of both the _tset_ and _correct_result_ ****
- **** arrays. ****
- **** ****
- **** The _tree_ is trained until the number of vectors presented in ****
- **** _tset_ equals _epoch_ epochs, or the last presentation of the number****
- **** in an epoch had at least _no_correct_ presentations. ****
- **** The _verbosity_ is currently 0 or 1. ****
- **** The routine returns TRUE if it stopped because it succeeded ****
- **** _no_correct_ times. ****
- **** ****
- *****************************************************************************/
-
- public BOOL FAR PASCAL
- atree_train(tree,tset,correct_result,bit_col,tset_size,no_correct,
- epochs,verbosity)
-
- LPATREE tree;
- LPBIT_VEC tset;
- LPBIT_VEC correct_result;
- int bit_col;
- int tset_size;
- int no_correct;
- int epochs;
- int verbosity;
-
- {
- bool no_correct_flag = FALSE;
- int i;
- int j;
- int cor_this_epoch;
- int vec_num;
- LPBIT_VEC vec;
- char szBuff[60];
- HWND hwnd;
-
- /* For the specified number of epochs */
-
- VERBOSE(1, hwnd = CreateWindow("VERBOSITY", "atree Training Progress",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- 250, 180,
- NULL, NULL, hInst, NULL);
- lstrcpy(szVerbLine1, "Beginning Training...");
- lstrcpy(szVerbLine2, " ");
- ShowWindow(hwnd, SW_SHOW);
- UpdateWindow(hwnd)
- );
-
- for (i = 0; i < epochs; i++)
- {
- cor_this_epoch = 0;
-
- VERBOSE(1,wsprintf(szBuff,"Epoch : %d ",i));
-
- /* For the elements of the test set */
-
- for (j = 0; j < tset_size; j++)
- {
- /* Pick a random vector */
-
- vec_num = RANDOM(tset_size);
- vec = tset + vec_num;
-
- /* allow for multitasking */
- Windows_Interrupt(1000);
-
- /* Train the tree */
-
- if (train(tree,vec,(bool)bv_extract(bit_col,correct_result + vec_num)))
- {
- /* The tree succeeded */
-
- cor_this_epoch++;
- if (cor_this_epoch == no_correct)
- {
- no_correct_flag = TRUE;
- break; /* out of this epoch */
-
- } /* if (cor_this...) */
- } /* if (train..) */
- } /* for (j = ..) */
-
- VERBOSE(1,wsprintf(szVerbLine2,"Number correct was %d ",cor_this_epoch);
- lstrcpy(szVerbLine1, szBuff);
- ScrollWindow(hwnd, 0, -2 * cyChar, NULL, NULL);
- InvalidateRect(hwnd, NULL, FALSE);
- UpdateWindow(hwnd);
- );
-
- /* If no_correct_flag is TRUE here, its time to stop */
-
- if (no_correct_flag)
- {
- break; /* out of the epoch loop */
- }
-
- } /* for (i = ...) */
-
- /*VERBOSE(1, DestroyWindow(hwnd));*/
- return(no_correct_flag);
- }
-
- /*****************************************************************************
- **** ****
- **** (void) atree_print(tree,verbosity) ****
- **** ****
- **** LPATREE tree; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Prints out a tree for diagnostic and explanation purposes, the ****
- **** verbosity levels are 0 or above. Currently, the Windows ****
- **** implementation outputs to a file called atree.out in the current ****
- **** directory. ****
- *****************************************************************************/
-
- public void FAR PASCAL
- atree_print(tree,verbosity)
-
- LPATREE tree;
- int verbosity;
-
- {
- /*
- * This routine makes an call to the private
- * print tree routine that takes an extra paramater
- * controlling the indentation
- */
-
- int hOut; /* File Handle */
-
- if((hOut = _lcreat("atree.out", 0)) == -1)
- {
- MessageBox(NULL, "Cannot open ATREE.OUT", "atree_print", MB_OK);
- return;
- }
-
- print_tree(tree,0,verbosity, hOut);
- _lclose(hOut);
- }
-
-
- /*****************************************************************************
- **** ****
- **** void atree_free(tree) ****
- **** ****
- **** LPATREE tree; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Frees the memory used by _tree_ ****
- *****************************************************************************/
-
- public void FAR PASCAL
- atree_free(tree)
-
- LPATREE tree;
-
- {
-
- if (!(LEFTLEAF & (tree -> leaf_flag)))
- atree_free(tree -> left.child);
-
- if (!(RIGHTLEAF & (tree -> leaf_flag)))
- atree_free(tree -> right.child);
-
- if (tree -> seg_flag)
- GlobalFree(GlobalHandle(HIWORD(tree)));
-
- return;
- }
-
-
- /*****************************************************************************
- **** ****
- **** (int) atree_load(tree,name) ****
- **** ****
- **** LPATREE tree; ****
- **** LPSTR name; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Loads a previously stored tree from disk, errors signalled with a ****
- **** -1. ****
- *****************************************************************************/
-
- /*****************************************************************************
- **** ****
- **** (int) atree_store(tree,name) ****
- **** ****
- **** LPATREE tree; ****
- **** LPSTR name; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Writes the _tree_ to disk with filename _name_. Errors are ****
- **** signalled with a -1. ****
- *****************************************************************************/
-
- /*****************************************************************************
- **** ****
- **** LPBIT_VEC bv_create(length) ****
- **** ****
- **** int length; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Produces a vector of _length_ bits, each one of which has been set ****
- **** to 0 ****
- *****************************************************************************/
-
- public LPBIT_VEC FAR PASCAL
- bv_create(length)
-
- int length;
-
- {
- int i;
- LPBIT_VEC out_vec;
-
- assert(length > 0);
-
- out_vec = (LPBIT_VEC)WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned)sizeof(bit_vec));
- MEMCHECK(out_vec);
-
- out_vec -> len = length;
- out_vec -> bv = WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) (length + BYTE - 1) / BYTE);
- MEMCHECK(out_vec -> bv);
-
- for (i = 0; i < (length + BYTE - 1) / BYTE; i++)
- {
- *((out_vec -> bv) + i) = (char) 0;
- }
-
- return(out_vec);
- }
-
- /*****************************************************************************
- **** ****
- **** LPBIT_VEC bv_pack(unpacked,length) ****
- **** ****
- **** LPSTR unpacked; ****
- **** int length; ****
- **** ****
- **** This routine takes an array _arr_ of zero and one characters ****
- **** and returns a packed bit vector suitable for use with the other ****
- **** routines in this library. ****
- *****************************************************************************/
-
- public LPBIT_VEC FAR PASCAL
- bv_pack(unpacked,length)
-
- LPSTR unpacked;
- int length;
-
- {
- LPBIT_VEC out_vec;
- LPSTR out_ptr;
- int i;
- int j;
- int bitptr;
-
- /* Create the structure */
-
- out_vec = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(bit_vec));
- MEMCHECK(out_vec);
-
- out_vec -> len = length;
- out_vec -> bv = WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) (length + BYTE - 1) / BYTE);
- MEMCHECK(out_vec -> bv);
-
- /* Pack the vector */
-
- out_ptr = out_vec -> bv;
-
- bitptr = 0;
- for (i = 0; i < (length + BYTE - 1) / BYTE; i++)
- {
- *out_ptr = 0;
-
- for (j = 0; j < BYTE; j++)
- {
- if (bitptr < length)
- {
- *out_ptr |= (unpacked[bitptr] << j);
- bitptr++;
- }
- else
- {
- break;
- }
- }
- out_ptr++;
- }
-
- /* Return the vector */
-
- return(out_vec);
- }
-
- /*****************************************************************************
- **** ****
- **** int bv_diff(v1,v2) ****
- **** ****
- **** LPBIT_VEC v1; ****
- **** LPBIT_VEC v2; ****
- **** ****
- **** This function returns the number of bits that are unequal in the ****
- **** two vectors. They must be the same number of bits in each vector ****
- *****************************************************************************/
-
- public int FAR PASCAL
- bv_diff(v1,v2)
-
- LPBIT_VEC v1;
- LPBIT_VEC v2;
- {
- int diff = 0;
- int i;
-
- assert (v1 -> len == v2 -> len);
- for (i = 0; i < v1 -> len; i++)
- {
- if (bv_extract(i,v1) != bv_extract(i,v2))
- {
- diff++;
- }
- }
-
- return(diff);
- }
-
- /*****************************************************************************
- **** ****
- **** LPBIT_VEC bv_concat(n,vectors) ****
- **** ****
- **** int n; ****
- **** LPBIT_VEC *vectors; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Returns the bit vector which is the string concatenation of each ****
- **** bit vector in _vector_; _n_ is the number of elements in _vector_. ****
- *****************************************************************************/
-
- public LPBIT_VEC FAR PASCAL
- bv_concat(n,vector)
-
- int n;
- LPBIT_VEC FAR *vector;
-
- {
- int size;
- LPBIT_VEC out_vec;
- LPSTR str;
- int i;
- int j;
- int count;
-
- /* Work out how big the new vector will be */
-
- size = 0;
- for (i = 0; i < n; i++)
- {
- size += vector[i] -> len;
- }
-
- /* Unpack the input vectors */
-
- str = WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) size);
- MEMCHECK(str);
-
- count = 0;
- for (i = 0; i < n; i++)
- {
- for (j = 0; j < vector[i] -> len; j++)
- {
- str[count] = bv_extract(j,vector[i]);
- count++;
- }
- }
-
- out_vec = bv_pack(str,size);
-
- WinMem_Free(str);
-
- return(out_vec);
- }
-
-
- /*****************************************************************************
- **** ****
- **** LPBIT_VEC bv_copy(vector) ****
- **** ****
- **** LPBIT_VEC vector; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Returns a copy of the bit vector _vector_. ****
- *****************************************************************************/
-
- public LPBIT_VEC FAR PASCAL
- bv_copy(vector)
-
- LPBIT_VEC vector;
- {
- LPBIT_VEC out_vec;
- int i;
-
- /* Work out how big the new vector will be */
-
- out_vec = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(bit_vec));
- MEMCHECK(out_vec);
-
- out_vec -> len = vector -> len;
- out_vec -> bv = WinMem_Malloc(LMEM_MOVEABLE | LMEM_ZEROINIT, (unsigned) (vector -> len + BYTE - 1) / BYTE);
- MEMCHECK(out_vec -> bv);
-
- for (i = 0; i < (vector -> len + BYTE - 1) / BYTE; i++)
- {
- out_vec -> bv[i] = vector -> bv[i];
- }
-
- return(out_vec);
- }
-
- /*****************************************************************************
- **** ****
- **** void bv_set(n,vec,bit) ****
- **** ****
- **** int n; ****
- **** LPBIT_VEC vec; ****
- **** BOOL bit; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Sets bit _n_ in _vec_ to have the value in _bit_. ****
- *****************************************************************************/
-
- public void FAR PASCAL
- bv_set(n,vec,bit)
-
- int n;
- LPBIT_VEC vec;
- BOOL bit;
-
- {
- char mask;
- LPSTR b;
- assert(n < vec -> len);
-
- mask = 0x1;
- b = (vec -> bv) + ((int) (n / BYTE));
-
- if (bit)
- {
- *b |= (mask << (n % BYTE));
- }
- else
- {
- *b &= ~(mask << (n % BYTE));
- }
- }
-
- /*****************************************************************************
- **** ****
- **** BOOL bv_extract(n,vec) ****
- **** ****
- **** int n; ****
- **** LPBIT_VEC vec; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Returns the _n_th bit of _vec_. ****
- *****************************************************************************/
-
- public BOOL FAR PASCAL
- bv_extract(n,vec)
-
- int n;
- LPBIT_VEC vec;
-
- {
- register int mask = 0x1;
-
- assert(n < vec -> len);
- return(((*((vec -> bv) + ((int) (n / BYTE)))) & (mask << (n % BYTE))) != 0);
- }
-
- /*****************************************************************************
- **** ****
- **** void bv_print(stream, vector) ****
- **** ****
- **** FILE *vector; ****
- **** LPBIT_VEC vector; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Prints out _vector_ in binary, MSB is the rightmost. ****
- *****************************************************************************/
-
- public void FAR PASCAL
- bv_print(stream, vector)
-
- FILE *stream;
- LPBIT_VEC vector;
-
- {
- LPSTR ptr; /* Points to the current char */
- char mask;
- int bits; /* Counts the number of bits output */
- int i;
-
- bits = 0;
- for (ptr = (vector -> bv);
- (ptr != (vector -> bv) + (int) ((vector -> len / BYTE) + 1)) &&
- (bits < vector -> len); ptr++)
-
- {
- mask = 0x1;
- for (i = 0; i < BYTE; i++)
- {
- if ((*ptr & mask) != 0)
- {
- (void) fprintf(stream, "1");
- }
- else
- {
- (void) fprintf(stream, "0");
- }
- bits++;
- if (bits == vector -> len)
- {
- break;
- }
- mask <<= 1;
- }
- }
- }
-
- /*****************************************************************************
- **** ****
- **** void bv_free(vector) ****
- **** ****
- **** LPBIT_VEC vector; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Frees the memory used by _vector_ ****
- *****************************************************************************/
-
- public void FAR PASCAL
- bv_free(vector)
-
- LPBIT_VEC vector;
-
- {
- WinMem_Free(vector -> bv);
- WinMem_Free((LPSTR) vector);
- }
-
- /*****************************************************************************
- **** ****
- **** BOOL bv_equal(v1,v2) ****
- **** ****
- **** LPBIT_VEC v1; ****
- **** LPBIT_VEC v2; ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Returns TRUE if each bit in v1 and v2 have the same value in the ****
- **** same position. It returns FALSE otherwise. ****
- *****************************************************************************/
-
- public BOOL FAR PASCAL
- bv_equal(v1,v2)
-
- LPBIT_VEC v1;
- LPBIT_VEC v2;
-
- {
- bool eq;
- int i;
-
- eq = TRUE;
-
- if (v1 -> len != v2 -> len)
- {
- eq = FALSE;
- }
- else
- {
- for (i = 0; i < (v1 -> len + BYTE - 1) / BYTE; i++)
- {
- if (v1 -> bv[i] != v2 -> bv[i])
- {
- eq = FALSE;
- break;
- }
- }
- }
-
- return(eq);
- }
-
- /*****************************************************************************
- **** ****
- **** void FAR PASCAL Windows_Interrupt(cElapsed) ****
- **** ****
- **** DWORD cElapsed ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Allows Windows to access other applications that may be running ****
- **** A call to PeekMessage accomplishes this, and we process all calling ****
- **** window messages. Will only call PeekMessage if _cElapsed_ time ****
- **** has passed since the last call to Windows_Interrupt. ****
- **** ****
- *****************************************************************************/
-
- public void FAR PASCAL
- Windows_Interrupt(cElapsed)
-
- DWORD cElapsed;
-
- {
- static cTick = 0; /* number of ticks since first called */
- MSG msg; /* Windows message structure */
-
- if ((GetTickCount() - cTick) > cElapsed)
- {
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- cTick = GetTickCount();
- }
- }
-
- /*****************************************************************************
- **** ****
- **** LPSTR FAR PASCAL WinMem_Malloc(wFlags, wBytes) ****
- **** ****
- **** WORD wFlags ****
- **** WORD wBytes ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Allocates _wBytes_ bytes of memory in a dynamically allocated ****
- **** segment. _wBytes_ cannot be greater than SEGLENGTH. wFlags can be ****
- **** any of the local memory allocation flags defined in the Windows ****
- **** Programmer's Reference, usually LMEM_MOVEABLE. ****
- **** Returns a valid pointer if successful, NULL if not. ****
- **** ****
- **** ****
- *****************************************************************************/
-
- public LPSTR FAR PASCAL WinMem_Malloc(WORD wFlags, WORD wBytes)
- {
- int offset;
- int i,j;
- BOOL found;
- HANDLE hmem;
- LPSTR lp;
- PSTR p;
- LONG lSize;
- WORD wSeg;
- static BOOL bFirst = TRUE;
-
- if (bFirst)
- {
- bFirst = FALSE;
- WinMem_Init();
- }
-
- if ((long)wBytes > (SEGLENGTH - 16)) return(NULL);
-
- for (i = 0; i < NUMSEGS; i++)
- {
- if (seg[i] == NULL)
- {
-
- /**** Get global segment, initialize local heap ****/
-
- hmem = GlobalAlloc(GMEM_MOVEABLE, SEGLENGTH);
- if (!hmem) return(NULL);
- lp = GlobalWire(hmem);
- wSeg = HIWORD(lp);
- seg[i] = hmem;
- lSize = GlobalSize(hmem) - 16; /*
- * reserve 16 bytes for local
- * heap initialization
- */
- if (lSize > (SEGLENGTH - 16)) lSize = SEGLENGTH - 16;
- if (!LocalInit(wSeg,0,lSize)) return(NULL);
- freemem[i] = (WORD) lSize;
- GlobalUnlock(hmem); /* from LocalInit */
- GlobalUnWire(hmem);
- }
- if (freemem[i] > wBytes)
- {
- lp = GlobalWire(seg[i]);
- if (!lp) return(NULL);
- wSeg = HIWORD(lp);
-
- asm { push ds
- mov ax, wSeg
- mov ds, ax
- }
-
- hmem = LocalAlloc(wFlags, wBytes);
-
- asm { pop ds
- }
-
- GlobalUnWire(seg[i]);
-
- if (hmem)
- {
- j = i;
- break;
- }
- }
- }
-
- if (!hmem) return(NULL);
-
- lp = GlobalWire (seg[j]); /*
- * move to low memory, will be
- * unwired in WinMem_Free
- */
- if (!lp) return(NULL);
- wSeg = HIWORD(lp);
-
- asm { push ds
- mov ax, wSeg
- mov ds, ax
- }
-
- i = LocalSize(hmem);
- p = LocalLock (hmem);
-
- asm { pop ds
- }
-
- freemem[j] -= i;
-
- if (!p) return(NULL);
- else return (LPSTR)MAKELONG (p, wSeg);
- }
-
- /*****************************************************************************
- **** ****
- **** LPSTR FAR PASCAL WinMem_Free(lpfree) ****
- **** ****
- **** LPSTR lpfree ****
- **** ****
- **** Synopsis: ****
- **** ****
- **** Frees the block of memory in a dynamically allocated segment ****
- **** pointed to by _lpFree_. ****
- **** Returns NULL if successful, lpfree if not ****
- **** ****
- **** ****
- *****************************************************************************/
-
- public LPSTR FAR PASCAL WinMem_Free(LPSTR lpfree)
- {
- HANDLE hmem, hseg;
- LPSTR lp;
- WORD wSeg;
- int i,j;
-
- wSeg = HIWORD(lpfree);
- hseg = GlobalHandle(wSeg);
-
- j = -1;
- for (i = 0; i < NUMSEGS; i++)
- {
- if (seg[i] == hseg)
- {
- j = i;
- break;
- }
- }
- if (j == -1) return(lpfree);
-
- lp = GlobalWire(hseg);
- if (!lp) goto FAIL;
-
- asm { push ds
- mov ax, wSeg
- mov ds, ax
- }
-
- hmem = LocalHandle(LOWORD(lpfree));
- if (!hmem)
- {
- asm { pop ds
- }
- goto FAIL;
- }
-
- i = LocalSize(hmem);
-
- if (!LocalUnlock (hmem))
- {
- hmem = LocalFree(hmem); /*returns NULL if successful*/
- if (hmem)
- {
- asm { pop ds
- }
- goto FAIL;
- }
- }
- else
- {
- asm { pop ds
- }
- goto FAIL;
- }
-
- asm { pop ds
- }
-
- freemem[j] += i;
-
- GlobalUnWire(hseg);
- if ((GlobalUnWire(hseg)) && (freemem[j] == (SEGLENGTH - 16))) /* TRUE if lock count at 0 */
- {
- GlobalFree(hseg);
- seg[j] = NULL;
- freemem[j] = 0;
- }
-
- return(NULL);
- FAIL:
- return(lpfree);
- }
-
- /*****************************************************************************
- *****************************************************************************
- **** ****
- **** Private Routines ****
- **** ****
- *****************************************************************************
- *****************************************************************************/
-
- /*
- * void FAR PASCAL WinMem_Init()
- *
- * internal routine to initialize memory manager
- * called automatically as needed
- */
-
- private void NEAR PASCAL WinMem_Init()
- {
- int i;
-
- for (i = 0; i < NUMSEGS; i++)
- {
- seg[i] = NULL;
- freemem[i] = 0;
- }
- }
-
-
- /*
- * This routine recursively creates a random tree in the previously allocated
- * space starting at _tree_. It returns a pointer giving the next available
- * space for other calls.
- */
-
- private LPATREE NEAR PASCAL
- build_tree(connection,complemented,start,end,tree)
-
- LPINT connection;
- char far *complemented;
- int start;
- int end;
- LPATREE tree;
-
- {
- int mid;
- LPATREE next_node;
- LPATREE right_descendant;
-
- /* Allocate this node */
-
- tree -> function = RANDOM(4);
- tree -> sig_left = UNEVALUATED;
- tree -> sig_right = UNEVALUATED;
- if (!LOWORD(tree)) /* this node starts a segment */
- tree -> seg_flag = TRUE;
- else
- tree -> seg_flag = FALSE;
-
- switch (tree -> function)
- {
- case AND:
- tree -> cnt_10 = BELOWMID;
- tree -> cnt_01 = BELOWMID;
- break;
-
- case RIGHT:
- tree -> cnt_10 = BELOWMID;
- tree -> cnt_01 = ABOVEMID;
- break;
-
- case LEFT:
- tree -> cnt_10 = ABOVEMID;
- tree -> cnt_01 = BELOWMID;
- break;
-
- case OR:
- tree -> cnt_10 = ABOVEMID;
- tree -> cnt_01 = ABOVEMID;
- break;
- }
-
- /* Are we at a leaf ?? */
-
- if (end - start < 3)
- {
- /* This is a leaf */
-
- if (end - start == 1)
- {
- tree -> /*left*/ leaf_flag = LEFTLEAF;
- tree -> /*right*/ leaf_flag |= RIGHTLEAF;
-
- tree -> /*left*/ cmp_flag = (LEFTLEAF & complemented[start]);
- tree -> left.leaf = connection[start];
- tree -> /*right*/ cmp_flag |= (RIGHTLEAF & complemented[end]);
- tree -> right.leaf = connection[end];
-
- next_node = tree + 1;
-
- }
- else
- {
- assert(end - start == 2);
-
- tree -> /*left*/ leaf_flag = LEFTLEAF;
- tree -> /*right*/ leaf_flag &= ~(RIGHTLEAF);
- tree -> /*left*/ cmp_flag = (LEFTLEAF & complemented[start]);
- tree -> left.leaf = connection[start];
-
- tree -> right.child = tree + 1;
-
- /* segment boundary check */
-
- if (!LOWORD(tree -> right.child)) /* crossed segment bound */
- {
- DWORD nodes = end - start;
-
- if (nodes >= (SEGLENGTH / sizeof(atree)))
- tree -> right.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE, SEGLENGTH));
- else
-
- tree -> right.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE, nodes * sizeof(atree)));
- MEMCHECK(tree -> right.child);
- }
-
- next_node = build_tree(connection,complemented,start+1,end,tree -> right.child);
-
- }
- }
- else
- {
- /* This is a not a leaf (ie, a node) */
-
- tree -> leaf_flag = FALSE;
- tree -> cmp_flag = FALSE;
-
- /* Create left descendants */
-
- mid = start + ((end - start)/2);
- tree -> left.child = tree + 1;
-
- /* segment boundary check */
-
- if (!LOWORD(tree -> left.child)) /* crossed segment bound */
- {
- DWORD nodes = mid - start;
-
- if (nodes >= (SEGLENGTH / sizeof(atree)))
- tree -> left.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE,SEGLENGTH));
- else
- tree -> left.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE,nodes * sizeof(atree)));
-
- MEMCHECK(tree -> left.child);
- }
-
- right_descendant = build_tree(connection,complemented,start,mid,tree -> left.child);
-
- /* Create right descendants and return next available node */
-
- tree -> right.child = right_descendant;
-
- /* segment boundary check */
-
- if (!LOWORD(tree -> right.child)) /* crossed segment bound */
- {
- DWORD nodes = end - mid;
-
- if (nodes >= (SEGLENGTH / sizeof(atree)))
- tree -> right.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE,SEGLENGTH));
- else
- tree -> right.child = (LPATREE) GlobalWire(GlobalAlloc(
- GMEM_MOVEABLE, nodes * sizeof(atree)));
-
- MEMCHECK(tree -> right.child);
- }
-
- next_node = build_tree(connection,complemented,mid+1,end,right_descendant);
- }
-
- return(next_node);
- }
-
- /*
- * print_tree routine prints out an atree to the
- * file pointed to by _fp_
- */
-
- private void NEAR PASCAL
- print_tree(tree,indent,verbosity,hOut)
-
- LPATREE tree;
- int indent;
- int verbosity;
- int hOut;
-
- {
- int i;
- char szBuffer[80];
-
- if (RIGHTLEAF & (tree -> leaf_flag))
- {
- for (i = 0; i < indent + 3; i++)
- {
- Printf(" ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- if (RIGHTLEAF & (tree -> cmp_flag))
- {
- Printf("Leaf : !%d ",tree -> right.leaf);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- else
- {
- Printf("Leaf : %d ",tree -> right.leaf);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- VERBOSE(1,Printf(",",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- PRINTBOOL(tree -> sig_right);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer)));
-
- Printf("\r\n",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- else
- {
- print_tree(tree -> right.child,indent + 3,verbosity,hOut);
- }
-
- for (i = 0; i < indent; i++)
- {
- Printf(" ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
-
- switch (tree -> function)
- {
- case AND:
- Printf("AND ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- break;
-
- case RIGHT:
- Printf("RIGHT ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- break;
-
- case LEFT:
- Printf("LEFT ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- break;
-
- case OR:
- Printf("OR ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- break;
- }
-
- VERBOSE(1, Printf("rsp = ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- Printf(",r=",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- PRINTBOOL(tree -> sig_right);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- Printf(",l=",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- PRINTBOOL(tree -> sig_left);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer)));
-
- Printf("\r\n",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
-
- if (LEFTLEAF & (tree -> leaf_flag))
- {
- for (i = 0; i < indent + 3; i++)
- {
- Printf(" ",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- if (LEFTLEAF & (tree -> cmp_flag))
- {
- Printf("Leaf : !%d ",tree -> left.leaf);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- else
- {
- Printf("Leaf : %d ",tree -> left.leaf);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
-
- VERBOSE(1,Printf(",",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- PRINTBOOL(tree -> sig_left);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer)));
-
- Printf("\r\n",0);
- _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
- }
- else
- {
- print_tree(tree -> left.child,indent + 3,verbosity, hOut);
- }
- }
-
- /*
- * bool train(tree,vec,result)
- *
- * LPATREE tree;
- * LPBITVEC vec;
- * bool result;
- *
- * This routine is actually responsible for the training of a tree for a
- * single input vector and result. If the tree gets the correct result
- * before the adaptation step occurs, the routine returns TRUE, otherwise,
- * false.
- */
-
- private bool NEAR PASCAL
- train(tree,vec,result)
-
- LPATREE tree;
- LPBIT_VEC vec;
- bool result;
-
- {
- bool correct;
-
- /* What does the tree currently think ?*/
-
- correct = (bool)atree_eval(tree,vec) == result;
-
- /* Adapt the tree */
-
- adapt(tree,vec,result);
-
- /* Did the tree get it right ? */
-
- correct = (bool)atree_eval(tree,vec) == result;
-
- /* If not, try again ! */
-
- if (!correct)
- {
- adapt(tree,vec,result);
- }
-
- return(correct);
- }
-
- /*
- * adapt(tree,vec,result)
- *
- * LPATREE tree;
- * LPBIT_VEC vec;
- * bool result;
- *
- */
-
- private void NEAR PASCAL
- adapt(tree,vec,result)
-
- LPATREE tree;
- LPBIT_VEC vec;
- bool result;
-
- {
-
- /*
- * INCR and DECR implement bounded counters, remembering that TRUE == 1,
- * how much should be added to t when t == MAXSET ?
- */
-
- #define INCR(t) t += (t != MAXSET)
- #define DECR(t) t -= (t != MINSET)
-
- /* If the left child is unevaluated, evaluate it */
-
- if (tree -> sig_left == UNEVALUATED)
- {
- LEFTEVAL;
- }
-
- /* If the right child is unevaluated, evaluate it */
-
- if (tree -> sig_right == UNEVALUATED)
- {
- RIGHTEVAL;
- }
-
- /* Update the counters if needed */
-
- if (tree -> sig_left != tree -> sig_right)
- {
- if (tree -> sig_left)
- {
- if (tree -> sig_left == result)
- {
- INCR(tree -> cnt_10);
- }
- else
- {
- DECR(tree -> cnt_10);
- }
-
- }
- else
- {
- assert(tree -> sig_right);
-
- if (tree -> sig_right == result)
- {
- INCR(tree -> cnt_01);
- }
- else
- {
- DECR(tree -> cnt_01);
- }
- }
-
- /* has the node function changed */
-
- tree -> function = node_function(tree);
- }
-
- /* Assign responsibility to the left child */
-
- if (!(LEFTLEAF & (tree -> leaf_flag)))
- {
- if (tree -> sig_right != result)
- {
- adapt(tree -> left.child,vec,result);
- }
- else if ((tree -> function == LEFT) || (tree -> function == RIGHT))
- {
- adapt(tree -> left.child,vec,result);
- }
- else
- {
- if (tree -> sig_right)
- {
- if (tree -> cnt_01 < ABOVEMID)
- {
- adapt(tree -> left.child,vec,result);
- }
- }
- else
- {
- if (tree -> cnt_10 >= ABOVEMID)
- {
- adapt(tree -> left.child,vec,result);
- }
- }
- }
- }
-
- /* Assign responsibility to the right child */
-
- if (!(RIGHTLEAF & (tree -> leaf_flag)))
- {
- if (tree -> sig_left != result)
- {
- adapt(tree -> right.child,vec,result);
- }
- else if ((tree -> function == LEFT) || (tree -> function == RIGHT))
- {
- adapt(tree -> right.child,vec,result);
- }
- else
- {
- if (tree -> sig_left)
- {
- if (tree -> cnt_10 < ABOVEMID)
- {
- adapt(tree -> right.child,vec,result);
- }
- }
- else
- {
- if (tree -> cnt_01 >= ABOVEMID)
- {
- adapt(tree -> right.child,vec,result);
- }
- }
- }
- }
- }
-
- private char NEAR PASCAL
- node_function(tree)
-
- LPATREE tree;
- {
- char result;
-
- if (tree -> cnt_10 >= ABOVEMID)
- {
- if (tree -> cnt_01 >= ABOVEMID)
- {
- result = OR;
- }
- else
- {
- result = LEFT;
- }
- }
- else
- {
- if (tree -> cnt_01 >= ABOVEMID)
- {
- result = RIGHT;
- }
- else
- {
- result = AND;
- }
- }
-
- return(result);
- }
-
-
- #pragma warn -rvl
-
- error(s)
-
- char *s;
-
- {
- char szBuffer[80];
-
- wsprintf(szBuffer,"Error: %s ", s);
- MessageBox(NULL,szBuffer,"ERROR",MB_OK);
- exit(0);
- }
-
- #pragma warn .rvl
-