📄 whopf.c
字号:
/*---------------------------------------------------------------------- File : whopf.c Contents: Windows program for Hopfield networks as associative memory Author : Christian Borgelt History : 2002.12.01 file created from file wsom.c 2003.01.28 mouse event handling improved----------------------------------------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <time.h>#include <windows.h>#include "whopf.rh"#include "hopf.h"/*---------------------------------------------------------------------- Preprocessor Definitions----------------------------------------------------------------------*/#define PRGNAME "whopf" /* main window title *//* --- abbreviations --- */#define HINST HINSTANCE#define MKIRSC MAKEINTRESOURCE#define SDIMSG SendDlgItemMessage#define WINSTYLE WS_CAPTION|WS_SYSMENU|WS_BORDER|WS_MINIMIZEBOX#define PATH_MAX _MAX_PATH/* --- edit box functions --- */#define edt_set(h,i,s) SetDlgItemText(h, i, s)#define edt_get(h,i,s,n) GetDlgItemText(h, i, s, n)#define int_set(h,i,n) SetDlgItemInt(h, i, n, 0)#define int_get(h,i) GetDlgItemInt(h, i, NULL, 0)/* --- combo box functions --- */#define cmb_add(h,i,s) SDIMSG(h, i, CB_ADDSTRING, 0, (LPARAM)(s))#define cmb_rem(h,i,k) SDIMSG(h, i, CB_DELETESTRING, k, 0)#define cmb_set(h,i,k) SDIMSG(h, i, CB_SETCURSEL, k, 0)#define cmb_get(h,i) SDIMSG(h, i, CB_GETCURSEL, 0, 0)/* --- extensions --- */#define INITXEXT 239 /* initial x-extension of window */#define INITYEXT 288 /* initial y-extension of window *//* --- error codes --- */#define OK 0 /* no error */#define E_NONE 0 /* no error */#define E_NOMEM (-1) /* not enough memory */#define E_FOPEN (-2) /* cannot open file */#define E_FREAD (-3) /* read error on file */#define E_FWRITE (-4) /* write error on file */#define E_INIT (-5) /* initialization failed */#define E_PATCNT (-6) /* pattern capacity exceeded */#define E_UNKNOWN (-7) /* unkown error *//*---------------------------------------------------------------------- Constants----------------------------------------------------------------------*/const char *errmsgs[] = { /* error messages */ /* E_NONE 0 */ "no error", /* E_NOMEM -1 */ "not enough memory", /* E_FOPEN -2 */ "cannot open file\n%s", /* E_FREAD -3 */ "read error on file\n%s", /* E_FWRITE -4 */ "write error on file\n%s", /* E_INIT -5 */ "initialization failed", /* E_PATCNT -6 */ "pattern capacity exceeded", /* E_UNKNOWN -7 */ "unknown error"};/*---------------------------------------------------------------------- Global Variables----------------------------------------------------------------------*/static HINST hinst; /* instance handle */static HWND hmain; /* handle of main window */static HDC hdc_win; /* device context of window */static char text[_MAX_PATH +1024];/* --- pens and brushes --- */static HPEN pen_black; /* black : grid of network */static HBRUSH br_white; /* white : activation = -1 */static HBRUSH br_grey; /* grey : activation = +1 *//* --- neural network information --- */static struct { /* -- parameters -- */ int width, height; /* width and height */ int grid; /* grid width */ int mode; /* update mode */ int curr; /* current pattern */ double delay; /* delay (in seconds) */} nnpar = { 10, 12, 24, 0, -1, 0.01 };static HOPFNET *hfn = NULL; /* current reference vectors, */static int running = 0; /* whether training is running *//*---------------------------------------------------------------------- Error Functions----------------------------------------------------------------------*/static void error (int code, ...){ /* --- print error message */ va_list args; /* list of variable arguments */ const char *msg; /* error message */ if ((code > 0) || (code < E_UNKNOWN)) code = E_UNKNOWN; /* check error code */ va_start(args, code); /* get variable arguments */ msg = errmsgs[-code]; /* and error message text */ if (!msg) msg = errmsgs[-E_UNKNOWN]; vsprintf(text, msg, args); /* format error message */ MessageBox(hmain, text, PRGNAME, MB_OK|MB_ICONSTOP); va_end(args); /* show alert dialog box */} /* error() *//*---------------------------------------------------------------------- Random Number Functions----------------------------------------------------------------------*/#ifdef DRAND48 /* if library for drand48() available */extern void srand48 (long seed);extern double drand48 (void); /* use drand48 functions */#define dseed(s) srand48((long)(s))#define drand drand48#else /* if only standard rand() available */#define dseed(s) srand((unsigned)(s))static double drand (void){ return rand()/(RAND_MAX +1.0); }#endif/*---------------------------------------------------------------------- Drawing Functions----------------------------------------------------------------------*/static void redraw (HDC hdc){ /* --- Actions > Redraw */ RECT rc; /* rectangle for drawing */ int x, y; /* loop variable */ int g, a; /* grid width, activation */ if (!hdc) hdc = hdc_win; /* get the DC of the window */ g = nnpar.grid; /* get the grid width */ for (y = hfn_height(hfn); --y >= 0; ) { for (x = hfn_width(hfn); --x >= 0; ) { a = hfn_actget(hfn, x,y); /* traverse the neurons */ rc.left = x*g; rc.right = rc.left +g-1; rc.top = y*g; rc.bottom = rc.top +g-1; FillRect(hdc, &rc, (a > 0) ? br_grey : br_white); } /* color each field according to */ } /* the activation of the neuron */ SelectObject(hdc, pen_black); y = hfn_height(hfn) *g -1; /* draw horizontal grid lines */ for (a = -1, x = hfn_width(hfn); --x > 0; ) { a += g; MoveToEx(hdc, a, 0, NULL); LineTo(hdc, a, y); } x = hfn_width(hfn) *g -1; /* draw vertical grid lines */ for (a = -1, y = hfn_height(hfn); --y > 0; ) { a += g; MoveToEx(hdc, 0, a, NULL); LineTo(hdc, x, a); }} /* redraw() *//*--------------------------------------------------------------------*/static void resize (HWND hwnd){ /* --- adapt window size */ RECT rc; /* client area rectangle */ int x, y, dx, dy; /* coordinates and offsets */ int wx, wy; /* coordinates of window corner */ GetClientRect(hwnd, &rc); /* get client rectangle of window */ rc.right = rc.left +(dx = nnpar.width *nnpar.grid -1); rc.bottom = rc.top +(dy = nnpar.height *nnpar.grid -1); AdjustWindowRect(&rc, WINSTYLE, 1); x = rc.right -rc.left; /* get window client area and */ y = rc.bottom -rc.top; /* compute new window rectangle, */ GetWindowRect(hwnd, &rc); /* get the current window position */ wx = rc.left; wy = rc.top; /* and resize the window */ MoveWindow(hwnd, wx, wy, x, y, 1); GetClientRect(hwnd, &rc); /* get resulting rectangle */ if ((rc.right -rc.left != dx) /* if resulting client area */ || (rc.bottom -rc.top != dy)) { /* has a different size */ x += dx -(rc.right -rc.left); /* (e.g. because of a */ y += dy -(rc.bottom -rc.top); /* two-line menu) */ MoveWindow(hwnd, wx, wy, x, y, 1); } /* resize window a second time */ InvalidateRect(hwnd, NULL,0); /* trigger window redraw */} /* resize() *//*--------------------------------------------------------------------*/static void mouse (int x, int y, int down){ /* --- evaluate mouse movement */ int g; /* grid width */ RECT rc; /* rectangle to fill */ static int a = 0; /* activation to set */ if (running) return; /* if update is running, abort */ if (down < 0) { a = 0; return; } if (!down && (a == 0)) return; g = nnpar.grid; /* compute the neuron coordinates */ x /= g; if ((x < 0) || (x >= hfn_width(hfn))) return; y /= g; if ((y < 0) || (y >= hfn_height(hfn))) return; if (down) { /* on mouse down, get activation */ a = (hfn_actget(hfn, x, y) > 0) ? -1 : 1; } hfn_actset(hfn, x, y, a); /* toggle the activation and redraw */ rc.left = x*g; rc.right = rc.left +g-1; rc.top = y*g; rc.bottom = rc.top +g-1; FillRect(hdc_win, &rc, (a > 0) ? br_grey : br_white);} /* mouse() *//*--------------------------------------------------------------------*/static void CALLBACK update (HWND hwnd, UINT msg, UINT id, DWORD systime){ /* --- do one training step */ RECT rc; /* rectangle for drawing */ int x, y; /* loop variable */ int g, a; /* grid width, activation */ if (!running) return; /* check the update flag */ if (nnpar.mode == 0) { /* if in single neuron mode */ hfn_curr(hfn, &x, &y); /* get the neuron coordinates */ a = hfn_update(hfn, -1, 0); /* and update the neuron */ g = nnpar.grid; /* redraw the corresp. field */ rc.left = x*g; rc.right = rc.left +g-1; rc.top = y*g; rc.bottom = rc.top +g-1; FillRect(hdc_win, &rc, (a > 0) ? br_grey : br_white); } else { /* if in epoch mode */ hfn_update(hfn, -1, -1); /* update all neurons */ redraw(NULL); /* redraw the window contents */ } SetTimer(hwnd, 1, (UINT)(nnpar.delay *1000), (TIMERPROC)update);} /* update() */ /* reinstall timer *//*---------------------------------------------------------------------- Dialog Functions----------------------------------------------------------------------*/static char* fselect (char *title, int load){ /* --- select a file */ static char fname[_MAX_PATH+1]; /* file name */ static char path [_MAX_PATH+1]; /* and path */ static char filter[] = /* file selection filter */ "Hopfield networks (*.hfn)\0*.hfn\0" "all files (*.*)\0*.*\0"; static OPENFILENAME ofn = { /* file selector structure */ sizeof(OPENFILENAME), /* lStructSize */ NULL, NULL, /* hwndOwner, hInstance */ filter, NULL, /* lpstrFilter, lpstrCustomFilter */ 0, 1, /* nMaxCustFilter, nFilterIndex */ fname, _MAX_PATH, /* lpstrFile, nMaxFile */ NULL, _MAX_FNAME+_MAX_EXT, /* lpstrFileTitle, nMaxFileTitle */ path, /* lpstrInitialDir */ "Select File...", /* lpstrTitle */ OFN_PATHMUSTEXIST, 0, 0, /* Flags, nFileOffset, nFileExtension */ "nn", 0L, /* lpstrDefExt, lCustData */ NULL, NULL }; /* lpfnHook, lpTemplateName */ ofn.hwndOwner = hmain; /* set window handle */ ofn.lpstrTitle = title; /* and title text */ ofn.Flags = (load) ? OFN_FILEMUSTEXIST : OFN_PATHMUSTEXIST; if (GetOpenFileName(&ofn) == 0) return NULL; /* open file selector box */ return fname; /* return name of selected file */} /* fselect() *//*--------------------------------------------------------------------*/static int load (void){ /* --- File > Load Network... */ char *fname; /* name of file to load */ FILE *file; /* input file */ HOPFNET *tmp; /* temporary buffer for network */ LoadString(hinst, CS_LOAD, text, 80); fname = fselect(text, 1); /* get the dialog box title */ if (!fname) return -1; /* and select a file */ file = fopen(fname, "r"); /* open input file */ if (!file) { error(E_FOPEN, fname); return -1; } tmp = hfn_load(file); /* load the self-org. map */ fclose(file); /* close the input file */ if (!tmp) { error(E_FREAD, fname); return -1; } hfn_delete(hfn); hfn = tmp; /* replace the existing network */ nnpar.width = hfn_width(hfn); nnpar.height = hfn_height(hfn); return 0; /* return 'ok' */} /* load() *//*--------------------------------------------------------------------*/static void save (void){ /* --- File > Save Network... */ char *fname; /* name of file to save to */ FILE *file; /* output file */ LoadString(hinst, CS_SAVE, text, 80); fname = fselect(text, 0); /* get the dialog box title */ if (!fname) return; /* and select a file */ file = fopen(fname, "w"); /* open output file */ if (!file) { error(E_FOPEN, fname); return; } hfn_save(hfn, file); /* save the Hopfield network */ if (fclose(file) != 0) error(E_FWRITE);} /* save() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -