void LayerNet::an1 ( TrainingSet *tptr , struct LearnParams *lptr ) { int itry, user_quit ; long seed ; double best_err ; char msg[80] ; LayerNet *worknet, *bestnet ; /* Allocate scratch memory */ MEMTEXT ( "AN1::learn new worknet, bestnet" ) ; worknet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 , nout , 0 , 0 ) ; bestnet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 , nout , 0 , 1 ) ; if ((worknet == NULL) || (! worknet->ok) || (bestnet == NULL) || (! bestnet->ok)) { memory_message ( "to learn" ) ; if (worknet != NULL) delete worknet ; if (bestnet != NULL) delete bestnet ; errtype = 0 ; return ; } best_err = 1.e30 ; for (itry=1 ; itry<=lptr->retries+1 ; itry++) { user_quit = anneal1 ( tptr , lptr , worknet , 1 , itry ) ; if (neterr < best_err) { best_err = neterr ; copy_weights ( bestnet , this ) ; } sprintf ( msg , "Try %d err=%lf best=%lf", itry, neterr, best_err ) ; normal_message ( msg ) ; if (user_quit || (neterr < lptr->quit_err)) break ; seed = flrand() - (long) (itry * 97) ; // Insure new seed for anneal sflrand ( seed ) ; zero_weights () ; // Retry random } copy_weights ( this , bestnet ) ; neterr = best_err ; MEMTEXT ( "AN1::learn delete worknet, bestnet" ) ; delete worknet ; delete bestnet ; return ; }
double MutualInformationDiscrete::mut_inf ( short int *bins_x ) { int i, j, ix, nbins_x, *grid, *marginal_x ; double MI, px, py, pxy ; MEMTEXT ( "MutualInformationDiscrete::compute()" ) ; /* Compute the number of bins */ nbins_x = 0 ; for (i=0 ; i<ncases ; i++) { if (bins_x[i] > nbins_x) nbins_x = bins_x[i] ; } ++nbins_x ; // Number of bins is one greater than max bin because org=0 /* Compute the marginal of x and the counts in the nbins_x by nbins_y grid */ marginal_x = (int *) MALLOC ( nbins_x * sizeof(int) ) ; assert (marginal_x != NULL) ; grid = (int *) MALLOC ( nbins_x * nbins_y * sizeof(int) ) ; assert ( grid != NULL ) ; for (i=0 ; i<nbins_x ; i++) { marginal_x[i] = 0 ; for (j=0 ; j<nbins_y ; j++) grid[i*nbins_y+j] = 0 ; } for (i=0 ; i<ncases ; i++) { ix = bins_x[i] ; ++marginal_x[ix] ; ++grid[ix*nbins_y+bins_y[i]] ; } /* Compute the mutual information */ MI = 0.0 ; for (i=0 ; i<nbins_x ; i++) { px = (double) marginal_x[i] / (double) ncases ; for (j=0 ; j<nbins_y ; j++) { py = (double) marginal_y[j] / (double) ncases ; pxy = (double) grid[i*nbins_y+j] / (double) ncases ; if (pxy > 0.0) MI += pxy * log ( pxy / (px * py) ) ; } } FREE ( marginal_x ) ; FREE ( grid ) ; return MI ; }
TrainingSet::~TrainingSet () { if (data != NULL) { MEMTEXT ( "TRAIN: data" ) ; FREE ( data ) ; } }
ARMA *arma_restore ( char *armaname , char *filename , int *errnum ) { FILE *fp ; ARMA *arma ; if ((fp = fopen ( filename , "rb" )) == NULL) { *errnum = 1 ; return NULL ; } arma = read_arma ( armaname , fp , errnum ) ; if (arma == NULL) { fclose ( fp ) ; return NULL ; } fclose ( fp ) ; if (*errnum) { // If file read error or insufficient memory MEMTEXT ( "ARMA_SAVE: file error delete ARMA" ) ; arma->ok = 1 ; delete arma ; arma = NULL ; } arma->trained = 1 ; // Tell other routines it is trained return arma ; }
static LayerNet *read_header ( FILE *fp ) { int model, lin, nin, nh1, nh2, nout, outmod ; struct wt_header1 h1 ; LayerNet *net ; if (! fread ( &h1 , sizeof(h1) , 1 , fp )) return NULL ; if (strcmp ( h1.id , "MLFN WEIGHT FILE" )) { error_message ( "This is not a MLFN WEIGHT file." ) ; return NULL ; } model = h1.model ; lin = h1.linear ; nin = h1.n_in ; nh1 = h1.n_hid1 ; nh2 = h1.n_hid2 ; nout = h1.n_out ; outmod = h1.outmodel ; MEMTEXT ( "WT_SAVE: new network for restore" ) ; net = new LayerNet ( model , outmod , lin , nin , nh1 , nh2 , nout , 1 , 0 ); if ((net == NULL) || (! net->ok)) { // Malloc failure? memory_message ( "to create network." ) ; if (net != NULL) delete net ; return NULL ; } return net ; }
Network *wt_restore ( char *netname , char *filename , int *errnum ) { FILE *fp ; Network *net ; if ((fp = fopen ( filename , "rb" )) == NULL) { *errnum = 1 ; return NULL ; } net = read_header ( netname , fp , errnum ) ; if (net == NULL) { fclose ( fp ) ; return NULL ; } *errnum = net->wt_restore ( fp ) ; fclose ( fp ) ; if (*errnum) { // If file read error or insufficient memory MEMTEXT ( "WT_SAVE: file error delete network" ) ; net->ok = 1 ; // Destructor must free memory delete net ; net = NULL ; } net->errtype = 1 ; // Tell other routines net is trained return net ; }
double MutualInformationDiscrete::conditional_error ( short int *bins_x ) { int i, ix, nbins_x, *error_count, *marginal_x ; double CI, pyx ; MEMTEXT ( "MutualInformationDiscrete::conditional_error()" ) ; /* Compute the number of bins */ nbins_x = 0 ; for (i=0 ; i<ncases ; i++) { if (bins_x[i] > nbins_x) nbins_x = bins_x[i] ; } ++nbins_x ; // Number of bins is one greater than max bin because org=0 /* Compute the marginal of x and the error counts */ marginal_x = (int *) MALLOC ( nbins_x * sizeof(int) ) ; assert (marginal_x != NULL) ; error_count = (int *) MALLOC ( nbins_x * sizeof(int) ) ; assert ( error_count != NULL ) ; for (ix=0 ; ix<nbins_x ; ix++) { marginal_x[ix] = 0 ; error_count[ix] = 0 ; } for (i=0 ; i<ncases ; i++) { ix = bins_x[i] ; ++marginal_x[ix] ; if (bins_y[i] != ix) ++error_count[ix] ; } /* Compute the conditional error entropy */ CI = 0.0 ; for (ix=0 ; ix<nbins_x ; ix++) { if (error_count[ix] > 0 && error_count[ix] < marginal_x[ix]) { pyx = (double) error_count[ix] / (double) marginal_x[ix] ; CI += (pyx * log(pyx) + (1.0-pyx) * log(1.0-pyx)) * marginal_x[ix] / ncases ; } } FREE ( marginal_x ) ; FREE ( error_count ) ; return -CI ; }
FFT::~FFT () { if (! ok) return ; MEMTEXT ( "MRFFT: destructor (2)" ) ; if (rwork != NULL) FREE ( rwork ) ; if (iwork != NULL) FREE ( iwork ) ; }
void remove_display ( Signal *sig ) { int i ; for (i=0 ; i<n_displayed ; i++) { if ((children[i])->signal == sig) { (children[i])->Destroy() ; MEMTEXT ( "--->DISPLAY remove_display delete child" ) ; delete children[i] ; return ; } } }
void restore_screen () { union REGS r ; if (screen == NULL) return ; disp_pokebox ( screen , 0 , 0 , 24 , 79 ) ; MEMTEXT ( "GRAPHICS: screen" ) ; FREE ( screen ) ; r.h.ah = 2 ; // Set cursor r.h.bh = 0 ; // Page r.h.dh = cursor_row ; r.h.dl = cursor_col ; int86 ( 0x10 , &r , &r ) ; }
static int ok_to_clear_weights( Network **network ) { if (*network == NULL) return 1 ; if (get_yn ( "Existing learned weights must be cleared. OK" )) { MEMTEXT ( "NEURAL: delete network" ) ; delete *network ; *network = NULL ; return 1 ; } else return 0 ; }
static int ok_to_clear_tset( TrainingSet **tset ) { if (*tset == NULL) return 1 ; if (get_yn ( "Existing training set must be cleared. OK" )) { MEMTEXT ( "NEURAL: delete tset" ) ; delete *tset ; *tset = NULL ; return 1 ; } else return 0 ; }
void Network::save_confusion ( char *name ) { int i ; char *msg ; FILE *fp ; MEMTEXT ( "CONFUSE:save msg" ) ; if ((msg = (char *) MALLOC ( (nout+1) * 5 + 1 )) == NULL ) { memory_message ( "to SAVE CONFUSION" ) ; return ; } /* Open the file to which confusion will be written. If it already exists, write a newline at its end. */ fp = fopen ( name , "rt" ) ; if (fp != NULL) { i = 1 ; fclose ( fp ) ; } else i = 0 ; if ((fp = fopen ( name , "at" )) == NULL) { error_message ( "Cannot open SAVE CONFUSION file" ) ; FREE ( msg ) ; return ; } if (i) fprintf ( fp , "\n" ) ; /* Write confusion */ for (i=0 ; i<nout ; i++) sprintf ( msg+5*i , "%5d" , confusion[i] ) ; sprintf ( msg+5*nout , "%5d", confusion[nout] ) ; msg[5*nout+5] = 0 ; fprintf ( fp , "%s", msg ) ; fclose ( fp ) ; FREE ( msg ) ; return ; }
int save_screen () { union REGS r ; MEMTEXT ( "GRAPHICS: screen" ) ; screen = MALLOC ( 25 * 80 * 2 ) ; if (screen == NULL) return 1 ; r.h.ah = 3 ; // Read cursor r.h.bh = 0 ; // Page int86 ( 0x10 , &r , &r ) ; cursor_row = r.h.dh ; cursor_col = r.h.dl ; disp_peekbox ( screen , 0 , 0 , 24 , 79 ) ; return 0 ; }
static Network *read_header ( FILE *fp , int *net_model ) { int i, nin, nh1, nh2, nout, outmod, norml ; struct wt_header1 h1 ; Network *net ; KohParams kp ; if (! fread ( &h1 , sizeof(h1) , 1 , fp )) return NULL ; if (strcmp ( h1.id , "NEURAL WEIGHT FILE" )) { error_message ( "This is not a NEURAL WEIGHT file." ) ; return NULL ; } *net_model = h1.model ; nin = h1.n_in ; nh1 = h1.n_hid1 ; nh2 = h1.n_hid2 ; nout = h1.n_out ; outmod = h1.outmodel ; kp.normalization = h1.normal ; MEMTEXT ( "WT_SAVE: new network for restore" ) ; if (*net_model == NETMOD_LAYER) net = new LayerNet ( outmod , nin , nh1 , nh2 , nout , 1 , 0 ) ; else if (*net_model == NETMOD_KOH) net = new KohNet ( nin , nout , &kp , 1 , 0 ) ; else if (*net_model == NETMOD_HOP) net = new HopNet (nin,nout, 1,0); else { error_message ( "WEIGHT file specified illegal network model" ) ; return NULL ; } if ((net == NULL) || (! net->ok)) { // Malloc failure? memory_message ( "to create network." ) ; if (net != NULL) delete net ; return NULL ; } return net ; }
static PNNet *read_header ( FILE *fp ) { int model, nin, nout, outmod, kernl, mom ; struct wt_header1 h1 ; PNNet *net ; if (! fread ( &h1 , sizeof(h1) , 1 , fp )) return NULL ; if (strcmp ( h1.id , "PNN NETWORK FILE" )) { error_message ( "This is not a PNN NETWORK file." ) ; return NULL ; } model = h1.model ; kernl = h1.kernel ; mom = h1.maxmom ; nin = h1.n_in ; nout = h1.n_out ; outmod = h1.outmodel ; MEMTEXT ( "WT_SAVE: new network for restore" ) ; if (model == NETMOD_BASIC) net = new PNNbasic ( kernl , outmod , nin , nout ) ; else if (model == NETMOD_SEPVAR) net = new PNNsepvar ( kernl , outmod , nin , nout ) ; else if (model == NETMOD_SEPCLASS) net = new PNNsepclass ( kernl , outmod , nin , nout ) ; else if (model == NETMOD_GCNN) net = new GCNN ( mom , 0 , outmod , nin , nout ) ; else if (model == NETMOD_GCNN_EW) net = new GCNN ( mom , 1 , outmod , nin , nout ) ; if ((net == NULL) || (! net->ok)) { // Malloc failure? memory_message ( "to create network." ) ; if (net != NULL) delete net ; return NULL ; } return net ; }
void Network::show_confusion () { int i ; char *msg ; MEMTEXT ( "CONFUSE:show msg" ) ; if ((msg = (char *) MALLOC ( (nout+1) * 5 + 11 )) == NULL ) { memory_message ( "to SHOW CONFUSION" ) ; return ; } strcpy ( msg , "Confusion:" ) ; for (i=0 ; i<nout ; i++) sprintf ( msg+5*i+10 , "%5d" , confusion[i] ) ; sprintf ( msg+5*nout+10, "%5d", confusion[nout] ) ; msg[5*nout+15] = 0 ; normal_message ( msg ) ; FREE ( msg ) ; return ; }
MutualInformationDiscrete::MutualInformationDiscrete ( int nc , // Number of cases short int *bins ) // They are here (y, the 'dependent' variable) { int i ; MEMTEXT ( "MutualInformationDiscrete constructor" ) ; /* Keep a local copy of the bins */ ncases = nc ; bins_y = (short int *) MALLOC ( ncases * sizeof(short int) ) ; assert (bins_y != NULL) ; memcpy ( bins_y , bins , ncases * sizeof(short int) ) ; /* Compute the number of bins, and then compute and save the marginal distribution */ nbins_y = 0 ; for (i=0 ; i<ncases ; i++) { if (bins_y[i] > nbins_y) nbins_y = bins_y[i] ; } ++nbins_y ; // Number of bins is one greater than max bin because org=0 marginal_y = (int *) MALLOC ( nbins_y * sizeof(int) ) ; assert (marginal_y != NULL) ; for (i=0 ; i<nbins_y ; i++) marginal_y[i] = 0 ; for (i=0 ; i<ncases ; i++) ++marginal_y[bins_y[i]] ; }
PNNet *wt_restore ( char *name ) { char msg[81] ; FILE *fp ; PNNet *net ; if ((fp = fopen ( name , "rb" )) == NULL) { strcpy ( msg , "Cannot open WEIGHT file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; return NULL ; } net = read_header ( fp ) ; if (net == NULL) { strcpy ( msg , "Could not read WEIGHT file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; fclose ( fp ) ; return NULL ; } net->wt_restore ( fp ) ; fclose ( fp ) ; if (! net->ok) { // Set to 0 if file read error or insufficient memory strcpy ( msg , "Could not read NETWORK file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; MEMTEXT ( "WT_SAVE: file error delete network" ) ; net->ok = 1 ; // Tells destructor to free vectors delete net ; net = NULL ; } net->errtype = 1 ; // Tell other routines net is trained return net ; }
Network *wt_restore ( char *name , int *net_model ) { int i ; char msg[81] ; FILE *fp ; Network *net ; if ((fp = fopen ( name , "rb" )) == NULL) { strcpy ( msg , "Cannot open WEIGHT file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; return NULL ; } net = read_header ( fp , net_model ) ; if (net == NULL) { strcpy ( msg , "Could not read WEIGHT file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; fclose ( fp ) ; return NULL ; } net->wt_restore ( fp ) ; fclose ( fp ) ; if (! net->ok) { // Set to 0 if file read error strcpy ( msg , "Could not read WEIGHT file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; MEMTEXT ( "WT_SAVE: file error delete network" ) ; net->ok = 1 ; // Tells destructor to free vectors delete net ; net = NULL ; } return net ; }
void Network::test_from_file ( char *dataname , // Input file name char *outname, // Output file name int netmod ) { int i, maxlin, did_any, best,name=0,win1,win2,win3 ; float *inputs, *iptr, maxi1,maxi2,maxi3 ; char msg[81], *line, *lptr, *tab[20]; FILE *fp_in, *fp_out, *fname; /* Open the file which contains the data to be classified */ if ((fp_in = fopen ( dataname , "rt" )) == NULL) { strcpy ( msg , "Cannot open input data file " ) ; strcat ( msg , dataname ) ; error_message ( msg ) ; return ; } /* Open the file to which outputs will be written. If it already exists, write a newline at its end. */ fp_out = fopen ( outname , "rt" ) ; if (fp_out != NULL) { did_any = 1 ; fclose ( fp_out ) ; } else did_any = 0 ; if ((fp_out = fopen ( outname , "at" )) == NULL) { strcpy ( msg , "Cannot open output file " ) ; strcat ( msg , outname ) ; error_message ( msg ) ; fclose ( fp_in ) ; return ; } if (did_any) { fprintf ( fp_out , "\n" ) ; } /* Allocate for the file lines as read. Conservatively guess length. Also allocate for network input vector. */ maxlin = nin * 20 + 100 ; if (maxlin < 1024) maxlin = 1024 ; MEMTEXT ( "EXECUTE:line, inputs" ) ; line = (char *) MALLOC ( maxlin ) ; inputs = (float *) MALLOC ( nin * sizeof(float) ) ; if ((line == NULL) || (inputs == NULL)) { memory_message ( "to execute" ) ; fclose ( fp_in ) ; fclose ( fp_out ) ; if (line != NULL) FREE ( line ) ; if (inputs != NULL) FREE ( inputs ) ; return ; } /* Read and process the file. */ did_any = 0 ; /* If file runs out on first try, ERROR! */ int e=0; for (;;) { // Endless loop reads until file exhausted if ((fgets ( line , maxlin , fp_in ) == NULL) || (strlen ( line ) < 2)) { if ((! did_any) || ferror ( fp_in )) { strcpy ( msg , "Problem reading file " ) ; strcat ( msg , dataname ) ; error_message ( msg ) ; } break ; } lptr = line ; // Parse the data from this line iptr = inputs ; // This will be the network inputs for (i=0 ; i<nin ; i++) *iptr++ = ParseDouble ( &lptr ) ; if (did_any) // Start each new case on new line fprintf ( fp_out , "\n" ) ; did_any = 1 ; // Flag that at least one found trial ( inputs ) ; // Compute network's outputs maxi1=maxi2=maxi3=0.0; win1=win2=win3=0; // Saving maximun activation and the winner of the output vector if (netmod==NETMOD_KOH) { // First maximum for (i=0 ; i<nout ; i++) { if (out[i]>maxi1) { maxi1=out[i]; win1=i; } } // 2nd Maximum for (i=0 ; i<nout ; i++) { if ( (out[i]>maxi2) && (out[i]<maxi1) ) { maxi2=out[i]; win2=i; } } // 3rd Maximum for (i=0 ; i<nout ; i++) { if ( (out[i]>maxi3) && (out[i]<maxi2) ) { maxi3=out[i]; win3=i; } } } if (netmod==NETMOD_KOH) { fprintf (fp_out,"%d %3.2lf\n",win1,maxi1*100.0); fprintf (fp_out,"%d %3.2lf\n",win2,maxi2*100.0); fprintf (fp_out,"%d %3.2lf",win3,maxi3*100.0); } else for (i=0 ; i<nout ; i++) { fprintf ( fp_out , "%.4lf ",out[i]); } e++; while ((! feof ( fp_in )) && (line[strlen(line)-1] != '\n')) fgets ( line , maxlin , fp_in ) ; // Line length may exceed maxlin if (feof ( fp_in )) break ; } /* Endless loop until a file runs out */ MEMTEXT ( "EXECUTE:line, inputs" ) ; fclose ( fp_in ) ; fclose ( fp_out ) ; FREE ( line ) ; FREE ( inputs ) ; }
void Network::classify_from_file ( char *name , double thresh ) { int i, maxlin, did_any, best ; double *inputs, *iptr, maxact ; char msg[81], *line, *lptr ; FILE *fp ; /* Open the file which contains the data to be classified */ if ((fp = fopen ( name , "rt" )) == NULL) { strcpy ( msg , "Cannot open " ) ; strcat ( msg , name ) ; error_message ( msg ) ; return ; } /* Allocate for the file lines as read. Conservatively guess length. Also allocate for network input vector. */ maxlin = nin * 20 + 100 ; if (maxlin < 1024) maxlin = 1024 ; MEMTEXT ( "CONFUSE:line, inputs" ) ; line = (char *) MALLOC ( maxlin ) ; inputs = (double *) MALLOC ( nin * sizeof(double) ) ; if ((line == NULL) || (inputs == NULL)) { memory_message ( "to classify" ) ; fclose ( fp ) ; if (line != NULL) FREE ( line ) ; if (inputs != NULL) FREE ( inputs ) ; return ; } /* Read the file. */ did_any = 0 ; /* If file runs out on first try, ERROR! */ for (;;) { // Endless loop reads until file exhausted if ((fgets ( line , maxlin , fp ) == NULL) || (strlen ( line ) < 2)) { if ((! did_any) || ferror ( fp )) { strcpy ( msg , "Problem reading file " ) ; strcat ( msg , name ) ; error_message ( msg ) ; } break ; } lptr = line ; // Parse the data from this line iptr = inputs ; // This will be the network inputs for (i=0 ; i<nin ; i++) *iptr++ = ParseDouble ( &lptr ) ; did_any = 1 ; // Flag that at least one found trial ( inputs ) ; // Compute network's outputs maxact = -1.e30 ; // Will keep highest activity here best = 0 ; // Insurance only (good habit) for (i=0 ; i<nout ; i++) { // Find winning output if (out[i] > maxact) { maxact = out[i] ; best = i ; } } if (maxact >= thresh) // If winner has enough activation ++confusion[best] ; // count it in confusion else // If too little, throw it ++confusion[nout] ; // in the reject category while ((! feof ( fp )) && (line[strlen(line)-1] != '\n')) fgets ( line , maxlin , fp ) ; // Line length may exceed maxlin if (feof ( fp )) break ; } /* Endless loop until a file runs out */ fclose ( fp ) ; MEMTEXT ( "CONFUSE:line, inputs" ) ; FREE ( line ) ; FREE ( inputs ) ; }
int qmf_sig ( MiscParams *misc , Signal *sig , double freq , double width , int *nsigs , Signal ***signals , char *error ) { int i, j, n, ivar, nvars, pad ; double *real, *imag, *temp, *x ; double *amp, *phase ; Signal **sptr ; Filter *filt ; nvars = misc->names->nreal ; if (! nvars) { strcpy ( error , "No signal names specified" ) ; return 1 ; } n = sig->n ; x = sig->sig ; pad = (int) (0.8 / width) ; // Good, conservative heuristic MEMTEXT ( "QMF_SIG: new Filter" ) ; filt = new Filter ( n , x , pad , 1 ) ; MEMTEXT ( "QMF_SIG: real, imag" ) ; real = (double *) MALLOC ( n * sizeof(double) ) ; imag = (double *) MALLOC ( n * sizeof(double) ) ; if ((real == NULL) || (imag == NULL) || (filt == NULL) || ! filt->ok){ if (real != NULL) FREE ( real ) ; if (imag != NULL) FREE ( imag ) ; if (filt != NULL) delete filt ; strcpy ( error , "Insufficient memory to filter signal" ) ; return 1 ; } if ((misc->names->n > 2) && misc->names->len[2]) { MEMTEXT ( "QMF_SIG: amp" ) ; amp = (double *) MALLOC ( n * sizeof(double) ) ; if (amp == NULL) { FREE ( real ) ; FREE ( imag ) ; delete filt ; strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } } else amp = NULL ; if ((misc->names->n > 3) && misc->names->len[3]) { MEMTEXT ( "QMF_SIG: phase" ) ; phase = (double *) MALLOC ( n * sizeof(double) ) ; if (phase == NULL) { FREE ( real ) ; FREE ( imag ) ; delete filt ; if (amp != NULL) FREE ( amp ) ; strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } } else phase = NULL ; filt->qmf ( freq , width , real , imag ) ; if (amp != NULL) { for (i=0 ; i<n ; i++) amp[i] = sqrt ( real[i] * real[i] + imag[i] * imag[i] ) ; } if (phase != NULL) { for (i=0 ; i<n ; i++) { if ((fabs(real[i]) > 1.e-40) || (fabs(imag[i]) > 1.e-40)) phase[i] = atan2 ( imag[i] , real[i] ) ; else phase[i] = 0.0 ; } } /* Count how many of these signals have names not already in use. Then allocate additional memory for their pointers. */ MEMTEXT ( "QMF_SIG: signals array" ) ; if (*nsigs) { // If signals already exist ivar = *nsigs ; // This many signals so far sptr = *signals ; // Array of pointers to them for (i=0 ; i<misc->names->n ; i++) { // Check every new name if (! misc->names->len[i]) // Some may be NULL continue ; // Obviously skip them for (j=*nsigs-1 ; j>=0 ; j--) { // Check every existing signal if (! strcmp ( misc->names->start[i] , sptr[j]->name )) // There? break ; // If found, quit looking } if (j < 0) // Means not there ++ivar ; // So count this new entry } sptr = (Signal **) REALLOC ( sptr , ivar * sizeof(Signal *) ) ; } else sptr = (Signal **) MALLOC ( nvars * sizeof(Signal *) ) ; if (sptr == NULL) { FREE ( real ) ; FREE ( imag ) ; if (amp != NULL) FREE ( amp ) ; if (phase != NULL) FREE ( phase ) ; strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } *signals = sptr ; /* Now create new signals for each variable. If a signal of the same name exists, delete it first. Recall that we have provision for up to four outputs in this order: Real, Imaginary, Amplitude, Phase. */ for (i=0 ; i<misc->names->n ; i++) { // Check all names if (i >= 4) // Allow at most 4 outputs break ; if (! misc->names->len[i]) { // Some may be NULL switch (i) { // If not used in a new signal case 0: FREE ( real ) ; break ; // Must free this memory case 1: FREE ( imag ) ; break ; } continue ; } for (j=*nsigs-1 ; j>=0 ; j--) { // Search existing signals for same name if (! strcmp ( misc->names->start[i] , sptr[j]->name )) { // There? MEMTEXT ( "SPECTRUM: delete duplicate signal" ) ; delete ( sptr[j] ) ; // If so, delete this signal break ; // And quit looking } } if (j < 0) { // Means new, unique name j = *nsigs ; // Tack it onto end of signal array ++*nsigs ; // And count it } switch (i) { case 0: temp = real ; break ; case 1: temp = imag ; break ; case 2: temp = amp ; break ; case 3: temp = phase ; break ; } MEMTEXT ( "SPECTRUM: new Signal" ) ; sptr[j] = new Signal ( misc->names->start[i] , n , temp ) ; if ((sptr[j] == NULL) || ! sptr[j]->n) { if (sptr[j] != NULL) { delete sptr[j] ; sptr[j] = NULL ; } switch (i) { case 0: FREE ( real ) ; case 1: FREE ( imag ) ; case 2: if (amp != NULL) FREE ( amp ) ; case 3: if (phase != NULL) FREE ( phase ) ; } strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } } // For all names if (misc->names->n == 1) { MEMTEXT ( "QMF_SIG imag" ) ; FREE ( imag ) ; } MEMTEXT ( "QMF_SIG: delete Filter" ) ; delete filt ; return 0 ; }
void display ( Signal *sig , MiscParams *misc , int id ) { int i, j, n ; double *signal, sigmin, sigmax, cl, val ; npredictMDIChild *child ; /* Search the display list for a signal having this name. If there, just use that existing child. Else create the MDI child window. */ for (i=0 ; i<n_displayed ; i++) { child = children[i] ; if (! strcmp ( child->signal->name , sig->name )) break ; } if (i == n_displayed) { child = new npredictMDIChild ( mdiClient , sig->name ) ; MEMTEXT ( "--->DISPLAY made new child" ) ; child->background_color = RGB ( 255 , 255 , 255 ) ; child->Create(); children[n_displayed++] = child ; } else child->Invalidate(); child->signal = sig ; child->command_id = id ; if (sig->type == CorrelationSignal) { child->istart = 0 ; child->istop = sig->n - 1 ; } else { child->istart = misc->display_domain0 ; child->istop = misc->display_domain1 ; if (sig->n-1 < child->istop) child->istop = sig->n-1 ; } n = child->istop - child->istart + 1 ; signal = sig->sig ; if (misc->display_range < 2) { // Optimal or Symmetric sigmin = sigmax = signal[child->istart] ; // Find signal limits for (i=child->istart ; i<=child->istop ; i++) { val = signal[i] ; if (val < sigmin) sigmin = val ; if (val > sigmax) sigmax = val ; } if (id == ID_PRED_DISPLAY_CONFIDENCE) { for (i=sig->known_n ; i<sig->known_n+sig->npred ; i++) { // Predictions if (i < child->istart) continue ; if (i > child->istop) break ; j = i - sig->known_n ; // This interval if (sig->mult_conf) val = signal[i] * sig->intervals[2*j] ; // Lower else val = signal[i] + sig->intervals[2*j] ; // Lower if (val < sigmin) sigmin = val ; if (sig->mult_conf) val = signal[i] * sig->intervals[2*j+1] ; // Upper else val = signal[i] + sig->intervals[2*j+1] ; // Upper if (val > sigmax) sigmax = val ; } } if ((sigmax - sigmin) < 1.e-20) { // Center for visual effect only sigmin = 0.5 * (sigmin + sigmax) - .000095 ; sigmax = 0.5 * (sigmin + sigmax) + .000095 ; } if (sig->type == CorrelationSignal) { cl = 1.96 / sqrt ( (double) sig->source_n ) ; // Confidence limits if (cl > sigmax) sigmax = cl ; if (-cl < sigmin) sigmin = -cl ; child->corrlim = cl ; } if (sig->type == SpectrumDevSignal) { cl = 1.22 / sqrt ((double) sig->source_n / 2 - 1) ; // Confidence if (cl > sigmax) sigmax = cl ; if (-cl < sigmin) sigmin = -cl ; child->corrlim = cl ; } if (misc->display_range == 1) { // Symmetric if (fabs(sigmin) > fabs(sigmax)) { sigmax = fabs(sigmin) ; sigmin = -fabs(sigmin) ; } else { sigmin = -fabs(sigmax) ; sigmax = fabs(sigmax) ; } } // If SYMMETRIC } // If OPTIMAL or SYMMETRIC else { sigmin = misc->display_min ; sigmax = misc->display_max ; if (sig->type == CorrelationSignal) child->corrlim = 1.96 / sqrt ( (double) sig->source_n ) ; // Confidence if (sig->type == SpectrumDevSignal) child->corrlim = 1.22 / sqrt ((double) sig->source_n / 2 - 1) ; } /* Compute 'pretty' tick locations. Graphlab may have to change our specified number of ticks a little to keep it pretty. */ if (sig->type == DataSignal) { child->leftx = misc->display_origin + child->istart / misc->display_rate ; child->rightx = misc->display_origin + child->istop / misc->display_rate ; } else if ((sig->type == SpectrumSignal) || (sig->type == SpectrumDevSignal)) { child->leftx = 0.5 * misc->display_rate * child->istart / sig->n ; child->rightx = 0.5 * misc->display_rate * child->istop / (sig->n - 1) ; } else if (sig->type == CorrelationSignal) { child->leftx = 0 ; child->rightx = n + 1 ; } best_graphlab ( child->leftx , child->rightx , 5 , 8 , &child->xmin , &child->xmax , &child->xdif , &child->xndigits , &child->xnfrac ) ; child->xnticks = 1 + (int) ((child->xmax - child->xmin) / child->xdif + 0.1); best_graphlab ( sigmin , sigmax , 5 , 10 , &child->ymin , &child->ymax , &child->ydif , &child->yndigits , &child->ynfrac ) ; child->ynticks = 1 + (int) ((child->ymax - child->ymin) / child->ydif + 0.1); }
void LayerNet::anneal ( TrainingSet *tptr , // Training set to use struct LearnParams *lptr , // User's general learning parameters LayerNet *bestnet , // Work area used to keep best network int init // Use zero suffix (initialization) anneal parms? ) { int ntemps, niters, setback, reg, nvars, key, user_quit ; int i, iter, improved, ever_improved, itemp ; long seed, bestseed ; char msg[80] ; double tempmult, temp, fval, bestfval, starttemp, stoptemp, fquit ; SingularValueDecomp *sptr ; struct AnnealParams *aptr ; // User's annealing parameters aptr = lptr->ap ; /* The parameter 'init' is nonzero if we are initializing weights for learning. If zero we are attempting to break out of a local minimum. The main effect of this parameter is whether or not we use the zero suffix variables in the anneal parameters. A second effect is that regression is used only for initialization, not for escape. */ if (init) { ntemps = aptr->temps0 ; niters = aptr->iters0 ; setback = aptr->setback0 ; starttemp = aptr->start0 ; stoptemp = aptr->stop0 ; } else { ntemps = aptr->temps ; niters = aptr->iters ; setback = aptr->setback ; starttemp = aptr->start ; stoptemp = aptr->stop ; } /* Initialize other local parameters. Note that there is no sense using regression if there are no hidden layers. Also, regression is almost always counterproductive for local minimum escape. */ fquit = lptr->quit_err ; reg = init && nhid1 && (lptr->init != 1) ; /* Allocate the singular value decomposition object for REGRESS. Also allocate a work area for REGRESS to preserve matrix. */ if (reg) { if (nhid1 == 0) // No hidden layer nvars = nin + 1 ; else if (nhid2 == 0) // One hidden layer nvars = nhid1 + 1 ; else // Two hidden layers nvars = nhid2 + 1 ; MEMTEXT ( "ANNEAL: new SingularValueDecomp" ) ; sptr = new SingularValueDecomp ( tptr->ntrain , nvars , 1 ) ; if ((sptr == NULL) || ! sptr->ok) { memory_message ( "for annealing with regression. Try ANNEAL NOREGRESS."); if (sptr != NULL) delete sptr ; neterr = 1.0 ; // Flag failure to LayerNet::learn which called us return ; } } /* For every temperature, the center around which we will perturb is the best point so far. This is kept in 'bestnet', so initialize it to the user's starting estimate. Also, initialize 'bestfval', the best function value so far, to be the function value at that starting point. */ copy_weights ( bestnet , this ) ; // Current weights are best so far if (init) bestfval = 1.e30 ; // Force it to accept SOMETHING else bestfval = trial_error ( tptr ) ; /* This is the temperature reduction loop and the iteration within temperature loop. We use a slick trick to keep track of the best point at a given temperature. We certainly don't want to replace the best every time an improvement is had, as then we would be moving our center about, compromising the global nature of the algorithm. We could, of course, have a second work area in which we save the 'best so far for this temperature' point. But if there are a lot of variables, the usual case, this wastes memory. What we do is to save the seed of the random number generator which created the improvement. Then later, when we need to retrieve the best, simply set the random seed and regenerate it. This technique also saves a lot of copying time if many improvements are made for a single temperature. */ temp = starttemp ; tempmult = exp( log( stoptemp / starttemp ) / (ntemps-1)) ; ever_improved = 0 ; // Flags if improved at all user_quit = 0 ; // Flags user pressed ESCape for (itemp=0 ; itemp<ntemps ; itemp++) { // Temp reduction loop improved = 0 ; // Flags if this temp improved if (init) { sprintf ( msg , "\nANNEAL temp=%.2lf ", temp ) ; progress_message ( msg ) ; } for (iter=0 ; iter<niters ; iter++) { // Iters per temp loop seed = longrand () ; // Get a random seed slongrand ( seed ) ; // Brute force set it perturb (bestnet, this, temp, reg) ;// Randomly perturb about best if (reg) // If using regression, estimate fval = regress ( tptr , sptr ) ; // out weights now else // Otherwise just evaluate fval = trial_error ( tptr ) ; if (fval < bestfval) { // If this iteration improved bestfval = fval ; // then update the best so far bestseed = seed ; // and save seed to recreate it ever_improved = improved = 1 ; // Flag that we improved if (bestfval <= fquit) // If we reached the user's break ; // limit, we can quit iter -= setback ; // It often pays to keep going if (iter < 0) // at this temperature if we iter = 0 ; // are still improving } } // Loop: for all iters at a temp if (improved) { // If this temp saw improvement slongrand ( bestseed ) ; // set seed to what caused it perturb (bestnet, this, temp, reg) ;// and recreate that point copy_weights ( bestnet , this ) ; // which will become next center slongrand ( bestseed / 2 + 999 ) ; // Jog seed away from best if (init) { sprintf ( msg , " err=%.3lf%% ", 100.0 * bestfval ) ; progress_message ( msg ) ; } } if (bestfval <= fquit) // If we reached the user's break ; // limit, we can quit /*********************************************************************** if (kbhit()) { // Was a key pressed? key = getch () ; // Read it if so while (kbhit()) // Flush key buffer in case function key getch () ; // or key was held down if (key == 27) { // ESCape user_quit = 1 ; // Flags user that ESCape was pressed break ; } } ***********************************************************************/ if (user_quit) break ; temp *= tempmult ; // Reduce temp for next pass } // through this temperature loop /* The trials left this weight set and neterr in random condition. Make them equal to the best, which will be the original if we never improved. Also, if we improved and are using regression, recall that bestnet only contains the best hidden weights, as we did not bother to run regress when we updated bestnet. Do that now before returning. */ copy_weights ( this , bestnet ) ; // Return best weights in this net neterr = bestfval ; // Trials destroyed weights, err if (ever_improved && reg) neterr = regress ( tptr , sptr ) ; // regressed output weights if (reg) { MEMTEXT ( "ANNEAL: delete SingularValueDecomp" ) ; delete sptr ; } }
MutualInformationDiscrete::~MutualInformationDiscrete () { MEMTEXT ( "MutualInformationDiscrete destructor" ) ; FREE ( bins_y ) ; FREE ( marginal_y ) ; }
double MutualInformationDiscrete::HYe ( short int *bins_x ) { int i, ix, iy, nbins_x, nerr, *grid, *marginal_x ; double minCI, pyx, cix ; MEMTEXT ( "MutualInformationDiscrete::HYe()" ) ; /* Compute the number of bins */ nbins_x = 0 ; for (i=0 ; i<ncases ; i++) { if (bins_x[i] > nbins_x) nbins_x = bins_x[i] ; } ++nbins_x ; // Number of bins is one greater than max bin because org=0 /* This algorithm makes sense only if nbins_x equals nbins_y. Return an error flag that will get the user's attention if this is violated. */ if (nbins_x != nbins_y) return -1.e60 ; /* Compute the marginal of x and the counts in the nbins_x by nbins_y grid */ marginal_x = (int *) MALLOC ( nbins_x * sizeof(int) ) ; assert (marginal_x != NULL) ; grid = (int *) MALLOC ( nbins_x * nbins_y * sizeof(int) ) ; assert ( grid != NULL ) ; for (ix=0 ; ix<nbins_x ; ix++) { marginal_x[ix] = 0 ; for (iy=0 ; iy<nbins_y ; iy++) grid[ix*nbins_y+iy] = 0 ; } for (i=0 ; i<ncases ; i++) { ix = bins_x[i] ; ++marginal_x[ix] ; ++grid[ix*nbins_y+bins_y[i]] ; } /* Compute the minimum entropy, conditional on error and each X Note that the computation in the inner loop is almost the same as in the conditional entropy. The only difference is that since we are also conditioning on the classification being in error, we must remove from the X marginal the diagonal element, which is the correct decision. The outer loop looks for the minimum, rather than summing. */ minCI = 1.e60 ; for (ix=0 ; ix<nbins_x ; ix++) { nerr = marginal_x[ix] - grid[ix*nbins_y+ix] ; // Marginal that is in error if (nerr > 0) { cix = 0.0 ; for (iy=0 ; iy<nbins_y ; iy++) { if (iy == ix) // This is the correct decision continue ; // So we exclude it; we are summing over errors pyx = (double) grid[ix*nbins_y+iy] / (double) nerr ; if (pyx > 0.0) cix -= pyx * log ( pyx ) ; } if (cix < minCI) minCI = cix ; } } FREE ( marginal_x ) ; FREE ( grid ) ; return minCI ; }
void LayerNet::gen_init ( TrainingSet *tptr , // Training set to use struct LearnParams *lptr // User's general learning parameters ) { int i, istart, individual, best_individual, generation, n_cross ; int first_child, parent1, parent2, improved, crosspt, nchoices, *choices ; int initpop, popsize, gens, climb, nvars, chromsize, split, ind ; float pcross, pmutate, error, besterror, *errors, *fitness, worst ; float fquit, favor_best, fitfac, maxerr, minerr, avgerr, overinit ; SingularValueDecomp *sptr ; struct GenInitParams *gptr ; // User's genetic initialization parameters char *pool1, *pool2, *oldpop, *newpop, *popptr, *temppop, *best ; char msg[80] ; gptr = lptr->gp ; popsize = gptr->pool ; gens = gptr->gens ; climb = gptr->climb ; overinit = gptr->overinit ; pcross = gptr->pcross ; pmutate = gptr->pmutate ; fquit = lptr->quit_err ; favor_best = 3.1 ; fitfac = -20.0 ; /* -------------------------------------------------------------------------------- Do all scratch memory allocation. -------------------------------------------------------------------------------- */ /* Allocate the singular value decomposition object for REGRESS. */ if (nhid2 == 0) // One hidden layer nvars = nhid1 + 1 ; else // Two hidden layers nvars = nhid2 + 1 ; MEMTEXT ( "GEN_INIT: new SingularValueDecomp" ) ; sptr = new SingularValueDecomp ( tptr->ntrain , nvars , 1 ) ; if ((sptr == NULL) || ! sptr->ok) { memory_message("for genetic initialization. Try ANNEAL NOREGRESS."); neterr = 1.0 ; // Flag failure to LayerNet::learn which called us if (sptr != NULL) delete sptr ; return ; } chromsize = nhid1 * (nin+1) ; // Length of an individual's chromosome if (nhid2) // is the number of hidden weights chromsize += nhid2 * (nhid1+1) ; errors = fitness = NULL ; choices = NULL ; pool1 = pool2 = NULL ; MEMTEXT ( "GEN_INIT: errors, fitness, choices, best, pool1,pool2"); if (((errors = (float*) MALLOC ( popsize * sizeof(float))) == NULL) || ((fitness = (float*) MALLOC ( popsize * sizeof(float))) == NULL) || ((best = (char*) MALLOC( chromsize )) == NULL) || ((choices = (int*) MALLOC ( popsize * sizeof(int))) == NULL) || ((pool1 = (char*) MALLOC( popsize * chromsize )) == NULL) || ((pool2 = (char*) MALLOC( popsize * chromsize )) == NULL)) { if (errors != NULL) FREE ( errors ) ; if (fitness != NULL) FREE ( fitness ) ; if (choices != NULL) FREE ( choices ) ; if (pool1 != NULL) FREE ( pool1 ) ; if (pool2 != NULL) FREE ( pool2 ) ; delete sptr ; memory_message("for genetic initialization. Try ANNEAL NOREGRESS." ) ; neterr = 1.0 ; // Flag failure to LayerNet::learn which called us return ; } /* Generate initial population pool. We also preserve the best weights across all generations, as this is what we will ultimately return to the user. Its mean square error is besterror. */ besterror = 1.e30 ; // For saving best (across all individuals and gens) maxerr = avgerr = 0.0 ; // For progress display only best_individual = 0 ; // Safety only initpop = popsize * overinit ; // Overinitialization of initial population progress_message ( "\nGenerating initial population" ) ; for (ind=0 ; ind<initpop ; ind++) { // Try overinitialization times if (ind<popsize) // If still in pop size limit individual = ind ; // just use next avail space else { // Else we search entire pop worst = -1. ; // for the worst member for (i=0 ; i<popsize ; i++) { // which we will then replace if (errors[i] > worst) { worst = errors[i] ; individual = i ; } } avgerr -= worst ; // Exclude discards from average } popptr = pool1 + individual * chromsize ; // Build init pop in pool1 rand_ind ( popptr , chromsize ) ; // Randomly generate individual decode ( popptr , nin , nhid1 , nhid2 , // Convert genotype (chromosome) hid1_coefs , hid2_coefs ); // to phenotype (weights) error = regress ( tptr , sptr ) ; // Evaluate network error errors[individual] = error ; // and keep all errors if (error < besterror) { // Keep track of best besterror = error ; // as it is returned to user best_individual = individual ; // This is its index in pool1 } if (error > maxerr) // Max and average error are maxerr = error ; // for progress display only avgerr += error ; if (error <= fquit) break ; progress_message ( "." ) ; } sprintf (msg , "\nInitial pop: Min err=%7.4lf Max=%7.4lf Avg=%7.4lf", 100. * besterror, 100. * maxerr, 100.0 * avgerr / (float) popsize); progress_message ( msg ) ; /* The initial population has been built in pool1. Copy its best member to 'best' in case it never gets beat (unlikely but possible!). Also, we will need best if the climb option is true. */ popptr = pool1 + best_individual * chromsize ; // Point to best memcpy ( best , popptr , chromsize ) ; // and save it /* This is the main generation loop. There are two areas for population pool storage: pool1 and pool2. At any given time, oldpop will be set to one of them, and newpop to the other. This avoids a lot of copying. */ oldpop = pool1 ; // This is the initial population newpop = pool2 ; // The next generation is created here for (generation=0 ; generation<gens ; generation++) { if (error <= fquit) // We may have satisfied this in init pop break ; // So we test at start of generation loop error_to_fitness ( popsize , favor_best , fitfac , errors , fitness ) ; fitness_to_choices ( popsize , fitness , choices ) ; nchoices = popsize ; // Will count down as choices array emptied n_cross = pcross * popsize ; // Number crossing over first_child = 1 ; // Generating first of parent's 2 children? improved = 0 ; // Flags if we beat best if (climb) { // If we are to hill climb memcpy ( newpop , best , chromsize ) ; // start with best errors[0] = besterror ; // Record its error istart = 1 ; // and start children past it } else istart = 0 ; /* Generate the children */ maxerr = avgerr = 0.0 ; // For progress display only minerr = 1.0 ; // Ditto for (individual=istart ; individual<popsize ; individual++) { popptr = newpop + individual * chromsize ; // Will put this child here if (first_child) // If this is the first of 2 children, pick parents pick_parents ( &nchoices , choices , &parent1 , &parent2 ) ; if (n_cross-- > 0) // Do crossovers first reproduce ( oldpop + parent1 * chromsize , oldpop + parent2 * chromsize , first_child , chromsize , popptr , &crosspt , &split ) ; else if (first_child) // No more crossovers, so just copy parent memcpy ( popptr , oldpop + parent1 * chromsize , chromsize ) ; else memcpy ( popptr , oldpop + parent2 * chromsize , chromsize ); if (pmutate > 0.0) mutate ( popptr , chromsize , pmutate ) ; decode ( popptr , nin , nhid1 , nhid2 , hid1_coefs , hid2_coefs ) ; error = regress ( tptr , sptr ) ; // Evaluate child's error errors[individual] = error ; // and keep each if (error < besterror) { // Keep track of best besterror = error ; // It will be returned to user best_individual = individual ; // This is its index in newpop improved = 1 ; // Flag so we copy it later } if (error > maxerr) // Min, max and average error maxerr = error ; // for progress display only if (error < minerr) minerr = error ; avgerr += error ; if (error <= fquit) break ; first_child = ! first_child ; } // For all genes in population /* We finished generating all children. If we improved (one of these children beat the best so far) then copy that child to the best. Swap oldpop and newpop for the next generation. */ if (improved) { popptr = newpop + best_individual * chromsize ; // Point to best memcpy ( best , popptr , chromsize ) ; // and save it } temppop = oldpop ; // Switch old and new pops for next generation oldpop = newpop ; newpop = temppop ; sprintf(msg, "\nGeneration %3d: Min err=%7.4lf Max=%7.4lf Avg=%7.4lf", generation+1, 100. * minerr, 100. * maxerr, 100.0 * avgerr / (float) popsize ) ; progress_message ( msg ) ; } /* We are all done. */ decode ( best , nin , nhid1 , nhid2 , hid1_coefs , hid2_coefs ) ; besterror = regress ( tptr , sptr ) ; // Evaluate network error MEMTEXT ( "GEN_INIT: errors, fitness, choices, best, pool1,pool2"); FREE ( errors ) ; FREE ( fitness ) ; FREE ( choices ) ; FREE ( best ) ; FREE ( pool1 ) ; FREE ( pool2 ) ; MEMTEXT ( "GEN_INIT: delete sptr" ) ; delete sptr ; }
int combine ( MiscParams *misc , int operation , Signal *sig1 , Signal *sig2 , int *nsigs , Signal ***signals , char *error ) { int i, j, ivar, nvars, ncases ; double *data, *temp, *dptr ; Signal **sptr ; nvars = misc->names->nreal ; if (! nvars) { strcpy ( error , "No signal names specified" ) ; return 1 ; } ncases = sig1->n ; if (sig2->n < ncases) ncases = sig2->n ; if (! ncases) { strcpy ( error , "Signal length is zero" ) ; return 1 ; } MEMTEXT ( "COMBINE: data" ) ; data = (double *) MALLOC ( ncases * sizeof(double) ) ; if (data == NULL) { strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } dptr = data ; switch (operation) { case ID_PRED_ADD: for (i=0 ; i<ncases ; i++) *dptr++ = sig1->sig[i] + sig2->sig[i] ; break ; case ID_PRED_SUBTRACT: for (i=0 ; i<ncases ; i++) *dptr++ = sig1->sig[i] - sig2->sig[i] ; break ; case ID_PRED_MULTIPLY: for (i=0 ; i<ncases ; i++) *dptr++ = sig1->sig[i] * sig2->sig[i] ; break ; case ID_PRED_DIVIDE: for (i=0 ; i<ncases ; i++) *dptr++ = (sig2->sig[i] != 0.0) ? sig1->sig[i] / sig2->sig[i] : 0.0; break ; } /* Count how many of these signals have names not already in use. Then allocate additional memory for their pointers. */ MEMTEXT ( "COMBINE: signals array" ) ; if (*nsigs) { // If signals already exist ivar = *nsigs ; // This many signals so far sptr = *signals ; // Array of pointers to them for (i=0 ; i<misc->names->n ; i++) { // Check every new name if (! misc->names->len[i]) // Some may be NULL continue ; // Obviously skip them for (j=*nsigs-1 ; j>=0 ; j--) { // Check every existing signal if (! strcmp ( misc->names->start[i] , sptr[j]->name )) // There? break ; // If found, quit looking } if (j < 0) // Means not there ++ivar ; // So count this new entry } sptr = (Signal **) REALLOC ( sptr , ivar * sizeof(Signal *) ) ; } else sptr = (Signal **) MALLOC ( nvars * sizeof(Signal *) ) ; if (sptr == NULL) { FREE ( data ) ; strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } *signals = sptr ; /* Now create new signals for each variable. If a signal of the same name exists, delete it first. */ ivar = 0 ; for (i=0 ; i<misc->names->n ; i++) { // Check all names if (! misc->names->len[i]) // Some may be NULL continue ; // Obviously skip them for (j=*nsigs-1 ; j>=0 ; j--) { // Search existing signals for same name if (! strcmp ( misc->names->start[i] , sptr[j]->name )) { // There? MEMTEXT ( "COMBINE: delete duplicate signal" ) ; delete ( sptr[j] ) ; // If so, delete this signal break ; // And quit looking } } if (j < 0) { // Means new, unique name j = *nsigs ; // Tack it onto end of signal array ++*nsigs ; // And count it } if (ivar) { // In this case, must allocate for new signal MEMTEXT ( "COMBINE: temp signal" ) ; temp = (double *) MALLOC ( ncases * sizeof(double) ) ; if (temp == NULL) { strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } memcpy ( temp , data , ncases * sizeof(double) ) ; } else temp = data ; MEMTEXT ( "COMBINE: new Signal" ) ; sptr[j] = new Signal ( misc->names->start[i] , ncases , temp ) ; if ((sptr[j] == NULL) || ! sptr[j]->n) { if (sptr[j] != NULL) { delete sptr[j] ; sptr[j] = NULL ; } strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } ++ivar ; } // For all names return 0 ; }
double MutualInformationDiscrete::conditional ( short int *bins_x ) { int i, ix, iy, nbins_x, *grid, *marginal_x ; double CI, pyx, cix ; MEMTEXT ( "MutualInformationDiscrete::conditional()" ) ; /* Compute the number of bins */ nbins_x = 0 ; for (i=0 ; i<ncases ; i++) { if (bins_x[i] > nbins_x) nbins_x = bins_x[i] ; } ++nbins_x ; // Number of bins is one greater than max bin because org=0 /* Compute the marginal of x and the counts in the nbins_x by nbins_y grid */ marginal_x = (int *) MALLOC ( nbins_x * sizeof(int) ) ; assert (marginal_x != NULL) ; grid = (int *) MALLOC ( nbins_x * nbins_y * sizeof(int) ) ; assert ( grid != NULL ) ; for (ix=0 ; ix<nbins_x ; ix++) { marginal_x[ix] = 0 ; for (iy=0 ; iy<nbins_y ; iy++) grid[ix*nbins_y+iy] = 0 ; } for (i=0 ; i<ncases ; i++) { ix = bins_x[i] ; ++marginal_x[ix] ; ++grid[ix*nbins_y+bins_y[i]] ; } /* Compute the conditional entropy */ CI = 0.0 ; for (ix=0 ; ix<nbins_x ; ix++) { if (marginal_x[ix] > 0) { cix = 0.0 ; for (iy=0 ; iy<nbins_y ; iy++) { pyx = (double) grid[ix*nbins_y+iy] / (double) marginal_x[ix] ; if (pyx > 0.0) cix += pyx * log ( pyx ) ; } } CI += cix * marginal_x[ix] / ncases ; } FREE ( marginal_x ) ; FREE ( grid ) ; return -CI ; }