This is ARTDoc.m in view mode; [Download] [Up]
// the great ART Document Object
#import "ARTDoc.h"
#import "Controller.h"
#import "Pattern.h"
#import "ART_Animator.h"
#import "ART2_Basic.h"
#import "ART_STM.h"
#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>
#import <libc.h> // For random(), etc...
#import <dpsclient/wraps.h> // For PS and DPS function prototypes
#define frand() ((float) rand() / (RAND_MAX+1.0))
/*
int PatRow,PatCol,PatDim,PatNum;
int F2_on=ART_F2_OFF;
char buf[256];
*/
// Animator mesages macro
#define A_MSG(F_msg) [[Animator F_msg] setStringValue:buf]
// preform states
#define ART_PERFORM_NEW 0
#define ART_PERFORM_PRE 1
#define ART_PERFORM_SEARCH 2
#define ART_PERFORM_MATCH 3
#define ART_PERFORM_LEARN_EXOR 4
#define ART_PERFORM_LEARN_ONE 5
#define ART_PERFORM_LEARN_STABLE 6
int perform_flag=ART_PERFORM_NEW;
#define ART_GO 0
#define ART_STOP 1
#define STEP if (go_flag)
@implementation ARTDoc
static void newLocation(NXPoint *p)
{
static count = 0;
p->x += (20.0 * count);
p->y -= (25.0 * count);
count = (count > 10)? 0 : count+1;
}
int DimMtx(int M,int t)
{
int i,td=t,tu=t;
for (i=M-1;i--;) {
if (0.0==fmod( (double)M,(double)td ))
return td;
if (0.0==fmod( (double)M,(double)tu ))
return tu;
td--;
tu++;
td=( td==1 ) ? 2:td;
tu=( tu==M ) ? M-1:tu;
}
return 0;
}
- init
{
return [self initFromFile:NULL];
}
- initFromFile:(const char *)file
{
NXStream *stream;
NXRect theFrame;
[super init];
[NXApp loadNibSection:"ARTDoc.nib" owner:self];
[window setDelegate:self];
[window getFrame:&theFrame];
newLocation(&theFrame.origin);
[window moveTo:theFrame.origin.x :theFrame.origin.y];
// getting the object pointer
//Control=[NXApp delegate];
Animator=[[NXApp delegate] Animator_id];
Pat=[[NXApp delegate] Pattern_id];
stringTable=[[NXApp delegate] stringTable];
// calc the pattern parameter
PatDim=[Pat Dimension];
PatNum=[Pat Quantity]-1;
// install SearchArray
[self setSearchArray];
// install the corresponding ART Modul
ARTModul=[ART2_Basic new];
artp = (struct ARTModulDefs *)ARTModul;
if (file) {
stream=NXMapFile(file,NX_READONLY);
if (stream) {
NX_DURING
[ARTModul loadfrom:stream];
NXCloseMemory(stream,NX_FREEBUFFER);
//NX_VALRETURN(self);
NX_HANDLER
NX_DURING
NXCloseMemory(stream,NX_FREEBUFFER);
NX_HANDLER
// ignore any error at this point
NX_ENDHANDLER
return nil;
NX_ENDHANDLER
}
else
return nil;
PatDim=artp->M;
//[self ARTState];
} // of if file
else
// default with the corresponding dimension
[ARTModul init_M:PatDim N:(int)[Pat Quantity]];
perform_flag=ART_PERFORM_NEW;
go_flag=ART_STOP;
disp_flag=ART_PAT_DISP;
// update the animator
PatRow=DimMtx(PatDim,(int)sqrt(PatDim));
PatCol=(int)PatDim/PatRow;
[self setAnimator];
// show the Document
//[self ARTState];
[self getARTDefs];
[window makeKeyAndOrderFront:nil];
return self;
}
- free
{
NXZoneFree([self zone],SearchArray);
[ARTModul free];
return [super free];
}
- setSearchArray
{
int i,q;
q=[Pat Quantity];
if (SearchArray) NXZoneFree([self zone],SearchArray);
SearchArray=NXZoneMalloc([self zone],q*sizeof(int));
for (i=0;i<q;i++) SearchArray[i]=0;
[queueOut setBackgroundGray:NX_LTGRAY];
return self;
}
- (BOOL)noSearch
{
int i,q;
//(if (!SearchArray) return NO;
q=[Pat Quantity];
for (i=0;i<q && (1==SearchArray[i]);i++);
return (i==(q)) ? YES:NO;
}
- setAnimator
{
[Animator setDispMode:disp_flag];
[Animator setRow:PatRow Col:PatCol];
[Animator setDim:PatDim Mag:[Pat Maximum]*1.1 zMax:1.0/(1-artp->d)];
[Animator setInVec:artp->zeroP];
[Animator setPreVec:artp->zeroP];
[Animator setTmpVec:artp->zeroP];
[Animator showAll];
return self;
}
- setFileName:(char *)aName
{
if (fileName)
free(fileName);
fileName = (char *)malloc(strlen(aName)+1);
strcpy(fileName,aName);
[window setTitleAsFilename:fileName];
return self;
}
- (char *)fileName
{
return fileName;
}
- save:sender
{
int fd;
NXStream *stream;
volatile BOOL hadAnError = NO;
if (fileName) {
fd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
stream = NXOpenFile(fd, NX_WRITEONLY);
if (stream) {
NX_DURING
// NXWRITE(stream,%s,[self name]);
[ARTModul saveinto:stream];
NXFlush(stream);
NXClose(stream);
close(fd);
NX_HANDLER
hadAnError = YES;
NX_DURING
NXFlush(stream);
NXClose(stream);
close(fd);
NX_HANDLER
/* ignore any error at this point */
NX_ENDHANDLER
NX_ENDHANDLER
} // if stream
else
hadAnError = YES;
// message in case of an error
if (hadAnError) {
NXRunAlertPanel(STRTAB("save alert title"),
STRTAB("save alert message"),
STRTAB("OK"),
NULL, NULL,fileName);
return nil;
}
else {
[window setDocEdited:NO];
return self;
}
} //of if filename
return nil;
}
- creatLTMdat:sender
{
int fd;
NXStream *stream;
char *p;
if (fileName) {
strcpy(buf,fileName);
if (p = rindex(buf,'.')) {
*++p = '\0';
strcat(buf,"LTMdat");
}
fd = open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0666);
stream = NXOpenFile(fd, NX_WRITEONLY);
// write only LTM weigths in ascii file with extension LTMdat
[[ARTModul LTM] saveinto:stream as:ART_LTM_ASCII];
NXFlush(stream);
NXClose(stream);
close(fd);
}
return self;
}
- performNEW
{
int i;
// get the NeXT Pattern and show
if ([[NXApp delegate] Rand_sel])
PatNum=(int)(frand()*(float)[Pat Quantity]);
else {
PatNum++;
PatNum=(PatNum>=[Pat Quantity]) ? 0:PatNum;
}
// assume that this pattern will be coded without search
SearchArray[PatNum]=1;
// show the pattern number and clean the textcells
sprintf(buf,STRTAB("Input is pattern No.: %d"),PatNum);
A_MSG(F0msg);
sprintf(buf," ");
A_MSG(F1msg);
A_MSG(F2msg);
[self updateARTDefs];
// Initialize ART & Animator and show input pattern
[Animator setInVec:[Pat thePattern:PatNum]];
[Animator showInVec];
// Set preprocessed Pattern
[ARTModul zeroSTMs];
[ARTModul setPattern:[Pat thePattern:PatNum]];
// hiding the previous template
[Animator setTmpVec:[[ARTModul F0] get_U]];
[Animator showTmpVec];
// Preprocessing
i=[ARTModul preproc];
// show Pattern and iterations
[Animator setPreVec:[[ARTModul F0] get_P]];
[Animator showPreVec];
STEP {
sprintf(buf,STRTAB("F0 stability after %d iterations"),i);
A_MSG(F1msg);
}
// define the next task
if (L2_norm([[ARTModul F0] get_P],artp->M)<0.01)
perform_flag=ART_PERFORM_NEW;
else
perform_flag=ART_PERFORM_SEARCH;
return self;
}
-performSEARCH
{
float sigT,sigI,sigS;
// perform the search and in the search methode the exorproc
F2_on=[ARTModul chooseF2];
STEP {
if (F2_on==[[ARTModul LTM] estabNodes])
sprintf(buf,STRTAB("new template is choosen %d "),F2_on);
else {
if (artp->art2_mode) {
switch(artp->set_type) {
case ART_MIX:
sprintf(buf,STRTAB("( Mixset ) choosen template is %d "),F2_on);
break;
case ART_SUP:
sprintf(buf,STRTAB("( Superset ) choosen template is %d "),F2_on);
break;
case ART_SUB:
sprintf(buf,STRTAB("( Subset ) choosen template is %d "),F2_on);
break;
case ART_IDE:
sprintf(buf,STRTAB("( Identical ) choosen template is %d "),F2_on);
break;
}
// STOP
/*
sigS=[ARTModul significance_of:[[ARTModul F0x] get_P]];
sigT=[ARTModul significance_of:[[ARTModul F0x] get_Q]];
sigI=[ARTModul significance_of:[[ARTModul F0 ] get_P]];
sprintf(buf,STRTAB("In %5.3f Tmp %5.3f Exor %5.3f "),
sigI,sigT,sigS);
A_MSG(F1msg);
if (sigS==0.0) sprintf(buf,"Identical set");
else {
sprintf(buf,"Mixed set");
if ( fabs(sigS+sigT-sigI) < 1.0) sprintf(buf,"Super set");
if ( fabs(sigS+sigI-sigT) < 1.0) sprintf(buf,"Sub set");
}
[Animator setPreVec:[[ARTModul F0x] get_P]];
[Animator showPreVec];
*/
// STOP
}
else
sprintf(buf,STRTAB("choosen template is %d "),F2_on);
}
A_MSG(F2msg);
} // of STEP
perform_flag=ART_PERFORM_MATCH;
return self;
}
- performMATCH
{
// iterate F1 and decide of good matching
[ARTModul compair];
if ([ARTModul match]) {
// show template is go and step by step modus
[Animator setTmpVec:[[ARTModul LTM] TD_of:F2_on]];
[Animator showTmpVec];
[ARTModul markActiveNode];
//
// extended mode only tricky one
// In case of extended mode, a real subset input and a stable
// template, the template will be completely erased to increase
// the recoding time of the subset to its superset template
if (artp->art2_mode)
if( ![ARTModul newNode] &&
[[ARTModul LTM] is:F2_on stable:artp->exor_thresh] &&
(artp->set_type==ART_SUB) )
[[ARTModul LTM] zero_template:F2_on with:artp->BU_inst];
// extended mode end
//
if ([ARTModul newNode]) [self setSearchArray];
perform_flag=ART_PERFORM_LEARN_ONE;
return self;
}
else {
STEP {
[Animator setTmpVec:[[ARTModul LTM] TD_of:F2_on]];
[Animator showTmpVec];
sprintf(buf,STRTAB("bad match (%4.3f < %4.3f) reset of Node %d"),
artp->r,artp->tmprho,F2_on);
A_MSG(F2msg);
}
[[ARTModul LTM] resetNode:F2_on];
// finaly reset all nosearch labels
[self setSearchArray];
perform_flag=ART_PERFORM_SEARCH;
}
return self;
}
-performLEARN_ONE
{
float z;
// perform learning and set window edited
z=[ARTModul learning];
[Animator showTmpVec];
[window setDocEdited:YES];
STEP {
sprintf(buf,STRTAB("good match (%4.3f > %4.3f) stable %4.3f"),
artp->r,artp->tmprho,z);
A_MSG(F2msg);
}
//
// define NeXT task
if (artp->learn_mode)
perform_flag=ART_PERFORM_LEARN_STABLE;
else
// only in extended mode
if (artp->art2_mode)
perform_flag=ART_PERFORM_LEARN_EXOR;
else
perform_flag=ART_PERFORM_NEW;
return self;
}
-performLEARN_STABLE
{
float z;
// perform the stable learning in the slow modus i.e.
// after every learning the F1 is set zero and will be newly
// iterated
[[ARTModul F1] set_zero];
[ARTModul compair];
z=[ARTModul learning];
//
STEP {
sprintf(buf,STRTAB("good match (%4.3f > %4.3f) stable %4.3f"),
artp->r,artp->tmprho,z);
A_MSG(F2msg);
}
[Animator showTmpVec];
//
// looking for stability of the weights and define NeXT task
if( (artp->z_diff<z) && [ARTModul match] )
perform_flag=ART_PERFORM_LEARN_STABLE;
else
if (artp->art2_mode)
// only in extended mode :
perform_flag=ART_PERFORM_LEARN_EXOR;
else
perform_flag=ART_PERFORM_NEW;
return self;
}
-performLEARN_EXOR
{
// Note that the EXOR Pattern P 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
// 2. stable learned template
//
if ( (artp->set_type==ART_SUP)
&& [ [ARTModul LTM] is:F2_on stable:artp->exor_thresh ]
) {
// 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([[ARTModul F0x] get_P],
[[ARTModul F0 ] get_P],artp->M);
//
[[ARTModul LTM ] newPattern];
perform_flag=ART_PERFORM_SEARCH;
//
// show the action and clean template textcell and graph
STEP {
sprintf(buf,STRTAB("Exor pattern features"));
A_MSG(F1msg);
sprintf(buf," ");
A_MSG(F2msg);
}
// hiding the previous template
[Animator setTmpVec:artp->zeroP];
[Animator showTmpVec];
// show Pattern and iterations
[Animator setPreVec:[[ARTModul F0] get_P]];
[Animator showPreVec];
}
else
perform_flag=ART_PERFORM_NEW;
return self;
}
- step:sender
{
switch(perform_flag) {
case ART_PERFORM_NEW:
[self performNEW];
break;
case ART_PERFORM_MATCH:
[self performMATCH];
break;
case ART_PERFORM_SEARCH:
if ([ARTModul resizeART]) {
sprintf(buf,STRTAB("ART is resized to %d"),artp->N);
[queueOut setStringValue:buf];
}
[self performSEARCH];
break;
case ART_PERFORM_LEARN_ONE:
[self performLEARN_ONE];
[self ARTState];
break;
case ART_PERFORM_LEARN_STABLE:
[self performLEARN_STABLE];
break;
case ART_PERFORM_LEARN_EXOR:
[self performLEARN_EXOR];
break;
}
return self;
}
void PerformIt(DPSTimedEntry te, double timeNow, void *data)
{
[(id)data animate];
}
- animate
{
NXEvent dummyEvent; // For peeking at the event queue.
do {
[self step:nil];
} while ([NXApp peekNextEvent:NX_ALLEVENTS
into:&dummyEvent
waitFor:0.0
threshold:NX_BASETHRESHOLD] == NULL);
return self;
}
- (BOOL)isPerforming
{
return (ART_GO==go_flag) ? YES:NO;
}
- (BOOL)matchWithPat
{
return ( [Pat Dimension]==artp->M ) ? YES:NO ;
}
- set_go
{
if (go_flag==ART_STOP) {
// Call the PerformIt() function as often as possible...
ARTTimedEntry=DPSAddTimedEntry(0.0, &PerformIt,
self,NX_BASETHRESHOLD);
go_flag=ART_GO;
}
return self;
}
- set_stop
{
if (go_flag==ART_GO) {
DPSRemoveTimedEntry(ARTTimedEntry);
// [self finishCycle];
go_flag=ART_STOP;
}
return self;
}
- stepPattern
{
do {
[self step:nil];
}
while (perform_flag!=ART_PERFORM_NEW);
return self;
}
- finishCycle
{
while (perform_flag!=ART_PERFORM_NEW) {
[self step:nil];
}
return self;
}
- resetLTM:sender
{
// finish for n new pattern
[self finishCycle];
[ARTModul resetLTM];
[self setSearchArray];
return self;
}
- ARTState
{
int i;
char a[100];
int *PQ=artp->PatQueue;
[inputOut setIntValue:PatNum];
// sprintf(buf,STRTAB("%d of %d"),[[ARTModul LTM] estabNodes],artp->N);
// [estabOut setStringValue:buf];
[estabOut setIntValue:[[ARTModul LTM] estabNodes]];
buf[0]='\0';
for(i=0; PQ[i]!=ART_F2_OFF; i++) {
sprintf(a,"%d ",PQ[i]);
strcat(buf,a);
}
// for no search print out additional
if (SearchArray[PatNum]==1) {
sprintf(a,"no search");
strcat(buf,a);
}
// for no search amoung the patternwell highlight textfield
if ([self noSearch])
[queueOut setBackgroundGray:NX_WHITE];
else
[queueOut setBackgroundGray:NX_LTGRAY];
if (strlen(buf)) {
[queueOut setStringValue:buf];
strcpy(a,buf);
// Animator Output F0msg
sprintf(buf,STRTAB("Input is pattern No.: %d"),PatNum);
A_MSG(F0msg);
// Animator Output F01msg
sprintf(buf,"coding to : ");
strcat(buf,a);
A_MSG(F01msg);
}
return self;
}
- setRow:sender
{
int r=[RowIn intValue];
r=(r<1 || r>PatDim) ? PatRow:r;
PatRow=DimMtx(PatDim,r);
PatCol=(int)PatDim/PatRow;
[RowIn setIntValue:PatRow];
[ColIn setIntValue:PatCol];
[Animator setRow:PatRow Col:PatCol ];
[Animator showAll];
return self;
}
- setCol:sender
{
int c=[ColIn intValue];
c=(c<1 || c>PatDim) ? PatCol:c;
PatCol=DimMtx(PatDim,c);
PatRow=(int)PatDim/PatCol;
[RowIn setIntValue:PatRow];
[ColIn setIntValue:PatCol];
[Animator setRow:PatRow Col:PatCol];
[Animator showAll];
return self;
}
- setVecModus:sender
{
if (disp_flag!=ART_VEC_DISP) {
disp_flag=ART_VEC_DISP;
[Animator setDispMode:disp_flag];
[Animator showAll];
}
return self;
}
- setPatModus:sender
{
if (disp_flag!=ART_PAT_DISP) {
disp_flag=ART_PAT_DISP;
[Animator setDispMode:disp_flag];
[Animator showAll];
}
return self;
}
- setDelegate:anObject
{
return self;
}
// comunication
- (int)inputPattern
{
return PatNum;
}
- (int)codesNodes
{
int i;
for(i=0; artp->PatQueue[i]!=ART_F2_OFF; i++);
return i;
}
- (int *)PatQueue
{
return artp->PatQueue;
}
- (int)F2Nodes
{
return [[ARTModul LTM] estabNodes];
}
- (float *)theTemplate:(int)i
{
return [[ARTModul LTM] TD_of:i];
}
// tricky delegations
- windowDidBecomeMain:sender
{
[window makeFirstResponder:window];
if ([[NXApp delegate] document] != self) {
[[NXApp delegate] stopAll];
if ([self matchWithPat]) {
[[NXApp delegate] unlookCTRL];
if ([self isPerforming])
[[NXApp delegate] setGoState];
else {
perform_flag=ART_PERFORM_NEW;
[[NXApp delegate] setStopState];
}
}
else {
[[NXApp delegate] lookCTRL];
[[NXApp delegate] MisMatchAlert];
}
[[NXApp delegate] setDocument:self];
[self setAnimator];
}
return self;
}
- windowDidResignMain:sender
{
//Animator=nil;
//if (perform_flag!=ART_PERFORM_NEW) [self set_stop];
// if ([[NXApp delegate] document] == self)
// [[NXApp delegate] setDocument:nil];
return self;
}
- windowDidMiniaturize:sender
{
return self;
}
- windowWillClose:sender
{
int choice;
if ([window isDocEdited]) {
if (!stringTable)
stringTable = [[NXApp delegate] stringTable];
choice = NXRunAlertPanel(
STRTAB("Close"),
STRTAB("ART Save it?"),
STRTAB("Yes"),
STRTAB("No"),
STRTAB("Cancel"));
switch (choice) {
case NX_ALERTALTERNATE:
break;
case NX_ALERTDEFAULT:
[[NXApp delegate] save:nil];
break;
case NX_ALERTOTHER:
return nil;
}
}
[self windowDidResignMain:nil];
[window setDelegate:nil];
[self set_stop];
[self free];
return sender;
}
- updateARTDefs // from the display and set the ARTModul
{
// ARTMode
artp->art2_mode=[[ARTModeMtx selectedCell] tag];
// Learning
artp->learn_mode=[[ARTLearnMtx selectedCell] tag];
// field const
artp->a=MAX(0.1,MIN([f_a floatValue],50.0));
artp->b=MAX(0.1,MIN([f_b floatValue],50.0));
// special check cause there is a dependance between d and c
// c has changed
if (artp->c!=[f_c floatValue]) {
artp->c=MAX(1E-03,MIN([f_c floatValue],(1.0-artp->d)/artp->d ));
// artp->d=MAX(1E-03,MIN([f_d floatValue],1/(1.0+artp->c) ));
}
// d has changed
if (artp->d!=[f_d floatValue]) {
artp->d=MAX(1E-03,MIN([f_d floatValue],1/(1.0+artp->c) ));
// artp->c=MAX(1E-03,MIN([f_c floatValue],(1.0-artp->d)/artp->d ));
}
// vigilance
//if ([f_rho floatValue] > 1.0) artp->rho=1.0;
//if ([f_rho floatValue] < 0.0) artp->rho=0.0;
artp->rho=MAX(0.0,MIN([f_rho floatValue],0.9999999999999));
artp->rhoset=MAX(0.0,MIN([f_rhoset floatValue],1.0));
// thresh
artp->theta=MAX(0.0,MIN([f_theta floatValue],1.0));
// integration
artp->z_diff=MAX(1E-10,MIN([f_z_diff floatValue],1.0));
artp->h=MAX(1E-5,MIN([f_h floatValue],10.0));
// activity
artp->ac_diff=MAX(1E-10,MIN([f_ac_diff floatValue],1.0));
// i_min has changed
if (artp->i_min!=[f_min intValue])
artp->i_min=MAX(1,MIN([f_min intValue],artp->i_max));
// i_max has changed
if (artp->i_max!=[f_max intValue])
artp->i_min=MAX(artp->i_min+1,MIN([f_max intValue],1000));
// BU
artp->BU_inst=MAX(1E-10,MIN([f_BU_inst floatValue],1.0));
// and finaly
[ARTModul update_syspara];
return self;
}
- getARTDefs // from the ARTModul and show
{
// ARTMode
[ARTModeMtx selectCellWithTag:(artp->art2_mode)];
// Learning
[ARTLearnMtx selectCellWithTag:(artp->learn_mode)];
// field const
[f_a setFloatValue:artp->a];
[f_b setFloatValue:artp->b];
[f_c setFloatValue:artp->c];
[f_d setFloatValue:artp->d];
// vigilance
[f_rho setFloatValue:artp->rho];
[f_rhoset setFloatValue:artp->rhoset];
// thresh
[f_theta setFloatValue:artp->theta];
// integration
[f_z_diff setFloatValue:artp->z_diff];
[f_h setFloatValue:artp->h];
// activity
[f_ac_diff setFloatValue:artp->ac_diff];
[f_min setIntValue:artp->i_min];
[f_max setIntValue:artp->i_max];
// BU
[f_BU_inst setFloatValue:artp->BU_inst];
// pattern parameter
[DimOut setIntValue:PatDim];
[RowIn setIntValue:PatRow];
[ColIn setIntValue:PatCol];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.