📄 nn.c
字号:
/* nn.c Copyright 1995 by Donald R. Tveter */
/* drt@mcs.com - http://www.mcs.com/~drt/home.html */
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <setjmp.h>
/* delete the following or comment it out if you have problems */
#define HOTKEYS
/* this is where you would want to #define UNIX and possibly
#define BSD or #define NEXT or else you can pass them to the
compiler with -DUNIX and maybe -DBSD or -DNEXT */
#ifdef BSD
#include <termios.h>
#elif defined NEXT
#include <malloc.h>
#include <sgtty.h>
#else /* SysV */
#include <malloc.h>
#include <termio.h>
#endif
#if defined(UNIX) && defined(HOTKEYS)
#ifdef BSD
struct termios raw; /* characteristics for hotkeys */
struct termios noraw; /* original characteristics */
#elif defined NEXT
struct sgttyb raw; /* characteristics for hotkeys */
struct sgttyb noraw; /* original characteristics */
#else /* the System V solution */
struct termio raw; /* characteristics for hotkeys */
struct termio noraw; /* original characteristics */
#endif
char onechar[1]; /* the buffer for the hotkey character */
#endif
#ifdef UNIX
#define REAL double
#define INT32 int
#define SIGINT 2
#elif defined DOS16
#include <stdlib.h>
#include <conio.h>
#define INT32 long
#define REAL float
#else
#include <stdlib.h>
#include <conio.h>
#define INT32 int
#define REAL float
#endif
#define BUFFSIZE 257
#define GE 1
#define GT 0
#define MAXINT 32767
#define MAXVAL 9.99999e+99
#define OUTSTRSIZE 257
#define scale(x) x
#define TRAIN 0
#define TEST 1
typedef struct node /* basic structure for each point */
{
int class; /* the correct classification */
int nn; /* the answer based on nn */
REAL *vector; /* the vector of coordinates */
struct node *next; /* to the next point */
} NODE;
typedef struct pat
{
NODE *point; /* used in finding k nearest neighbors */
REAL distsq;
struct pat *next;
} PAT;
typedef struct cpat /* used in clustering patterns */
{
int count;
struct cpat *next;
REAL *vector;
} CPAT;
typedef struct data
{
int npats; /* number of patterns */
int iterno; /* iteration number when data was found */
int right; /* number of patterns right */
int wrong; /* number of patterns wrong */
float pctright; /* percentage right */
} DATA;
char algorithm; /* flags lvq or dsm */
REAL alpha; /* learning rate */
NODE *blank; /* blank test pattern */
int bufferend; /* index of last character in input line */
int bufferptr; /* position of next character in buffer */
char buffer[BUFFSIZE];/* holds contents of one input line */
int ch; /* general purpose character variable */
PAT *closest; /* ptr to list of nearest neighbor patterns */
CPAT *clusterstart; /* start of the list of clusters */
jmp_buf cmdloopstate; /* to save state in case of a SIGINT */
FILE *copy; /* file to copy interactive session to */
char copyflag; /* flags the interactive copy */
int count; /* number of clusters in all */
int create; /* number of clusters created in ONE pass */
FILE *data; /* file for original data */
char *datafilename; /* copy of the data file name saved here */
int destroy; /* number of clusters removed */
char echo; /* controls echoing of characters during input */
char emptystring; /* for unused string values */
INT32 *errmat; /* addr of dynamic array for error matrix */
int errmatsize; /* size of error matrix */
INT32 *errtotal; /* addr of dynamic array for error totals */
REAL fract; /* fraction of patterns to ignore when clustering */
FILE *debug;
FILE *filestack[4]; /* allows for nested reads from files */
int filestackptr; /* has the index of the current file */
REAL highalpha; /* alpha to start training with */
char informat; /* controls format to read numbers */
REAL initiallambda; /* starting lambda */
char *inputfile; /* name of file to take extra commands from */
int iter; /* for counting iterations in one run */
int k; /* the k for k-nearest neighbor */
REAL lambda; /* lambda in the current pass */
int length; /* length of input vector */
int lineno; /* counts lines for pg */
int listcount; /* returns number of patterns from readpats */
char listpat; /* flags writing of patterns when evaluating them */
REAL lowalpha; /* alpha to end with */
REAL maxdist; /* distance used by the clustering routine */
int maxpasses; /* maximum number of passes thru cluster */
int nclasses; /* maximum number of possible answers */
int npats; /* number of training patterns */
REAL oneminus; /* one minus lambda */
char *original; /* original prototype file */
char outformat; /* controls format to print output */
int outofdate; /* flags out of date test stats */
char outstr[OUTSTRSIZE]; /* the output string */
NODE *initialprotos; /* a copy of the initial prototype points */
char *nearestfile; /* file to write nearest neighbors to */
char *newproto; /* new prototype file */
int npasses; /* number of passes to make thru training set */
int nprotos; /* number of prototype points */
int ntestpats; /* number of test patterns */
int pagesize; /* size of page on screen */
char *protofile; /* ptr to start of string */
NODE *protolist; /* linked list of prototypes */
int readerror; /* flags an error in reading a value */
int readingpattern; /* flags reading pattern state */
int right; /* number of training patterns learned */
DATA s[2]; /* statistics on training and test sets */
char summary; /* flags summary output mode */
char *testfile; /* file to take test patterns from */
NODE *testlist; /* the list of test patterns */
char *trainfile; /* file to take training patterns from */
NODE *trainlist; /* linked list of training patterns */
int unstable; /* flags a changing number of clusters */
int unlearned; /* number unlearned in last learning cycle */
INT32 *votes; /* an array to count votes per category */
int wrong; /* number of training patterns unlearned */
char wtformat; /* controls format to save and restore weights */
#ifndef UNIX
void interrupt(i) /* Hitting the escape key stops the program in */
/* selected loops in an emergency. This was */
/* used in debugging. The variable, i was the */
/* line number but since the lines keep shifting */
/* around the numbers are no longer correct. */
int i;
{if (kbhit() && getch() == 033) {printf("interrupt at %d\n",i); exit(1);};}
void hit(int i) /* another debugging function, not now in use. */
{return;printf("hit line %d\n",i);}
#endif
int pushfile(filename)
char *filename;
{
FILE *file;
bufferptr = 0;
bufferend = 0;
buffer[0] = '\n';
file = fopen(filename,"r");
if (file == NULL)
{
sprintf(outstr,"cannot open:, %s\n",filename); pg(outstr);
return(0);
};
filestackptr = filestackptr + 1;
if (filestackptr > 3)
{
pg("can't stack up any more files\n");
filestackptr = filestackptr - 1;
fclose(file);
return(0);
};
filestack[filestackptr] = file;
data = file;
return(1);
}
#if defined(UNIX) && defined(HOTKEYS)
#ifdef BSD
void initraw()
{
int i;
tcgetattr(0,&noraw);
raw.c_iflag = noraw.c_iflag;
raw.c_oflag = noraw.c_oflag;
raw.c_cflag = noraw.c_oflag;
raw.c_lflag = noraw.c_lflag & ~ ECHO;
raw.c_lflag = raw.c_lflag & ~ ICANON;
for (i=0;i<NCCS;i++) raw.c_cc[i] = noraw.c_cc[i];
raw.c_cc[VMIN] = 1;
raw.c_cc[VTIME] = 0;
raw.c_ispeed = noraw.c_ispeed;
raw.c_ospeed = noraw.c_ospeed;
}
void setraw()
{
tcsetattr(0,TCSANOW,&raw);
}
void setnoraw()
{
tcsetattr(0,TCSANOW,&noraw);
}
#elif defined NEXT
void initraw()
{
ioctl(0,TIOCGETD,&noraw);
raw.sg_ispeed = noraw.sg_ispeed;
raw.sg_ospeed = noraw.sg_ospeed;
raw.sg_erase = noraw.sg_erase;
raw.sg_kill = noraw.sg_kill;
raw.sg_flags = noraw.sg_flags & 0000040; /* turn on raw mode */
}
void setraw()
{
ioctl(0,TIOCSETD,&raw);
}
void setnoraw()
{
ioctl(0,TIOCSETD,&noraw);
}
#else /* System V code */
void initraw()
{
int i;
ioctl(0,TCGETA,&noraw);
raw.c_iflag = noraw.c_iflag;
raw.c_oflag = noraw.c_oflag;
raw.c_cflag = noraw.c_oflag;
raw.c_lflag = noraw.c_lflag & ~ 0x02; /* hot key bit */
raw.c_lflag = raw.c_lflag & ~ 010; /* echo bit */
raw.c_line = noraw.c_line;
for (i=0;i<=7;i++) raw.c_cc[i] = noraw.c_cc[i];
raw.c_cc[4] = 1;
}
void setraw()
{
ioctl(0,TCSETA,&raw);
}
void setnoraw()
{
ioctl(0,TCSETA,&noraw);
}
#endif /* end of the System V code */
int getch()
{
int ch;
setraw();
do ch = read(0,onechar,1); while (ch != 1);
setnoraw();
return(onechar[0]);
}
#endif /* end of the if defined(UNIX) ... code */
int readch() /* returns the next character in the input buffer */
{
int i, ch2;
if (bufferptr > bufferend) /* then read next line into buffer */
{
ch2 = getc(data);
if (ch2 == EOF) return(ch2);
i = 0;
while(ch2 != '\n' && i < (BUFFSIZE-1))
{
#ifdef UNIX
if (ch2 == 13) ch2 = ' '; /* turn a ctrl-M into a blank */
#endif
if (ch2 == '\t') ch2 = ' ';
buffer[i] = ch2;
i = i + 1;
ch2 = getc(data);
};
if (i == (BUFFSIZE-1)) pg("line too long\n");
buffer[i] = '\n';
buffer[i+1] = '\0';
bufferend = i;
bufferptr = 0;
if (echo == '+') for(i = 0; i <= bufferend; i++) putchar(buffer[i]);
if (copy && ((data == stdin) || (echo == '+')))
for (i=0;i<=bufferend;i++) putc(buffer[i],copy);
} /* end if bufferptr > bufferend */
ch2 = buffer[bufferptr];
bufferptr = bufferptr + 1;
return(ch2);
}
int pg(str) /* paging and making a copy function */
char *str;
{
char *ch3,action,cr;
int i;
int nbackspaces = 5;
action = 0;
ch3 = str;
while (*ch3 != '\0')
{
if (*ch3 == '\n')
{
putchar('\n');
if (copyflag == '+') putc('\n',copy);
lineno = lineno + 1;
if (pagesize > 0 && lineno > 0 && lineno % pagesize == 0)
{
printf("More?");
#ifdef HOTKEYS
action = getch();
#else
action = getchar();
if (action != '\n') cr = getchar();
#endif
for(i=1;i<=nbackspaces;i++) putchar(8);
for(i=1;i<=nbackspaces;i++) putchar(' ');
for(i=1;i<=nbackspaces;i++) putchar(8);
if (action == 'q') return(1);
else if (action == 'c') lineno = -MAXINT;
#ifdef UNIX
else if (action == '\n') lineno = lineno - 1;
#else
else if (action == 13) lineno = lineno - 1;
#endif
else if (action == 4) lineno = pagesize / 2;
else lineno = 0;
}
}
else {putchar(*ch3); if (copyflag == '+') putc(*ch3,copy); };
ch3++;
};
return(0);
}
void popfile()
{
bufferptr = 0;
bufferend = 0;
buffer[0] = '\n';
if (filestackptr > 0)
{
fclose(data);
filestackptr = filestackptr - 1;
}
else
{
pg("\nunexpected EOF: to quit the program, type q\n");
exit(2);
};
data = filestack[filestackptr];
}
void texterror(int location)
{
int ch2;
pg("unexpected text: ");
bufferptr = bufferptr - 1;
do {ch2 = readch(); putchar(ch2);} while (ch2 != '\n');
pg("\n");
sprintf(outstr,"from %d\n",location); pg(outstr);
bufferptr = bufferptr - 1;
}
char *readstr()
{
short i,start,end;
char *addr, *addr2;
i = bufferptr;
while (buffer[i] == ' ') i = i + 1;
start = i;
while (buffer[i] != ' ' && buffer[i] != '\n') i = i + 1;
end = i-1;
addr = (char *) malloc((int) end-start+2);
addr2 = addr;
for (i=start;i<=end;i++) *addr++ = buffer[i];
bufferptr = end + 1;
*addr = '\0';
return(addr2);
}
int scanfordigit()
{
int sign, ch2;
sign = 1;
restart:
do ch2 = readch(); while (ch2 == ' ' || ch2 == '\n');
if ((ch2 >= '0' && ch2 <= '9') || ch2 == '.')
{
bufferptr = bufferptr - 1;
return(sign);
};
switch (ch2) {
case EOF: readerror = 2;
return(0);
case '*': while (ch2 != '\n') ch2 = readch();
goto restart;
case '-': sign = -sign;
goto restart;
default: readerror = 1;
return(0);
};
}
int readint(min,max,command)
int min, max;
char command;
{
int sign, number, ch2;
readerror = 0;
sign = scanfordigit();
if (readerror)
{
if (readerror == 1) texterror(477);
return(0);
};
number = 0;
do ch2 = readch(); while (ch2 == ' ');
while (ch2 >= '0' && ch2 <= '9')
{
number = number * 10 + (ch2 - '0');
ch2 = readch();
};
bufferptr = bufferptr - 1;
number = sign * number;
if (number < min || number > max)
{
sprintf(outstr,"out of range value: %d",number); pg(outstr);
if (data == stdin) pg("\n");
else
{
sprintf(outstr," in %c command\n",command);
pg(outstr);
};
readerror = 1;
};
return(number);
}
REAL readreal(op,min,command)
int op;
REAL min;
int command;
{
REAL fractpart, divisor, intpart, sign;
double number;
int ch2, numread, i;
readerror = 0;
sign = (REAL) scanfordigit();
if (readerror || (sign == 0 && !readingpattern))
{
if (readerror == 1) texterror(516);
return(0);
};
ch2 = readch();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -