This is ART2_Basic.m in view mode; [Download] [Up]
// Basic ART2 Object provides compressed acces routines // and system parameter #import <objc/Object.h> #import "ART2_Basic.h" #import "ART_STM.h" #import "ART_LTM.h" #include "ART_Func.h" // only for the Alert checking usw. #import <appkit/Application.h> #import <appkit/Control.h> #import <appkit/TextField.h> #import <appkit/Window.h> #import <appkit/Panel.h> #import <appkit/Cursor.h> #import <appkit/Matrix.h> #import <appkit/Cell.h> #import <stdlib.h> #import <string.h> #import <objc/NXStringTable.h> /* #define ART_STABLE_LEARNING 1 #define ART_ONE_LEARNING 0 #define ART_STD_MODE 0 #define ART_EXT_MODE 1 #define ART_F2_OFF -1 #define ART_MIX 0 #define ART_SUB 1 #define ART_SUP 2 #define ART_IDE 3 */ #define ART_READ(x) NXRead(stream,&x,sizeof(x)) #define ART_WRITE(x) NXWrite(stream,&x,sizeof(x)) // translate the V array in an inververs array inv_V void invert_of(int M,float *V ,float *inv_V, float theta); void mulVec(int M,float *mul1 ,float *mul2,float *prod); // build the magic R array and returns its norm float calc_R_with(int M,float *Q ,float *P, float *R, float c); @implementation ART2_Basic : Object + new { self=[super new]; return self; } - saveinto:(NXStream *)stream { ART_WRITE(M); ART_WRITE(N); ART_WRITE(rho); ART_WRITE(rhoset); ART_WRITE(theta); ART_WRITE(a); ART_WRITE(b); ART_WRITE(c); ART_WRITE(d); ART_WRITE(h); ART_WRITE(ac_diff); ART_WRITE(z_diff); ART_WRITE(BU_inst); ART_WRITE(exor_thresh); ART_WRITE(i_min); ART_WRITE(i_max); ART_WRITE(art2_mode); ART_WRITE(learn_mode); [LTM saveinto:stream as:ART_LTM_BIN]; return self; } - loadfrom:(NXStream *)stream { int i,n; [super init]; ART_READ(M); ART_READ(N); ART_READ(rho); ART_READ(rhoset); ART_READ(theta); ART_READ(a); ART_READ(b); ART_READ(c); ART_READ(d); ART_READ(h); ART_READ(ac_diff); ART_READ(z_diff); ART_READ(BU_inst); ART_READ(exor_thresh); ART_READ(i_min); ART_READ(i_max); ART_READ(art2_mode); ART_READ(learn_mode); [self build_ART2]; [self resetLTM]; R =NXZoneMalloc([self zone],M*sizeof(float)); PatQueue=NXZoneMalloc([self zone],N*sizeof(int)); zeroP=NXZoneMalloc([self zone],M*sizeof(float)); for (i=0;i<M;i++) zeroP[i]=0.0; [LTM loadfrom:stream]; return self; } - init_M:(int)Vec_dim N:(int)F2_dim { int i; [super init]; M=Vec_dim; N=F2_dim; [self build_ART2]; [self setdefault_config]; [self resetLTM]; R =NXZoneMalloc([self zone],M*sizeof(float)); PatQueue=NXZoneMalloc([self zone],N*sizeof(int)); zeroP=NXZoneMalloc([self zone],M*sizeof(float)); for (i=0;i<M;i++) zeroP[i]=0.0; return self; } - free { [F0 free]; [F1 free]; [F2 free]; [LTM free]; [F0x free]; NXZoneFree([self zone],R); NXZoneFree([self zone],zeroP); NXZoneFree([self zone],PatQueue); return [super free]; } - build_ART2 { F0=[ART_STM new]; F1=[ART_STM new]; F2=[ART_STM new]; LTM=[ART_LTM new]; F0x=[ART_STM new]; [F0 init:M]; [F1 init:M]; [F2 init:N]; [LTM init:M of:N]; [F0x init:M]; return self; } - (BOOL)resizeART { int i,j, extN, ac; float *TMP; char buf1[255],buf2[255]; if ([LTM estabNodes]==N){ // new dimension of F2 extN=N+5; // free and realloc the pattern queue NXZoneFree([self zone],PatQueue); PatQueue=NXZoneMalloc([self zone],extN*sizeof(int)); // generate a new LTM object tmpLTM=[ART_LTM new]; [tmpLTM init:M of:extN]; [tmpLTM set_d:d h:h]; [tmpLTM set_zero_with:BU_inst]; [tmpLTM setestabNodes:N]; [tmpLTM newPattern]; // translate the TD templates for (j=0;j<N;j++) [tmpLTM set:[LTM TD_of:j] of:M to_TD_of:j]; // emty the pattern queue for (j=0;j<extN;j++) PatQueue[j]=ART_F2_OFF; // translate the BU templates form the old N for (i=0;i<M;i++) [tmpLTM set:[LTM BU_of:i] of:N to_BU_of:i]; // free LTM and switch tmpLTM to LTM [LTM free]; // free F2 and install again with extN tmpF2=[ART_STM new]; [tmpF2 init:extN]; // save the last active node ac=[F2 activeNode]; [F2 free]; F2=tmpF2; TMP=[F2 get_U]; if (ac >= 0) TMP[ac]=1; [F2 MaxAct_with:extN]; LTM=tmpLTM; // switch to the new F2 size of N N=extN; return YES; } return NO; } - setdefault_config { // system parameter rho=0.955; rhoset=0.95; theta=1.1/sqrt( (float)M ); c=0.225; d=0.8; h=1.0; a=5.0; b=5.0; ac_diff=0.01; z_diff=0.01; BU_inst=0.1; exor_thresh=0.98; sigmoWidth=0.001; i_min=2; i_max=100; // performance parameter art2_mode=ART_STD_MODE; learn_mode=ART_ONE_LEARNING; set_type=ART_MIX; return self; } - update_syspara { [F0 set_a:a b:b theta:theta d:0.0]; [F0 setIterationmin:i_min max:i_max stable:ac_diff]; [F0 set_NoLinFunc:ART_STM_SIGMO]; [F1 set_a:a b:b theta:theta d:d]; [F1 setIterationmin:i_min max:i_max stable:ac_diff]; [F1 set_NoLinFunc:ART_STM_SIGMO]; [F2 set_a:a b:b theta:theta d:0.0]; [F2 setIterationmin:i_min max:i_max stable:ac_diff]; [F2 set_NoLinFunc:ART_STM_SIGMO]; [F0x set_a:a b:b theta:theta d:0.0]; [F0x setIterationmin:i_min max:i_max stable:ac_diff]; [F0x set_NoLinFunc:ART_STM_SIGMO]; [LTM set_d:d h:h]; return self; } - zeroSTMs { [F0 set_zero]; [F1 set_zero]; [F2 set_zero]; [F0x set_zero]; return self; } - resetLTM { [LTM set_zero_with:BU_inst]; return self; } // set the input pattern and initialize the STM's - setPattern:(float *)In { int j; InPat=In; [LTM newPattern]; for(j=0;j<N;j++) PatQueue[j]=ART_F2_OFF; set_type=ART_MIX; return self; } // preprocessing - (int)preproc { [F0 set_I:InPat and_E:zeroP]; return [F0 iterate]; } // chooseF2 - (int)chooseF2 { [F1 set_zero]; [F1 set_I:[F0 get_P] and_E:zeroP]; [F1 iterate]; // looking for the winner at F2 an store for output [LTM korrelate_with:[F1 get_P] to:[F2 get_U]]; [F2 MaxAct_with:[LTM estabNodes]+1]; if (art2_mode) set_type=[self exorproc]; return [F2 activeNode]; } - compair { [F1 set_I:[F0 get_P] and_E:[LTM TD_of:[F2 activeNode]] ]; [F1 iterate]; return self; } // perform F1 with TD template an return the match - (BOOL)match { // switch to the required rho for vigilance // in extended mode tmprho is set to rhoset in case of // a super or subset presentation //tmprho= (art2_mode) ? ( (set_type) ? rho:rhoset ):rho); if (art2_mode) if (set_type!=ART_MIX) tmprho=rhoset; else tmprho=rho; else tmprho=rho; // store the rho value in r for display r=calc_R_with(M,[F0 get_P],[F1 get_P],R,c); return (tmprho > r) ? NO:YES; } // perform learning with the stable criterion as return - (float)learning { return [LTM learnPattern:[F1 get_P] toNode:[F2 activeNode]]; } // perform the magic exor processing returns the type of set - (int)exorproc { int F2_on,i; float tmp; float sigE,sigI,sigS; if ([self newNode]) return (int)ART_SUB; F2_on=[F2 activeNode]; // preprocessing the template [F0x set_zero]; [F0x set_I:[LTM TD_of:F2_on] and_E:zeroP]; [F0x iterate]; // art norm of I and the template's preprocessed sigE=[self significance_of:[F0x get_Q]]; sigI=[self significance_of:[F0 get_P]]; // note that S = O*inv(T) is written to p of F0x // w of act as a buffer if ( sigE < sigI) { // the input I could be a superset of E invert_of(M,[F0x get_Q],[F0x get_W],theta); mulVec(M,[F0 get_P],[F0x get_W],[F0x get_P]); sigS=[self significance_of:[F0x get_P]]; // analysing EXOR pattern and decide of real superset if ( fabs(sigS+sigE-sigI)< 1.0 ) return (int)ART_SUP; } else { // the input I could be a subset of E invert_of(M,[F0 get_P],[F0x get_W],theta); mulVec(M,[F0x get_W],[F0x get_Q],[F0x get_P]); sigS=[self significance_of:[F0x get_P]]; // Input and teplate have the same features if (sigS==0.0) return(int)ART_IDE; // analysing EXOR pattern and decide of real subset if ( fabs(sigS+sigI-sigE)< 1.0 ) return (int)ART_SUB; } return (int)ART_MIX; } -(BOOL)setExorPattern { // Note that the EXOR Pattern S is the part of the input // that the template need additional to figure the input. // Hence the EXOR pattern should be presented to the system // virually as a new pattern. This pattern is also orthogonal // to its source. // The input Pattern should be : // 1. superset // if ( (set_type==ART_SUP) ) // in this case the Pointer to F0x is set to F1 so that // for further search the vector P of F0x, containing // the processed EXOR-pattern is going to be treated as // a new pattern with full ART ability. { L2_norm_Vec([F0x get_P],[F0 get_P],M); return YES; } else return NO; } - (BOOL)newNode { if ([F2 activeNode]==[LTM estabNodes]) return YES; else return NO; } - markActiveNode { int j; for(j=0;PatQueue[j]!=ART_F2_OFF;j++); PatQueue[j]=[F2 activeNode]; return self; } // additionl procedures float calc_R_with(int M,float *Q, float *P,float *R,float c) { int i; float tmp; tmp=c*L2_norm(P,M)+L2_norm(Q,M); tmp=(tmp >0.1)? tmp: 1; for (i=0;i<M;i++) R[i]=(Q[i]+P[i]*c)/tmp; return L2_norm(R,M) ; } void invert_of(int M,float *V ,float *inv_V,float theta) { int i; float tmp=L2_norm(V,M); for (i=0; i<M; i++) inv_V[i]= ( (V[i]/tmp) < theta) ? 1.0 : 0.0 ; return; } void mulVec(int M,float *mul1 ,float *mul2,float *prod) { int i; for (i=0; i<M; i++) prod[i]=mul1[i]*mul2[i]; return; } // calculating the special ART-norm of a vector - (float)significance_of:(float *)V { float tmp=L2_norm(V,M); int i,s=0; for (i=0; i<M; i++) if ( (V[i]/tmp) > theta) s++; return (float)s; } // direct access methods - F0 { return F0; } - F1 { return F1; } - F2 { return F2; } - F0x { return F0x; } - LTM { return LTM; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.