1 /*****************************************************************************
2   FILE           : $Source: /projects/higgs1/SNNS/CVS/SNNS/kernel/sources/kernel.c,v $
3   SHORTNAME      : kernel.c
4   SNNS VERSION   : 4.2
5 
6   PURPOSE        : SNNS Kernel
7   NOTES          :
8 
9   AUTHOR         : Niels Mache
10   DATE           : 20.02.90
11 
12   CHANGED BY     : Sven Doering, Michael Vogt, Guenter Mamier,Christine Bagdi,
13                    Thomas Gern
14   RCS VERSION    : $Revision: 2.24 $
15   LAST CHANGE    : $Date: 1998/05/15 13:12:06 $
16 
17     Copyright (c) 1990-1995  SNNS Group, IPVR, Univ. Stuttgart, FRG
18     Copyright (c) 1996-1998  SNNS Group, WSI, Univ. Tuebingen, FRG
19 
20 ******************************************************************************/
21 #include <config.h>
22 #define  SNNS_KERNEL
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <memory.h>
28 #include <math.h>
29 
30 #include "kr_typ.h"	 /*  Kernel Types and Constants  */
31 #include "kr_const.h"	 /*  Constant Declarators for SNNS-Kernel  */
32 #include "kr_def.h"	 /*  Default Values  */
33 
34 #ifndef rand
35 #include "random.h"	 /*  Randomize Library Function Prototypes  */
36 #endif
37 
38 #include "kernel.ph"	 /*  Function Prototypes  */
39 #include "kr_mem.h"	 /*  Function Prototypes  */
40 #include "kr_funcs.h"	 /*  Function Prototypes  */
41 #include "kr_mac.h"	 /*  Kernel Macros  */
42 #include "cc_glob.h"
43 #include "kr_newpattern.h"
44 #include "prun_f.h"
45 #include "learn_f.h"
46 #include "matrix.h"
47 
48 #ifdef MASPAR_KERNEL
49 
50 #include "kr_feedf.h"	 /*  Function Prototypes */
51 
52 #endif
53 
54 #include "kr_art.h"      /*  Function Prototypes  */
55 #include "kr_art1.h"     /*  Prototypes and global defs for ART1  */
56 #include "kr_art2.h"     /*  Prototypes and global defs for ART2  */
57 #include "kr_amap.h"     /*  Prototypes and global defs for ARTMAP  */
58 #include "kr_JordElm.h"
59 
60 extern FlintType OUT_Custom_Python(FlintType act);
61 extern FlintType ACT_Custom_Python(struct Unit * unit_ptr);
62 extern FlintType ACT_DERIV_Custom_Python(struct Unit * unit_ptr);
63 extern FlintType ACT_2_DERIV_Custom_Python(struct Unit * unit_ptr);
64 
65 PyObject *kr_findPythonFunction(char *name, int type);
66 FlintType kr_PythonOutFunction(PyObject *func, FlintType activation);
67 
68 /*****************************************************************************
69   FUNCTION : kr_countUnits
70 
71   PURPOSE  : count units according to their topological type
72   NOTES    :
73 
74   RETURNS  :
75   UPDATE   :
76 ******************************************************************************/
kr_countUnits(struct Unit * unit_ptr,int mode)77 static void  kr_countUnits(struct Unit *unit_ptr, int mode)
78 {
79   if (mode == UNIT_ADD)  {
80     /*  add unit  */
81     switch (unit_ptr->flags & UFLAG_TTYP_PAT)  {
82       case  UFLAG_TTYP_IN:
83         NoOfInputUnits++;
84         break;
85       case  UFLAG_TTYP_OUT:
86         NoOfOutputUnits++;
87         break;
88       case  UFLAG_TTYP_HIDD:
89         NoOfHiddenUnits++;
90         break;
91     }
92     return;
93   }
94   if (mode == UNIT_DELETE)  {
95     /*  delete unit  */
96     switch (unit_ptr->flags & UFLAG_TTYP_PAT)  {
97       case  UFLAG_TTYP_IN:
98         --NoOfInputUnits;
99         break;
100       case  UFLAG_TTYP_OUT:
101         --NoOfOutputUnits;
102         break;
103       case  UFLAG_TTYP_HIDD:
104         --NoOfHiddenUnits;
105         break;
106     }
107     return;
108   }
109 }
110 
111 /*****************************************************************************
112   FUNCTION : kr_symbolCheck
113 
114   PURPOSE  : spell checker  (check identifiers for matching [A-Za-z]^[|, ]*
115   NOTES    :
116 
117   RETURNS  :
118   UPDATE   :
119 ******************************************************************************/
kr_symbolCheck(char * symbol)120 bool    kr_symbolCheck(char *symbol)
121 {
122   register  char  c;
123 
124 
125   KernelErrorCode = KRERR_SYMBOL;
126 
127   if (!isalpha( *symbol ))
128     /*	Symbol pattern invalid (must match [A-Za-z]^[|, ]*)  */
129     return( FALSE );
130 
131   while ( (c = *(++symbol)) != '\0' )
132     {
133     if (!isgraph( c ))
134       /*  Symbol pattern invalid (must match [A-Za-z]^[|, ]*)  */
135       return( FALSE );
136 
137     if ( c == '|' || c == ',')
138       /*  Symbol pattern invalid (must match [A-Za-z]^[|, ]*)  */
139       return( FALSE );
140   }
141 
142   KernelErrorCode = KRERR_NO_ERROR;
143   return( TRUE );
144 }
145 
146 /*****************************************************************************
147   FUNCTION : kr_getUnitPtr
148 
149   PURPOSE  :
150   NOTES    :
151 
152   RETURNS  : returns the pointer to the given unit, returns NULL if unit
153              doesn't exist
154   UPDATE   :
155 ******************************************************************************/
kr_getUnitPtr(int unit_no)156 struct Unit  *kr_getUnitPtr(int unit_no)
157 {
158   struct Unit   *unit_ptr;
159 
160   KernelErrorCode = KRERR_NO_ERROR;
161 
162   if ((unit_no != 0) &&
163       (unit_no >= MinUnitNo) && (unit_no <= MaxUnitNo) &&
164       UNIT_IN_USE( unit_ptr = unit_array + unit_no ))
165     return( unit_ptr );
166 
167   /*  invalid unit no.  */
168   KernelErrorCode = KRERR_UNIT_NO;
169   return( NULL );
170 }
171 
172 /*****************************************************************************
173   FUNCTION : kr_getUnitValues
174 
175   PURPOSE  :
176   NOTES    :
177 
178   RETURNS  : Returns the value of the specified unit component
179   UPDATE   :
180 ******************************************************************************/
kr_getUnitValues(int unit_no,int component_selector)181 FlintType  kr_getUnitValues(int unit_no, int component_selector)
182 {
183   struct Unit   *unit_ptr;
184 
185   unit_ptr = kr_getUnitPtr( unit_no );
186   if (KernelErrorCode != KRERR_NO_ERROR)
187     return( (FlintType) 0);    /*  invalid unit no.  */
188 
189   switch (component_selector)
190     {
191     case SEL_UNIT_ACT:
192       return( (FlintType) unit_ptr->act );
193     case SEL_UNIT_OUT:
194       return( (FlintType) unit_ptr->Out.output );
195     case SEL_UNIT_IACT:
196       return( (FlintType) unit_ptr->i_act );
197     case SEL_UNIT_BIAS:
198       return( (FlintType) unit_ptr->bias );
199     case SEL_UNIT_VALA:
200       return( (FlintType) unit_ptr->value_a );
201     default:
202       KernelErrorCode = KRERR_PARAMETERS;
203       return ((FlintType) 0);    /*  invalid selector */
204   }
205 }
206 /*****************************************************************************
207   FUNCTION : kr_setUnitValues
208 
209   PURPOSE  : Sets the value of the specified unit component
210   NOTES    :
211 
212   RETURNS  : Returns the errorcode
213   UPDATE   :
214 ******************************************************************************/
kr_setUnitValues(int unit_no,int component_selector,FlintTypeParam value)215 krui_err  kr_setUnitValues(int unit_no, int component_selector,
216 			   FlintTypeParam value)
217 {
218   struct Unit   *unit_ptr;
219 
220   unit_ptr = kr_getUnitPtr( unit_no );
221   if (KernelErrorCode != KRERR_NO_ERROR)
222     return( KernelErrorCode );	  /*  invalid unit no.	*/
223 
224   switch (component_selector)
225     {
226     case SEL_UNIT_ACT:
227       unit_ptr->act = (FlintType) value;
228       break;
229     case SEL_UNIT_OUT:
230       unit_ptr->Out.output = (FlintType) value;
231       break;
232     case SEL_UNIT_IACT:
233       unit_ptr->i_act = (FlintType) value;
234       break;
235     case SEL_UNIT_BIAS:
236       unit_ptr->bias = (FlintType) value;
237       break;
238     case SEL_UNIT_VALA:
239       unit_ptr->value_a = (FlintType) value;
240       break;
241     default:
242       KernelErrorCode = KRERR_PARAMETERS;
243       break;   /*  invalid selector */
244   }
245 
246   return( KernelErrorCode );
247 }
248 /*****************************************************************************
249   FUNCTION : kr_setAllUnitValues
250 
251   PURPOSE  : Sets all unit components of the specified unit
252   NOTES    :
253 
254   RETURNS  : Returns the errorcode
255   UPDATE   :
256 ******************************************************************************/
kr_setAllUnitValues(int unit_no,FlintTypeParam out,FlintTypeParam act,FlintTypeParam i_act,FlintTypeParam bias)257 krui_err  kr_setAllUnitValues(int unit_no, FlintTypeParam out,
258 			      FlintTypeParam act, FlintTypeParam i_act,
259 			      FlintTypeParam bias)
260 {
261   struct Unit   *unit_ptr;
262 
263   unit_ptr = kr_getUnitPtr( unit_no );
264   if (KernelErrorCode != KRERR_NO_ERROR)
265     return( KernelErrorCode );
266 
267   unit_ptr->Out.output = (FlintType) out;
268   unit_ptr->act = (FlintType) act;
269   unit_ptr->i_act = (FlintType) i_act;
270   unit_ptr->bias = (FlintType) bias;
271 
272   return( KernelErrorCode );
273 }
274 
275 /*****************************************************************************
276   FUNCTION : kr_makeDefaultUnit
277 
278   PURPOSE  : Creates a unit with default values
279   NOTES    :
280 
281   RETURNS  :
282   UPDATE   : Thomas Gern, 07.09.95 -> actbuf is initialized
283 ******************************************************************************/
kr_makeDefaultUnit(void)284 int  kr_makeDefaultUnit(void)
285 {
286   struct Unit  *unit_ptr;
287   FunctionPtr  func_ptr;
288   int  unit_no;
289   int  i;
290 
291   if ((unit_no = krm_getUnit()) == 0)
292     return( KernelErrorCode );
293   unit_no = abs(unit_no);
294 
295   if (KernelErrorCode != KRERR_NO_ERROR)
296     return( KernelErrorCode );
297 
298   (void) kr_setAllUnitValues( unit_no, (FlintTypeParam) DEF_OUT, DefaultIAct,
299 			      DefaultIAct, DefaultBias );
300 
301   unit_ptr = unit_array + unit_no;
302 
303   unit_ptr->Ftype_entry = NULL;
304   unit_ptr->value_a = (FlintType) 0;          /*previous bias change*/
305   unit_ptr->value_b = (FlintType) 0;          /*previous bias slope*/
306   unit_ptr->value_c = (FlintType) 0;          /*actual bias slope*/
307 
308   for (i = 0; i < MAX_BPTT_BACKSTEP; i++)
309     unit_ptr->actbuf[i] = 0.0;
310 
311 
312   if (DefaultUFuncAct == NULL)  {
313     if (!krf_funcSearch( krf_getCurrentNetworkFunc( ACT_FUNC ),
314                          ACT_FUNC, &func_ptr))
315       return( KernelErrorCode );
316 
317     DefaultUFuncAct = (ActFuncPtr) func_ptr;
318 
319     if (!krf_funcSearch( krf_getCurrentNetworkFunc( ACT_FUNC ),
320                          ACT_DERIV_FUNC, &func_ptr))
321       return( KernelErrorCode );
322 
323     DefaultUFuncActDeriv = (ActDerivFuncPtr) func_ptr;
324 
325     if (!krf_funcSearch( krf_getCurrentNetworkFunc( ACT_FUNC ),
326                          ACT_2_DERIV_FUNC, &func_ptr))
327       return( KernelErrorCode );
328 
329     DefaultUFuncAct2Deriv = (ActDerivFuncPtr) func_ptr;
330 
331     if (!krf_funcSearch( krf_getCurrentNetworkFunc( OUT_FUNC ),
332                          OUT_FUNC, &func_ptr))
333       return( KernelErrorCode );
334 
335     DefaultUFuncOut = (OutFuncPtr) func_ptr;
336   }
337 
338   unit_ptr->out_func = DefaultUFuncOut;       /*  default output function  */
339   unit_ptr->act_func = DefaultUFuncAct;       /*  default activation function */
340   unit_ptr->act_deriv_func = DefaultUFuncActDeriv; /* def. derivation actfunc */
341   unit_ptr->act_2_deriv_func = DefaultUFuncAct2Deriv; 	/*  default derivation act. function */
342   unit_ptr->python_out_func = DefaultUPythonFuncOut;       /*  default output function  */
343   unit_ptr->python_act_func = DefaultUPythonFuncAct;       /*  default activation function */
344   unit_ptr->python_act_deriv_func = DefaultUPythonFuncActDeriv; /* def. derivation actfunc */
345   unit_ptr->python_act_2_deriv_func = DefaultUPythonFuncAct2Deriv; 	/*  default derivation act. function */
346   unit_ptr->unit_name= NULL;			/*  default is no unit name */
347   unit_ptr->subnet_no  = DefaultSubnetNo;
348   unit_ptr->layer_no   = DefaultLayerNo;
349   unit_ptr->unit_pos.x = DefaultPosX;
350   unit_ptr->unit_pos.y = DefaultPosY;
351 
352   unit_ptr->unit_pos.z = DefaultPosZ;
353 
354   /*  set unit flags  */
355   unit_ptr->flags = UFLAG_INITIALIZED | DefaultSType;
356 
357   /*  count units  */
358   kr_countUnits( unit_ptr, UNIT_ADD );
359 
360   return( unit_no );
361 }
362 
363 /*****************************************************************************
364   FUNCTION : kr_createUnit
365 
366   PURPOSE  : Creates a user defined unit
367   NOTES    :
368 
369   RETURNS  :
370   UPDATE   :
371 ******************************************************************************/
kr_createUnit(char * unit_name,char * out_func_name,char * act_func_name,FlintTypeParam i_act,FlintTypeParam bias)372 int  kr_createUnit(char *unit_name, char *out_func_name, char *act_func_name,
373 		   FlintTypeParam i_act, FlintTypeParam bias)
374 {
375   FunctionPtr   out_func_ptr, act_func_ptr, act_deriv_func_ptr,
376                 act_2_deriv_func_ptr;
377   char  *str_ptr;
378   int   unit_no;
379   struct Unit  *unit_ptr;
380 
381 
382 
383   if (!kr_symbolCheck( unit_name ))
384     return( KernelErrorCode );	/*  Symbol pattern invalid
385 				    (must match [A-Za-z]^[|, ]*)  */
386 
387   if ( !krf_funcSearch( out_func_name, OUT_FUNC, &out_func_ptr ) )
388     return( KernelErrorCode );
389   if ( !krf_funcSearch( act_func_name, ACT_FUNC, &act_func_ptr ) )
390     return( KernelErrorCode );
391 
392   /*  set the derivation function of the activation function  */
393   if ( !krf_funcSearch( act_func_name, ACT_DERIV_FUNC, &act_deriv_func_ptr ))
394     return( KernelErrorCode );
395 
396   /*  set the second derivation function of the activation function  */
397   if ( !krf_funcSearch( act_func_name, ACT_2_DERIV_FUNC, &act_2_deriv_func_ptr ))
398     return( KernelErrorCode );
399 
400   if ( (str_ptr = krm_NTableInsertSymbol( unit_name, UNIT_SYM ) ) == NULL)
401     return( KernelErrorCode );
402 
403   unit_no = kr_makeDefaultUnit();
404   if (KernelErrorCode != KRERR_NO_ERROR)
405     return( KernelErrorCode );
406 
407   (void) kr_setAllUnitValues( unit_no, (FlintTypeParam) DEF_OUT,
408 			      i_act, i_act, bias );
409 
410   unit_ptr = unit_array + unit_no;
411 
412   unit_ptr->out_func  = (OutFuncPtr) out_func_ptr;
413   if(unit_ptr->out_func == OUT_Custom_Python) {
414   	unit_ptr->python_out_func =
415 		kr_findPythonFunction(out_func_name, OUT_FUNC);
416   }
417   unit_ptr->act_func  = (ActFuncPtr) act_func_ptr;
418   unit_ptr->act_deriv_func = (ActDerivFuncPtr) act_deriv_func_ptr;
419   unit_ptr->act_2_deriv_func = (ActDerivFuncPtr) act_2_deriv_func_ptr;
420   if(unit_ptr->act_func == ACT_Custom_Python) {
421   	unit_ptr->python_act_func =
422 		kr_findPythonFunction(act_func_name, ACT_FUNC);
423   	unit_ptr->python_act_deriv_func =
424 		kr_findPythonFunction(act_func_name, ACT_DERIV_FUNC);
425   	unit_ptr->python_act_2_deriv_func =
426 		kr_findPythonFunction(act_func_name, ACT_DERIV_FUNC);
427   }
428   unit_ptr->unit_name = str_ptr;
429 
430   NetModified = TRUE;
431   return( unit_no );
432 }
433 
434 /*****************************************************************************
435   FUNCTION : kr_unitSetTType
436 
437   PURPOSE  : Sets the topologic type of the unit
438   NOTES    :
439 
440   RETURNS  : Returns the errorcode
441   UPDATE   :
442 ******************************************************************************/
kr_unitSetTType(int unit_no,int UnitTType)443 krui_err  kr_unitSetTType(int unit_no, int UnitTType)
444 {
445   struct  Unit	*unit_ptr;
446   int  intflags;
447 
448   if ((unit_ptr = kr_getUnitPtr( unit_no )) == NULL)
449     return( KernelErrorCode );
450 
451   intflags = kr_TType2Flags( UnitTType );
452   if (KernelErrorCode != KRERR_NO_ERROR)
453     return( KernelErrorCode );
454 
455   if (((FlagWord) intflags == UFLAG_TTYP_SPEC_X) ||
456       ((FlagWord) intflags == UFLAG_TTYP_N_SPEC_X)) {
457       if ((FlagWord) intflags == UFLAG_TTYP_SPEC_X) {
458 	  /*  the topologic type of the unit will change  */
459 	  NetModified = TRUE;
460 	  /*  count units  */
461 	  kr_countUnits( unit_ptr, UNIT_DELETE );
462 
463 	  /*  change topologic type of the unit,  add special Flag  */
464 	  unit_ptr->flags |= (FlagWord)  UFLAG_TTYP_SPEC;
465 
466 	  /*  count units  */
467 	  kr_countUnits( unit_ptr, UNIT_ADD );
468       }else{
469 	  if((unit_ptr->flags & UFLAG_TTYP_PAT)!= UFLAG_TTYP_SPEC){
470 	      /*  the topologic type of the unit will change  */
471 	      NetModified = TRUE;
472 	      /*  count units  */
473 	      kr_countUnits( unit_ptr, UNIT_DELETE );
474 
475 	      /*  change topologic type of the unit,  delete special Flag  */
476 	      unit_ptr->flags &= (FlagWord)  ~UFLAG_TTYP_SPEC;
477 
478 	      /*  count units  */
479 	      kr_countUnits( unit_ptr, UNIT_ADD );
480 	  }
481       }
482   }else{
483       if ((unit_ptr->flags & UFLAG_TTYP_PAT) != (FlagWord) intflags) {
484 	  /*  the topologic type of the unit will change  */
485 	  NetModified = TRUE;
486 	  /*  count units  */
487 	  kr_countUnits( unit_ptr, UNIT_DELETE );
488 
489 	  /*  change topologic type of the unit  */
490 	  unit_ptr->flags &= ~UFLAG_TTYP_PAT;
491 	  unit_ptr->flags |= (FlagWord)  intflags;
492 
493 	  /*  count units  */
494 	  kr_countUnits( unit_ptr, UNIT_ADD );
495       }
496   }
497 
498   return( KernelErrorCode );
499 }
500 
501 
502 
503 /*****************************************************************************
504   FUNCTION : kr_setSite
505 
506   PURPOSE  : initialize the first/next site or the named site at the current
507              unit for access
508   NOTES    :
509 
510   RETURNS  :
511   UPDATE   :
512 ******************************************************************************/
kr_setSite(int mode,char * site_name)513 int  kr_setSite(int mode, char *site_name)
514 {
515   struct SiteTable  *stbl_ptr;
516 
517   if (unitPtr == NULL)  {
518     KernelErrorCode = KRERR_UNIT_NO;
519     return( KernelErrorCode );
520   }
521 
522   KernelErrorCode = KRERR_NO_ERROR;
523 
524   switch (mode)  {
525     case  FIRST:
526       prevSitePtr = NULL;
527 
528       if UNIT_HAS_SITES( unitPtr )
529 	{  /*  Unit has sites  */
530 	sitePtr = unitPtr->sites;
531 	return( TRUE );
532       }
533       else  {
534 	sitePtr = NULL;
535 	return( FALSE );
536       }
537 
538     case  NEXT:
539       if ((sitePtr == NULL) || (sitePtr->next == NULL))  return( FALSE );
540 
541       prevSitePtr = sitePtr;
542       sitePtr	  = sitePtr->next;
543       return( TRUE );
544 
545     case  NAME:
546       if (!UNIT_HAS_SITES( unitPtr ))
547 	{  /*  Current unit doesn't have sites  */
548 	KernelErrorCode = KRERR_NO_SITES;
549 	return( KernelErrorCode );
550       }
551 
552       if ((stbl_ptr = krm_STableSymbolSearch( site_name )) == NULL)
553 	{  /*	site name isn't defined */
554 	KernelErrorCode = KRERR_UNDEF_SITE_NAME;
555 	return( KernelErrorCode );
556       }
557 
558       for (sitePtr = unitPtr->sites, prevSitePtr = NULL;
559 	   sitePtr != NULL;
560 	   prevSitePtr = sitePtr, sitePtr = sitePtr->next)
561 	if (sitePtr->site_table == stbl_ptr)
562 	  return( KRERR_NO_ERROR );  /*  site was found  */
563 
564       sitePtr = prevSitePtr = NULL;
565 
566       /*  Current unit doesn't have a site with this name  */
567       KernelErrorCode = KRERR_NO_SUCH_SITE;
568       return( KernelErrorCode );
569 
570     default:
571       KernelErrorCode = KRERR_PARAMETERS;
572       return( KernelErrorCode );
573   }
574 }
575 
576 
577 /*****************************************************************************
578   FUNCTION : kr_getUnit
579 
580   PURPOSE  : returns the number of the first/next/current unit of the unit array
581   NOTES    :
582 
583   RETURNS  :
584   UPDATE   :
585 ******************************************************************************/
kr_getUnit(int mode)586 int  kr_getUnit(int mode)
587 {
588   register struct Unit   *unit_ptr;
589 
590 
591   if (NoOfUnits == 0)  return( 0 );
592 
593   switch (mode)
594     {
595     case  FIRST:
596       unitNo = MinUnitNo;
597       unitPtr = unit_array + MinUnitNo;
598 
599       if UNIT_HAS_SITES( unitPtr )
600 	{  /*  Initialize current site pointer to the first available site */
601 	prevSitePtr = NULL;
602 	sitePtr = unitPtr->sites;
603       }
604       else
605 	{  /*  No sites available  */
606 	prevSitePtr = NULL;
607 	sitePtr     = NULL;
608       }
609 
610       return( unitNo );
611 
612     case  NEXT:
613       unit_ptr = unitPtr;
614       if ((unit_ptr - unit_array) >= MaxUnitNo)  return( 0 );
615 
616       while (!UNIT_IN_USE( ++unit_ptr )) ;
617 
618       unitNo = unit_ptr - unit_array;
619       unitPtr = unit_ptr;
620 
621       if UNIT_HAS_SITES( unit_ptr )
622 	{  /*  Initialize current site pointer to the first available site */
623 	prevSitePtr = NULL;
624 	sitePtr = unit_ptr->sites;
625       }
626       else
627 	{  /*  No sites available  */
628 	prevSitePtr = NULL;
629 	sitePtr     = NULL;
630       }
631 
632       return( unitNo );
633 
634     case  CURRENT:
635       return( unitNo );
636 
637     default:
638       KernelErrorCode = KRERR_PARAMETERS;
639       return( 0 );
640   }
641 }
642 
643 /*****************************************************************************
644   FUNCTION : kr_setCurrUnit
645 
646   PURPOSE  : initializes the given unit for access
647   NOTES    :
648 
649   RETURNS  : Returns the errorcode
650   UPDATE   :
651 ******************************************************************************/
kr_setCurrUnit(int unit_no)652 krui_err  kr_setCurrUnit(int unit_no)
653 {
654   struct Unit   *unit_ptr;
655 
656 
657   if ((unit_ptr = kr_getUnitPtr( unit_no )) == NULL)
658     return( KernelErrorCode );
659 
660   unitNo = unit_no;
661   unitPtr = unit_ptr;
662 
663   if UNIT_HAS_SITES( unit_ptr )
664     {  /*  Initialize current site pointer to the first available site */
665     prevSitePtr = NULL;
666     sitePtr = unit_ptr->sites;
667   }
668   else
669     {  /*  No sites available  */
670     prevSitePtr = NULL;
671     sitePtr	= NULL;
672   }
673 
674   return( KRERR_NO_ERROR );
675 }
676 
677 
678 /*****************************************************************************
679   FUNCTION : kr_getPredecessorUnit
680 
681   PURPOSE  : Returns the no. of first, next or current predecessor unit of the
682              current unit/site and the connection weight
683   NOTES    :
684 
685   RETURNS  :
686   UPDATE   :
687 ******************************************************************************/
kr_getPredecessorUnit(int mode,FlintType * weight,float * val_a,float * val_b,float * val_c)688 int  kr_getPredecessorUnit(int mode, FlintType *weight, float* val_a, float* val_b, float* val_c)
689 {
690   static struct Link  *link_ptr = NULL;
691 
692 
693   if (unitPtr == NULL)
694     {  /*  no current unit  */
695     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
696     return( 0 );
697   }
698 
699   switch (mode)
700     {
701     case  FIRST:  /*  first predecessor link wanted  */
702       if UNIT_HAS_SITES( unitPtr )
703 	{
704 	if (sitePtr == NULL)
705 	  /*  site not initialized  */
706 	  link_ptr = unitPtr->sites->links;
707 	else
708 	  link_ptr = sitePtr->links;
709       }
710       else
711 	link_ptr = (struct Link *) unitPtr->sites;
712 
713       linkPtr = link_ptr;
714       prevLinkPtr = NULL;
715       if (link_ptr == NULL)  return( 0 );  /*  No inputs   */
716 
717       *weight = link_ptr->weight;
718       *val_a  = link_ptr->value_a;
719       *val_b  = link_ptr->value_b;
720       *val_c  = link_ptr->value_c;
721       return( link_ptr->to - unit_array );  /*	Return unit number  */
722 
723     case  NEXT:
724       if (link_ptr == NULL)
725 	 {  /*	no current link  */
726 	 KernelErrorCode = KRERR_NO_CURRENT_LINK;
727 	 return( 0 );
728        }
729 
730       prevLinkPtr = link_ptr;
731       if ((linkPtr = link_ptr = link_ptr->next) == NULL)
732 	{
733 	prevLinkPtr = NULL;
734 	return( 0 );  /*  no successor unit  */
735       }
736 
737 
738       *weight = link_ptr->weight;
739       *val_a  = link_ptr->value_a;
740       *val_b  = link_ptr->value_b;
741       *val_c  = link_ptr->value_c;
742       return( link_ptr->to - unit_array );  /*	Return unit number  */
743 
744     case  CURRENT:
745       if (link_ptr == NULL)
746 	 {  /*	no current link  */
747 	 KernelErrorCode = KRERR_NO_CURRENT_LINK;
748 	 return( 0 );
749        }
750 
751       *weight = link_ptr->weight;
752       *val_a  = link_ptr->value_a;
753       *val_b  = link_ptr->value_b;
754       *val_c  = link_ptr->value_c;
755       return( link_ptr->to - unit_array );  /*	Return unit number  */
756 
757     default:
758       KernelErrorCode = KRERR_PARAMETERS;
759       return( 0 );
760   }
761 }
762 
763 /*****************************************************************************
764   FUNCTION : kr_searchOutputConnection
765 
766   PURPOSE  :
767   NOTES    :
768 
769   RETURNS  :
770   UPDATE   :
771 ******************************************************************************/
kr_searchOutputConnection(struct Unit * start_unit_ptr,struct Unit * source_unit_ptr,FlintType * weight)772 static int  kr_searchOutputConnection(struct Unit *start_unit_ptr,
773 				      struct Unit *source_unit_ptr,
774 				      FlintType *weight)
775 {
776   register struct  Link  *link_ptr, *prev_link_ptr;
777   register struct  Unit  *source_unit;
778   register struct  Site  *site_ptr, *prev_site_ptr;
779   register struct  Unit  *unit_ptr;
780 
781 
782   source_unit = source_unit_ptr;
783 
784   if ((sitePtr != NULL))
785     {  /*  current unit has sites, so search for another connection at the
786 	   other sites of the unit  */
787     for (site_ptr = sitePtr->next, prev_site_ptr = sitePtr;
788 	 site_ptr != NULL;
789 	 prev_site_ptr = site_ptr, site_ptr = site_ptr->next)
790       for (link_ptr = site_ptr->links, prev_link_ptr = NULL;
791 	   link_ptr != NULL;
792 	   prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
793 	if (link_ptr->to == source_unit)
794 	  {
795 	  sitePtr = site_ptr;  /*  set current site  */
796 	  prevSitePtr = prev_site_ptr;	/*  set previous site  */
797 	  linkPtr = link_ptr;  /*  set current link  */
798 	  prevLinkPtr = prev_link_ptr;	/*  set previous link  */
799 
800 	  *weight = link_ptr->weight;
801 	  return( unitNo );
802         }
803 
804     start_unit_ptr++;  /*  no connection found at the current site,
805                            so start search at the next units  */
806   }
807 
808   for(unit_ptr = start_unit_ptr; unit_ptr <= unit_array + MaxUnitNo; unit_ptr++)
809     if UNIT_IN_USE( unit_ptr )
810        {
811        if UNIT_HAS_DIRECT_INPUTS( unit_ptr )
812 	 {
813 	 for (link_ptr = (struct Link *) unit_ptr->sites, prev_link_ptr = NULL;
814 	      link_ptr != NULL;
815 	      prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
816 	   if (link_ptr->to == source_unit)
817 	     {
818 	     unitPtr = unit_ptr;  /*  set current unit pointer	*/
819 	     unitNo = unit_ptr - unit_array;  /*  set current unit no.	*/
820 	     sitePtr = prevSitePtr = NULL;  /*	no current site  */
821 	     linkPtr = link_ptr;  /*  set current link	*/
822 	     prevLinkPtr = prev_link_ptr;  /*  set previous link  */
823 
824 	     *weight = link_ptr->weight;
825 	     return( unitNo );
826 	   }
827        }
828        else
829 	 if UNIT_HAS_SITES( unit_ptr )
830 	   {
831 	   for (site_ptr = unit_ptr->sites, prev_site_ptr = NULL;
832 		site_ptr != NULL;
833 		prev_site_ptr = site_ptr, site_ptr = site_ptr->next)
834 	     for (link_ptr = site_ptr->links, prev_link_ptr = NULL;
835 		  link_ptr != NULL;
836 		  prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
837 	       if (link_ptr->to == source_unit)
838 		 {
839 		 unitPtr = unit_ptr;  /*  set current unit pointer  */
840 		 unitNo = unit_ptr - unit_array;  /*  set current unit no.  */
841 		 sitePtr = site_ptr;  /*  set current site  */
842 		 prevSitePtr = prev_site_ptr;  /*  set previous site  */
843 		 linkPtr = link_ptr;  /*  set current link  */
844 		 prevLinkPtr = prev_link_ptr;  /*  set previous link  */
845 
846 		 *weight = link_ptr->weight;
847 		 return( unitNo );
848 	       }
849 	 }
850     }
851 
852   /*  no successor unit found  */
853   unitPtr = NULL; unitNo = 0;  /*  no current unit  */
854   sitePtr = prevSitePtr = NULL;  /*  no current site  */
855   linkPtr = prevLinkPtr = NULL;  /*  no current link  */
856 
857   return( 0 );
858 }
859 
860 
861 /*****************************************************************************
862   FUNCTION : kr_getSuccessorUnit
863 
864   PURPOSE  : Returns the no. of first or next succecessor unit of the
865              given unit and the connection strenght.
866              Sets the current unit/site.
867   NOTES    :
868 
869   RETURNS  :
870   UPDATE   :
871 ******************************************************************************/
kr_getSuccessorUnit(int mode,int source_unit_no,FlintType * weight)872 int  kr_getSuccessorUnit(int mode, int source_unit_no, FlintType *weight)
873 {
874   static struct Unit  *source_unit_ptr,
875 		      *current_unit_ptr = NULL;
876   static struct Site  *current_site_ptr = NULL;
877   int  unit_no;
878 
879 
880   switch (mode)
881     {
882     case  FIRST:  /*  first successor link wanted  */
883       if ((source_unit_ptr = kr_getUnitPtr( source_unit_no )) == NULL)
884 	return( KernelErrorCode );
885 
886       sitePtr = NULL;  /*  no current Site  */
887       unit_no = kr_searchOutputConnection( unit_array + MinUnitNo,
888 					   source_unit_ptr, weight );
889       current_unit_ptr = unitPtr;
890       current_site_ptr = sitePtr;
891 
892       return( unit_no );
893 
894     case  NEXT:  /*  next successor link wanted  */
895       if (current_unit_ptr == NULL)
896 	{  /*  no current unit	*/
897 	KernelErrorCode = KRERR_NO_CURRENT_UNIT;
898 	return( 0 );
899       }
900 
901       sitePtr = current_site_ptr;
902 
903       unit_no = kr_searchOutputConnection( current_unit_ptr + 1,
904 					   source_unit_ptr, weight );
905       current_unit_ptr = unitPtr;
906       current_site_ptr = sitePtr;
907 
908       return( unit_no );
909 
910     default:
911       KernelErrorCode = KRERR_PARAMETERS;
912       return( 0 );
913   }
914 }
915 
916 
917 
918 /*****************************************************************************
919   FUNCTION : kr_areConnected
920 
921   PURPOSE  : True if there exists a connection between source unit
922              <source_unit_no> and target unit <target_unit_no>, otherwise false.
923 	     If there exist a  connection between these units, kr_areConnected
924 	     returns the connection strength also.
925   NOTES    : This function is slow (Units are backward chained only)
926   IMPORTANT: If there exist a connection, the current unit and site will be
927 	     set to the target unit/site.
928 
929   RETURNS  : Returns FALSE if unit doesn't exist.
930   UPDATE   :
931 ******************************************************************************/
kr_areConnected(int source_unit_no,int target_unit_no,FlintType * weight)932 bool  kr_areConnected(int source_unit_no, int target_unit_no, FlintType *weight)
933 {
934   register struct  Link  *link_ptr, *prev_link_ptr;
935   register struct  Unit  *source_unit_ptr;
936   register struct  Site  *site_ptr, *prev_site_ptr;
937   struct  Unit	*target_unit_ptr;
938 
939 
940   if ( (source_unit_ptr = kr_getUnitPtr( source_unit_no ) ) == NULL)
941     return( FALSE );    /*  invalid unit #  */
942   if ( (target_unit_ptr = kr_getUnitPtr( target_unit_no ) ) == NULL)
943     return( FALSE );    /*  invalid unit #  */
944 
945   if UNIT_HAS_DIRECT_INPUTS( target_unit_ptr )
946     {
947     for(link_ptr = (struct Link *) target_unit_ptr->sites, prev_link_ptr = NULL;
948 	 link_ptr != NULL;
949 	 prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
950       if (link_ptr->to == source_unit_ptr)
951 	{  /*  connection found  */
952 	unitPtr = target_unit_ptr;  /*	set current unit pointer  */
953 	unitNo = target_unit_no;  /*  set current unit no.  */
954 	sitePtr = prevSitePtr = NULL;  /*  no current site  */
955 	linkPtr = link_ptr;  /*  set current link  */
956 	prevLinkPtr = prev_link_ptr;  /*  set previous link  */
957 
958 	*weight = link_ptr->weight;
959 	return( TRUE );
960       }
961   }
962   else
963     if UNIT_HAS_SITES( target_unit_ptr )
964       for (site_ptr = target_unit_ptr->sites, prev_site_ptr = NULL;
965 	   site_ptr != NULL;
966 	   prev_site_ptr = site_ptr, site_ptr = site_ptr->next)
967 	for (link_ptr = site_ptr->links, prev_link_ptr = NULL;
968 	     link_ptr != NULL;
969 	     prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
970 	  if (link_ptr->to == source_unit_ptr)
971 	    {  /*  connection found  */
972 	    unitPtr = target_unit_ptr;	/*  set current unit pointer  */
973 	    unitNo = target_unit_no;  /*  set current unit no.	*/
974 	    sitePtr = site_ptr;  /*  set current site  */
975 	    prevSitePtr = prev_site_ptr;  /*  set previous site  */
976 	    linkPtr = link_ptr;  /*  set current link  */
977 	    prevLinkPtr = prev_link_ptr;  /*  set previous link  */
978 
979 	    *weight = link_ptr->weight;
980 	    return( TRUE );
981 	  }
982 
983   /*  no successor unit found  */
984   unitPtr = NULL; unitNo = 0;  /*  no current unit  */
985   sitePtr = prevSitePtr = NULL;  /*  no current site  */
986   linkPtr = prevLinkPtr = NULL;  /*  no current link  */
987 
988   return( FALSE );
989 }
990 
991 /*****************************************************************************
992   FUNCTION : kr_isConnected
993 
994   PURPOSE  :
995   NOTES    : If there exists a connection between the two units, the current
996              link is set to the link between the two units.
997   RETURNS  : True if there exists a connection between source unit
998              <source_unit_no> and the current unit/site, otherwise false.
999   UPDATE   :
1000 ******************************************************************************/
kr_isConnected(int source_unit_no,FlintType * weight)1001 bool  kr_isConnected(int source_unit_no, FlintType *weight)
1002 {
1003   register struct  Link  *link_ptr, *prev_link_ptr;
1004   register struct  Unit  *source_unit_ptr;
1005   struct  Link	*start_link_ptr;
1006 
1007 
1008   if (unitPtr == NULL)
1009     {  /*  no current unit  */
1010     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
1011     return( FALSE );
1012   }
1013   if ((source_unit_ptr = kr_getUnitPtr( source_unit_no ) ) == NULL)
1014     return( FALSE );  /*  invalid unit #  */
1015 
1016   if UNIT_HAS_DIRECT_INPUTS( unitPtr )
1017     start_link_ptr = (struct Link *) unitPtr->sites;
1018   else
1019     if UNIT_HAS_SITES( unitPtr )
1020       start_link_ptr = sitePtr->links;
1021     else
1022       return( FALSE );
1023 
1024   for (link_ptr = start_link_ptr, prev_link_ptr = NULL;
1025        link_ptr != NULL;
1026        prev_link_ptr = link_ptr, link_ptr = link_ptr->next)
1027     if (link_ptr->to == source_unit_ptr)
1028       {  /*  connection found  */
1029       linkPtr = link_ptr;  /*  set current link  */
1030       prevLinkPtr = prev_link_ptr;  /*	set previous link  */
1031 
1032       *weight = link_ptr->weight;
1033       return( TRUE );
1034     }
1035 
1036   /*  no successor unit found  */
1037   linkPtr = prevLinkPtr = NULL;  /*  no current link  */
1038 
1039   return( FALSE );
1040 }
1041 
1042 
1043 /*****************************************************************************
1044   FUNCTION : kr_getLinkWeight
1045 
1046   PURPOSE  :
1047   NOTES    :
1048 
1049   RETURNS  : Returns the link weight of the current link
1050   UPDATE   :
1051 ******************************************************************************/
kr_getLinkWeight(void)1052 FlintType  kr_getLinkWeight(void)
1053 {
1054   if (linkPtr != NULL)	return( linkPtr->weight );
1055 
1056   KernelErrorCode = KRERR_NO_CURRENT_LINK;
1057   return( (FlintType) 0 );
1058 }
1059 
1060 
1061 /*****************************************************************************
1062   FUNCTION : kr_setLinkWeight
1063 
1064   PURPOSE  : Sets the link weight of the current link
1065   NOTES    :
1066 
1067   RETURNS  :
1068   UPDATE   :
1069 ******************************************************************************/
kr_setLinkWeight(FlintTypeParam weight)1070 void  kr_setLinkWeight(FlintTypeParam weight)
1071 {
1072   if (linkPtr != NULL)
1073     {
1074     linkPtr->weight = weight;
1075     return;
1076   }
1077 
1078   KernelErrorCode = KRERR_NO_CURRENT_LINK;
1079 }
1080 
1081 
1082 /*****************************************************************************
1083   FUNCTION : kr_createLink
1084 
1085   PURPOSE  : Creates a link between source unit and the current unit/site
1086   NOTES    : kr_createLink DO NOT set the current link
1087              If you want to create a link and its unknown if there exists
1088 	     already a connection between the two units, use krui_createLink
1089 	     and test the return code, instead of the sequence kr_isConnected
1090 	     and kr_createLink
1091   RETURNS  : Returns an error code:
1092              - if memory allocation fails
1093              - if source unit doesn't exist or
1094              - if there exists already a connection between current unit/site
1095 	     and the source unit
1096              0 otherwise.
1097   UPDATE   :
1098 ******************************************************************************/
kr_createLink(int source_unit_no,FlintTypeParam weight)1099 krui_err  kr_createLink(int source_unit_no, FlintTypeParam weight)
1100 {
1101   register struct Link	*link_ptr;
1102   register struct Unit	*source_unit_ptr;
1103 
1104 
1105   KernelErrorCode = KRERR_NO_ERROR;
1106 
1107   if (unitPtr == NULL)
1108     {  /*  no current unit  */
1109     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
1110     return( KernelErrorCode );
1111   }
1112 
1113   if ((source_unit_ptr = kr_getUnitPtr( source_unit_no ) ) == NULL)
1114     return( KernelErrorCode );	/*  invalid unit #  */
1115 
1116   switch ((int) (unitPtr->flags & UFLAG_INPUT_PAT))
1117     {
1118     case  UFLAG_NO_INP:  /*  current unit doesn't have inputs  */
1119       if ((link_ptr = krm_getLink()) == NULL)
1120 	return( KernelErrorCode );
1121 
1122       link_ptr->to     = source_unit_ptr;
1123       link_ptr->weight = (FlintType) weight;
1124       link_ptr->next   = NULL;
1125 
1126       unitPtr->sites = (struct Site *) link_ptr;
1127       unitPtr->flags |= UFLAG_DLINKS;  /*  unit has direkt inputs now  */
1128 
1129       break;
1130 
1131     case  UFLAG_DLINKS:  /*  current unit has direct inputs  */
1132       FOR_ALL_LINKS( unitPtr, link_ptr )
1133 	if (link_ptr->to == source_unit_ptr)
1134 	  {  /*  there exists already a connection  */
1135 	  KernelErrorCode = KRERR_ALREADY_CONNECTED;
1136 	  return( KRERR_ALREADY_CONNECTED );
1137 	}
1138 
1139       if ((link_ptr = krm_getLink()) == NULL)
1140 	return( KernelErrorCode );
1141 
1142       link_ptr->to     = source_unit_ptr;
1143       link_ptr->weight = (FlintType) weight;
1144       link_ptr->next   = (struct Link *) unitPtr->sites;
1145       unitPtr->sites   = (struct Site *) link_ptr;
1146 
1147       break;
1148 
1149     case  UFLAG_SITES:	/*  current unit has sites  */
1150       FOR_ALL_LINKS_AT_SITE( sitePtr, link_ptr )
1151 	if (link_ptr->to == source_unit_ptr)
1152 	  {  /*  there exists already a connection  */
1153 	  KernelErrorCode = KRERR_ALREADY_CONNECTED;
1154 	  return( KRERR_ALREADY_CONNECTED );
1155 	}
1156 
1157       if ((link_ptr = krm_getLink()) == NULL)
1158 	return( KernelErrorCode );
1159 
1160       link_ptr->to     = source_unit_ptr;
1161       link_ptr->weight = (FlintType) weight;
1162       link_ptr->next   = (struct Link *) sitePtr->links;
1163       sitePtr->links   = link_ptr;
1164 
1165       break;
1166 
1167     default:
1168       KernelErrorCode = KRERR_PARAMETERS;
1169       return( KernelErrorCode );
1170   }
1171 
1172   NetModified = TRUE;
1173   return( KRERR_NO_ERROR );
1174 }
1175 
1176 /*****************************************************************************
1177   FUNCTION : kr_createLinkWithAdditionalParameters
1178 
1179   PURPOSE  : Creates a link between source unit and the current unit/site
1180              and sets the values for value_a, value_b and value_c.
1181   NOTES    : this version returns pointer to the new link and no error value.
1182              This means that you have to use the routine as follows :
1183                NewLink=kr_createLinkWithAdditionalParameters(...);
1184                if (KernelErrorCode!=KRERR_NO_ERROR) return(KernelErroCode);
1185 
1186              See notes of kr_createLink, too
1187 
1188   UPDATE   : 13.05.96 <Juergen Gatter>
1189 ******************************************************************************/
kr_createLinkWithAdditionalParameters(int source_unit_no,FlintTypeParam weight,float val_a,float val_b,float val_c)1190  struct Link*  kr_createLinkWithAdditionalParameters
1191                       (int source_unit_no, FlintTypeParam weight,
1192                        float val_a,float val_b,float val_c)
1193 {
1194   register struct Link	*link_ptr=NULL;
1195   register struct Unit	*source_unit_ptr;
1196 
1197 
1198   KernelErrorCode = KRERR_NO_ERROR;
1199 
1200   if (unitPtr == NULL)
1201     {  /*  no current unit  */
1202     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
1203     return ( link_ptr );
1204   }
1205 
1206   if ((source_unit_ptr = kr_getUnitPtr( source_unit_no ) ) == NULL)
1207     return ( link_ptr );	/*  invalid unit #  */
1208 
1209   switch ((int) (unitPtr->flags & UFLAG_INPUT_PAT))
1210     {
1211     case  UFLAG_NO_INP:  /*  current unit doesn't have inputs  */
1212       if ((link_ptr = krm_getLink()) == NULL)
1213 	return ( link_ptr );
1214 
1215       link_ptr->to     = source_unit_ptr;
1216       link_ptr->weight = (FlintType) weight;
1217       link_ptr->next   = NULL;
1218       link_ptr->value_a = val_a;
1219       link_ptr->value_b = val_b;
1220       link_ptr->value_c = val_c;
1221 
1222       unitPtr->sites = (struct Site *) link_ptr;
1223       unitPtr->flags |= UFLAG_DLINKS;  /*  unit has direkt inputs now  */
1224 
1225       break;
1226 
1227     case  UFLAG_DLINKS:  /*  current unit has direct inputs  */
1228       FOR_ALL_LINKS( unitPtr, link_ptr )
1229 	if (link_ptr->to == source_unit_ptr)
1230 	  {  /*  there exists already a connection  */
1231 	  KernelErrorCode = KRERR_ALREADY_CONNECTED;
1232 	  return( link_ptr );
1233 	}
1234 
1235       if ((link_ptr = krm_getLink()) == NULL)
1236 	return( link_ptr );
1237 
1238       link_ptr->to     = source_unit_ptr;
1239       link_ptr->weight = (FlintType) weight;
1240       link_ptr->next   = (struct Link *) unitPtr->sites;
1241       link_ptr->value_a = val_a;
1242       link_ptr->value_b = val_b;
1243       link_ptr->value_c = val_c;
1244       unitPtr->sites   = (struct Site *) link_ptr;
1245 
1246       break;
1247 
1248     case  UFLAG_SITES:	/*  current unit has sites  */
1249       FOR_ALL_LINKS_AT_SITE( sitePtr, link_ptr )
1250 	if (link_ptr->to == source_unit_ptr)
1251 	  {  /*  there exists already a connection  */
1252 	  KernelErrorCode = KRERR_ALREADY_CONNECTED;
1253 	  return( link_ptr );
1254 	}
1255 
1256       if ((link_ptr = krm_getLink()) == NULL)
1257 	return( link_ptr );
1258 
1259       link_ptr->to     = source_unit_ptr;
1260       link_ptr->weight = (FlintType) weight;
1261       link_ptr->next   = (struct Link *) sitePtr->links;
1262       link_ptr->value_a = val_a;
1263       link_ptr->value_b = val_b;
1264       link_ptr->value_c = val_c;
1265       sitePtr->links   = link_ptr;
1266 
1267       break;
1268 
1269     default:
1270       KernelErrorCode = KRERR_PARAMETERS;
1271       return( link_ptr );
1272   }
1273 
1274   NetModified = TRUE;
1275   return( link_ptr );
1276 }
1277 
1278 
1279 /*****************************************************************************
1280   FUNCTION : kr_deleteLink
1281 
1282   PURPOSE  : Deletes the current link
1283   NOTES    : To delete a link between the current unit/site and the source unit
1284              <source_unit_no>, call krui_isConnected( source_unit_no ) and
1285              krui_deleteLink()
1286 
1287   RETURNS  : Returns the errorcode
1288   UPDATE   :
1289 ******************************************************************************/
kr_deleteLink(void)1290 krui_err  kr_deleteLink(void)
1291 {
1292   register struct Link	 *next_link_ptr;
1293 
1294 
1295   if (linkPtr == NULL)
1296     {  /*  no current link  */
1297     KernelErrorCode = KRERR_NO_CURRENT_LINK;
1298     return( KernelErrorCode );
1299   }
1300 
1301   if (unitPtr == NULL)
1302     {  /*  no current unit  */
1303     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
1304     return( KernelErrorCode );
1305   }
1306 
1307   KernelErrorCode = KRERR_NO_ERROR;
1308   switch ((int) (unitPtr->flags & UFLAG_INPUT_PAT))
1309     {
1310     case  UFLAG_NO_INP:  /*  current unit doesn't have inputs  */
1311       KernelErrorCode = KRERR_UNIT_NO_INPUTS;
1312       return( KernelErrorCode );
1313 
1314     case  UFLAG_DLINKS:  /*  current unit has direct inputs  */
1315       next_link_ptr = linkPtr->next;
1316       krm_releaseLink( linkPtr );
1317       linkPtr = next_link_ptr;
1318 
1319       if (prevLinkPtr != NULL)	/*  current link isn't first link at the unit */
1320 	prevLinkPtr->next = next_link_ptr;  /*	chain previous link pointer
1321 						with next link pointer	*/
1322       else
1323 	{  /*  current link is the first link at the unit  */
1324 	unitPtr->sites = (struct Site *) next_link_ptr;
1325 	if (next_link_ptr == NULL)
1326 	  unitPtr->flags &= (~UFLAG_INPUT_PAT);  /* last input deleted:
1327 						    the unit has no inputs now*/
1328       }
1329 
1330       NetModified = TRUE;
1331       return( KRERR_NO_ERROR );
1332 
1333     case  UFLAG_SITES:	/*  current unit has sites  */
1334       next_link_ptr = linkPtr->next;
1335       krm_releaseLink( linkPtr );
1336       linkPtr = next_link_ptr;
1337 
1338       if (prevLinkPtr != NULL)	/*  current link isn't first link at the unit */
1339 	prevLinkPtr->next = next_link_ptr;  /*	chain previous link pointer
1340 						with next link pointer	*/
1341       else  /*	current link is the first link at the unit  */
1342 	sitePtr->links = next_link_ptr;
1343 
1344       NetModified = TRUE;
1345       return( KRERR_NO_ERROR );
1346    }
1347 
1348   KernelErrorCode = KRERR_PARAMETERS;
1349   return( KernelErrorCode );
1350 }
1351 
1352 
1353 /*****************************************************************************
1354   FUNCTION : kr_deleteAllLinks
1355 
1356   PURPOSE  : Deletes all input links at current unit/site
1357   NOTES    :
1358 
1359   RETURNS  : Returns the errorcode
1360   UPDATE   :
1361 ******************************************************************************/
kr_deleteAllLinks(int mode)1362 krui_err  kr_deleteAllLinks(int mode)
1363 {
1364   if (unitPtr == NULL)
1365     {  /*  no current unit  */
1366     KernelErrorCode = KRERR_NO_CURRENT_UNIT;
1367     return( KernelErrorCode );
1368   }
1369 
1370   linkPtr = NULL;
1371   NetModified = TRUE;
1372 
1373   switch (mode)
1374     {
1375     case  INPUTS:  /*  delete all inputs  */
1376       if UNIT_HAS_DIRECT_INPUTS( unitPtr )
1377 	{
1378 	krm_releaseAllLinks( (struct Link *) unitPtr->sites );
1379 	unitPtr->sites = NULL;
1380 	unitPtr->flags &= (~UFLAG_INPUT_PAT);  /*  unit don't has inputs now  */
1381 
1382 	return( KernelErrorCode );
1383       }
1384 
1385       if UNIT_HAS_SITES( unitPtr )
1386 	{
1387 	krm_releaseAllLinks( sitePtr->links );
1388 	sitePtr->links = NULL;	/*  site has no inputs now   */
1389 
1390 	return( KernelErrorCode );
1391       }
1392 
1393       return( KernelErrorCode );
1394 
1395     case  OUTPUTS:  /*	delete all outputs  */
1396       kr_deleteAllOutputLinks( unitPtr );
1397 
1398       return( KernelErrorCode );
1399   }
1400 
1401   KernelErrorCode = KRERR_PARAMETERS;
1402   return( KernelErrorCode );
1403 }
1404 
1405 
1406 
1407 
1408 
1409 
1410 
1411 
1412 /*#################################################
1413 
1414 GROUP: Low-Level Kernel Functions
1415 
1416 #################################################*/
1417 
1418 
1419 /*****************************************************************************
1420   FUNCTION : kr_deleteAllInputs
1421 
1422   PURPOSE  : delete all links and sites at the given unit
1423   NOTES    :
1424 
1425   RETURNS  :
1426   UPDATE   :
1427 ******************************************************************************/
kr_deleteAllInputs(struct Unit * unit_ptr)1428 void    kr_deleteAllInputs(struct Unit *unit_ptr)
1429 {
1430   register struct Site	*site_ptr;
1431 
1432 
1433   if (UNIT_HAS_SITES( unit_ptr ))
1434     {   /*  Unit has sites  */
1435     FOR_ALL_SITES( unit_ptr, site_ptr )
1436       /*  Release all links   */
1437       krm_releaseAllLinks( site_ptr->links );
1438 
1439     krm_releaseAllSites( unit_ptr->sites );
1440   }
1441   else
1442     {   /*  Unit don't has sites   */
1443     if (UNIT_HAS_DIRECT_INPUTS( unit_ptr ))
1444       krm_releaseAllLinks( (struct Link *) unit_ptr->sites );
1445   }
1446 
1447   unit_ptr->sites = NULL;
1448 
1449   /*  The unit has no inputs now  */
1450   unit_ptr->flags &= (~UFLAG_INPUT_PAT);
1451 }
1452 
1453 /*****************************************************************************
1454   FUNCTION : kr_deleteAllOutputLinks
1455 
1456   PURPOSE  : Deletes all output links at <source_unit>
1457   NOTES    : This function is slow
1458 
1459   RETURNS  :
1460   UPDATE   :
1461 ******************************************************************************/
kr_deleteAllOutputLinks(struct Unit * source_unit_ptr)1462 void  kr_deleteAllOutputLinks(struct Unit *source_unit_ptr)
1463 {
1464   register struct Link   *link_ptr,
1465                          *pred_link_ptr;
1466   register struct Site   *site_ptr;
1467   register struct Unit   *unit_ptr;
1468 
1469 
1470   FOR_ALL_UNITS( unit_ptr )
1471     if UNIT_IN_USE( unit_ptr )
1472       if UNIT_HAS_SITES( unit_ptr )
1473         {  /*  unit has sites  */
1474 	FOR_ALL_SITES( unit_ptr, site_ptr )
1475           for (link_ptr = site_ptr->links, pred_link_ptr = NULL;
1476                link_ptr != NULL;
1477                pred_link_ptr = link_ptr, link_ptr = link_ptr->next)
1478 
1479             if (link_ptr->to == source_unit_ptr)
1480               {     /*  Connection between unit and source_unit found   */
1481               if (pred_link_ptr == NULL)
1482                 site_ptr->links = link_ptr->next;
1483               else
1484                 pred_link_ptr->next = link_ptr->next;
1485 
1486               krm_releaseLink( link_ptr );
1487 
1488               break;    /*  next site/unit  */
1489 	    }
1490       }
1491       else  /*	unit has no sites   */
1492 	if UNIT_HAS_DIRECT_INPUTS( unit_ptr )
1493           for (link_ptr = (struct Link *) unit_ptr->sites, pred_link_ptr = NULL;
1494                link_ptr != NULL;
1495                pred_link_ptr = link_ptr, link_ptr = link_ptr->next)
1496             if (link_ptr->to == source_unit_ptr)
1497               {     /*  Connection between unit and source_unit found   */
1498               if (pred_link_ptr == NULL)
1499                 {
1500                 unit_ptr->sites = (struct Site *) link_ptr->next;
1501                 if (link_ptr->next == NULL)
1502                   /*  The unit has no inputs now  */
1503                   unit_ptr->flags &= (~UFLAG_INPUT_PAT);
1504 	      }
1505               else
1506                 pred_link_ptr->next = link_ptr->next;
1507 
1508               krm_releaseLink( link_ptr );
1509 
1510               break;    /*  next unit  */
1511 	    }
1512 }
1513 
1514 
1515 /*****************************************************************************
1516   FUNCTION : kr_copyOutputLinks
1517 
1518   PURPOSE  : Copies all output links at <source_unit> to <new_unit>.
1519   NOTES    : This function is slow
1520 
1521   RETURNS  : Returns error code if memory allocation fails.
1522   UPDATE   :
1523 ******************************************************************************/
kr_copyOutputLinks(struct Unit * source_unit_ptr,struct Unit * new_unit_ptr)1524 static krui_err  kr_copyOutputLinks(struct Unit *source_unit_ptr,
1525 				    struct Unit *new_unit_ptr)
1526 {
1527   register struct Link   *link_ptr,
1528 			 *new_link;
1529   register struct Site   *site_ptr;
1530   register struct Unit   *unit_ptr;
1531 
1532 
1533   KernelErrorCode = KRERR_NO_ERROR;
1534 
1535   FOR_ALL_UNITS( unit_ptr )
1536     if UNIT_IN_USE( unit_ptr )
1537       if UNIT_HAS_DIRECT_INPUTS( unit_ptr )
1538 	FOR_ALL_LINKS( unit_ptr, link_ptr )
1539 	  if (link_ptr->to == source_unit_ptr)
1540 	    {  /*  Connection between unit and source_unit found   */
1541 	    if ( (new_link = krm_getLink() ) == NULL)
1542 	      return( KernelErrorCode );
1543 
1544 	    memcpy( (char *) new_link, (char *) link_ptr, LINK_SIZE );
1545 	    new_link->next = (struct Link *) unit_ptr->sites;
1546 	    unit_ptr->sites = (struct Site *) new_link;
1547 
1548 	    new_link->to = new_unit_ptr;
1549 	    new_link->weight = link_ptr->weight;
1550 	    break;    /*  next unit  */
1551 	  }
1552       else
1553 	if UNIT_HAS_SITES( unit_ptr )
1554 	  FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
1555 	    if (link_ptr->to == source_unit_ptr)
1556 	      {  /*  Connection between unit and source_unit found   */
1557 	      if ( (new_link = krm_getLink() ) == NULL)
1558 		return( KernelErrorCode );
1559 
1560 	      new_link->next = site_ptr->links;
1561 	      site_ptr->links = new_link;
1562 
1563 	      new_link->to = new_unit_ptr;
1564 	      new_link->weight = link_ptr->weight;
1565 
1566 	      break;	/*  next site/unit  */
1567 	    }
1568   return( KernelErrorCode );
1569 }
1570 
1571 /*****************************************************************************
1572   FUNCTION : kr_copyInputLinks
1573 
1574   PURPOSE  : Copy all input links from <source_unit> to <new_unit>
1575   NOTES    :
1576 
1577   RETURNS  : Returns error code
1578   UPDATE   :
1579 ******************************************************************************/
kr_copyInputLinks(struct Unit * source_unit_ptr,struct Unit * new_unit_ptr)1580 static krui_err  kr_copyInputLinks(struct Unit *source_unit_ptr,
1581 				   struct Unit *new_unit_ptr)
1582 {
1583   register struct Link	 *link_ptr, *new_link,
1584 			 *last_link_ptr;
1585   register struct Site	 *source_site_ptr, *dest_site_ptr;
1586 
1587 
1588   KernelErrorCode = KRERR_NO_ERROR;
1589 
1590   if UNIT_HAS_DIRECT_INPUTS( source_unit_ptr )
1591     {
1592     last_link_ptr = new_link = NULL;
1593     FOR_ALL_LINKS( source_unit_ptr, link_ptr )
1594       {
1595       if ((new_link = krm_getLink()) == NULL)
1596 	{
1597 	new_unit_ptr->sites = (struct Site *) last_link_ptr;
1598 	return( KernelErrorCode );
1599       }
1600 
1601       memcpy( (char *) new_link, (char *) link_ptr, LINK_SIZE );
1602       new_link->next = last_link_ptr;
1603       last_link_ptr = new_link;
1604     }
1605 
1606     new_unit_ptr->sites = (struct Site *) new_link;
1607     new_unit_ptr->flags &= ~UFLAG_INPUT_PAT;
1608     if (new_link != NULL)  new_unit_ptr->flags |= UFLAG_DLINKS;
1609   }
1610   else
1611     if UNIT_HAS_SITES( source_unit_ptr )
1612       FOR_ALL_SITES( source_unit_ptr, source_site_ptr )
1613 	FOR_ALL_SITES( new_unit_ptr, dest_site_ptr )
1614 	  if (source_site_ptr->site_table == dest_site_ptr->site_table)
1615 	    {
1616 	    last_link_ptr = new_link = NULL;
1617 	    FOR_ALL_LINKS_AT_SITE( source_site_ptr, link_ptr )
1618 	      {
1619 	      if ((new_link = krm_getLink()) == NULL)
1620 		{
1621 		dest_site_ptr->links = last_link_ptr;
1622 		return( KernelErrorCode );
1623 	      }
1624 
1625 	      memcpy( (char *) new_link, (char *) link_ptr, LINK_SIZE );
1626 	      new_link->next = last_link_ptr;
1627 	      last_link_ptr = new_link;
1628 	      }
1629 
1630 	    dest_site_ptr->links = new_link;
1631 	  }
1632 
1633   return( KernelErrorCode );
1634 }
1635 
1636 
1637 
1638 
1639 /*#################################################
1640 
1641 GROUP: Site Name/Func functions
1642 
1643 #################################################*/
1644 
1645 /*****************************************************************************
1646   FUNCTION : kr_searchUnitSite
1647 
1648   PURPOSE  : search for a site at a unit
1649   NOTES    :
1650 
1651   RETURNS  : Returns the site or NULL
1652   UPDATE   :
1653 ******************************************************************************/
kr_searchUnitSite(struct Unit * unit_ptr,struct SiteTable * stbl_ptr)1654 struct Site *kr_searchUnitSite(struct Unit *unit_ptr,struct SiteTable *stbl_ptr)
1655 {
1656   register struct Site	*site_ptr;
1657 
1658   FOR_ALL_SITES( unit_ptr, site_ptr )
1659     if (site_ptr->site_table == stbl_ptr)
1660       return( site_ptr );
1661 
1662   return( NULL );   /*  there is no site at this unit with this name    */
1663 }
1664 
1665 
1666 /*****************************************************************************
1667   FUNCTION : kr_searchNetSite
1668 
1669   PURPOSE  : searches for a site in the network
1670   NOTES    :
1671 
1672   RETURNS  :
1673   UPDATE   :
1674 ******************************************************************************/
kr_searchNetSite(struct SiteTable * stbl_ptr)1675 int  kr_searchNetSite(struct SiteTable *stbl_ptr)
1676 {
1677   register struct Site   *site_ptr;
1678   register struct Unit   *unit_ptr;
1679 
1680 
1681   if (NoOfUnits == 0)
1682     return( 0 ); /*  no units -> no sites */
1683 
1684   FOR_ALL_UNITS( unit_ptr )
1685     if (UNIT_HAS_SITES( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
1686       {  /*  unit has sites and is in use  */
1687       FOR_ALL_SITES( unit_ptr, site_ptr )
1688         if (site_ptr->site_table == stbl_ptr)
1689           return( unit_ptr - unit_array );  /*  return unit no. */
1690     }
1691 
1692   return( 0 );  /*  site isn't in use   */
1693 }
1694 
1695 
1696 /*#################################################
1697 
1698 GROUP: Link Functions
1699 
1700 #################################################*/
1701 /*****************************************************************************
1702   FUNCTION : kr_jogWeights
1703 
1704   PURPOSE  : Add random uniform distributed values to connection weights.
1705              <minus> must be less then <plus>.
1706              New:
1707              Value and range depends on the given parameters and the current
1708              weight. e.g.:
1709              -0.02, 0.04 means that the new weight will be in the range of
1710              100-2% to 100+4% = 98% to 104% of its previous value.
1711 
1712   NOTES    : The old way of just adding noise may be achieved by defining
1713              -DJOGWEIGHTS_BY_ADDING during compilation
1714 
1715   RETURNS  :
1716   UPDATE   :
1717 ******************************************************************************/
kr_jogWeights(FlintTypeParam minus,FlintTypeParam plus)1718 void  kr_jogWeights(FlintTypeParam minus, FlintTypeParam plus)
1719 {
1720   register  struct Link   *link_ptr;
1721   FlagWord	flags;
1722   struct Unit   *unit_ptr;
1723   struct Site   *site_ptr;
1724   register FlintType  range, min;
1725 
1726 
1727   if (NoOfUnits == 0)  return;  /*  no. units  */
1728   range = plus - minus;
1729   min = minus;
1730 
1731   FOR_ALL_UNITS( unit_ptr )  {
1732     flags = unit_ptr->flags;
1733 
1734       if(((flags & UFLAG_IN_USE) == UFLAG_IN_USE)
1735 	  && !IS_SPECIAL_UNIT(unit_ptr))
1736       /*  unit is in use  */
1737       if (flags & UFLAG_DLINKS)
1738 	/*  unit has direct links   */
1739 	FOR_ALL_LINKS( unit_ptr, link_ptr )
1740 #ifdef JOGWEIGHTS_BY_ADDING
1741           link_ptr->weight += (FlintType) drand48() * range + min;
1742 #else
1743           link_ptr->weight += link_ptr->weight * ((FlintType) drand48() * range + min);
1744 
1745 #endif
1746 	  else
1747 	if (flags & UFLAG_SITES)
1748 	  /*  unit has sites  */
1749 	  FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
1750 #ifdef JOGWEIGHTS_BY_ADDING
1751             link_ptr->weight += (FlintType) drand48() * range + min;
1752 #else
1753             link_ptr->weight += link_ptr->weight * ((FlintType) drand48() * range + min);
1754 #endif
1755   }
1756 }
1757 
1758 /*****************************************************************************
1759 
1760   GROUP: correlation
1761 
1762 ******************************************************************************/
1763 
1764 
1765 /*****************************************************************************
1766   FUNCTION : kr_getCorrelatedHiddens
1767   PURPOSE  : calculate correlation coefficients between all non-special
1768              hidden units, determine the two hidden units with maximum
1769 	     correlation, return the pointers to these units and their
1770 	     correlation coefficient.
1771 	     If no such units exist return NULL pointers instead of unit
1772 	     pointers.
1773 
1774 	     calculate correlation coefficients between all non-special
1775              hidden units of the current network over all pattern.
1776              Store these values into the
1777 	     kr_CorrMatrix in the following way:
1778 
1779 	     for all non-special hidden units c and r
1780              (c, r = unit_array indexed from first hidden unit)
1781 	     with r > c
1782 	     kr_CorrMatrix[row=r][column=c] =
1783 	         correlation coefficient between these two units, based on
1784 		 unit output values for all patterns of the current pattern set.
1785 
1786 	     Note that the following values are not set since they are obsolete:
1787 	     kr_CorrMatrix[row=n][column=n] == 1
1788 	     kr_CorrMatrix[row=c][column=r] == kr_CorrMatrix[row=r][column=c]
1789 
1790   NOTES    : mean in value_b, stddev in value_c
1791   RETURNS  : kernel error code
1792 ******************************************************************************/
1793 
kr_getCorrelatedHiddens(struct Unit ** hn1,struct Unit ** hn2,double * res_corr)1794 static krui_err kr_getCorrelatedHiddens(struct Unit **hn1, struct Unit **hn2,
1795 					double *res_corr)
1796 {
1797     static RbfFloatMatrix kr_CorrMatrix = {0, 0, NULL, NULL};
1798 
1799     int no_of_layers;
1800 
1801     struct Unit *unit_ptr;
1802     struct Unit *unit_ptr2;
1803     struct Unit *first_hidden;
1804     int pattern_no, sub_pat_no, no_of_patterns;
1805     int MyNoOfHidden;
1806     int col, row;
1807     double covadd;
1808     double corr;
1809     double mincorr, maxcorr;
1810     int mincorrcol, mincorrrow;
1811     int maxcorrcol, maxcorrrow;
1812 
1813     if (NetModified || (TopoSortID != TOPOLOGICAL_FF)) {
1814 	/* Net has been modified or topologic array isn't initialized */
1815 	/* check the topology of the network  */
1816 	no_of_layers = kr_topoCheck();
1817 	if (KernelErrorCode != KRERR_NO_ERROR)
1818 	    /* an error has occured	 */
1819 	    return (KernelErrorCode);
1820 
1821 	if (no_of_layers < 2) {	/* the network has less then 2 layers  */
1822 	    KernelErrorCode = KRERR_FEW_LAYERS;
1823 	    return (KernelErrorCode);
1824 	}
1825 	/* count the no. of I/O units and check the patterns  */
1826 	if (kr_IOCheck() != KRERR_NO_ERROR)
1827 	    return (KernelErrorCode);
1828 
1829 	/* sort units by topology and by topologic type  */
1830 	(void) kr_topoSort(TOPOLOGICAL_FF);
1831 	if ((KernelErrorCode != KRERR_NO_ERROR) &&
1832 	    (KernelErrorCode != KRERR_DEAD_UNITS))
1833 	    return (KernelErrorCode);
1834 
1835 	NetModified = FALSE;
1836     }
1837 
1838     /* initialize value_b and value_c of each unit */
1839     MyNoOfHidden = 0;
1840     first_hidden = NULL;
1841     FOR_ALL_UNITS (unit_ptr)
1842 	if (IS_HIDDEN_UNIT (unit_ptr))
1843 	{
1844 	    MyNoOfHidden++;
1845 	    if (!first_hidden)
1846 		first_hidden = unit_ptr;
1847 	    if (! IS_SPECIAL_UNIT (unit_ptr))
1848 	    {
1849 		unit_ptr->value_b = 0;
1850 		unit_ptr->value_c = 0;
1851 	    }
1852 	}
1853 
1854     /* allocate space for new correlation matrix if necessary: */
1855     if (kr_CorrMatrix.rows < MyNoOfHidden ||
1856 	kr_CorrMatrix.columns < MyNoOfHidden)
1857     {
1858 	if (kr_CorrMatrix.field != NULL)
1859 	    RbfFreeMatrix(&kr_CorrMatrix);
1860 
1861 	if (!RbfAllocMatrix(MyNoOfHidden, MyNoOfHidden, &kr_CorrMatrix))
1862 	{
1863 	    KernelErrorCode = KRERR_INSUFFICIENT_MEM;
1864 	    return KernelErrorCode;
1865 	}
1866     }
1867 
1868     /* reset correlation matrix */
1869     RbfClearMatrix(&kr_CorrMatrix, 0.0);
1870 
1871     /* compute the necessary sub patterns (allways work on all patterns) */
1872     KernelErrorCode =
1873 	kr_initSubPatternOrder(0, kr_np_pattern(PATTERN_GET_NUMBER, 0, 0) - 1);
1874     if (KernelErrorCode != KRERR_NO_ERROR)
1875     {
1876 	if (KernelErrorCode == KRERR_NP_NO_TRAIN_SCHEME)
1877 	    KernelErrorCode = KRERR_NP_WORKAROUND;
1878 	return (KernelErrorCode);
1879     }
1880 
1881     /* calculate total number of subpatterns */
1882     no_of_patterns = 0;
1883 
1884     /* calculate the following values:
1885        sum(x)   -> value_b
1886        sum(x^2) -> value_c
1887        sum(x*y) -> matrix[col for x][row for y]
1888 
1889        x and y are output values of arbitraty hidden units
1890      */
1891     while (kr_getSubPatternByOrder (&pattern_no, &sub_pat_no)) {
1892         /* propagate pattern through net */
1893         propagateNetForward (pattern_no, sub_pat_no);
1894 	no_of_patterns++;
1895 
1896         /* calculate mean for all units */
1897         FOR_ALL_UNITS (unit_ptr)
1898             if (! IS_SPECIAL_UNIT (unit_ptr) && IS_HIDDEN_UNIT (unit_ptr))
1899 	    {
1900 		/* sum up x and x^2 */
1901                 unit_ptr->value_b += unit_ptr->Out.output;
1902 		unit_ptr->value_c += unit_ptr->Out.output * unit_ptr->Out.output;
1903 
1904 		col = unit_ptr - first_hidden;
1905 
1906 		/* sum up x*y */
1907 		FOR_ALL_UNITS (unit_ptr2)
1908 		    if (! IS_SPECIAL_UNIT (unit_ptr2)
1909 			&& IS_HIDDEN_UNIT (unit_ptr2)
1910 			&& unit_ptr2 > unit_ptr)
1911 		    {
1912 			row = unit_ptr2 - first_hidden;
1913 			covadd = (unit_ptr->Out.output * unit_ptr2->Out.output);
1914 			RbfMatrixSetValue(&kr_CorrMatrix, row, col,
1915 			    RbfMatrixGetValue(&kr_CorrMatrix, row, col) + covadd);
1916 		    }
1917 	    }
1918     }
1919 
1920     /* now finish computation of correlation matrix. compute:
1921 
1922        matrix[col for x][row for y] =
1923        (n * sum(x*y) - sum(x) * sum(y))   /
1924        sqrt((n * sum(x^2) - sum^2(x)) * (n * sum(y^2) - sum^2(y)))
1925 
1926        also find minimum and maximum correlation (hint: 0 means not correlated,
1927        1.0 means correlated -1.0 means anti-correlated
1928     */
1929     mincorr = maxcorr = 0.0;
1930     FOR_ALL_UNITS (unit_ptr)
1931         if (! IS_SPECIAL_UNIT (unit_ptr) && IS_HIDDEN_UNIT (unit_ptr))
1932 	{
1933 	    col = unit_ptr - first_hidden;
1934 
1935 	    FOR_ALL_UNITS (unit_ptr2)
1936 		if (! IS_SPECIAL_UNIT (unit_ptr2)
1937 		    && IS_HIDDEN_UNIT (unit_ptr2)
1938 		    && unit_ptr2 > unit_ptr)
1939 		{
1940 		    row = unit_ptr2 - first_hidden;
1941 		    corr = no_of_patterns * RbfMatrixGetValue(&kr_CorrMatrix, row, col)
1942 			- unit_ptr->value_b * unit_ptr2->value_b;
1943 		    corr /= sqrt(
1944 			(no_of_patterns * unit_ptr->value_c
1945 			 - unit_ptr->value_b * unit_ptr->value_b)
1946 			*(no_of_patterns * unit_ptr2->value_c
1947 			  - unit_ptr2->value_b * unit_ptr2->value_b)
1948 			);
1949 		    RbfMatrixSetValue(&kr_CorrMatrix, row, col, corr);
1950 
1951 		    if (corr > maxcorr)
1952 		    {
1953 			maxcorr = corr;
1954 			maxcorrcol = col;
1955 			maxcorrrow = row;
1956 		    }
1957 		    if (corr < mincorr)
1958 		    {
1959 			mincorr = corr;
1960 			mincorrcol = col;
1961 			mincorrrow = row;
1962 		    }
1963 		}
1964 	}
1965 
1966 #ifdef CORR_DEBUG
1967     RbfPrintMatrix(&kr_CorrMatrix, stderr);
1968 #endif
1969 
1970     if (-mincorr > maxcorr && -mincorr > 0.0)
1971     {
1972 	*res_corr = -mincorr;
1973 	*hn1 = first_hidden + mincorrcol;
1974 	*hn2 = first_hidden + mincorrrow;
1975     }
1976     else if (maxcorr > -mincorr && maxcorr > 0.0)
1977     {
1978 	*res_corr = maxcorr;
1979 	*hn1 = first_hidden + maxcorrcol;
1980 	*hn2 = first_hidden + maxcorrrow;
1981     }
1982     else
1983     {
1984 	*res_corr = 0.0;
1985 	*hn1 = *hn2 = NULL;
1986     }
1987 
1988     return (KRERR_NO_ERROR);
1989 }
1990 
1991 
1992 /*****************************************************************************
1993   FUNCTION : kr_jogCorrWeights
1994 
1995   PURPOSE  : Add uniform distributed random values to connection weights of
1996              highly correlated, non-special hidden units.
1997              <minus> must be less then <plus>.
1998 	     The two hidden units with maximum positive or negative correlation
1999 	     with an absolute value higher then mincorr are searched. The
2000 	     incoming weights of one of these units are jogged.
2001 
2002              New:
2003              Value and range depends on the given parameters and the current
2004              weight. e.g.:
2005              -0.02, 0.04 means that the new weight will be in the range of
2006              100-2% to 100+4% = 98% to 104% of its previous value.
2007 
2008   NOTES    : The old way of just adding noise may be achieved by defining
2009              -DJOGWEIGHTS_BY_ADDING during compilation
2010 
2011   RETURNS  : error code
2012   UPDATE   :
2013 ******************************************************************************/
kr_jogCorrWeights(FlintTypeParam minus,FlintTypeParam plus,FlintTypeParam mincorr)2014 krui_err  kr_jogCorrWeights(FlintTypeParam minus, FlintTypeParam plus,
2015 			    FlintTypeParam mincorr)
2016 {
2017     register  struct Link   *link_ptr;
2018     FlagWord	flags;
2019     struct Unit   *unit_ptr = NULL;
2020     struct Unit   *unit_ptr1 = NULL;
2021     struct Unit   *unit_ptr2 = NULL;
2022     double         correlation;
2023     struct Site   *site_ptr;
2024     register FlintType  range, min;
2025     double maxweight;
2026 
2027     if (NoOfUnits == 0)  return KRERR_NO_UNITS;  /*  no. units  */
2028     range = plus - minus;
2029     min = minus;
2030 
2031     KernelErrorCode = KRERR_NO_ERROR;
2032     if (kr_getCorrelatedHiddens(&unit_ptr1, &unit_ptr2, &correlation)
2033 	!= KRERR_NO_ERROR)
2034 	return KernelErrorCode;
2035 
2036     if (unit_ptr1 == NULL || unit_ptr2 == NULL || fabs(correlation) < mincorr)
2037 	return KRERR_NO_ERROR;
2038 
2039     unit_ptr = drand48() > 0.5 ? unit_ptr2 : unit_ptr1;
2040 
2041 #ifdef CORR_DEBUG
2042     printf("maximum correlation is %g between %s and %s, jogging %s\n",
2043 	   correlation,
2044 	   unit_ptr1->unit_name == NULL ? "noname" : unit_ptr1->unit_name,
2045 	   unit_ptr2->unit_name == NULL ? "noname" : unit_ptr2->unit_name,
2046 	   unit_ptr->unit_name == NULL ? "noname" : unit_ptr->unit_name);
2047 #endif
2048 
2049     flags = unit_ptr->flags;
2050 
2051     if(((flags & UFLAG_IN_USE) == UFLAG_IN_USE)
2052        && !IS_SPECIAL_UNIT(unit_ptr))
2053 	/*  unit is in use  */
2054 	if (flags & UFLAG_DLINKS)
2055 	{
2056 	    /*  unit has direct links   */
2057 	    maxweight = 0.0;
2058 	    FOR_ALL_LINKS( unit_ptr, link_ptr )
2059 	    {
2060 		if (fabs(link_ptr->weight) > maxweight)
2061 		    maxweight = fabs(link_ptr->weight);
2062 	    }
2063 	    if (maxweight > 1.0)
2064 		maxweight = 1.0;
2065 	    FOR_ALL_LINKS( unit_ptr, link_ptr )
2066                 link_ptr->weight +=
2067 		    maxweight * ((FlintType) drand48() * range + min);
2068 	}
2069 	else
2070 	{
2071 	    if (flags & UFLAG_SITES)
2072 		/*  unit has sites  */
2073 		FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
2074 #ifdef JOGWEIGHTS_BY_ADDING
2075 		    link_ptr->weight += (FlintType) drand48() * range + min;
2076 #else
2077                     link_ptr->weight +=
2078 			link_ptr->weight * ((FlintType) drand48() * range + min);
2079 #endif
2080 	}
2081 
2082     return KRERR_NO_ERROR;
2083 }
2084 
2085 
2086 
2087 /*#################################################
2088 
2089 GROUP: Site Functions
2090 
2091 #################################################*/
2092 /*****************************************************************************
2093   FUNCTION : kr_createDefaultSite
2094 
2095   PURPOSE  : Creates a new site with default initialisation
2096   NOTES    :
2097 
2098   RETURNS  : the new site
2099   UPDATE   :
2100 ******************************************************************************/
kr_createDefaultSite(void)2101 struct Site  *kr_createDefaultSite(void)
2102 {
2103   struct Site   *site_ptr;
2104 
2105 
2106   if ( (site_ptr = krm_getSite() ) == NULL)   return( NULL );
2107 
2108   site_ptr->links = NULL;
2109   site_ptr->next  = NULL;
2110 
2111   return( site_ptr );
2112 }
2113 
2114 
2115 
2116 /*#################################################
2117 
2118 GROUP: Unit Functions
2119 
2120 #################################################*/
2121 
2122 
2123 /*****************************************************************************
2124   FUNCTION : kr_unitNameSearch
2125 
2126   PURPOSE  : Searches for a unit with the given symbol pointer.
2127   NOTES    :
2128 
2129   RETURNS  : Returns the first unit no. if a unit with the given name was found,
2130              0 otherwise
2131 
2132   UPDATE   :
2133 ******************************************************************************/
kr_unitNameSearch(int min_unit_no,char * unit_symbol_ptr)2134 int  kr_unitNameSearch(int min_unit_no, char *unit_symbol_ptr)
2135 {
2136   register char   *symbol;
2137   register struct Unit   *unit_ptr;
2138 
2139 
2140   if ((symbol = unit_symbol_ptr) == NULL)
2141     return( 0 );
2142 
2143   /*  search for symbol pointer  */
2144   for (unit_ptr = unit_array + min_unit_no; unit_ptr <= unit_array + MaxUnitNo; unit_ptr++)
2145     if UNIT_IN_USE( unit_ptr )
2146       if (unit_ptr->unit_name == symbol)
2147         return( unit_ptr - unit_array );
2148 
2149   return( 0 );
2150 }
2151 
2152 /*****************************************************************************
2153   FUNCTION : kr_copyUnitFrame
2154 
2155   PURPOSE  : copy the source unit with sites, but no links
2156   NOTES    :
2157 
2158   RETURNS  : Returns the error code
2159   UPDATE   :
2160 ******************************************************************************/
kr_copyUnitFrame(struct Unit * source_unit_ptr,struct Unit * new_unit_ptr)2161 static krui_err kr_copyUnitFrame(struct Unit *source_unit_ptr,
2162 				 struct Unit *new_unit_ptr)
2163 {
2164   struct Site	*site_ptr,
2165 		*new_site_ptr,
2166 		*last_site_ptr;
2167 
2168 
2169   KernelErrorCode = KRERR_NO_ERROR;
2170 
2171   memcpy( (char *) new_unit_ptr, (char *) source_unit_ptr, UNIT_SIZE );
2172 
2173   if (source_unit_ptr->unit_name != NULL)
2174     (void) krm_NTableInsertSymbol( source_unit_ptr->unit_name, UNIT_SYM );
2175 
2176   /*  unit has no inputs now  */
2177   new_unit_ptr->flags &= ~UFLAG_INPUT_PAT;
2178   new_unit_ptr->sites = NULL;
2179 
2180   if UNIT_HAS_SITES( source_unit_ptr )
2181     {  /*  Copy all sites, but no links.  */
2182     last_site_ptr = new_site_ptr = NULL;
2183     FOR_ALL_SITES( source_unit_ptr, site_ptr )  {
2184       if ((new_site_ptr = krm_getSite()) == NULL)  {
2185 	new_unit_ptr->sites = last_site_ptr;
2186 	return( KernelErrorCode );
2187       }
2188 
2189       memcpy( (char *) new_site_ptr, (char *) site_ptr, SITE_SIZE );
2190       new_site_ptr->links = NULL;
2191       new_site_ptr->next = last_site_ptr;
2192       last_site_ptr = new_site_ptr;
2193     }
2194 
2195     new_unit_ptr->sites = new_site_ptr;
2196     if (new_site_ptr != NULL)  new_unit_ptr->flags |= UFLAG_SITES;
2197   }
2198 
2199   return( KernelErrorCode );
2200 }
2201 
2202 /*****************************************************************************
2203   FUNCTION : kr_removeUnit
2204 
2205   PURPOSE  : Remove unit and all links from network
2206   NOTES    :
2207 
2208   RETURNS  : Returns the error code
2209   UPDATE   :
2210 ******************************************************************************/
kr_removeUnit(struct Unit * unit_ptr)2211 krui_err  kr_removeUnit(struct Unit *unit_ptr)
2212 {
2213 
2214   /*  delete inputs   */
2215   kr_deleteAllInputs( unit_ptr );
2216   /*  delete output links */
2217   kr_deleteAllOutputLinks( unit_ptr );
2218   /*  check references to the unit symbol   */
2219   krm_NTableReleaseSymbol( unit_ptr->unit_name, UNIT_SYM );
2220   /*  count units  */
2221   kr_countUnits( unit_ptr, UNIT_DELETE );
2222   /*  delete Unit */
2223   krm_releaseUnit( unit_ptr - unit_array );
2224 
2225   return( KernelErrorCode );
2226 }
2227 
2228 
2229 /*****************************************************************************
2230   FUNCTION : kr_copyUnit
2231 
2232   PURPOSE  : Copy a given unit, according to the copy mode
2233              1. copy unit (with it sites, if available) and input/output links
2234              2. copy unit (with it sites, if available) and input links
2235              3. copy unit (with it sites, if available) and output links
2236              4. copy unit (with it sites, if available) but no links
2237 	     Function has no effect on the current unit.
2238   NOTES    : Copying of output links is slow.
2239              If return code < 0, an error occured.
2240 
2241   RETURNS  : Returns the unit number of the new unit or error message < 0 ,
2242              if errors occured.
2243   UPDATE   :
2244 ******************************************************************************/
kr_copyUnit(int copy_mode,int source_unit)2245 krui_err  kr_copyUnit(int copy_mode, int source_unit)
2246 {
2247   struct Unit	*source_unit_ptr,
2248 		*new_unit_ptr;
2249   int  new_unit_no;
2250 
2251 
2252   KernelErrorCode = KRERR_NO_ERROR;
2253 
2254   if ((source_unit_ptr = kr_getUnitPtr( source_unit )) == NULL)
2255     return( KernelErrorCode );
2256   if ((new_unit_no = krm_getUnit()) == 0)
2257     return( KernelErrorCode );
2258   if (new_unit_no != abs(new_unit_no)){
2259       /* new unit block allocated; need to update unit pointer */
2260       new_unit_no = abs(new_unit_no);
2261       source_unit_ptr = kr_getUnitPtr( source_unit );
2262   }
2263 
2264   new_unit_ptr = unit_array + new_unit_no;
2265 
2266   /*  copy unit (with it sites, if available) but no input/output links  */
2267   if (kr_copyUnitFrame( source_unit_ptr, new_unit_ptr ) != KRERR_NO_ERROR)
2268     return( KernelErrorCode );
2269 
2270   switch (copy_mode)
2271     {
2272     case ONLY_UNIT:
2273       break;
2274 
2275     case ONLY_INPUTS:
2276     /*	copy unit (with it sites, if available) and input links */
2277       (void) kr_copyInputLinks( source_unit_ptr, new_unit_ptr );
2278       break;
2279 
2280     case ONLY_OUTPUTS:
2281     /*  copy unit (with it sites, if available) and output links    */
2282       (void) kr_copyOutputLinks( source_unit_ptr, new_unit_ptr);
2283       break;
2284 
2285     case INPUTS_AND_OUTPUTS:
2286     /*  copy unit (with it sites, if available) and input/output links  */
2287       if (kr_copyOutputLinks( source_unit_ptr, new_unit_ptr) != KRERR_NO_ERROR)
2288 	break;
2289 
2290       (void) kr_copyInputLinks( source_unit_ptr, new_unit_ptr );
2291       break;
2292 
2293     default:
2294       KernelErrorCode = KRERR_COPYMODE;
2295   }
2296 
2297   if (KernelErrorCode != KRERR_NO_ERROR)
2298     {
2299     kr_removeUnit( new_unit_ptr );  /*	delete Unit  */
2300     return( KernelErrorCode );
2301   }
2302   else
2303     {  /*  Successful copy   */
2304     new_unit_ptr->flags = source_unit_ptr->flags;  /*  copy flags  */
2305     /*  count units  */
2306     kr_countUnits( new_unit_ptr, UNIT_ADD );
2307     NetModified = TRUE;
2308     return( new_unit_no );
2309   }
2310 }
2311 
2312 /*#################################################
2313 
2314 GROUP: Ftype Unit Functions
2315 
2316 #################################################*/
2317 /*****************************************************************************
2318   FUNCTION : kr_changeFtypeUnits
2319 
2320   PURPOSE  : changes all units in the network with the given functionality type
2321              to the new functions of the (new) functionality type
2322   NOTES    :
2323 
2324   RETURNS  :
2325   UPDATE   :
2326 ******************************************************************************/
kr_changeFtypeUnits(struct FtypeUnitStruct * Ftype_entry)2327 void   kr_changeFtypeUnits(struct FtypeUnitStruct *Ftype_entry)
2328 {
2329   register struct Unit   *unit_ptr;
2330 
2331 
2332   if (NoOfUnits == 0)  return;  /*  no units  */
2333 
2334   FOR_ALL_UNITS( unit_ptr )
2335     if UNIT_IN_USE( unit_ptr )
2336       {     /*  unit is in use  */
2337       if (unit_ptr->Ftype_entry == Ftype_entry)
2338 	{  /*  unit with this type was found. Now change the transfer functions
2339 	       of the unit to the modified functionality type */
2340         unit_ptr->act_func = Ftype_entry->act_func;
2341         unit_ptr->out_func = Ftype_entry->out_func;
2342         unit_ptr->act_deriv_func = Ftype_entry->act_deriv_func;
2343         unit_ptr->act_2_deriv_func = Ftype_entry->act_2_deriv_func;
2344         unit_ptr->python_act_func = Ftype_entry->python_act_func;
2345         unit_ptr->python_out_func = Ftype_entry->python_out_func;
2346         unit_ptr->python_act_deriv_func = Ftype_entry->python_act_deriv_func;
2347         unit_ptr->python_act_2_deriv_func = Ftype_entry->python_act_2_deriv_func;
2348         }
2349       }
2350 
2351   NetModified = TRUE;
2352 }
2353 
2354 /*****************************************************************************
2355   FUNCTION : kr_deleteUnitsFtype
2356 
2357   PURPOSE  : delete the functionality type of the units with the given type
2358   NOTES    :
2359 
2360   RETURNS  :
2361   UPDATE   :
2362 ******************************************************************************/
kr_deleteUnitsFtype(struct FtypeUnitStruct * ftype_ptr)2363 void  kr_deleteUnitsFtype(struct FtypeUnitStruct *ftype_ptr)
2364 {
2365   register struct Unit   *unit_ptr;
2366 
2367 
2368   if (NoOfUnits == 0)  return;  /*  no units  */
2369 
2370   FOR_ALL_UNITS( unit_ptr )
2371     if UNIT_IN_USE( unit_ptr )
2372       /*  unit is in use  */
2373       if (unit_ptr->Ftype_entry == ftype_ptr)
2374         unit_ptr->Ftype_entry = NULL;
2375 }
2376 
2377 /*****************************************************************************
2378   FUNCTION : kr_makeFtypeUnit
2379 
2380   PURPOSE  : create a new unit with the given functionality type
2381   NOTES    :
2382 
2383   RETURNS  :
2384   UPDATE   :
2385 ******************************************************************************/
kr_makeFtypeUnit(char * Ftype_symbol)2386 int  kr_makeFtypeUnit(char *Ftype_symbol)
2387 {
2388   register struct Site	*ftype_site, *site_ptr;
2389   struct Unit  *unit_ptr;
2390   struct FtypeUnitStruct  *ftype_ptr;
2391   int  unit_no;
2392 
2393 
2394   KernelErrorCode = KRERR_NO_ERROR;
2395 
2396   if (!kr_symbolCheck( Ftype_symbol ))
2397     return( KernelErrorCode );
2398 
2399   if ((ftype_ptr = krm_FtypeSymbolSearch( Ftype_symbol ) ) == NULL)
2400     {  /*  Ftype name isn't defined    */
2401     KernelErrorCode = KRERR_FTYPE_SYMBOL;
2402     return( KernelErrorCode );
2403   }
2404 
2405   unit_no = kr_makeDefaultUnit();
2406   if (KernelErrorCode != KRERR_NO_ERROR)
2407     return( KernelErrorCode );
2408 
2409   unit_ptr = unit_array + unit_no;
2410 
2411   unit_ptr->Ftype_entry = ftype_ptr;
2412   unit_ptr->out_func    = ftype_ptr->out_func;
2413   unit_ptr->act_func    = ftype_ptr->act_func;
2414   unit_ptr->act_deriv_func = ftype_ptr->act_deriv_func;
2415   unit_ptr->act_2_deriv_func = ftype_ptr->act_2_deriv_func;
2416   unit_ptr->python_out_func    = ftype_ptr->python_out_func;
2417   unit_ptr->python_act_func    = ftype_ptr->python_act_func;
2418   unit_ptr->python_act_deriv_func = ftype_ptr->python_act_deriv_func;
2419   unit_ptr->python_act_2_deriv_func = ftype_ptr->python_act_2_deriv_func;
2420 
2421   ftype_site = ftype_ptr->sites;
2422 
2423   /*  make sites  */
2424   while (ftype_site != NULL)
2425     {   /*  Ftype has sites */
2426     if ((site_ptr = krm_getSite()) == NULL)
2427       {  /*  memory alloc failed */
2428       krm_releaseAllSites( unit_ptr->sites );
2429       unit_ptr->sites = NULL;
2430       KernelErrorCode = KRERR_INSUFFICIENT_MEM;
2431       return( KernelErrorCode );
2432     }
2433 
2434     site_ptr->next = unit_ptr->sites;
2435     unit_ptr->sites = site_ptr;
2436 
2437     site_ptr->site_table = ftype_site->site_table;
2438     ftype_site = ftype_site->next;
2439   }
2440 
2441   if (ftype_ptr->sites != NULL)
2442     unit_ptr->flags |= UFLAG_SITES;     /*  unit has now sites  */
2443 
2444   return( unit_no );
2445 }
2446 
2447 /*****************************************************************************
2448   FUNCTION : kr_FtypeSiteSearch
2449 
2450   PURPOSE  :
2451   NOTES    :
2452 
2453   RETURNS  : returns TRUE, if there exists the given site at the given ftype
2454              entry
2455   UPDATE   :
2456 ******************************************************************************/
kr_FtypeSiteSearch(struct Site * ftype_first_site,struct SiteTable * site_table_ptr)2457 bool  kr_FtypeSiteSearch(struct Site *ftype_first_site,
2458 			 struct SiteTable *site_table_ptr)
2459 {
2460   register struct  Site      *site_ptr;
2461 
2462 
2463   for (site_ptr = ftype_first_site; site_ptr != NULL; site_ptr = site_ptr->next)
2464     if (site_ptr->site_table == site_table_ptr)
2465       return( TRUE );
2466 
2467   return( FALSE );
2468 }
2469 
2470 /*****************************************************************************
2471   FUNCTION : kr_changeFtypeUnit
2472 
2473   PURPOSE  : change the properties of the given unit to the properties of the
2474              given F-Type
2475   NOTES    :
2476 
2477   RETURNS  :
2478   UPDATE   :
2479 ******************************************************************************/
kr_changeFtypeUnit(struct Unit * unit_ptr,struct FtypeUnitStruct * ftype_ptr)2480 void    kr_changeFtypeUnit(struct Unit *unit_ptr,
2481 			   struct FtypeUnitStruct *ftype_ptr)
2482 {
2483   FlagWord	flags;
2484   struct  Site  *site_ptr,
2485                 *pred_site_ptr,
2486                 *tmp_ptr,
2487                 *ftype_site;
2488 
2489 
2490   unit_ptr->out_func = ftype_ptr->out_func;
2491   unit_ptr->act_func = ftype_ptr->act_func;
2492   unit_ptr->act_deriv_func = ftype_ptr->act_deriv_func;
2493   unit_ptr->act_2_deriv_func = ftype_ptr->act_2_deriv_func;
2494   unit_ptr->python_out_func = ftype_ptr->python_out_func;
2495   unit_ptr->python_act_func = ftype_ptr->python_act_func;
2496   unit_ptr->python_act_deriv_func = ftype_ptr->python_act_deriv_func;
2497   unit_ptr->python_act_2_deriv_func = ftype_ptr->python_act_2_deriv_func;
2498 
2499 
2500   flags = unit_ptr->flags & UFLAG_INPUT_PAT;
2501 
2502   switch (flags)
2503     {
2504     case  UFLAG_NO_INP:
2505       /*  Unit has no inputs  */
2506       if (ftype_ptr->sites != NULL)
2507         /*    Ftype has sites, delete unit's Ftype  */
2508         unit_ptr->Ftype_entry = NULL;
2509       else
2510         /*    Ftype and unit don't have sites */
2511         unit_ptr->Ftype_entry = ftype_ptr;    /* unit accept Ftype and inputs */
2512 
2513       return;     /*  done !  */
2514 
2515     case  UFLAG_SITES:
2516       /*  Unit has sites  */
2517       ftype_site = ftype_ptr->sites;
2518       if (ftype_site == NULL)
2519         {  /* unit has sites, but Ftype hasn't sites,
2520 	      delete unit's Ftype and all inputs  */
2521         unit_ptr->Ftype_entry = NULL;
2522 
2523         kr_deleteAllInputs( unit_ptr );
2524         unit_ptr->flags = UFLAG_INITIALIZED;  /*  unit has no inputs now !    */
2525         }
2526       else
2527         {     /*  both unit and Ftype have sites: check sites  */
2528         unit_ptr->Ftype_entry = ftype_ptr;
2529 
2530         site_ptr = unit_ptr->sites;
2531         pred_site_ptr = NULL;
2532 
2533         do
2534           {
2535           if ( ! kr_FtypeSiteSearch( ftype_site, site_ptr->site_table ))
2536             {  /*  Ftype and unit site definitions are not equivalent:
2537 		   remove site    */
2538             if (pred_site_ptr == NULL)
2539               {   /*  this is the first site at the unit  */
2540               unit_ptr->sites = site_ptr->next;
2541 
2542               if (site_ptr->next == NULL)
2543                 /*  unit don't has any inputs   */
2544                 unit_ptr->flags &= (~UFLAG_INPUT_PAT);
2545               }
2546             else
2547               {   /*  this site isn't the first site at the unit  */
2548               pred_site_ptr->next = site_ptr->next;
2549               pred_site_ptr = site_ptr;
2550               }
2551 
2552 	    /*  work with temporary pointer and get */
2553             tmp_ptr = site_ptr;
2554 
2555 	    /*  next site pointer BEFORE krm_releaseSite    */
2556             site_ptr = site_ptr->next;
2557 
2558 	    /*  (important in a multiprocessor system   */
2559             krm_releaseAllLinks( tmp_ptr->links );
2560             krm_releaseSite( tmp_ptr );
2561             /*    delete unit's Ftype */
2562             unit_ptr->Ftype_entry = NULL;
2563             }
2564           else
2565             {
2566             pred_site_ptr = site_ptr;
2567             site_ptr = site_ptr->next;
2568             }
2569           }
2570         while (site_ptr != NULL);
2571 
2572         if (unit_ptr->sites == NULL)
2573           unit_ptr->flags = UFLAG_INITIALIZED;  /*  unit has no inputs now !  */
2574         }
2575 
2576       return;
2577 
2578 
2579     case  UFLAG_DLINKS:
2580     /*  Unit has direct links   */
2581       if (ftype_ptr->sites != NULL)
2582         { /*  unit has direct links, but Ftype entry has sites: delete links  */
2583         unit_ptr->Ftype_entry = NULL;
2584 
2585         kr_deleteAllInputs( unit_ptr );
2586         unit_ptr->flags = UFLAG_INITIALIZED;  /*  unit has no inputs now !    */
2587         }
2588       else
2589         { /* unit has direct links and Ftype has no sites: use direct links  */
2590         unit_ptr->Ftype_entry = ftype_ptr;
2591         }
2592 
2593     }
2594 }
2595 
2596 /*****************************************************************************
2597   FUNCTION : kr_changeFtypeSites
2598 
2599   PURPOSE  : change a site at the F-Type
2600   NOTES    :
2601 
2602   RETURNS  :
2603   UPDATE   :
2604 ******************************************************************************/
kr_changeFtypeSites(struct FtypeUnitStruct * Ftype_entry,struct SiteTable * old_site_table,struct SiteTable * new_site_table)2605 void    kr_changeFtypeSites(struct FtypeUnitStruct *Ftype_entry,
2606 			    struct SiteTable *old_site_table,
2607 			    struct SiteTable *new_site_table)
2608 {
2609   struct Unit   *unit_ptr;
2610   struct Site   *site_ptr;
2611 
2612 
2613   if (NoOfUnits == 0)  return;  /*  no units  */
2614 
2615   FOR_ALL_UNITS( unit_ptr )
2616     if UNIT_IN_USE( unit_ptr )
2617       {     /*  unit is in use  */
2618       if (unit_ptr->Ftype_entry == Ftype_entry)
2619         {
2620 	FOR_ALL_SITES( unit_ptr, site_ptr )
2621           if (site_ptr->site_table == old_site_table)
2622             site_ptr->site_table = new_site_table;
2623       }
2624     }
2625 
2626   NetModified = TRUE;
2627 }
2628 
2629 
2630 /*#################################################
2631 
2632 GROUP: Miscellanous
2633 
2634 #################################################*/
2635 /*****************************************************************************
2636   FUNCTION : kr_flags2TType
2637 
2638   PURPOSE  : translate unit flags to the topological type of the unit
2639   NOTES    :
2640 
2641   RETURNS  :
2642   UPDATE   :
2643 ******************************************************************************/
kr_flags2TType(int flags)2644 int  kr_flags2TType(int flags)
2645 {
2646   KernelErrorCode = KRERR_NO_ERROR;
2647 
2648   switch (flags)
2649     {
2650     case UFLAG_TTYP_UNKN:  return( UNKNOWN );
2651     case UFLAG_TTYP_IN  :  return( INPUT );
2652     case UFLAG_TTYP_OUT :  return( OUTPUT );
2653     case UFLAG_TTYP_DUAL:  return( DUAL );
2654     case UFLAG_TTYP_HIDD:  return( HIDDEN );
2655     case UFLAG_TTYP_SPEC:  return( SPECIAL );
2656     case UFLAG_TTYP_SPEC_I: return (SPECIAL_I) ;
2657     case UFLAG_TTYP_SPEC_O: return (SPECIAL_O) ;
2658     case UFLAG_TTYP_SPEC_H: return (SPECIAL_H) ;
2659     case UFLAG_TTYP_SPEC_D: return (SPECIAL_D) ;
2660       /* case UFLAG_TTYP_SPEC_X and
2661 	 case UFLAG_TTYP_N_SPEC_X are no true TType*/
2662 
2663     default: KernelErrorCode = KRERR_TTYPE;
2664 	     return( UNKNOWN );
2665   }
2666 }
2667 
2668 /*****************************************************************************
2669   FUNCTION : kr_TType2Flags
2670 
2671   PURPOSE  : translate the topological type to unit flags
2672   NOTES    :
2673 
2674   RETURNS  :
2675   UPDATE   :
2676 ******************************************************************************/
kr_TType2Flags(int ttype)2677 int  kr_TType2Flags(int ttype)
2678 {
2679   KernelErrorCode = KRERR_NO_ERROR;
2680 
2681   switch (ttype)
2682     {
2683     case UNKNOWN:  return( UFLAG_TTYP_UNKN );
2684     case INPUT	:  return( UFLAG_TTYP_IN );
2685     case OUTPUT :  return( UFLAG_TTYP_OUT );
2686     case DUAL	:  return( UFLAG_TTYP_DUAL );
2687     case HIDDEN :  return( UFLAG_TTYP_HIDD );
2688     case SPECIAL:  return( UFLAG_TTYP_SPEC );
2689     case SPECIAL_I: return (UFLAG_TTYP_SPEC_I) ;
2690     case SPECIAL_O: return (UFLAG_TTYP_SPEC_O) ;
2691     case SPECIAL_H: return (UFLAG_TTYP_SPEC_H) ;
2692     case SPECIAL_D: return (UFLAG_TTYP_SPEC_D) ;
2693     case SPECIAL_X: return (UFLAG_TTYP_SPEC_X) ;
2694     case N_SPECIAL_X: return (UFLAG_TTYP_N_SPEC_X) ;
2695     default:  KernelErrorCode = KRERR_TTYPE;
2696 	      /*  return( KernelErrorCode );  */
2697 	      return( -1 );
2698   }
2699 }
2700 /*****************************************************************************
2701   FUNCTION : kr_updateUnitOutputs
2702 
2703   PURPOSE  : update the outputs of all units in the network
2704   NOTES    :
2705 
2706   RETURNS  :
2707   UPDATE   :
2708 ******************************************************************************/
kr_updateUnitOutputs(void)2709 void    kr_updateUnitOutputs(void)
2710 {
2711   register struct Unit   *unit_ptr;
2712 
2713 
2714   FOR_ALL_UNITS( unit_ptr )
2715     if ( (unit_ptr->flags & UFLAG_INITIALIZED) == UFLAG_INITIALIZED)
2716       {     /*  unit is in use and enabled  */
2717       if (unit_ptr->out_func == NULL)
2718         /*  Identity Function   */
2719         unit_ptr->Out.output = unit_ptr->act;
2720       else if(unit_ptr->out_func == OUT_Custom_Python)
2721       	unit_ptr->Out.output = kr_PythonOutFunction(unit_ptr->python_out_func,
2722 						unit_ptr->act);
2723       else
2724         unit_ptr->Out.output = (*unit_ptr->out_func) (unit_ptr->act);
2725       }
2726 }
2727 
2728 
2729 /*****************************************************************************
2730   FUNCTION : kr_getNoOfUnits
2731 
2732   PURPOSE  : returns the no. of units of the specified topologic type
2733              (i.e. Input, Hidden, Output or Special units)
2734   NOTES    :
2735 
2736   RETURNS  :
2737   UPDATE   :
2738 ******************************************************************************/
kr_getNoOfUnits(int UnitTType)2739 int  kr_getNoOfUnits(int UnitTType)
2740 {
2741   register struct Unit   *unit_ptr;
2742   register int   no_of_units;
2743   register FlagWord      ttyp_flg;
2744   int   flg;
2745 
2746 
2747   if ((NoOfUnits == 0) || ((flg = kr_TType2Flags( UnitTType )) == -1))
2748     return( 0 );  /*  no units or this topologic type doesn't exist  */
2749 
2750   ttyp_flg = (FlagWord) flg;
2751   no_of_units = 0;
2752   FOR_ALL_UNITS( unit_ptr )
2753     if ( ((unit_ptr->flags & UFLAG_TTYP_PAT) == ttyp_flg) &&
2754          UNIT_IN_USE( unit_ptr ) )
2755       no_of_units++;
2756 
2757   return( no_of_units );
2758 }
2759 
2760 
2761 /*****************************************************************************
2762   FUNCTION : kr_getNoOfSpecialUnits
2763 
2764   PURPOSE  : returns the no. of special units of the specified topologic type
2765              (i.e. Input, Hidden, Output or Special units)
2766   NOTES    :
2767 
2768   RETURNS  :
2769   UPDATE   :
2770 ******************************************************************************/
kr_getNoOfSpecialUnits(int UnitTType)2771 int  kr_getNoOfSpecialUnits(int UnitTType)
2772 {
2773   register struct Unit   *unit_ptr;
2774   register int   no_of_units;
2775   register FlagWord      ttyp_flg;
2776   int   flg;
2777 
2778 
2779   if ((NoOfUnits == 0) || ((flg = kr_TType2Flags( UnitTType )) == -1))
2780     return( 0 );  /*  no units or this topologic type doesn't exist  */
2781 
2782   ttyp_flg = (FlagWord) flg;
2783   no_of_units = 0;
2784   FOR_ALL_UNITS( unit_ptr )
2785     if ( ((unit_ptr->flags & UFLAG_TTYP_PAT) == (ttyp_flg | UFLAG_TTYP_SPEC)) &&
2786          UNIT_IN_USE( unit_ptr ) )
2787       no_of_units++;
2788 
2789   return( no_of_units );
2790 }
2791 
2792 
2793 /*****************************************************************************
2794   FUNCTION : kr_forceUnitGC
2795 
2796   PURPOSE  : force unit array garbage collection
2797   NOTES    :
2798 
2799   RETURNS  :
2800   UPDATE   :
2801 ******************************************************************************/
kr_forceUnitGC(void)2802 void  kr_forceUnitGC(void)
2803 {
2804   krm_unitArrayGC();
2805 }
2806 
2807 
2808 /*#################################################
2809 
2810 GROUP: Functions default presettings
2811 
2812 #################################################*/
2813 
2814 /*****************************************************************************
2815   FUNCTION : kr_getUnitDefaults
2816 
2817   PURPOSE  :
2818   NOTES    :
2819 
2820   RETURNS  : Returns information about the unit default settings.
2821   UPDATE   :
2822 ******************************************************************************/
kr_getUnitDefaults(FlintType * act,FlintType * bias,int * ttflags,int * subnet_no,int * layer_no,char ** act_func,char ** out_func)2823 void	kr_getUnitDefaults(FlintType *act, FlintType *bias, int *ttflags,
2824 			   int *subnet_no, int *layer_no, char **act_func,
2825 			   char **out_func)
2826 {
2827   static char  activation_func[FUNCTION_NAME_MAX_LEN],
2828                output_func[FUNCTION_NAME_MAX_LEN];
2829 
2830 
2831   *act          = DefaultIAct;
2832   *bias         = DefaultBias;
2833   *ttflags	= (int) DefaultSType;
2834   *subnet_no    = DefaultSubnetNo;
2835   *layer_no     = DefaultLayerNo;
2836 
2837   strcpy( activation_func, krf_getCurrentNetworkFunc( ACT_FUNC ) );
2838   *act_func = activation_func;
2839   strcpy( output_func, krf_getCurrentNetworkFunc( OUT_FUNC ) );
2840   *out_func = output_func;
2841 }
2842 
2843 /*****************************************************************************
2844   FUNCTION : kr_setUnitDefaults
2845 
2846   PURPOSE  : Changes the unit default settings.
2847   NOTES    :
2848 
2849   RETURNS  : Returns error code
2850   UPDATE   :
2851 ******************************************************************************/
kr_setUnitDefaults(FlintTypeParam act,FlintTypeParam bias,int ttflags,int subnet_no,int layer_no,char * act_func,char * out_func)2852 krui_err  kr_setUnitDefaults(FlintTypeParam act, FlintTypeParam bias,
2853 			     int ttflags, int subnet_no, int layer_no,
2854 			     char *act_func, char *out_func)
2855 {
2856   FunctionPtr  act_func_ptr,
2857                act_deriv_func_ptr,
2858                act_2_deriv_func_ptr,
2859                out_func_ptr;
2860 
2861 
2862   KernelErrorCode = KRERR_NO_ERROR;
2863 
2864 
2865   if (!krf_funcSearch( act_func, ACT_FUNC, &act_func_ptr))
2866     return( KernelErrorCode );
2867   if (!krf_funcSearch( act_func, ACT_DERIV_FUNC, &act_deriv_func_ptr))
2868     return( KernelErrorCode );
2869   if (!krf_funcSearch( act_func, ACT_2_DERIV_FUNC, &act_2_deriv_func_ptr))
2870     return( KernelErrorCode );
2871   if (!krf_funcSearch( out_func, OUT_FUNC, &out_func_ptr))
2872     return( KernelErrorCode );
2873 
2874   if (krf_setCurrentNetworkFunc( act_func, ACT_FUNC ) != KRERR_NO_ERROR)
2875     return( KernelErrorCode );
2876   if (krf_setCurrentNetworkFunc( out_func, OUT_FUNC ) != KRERR_NO_ERROR)
2877     return( KernelErrorCode );
2878 
2879   DefaultIAct       = (FlintType) act;
2880   DefaultBias       = (FlintType) bias;
2881   DefaultSType	    = (FlagWord) ttflags;
2882   DefaultPosX       = DEF_POS_X;
2883   DefaultPosY       = DEF_POS_Y;
2884 
2885   DefaultPosZ       = DEF_POS_Z;
2886 
2887 
2888   DefaultSubnetNo   = subnet_no;
2889   DefaultLayerNo    = layer_no;
2890 
2891   DefaultUFuncOut   = (OutFuncPtr) out_func_ptr;
2892   DefaultUFuncAct   = (ActFuncPtr) act_func_ptr;
2893   DefaultUFuncActDeriv = (ActDerivFuncPtr) act_deriv_func_ptr;
2894   DefaultUFuncAct2Deriv = (ActDerivFuncPtr) act_2_deriv_func_ptr;
2895   if(DefaultUFuncOut == OUT_Custom_Python) {
2896 	  DefaultUPythonFuncOut   = kr_findPythonFunction(out_func,OUT_FUNC);
2897   }
2898   if(DefaultUFuncAct == ACT_Custom_Python) {
2899 	  DefaultUPythonFuncAct   = kr_findPythonFunction(act_func,ACT_FUNC);
2900 	  DefaultUPythonFuncActDeriv = kr_findPythonFunction(act_func,ACT_DERIV_FUNC);
2901 	  DefaultUPythonFuncAct2Deriv = kr_findPythonFunction(act_func,ACT_2_DERIV_FUNC);
2902   }
2903 
2904   return( KernelErrorCode );
2905 }
2906 
2907 
2908 /*#################################################
2909 
2910 GROUP: Topological Sorting Functions
2911 
2912 #################################################*/
2913 
2914 /*****************************************************************************
2915   FUNCTION : clr_T_flags
2916 
2917   PURPOSE  : Clears the 'touch' (refresh) flag of all units
2918   NOTES    :
2919 
2920   RETURNS  :
2921   UPDATE   :
2922 ******************************************************************************/
clr_T_flags(void)2923 static void  clr_T_flags(void)
2924 {
2925   register struct Unit   *unit_ptr;
2926 
2927 
2928   FOR_ALL_UNITS( unit_ptr )
2929     if (UNIT_IN_USE( unit_ptr ))
2930       {
2931       unit_ptr->flags &= ~UFLAG_REFRESH;
2932       unit_ptr->lln = 0;
2933     }
2934 }
2935 
2936 /*****************************************************************************
2937   FUNCTION : DepthFirst1
2938 
2939   PURPOSE  : Depth search routine for topological sorting
2940   NOTES    :
2941 
2942   RETURNS  :
2943   UPDATE   :
2944 ******************************************************************************/
DepthFirst1(struct Unit * unit_ptr,int depth)2945 static void  DepthFirst1(struct Unit *unit_ptr, int depth)
2946 {
2947   struct Site   *site_ptr;
2948   struct Link   *link_ptr;
2949 
2950 
2951   if (unit_ptr->flags & UFLAG_REFRESH)
2952     {  /*  the 'touch' flag is set: don't continue search  */
2953     if (unit_ptr->lln == 0)
2954       {  /*  logical layer no. isn't set => Cycle found  */
2955       topo_msg.no_of_cycles++;
2956       if (topo_msg.error_code == KRERR_NO_ERROR)
2957 	{  /*  remember the cycle unit	*/
2958         topo_msg.src_error_unit = unit_ptr - unit_array;
2959         topo_msg.error_code = KRERR_CYCLES;
2960       }
2961     }
2962 
2963     return;
2964   }
2965   else
2966     /*	set the 'touch' flag  */
2967     unit_ptr->flags |= UFLAG_REFRESH;
2968 
2969   switch (unit_ptr->flags & UFLAG_INPUT_PAT)
2970     {
2971     case  UFLAG_DLINKS:   /*  unit has direct links  */
2972       FOR_ALL_LINKS( unit_ptr, link_ptr )
2973 	DepthFirst1( link_ptr->to, depth + 1 );  /*  increase depth  */
2974 
2975       break;
2976 
2977     case  UFLAG_SITES:	/*  unit has sites  */
2978 	FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
2979 	  DepthFirst1( link_ptr->to, depth + 1 );  /*  increase depth  */
2980 
2981       break;
2982   }
2983 
2984   /*  remember the depth (for cycle detection and statistics)  */
2985   unit_ptr->lln = depth;
2986   *global_topo_ptr++ = unit_ptr;  /*  store sorted unit pointer  */
2987 }
2988 
2989 /*****************************************************************************
2990   FUNCTION : DepthFirst2
2991 
2992   PURPOSE  : Depth search routine for topology check function
2993   NOTES    :
2994 
2995   RETURNS  :
2996   UPDATE   :
2997 ******************************************************************************/
DepthFirst2(struct Unit * unit_ptr,int depth)2998 static void  DepthFirst2(struct Unit *unit_ptr, int depth)
2999 {
3000   struct Site   *site_ptr;
3001   struct Link   *link_ptr;
3002 
3003 
3004   if (unit_ptr->flags & UFLAG_REFRESH)
3005     {  /*  the 'touch' flag is set: don't continue search  */
3006     if (unit_ptr->lln == 0)
3007       {  /*  logical layer no. isn't set => Cycle found  */
3008       topo_msg.no_of_cycles++;
3009       if (topo_msg.error_code == KRERR_NO_ERROR)
3010 	{  /*  remember the cycle unit	*/
3011         topo_msg.src_error_unit = unit_ptr - unit_array;
3012         topo_msg.error_code = KRERR_CYCLES;
3013       }
3014     }
3015 
3016     return;
3017   }
3018   else
3019     /*	set the 'touch' flag  */
3020     unit_ptr->flags |= UFLAG_REFRESH;
3021 
3022   switch (unit_ptr->flags & UFLAG_INPUT_PAT)
3023     {
3024     case  UFLAG_DLINKS:   /*  unit has direct links  */
3025       FOR_ALL_LINKS( unit_ptr, link_ptr )
3026 	DepthFirst2( link_ptr->to, depth + 1 );  /*  increase depth  */
3027 
3028       break;
3029 
3030     case  UFLAG_SITES:	/*  unit has sites  */
3031       FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
3032 	DepthFirst2( link_ptr->to, depth + 1 );  /*  increase depth  */
3033 
3034       break;
3035   }
3036 
3037   /*  remember the depth (for cycle detection and statistics)  */
3038   unit_ptr->lln = depth;
3039 
3040   /*  store highest layer no.  */
3041   if (depth > topo_msg.no_of_layers)  topo_msg.no_of_layers = depth;
3042 }
3043 
3044 /*****************************************************************************
3045   FUNCTION : DepthFirst3
3046 
3047   PURPOSE  : Depth search routine for topological sorting in feedforward networks
3048   NOTES    :
3049 
3050   RETURNS  :
3051   UPDATE   :
3052 ******************************************************************************/
DepthFirst3(struct Unit * unit_ptr,int depth)3053 static void  DepthFirst3(struct Unit *unit_ptr, int depth)
3054 {
3055   struct Site   *site_ptr;
3056   struct Link   *link_ptr;
3057 
3058 
3059   if (unit_ptr->flags & UFLAG_REFRESH)
3060     {  /*  the 'touch' flag is set: don't continue search  */
3061     topo_msg.src_error_unit = unit_ptr - unit_array; /*  store unit number  */
3062 
3063     if IS_OUTPUT_UNIT( unit_ptr )
3064       {  /*  this output unit has a output connection to another unit  */
3065       if (topo_msg.error_code == KRERR_NO_ERROR)
3066         topo_msg.error_code = KRERR_O_UNITS_CONNECT;
3067     }
3068     else
3069       if (unit_ptr->lln == 0)
3070         {  /*  logical layer no. isn't set => Cycle found  */
3071         topo_msg.no_of_cycles++;
3072         if (topo_msg.error_code == KRERR_NO_ERROR)
3073           topo_msg.error_code = KRERR_CYCLES;
3074       }
3075 
3076     return;
3077   }
3078   else
3079     /*	set the 'touch' flag  */
3080     unit_ptr->flags |= UFLAG_REFRESH;
3081 
3082   switch (unit_ptr->flags & UFLAG_INPUT_PAT)
3083     {
3084     case  UFLAG_DLINKS:   /*  unit has direct links  */
3085       FOR_ALL_LINKS( unit_ptr, link_ptr )
3086 	DepthFirst3( link_ptr->to, depth + 1 );  /*  increase depth  */
3087 
3088       break;
3089 
3090     case  UFLAG_SITES:	/*  unit has sites  */
3091       FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
3092 	DepthFirst3( link_ptr->to, depth + 1 );  /*  increase depth  */
3093 
3094       break;
3095   }
3096 
3097   /*  remember the depth (for cycle detection and statistics)  */
3098   unit_ptr->lln = depth;
3099 
3100   /*  store only hidden units  */
3101   if IS_HIDDEN_UNIT( unit_ptr )
3102     *global_topo_ptr++ = unit_ptr;  /*	store sorted unit pointer  */
3103 }
3104 
3105 
3106 /*****************************************************************************
3107   FUNCTION : kr_topoSortT
3108 
3109   PURPOSE  : Sort units topological (general version) and stores the
3110              pointers to this units in the topologic array
3111   NOTES    : Units are not sorted by their topologic type (that's not possible
3112              in the general case)
3113 
3114   RETURNS  : error code
3115   UPDATE   :
3116 ******************************************************************************/
kr_topoSortT(void)3117 static krui_err  kr_topoSortT(void)
3118 {
3119   register struct Unit	 *unit_ptr;
3120   int	io_units;
3121 
3122 
3123   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
3124   clr_T_flags();    /*	reset units 'touch' flags  */
3125   global_topo_ptr = topo_ptr_array;  /*  initialize global pointer */
3126 
3127   /*  limit left side of the topological array with NULL pointer  */
3128   *global_topo_ptr++ = NULL;
3129 
3130   /*  put all input units in the topologic array  */
3131   io_units = 0;
3132   FOR_ALL_UNITS( unit_ptr )
3133     if (IS_INPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3134       io_units++;	/*  there is a input unit  */
3135 
3136   if ((NoOfInputUnits = io_units) == 0)
3137     {  /*  no input units */
3138     KernelErrorCode = KRERR_NO_INPUT_UNITS;
3139     return( KernelErrorCode );
3140   }
3141 
3142   /*  begin depth search at the first output unit  */
3143   io_units = 0;
3144   FOR_ALL_UNITS( unit_ptr )
3145     if ( IS_OUTPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ) )
3146       {
3147       io_units++;  /*  there is a output unit  */
3148 
3149       /*  sort the units topological (using depth search algorithm,
3150 	  starting at this output unit */
3151       DepthFirst1( unit_ptr, 1 );
3152       if (topo_msg.error_code != KRERR_NO_ERROR)
3153         {  /*  stop if an error occured  */
3154         KernelErrorCode = topo_msg.error_code;
3155         return( KernelErrorCode );
3156       }
3157     }
3158 
3159   if ((NoOfOutputUnits = io_units) == 0)
3160     {  /*  no output units */
3161     KernelErrorCode = KRERR_NO_OUTPUT_UNITS;
3162     return( KernelErrorCode );
3163   }
3164 
3165   /*  limit right side of the topologic array with NULL pointer  */
3166   *global_topo_ptr++ = NULL;
3167 
3168   /*  calc. no. of sorted units  */
3169   no_of_topo_units = (global_topo_ptr - topo_ptr_array) - 2;
3170 
3171   /*  search for dead units i.e. units without inputs  */
3172   FOR_ALL_UNITS( unit_ptr )
3173     if ( !(unit_ptr->flags &  (UFLAG_REFRESH | UFLAG_TTYP_SPEC)) &&
3174          UNIT_IN_USE( unit_ptr ) )
3175       {
3176       topo_msg.no_of_dead_units++;
3177       if (topo_msg.src_error_unit == 0)
3178         topo_msg.src_error_unit = unit_ptr - unit_array; /* store the unit no.*/
3179     }
3180 
3181   if (topo_msg.no_of_dead_units != 0)
3182     KernelErrorCode = KRERR_DEAD_UNITS;
3183 
3184   return( KernelErrorCode );
3185 }
3186 
3187 
3188 /*****************************************************************************
3189   FUNCTION : kr_topoSortT
3190 
3191   PURPOSE  : Sorts units topological in feed-forward networks and stores the
3192              pointers to these units in the topologic array in the following
3193 	     order:
3194 	     - input,
3195 	     - hidden and
3196 	     - output units
3197 
3198              This function make following assumtions (like all learning
3199 	     functions for feed-forward networks):
3200              a) input units doesn't have input connections to other units and
3201              b) output units doesn't have outputs connections to other units.
3202   NOTES    :
3203 
3204   RETURNS  : error code
3205   UPDATE   :
3206 ******************************************************************************/
kr_topoSortFF(void)3207 static krui_err  kr_topoSortFF(void)
3208 {
3209   register struct Unit	 *unit_ptr;
3210   int	io_units;
3211 
3212 
3213   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
3214   clr_T_flags();    /*	reset units 'touch' flags  */
3215   global_topo_ptr = topo_ptr_array;  /*  initialize global pointer */
3216 
3217   /*  limit left side of the topological array with NULL pointer  */
3218   *global_topo_ptr++ = NULL;
3219 
3220   /*  put all input units in the topologic array  */
3221   io_units = 0;
3222   FOR_ALL_UNITS( unit_ptr )
3223     if (IS_INPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3224       {
3225       if UNIT_HAS_INPUTS( unit_ptr )
3226 	{  /*  this input unit has a connection to another unit  */
3227 
3228 	/*  store the unit no.  */
3229 	topo_msg.dest_error_unit = unit_ptr - unit_array;
3230 
3231 	KernelErrorCode = KRERR_I_UNITS_CONNECT;  /*  input unit has input  */
3232         return( KernelErrorCode );
3233       }
3234 
3235       io_units++;	/*  there is a input unit  */
3236       *global_topo_ptr++ = unit_ptr;  /*  save input unit  */
3237     }
3238 
3239   if ((NoOfInputUnits = io_units) == 0)
3240     {  /*  no input units */
3241     KernelErrorCode = KRERR_NO_INPUT_UNITS;
3242     return( KernelErrorCode );
3243   }
3244 
3245   /*  limit input units in the topological array with NULL pointer  */
3246   *global_topo_ptr++ = NULL;
3247 
3248   /*  begin depth search at the first output unit  */
3249   io_units = 0;
3250   FOR_ALL_UNITS( unit_ptr )
3251     if (IS_OUTPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3252       {
3253       io_units++;	/*  there is a output unit  */
3254 
3255       /*  sort the units topological (using depth search algorithm,
3256 	  starting at this output unit */
3257       DepthFirst3( unit_ptr, 1 );
3258       if (topo_msg.error_code != KRERR_NO_ERROR)
3259         {  /*  stop if an error occured  */
3260         KernelErrorCode = topo_msg.error_code;
3261         return( KernelErrorCode );
3262       }
3263     }
3264 
3265   if ((NoOfOutputUnits = io_units) == 0)
3266     {  /*  no output units */
3267     KernelErrorCode = KRERR_NO_OUTPUT_UNITS;
3268     return( KernelErrorCode );
3269   }
3270 
3271   /*  limit hidden units in the topological array with NULL pointer  */
3272   *global_topo_ptr++ = NULL;
3273 
3274   /*  put all output units in the topological array  */
3275   FOR_ALL_UNITS( unit_ptr )
3276     if (IS_OUTPUT_UNIT(unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3277       *global_topo_ptr++ = unit_ptr;  /*  save output unit  */
3278 
3279   /*  limit right side of the topologic array with NULL pointer  */
3280   *global_topo_ptr++ = NULL;
3281 
3282   /*  calc. no. of sorted units  */
3283   no_of_topo_units = (global_topo_ptr - topo_ptr_array) - 4;
3284 
3285   /*  search for dead units i.e. units without inputs  */
3286   FOR_ALL_UNITS( unit_ptr )
3287     if (!(unit_ptr->flags & (UFLAG_REFRESH | UFLAG_TTYP_SPEC)) && UNIT_IN_USE( unit_ptr ))
3288       {
3289       topo_msg.no_of_dead_units++;
3290       if (topo_msg.src_error_unit == 0)
3291         topo_msg.src_error_unit = unit_ptr - unit_array;  /*  store unit no.  */
3292     }
3293 
3294   if (topo_msg.no_of_dead_units != 0)
3295     KernelErrorCode = KRERR_DEAD_UNITS;
3296 
3297   return( KernelErrorCode );
3298 }
3299 
3300 
3301 /*****************************************************************************
3302   FUNCTION : kr_topoSortIHO
3303 
3304   PURPOSE  : Sort units by their topologic type, i.e. Input, Hidden, Output
3305              units and stores the pointers to this units in the topologic array.
3306   NOTES    :
3307 
3308   RETURNS  : error code
3309   UPDATE   :
3310 ******************************************************************************/
kr_topoSortIHO(void)3311 static krui_err  kr_topoSortIHO(void)
3312 {
3313   TopoPtrArray     topo_ptr;
3314   register struct Unit   *unit_ptr;
3315   int  no_of_units;
3316   int has_no_dual;
3317 
3318 
3319   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
3320   topo_ptr = topo_ptr_array;
3321 
3322   /*  limit left side of the topological array with NULL pointer  */
3323   *topo_ptr++ = NULL;
3324 
3325   /*  get input units  */
3326   no_of_units = 0;
3327   FOR_ALL_UNITS( unit_ptr )
3328     if (IS_INPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3329       {
3330       *topo_ptr++ = unit_ptr;
3331       no_of_units++;
3332     }
3333 
3334 
3335   if ((NoOfInputUnits = no_of_units) == 0)
3336     {
3337     KernelErrorCode = KRERR_NO_INPUT_UNITS;
3338     return( KernelErrorCode );
3339   }
3340 
3341   /*  limit input units in the topological array with NULL pointer  */
3342   *topo_ptr++ = NULL;
3343 
3344   /*  get hidden units  */
3345   no_of_units = 0;
3346   FOR_ALL_UNITS( unit_ptr )
3347     if (IS_HIDDEN_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3348       {
3349       *topo_ptr++ = unit_ptr;
3350       no_of_units++;
3351     }
3352 
3353   if ((NoOfHiddenUnits = no_of_units) == 0)
3354     {
3355     /* In special case for DUAL units */
3356     FOR_ALL_UNITS( unit_ptr )
3357       if (IS_DUAL_UNIT( unit_ptr ) )
3358         has_no_dual = FALSE;
3359     if ( has_no_dual ){
3360 	KernelErrorCode = KRERR_NO_HIDDEN_UNITS;
3361 	return( KernelErrorCode );
3362     }
3363   }
3364 
3365   /*  limit hidden units in the topological array with NULL pointer  */
3366   *topo_ptr++ = NULL;
3367 
3368   /*  get output units  */
3369   no_of_units = 0;
3370   FOR_ALL_UNITS( unit_ptr )
3371     if (IS_OUTPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
3372       {
3373       *topo_ptr++ = unit_ptr;
3374       no_of_units++;
3375     }
3376 
3377   if ((NoOfOutputUnits = no_of_units) == 0)
3378     {
3379     KernelErrorCode = KRERR_NO_OUTPUT_UNITS;
3380     return( KernelErrorCode );
3381   }
3382 
3383   /*  limit right side of the topologic array with NULL pointer  */
3384   *topo_ptr++ = NULL;
3385 
3386   /*  calc. no. of sorted units  */
3387   no_of_topo_units = (topo_ptr - topo_ptr_array) - 4;
3388 
3389   return( KernelErrorCode );
3390 }
3391 
3392 /*****************************************************************************
3393   FUNCTION : kr_topoSortLOG()
3394 
3395   PURPOSE  : Sort units by their logical Layer- and Unitnumber
3396 
3397   NOTES    :
3398 
3399   RETURNS  : error code
3400   UPDATE   :
3401 ******************************************************************************/
3402 
llncompare(const struct Unit ** a,const struct Unit ** b)3403 static int llncompare(const struct Unit **a, const struct Unit **b)
3404 {
3405   int llndiff, lundiff;
3406 
3407   llndiff = ((*a)->lln - (*b)->lln);
3408   lundiff = ((*a)->lun - (*b)->lun);
3409   return(llndiff != 0 ? llndiff : lundiff);
3410 }
3411 
kr_topoSortLOG(void)3412 static krui_err  kr_topoSortLOG(void)
3413 {
3414   struct Unit      *unit_ptr;
3415   TopoPtrArray     topo_ptr;
3416   TopoPtrArray     topo_ptr_save;
3417   int              no_of_units = 0;
3418 
3419   topo_ptr = topo_ptr_array;
3420   *topo_ptr++ = (struct Unit *) NULL;
3421 
3422 
3423   FOR_ALL_UNITS( unit_ptr )
3424     if ( (unit_ptr->flags & UFLAG_IN_USE) == UFLAG_IN_USE)
3425       {
3426       *topo_ptr = unit_ptr;
3427       topo_ptr++;
3428       no_of_units++;
3429       }
3430   *topo_ptr = (struct Unit *) NULL;
3431   topo_ptr_save = topo_ptr;
3432 
3433   no_of_topo_units = no_of_units;
3434   topo_ptr = topo_ptr_array;
3435   topo_ptr++;
3436   qsort(topo_ptr, no_of_units, sizeof(*topo_ptr),
3437 	(int (*)(const void *, const void *)) llncompare);
3438 
3439   /* insert NULL pointer between input units and rest */
3440   topo_ptr = topo_ptr_save;
3441   while (*topo_ptr == (struct Unit *) NULL ||
3442          !(IS_INPUT_UNIT(*topo_ptr)))
3443   {
3444       *(topo_ptr + 1) = *topo_ptr;
3445       topo_ptr--;
3446   }
3447   topo_ptr++;
3448   *topo_ptr = (struct Unit *) NULL;
3449   topo_ptr_save++;
3450 
3451   /* insert NULL pointer between output units and rest */
3452   topo_ptr = topo_ptr_save;
3453   while (*topo_ptr == (struct Unit *) NULL ||
3454          (IS_OUTPUT_UNIT(*topo_ptr)))
3455   {
3456       *(topo_ptr + 1) = *topo_ptr;
3457       topo_ptr--;
3458   }
3459   topo_ptr++;
3460   *topo_ptr = (struct Unit *) NULL;
3461   topo_ptr_save++;
3462 
3463   /* create pointers from units to topo_ptr_array */
3464   topo_ptr = topo_ptr_array;
3465   while (topo_ptr != topo_ptr_save)
3466   {
3467       if (*topo_ptr != (struct Unit *) NULL)
3468       {
3469           (*topo_ptr) -> TD.my_topo_ptr = topo_ptr;
3470       }
3471       topo_ptr++;
3472   }
3473   return (KRERR_NO_ERROR);
3474 }
3475 
3476 
3477 /*****************************************************************************
3478   FUNCTION : kr_topoSort
3479 
3480   PURPOSE  :
3481 
3482     Sort units according to the given mode:
3483     TOPOLOGICAL:
3484       Sort units topological (general version) and stores the
3485       pointers to this units in the topologic array.
3486       NOTE: Units are not sorted by their topologic type (that's not
3487 	    possible in general case).
3488 
3489     TOPOLOGICAL_FF:
3490       Sorts unit topological in feed-forward networks and stores the
3491       pointers to this units in the topologic array in the following order:
3492        - input,
3493        - hidden and
3494        - output units
3495 
3496       This function make following assumtions (like all learning functions for
3497       feed-forward networks):
3498        a) input units doesn't have input connections to other units and
3499        b) output units doesn't have outputs connections to other units.
3500 
3501     TOPOLOGIC_TYPE:
3502       Sort units by their topologic type, i.e. Input, Hidden, Output units and
3503       stores the pointers to this units in the topologic array.
3504 
3505     TOPOLOGIC_LOGICAL:
3506       Sort Units according to their logical Layers- and Unitsnumbers.
3507       The entry TD.my_topo_ptr in every unit is set to point to coresponding
3508       entry in the topo_ptr_array.
3509 
3510     ART1_TOPO_TYPE:
3511       Sort units in ART1 manner. For informations about the structure of
3512       ART1 networks see Diplomarbeit No.929; Kai-Uwe Herrmann; University of
3513       Stuttgart; Germany 1992. The pointers are sorted as follows:
3514 
3515       NULL, pointers to input units, NULL, pointers to comparison units,
3516       NULL, pointers to recognition units, NULL, pointers to delay units,
3517       NULL, pointers to local reset units, NULL, pointers to special units,
3518       NULL, NULL, ...
3519 
3520     ART2_TOPO_TYPE:
3521       Sort units in ART2 manner. For informations about the structure of
3522       ART2 networks see Diplomarbeit No.929; Kai-Uwe Herrmann; University of
3523       Stuttgart; Germany 1992. The pointers are sorted as follows:
3524 
3525       NULL, pointers to input units, NULL, pointers to w units,
3526       NULL, pointers to x units, NULL, pointers to u units,
3527       NULL, pointers to v units, NULL, pointers to p units,
3528       NULL, pointers to q units, NULL, pointers to r units,
3529       NULL, pointers to recognition units, NULL, pointers to delay units,
3530       NULL, pointers to local reset units, NULL, pointers to special units,
3531       NULL, NULL, ...
3532 
3533     ARTMAP_TOPO_TYPE:
3534       Sort units in ARTMAP manner. For informations about the structure of
3535       ARTMAP networks see Diplomarbeit No.929; Kai-Uwe Herrmann; University of
3536       Stuttgart; Germany 1992. The pointers are sorted as follows:
3537 
3538       NULL, ARTa inp units, NULL, ARTa cmp units, NULL, ARTa rec units ...,
3539       NULL, ARTb inp units, NULL, ARTb cmp units, NULL, ARTb rec units ...,
3540       NULL, map field units, NULL, map field special units, NULL
3541 
3542   NOTES    :
3543 
3544   RETURNS  : error code
3545   UPDATE   :
3546 ******************************************************************************/
kr_topoSort(int topo_sorting_mode)3547 krui_err  kr_topoSort(int topo_sorting_mode)
3548 {
3549   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
3550   TopoSortID = NOT_SORTED;
3551   if (NoOfUnits == 0)
3552     {  /*  No units defined  */
3553     KernelErrorCode = KRERR_NO_UNITS;
3554     return( KernelErrorCode );
3555   }
3556 
3557 
3558   if (krm_allocUnitTopoArray( NoOfUnits + 15) != KRERR_NO_ERROR)
3559     return( KernelErrorCode );
3560 
3561   /*  clear error codes  */
3562   topo_msg.no_of_cycles = topo_msg.no_of_dead_units =
3563   topo_msg.dest_error_unit = topo_msg.src_error_unit = 0;
3564   topo_msg.error_code = KRERR_NO_ERROR;
3565 
3566   switch (topo_sorting_mode)
3567     {
3568     case  TOPOLOGICAL:
3569 	(void) kr_topoSortT();
3570 	break;
3571     case  TOPOLOGICAL_FF:
3572 	(void) kr_topoSortFF();
3573 	break;
3574     case  TOPOLOGIC_TYPE:
3575 	(void) kr_topoSortIHO();
3576 	break;
3577     case  TOPOLOGIC_LOGICAL:
3578         KernelErrorCode = kr_topoSortLOG();
3579         break;
3580     case  ART1_TOPO_TYPE:
3581         KernelErrorCode = kra1_sort ();
3582         break;
3583 
3584     case ART2_TOPO_TYPE:
3585         KernelErrorCode = kra2_sort ();
3586         break;
3587 
3588     case ARTMAP_TOPO_TYPE:
3589         KernelErrorCode = kram_sort ();
3590         break;
3591     case TOPOLOGICAL_CC:
3592         (void) cc_topoSort(TOPOLOGICAL_CC);
3593         break;
3594     case TOPOLOGICAL_BCC:
3595         (void) cc_topoSort(TOPOLOGICAL_BCC);
3596         break;
3597     case TOPOLOGICAL_JE:
3598 	KernelErrorCode = kr_topoSortJE () ;
3599 	break ;
3600 
3601     default:
3602 	KernelErrorCode = KRERR_TOPOMODE;
3603     }
3604 
3605   if ((KernelErrorCode == KRERR_NO_ERROR) ||
3606       (KernelErrorCode == KRERR_DEAD_UNITS))
3607     TopoSortID = topo_sorting_mode;
3608 
3609   return( KernelErrorCode );
3610 }
3611 
3612 
3613 
3614 /*****************************************************************************
3615   FUNCTION : kr_topoCheck
3616 
3617   PURPOSE  : Checks the topology of the network:
3618              a) counts the number of layers of the network and
3619 	     b) determines if the network has cycles.
3620   NOTES    :
3621 
3622   RETURNS  : Returns the no. of layers of the network.
3623   UPDATE   :
3624 ******************************************************************************/
kr_topoCheck(void)3625 int  kr_topoCheck(void)
3626 {
3627   struct Unit   *unit_ptr;
3628   bool      o_units;
3629 
3630 
3631   topo_msg.no_of_cycles = topo_msg.no_of_dead_units =
3632   topo_msg.dest_error_unit = topo_msg.src_error_unit =
3633   topo_msg.no_of_layers = 0;
3634   topo_msg.error_code = KernelErrorCode = KRERR_NO_ERROR;
3635 
3636   if (NoOfUnits == 0)
3637     {  /*  no units defined  */
3638     KernelErrorCode = KRERR_NO_UNITS;
3639     return( KernelErrorCode );
3640   }
3641 
3642   clr_T_flags();    /*	reset units 'touch' flags  */
3643 
3644   /*  begin depth search at the first output unit  */
3645   o_units = FALSE;
3646   FOR_ALL_UNITS( unit_ptr )
3647     if ( IS_OUTPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ) )
3648       {
3649       o_units = TRUE;
3650       DepthFirst2( unit_ptr, 1 );
3651       if (topo_msg.error_code != KRERR_NO_ERROR)
3652         {  /*  stop if an error occured  */
3653         KernelErrorCode = topo_msg.error_code;
3654         return( KernelErrorCode );
3655       }
3656     }
3657 
3658   if (!o_units)
3659     {  /*  no output units */
3660     KernelErrorCode = KRERR_NO_OUTPUT_UNITS;
3661     return( KernelErrorCode );
3662   }
3663 
3664   /*  return the no. of layers of the network  */
3665   return( topo_msg.no_of_layers );
3666 }
3667 
3668 /*****************************************************************************
3669   FUNCTION : kr_makeUnitPermutation
3670 
3671   PURPOSE  :
3672   NOTES    :
3673 
3674   RETURNS  : Returns error code
3675   UPDATE   :
3676 ******************************************************************************/
kr_makeUnitPermutation(void)3677 krui_err  kr_makeUnitPermutation(void)
3678 {
3679   register struct Unit   *unit_ptr;
3680   register int	   no_of_units, i;
3681   TopoPtrArray     topo_ptr,  t_ptr1,  t_ptr2;
3682 
3683 
3684   TopoSortID = NOT_SORTED;
3685   if (NoOfUnits == 0)  return( KRERR_NO_UNITS );  /*  no units defined	*/
3686 
3687   if ( krm_allocUnitTopoArray( NoOfUnits + 2) != 0)
3688     return( KRERR_INSUFFICIENT_MEM );
3689 
3690   topo_ptr = topo_ptr_array;
3691 
3692   /*  limit left side of the topological array with NULL pointer  */
3693   *topo_ptr++ = NULL;
3694 
3695   /*  initialize permutation array  */
3696   FOR_ALL_UNITS( unit_ptr )
3697     if ( (unit_ptr->flags & UFLAG_INITIALIZED) == UFLAG_INITIALIZED)
3698       /*  unit is in use and enabled  */
3699       *topo_ptr++ = unit_ptr;
3700 
3701   no_of_topo_units = topo_ptr - topo_ptr_array;  /* calc no. of sorted units */
3702   no_of_units = no_of_topo_units;
3703 
3704   topo_ptr = topo_ptr_array;
3705   /*  permutate unit order  */
3706   for (i = 0; i < no_of_units; i++)
3707     {
3708     t_ptr1 = topo_ptr + (lrand48() % no_of_units);
3709     t_ptr2 = topo_ptr + (lrand48() % no_of_units);
3710 
3711     unit_ptr = *t_ptr1;
3712     *t_ptr1 = *t_ptr2;
3713     *t_ptr2 = unit_ptr;
3714     }
3715 
3716   /*  limit right side of the topologic array with NULL pointer  */
3717   *topo_ptr++ = NULL;
3718 
3719   TopoSortID = PERMUTATION;
3720   NetModified = FALSE;
3721 
3722   return( KRERR_NO_ERROR );
3723 }
3724 
3725 
3726 /*#################################################
3727 
3728 GROUP: Functions for pattern management
3729 
3730 #################################################*/
3731 /*****************************************************************************
3732   FUNCTION : kr_IOCheck
3733 
3734   PURPOSE  :  Count the no. of input and output units and return an error code
3735               if the no. do not fit to the loaded patterns.
3736   NOTES    :
3737 
3738   RETURNS  : Returns error code
3739   UPDATE   :
3740 ******************************************************************************/
kr_IOCheck(void)3741 krui_err  kr_IOCheck(void)
3742 {
3743   register struct Unit   *unit_ptr;
3744   register int  no_of_i_units, no_of_o_units;
3745 
3746   KernelErrorCode = KRERR_NO_ERROR;  /*  reset return code  */
3747 
3748   /*  count no. of input and output units  */
3749   no_of_i_units = no_of_o_units = 0;
3750   FOR_ALL_UNITS( unit_ptr )
3751     if UNIT_IN_USE( unit_ptr ){
3752       if IS_INPUT_UNIT( unit_ptr )
3753         no_of_i_units++;
3754       if IS_OUTPUT_UNIT( unit_ptr )
3755           no_of_o_units++;
3756     }
3757   NoOfInputUnits = no_of_i_units;
3758   NoOfOutputUnits = no_of_o_units;
3759 
3760   return( KernelErrorCode );
3761 }
3762 
3763 /*#################################################
3764 
3765 GROUP: other functions
3766 
3767 #################################################*/
3768 
3769  /*****************************************************************************
3770   FUNCTION :  kr_NA_Error
3771 
3772   PURPOSE  : calculates the error for the network-analyzer tool
3773   NOTES    :
3774 
3775   RETURNS  : Returns the float value of the error
3776   UPDATE   :
3777 ******************************************************************************/
3778 
kr_NA_Error(int currentPattern,int error_unit,int error,bool ave)3779 float kr_NA_Error(int currentPattern, int error_unit, int error, bool ave)
3780 {
3781   register struct   Unit *unit_ptr, *error_unit_ptr ;
3782   register Patterns       out_pat  ;
3783   register float          error_lin, error_sqr, error_su, devit ;
3784   int                     pattern_no, sub_pat_no;
3785 
3786 
3787   kr_initSubPatternOrder(currentPattern, currentPattern);
3788   kr_getSubPatternByOrder(&pattern_no, &sub_pat_no);
3789   out_pat = kr_getSubPatData(pattern_no,sub_pat_no,OUTPUT, NULL);
3790 
3791   error_lin = 0 ;
3792   error_sqr= 0 ;
3793   error_su  = 0 ;
3794 
3795   if (error_unit != 0)
3796     error_unit_ptr = kr_getUnitPtr (error_unit) ;
3797 
3798   FOR_ALL_UNITS (unit_ptr)
3799   {
3800     if (IS_OUTPUT_UNIT (unit_ptr))
3801     {
3802       devit = (float) (*(out_pat++) - unit_ptr->Out.output) ;
3803       error_lin += fabs (devit) ;
3804       error_sqr += devit * devit ;
3805 
3806       if (unit_ptr == error_unit_ptr) error_su = fabs (devit) ;
3807     }
3808   }
3809 
3810 
3811   switch (error)
3812   {
3813     case NA_ERROR_LIN :
3814     {
3815       if (ave) return (error_lin / (float) NoOfOutputUnits);
3816       else        return (error_lin) ;
3817       break ;
3818     }
3819 
3820     case NA_ERROR_SQR :
3821     {
3822       if (ave) return (error_sqr / (float) NoOfOutputUnits);
3823       else        return (error_sqr) ;
3824       break ;
3825     }
3826 
3827     case NA_ERROR_SU :
3828     {
3829       return (error_su) ;
3830       break ;
3831     }
3832   }
3833   /* Only for the warning */
3834   return(0.0);
3835 }
3836 
3837 /*#################################################
3838 
3839 GROUP: Functions for handeling network propagation,
3840        update and learning functions.
3841 
3842 #################################################*/
3843 /*****************************************************************************
3844   FUNCTION : kr_callNetworkFunctionSTD
3845 
3846   PURPOSE  : calls the current network function
3847   NOTES    :
3848 
3849   RETURNS  : Returns error code
3850   UPDATE   :
3851 ******************************************************************************/
kr_callNetworkFunctionSTD(int type,float * parameterInArray,int NoOfInParams,float ** parameterOutArray,int * NoOfOutParams,int start_pattern,int end_pattern)3852 static krui_err  kr_callNetworkFunctionSTD(int type, float *parameterInArray,
3853 					   int NoOfInParams,
3854 					   float **parameterOutArray,
3855 					   int *NoOfOutParams,
3856 					   int start_pattern, int end_pattern)
3857 {
3858   FunctionPtr  func_ptr;
3859   NetFunctionPtr  net_func_ptr;
3860   char  *curr_func;
3861   int size;
3862 
3863 
3864   if ( (curr_func = krf_getCurrentNetworkFunc( type )) == NULL)
3865     return( KernelErrorCode );
3866   if (!krf_funcSearch( curr_func, type, &func_ptr ) )
3867     return( KernelErrorCode );
3868 
3869   KernelErrorCode = KRERR_NO_ERROR;
3870   net_func_ptr = (NetFunctionPtr) func_ptr;
3871 
3872   switch (type)  {
3873     case  UPDATE_FUNC:
3874       KernelErrorCode =
3875 	  (*(UpdateFuncPtr)net_func_ptr) ( parameterInArray, NoOfInParams );
3876       return( KernelErrorCode );
3877 
3878     case TEST_FUNC:
3879     case  LEARN_FUNC:
3880       if (kr_TotalNoOfPattern() == 0)
3881 	{  /*  no patterns defined  */
3882 	KernelErrorCode = KRERR_NO_PATTERNS;
3883 	return( KernelErrorCode );
3884       }
3885       if ((start_pattern < 0) || (end_pattern >= kr_TotalNoOfPattern()) )
3886 	{  /*  Invalid pattern number  */
3887 	KernelErrorCode = KRERR_PATTERN_NO;
3888 	return( KernelErrorCode );
3889       }
3890 
3891       /* check whether sub pattern fits onto network */
3892       if (NetModified)
3893 	  kr_IOCheck();
3894       size = kr_SizeOfInputSubPat();
3895       if (NoOfInputUnits != size)
3896       {
3897 	  if (size < 0)
3898 	      KernelErrorCode = size;
3899 	  else
3900 	      KernelErrorCode = KRERR_NP_DOES_NOT_FIT;
3901 	  return KernelErrorCode;
3902       }
3903       size = kr_SizeOfOutputSubPat();
3904       if (NoOfOutputUnits != size)
3905       {
3906 	  if (size < 0)
3907 	      KernelErrorCode = size;
3908 	  else if (size == 0)
3909 	      KernelErrorCode = KRERR_NP_NO_OUTPUT_PATTERN;
3910 	  else
3911 	      KernelErrorCode = KRERR_NP_DOES_NOT_FIT;
3912 	  return KernelErrorCode;
3913       }
3914 
3915       /*  call current learning function  */
3916       KernelErrorCode =
3917 	  (*(LearnFuncPtr)net_func_ptr) (start_pattern, end_pattern,
3918 					 parameterInArray, NoOfInParams,
3919 					 parameterOutArray, NoOfOutParams);
3920 
3921       if (KernelErrorCode == KRERR_NO_ERROR)
3922 	{  /*  learning function has initialized the network  */
3923 	NetInitialize = FALSE;
3924 	LearnFuncHasChanged = FALSE;
3925       }
3926 
3927       return( KernelErrorCode );
3928 
3929     case (FF_LEARN_FUNC | LEARN_FUNC):
3930 
3931       /* check whether sub pattern fits onto network */
3932       if (NetModified)
3933 	  kr_IOCheck();
3934       size = kr_SizeOfInputSubPat();
3935       if (NoOfInputUnits != size)
3936       {
3937 	  if (size < 0)
3938 	      KernelErrorCode = size;
3939 	  else
3940 	      KernelErrorCode = KRERR_NP_DOES_NOT_FIT;
3941 	  return KernelErrorCode;
3942       }
3943       size = kr_SizeOfOutputSubPat();
3944       if (NoOfOutputUnits != size)
3945       {
3946 	  if (size < 0)
3947 	      KernelErrorCode = size;
3948 	  else if (size == 0)
3949 	      KernelErrorCode = KRERR_NP_NO_OUTPUT_PATTERN;
3950 	  else
3951 	      KernelErrorCode = KRERR_NP_DOES_NOT_FIT;
3952 	  return KernelErrorCode;
3953       }
3954       /*  call embedded feed forward learning function for pruning */
3955       KernelErrorCode =
3956 	  (*(LearnFuncPtr) net_func_ptr) (start_pattern, end_pattern,
3957 					  parameterInArray, NoOfInParams,
3958 					  parameterOutArray, NoOfOutParams);
3959 
3960       if (KernelErrorCode == KRERR_NO_ERROR)
3961 	  /*  learning function has initialized the network  */
3962       {
3963 	  NetInitialize = FALSE;
3964 	  LearnFuncHasChanged = FALSE;
3965       }
3966 
3967       return( KernelErrorCode );
3968 
3969     case  INIT_FUNC:
3970       NetInitialize = TRUE;
3971       KernelErrorCode =
3972 	  (*(InitFuncPtr)net_func_ptr) ( parameterInArray, NoOfInParams );
3973 
3974       return( KernelErrorCode );
3975 
3976    default:
3977      KernelErrorCode = KRERR_PARAMETERS;
3978      return( KernelErrorCode );
3979   }
3980 }
3981 
3982 /*****************************************************************************
3983   FUNCTION : kr_callNetworkFunction
3984 
3985   PURPOSE  : calls the current network function
3986   NOTES    :
3987 
3988   RETURNS  : Returns error code
3989   UPDATE   :
3990 ******************************************************************************/
kr_callNetworkFunction(int type,float * parameterInArray,int NoOfInParams,float ** parameterOutArray,int * NoOfOutParams,int start_pattern,int end_pattern)3991 krui_err  kr_callNetworkFunction(int type, float *parameterInArray,
3992 				 int NoOfInParams, float **parameterOutArray,
3993 				 int *NoOfOutParams, int start_pattern,
3994 				 int end_pattern)
3995 {
3996 #ifdef MASPAR_KERNEL
3997   static struct NetFuncParameters  net_func_params;
3998 #endif
3999 
4000   krui_err dummy;
4001   if (NoOfUnits == 0)
4002     {  /*  No Units defined  */
4003     KernelErrorCode = KRERR_NO_UNITS;
4004     return( KRERR_NO_UNITS );
4005   }
4006 
4007   KernelErrorCode = KRERR_NO_ERROR;
4008 
4009   switch (specialNetworkType)  {
4010     case NET_TYPE_GENERAL:
4011       /*  normal network presentation  */
4012       /*  the result of this call has been void which is not compatible */
4013       /*  to the declaration; therefor the dummy error variable is included */
4014       dummy = kr_callNetworkFunctionSTD( type, parameterInArray, NoOfInParams,
4015                                         parameterOutArray, NoOfOutParams,
4016                                         start_pattern, end_pattern );
4017       break;
4018 
4019 #ifdef MASPAR_KERNEL
4020     case NET_TYPE_FF1:
4021 
4022       /*  feedforward net on MasPar  */
4023       net_func_params.start_pattern_no = start_pattern;
4024       net_func_params.end_pattern_no   = end_pattern;
4025       net_func_params.no_of_input_parameters = NoOfInParams;
4026 
4027       memcpy( net_func_params.input_parameters, parameterInArray,
4028               sizeof (float) * NoOfInParams );
4029 
4030       (void) krff_callMasParNetworkFunction( type, &net_func_params );
4031 
4032       if (NoOfOutParams != NULL)
4033         *NoOfOutParams = net_func_params.no_of_output_parameters;
4034       if (parameterOutArray != NULL)
4035         *parameterOutArray = net_func_params.output_parameters;
4036 
4037       break;
4038 #endif
4039 
4040     default:
4041       KernelErrorCode = KRERR_PARAMETERS;
4042   }
4043 
4044   return( KernelErrorCode );
4045 }
4046 
4047 
4048 
4049 #ifdef HAVE_QSORT
transTableCompare(const void * node1,const void * node2)4050 static int  transTableCompare( const void *node1, const void *node2)
4051 {
4052   short  z1, z2;
4053 
4054   z1=((struct TransTable *) node1)->z;
4055   z2=((struct TransTable *) node2)->z;
4056 
4057   if (z1 < z2)  return -1;
4058   if (z1 > z2)  return 1;
4059   return 0;
4060 }
4061 #endif
4062 
kr_xyTransTable(int op,int * x,int * y,int z)4063 krui_err  kr_xyTransTable(int op, int *x, int *y, int z)
4064 {
4065   struct TransTable  *transTablePtr,
4066                      *new_transTable,
4067                      transTableEntry;
4068 
4069 
4070   switch(op)  {
4071     case OP_TRANSTABLE_GET:
4072       if (transTable != NULL)  {
4073 
4074 #ifdef HAVE_QSORT
4075         transTableEntry.z = z;
4076         transTablePtr =
4077 	    (struct TransTable *) bsearch( &transTableEntry,
4078 					  (struct TransTable *) transTable,
4079 					  transTableSize,
4080 					  sizeof(struct TransTable),
4081 					  transTableCompare );
4082 #else
4083 	for (transTablePtr = transTable;
4084              transTablePtr < (transTable + transTableSize);
4085              transTablePtr++)
4086           if (transTablePtr->z == z)  break;
4087 
4088           if (transTablePtr == (transTable + transTableSize))
4089             transTablePtr=NULL;
4090 #endif
4091 
4092         if (transTablePtr == NULL)  {
4093           *x = *y = 0;
4094         }
4095         else  {
4096           *x=transTablePtr->x;
4097           *y=transTablePtr->y;
4098         }
4099       }
4100       else  {
4101         *x = *y = 0;
4102       }
4103 
4104       KernelErrorCode = KRERR_NO_ERROR;
4105       return( KRERR_NO_ERROR );
4106 
4107     case OP_TRANSTABLE_SET:
4108       if (transTable == NULL)  {
4109         if((new_transTable =
4110            (struct TransTable *) malloc( sizeof(struct TransTable) )) == NULL){
4111           KernelErrorCode = KRERR_INSUFFICIENT_MEM;
4112           return( KRERR_INSUFFICIENT_MEM );
4113         }
4114 
4115         transTable=new_transTable;
4116 
4117         transTable->z = z;
4118         transTable->x = *x;
4119         transTable->y = *y;
4120         transTableSize=1;
4121       }
4122       else  {
4123 #ifdef HAVE_QSORT
4124         transTableEntry.z = z;
4125         transTablePtr =
4126 	    (struct TransTable *) bsearch( &transTableEntry,
4127 					  (struct TransTable *) transTable,
4128 					  transTableSize,
4129 					  sizeof(struct TransTable),
4130 					  transTableCompare );
4131 #else
4132     	for (transTablePtr = transTable;
4133              transTablePtr < (transTable + transTableSize);
4134              transTablePtr++)
4135           if (transTablePtr->z == z)  break;
4136 
4137           if (transTablePtr == (transTable + transTableSize))
4138             transTablePtr=NULL;
4139 #endif
4140 
4141         if (transTablePtr == NULL)  {
4142           if ((new_transTable =
4143 	       (struct TransTable *) realloc( (void *) transTable,
4144 		sizeof(struct TransTable) * (transTableSize + 1) )) == NULL)  {
4145             KernelErrorCode = KRERR_INSUFFICIENT_MEM;
4146             return( KRERR_INSUFFICIENT_MEM );
4147           }
4148 
4149           transTable=new_transTable;
4150 
4151           transTable[transTableSize].z = z;
4152           transTable[transTableSize].x = *x;
4153           transTable[transTableSize].y = *y;
4154           ++transTableSize;
4155 
4156 #ifdef HAVE_QSORT
4157           qsort( (struct TransTable *) transTable,
4158                  transTableSize,
4159                  sizeof(struct TransTable),
4160                  transTableCompare );
4161 #endif
4162         }
4163         else  {
4164           transTablePtr->x = *x;
4165           transTablePtr->y = *y;
4166         }
4167       }
4168 
4169       KernelErrorCode=KRERR_NO_ERROR;
4170       return( KRERR_NO_ERROR );
4171 
4172     case OP_TRANSTABLE_CLEAR:
4173       if (transTable != NULL)  {
4174         free( (void *) transTable );
4175         transTable = NULL;
4176         transTableSize = 0;
4177       }
4178 
4179       KernelErrorCode=KRERR_NO_ERROR;
4180       return( KRERR_NO_ERROR );
4181 
4182     default:
4183       KernelErrorCode=KRERR_PARAMETERS;
4184       return( KRERR_PARAMETERS );
4185   }
4186 }
4187 
4188 
4189 /*#################################################
4190 
4191 GROUP: Functions for the parallel kernel
4192 
4193 #################################################*/
4194 
4195 /*****************************************************************************
4196   FUNCTION : kr_setSpecialNetworkType
4197 
4198   PURPOSE  : Sets the topologic type of the current network and checks the
4199              topology of the current network.
4200 	     Returns an error if the topologic type of the current network
4201 	     doesn't fit to this type.
4202 	     Topologic types are:
4203 	     - NET_TYPE_GENERAL
4204 	     general purpose network type with no limitations
4205 	     - NET_TYPE_FF1
4206 	     feedforward network with fully connected units in
4207 	     neighbour layers
4208   NOTES    :
4209 
4210   RETURNS  : Returns error code
4211   UPDATE   :
4212 ******************************************************************************/
kr_setSpecialNetworkType(int net_type)4213 krui_err  kr_setSpecialNetworkType(int net_type)
4214 {
4215   KernelErrorCode = KRERR_NO_ERROR;
4216 
4217   if (net_type == specialNetworkType)  return( KRERR_NO_ERROR );
4218 
4219   if (NoOfUnits == 0)
4220     {  /*  no units defined  */
4221     KernelErrorCode = KRERR_NO_UNITS;
4222     return( KernelErrorCode );
4223   }
4224 
4225   switch (net_type)  {
4226     case  NET_TYPE_GENERAL:
4227 
4228       switch (specialNetworkType)  {
4229         case  NET_TYPE_FF1:
4230           /*  change special network presentation to standard presentation  */
4231 
4232 #ifdef  MASPAR_KERNEL
4233           (void) krff_standardNetPresentationFF1();
4234           specialNetworkType = NET_TYPE_GENERAL;
4235 #else
4236           KernelErrorCode = KRERR_NO_MASPAR_KERNEL;
4237 #endif
4238           break;
4239 
4240         default:
4241           KernelErrorCode = KRERR_PARAMETERS;
4242       }
4243 
4244       break;
4245 
4246     case  NET_TYPE_FF1:
4247       /*  change standart network presentation to special presentation  */
4248 #ifdef  MASPAR_KERNEL
4249       (void) krff_determineNetFF1Params();
4250       /*  change internal network presentation	*/
4251       if (KernelErrorCode != KRERR_NO_ERROR)  break;
4252 
4253       (void) krff_initMasPar();
4254       if (KernelErrorCode != KRERR_NO_ERROR)  break;
4255 
4256       (void) krff_changeNetPresentationFF1();
4257 
4258 #else
4259       KernelErrorCode = KRERR_NO_MASPAR_KERNEL;
4260 #endif
4261       break;
4262 
4263     default:
4264       KernelErrorCode = KRERR_PARAMETERS;
4265   }
4266 
4267   if (KernelErrorCode == KRERR_NO_ERROR)
4268     specialNetworkType = net_type;
4269 
4270   return( KernelErrorCode );
4271 }
4272 
4273 /*****************************************************************************
4274   FUNCTION : kr_getSpecialNetworkType
4275 
4276   PURPOSE  : Returns the special topologic type of the current network, if set.
4277   NOTES    :
4278 
4279   RETURNS  : Returns the special topologic type of the current network, if set.
4280   UPDATE   :
4281 ******************************************************************************/
kr_getSpecialNetworkType(void)4282 int  kr_getSpecialNetworkType(void)
4283 {
4284   return( specialNetworkType );
4285 }
4286 
4287 
4288 /*****************************************************************************
4289   FUNCTION : kr_validateOperation
4290 
4291   PURPOSE  : Validate a network modifying operation according to
4292              the kernel mode
4293   NOTES    :
4294 
4295   RETURNS  : error code
4296   UPDATE   :
4297 ******************************************************************************/
kr_validateOperation(void)4298 krui_err  kr_validateOperation(void)
4299 {
4300   switch (specialNetworkType)
4301     {
4302     case NET_TYPE_GENERAL:
4303       /*  normal network presentation, no limitations  */
4304       KernelErrorCode = KRERR_NO_ERROR;
4305       break;
4306     case NET_TYPE_FF1:
4307       /*  feedforward net with limitations  */
4308       KernelErrorCode = KRERR_MODE_FF1_INVALID_OP;
4309       break;
4310   }
4311 
4312   return( KernelErrorCode );
4313 }
4314 
4315 
4316 /* #############################################################
4317 
4318   Functions for the MasPar kernel
4319 
4320 ############################################################# */
4321 
4322 #ifdef  MASPAR_KERNEL
4323 /*****************************************************************************
4324   FUNCTION : kr_initMasPar
4325 
4326   PURPOSE  : Connects and Disconnects the MasPar.
4327              The mode switches are:  MASPAR_CONNECT and MASPAR_DISCONNECT.
4328   NOTES    :
4329 
4330   RETURNS  : error code
4331   UPDATE   :
4332 ******************************************************************************/
kr_initMasPar(int mode)4333 krui_err  kr_initMasPar(int mode )
4334 {
4335   if (specialNetworkType == NET_TYPE_GENERAL)  {
4336     KernelErrorCode = KRERR_NOT_PARALLEL_MODE;
4337     return( KernelErrorCode );
4338   }
4339 
4340   KernelErrorCode = KRERR_NO_ERROR;
4341 
4342   switch (mode)
4343     {
4344     case  MASPAR_CONNECT:
4345       /*  connect maspar  */
4346       if (krff_initMasPar() == KRERR_NO_ERROR)
4347         masParStatus = MASPAR_CONNECT;
4348 
4349       break;
4350     case  MASPAR_DISCONNECT:
4351       /*  disconnect maspar  */
4352       masParStatus = MASPAR_DISCONNECT;
4353 
4354       break;
4355     default:
4356       KernelErrorCode = KRERR_PARAMETERS;
4357   }
4358 
4359   return( KernelErrorCode );
4360 }
4361 
4362 /*****************************************************************************
4363   FUNCTION : kr_getMasParStatus
4364 
4365   PURPOSE  :
4366   NOTES    :
4367 
4368   RETURNS  : Returns the Status of the MasPar or an error code
4369   UPDATE   :
4370 ******************************************************************************/
kr_getMasParStatus(void)4371 krui_err  kr_getMasParStatus(void)
4372 {
4373   KernelErrorCode = KRERR_NO_ERROR;
4374 
4375   return( masParStatus );
4376 }
4377 
4378 #endif
4379 
4380 /*****************************************************************************
4381 
4382   Note: This is not part of the official SNNS distribution, but provided
4383   by the snns-dev project (http://snns-dev.berlios.de)
4384 
4385   The point where the Python extension hooks in - this wrapper layer shall
4386   make sure that the SNNS kernel can still be compiled without having Python,
4387   even with the Python patch applied.
4388 
4389 ******************************************************************************/
4390 
4391 FlintType (*kr_PythonOutFunctionHook)(PyObject *func, FlintType activation);
4392 FlintType (*kr_PythonActFunctionHook)(PyObject *func, struct Unit *unit_ptr);
4393 PyObject *(*kr_findPythonFunctionHook)(char *func, int type);
4394 int (*kr_getNoOfPythonFunctionsHook)();
4395 krui_err (*kr_getPythonFuncInfoHook)(int mode, struct FuncInfoDescriptor *descr);
4396 
kr_getNoOfPythonFunctions()4397 int kr_getNoOfPythonFunctions()
4398 {
4399 	if(!kr_getNoOfPythonFunctionsHook) {
4400 		fputs("No callback for number of Python functions found\n",
4401 			stderr);
4402 		return 0;
4403 	} else {
4404 		return kr_getNoOfPythonFunctionsHook();
4405 	}
4406 }
4407 
kr_getPythonFuncInfo(int mode,struct FuncInfoDescriptor * descr)4408 krui_err kr_getPythonFuncInfo(int mode, struct FuncInfoDescriptor *descr)
4409 {
4410 	if(!kr_getPythonFuncInfoHook) {
4411 		fputs("No Python function info callback found\n",stderr);
4412 		return KRERR_PARAMETERS;
4413 	} else {
4414 		return kr_getPythonFuncInfoHook(mode, descr);
4415 	}
4416 }
4417 
4418 
kr_PythonOutFunction(PyObject * func,FlintType activation)4419 FlintType kr_PythonOutFunction(PyObject *func, FlintType activation)
4420 {
4421 	if(!kr_PythonOutFunctionHook) {
4422 		fputs("The Python output function you are requesting "
4423 		        "can not be called because there is no callback "
4424 			"registered.\n",stderr);
4425 		return 0;
4426 	} else {
4427 		return kr_PythonOutFunctionHook(func, activation);
4428 	}
4429 }
4430 
kr_PythonActFunction(PyObject * func,struct Unit * unit_ptr)4431 FlintType kr_PythonActFunction(PyObject *func, struct Unit *unit_ptr)
4432 {
4433 	if(!kr_PythonActFunctionHook) {
4434 		fputs("The Python activation function you are requesting "
4435 		        "can not be called because there is no callback "
4436 			"registered.\n",stderr);
4437 		return 0;
4438 	} else {
4439 		return kr_PythonActFunctionHook(func, unit_ptr);
4440 	}
4441 }
4442 
4443 
kr_findPythonFunction(char * name,int type)4444 PyObject *kr_findPythonFunction(char *name, int type)
4445 {
4446 	if(!kr_findPythonFunctionHook) {
4447 		fputs("Can't check for Python functions because there is "
4448 		      "no callback registered.\n",stderr);
4449 		return NULL;
4450 	} else {
4451 		return kr_findPythonFunctionHook(name, type);
4452 	}
4453 }
4454