1 /*****************************************************************************
2   FILE           : $Source: /projects/higgs1/SNNS/CVS/SNNS/xgui/sources/ui_inversion.c,v $
3   SHORTNAME      : inversion.c
4   SNNS VERSION   : 4.2
5 
6   PURPOSE  : contains all routines for handling inversion of NN, invented
7             by Alexander Linden
8 
9   FUNCTIONS: -- ui_inversion
10                Purpose : Main program for the inversion
11 	        Calls   : void ui_confirmOk();
12 		          Widget ui_xCreateButtonItem();
13 			  int ui_set_IO_units();
14                          various X routines for widget handling
15 
16             -- ui_invSetup
17                Purpose : Display setup panel for Inversion
18                Calls   : Widget ui_xCreateDialogItem();
19                          Widget ui_xCreateLabelItem();
20 
21             -- ui_inv_popupDone
22                Purpose : read new params and close popup display
23                Calls   : nothing
24 
25             -- ui_invHelp
26                Purpose : display help information for inversion
27                Calls   : nothing
28 
29             -- ui_inv_helpDone
30                Purpose : close help window
31                Calls   : nothing
32 
33             -- ui_set_IO_units
34                Purpose : create a chain of input units
35                Calls   : int krui_getUnitTType();
36                          void krui_getUnitPosition();
37 
38             -- ui_closeDisplay
39                Purpose : closing all widgets for inversion
40                Calls   : nothing
41 
42             -- ui_invNew
43                Purpose : restart the inversion
44                Calls   : void ui_drawInput();
45 
46             -- ui_invEvent
47                Purpose : event handler for graphic window
48                Calls   : void ui_drawInput();
49 
50             -- ui_inversionFromUpdate
51                Purpose : refresh the screen
52                Calls   : void ui_drawInput();
53 
54             -- ui_drawInput
55                Purpose : drawing the input units
56                Calls   : int krui_getFirstUnit();
57                          void ui_col_setPalette();
58                          void krui_getUnitPosition();
59                          void ui_drawGrowingThing();
60                          position ui_utilPixUpperLeft();
61                          position ui_utilPixLowerRight();
62                          void ui_xDeleteRect();
63 
64             -- ui_start_inversion
65                Purpose : Program to start inversion
66                Calls   : X routines
67 
68             -- ui_stop_inversion
69                Purpose : Program to stop inversion
70                Calls   : X routines
71 
72             -- ui_do_inversion
73                Purpose : Program for actual inversion algorithm
74                Calls   : void ui_confirmOk();
75                          void ui_sel_lookForItem();
76                          int krui_initInversion();
77                          void krui_inv_forwardPass();
78                          int krui_inv_backwardPass();
79                          void ui_drawInput();
80 
81  AUTHOR   : Guenter Mamier
82  DATE     : 28.02.92
83  VERSION  : 0.20
84 
85  CHANGED BY     : Sven Doering
86  RCS VERSION    : $Revision: 2.11 $
87  LAST CHANGE    : $Date: 1998/03/03 14:10:30 $
88 
89     Copyright (c) 1990-1995  SNNS Group, IPVR, Univ. Stuttgart, FRG
90     Copyright (c) 1996-1998  SNNS Group, WSI, Univ. Tuebingen, FRG
91 
92 ******************************************************************************/
93 #include <config.h>
94 
95 #ifndef MASPAR_KERNEL
96 
97 #include <stdio.h>			/* For the Syntax message */
98 #include <stdlib.h>
99 #include <math.h>
100 
101 #include "ui.h"
102 
103 #include <X11/Shell.h>
104 #include <X11/Xaw3d/Form.h>
105 #include <X11/Xaw3d/Box.h>
106 
107 #include "ui_xWidgets.h"
108 #include "ui_main.h"
109 #include "ui_mainP.h"
110 #include "ui_netGraph.h"
111 #include "ui_utilP.h"
112 #include "ui_display.h"
113 #include "ui_selection.h"
114 #include "ui_color.h"
115 #include "ui_confirmer.h"
116 #include "ui_xGraphic.h"
117 #include "ui_key.h"
118 #include "kr_ui.h"
119 #include "kr_typ.h"
120 
121 #include "ui_inversion.ph"
122 
123 
124 /*****************************************************************************
125   FUNCTION : ui_inversion
126 
127   PURPOSE  : Main program for the inversion
128   NOTES    : callback from the info panel
129   RETURNS  :
130   UPDATE   : 29.01.92
131 ******************************************************************************/
132 
ui_inversion(Widget button,caddr_t call_data)133 void ui_inversion(Widget button, caddr_t call_data)
134 {
135 
136     Widget         fbutton,sbutton,stbutton,setbutton,stopbutton,helpbutton;
137     Arg		   args[10];
138     Cardinal	   n;
139     char           buf[40];
140     struct UnitList *IUnit, *OUnit;
141     struct Ui_DisplayType *dPtr;
142     int maxx,maxy;
143     int test;
144 
145     if (krui_getNoOfUnits() == 0){
146 	ui_confirmOk("No network loaded !");
147 	return;
148     }
149 
150 
151     if(INVERS_CREATED){
152        XRaiseWindow(XtDisplay(ui_InvRootWidget), XtWindow(ui_InvRootWidget));
153        return;
154     }
155 
156     if((test = ui_set_IO_units()) == 1){
157       ui_confirmOk("No input and/or output units defined !");
158       return;
159     }
160 
161 
162     if ((displayPtr = ui_displ_getFreeItem()) == NULL) {
163 	ui_confirmOk("No more memory for displays available!");
164 	return;
165     }
166 
167 
168     /* now create the widget structure to display input units */
169 
170     n = 0;
171     displayPtr->gridSize = 37;
172     dPtr = ui_displ_listPtr;
173     while(dPtr != NULL){
174        displayPtr->gridSize = dPtr->gridSize;
175        dPtr = dPtr->nextPtr;
176     }
177 
178     sprintf(buf,"SNNS Inversion Display");
179     ui_InvRootWidget =
180 	XtCreatePopupShell(buf, topLevelShellWidgetClass, ui_toplevel,args, n);
181     displayPtr->frameWidget =
182 	XtCreateManagedWidget("form", formWidgetClass, ui_InvRootWidget,NULL,0);
183 
184     fbutton = ui_xCreateButtonItem("done", displayPtr->frameWidget, NULL, NULL);
185     sbutton    = ui_xCreateButtonItem("multiStep", displayPtr->frameWidget,
186 				   fbutton, NULL);
187     stopbutton = ui_xCreateButtonItem("stop", displayPtr->frameWidget,
188 				      sbutton, NULL);
189     stbutton   = ui_xCreateButtonItem("new", displayPtr->frameWidget,
190 				   stopbutton, NULL);
191     setbutton  = ui_xCreateButtonItem("setup", displayPtr->frameWidget,
192 				   stbutton, NULL);
193     helpbutton  = ui_xCreateButtonItem("help", displayPtr->frameWidget,
194 				   setbutton, NULL);
195 
196 
197     /* get necessary window size */
198 
199     maxy = maxx = 0;
200     IUnit = inputs;
201     do{
202       maxy = (IUnit->gridPos.y > maxy)? IUnit->gridPos.y: maxy;
203       maxx = (IUnit->gridPos.x > maxx)? IUnit->gridPos.x: maxx;
204       IUnit = IUnit->next;
205     }while(IUnit != NULL);
206     OUnit = outputs;
207     do{
208       maxy = (OUnit->gridPos.y > maxy)? OUnit->gridPos.y: maxy;
209       maxx = (OUnit->gridPos.x > maxx)? OUnit->gridPos.x: maxx;
210       OUnit = OUnit->next;
211     }while(OUnit != NULL);
212 
213     n = 0;
214     /* XtSetArg(args[n], XtNwidth,  displayPtr->width); n++; */
215     /* XtSetArg(args[n], XtNheight, displayPtr->height); n++; */
216     XtSetArg(args[n], XtNwidth,    ++maxx * displayPtr->gridSize); n++;
217     XtSetArg(args[n], XtNheight,   ++maxy * displayPtr->gridSize); n++;
218     XtSetArg(args[n], XtNfromVert, fbutton); n++;
219     XtSetArg(args[n], XtNleft,     XtChainLeft); n++;
220     XtSetArg(args[n], XtNright,    XtChainRight); n++;
221     XtSetArg(args[n], XtNtop,      XtChainTop ); n++;
222     XtSetArg(args[n], XtNbottom,   XtChainBottom); n++;
223     displayPtr->widget =
224         XtCreateManagedWidget("display",boxWidgetClass,displayPtr->frameWidget,
225 			      args,n);
226 
227 
228     /* define necessary callbacks */
229 
230     XtAddCallback(fbutton, XtNcallback,(XtCallbackProc)ui_closeDisplay,NULL);
231     XtAddCallback(sbutton, XtNcallback,(XtCallbackProc)ui_start_inversion,NULL);
232     XtAddCallback(stbutton, XtNcallback, (XtCallbackProc) ui_invNew, NULL);
233     XtAddCallback(stopbutton, XtNcallback,
234 		  (XtCallbackProc) ui_stop_inversion, NULL);
235     XtAddCallback(setbutton,  XtNcallback, (XtCallbackProc) ui_invSetup, NULL);
236     XtAddCallback(helpbutton, XtNcallback, (XtCallbackProc) ui_invHelp,
237 		  (caddr_t) TRUE);
238     XtAddEventHandler(displayPtr->widget,StructureNotifyMask | ExposureMask,
239 		      FALSE, (XtEventHandler) ui_invEvent,inv_display);
240     XtAddEventHandler(displayPtr->widget,KeyPressMask,FALSE,
241 		      (XtEventHandler)ui_key_control,(Cardinal *) 0);
242     ui_checkWindowPosition(ui_InvRootWidget);
243     XtPopup(ui_InvRootWidget, XtGrabNone);
244 
245     INVERS_CREATED = 1;
246     inv_display   = XtDisplay(ui_InvRootWidget);
247     inv_screen    = DefaultScreen(inv_display);
248     displayPtr->drawable = XtWindow(displayPtr->widget);
249     XSelectInput(inv_display, displayPtr->drawable,  ExposureMask);
250 
251 
252 }
253 
254 
255 
256 
257 /*****************************************************************************
258   FUNCTION : ui_invSetup
259 
260   PURPOSE  : Display setup panel for Inversion
261   NOTES    :
262   RETURNS  :
263   UPDATE   : 20.02.92
264 *****************************************************************************/
ui_invSetup(Widget button,caddr_t call_data)265 static void ui_invSetup(Widget button, caddr_t call_data)
266 {
267     Widget      ui_invBox,doneButton,helpButton;
268     Widget      eta_lab,delta_lab,pat_lab,rat_lab;
269     Arg         args[5];
270     Position    x, y;
271     Dimension   width, height;
272     Cardinal    n;
273     char        buf[40];
274 
275 
276     /* set Popup arguments */
277 
278     n = 0;
279     XtSetArg(args[0], XtNwidth, &width);n++;
280     XtSetArg(args[1], XtNheight, &height);n++;
281     XtGetValues(button, args, n);
282     XtTranslateCoords(button, (Position)(width/2), (Position)(height/2), &x,&y);
283     n = 0;
284     XtSetArg(args[n], XtNx, x);n++;
285     XtSetArg(args[n], XtNy, y);n++;
286 
287 
288     /* Now create Popup */
289 
290     ui_invpop = XtCreatePopupShell("setup", transientShellWidgetClass,
291 				   ui_toplevel, args, n);
292     ui_invBox = XtCreateManagedWidget("form", formWidgetClass, ui_invpop,
293 				      NULL, 0);
294     doneButton = ui_xCreateButtonItem("done", ui_invBox, NULL, NULL);
295     XtAddCallback(doneButton, XtNcallback, (XtCallbackProc) ui_inv_popupDone,
296 		  NULL);
297     helpButton = ui_xCreateButtonItem("help", ui_invBox, doneButton, NULL);
298     XtAddCallback(helpButton, XtNcallback, (XtCallbackProc) ui_invHelp, FALSE);
299     eta_lab = ui_xCreateLabelItem("eta           =", ui_invBox,120,
300 				  NULL,doneButton);
301     sprintf(buf,"%g",INV_eta);
302     etaW = ui_xCreateDialogItem("eta_val",ui_invBox,buf,56,eta_lab,doneButton);
303     delta_lab = ui_xCreateLabelItem("delta_max     =",ui_invBox,120,
304 				    NULL,eta_lab);
305     sprintf(buf,"%g",INV_delta_max);
306     delta_maxW = ui_xCreateDialogItem("delta_max_val",ui_invBox,
307 				      buf, 56, delta_lab, etaW);
308     pat_lab = ui_xCreateLabelItem("Input pattern =",ui_invBox,120,NULL,
309 				  delta_lab);
310     sprintf(buf,"%g",INPUT_PAT);
311     inPatW = ui_xCreateDialogItem("input_pat_val",ui_invBox,buf,56,
312 				  pat_lab,delta_maxW);
313     rat_lab = ui_xCreateLabelItem("2nd approx ratio",ui_invBox,120,NULL,
314 				  pat_lab);
315     sprintf(buf,"%g",RATIO);
316     ratioW = ui_xCreateDialogItem("ratio_val",ui_invBox,buf,56,
317 				  rat_lab,inPatW);
318 
319 
320     /* Display popup now */
321 
322     ui_checkWindowPosition(ui_invpop);
323     XtPopup(ui_invpop, XtGrabExclusive);
324     ui_xDontResizeWidget(ui_invpop);
325 }
326 
327 
328 
329 
330 
331 /*****************************************************************************
332   FUNCTION : ui_inv_popupDone
333 
334   PURPOSE  : read new params and close popup display
335   NOTES    :
336   RETURNS  :
337   UPDATE   : 20.02.92
338 *****************************************************************************/
ui_inv_popupDone(Widget button,caddr_t call_data)339 static void ui_inv_popupDone(Widget button, caddr_t call_data)
340 {
341     struct UnitList *IUnit;
342 
343     INPUT_PAT     = (float)ui_xFloatFromAsciiWidget(inPatW);
344     INPUT_PAT     = (INPUT_PAT > 1.0)? 1.0 :INPUT_PAT;
345     INPUT_PAT     = (INPUT_PAT < 0.0)? 0.0 :INPUT_PAT;
346     INV_eta       = (float)ui_xFloatFromAsciiWidget(etaW);
347     INV_delta_max = (float)ui_xFloatFromAsciiWidget(delta_maxW);
348     RATIO         = (float)ui_xFloatFromAsciiWidget(ratioW);
349     XtDestroyWidget(ui_invpop);
350 
351     IUnit = inputs;
352     while(IUnit != NULL){
353       IUnit->act = (FlintType)INPUT_PAT;
354       IUnit->i_act = (FlintType)INPUT_PAT;
355       if(INPUT_PAT == 1.0)
356 	IUnit->im_act  = 9.2102404;
357       else if(INPUT_PAT == 0.0)
358 	IUnit->im_act  = -9.2102404;
359       else
360 	IUnit->im_act  = (FlintType)(-log((double)(1.0/INPUT_PAT - 1.0)));
361       IUnit = IUnit->next;
362     }
363     ui_drawInput();
364 }
365 
366 
367 
368 
369 
370 /*****************************************************************************
371   FUNCTION : ui_inv_helpDone
372 
373   PURPOSE  : destroy help window
374   NOTES    :
375   RETURNS  :
376   UPDATE   : 03.03.92
377 *****************************************************************************/
ui_inv_helpDone(Widget button,caddr_t call_data)378 static void ui_inv_helpDone(Widget button, caddr_t call_data)
379 {
380     XtDestroyWidget(XtParent(XtParent(button)));
381 }
382 
383 
384 
385 
386 /*****************************************************************************
387   FUNCTION : ui_invHelp
388 
389   PURPOSE  : display help information for inversion
390   NOTES    :
391   RETURNS  :
392   UPDATE   : 03.03.92
393 *****************************************************************************/
ui_invHelp(Widget button,Boolean fromMain,caddr_t call_data)394 static void ui_invHelp(Widget button, Boolean fromMain, caddr_t call_data)
395 {
396     Widget      ui_invHBox,ui_invHelp,doneButton,lab[10];
397     Arg         args[5];
398     Position    x, y;
399     Dimension   width, height;
400     Cardinal    n;
401     char        buf[80];
402 
403     /* set Popup arguments */
404 
405     n = 0;
406     XtSetArg(args[0], XtNwidth, &width);n++;
407     XtSetArg(args[1], XtNheight, &height);n++;
408     XtGetValues(button, args, n);
409     XtTranslateCoords(button, (Position)(width), (Position)(height), &x, &y);
410     n = 0;
411     XtSetArg(args[n], XtNx, x);n++;
412     XtSetArg(args[n], XtNy, y+100);n++;
413 
414 
415     /* Now create Popup */
416 
417     ui_invHelp = XtCreatePopupShell("help", transientShellWidgetClass,
418 				   ui_toplevel, args, n);
419     ui_invHBox = XtCreateManagedWidget("form", formWidgetClass, ui_invHelp,
420 				      NULL, 0);
421     doneButton = ui_xCreateButtonItem("done", ui_invHBox, NULL, NULL);
422     XtAddCallback(doneButton, XtNcallback, (XtCallbackProc) ui_inv_helpDone, NULL);
423 
424 
425     if(fromMain){
426        sprintf(buf,"Start/continue inversion with 'STEP'");
427        lab[0] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,doneButton);
428        sprintf(buf,"Halt inversion run anytime with 'STOP'");
429        lab[1] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[0]);
430        sprintf(buf,"Reset inversion with 'NEW'");
431        lab[2] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[1]);
432        sprintf(buf,"Change parameters with 'SETUP'");
433        lab[3] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[2]);
434        sprintf(buf,"After SETUP continue with 'STEP',");
435        lab[4] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[3]);
436        sprintf(buf,"  or restart with 'NEW','STEP'");
437        lab[5] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[4]);
438        sprintf(buf,"HINT: If inversion is performed on an untrained net,");
439        lab[6] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[5]);
440        sprintf(buf,"      or on a trained net with an average error of more than 0.05,");
441        lab[7] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[6]);
442        sprintf(buf,"      the algorithm is very likely not to converge !!");
443        lab[8] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[7]);
444     }else{
445        sprintf(buf,"eta           : The learn parameter; should range from 1.0 to 10.0");
446        lab[0] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,doneButton);
447        sprintf(buf,"delta_max     : The maximum allowed error for a output unit");
448        lab[1] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[0]);
449        sprintf(buf,"Input  pattern: The initial activation for all input units");
450        lab[2] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[1]);
451        sprintf(buf,"2nd approx    : The degree to which the target input pattern");
452        lab[3] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[2]);
453        sprintf(buf,"                is dependent of the initial input pattern");
454        lab[4] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[3]);
455        sprintf(buf,"                good values range from 0.2 to 0.8");
456        lab[5] = ui_xCreateLabelItem(buf,ui_invHBox,strlen(buf)*8,NULL,lab[4]);
457     }
458 
459 
460     /* Display popup now */
461 
462     ui_checkWindowPosition(ui_invHelp);
463     XtPopup(ui_invHelp, XtGrabExclusive);
464     XFlush(ui_display);
465 
466 
467 }
468 
469 
470 
471 
472 /*****************************************************************************
473   FUNCTION : ui_set_IO_units
474 
475   PURPOSE  : create a chain of input units and the corresponding pattern
476   NOTES    :
477   RETURNS  :
478   UPDATE   : 29.01.92
479 *****************************************************************************/
ui_set_IO_units(void)480 static int ui_set_IO_units(void)
481 {
482     int            next;
483     int            u_type;
484     struct PosType position;
485     struct UnitList *IUnit,*OUnit,*dummy1,*dummy2;
486     int            i_count = 0,
487                    o_count = 0,
488                    i,
489                    max_no;
490 
491     if((next = krui_getFirstUnit()) == 0)return(0);
492 
493     IUnit = (struct UnitList *) malloc(sizeof(struct UnitList));
494     inputs = IUnit;
495     IUnit->prev = NULL;
496     OUnit = (struct UnitList *) malloc(sizeof(struct UnitList));
497     outputs = OUnit;
498     IUnit->prev = NULL;
499     max_no = krui_getNoOfUnits();
500     for(i=1; i<= max_no; i++){
501       u_type = krui_getUnitTType(next);
502       if(u_type == INPUT){
503 	 i_count++;
504  	 krui_getUnitPosition(next,&position);
505 	 dummy1 = IUnit;
506 	 IUnit->no      = next;
507 	 IUnit->gridPos = position;
508          IUnit->act     = (FlintType)INPUT_PAT;
509          IUnit->i_act   = (FlintType)INPUT_PAT;
510 	 if(INPUT_PAT == 1.0)
511 	   IUnit->im_act  = 9.2102404;   /* = -ln(1/0.9999 - 1); */
512 	 else if(INPUT_PAT == 0.0)
513 	   IUnit->im_act  = -9.2102404;  /* = -ln(1/0.0001 - 1); */
514 	 else
515 	   IUnit->im_act  =(FlintType)( -log((double)(1.0/INPUT_PAT - 1.0)));
516 	 IUnit->next    = (struct UnitList *) malloc(sizeof(struct UnitList));
517          IUnit          = IUnit->next;
518 	 IUnit->prev    = dummy1;
519       }else if(u_type == OUTPUT){
520 	 o_count++;
521  	 krui_getUnitPosition(next,&position);
522 	 dummy2         = OUnit;
523 	 OUnit->no      = next;
524 	 OUnit->gridPos = position;
525          OUnit->act     = 0.0;
526 	 OUnit->next    = (struct UnitList *) malloc(sizeof(struct UnitList));
527          OUnit          = OUnit->next;
528 	 OUnit->prev    = dummy2;
529       }
530       next=krui_getNextUnit();
531     }
532 
533     if(i_count == 0 || o_count == 0){
534 
535       /* Stop inversion if no input or output units are defined */
536       return(1);
537     }else{
538 
539       /* Finish the pointer chain */
540       dummy1->next = NULL;
541       dummy2->next = NULL;
542       return(0);
543     }
544 
545 }
546 
547 
548 
549 
550 /*****************************************************************************
551   FUNCTION : ui_closeDisplay
552 
553   PURPOSE  : closing all widgets for inversion
554   NOTES    :
555   RETURNS  :
556   UPDATE   : 29.01.92
557 *****************************************************************************/
ui_closeDisplay(Widget w,caddr_t call_data)558 static void ui_closeDisplay(Widget w, caddr_t call_data)
559 {
560 
561 
562     if(INV_RUNNING){
563        ui_confirmOk("Stop inversion run before quiting !");
564        return;
565     }
566     XtDestroyWidget(ui_InvRootWidget);
567     INVERS_CREATED = 0;
568     inputs  = NULL;
569     outputs = NULL;
570 }
571 
572 
573 /*****************************************************************************
574   FUNCTION : ui_invNew
575 
576   PURPOSE  : restart the inversion
577   NOTES    :
578   RETURNS  :
579   UPDATE   : 11.02.92
580 *****************************************************************************/
ui_invNew(Widget w,caddr_t call_data)581 static void ui_invNew(Widget w, caddr_t call_data)
582 {
583     struct UnitList *IUnit, *OUnit;
584 
585     IUnit = inputs;
586     while(IUnit != NULL){
587       IUnit->act = (FlintType)INPUT_PAT;
588       IUnit->i_act = (FlintType)INPUT_PAT;
589       if(INPUT_PAT == 1.0)
590 	IUnit->im_act  = 9.2102404;   /* = -ln(1/0.9999 - 1); */
591       else if(INPUT_PAT == 0.0)
592 	IUnit->im_act  = -9.2102404;  /* = -ln(1/0.0001 - 1); */
593       else
594 	IUnit->im_act  = (FlintType)(-log((double)(1.0/INPUT_PAT - 1.0)));
595       IUnit = IUnit->next;
596     }
597     OUnit = outputs;
598     while(OUnit != NULL){
599       OUnit->act = 0.0;
600       OUnit->i_act = 0.0;
601       OUnit = OUnit->next;
602     }
603     ui_drawInput();
604     INV_NEW = 1;
605 }
606 
607 
608 
609 
610 /*****************************************************************************
611   FUNCTION : ui_invEvent
612 
613   PURPOSE  : event handler for graphic window
614   NOTES    :
615   RETURNS  :
616   UPDATE   : 20.02.92
617 *****************************************************************************/
ui_invEvent(Widget w,Display * display,XEvent * event)618 static void ui_invEvent(Widget w, Display *display, XEvent *event)
619 {
620     switch (event->type){
621         case Expose:
622                if (event->xexpose.count == 0)
623 		 ui_drawInput();
624 	       break;
625 	default:
626 	       break;
627     }
628 }
629 
630 
631 
632 
633 
634 /*****************************************************************************
635   FUNCTION : ui_drawInput
636 
637   PURPOSE  : drawing the input units
638   NOTES    :
639   RETURNS  :
640   UPDATE   : 29.01.92
641 *****************************************************************************/
ui_drawInput(void)642 static void ui_drawInput(void)
643 {
644 
645     int            next;
646     int            u_type;
647     int            dx,dy;
648     int            procent_value;
649     struct PosType position,pixpos,pixpos2;
650     struct UnitList *IUnit, *OUnit;
651 
652 
653 
654     /* do nothing if no net is loaded */
655 
656     if((next = krui_getFirstUnit()) == 0)return;
657 
658 
659     /* prepare window for drawing */
660 
661     displayPtr->frozen = FALSE;
662     XClearWindow(inv_display,displayPtr->drawable);
663     if(ui_col_monochromeMode){
664        XSetBackground(inv_display,ui_gc,
665 		      ui_backgroundColor);
666        XSetForeground(inv_display,
667 		      ui_gc,ui_textColor);
668 
669        /* draw rectangle for EACH input/output unit */
670        do{
671          u_type = krui_getUnitTType(next);
672          if(u_type == OUTPUT || u_type == INPUT){
673  	    krui_getUnitPosition(next,&position);
674             ui_drawGrowingThing(displayPtr, position, -100);
675          }
676        }while((next=krui_getNextUnit()) != 0);
677     }else{
678        XSetBackground(inv_display,ui_gc,
679 		   ui_backgroundColor);
680        XSetForeground(inv_display,
681 		   ui_gc, ui_editColor[UI_BLACK]);
682        XSetFunction(inv_display, ui_gc, GXcopy);
683     }
684 
685 
686     /* draw activation of input units */
687 
688     IUnit = inputs;
689     do{
690       position.x = displayPtr->gridSize * (IUnit->gridPos.x-displayPtr->origin.x) +
691 	           displayPtr->gridSize/2;
692       position.y = displayPtr->gridSize * (IUnit->gridPos.y-displayPtr->origin.y) +
693 	           displayPtr->gridSize/2;
694       procent_value = (int)(100.0*IUnit->act);
695       if(ui_col_monochromeMode){
696          pixpos = ui_utilPixUpperLeft(displayPtr,IUnit->gridPos);
697          pixpos2 = ui_utilPixLowerRight(displayPtr,IUnit->gridPos,0);
698 	 dx = dy = (int)((float)(pixpos2.x - pixpos.x)*IUnit->act);
699 	 pixpos.x += (int)((float)(pixpos2.x-pixpos.x)*0.5*(1.0 - IUnit->act)+0.5);
700 	 pixpos.y += (int)((float)(pixpos2.y-pixpos.y)*0.5*(1.0 - IUnit->act)+0.5);
701 	 XFillRectangle(inv_display, displayPtr->drawable, ui_gc,
702 			pixpos.x,pixpos.y,(unsigned int) dx,(unsigned int) dy);
703       }else{
704          pixpos = ui_utilPixUpperLeft(displayPtr,IUnit->gridPos);
705          pixpos2 = ui_utilPixLowerRight(displayPtr,IUnit->gridPos,0);
706 	 XSetForeground(inv_display, ui_gc,
707 	       ui_col_rangePixels[ui_col_steps+procent_value*ui_col_steps DIV 100]);
708 	 ui_xDeleteRect(inv_display, displayPtr->drawable, ui_gc,pixpos,pixpos2);
709       }
710       IUnit = IUnit->next;
711     }while(IUnit != NULL);
712 
713 
714     /* draw activation of output units */
715 
716     OUnit = outputs;
717     do{
718       position.x = displayPtr->gridSize * (OUnit->gridPos.x-displayPtr->origin.x) +
719 	           displayPtr->gridSize/2;
720       position.y = displayPtr->gridSize * (OUnit->gridPos.y-displayPtr->origin.y) +
721 	           displayPtr->gridSize/2;
722 
723       procent_value = (int)(100.0*OUnit->act);
724       if(NOT ui_col_monochromeMode){
725          pixpos = ui_utilPixUpperLeft(displayPtr,OUnit->gridPos);
726          pixpos2 = ui_utilPixLowerRight(displayPtr,OUnit->gridPos,0);
727 	 XSetForeground(inv_display, ui_gc,
728 	       ui_col_rangePixels[ui_col_steps+procent_value*ui_col_steps DIV 100]);
729 	 ui_xDeleteRect(inv_display, displayPtr->drawable, ui_gc,pixpos,pixpos2);
730       }else{
731          pixpos = ui_utilPixUpperLeft(displayPtr,OUnit->gridPos);
732          pixpos2 = ui_utilPixLowerRight(displayPtr,OUnit->gridPos,0);
733 	 dx = dy = (int)((float)(pixpos2.x - pixpos.x)*OUnit->act);
734 	 pixpos.x += (int)((float)(pixpos2.x-pixpos.x)*0.5*(1.0 - OUnit->act)+0.5);
735 	 pixpos.y += (int)((float)(pixpos2.y-pixpos.y)*0.5*(1.0 - OUnit->act)+0.5);
736 	 XFillRectangle(inv_display, displayPtr->drawable, ui_gc,
737 			pixpos.x,pixpos.y,(unsigned int) dx,(unsigned int) dy);
738       }
739       OUnit = OUnit->next;
740     }while(OUnit != NULL);
741 
742 
743 
744     /* drawing finished */
745 
746     XFlush(inv_display);
747     displayPtr->frozen = TRUE;
748 }
749 
750 
751 
752 
753 
754 /*****************************************************************************
755   FUNCTION : ui_start_inversion
756 
757   PURPOSE  : Program to start inversion
758   NOTES    : callback from the control panel
759   RETURNS  :
760   UPDATE   : 29.01.92
761 ******************************************************************************/
ui_start_inversion(Widget button,caddr_t call_data)762 static void ui_start_inversion(Widget button, caddr_t call_data)
763 {
764     if (ui_workProcId)
765         XtRemoveWorkProc(ui_workProcId); /* kill old workProc */
766     ui_workType = 99;
767     INV_RUNNING = 1;
768     ui_workProcId = XtAppAddWorkProc(ui_appContext, (XtWorkProc) ui_do_inversion,NULL);
769 }
770 
771 
772 
773 /*****************************************************************************
774   FUNCTION : ui_stop_inversion
775 
776   PURPOSE  : Program to stop inversion
777   NOTES    : callback from the control panel
778   RETURNS  :
779   UPDATE   : 29.01.92
780 ******************************************************************************/
ui_stop_inversion(Widget button,caddr_t call_data)781 static void ui_stop_inversion(Widget button, caddr_t call_data)
782 {
783     if(ui_workProcId){
784       INV_RUNNING = 0;
785       ui_drawInput();
786       printf("cycle %d inversion error %f, %d error units left\n",
787 	     INV_cycle,INV_error,INV_units);
788       XtRemoveWorkProc(ui_workProcId); /* kill old workProc */
789       ui_workProcId = (XtWorkProcId) NULL;
790     }
791 }
792 
793 
794 
795 /*****************************************************************************
796   FUNCTION : ui_do_inversion
797 
798   PURPOSE  : Program for actual inversion algorithm
799   NOTES    : callback from the control panel
800   RETURNS  :
801   UPDATE   : 29.01.92
802 ******************************************************************************/
803 
ui_do_inversion(Widget button,caddr_t call_data)804 static Boolean ui_do_inversion(Widget button, caddr_t call_data)
805 {
806     struct UnitList *OUnit;
807     struct SelectionType *SelDummy;
808     int dummy;
809     double old_err;
810     int selUnits, err_units;
811     int err;
812     static int growing_errors = 0;
813 
814 
815     /* set output pattern */
816 
817     if(INV_NEW){
818        INV_cycle = 0;
819        selUnits = 0;
820        if(krui_getNoOfPatterns() == 0){
821 	  ui_confirmOk("Please load patterns first !");
822           INV_RUNNING = 0;
823 	  return(TRUE);
824        }
825        OUnit = outputs;
826        while(OUnit != NULL){
827 	 if((SelDummy = ui_sel_lookForItem(OUnit->no)) != NULL){
828 	   OUnit->i_act = 1.0;
829 	   OUnit->act = 1.0;
830 	   selUnits++;
831 	 }else{
832 	   OUnit->i_act = 0.0;
833 	   OUnit->act = 0.0;
834 	 }
835 	 OUnit = OUnit->next;
836        }
837        if(!selUnits){
838           ui_confirmOk("No target output selected !!");
839           INV_RUNNING = 0;
840           return(TRUE);
841        }
842        INV_NEW = 0;
843     }
844 
845 
846     /* do the inversion */
847 
848     if((err = krui_initInversion()) < 0){
849        printf("init returned error %d\n",err);
850        INV_RUNNING = 0;
851        return(TRUE);
852     }
853 
854     INV_cycle++;
855     err_units = 0;
856     old_err = INV_error;
857     krui_inv_forwardPass(inputs);
858     INV_error = krui_inv_backwardPass(INV_eta,INV_delta_max,&err_units,RATIO,
859 				      inputs,outputs);
860     INV_units = err_units;
861     if((dummy=(INV_cycle%50)) == 0)
862 	 printf("cycle %d inversion error %f still %d error unit(s)\n",
863 	        INV_cycle,INV_error,INV_units);
864     if(old_err<= INV_error)growing_errors++;
865     else growing_errors = 0;
866 /*
867     if(growing_errors > 50){
868        growing_errors = 0;
869        ui_drawInput();
870        ui_confirmOk(" Inversion error does not diminish!\n Net might not be properly trained !");
871        INV_RUNNING = 0;
872        return(TRUE);
873     }
874 */
875 
876     /* check the result of this inversion step */
877 
878     if(INV_units > 0){
879 
880        /* while still one unit has an error > delta_max return FALSE,  */
881        /* to start another cycle                                       */
882        return(FALSE);
883     }else{
884 
885        /*   algorithm has converged, display discovered activation pattern */
886        printf("cycle %d inversion error %f, %d error units left\n",
887 	      INV_cycle,INV_error,INV_units);
888        ui_drawInput();
889        INV_RUNNING = 0;
890        return(TRUE);
891     }
892 
893 
894 }
895 
896 #endif
897 
898 
899