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