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; }
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.