1 /******************************************************************************
2 FILE : $Source: /projects/higgs1/SNNS/CVS/SNNS/tools/sources/snns2c.c,v $
3 SHORTNAME : snns2c.c
4 SNNS VERSION : 4.2
5
6 PURPOSE : Converter for SNNS-net -Files to executable C-Source
7 only for Feed-Forward- and Elman-nets.
8
9 Loads the net with the functions given by the
10 kernel-interface of the SNNS-kernel.
11 Groups similar units in layers and sorts the layers
12 topologically.
13 Saves the Net as a C function.
14
15 Updates : TDNN (01.11.94 - 04.01.95)
16 DLVQ (05.01.95 - 10.01.95)
17 CPN (11.01.95 - 30.01.95)
18 generated HeaderFiles (31.01.95)
19 update function with pointers (01.02.95)
20 BBTT (02.02.95 - 20.02.95)
21 releasing all memory (23.02.95)
22
23 AUTHOR : Bernward Kett
24 DATE : 31.08.94
25 LAST UPDATE : 23.02.95 (Bernward Kett)
26
27 CHANGED BY :
28 RCS VERSION : $Revision: 1.19 $
29 LAST CHANGE : $Date: 1998/04/22 16:48:12 $
30
31 Copyright (c) 1990-1995 SNNS Group, IPVR, Univ. Stuttgart, FRG
32 Copyright (c) 1996-1998 SNNS Group, WSI, Univ. Tuebingen, FRG
33
34 used files : glob_typ.h, kr_ui.h from kernel/sources
35 libkernel.a from kernel/bin/<architecture>
36 functions.h, templates.h from actual directory
37 ******************************************************************************/
38 #include <config.h>
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44 #ifdef HAVE_LIMITS_H
45 #include <limits.h>
46 #endif
47 #include <time.h>
48 #include <memory.h>
49 #include "glob_typ.h"
50 #include "kr_ui.h"
51 #include "functions.h"
52 #include "templates.h"
53 #include "snns2clib.h"
54
55 #include "kr_typ.h"
56 #include "kernel.h" /* should be removed, when the kr_ui.h is updated */
57
58 #undef debug
59 /*
60 #define debug
61 */
62
63 /* Macros for calculating the minimum or maximum of two values */
64 #define MAX(a, b) ( (a > b) ? (a) : (b) )
65 #define MIN(a, b) ( (a < b) ? (a) : (b) )
66
67 /* Macro for releasing memory of units and layers */
68 #define FREE_ALL freeUnits(Units); freeLayers(Layers); free(TDNN_prot);
69
70 /* Status (Error) Codes : OK = 0 (NO Error), ERR = 1, ... */
71 typedef enum { OK, ERR, CANT_ADD, CANT_LOAD, MEM_ERR,
72 WRONG_PARAM, WRONG_ACT_FUNC, CANT_OPEN,
73 ILLEGAL_CYCLES, NO_CPN, NO_TDNN, NOT_SUPPORTED} Status;
74
75 /* Recordtype for Layers */
76 typedef struct {
77 int number; /* of the Layer (not used yet) */
78 pList members; /* Numbers of all member-units */
79 pList sources; /* numbers of all sources of the member-units */
80 int type; /* INPUT , OUTPUT ... */
81 int ActFunc; /* No in the ActivationFunctionList */
82 char *name; /* Name of the Layer */
83 /* Special entries for TDNN */
84 int TotalDelay; /* Total Delay Number of the Layer */
85 int delay; /* Delay of the receptive Field */
86 int SuccDelay; /* Delay of the following Layer */
87 char *readCounter; /* Name of the DelayPointer */
88 char *writeCounter; /* Name of the WriteDelayPointer */
89 } tLayer, *pLayer;
90
91 /* Recordtype for Units */
92 typedef struct {
93 int number; /* of the Unit */
94 pList members; /* Units with the same Prototype (TDNN)*/
95 pList sources; /* numbers of the source-Units */
96 float *weights; /* Link-Weights to the Source-Units */
97 int ActFunc; /* No in the ActivationFunctionList */
98 int type; /* INPUT , OUTPUT ... */
99 char *name; /* Name of the unit, given by the user */
100 float Bias; /* Bias of the unit */
101 pLayer layer; /* Pointer to the layer wich contains the unit */
102 /* Special entries for BPTT and Elman/Jordan */
103 float act; /* Initial Activation of the Unit */
104 /* Special entries for CPN */
105 float *dest; /* weights from Hidden to Output written in the hidden units */
106 int NoOfDest; /* Numbers of the weights to the Output */
107 /* Special entries for TDNN */
108 int index; /* Index in the global Array */
109 int FeatureWidth; /* Number of Prototype Source units */
110 int DelayLength; /* Delay Length of the receptive Field */
111 int **TDNNsources; /* special Format for TDNNs */
112 float **TDNNweights; /* special Format for TDNNs */
113 } tUnit, *pUnit;
114
115 /*
116 * Output-Functions for debug-informations
117 */
118
printLayer(pLayer layer)119 void printLayer(pLayer layer)
120 {
121 int i;
122 printf("\nLayer %d", layer->number);
123 printf("\nmembers: ");
124 for (i = 0; i < NoOf(layer->members); i++) {
125 printf("%d ", element(layer->members, i) );
126 }
127 printf("\nsources: ");
128 for (i = 0; i < NoOf(layer->sources); i++) {
129 printf("%d ", element(layer->sources, i) );
130 }
131 printf("\n");
132 }
133
134
printUnit(pUnit unit)135 void printUnit(pUnit unit)
136 {
137 int i;
138 printf("\nUnit %d", unit->number);
139 printf("\nsources: ");
140 for (i = 0; i < NoOf(unit->sources); i++) {
141 printf("%9d ", element(unit->sources, i) );
142 }
143 printf("\nweights: ");
144 for (i = 0; i < NoOf(unit->sources); i++) {
145 printf("%9f ", unit->weights[i] );
146 }
147 printf("\n");
148 }
149
150
printTDNNunit(pUnit unit)151 void printTDNNunit(pUnit unit)
152 {
153 int i, j;
154 printf("\nUnit %d", unit->number);
155 printf("\nmembers : ");
156 for (i = 0; i < NoOf(unit->members); i++) {
157 printf("%d ", element(unit->members, i) );
158 }
159 printf("\nsources: \n");
160 for (i = 0; i < unit->FeatureWidth; i++) {
161 for (j = 0; j < NoOf(unit->sources) / unit->FeatureWidth; j++) {
162 printf("%8d ", unit->TDNNsources[i][j]);
163 }
164 printf("\n");
165 }
166 printf("weights: \n");
167 for (i = 0; i < unit->FeatureWidth; i++) {
168 for (j = 0; j < NoOf(unit->sources) / unit->FeatureWidth; j++) {
169 printf("%8f ", unit->TDNNweights[i][j]);
170 }
171 printf("\n");
172 }
173 }
174
175 /******************************************************************************
176 void toAlphaNum(char *string)
177 -----------------------------------------------------------------------------
178 replaces all characters in string wich are not alphanumerical with '_'.
179 Furtheron it deletes all characters before first '/'.
180 If the first Character is a digit, it is replaced by 'X'
181 ******************************************************************************/
toAlphaNum(char * string)182 void toAlphaNum(char *string)
183 {
184 char *pointer;
185
186 pointer = string - 1; /* because of increment in while-condition */
187 while( *(++pointer) != '\0') { /* to the end of the String */
188 while (*pointer == '/') { /* only the tail of Path-names */
189 strcpy(string, pointer + 1);
190 pointer = string;
191 }
192 if (!isalnum(*pointer) ) *pointer = '_'; /* no special characters */
193 }
194 if (*string == '\0') strcpy (string, "NOTHING"); /* no empty strings */
195 if (isdigit(*string) ) *string = 'X'; /* no leading digit */
196 }
197
198
199 /******************************************************************************
200 void checkErr(int errCode)
201 -----------------------------------------------------------------------------
202 writes an error message if needed and also stops program if errCode
203 stands for a fatal error
204 -> errCode : code of the actual status
205 ******************************************************************************/
checkErr(int errCode)206 void checkErr(int errCode)
207 {
208 switch(errCode)
209 {
210 case OK : ;
211 break;
212 case ERR : printf("unspecified Error\n");
213 break;
214 case CANT_ADD :
215 case MEM_ERR : printf("not enough memory\n");
216 break;
217 case CANT_LOAD : printf("can't load file\n");
218 break;
219 case WRONG_PARAM : printf("wrong parameters\n");
220 break;
221 case CANT_OPEN : printf("can't open file\n");
222 break;
223 case NO_CPN : printf("net is not a CounterPropagation network\n");
224 break;
225 case NO_TDNN : printf("net is not a Time Delay Neural Network\n");
226 break;
227 case ILLEGAL_CYCLES : printf("net contains illegal cycles\n");
228 break;
229 case WRONG_ACT_FUNC : ;
230 break;
231 case NOT_SUPPORTED : printf("not supported network type\n");
232 break;
233 default : printf("unknown error code : %d\n", errCode);
234 }
235 }
236
237
238 /*****************************************************************************
239 bool is_TDNN_net(void)
240 ----------------------------------------------------------------------------
241 checks, if the current Net is a Time Delay Neural Network by testing
242 the learning functions.
243 <- (func) : TRUE Net is a TDNN Network
244 FALSE otherwise
245 *****************************************************************************/
is_TDNN_net(void)246 bool is_TDNN_net(void)
247 {
248 return (0 == strcmp("TimeDelayBackprop", krui_getLearnFunc() ) );
249 }
250
251
252 /*****************************************************************************
253 bool is_DLVQ_net(void)
254 ----------------------------------------------------------------------------
255 checks, if the current Net is a Dynamic LVQ Network by testing
256 the learning functions.
257 <- (func) : TRUE Net is a TDNN Network
258 FALSE otherwise
259 *****************************************************************************/
is_DLVQ_net(void)260 bool is_DLVQ_net(void)
261 {
262 return (0 == strcmp("Dynamic_LVQ", krui_getLearnFunc() ));
263 }
264
265
266 /*****************************************************************************
267 bool is_CPN_net(void)
268 ----------------------------------------------------------------------------
269 checks, if the current Net is a CounterPropagation Network by testing
270 the learning functions.
271 <- (func) : TRUE Net is a TDNN Network
272 FALSE otherwise
273 *****************************************************************************/
is_CPN_net(void)274 bool is_CPN_net(void)
275 {
276 return (0 == strcmp("Counterpropagation", krui_getLearnFunc() ));
277 }
278
279
280 /*****************************************************************************
281 bool is_BPTT_net(void)
282 ----------------------------------------------------------------------------
283 checks, if the current Net is a BPTT, BBPTT or QPTT Network by testing
284 the learning functions.
285 <- (func) : TRUE Net is a kind of BPTT Network
286 FALSE otherwise
287 *****************************************************************************/
is_BPTT_net(void)288 bool is_BPTT_net(void)
289 {
290 return ( (0 == strcmp("BPTT", krui_getLearnFunc() ))
291 || (0 == strcmp("BBPTT", krui_getLearnFunc() ))
292 || (0 == strcmp("QPTT", krui_getLearnFunc() )) );
293 }
294
295
296 /*****************************************************************************
297 int checkLearnFunc(void)
298 ----------------------------------------------------------------------------
299 checks, if the Learning Function is supported by the snns2c
300 <- Error Code : OK / NOT_SUPPORTED
301 *****************************************************************************/
checkLearnFunc(void)302 int checkLearnFunc(void)
303 {
304 static char *NotSupportedLearnFuncs[] = {
305 "ART1", "ART2", "ARTMAP", "BackPercolation", "Hebbian", "RM_delta",
306 "Kohonen", NULL
307 };
308
309 char *LearnFunc = krui_getLearnFunc(); /* learning function of the network */
310 char **string = NotSupportedLearnFuncs; /* current function name to test */
311
312 while(*string) {
313 if (!strcmp(*string, LearnFunc)) { /* e.g. the same function-name */
314 return(NOT_SUPPORTED);
315 }
316 string++;
317 }
318
319 return(OK);
320 }
321
322
323 /*****************************************************************************
324 bool is_Prototype_Unit(int UnitNr)
325 ----------------------------------------------------------------------------
326 checks, if the current unit is a prototype unit, e.g. if the links are
327 defined in this unit.
328
329 Note : Function is only needed for TDNN
330
331 <- (func) : TRUE unit is a prototype unit
332 FALSE otherwise
333 *****************************************************************************/
is_Prototype_Unit(int UnitNr)334 bool is_Prototype_Unit(int UnitNr)
335 {
336 struct Unit *unit_ptr;
337
338 if ((unit_ptr = kr_getUnitPtr( UnitNr ) ) == NULL) {
339 return (FALSE);
340 }
341 else {
342 return ( unit_ptr->TD.target_offset == 0);
343 }
344 }
345
346
347 /****************************************************************************
348 int get_Prototype_Unit(int(unitNr)
349 ---------------------------------------------------------------------------
350 returns the number of the prototype Unit and 0 if an error occurs
351
352 Note : Function is only needed for TDNN
353
354 <- (func) : Number of the Prototype Unit
355 (0 = Unit not found)
356 *****************************************************************************/
get_Prototype_Unit(int UnitNr)357 int get_Prototype_Unit(int UnitNr)
358 {
359 struct Unit *unit_ptr;
360
361 if ((unit_ptr = kr_getUnitPtr( UnitNr ) ) == NULL) {
362 return (0);
363 }
364 else {
365 return (UnitNr + unit_ptr->TD.target_offset);
366 }
367 }
368
369
370 /****************************************************************************
371 pUnit searchUnit(int UnitNr, pUnit global Units, pUnit lastUnit)
372 ---------------------------------------------------------------------------
373 returns a pointer to the Unit wich has the current number UnitNr
374
375 Note : Function is only needed for TDNN
376
377 -> UnitNr : Number of the UNit in the original SNNS network
378 globalUnits : Array of all existing snns2c-units
379 <- index : index of the unit, found in the Array
380 (func) : pointer to the unit or NULL if the unit isn't found
381 *****************************************************************************/
searchUnit(int UnitNr,pUnit globalUnits,int * index)382 pUnit searchUnit(int UnitNr, pUnit globalUnits, int *index)
383 {
384 pUnit unit;
385
386 *index = 0;
387 for (unit = globalUnits; unit->number > 0; unit++, (*index)++) {
388 if (unit->number == UnitNr) return (unit);
389 }
390
391 return(NULL);
392 }
393
394
395 /*****************************************************************************
396 int checkActFunc(char *actName)
397 ----------------------------------------------------------------------------
398 checks, if an activation Function with the name actName is present
399 -> actName : Name of the activation function
400 <- (func) : number in the function table or -1 if not present
401 *****************************************************************************/
checkActFunc(char * actName)402 int checkActFunc(char *actName)
403 {
404 int i=0;
405
406 while (**(ACT_FUNC_NAMES + i) ) {
407 if (!strcmp(ACT_FUNC_NAMES[i], actName) ) return (i);
408 i++;
409 }
410 fprintf(stderr, "Can't find the function <%s>\n", actName);
411 return(-1);
412 }
413
414
415 /*****************************************************************************
416 int initLayer(pLayer layer, pUnit unit)
417 ----------------------------------------------------------------------------
418 initialize the given layer e.g :
419 - initializes the two lists members and sources
420 - insert the type and the Number of the activation-function of the
421 given Unit in the predefined places.
422 - inserts the sources of the given Unit into the list sources
423
424 -> layer : pointer to the new Layer
425 unit : pointer to the first (e.g.prototype-) unit
426 <- (func) : Status (Errorcodes)
427 *****************************************************************************/
initLayer(pLayer layer,pUnit unit)428 int initLayer(pLayer layer, pUnit unit)
429 {
430 layer->members = newList(); /* a list for member unit */
431 if (!layer->members) return(MEM_ERR);
432
433 layer->sources = newList(); /* a list for all predecessor */
434 if (!layer->sources) return(MEM_ERR); /* units of all members */
435
436 addList(layer->members, unit->number); /* prototype unit is the first member */
437 if (copyList(layer->sources, unit->sources) ) return(MEM_ERR);
438
439 layer->ActFunc = unit->ActFunc;
440 layer->type = unit->type;
441
442 unit->layer = layer;
443
444 return(OK);
445 }
446
447
448 /******************************************************************************
449 int matchLayer(pLayer layer, pUnit unit)
450 -----------------------------------------------------------------------------
451 checks if the unit could be in the same layer as the other units wich
452 are in the layer yet
453 -> layer : pointer to the (existing) layer
454 unit : pointer to the unit wich is to be prooved
455 <- (func) TRUE the unit matches with the other units
456 FALSE otherwise
457 ******************************************************************************/
matchLayer(pLayer layer,pUnit unit)458 int matchLayer(pLayer layer, pUnit unit)
459 {
460 static int is_BPTT = 0, first_time = 1;
461
462 /* a special flag is set to avoid unneeded function calls */
463 if (first_time) {
464 is_BPTT = is_BPTT_net();
465 first_time = 0;
466 }
467
468 /* input neurons are all treated the same way */
469 if ( (unit->type == INPUT) && (layer->type == INPUT) ) return (TRUE);
470
471 /* unit should match the attributes of the Layer */
472 if (unit->type != layer->type) return(FALSE);
473 if (unit->ActFunc != layer->ActFunc) return(FALSE);
474
475 /* BPTT-nets have no topological order */
476 if (is_BPTT) return (TRUE);
477
478 /* unit must not be a member of the source units */
479 if (isMember(layer->sources, unit->number) ) return (FALSE);
480
481 /* Neue Version von Matthias Oderdorfer */
482 return ( CompareSources(unit->sources, layer->sources) );
483
484 /* alte Version */
485 /* a member of the layer must not be a source element of the unit */
486 /* return( !haveIntersection(unit->sources, layer->members) ); */
487 }
488
489
490 /******************************************************************************
491 int searchLayer(pUnit unit, pLayer globalLayers)
492 -----------------------------------------------------------------------------
493 searches a Layer with matches the unit (or an empty Layer) and inserts the
494 unit in the layer.
495 -> unit : actual unit wich searches a friendly layer
496 globalLayers : array of all Layers
497 <- (func) MEM_ERR : not enough Memory
498 OK : no problems
499 ******************************************************************************/
searchLayer(pUnit unit,pLayer globalLayers)500 int searchLayer(pUnit unit, pLayer globalLayers)
501 {
502 pLayer layer;
503
504 layer = globalLayers;
505 while(TRUE) {
506 if (layer->members == NULL) { /* empty layer found */
507 return(initLayer(layer, unit)); /* give possible Errors to caller */
508 }
509 else if (matchLayer(layer, unit) ) { /* matching layer found */
510 if (addList(layer->members, unit->number)) {
511 return(MEM_ERR);
512 }
513 unit->layer = layer;
514 return(mergeList(layer->sources, unit->sources)); /* returns Status */
515 }
516 layer++;
517 }
518 }
519
520
521 /******************************************************************************
522 int divideNet(pUnit globalUnits, pLayer globalLayers, int *TDNN_prot)
523 -----------------------------------------------------------------------------
524 parts a net into groups and prepares the Net for sorting the
525 layers.
526
527 -> globalUnits : all the Units are going to be written in this array
528 globalLayers : all the different Layers will be written in this array
529 <- globalUnits : (the values in the array)
530 globalLayers : (the values in the array)
531 TDNN_prot : The numbers of the prototype units of each unit
532 <- (func) MEM_ERR : not enough Memory
533 OK : no problems
534 ******************************************************************************/
divideNet(pUnit globalUnits,pLayer globalLayers,int * TDNN_prot)535 int divideNet(pUnit globalUnits, pLayer globalLayers, int *TDNN_prot)
536 {
537 int unitNo, sourceNo; /* number of the unit and source unit */
538 int prototypeNo; /* number of the prototype unit */
539 pUnit unit, prot_unit; /* unit and prototype unit */
540 FlintType dummy, weight; /* link weights */
541 bool isTDNN; /* flag for TDNN networks */
542 int error; /* error code */
543 char *string; /* free variable */
544 int pos; /* free variable */
545
546 /* Testing if the network is a TDNN-network */
547 isTDNN = is_TDNN_net();
548
549 /* --------------------------------------------
550 * loading all Units and group them into Layers
551 */
552 unitNo = krui_getFirstUnit();
553 unit = globalUnits;
554
555 while (unitNo) {
556 unit->members = newList();
557 if (!unit->members) return (MEM_ERR);
558
559 /* TDNN-Units wich are not Prototype-Units are
560 * treated in a special way ...
561 */
562 if (isTDNN && !is_Prototype_Unit(unitNo) ) {
563 prototypeNo = get_Prototype_Unit(unitNo);
564 TDNN_prot[unitNo] = prototypeNo; /* fix the Number of the prototype Unit */
565 prot_unit = searchUnit(prototypeNo, globalUnits, &pos);
566 if (!prot_unit) return(ERR); /* prototype unit not found */
567 addList(prot_unit->members, unitNo);
568 unitNo = krui_getNextUnit();
569 continue; /* nothing else to do */
570 }
571
572 /*
573 * TDNN Prototype-Units are treated as normal units
574 */
575 unit->number = unitNo;
576 addList(unit->members, unitNo); /* the Prototype is also part of the member list */
577 TDNN_prot[unitNo] = unitNo; /* the prototype unit is his own prototype */
578
579 /* copy the entries from SNNS to the own format */
580 unit->act = krui_getUnitActivation(unitNo);
581 unit->type = krui_getUnitTType(unitNo);
582 unit->Bias = krui_getUnitBias(unitNo);
583
584 /* units always have a name (at least its old number) */
585 string = krui_getUnitName(unitNo);
586 if (NULL == string) {
587 unit->name = malloc(12 * sizeof(char));
588 if(! unit->name) {
589 return (MEM_ERR);
590 }
591 sprintf(unit->name, "Old: %d", unit->number);
592 }
593 else {
594 unit->name = malloc(MAX(1,strlen(string)+1));
595 if(! unit->name) {
596 return (MEM_ERR);
597 }
598 strcpy(unit->name, string);
599 }
600
601 unit->ActFunc = checkActFunc(krui_getUnitActFuncName(unitNo) );
602 if (unit->ActFunc < 0) return(WRONG_ACT_FUNC);
603
604 /* insert all Source units in the list */
605 unit->sources = newList();
606 if (!unit->sources) return (MEM_ERR);
607 sourceNo = krui_getFirstPredUnit(&dummy);
608 while (sourceNo) {
609 /* only special-hidden-neurons may have links to itself */
610 if ( (unit->type != SPECIAL_H) && !is_BPTT_net() ) {
611 if (unit->number == sourceNo) return(ILLEGAL_CYCLES);
612 }
613 if(addList(unit->sources, sourceNo)) return (MEM_ERR);
614 sourceNo = krui_getNextPredUnit(&dummy);
615 }
616 /* now the weights can be written in the right order */
617 /* One more Element is allocated, because the array might have size 0 */
618 unit->weights = (float *)malloc(NoOf(unit->sources) * sizeof(float) + sizeof(float));
619 if (!unit->weights) return(MEM_ERR);
620 sourceNo = krui_getFirstPredUnit(&weight);
621 while (sourceNo) {
622 pos = searchList(unit->sources, sourceNo);
623 unit->weights[pos] = weight;
624 sourceNo = krui_getNextPredUnit(&weight);
625 }
626 #ifdef debug
627 printUnit(unit);
628 #endif
629 error = searchLayer(unit, globalLayers);
630 if (error) return(error);
631
632 unit++;
633 unitNo = krui_getNextUnit();
634 }
635
636 return(OK);
637 }
638
639
640 /****************************************************************************
641 int prepareCpnUnits(pUnit globalUnits, pLayer global Layers, int NoOfLayers)
642 ---------------------------------------------------------------------------
643 calculates the entries in the Units, wich are necessary for CPN
644 -> globalUnits : all units of the net
645 globalLayers : all layers of the net
646 <- (func) MEM_ERR : Not enough memory
647 ERR : Error in structure of the Network
648 OK : No problems found
649 ****************************************************************************/
prepareCpnUnits(pUnit globalUnits,pLayer globalLayers)650 int prepareCpnUnits(pUnit globalUnits, pLayer globalLayers)
651 {
652 pLayer HiddenLayer, OutputLayer; /* pointer to the hidden and Output layer */
653 int memberNr, sourceNr, dummy; /* loop-variables */
654
655 /* CPN-Nets need a fixed architecture : */
656 if ( (globalLayers[0].type != INPUT)
657 || (globalLayers[1].type != HIDDEN)
658 || (globalLayers[2].type != OUTPUT)
659 || (globalLayers[3].members != NULL) /* there must not exist a forth layer */
660 ) {
661 return(NO_CPN);
662 }
663
664 /* better to read */
665 HiddenLayer = globalLayers + 1;
666 OutputLayer = HiddenLayer + 1;
667
668
669 for (memberNr = 0; memberNr < NoOf(HiddenLayer->members); memberNr++) {
670 pUnit unit = searchUnit(element(HiddenLayer->members, memberNr), globalUnits, &dummy);
671 if (unit == NULL) return (NO_TDNN);
672
673 if (NULL == (unit->dest = malloc(NoOf(OutputLayer->members))) ) {
674 return(MEM_ERR);
675 }
676 }
677
678 for (memberNr = 0; memberNr < NoOf(OutputLayer->members); memberNr++) {
679 pUnit dest = searchUnit(element(OutputLayer->members, memberNr), globalUnits, &dummy);
680 if (dest == NULL) return (NO_CPN);
681
682 /* Hiddenlayer and Outputlayer must be fully connected */
683 if (NoOf(dest->sources) != NoOf(HiddenLayer->members)) {
684 return(NO_CPN);
685 }
686
687 /* copy the weights to the hidden units */
688 for(sourceNr = 0; sourceNr < NoOf(dest->sources); sourceNr++) {
689 pUnit source = searchUnit(element(dest->sources,sourceNr), globalUnits, &dummy);
690 if (source == NULL) return (NO_CPN);
691 printUnit(source);
692 source->dest[memberNr] = dest->weights[sourceNr];
693 source->NoOfDest = NoOf(OutputLayer->members);
694 }
695 }
696
697 return(OK);
698 }
699
700
701 /****************************************************************************
702 int prepareTDNNunits(pUnit globalUnits, int *TDNN_prot)
703 ---------------------------------------------------------------------------
704 calculates the entries in the Units, wich are necessary for TDNNs
705 -> globalUnits : all units of the net
706 TDNN_prot : Array with the numbers of the needed prototypes
707 <- (func) MEM_ERR : Not enough memory
708 NO_TDNN : Error in structure of the Network
709 MEM_ERR : not enough memory
710 OK : No problems found
711 ****************************************************************************/
prepareTDNNunits(pUnit globalUnits,int * TDNN_prot)712 int prepareTDNNunits(pUnit globalUnits, int *TDNN_prot)
713 {
714 int sourceNo; /* Unit Number of the current source unit */
715 int protNo; /* Unit Number of the current prototype Unit */
716 pUnit unit; /* Current examined Unit */
717 pList ProtSources; /* List with the prototype source units */
718 int *countArray; /* Counters for the entries in the raws */
719 int raw; /* current raw in the weight matrix of a unit */
720 int listNo; /* Number of a list entry */
721 int i, delay;
722
723 countArray = malloc(sizeof(int)); /* necessary because of the reallocs */
724 if(! countArray) {
725 return MEM_ERR;
726 }
727
728 for(unit = globalUnits; unit->number != 0; unit++) { /* e.g. All Units */
729
730 ProtSources = newList(); /* An own list for each unit */
731 if(! ProtSources) {
732 free(countArray);
733 return MEM_ERR;
734 }
735
736 /* finding all Prototype Units in the source Units */
737 for (listNo = 0; listNo < NoOf(unit->sources); listNo++) {
738
739 sourceNo = element(unit->sources, listNo);
740
741 if (sourceNo == TDNN_prot[sourceNo]) { /* e.g. his own prototype */
742 addList(ProtSources, sourceNo);
743 }
744
745 }
746
747 if (NoOf(unit->sources) == 0) { /* Must be an input unit */
748 killList(ProtSources); /* e.g. has no sources and weights */
749 unit->FeatureWidth = 0;
750 unit->DelayLength = 0;
751 continue; /* so nothing to do */
752 }
753
754 /* A simple check (delay * width = Number of Sources) */
755 if ( (NoOf(unit->sources) % NoOf(ProtSources)) != 0 ) {
756 printf("Unit %d has wrong count of Source Units", unit->number);
757 return(NO_TDNN);
758 }
759
760 unit->FeatureWidth = NoOf(ProtSources);
761 unit->DelayLength = NoOf(unit->sources) / unit->FeatureWidth;
762
763 /* get Memory for the new data structures */
764 /* width := NoOf(ProtSources); Delay Length := delay */
765 countArray = (int *)realloc(countArray, NoOf(ProtSources) * sizeof(int) );
766 unit->TDNNsources = (int **)malloc(NoOf(ProtSources) * sizeof (int *) );
767 unit->TDNNweights = (float **)malloc(NoOf(ProtSources) * sizeof (float *) );
768
769 delay = unit->DelayLength;
770 for(i = 0; i < NoOf(ProtSources); i++) {
771 unit->TDNNsources[i] = (int *)malloc(delay * sizeof(int));
772 unit->TDNNweights[i] = (float *)malloc(delay * sizeof(float));
773 if(unit->TDNNweights[i] == NULL) return (MEM_ERR);
774 }
775
776 /** write New Datas **/
777 /* At first one Prototype Unit for each raw */
778 for(raw = 0; raw < NoOf(ProtSources); raw++) {
779 sourceNo = element(ProtSources, raw);
780 unit->TDNNsources[raw][0] = sourceNo;
781 countArray[raw] = 1;
782 }
783
784 /* Then writing the other weights and sources */
785 for(i = 0; i < NoOf(unit->sources); i++) {
786 sourceNo = element(unit->sources, i);
787 protNo = TDNN_prot[sourceNo];
788
789 /* Searching the raw with the Prototype unit */
790 for(raw = 0; raw < NoOf(ProtSources); raw++) {
791 if(unit->TDNNsources[raw][0] == protNo) break; /* Prototype Unit found */
792 }
793 if(unit->TDNNsources[raw][0] != protNo) {
794 printf("Prototype Unit (%d) of (%d) not found", protNo, sourceNo);
795 free(countArray);
796 return(NO_TDNN);
797 }
798
799 /* writing SourceNumber and weight */
800 if (sourceNo == protNo ) { /* Prototype Unit */
801 unit->TDNNweights[raw][0] = unit->weights[i];
802 }
803 else {
804 unit->TDNNsources[raw][countArray[raw]] = sourceNo;
805 unit->TDNNweights[raw][countArray[raw]] = unit->weights[i];
806 countArray[raw]++; /* one more entry */
807 }
808 }
809
810 killList(ProtSources);
811
812 }
813
814 free(countArray);
815 return(OK);
816 }
817
818 /****************************************************************************
819 char checkOrder(pLayer globalLayers, int x, int y)
820 ---------------------------------------------------------------------------
821 checks the order between layer x and layer y
822
823 SIDE-EFFECT : the entry SuccDelay is set up, if one layer follows
824 immediatly another. (needed by TDNN-networks)
825
826 -> globalLayers : all layers of the net
827 x, y : numbers of layer x and y
828 <- (func) -1 : layer x before layer y
829 0 : indifferent
830 1 : layer x after layer y
831 ILLEGAL_CYCLES : error occured (no order given)
832 ****************************************************************************/
checkOrder(pLayer globalLayers,int x,int y)833 signed char checkOrder(pLayer globalLayers, int x, int y)
834 {
835 /* preference of the unit type : low value means early update */
836 static char pref[12] = {0, 0, 2, 0, 1, 3, 3, 3, 3, 3, 3, 3};
837
838 signed char order = 0;
839
840 if (pref[globalLayers[x].type] < pref[globalLayers[y].type]) {
841 order = (signed char)-1; /* e.g. layer x before layer y */
842 }
843 else if (pref[globalLayers[x].type] > pref[globalLayers[y].type]) {
844 order = 1; /* e.g. layer x after layer y */
845 }
846
847 /* BPTT-Networks may contain any cycles so they must not be checked */
848 if (is_BPTT_net() ) {
849 return(order);
850 }
851
852 if (haveIntersection(globalLayers[x].sources, globalLayers[y].members) ) {
853 globalLayers[y].SuccDelay = globalLayers[x].delay; /* Side-Effect */
854 if (order == -1) {
855 if (SPECIAL_H != globalLayers[y].type) return (ILLEGAL_CYCLES);
856 }
857 else {
858 order = 1;
859 }
860 }
861 if (haveIntersection(globalLayers[x].members, globalLayers[y].sources) ) {
862 globalLayers[x].SuccDelay = globalLayers[y].delay; /* Side-Effect */
863 if (order == 1) {
864 if (SPECIAL_H != globalLayers[x].type) return (ILLEGAL_CYCLES);
865 }
866 else {
867 order = (signed char)-1;
868 }
869 }
870
871 return(order);
872 }
873
874
875 /*****************************************************************************
876 int sortNet(pLayer globalLayers, int NoOfLayers, int *order)
877 ----------------------------------------------------------------------------
878 calculates the order between the globalLayers an returns it in the array
879 order. So the first number in the array is the first Layer to be updated
880 and so on.
881 -> globalLayers : Array of all layers in the net
882 NoOfLayers : Number of all layers in the net
883 <- order : the order for updating the layers
884 (func) OK : no errors occured
885 MEM_ERR : not enough memory for calculations
886 *****************************************************************************/
sortNet(pLayer globalLayers,int NoOfLayers,int * order)887 int sortNet(pLayer globalLayers, int NoOfLayers, int *order)
888 {
889 char **matrix; /* precedence matrix */
890 char *mask; /* already chosen layers */
891 int i, j, x, y, ord, isSource = TRUE;
892 char precedence;
893
894 /* reserve memory for all the arrays and matrices */
895 matrix = (char **)malloc(NoOfLayers * sizeof(char *) );
896 if (!matrix) return (MEM_ERR);
897
898 for (i = 0; i < NoOfLayers; i++) {
899 matrix[i] = (char *)calloc(NoOfLayers, sizeof(char) );
900 if (!matrix[i]) return (MEM_ERR);
901 }
902
903 mask = (char *)calloc(NoOfLayers, sizeof(char) );
904 if (!mask) {
905 free(matrix);
906 return (MEM_ERR);
907 }
908
909 /** build the precedence matrix of the Layer-Graph */
910 for (y = 0; y < NoOfLayers; y++) {
911 for (x = y + 1; x < NoOfLayers; x++) {
912 precedence = checkOrder(globalLayers, x, y);
913 if (precedence == ILLEGAL_CYCLES) return(ILLEGAL_CYCLES);
914
915 matrix[x][y] = precedence;
916 matrix[y][x] = -precedence;
917
918 } /* for x */
919
920 } /* for y */
921
922 #ifdef debug
923 printf("\nPrecedence Matrix is:\n");
924 for (y = 0; y < NoOfLayers; y++) {
925 for (x = 0; x < NoOfLayers; x++) {
926 printf("%3d ", matrix[y][x]);
927 }
928 printf("\n");
929 }
930 #endif
931
932 /** put the Layers in the right order **/
933 for (ord = 0; ord < NoOfLayers; ord++) {
934
935 for (i = 0; i < NoOfLayers; i++) {
936 if (mask[i]) continue; /* Layer already chosen */
937
938 isSource = TRUE;
939 for (j = 0; j < NoOfLayers; j++) {
940 /* exists a layer wich must be updated before ? */
941 if (matrix[i][j] == 1) {
942 isSource = FALSE;
943 break;
944 }
945 }
946
947 if (isSource) {
948 order[ord] = i; /* the number of the Layer becomes ord */
949 mask[i] = 1; /* must not test this Layer again */
950
951 for (j = 0; j < NoOfLayers; j++) {
952 matrix[j][i] = 0; /* clear depencies for other Layers */
953 }
954
955 break; /* find next Layer */
956 }
957
958 } /* for i */
959
960 if (!isSource) {
961 return(ILLEGAL_CYCLES);
962 }
963
964 } /* for ord */
965
966 for (i = 0; i < NoOfLayers; i++) {
967 free(matrix[i]);
968 }
969 free(matrix);
970 free(mask);
971
972 #ifdef debug
973 printf("\nLayers sorted in following order :\n");
974 for (i = 0; i < NoOfLayers; i++) {
975 printf(" %d", order[i]);
976 }
977 printf("\n");
978 #endif
979
980 return(OK);
981 }
982
983
984 /*****************************************************************************
985 void writeList(pList list, FILE *fOutFile)
986 ----------------------------------------------------------------------------
987 writes a List to a OutputFile in the Form :
988 { <element1>, <element2>, ... }
989 -> list : pointer to the list wich is to be written
990 fOutFile : appreciated output stream
991 *****************************************************************************/
writeList(pList list,FILE * fOutFile)992 void writeList(pList list, FILE *fOutFile)
993 {
994 int e; /* (like element) Element counter for the list */
995
996 fprintf(fOutFile, "{");
997 if (0 == NoOf(list) ) fprintf(fOutFile, "0 /*NO MEMBERS */");
998 for(e = 0; e < NoOf(list); e++) {
999 fprintf(fOutFile, "%d", element(list, e) );
1000 if (e < NoOf(list) - 1) fprintf(fOutFile, ", ");
1001 }
1002 fprintf(fOutFile, "}");
1003 }
1004
1005
1006 /*****************************************************************************
1007 void writeLayer(pLayer layer, FILE *fOutFile)
1008 ----------------------------------------------------------------------------
1009 writes the LayerName and his members as an array of integers to the
1010 given OutputStream
1011 -> layer : layer wich is to be written
1012 LayerName : a C-identifier for the struct
1013 fOutFile : appreciated output stream
1014 *****************************************************************************/
writeLayer(pLayer layer,FILE * fOutFile)1015 void writeLayer(pLayer layer, FILE *fOutFile)
1016 {
1017 int i;
1018
1019 fprintf(fOutFile, "\n static pUnit %s[%d] = ",
1020 layer->name, NoOf(layer->members) );
1021
1022 /* write the Members of the layer */
1023 fprintf(fOutFile, "{");
1024 for(i = 0; i < NoOf(layer->members); i++) {
1025 /* write the members as pointer to the member units */
1026 fprintf(fOutFile, "Units + %d", element(layer->members,i) );
1027 if (i < NoOf(layer->members) - 1) fprintf(fOutFile, ", ");
1028 }
1029
1030 fprintf(fOutFile, "}; /* members */\n");
1031 }
1032
1033 /*****************************************************************************
1034 void writeUnitNew(pUnit unit, FILE *fOutFile)
1035 ----------------------------------------------------------------------------
1036 writes a Unit ( activation, bias, sources, Linkweights) as a struct to the
1037 Outfile
1038 -> unit : unit wich is to be written
1039 fOutFile : appreciated output stream
1040 Autor : Matthias Oberdorfer
1041 *****************************************************************************/
writeUnitNew(pUnit unit,FILE * fOutFile,int count_links)1042 void writeUnitNew(pUnit unit, FILE *fOutFile, int count_links)
1043 {
1044
1045 static int first_time = 1, is_Bptt = 0; /* to avoid unneeded procedure calls */
1046
1047 /* initialisation of is_Bptt */
1048 if (first_time) {
1049 is_Bptt = is_BPTT_net();
1050 first_time = 0;
1051 }
1052
1053 /* write Number and Name of the unit for identification,
1054 * if a user is reading the code
1055 */
1056 fprintf(fOutFile, " { /* unit %d (%s) */\n", unit->number, unit->name);
1057
1058 /* write Activation, Bias and number of sources */
1059 if (is_Bptt) {
1060 fprintf(fOutFile, " {%f, 0.0}, %f, %d,\n",
1061 unit->act, unit->Bias, NoOf(unit->sources));
1062 }
1063 else {
1064 fprintf(fOutFile, " 0.0, %f, %d,\n",unit->Bias, NoOf(unit->sources));
1065 }
1066
1067 /* write the Sources of the unit */
1068 fprintf(fOutFile, " &Sources[%d] , \n", count_links);
1069 /* write the weights of the units */
1070 fprintf(fOutFile, " &Weights[%d] , \n", count_links);
1071
1072 fprintf(fOutFile, " }");
1073 }
1074
1075 /*****************************************************************************
1076 void writeUnit(pUnit unit, FILE *fOutFile)
1077 ----------------------------------------------------------------------------
1078 writes a Unit ( activation, bias, sources, Linkweights) as a struct to the
1079 Outfile
1080 -> unit : unit wich is to be written
1081 fOutFile : appreciated output stream
1082 *****************************************************************************/
writeUnit(pUnit unit,FILE * fOutFile)1083 void writeUnit(pUnit unit, FILE *fOutFile)
1084 {
1085 int i;
1086 static int first_time = 1, is_Bptt = 0; /* to avoid unneeded procedure calls */
1087
1088 /* initialisation of is_Bptt */
1089 if (first_time) {
1090 is_Bptt = is_BPTT_net();
1091 first_time = 0;
1092 }
1093
1094 /* write Number and Name of the unit for identification, if a user is reading the code */
1095 fprintf(fOutFile, " { /* unit %d (%s) */\n", unit->number, unit->name);
1096
1097 /* write Activation, Bias and number of sources */
1098 if (is_Bptt) {
1099 fprintf(fOutFile, " {%f, 0.0}, %f, %d,\n",
1100 unit->act, unit->Bias, NoOf(unit->sources));
1101 }
1102 else {
1103 fprintf(fOutFile, " 0.0, %f, %d,\n",unit->Bias, NoOf(unit->sources));
1104 }
1105
1106 /* write the Sources of the unit */
1107 fprintf(fOutFile, " {");
1108 /* There should be at least one element in the list */
1109 if (NoOf(unit->sources) == 0) fprintf(fOutFile, "NULL /* no source units */");
1110 for(i = 0; i < NoOf(unit->sources); i++) {
1111 /* write the sources as pointer to the source units */
1112 fprintf(fOutFile, "Units + %d", element(unit->sources,i) );
1113 if (i < NoOf(unit->sources) - 1) fprintf(fOutFile, ", ");
1114 }
1115 fprintf(fOutFile, "},\n");
1116
1117 /* write the weights of the units */
1118 fprintf(fOutFile, " {");
1119 /* ANSI-C needs at least one entry in an array */
1120 if (0 == NoOf(unit->sources) ) fprintf(fOutFile, "0.0 /* NO MEMBERS */");
1121
1122 for(i = 0; i < NoOf(unit->sources); i++) {
1123 fprintf(fOutFile, "%f", unit->weights[i]);
1124 if (i < NoOf(unit->sources) - 1) fprintf(fOutFile, ", ");
1125 }
1126
1127 fprintf(fOutFile, "}\n }");
1128 }
1129
1130
1131 /*****************************************************************************
1132 void writeCpnUnit(pUnit unit, FILE *fOutFile)
1133 ----------------------------------------------------------------------------
1134 writes a CPN Unit ( activation, bias, sources, Linkweights, dest) as a struct to the
1135 Outfile
1136 -> unit : unit wich is to be written
1137 fOutFile : appreciated output stream
1138 *****************************************************************************/
writeCpnUnit(pUnit unit,FILE * fOutFile)1139 void writeCpnUnit(pUnit unit, FILE *fOutFile)
1140 {
1141 int i;
1142
1143 /* output-units are dummy-units */
1144 if (unit->type == OUTPUT) {
1145 fflush(fOutFile);
1146 fprintf(fOutFile, CpnDummyUnit);
1147 fflush(fOutFile);
1148 return;
1149 }
1150
1151 /* write Number and Name of the unit for identification, if a user is reading the code */
1152 fprintf(fOutFile, " { /* unit %d (%s) */\n", unit->number, unit->name);
1153
1154 /* write Activation, Bias and number of sources */
1155 fprintf(fOutFile, " 0.0, %f, %d,\n",unit->Bias, NoOf(unit->sources));
1156
1157 /* write the Sources of the unit */
1158 fprintf(fOutFile, " {");
1159 /* There should be at least one element in the list */
1160 if ((NoOf(unit->sources) == 0) || (unit->type == OUTPUT) ){
1161 fprintf(fOutFile, "NULL /* no source units */");
1162 }
1163 for(i = 0; i < NoOf(unit->sources); i++) {
1164 /* write the sources as pointer to the source units */
1165 fprintf(fOutFile, "Units + %d", element(unit->sources,i) );
1166 if (i < NoOf(unit->sources) - 1) fprintf(fOutFile, ", ");
1167 }
1168 fprintf(fOutFile, "},\n");
1169
1170 /* write the weights of the units */
1171 fprintf(fOutFile, " {");
1172 /* ANSI-C needs at least one entry in an array */
1173 if (0 == NoOf(unit->sources) ) fprintf(fOutFile, "0.0 /* NO MEMBERS */");
1174
1175 for(i = 0; i < NoOf(unit->sources); i++) {
1176 fprintf(fOutFile, "%f", unit->weights[i]);
1177 if (i < NoOf(unit->sources) - 1) fprintf(fOutFile, ", ");
1178 }
1179 fprintf(fOutFile, "},\n");
1180
1181 /* write the weights from hidden to the output */
1182 if (unit->type == INPUT) { /* inputs haven't such weights */
1183 fprintf(fOutFile, " {0.0}\n");
1184 }
1185 else {
1186 fprintf(fOutFile, " {");
1187 for(i = 0; i < unit->NoOfDest; i++) {
1188 fprintf(fOutFile, "%f", unit->dest[i]);
1189 if (i < unit->NoOfDest - 1) fprintf(fOutFile, ", ");
1190 }
1191 fprintf(fOutFile, "}\n");
1192 }
1193 fprintf(fOutFile, " }");
1194 }
1195
1196
1197 /*****************************************************************************
1198 void writeTdnnUnit(pUnit unit, FILE *fOutFile)
1199 ----------------------------------------------------------------------------
1200 writes a TdnnUnit ( activation, bias, sources, Linkweights)
1201 as a struct to the Outfile
1202 -> unit : unit wich is to be written
1203 Units : pointer to the global UnitArray
1204 fOutFile : appreciated output stream
1205 *****************************************************************************/
writeTdnnUnit(pUnit unit,pUnit Units,FILE * fOutFile)1206 void writeTdnnUnit(pUnit unit, pUnit Units, FILE *fOutFile)
1207 {
1208 int feature, delay, sourceIndex, pos;
1209
1210 /* write Number and Name of the unit for identification by a user */
1211 fprintf(fOutFile, " { /* unit %d (%s) */\n", unit->index, unit->name);
1212
1213 /* write Activation, Bias and number of sources */
1214 fprintf(fOutFile, " {");
1215 for (delay = 1; delay < unit->NoOf(members); delay++) fprintf(fOutFile, "0.0, ");
1216 fprintf(fOutFile, "0.0}, %f, %d,",unit->Bias, unit->FeatureWidth);
1217
1218 /* write the Sources of the Unit */
1219 fprintf(fOutFile, "\n {");
1220
1221 /* ANSI-C needs at least one entry in an array */
1222 if (0 == NoOf(unit->sources) ) fprintf(fOutFile, "NULL /* NO SOURCES */");
1223
1224 for(feature = 0; feature < unit->FeatureWidth; feature++) {
1225 sourceIndex = searchUnit(unit->TDNNsources[feature][0], Units, &pos)->index;
1226 fprintf(fOutFile, "Units + %d", sourceIndex);
1227 if (feature < unit->FeatureWidth - 1) fprintf(fOutFile, ", ");
1228 }
1229 fprintf(fOutFile, "},\n");
1230
1231
1232 /* write the weights to the source units */
1233 fprintf(fOutFile, " {");
1234
1235 /* ANSI-C needs at least one entry in an array */
1236 if (0 == NoOf(unit->sources) ) fprintf(fOutFile, " {0.0} /* NO WEIGHTS */");
1237
1238 for(feature = 0; feature < unit->FeatureWidth; feature++) {
1239 fprintf(fOutFile, "\n {");
1240
1241 for(delay = 0; delay < unit->DelayLength; delay++) {
1242 fprintf(fOutFile, "%f", unit->TDNNweights[feature][delay]);
1243 if (delay < unit->DelayLength - 1) fprintf(fOutFile, ", ");
1244 }
1245
1246 fprintf(fOutFile, "}");
1247 if (feature < unit->FeatureWidth - 1) fprintf(fOutFile, ", ");
1248 }
1249 fprintf(fOutFile, "\n }\n }");
1250
1251 fflush(fOutFile);
1252 }
1253
1254
1255
1256 /*****************************************************************************
1257 void writeAllUnitsOld(pUnit Units, int NoOfUnits, FILE *fOutFile)
1258 ----------------------------------------------------------------------------
1259 writes all Units of the Net as an array of structs to the OutputFile
1260 -> pUnits : array of all units of the net
1261 NoOfUnits : #units in the net
1262 fOutFile : appreciated output stream
1263 *****************************************************************************/
writeAllUnitsOld(pUnit Units,int NoOfUnits,FILE * fOutFile)1264 void writeAllUnitsOld(pUnit Units, int NoOfUnits, FILE *fOutFile)
1265 {
1266 int nr;
1267
1268 fprintf(fOutFile, " /* unit definition section (see also UnitType) */\n");
1269
1270 /* Writing declaration of the Unit-Array */
1271 /* the 0-Element is left free because the comiler was easier
1272 * to implement this way. The only exeptions are the TDNNs
1273 * because here the Units are rewritten completely */
1274 if (is_TDNN_net()) {
1275 fprintf(fOutFile,
1276 " static UnitType Units[%d] = \n {\n", NoOfUnits
1277 );
1278 }
1279 else if (is_CPN_net() ){
1280 fflush(fOutFile);
1281 fprintf(fOutFile,
1282 " static UnitType Units[%d] = \n {\n %s,\n",
1283 NoOfUnits + 1, CpnDummyUnit
1284 );
1285 fflush(fOutFile);
1286 }
1287 else if (is_BPTT_net() ) {
1288 fprintf(fOutFile,
1289 " static UnitType Units[%d] = \n {\n %s,\n",
1290 NoOfUnits + 1,
1291 "{ {0.0, 0.0}, 0.0, 0, {NULL /* NO SOURCES */}, {0.0 /* NO MEMBERS*/} }"
1292 );
1293 }
1294 else {
1295 fprintf(fOutFile,
1296 " static UnitType Units[%d] = \n {\n %s,\n",
1297 NoOfUnits + 1,
1298 "{ 0.0, 0.0, 0, {NULL /* NO SOURCES */}, {0.0 /* NO MEMBERS*/} }"
1299 );
1300 }
1301
1302 /* Because of the special requirements of each network-type
1303 * the Unit types are slightly modified for each update-function.
1304 * so they need a special output-template */
1305 if (is_TDNN_net() ) {
1306 for(nr = 0; nr < NoOfUnits; nr++) {
1307 writeTdnnUnit(Units + nr, Units, fOutFile);
1308 if (nr < NoOfUnits -1) fprintf(fOutFile, ",\n");
1309 else fprintf(fOutFile, "\n");
1310 }
1311 }
1312 else if(is_CPN_net() ) {
1313 for(nr = 0; nr < NoOfUnits; nr++) {
1314 if (nr != 0) {
1315 fprintf(fOutFile, ",\n");
1316 }
1317 writeCpnUnit(Units + nr, fOutFile);
1318 }
1319 fprintf(fOutFile, "\n");
1320 }
1321 /* Here also BPTT-units are included, because they are very similar to
1322 the other types */
1323 else {
1324 for(nr = 0; nr < NoOfUnits; nr++) {
1325 writeUnit(Units + nr, fOutFile);
1326 if (nr < NoOfUnits -1) fprintf(fOutFile, ",\n");
1327 else fprintf(fOutFile, "\n");
1328 }
1329 }
1330 fprintf(fOutFile, "\n };\n\n");
1331 }
1332
1333 /*****************************************************************************
1334 void writeAllUnits(pUnit Units, int NoOfUnits, FILE *fOutFile)
1335 ----------------------------------------------------------------------------
1336 writes all Units of the Net as an array of structs to the OutputFile
1337 -> pUnits : array of all units of the net
1338 NoOfUnits : #units in the net
1339 fOutFile : appreciated output stream
1340 Autor : Matthias Oberdorfer (changed original)
1341 *****************************************************************************/
writeAllUnits(pUnit Units,int NoOfUnits,FILE * fOutFile)1342 void writeAllUnits(pUnit Units, int NoOfUnits, FILE *fOutFile)
1343 {
1344 int nr;
1345 int count_links; /* to give number to links */
1346
1347 fprintf(fOutFile, " /* unit definition section (see also UnitType) */\n");
1348
1349 /* Writing declaration of the Unit-Array */
1350 /* the 0-Element is left free because the comiler was easier
1351 * to implement this way. The only exeptions are the TDNNs
1352 * because here the Units are rewritten completely */
1353 if (is_TDNN_net()) {
1354 fprintf(fOutFile,
1355 " static UnitType Units[%d] = \n {\n", NoOfUnits
1356 );
1357 }
1358 else if (is_CPN_net() ){
1359 fflush(fOutFile);
1360 fprintf(fOutFile,
1361 " static UnitType Units[%d] = \n {\n %s,\n",
1362 NoOfUnits + 1, CpnDummyUnit
1363 );
1364 fflush(fOutFile);
1365 }
1366 else if (is_BPTT_net() ) {
1367 fprintf(fOutFile,
1368 " static UnitType Units[%d] = \n {\n %s,\n",
1369 NoOfUnits + 1,
1370 "{ {0.0, 0.0}, 0.0, 0, {NULL /* NO SOURCES */}, {0.0 /* NO MEMBERS*/} }"
1371 );
1372 }
1373 else {
1374
1375 fprintf(fOutFile,
1376 " static UnitType Units[%d] = \n {\n %s,\n",
1377 NoOfUnits + 1,
1378 "{ 0.0, 0.0, 0, NULL , NULL }"
1379 /* old "{ 0.0, 0.0, 0, {NULL * NO SOURCES *}, {0.0 * NO MEMBERS*} }" */
1380 );
1381 }
1382
1383 /* Because of the special requirements of each network-type
1384 * the Unit types are slightly modified for each update-function.
1385 * so they need a special output-template */
1386 if (is_TDNN_net() ) {
1387 for(nr = 0; nr < NoOfUnits; nr++) {
1388 writeTdnnUnit(Units + nr, Units, fOutFile);
1389 if (nr < NoOfUnits -1) fprintf(fOutFile, ",\n");
1390 else fprintf(fOutFile, "\n");
1391 }
1392 }
1393 else if(is_CPN_net() ) {
1394 for(nr = 0; nr < NoOfUnits; nr++) {
1395 if (nr != 0) {
1396 fprintf(fOutFile, ",\n");
1397 }
1398 writeCpnUnit(Units + nr, fOutFile);
1399 }
1400 fprintf(fOutFile, "\n");
1401 }
1402 /* Here also BPTT-units are included, because they are very similar to
1403 the other types */
1404 else {
1405 count_links = 0; /* no links yet */
1406
1407 for(nr = 0; nr < NoOfUnits; nr++) {
1408 writeUnitNew(Units + nr, fOutFile, count_links);
1409 count_links += NoOf((Units+nr)->sources);
1410 /* old writeUnit(Units + nr, fOutFile); */
1411 if (nr < NoOfUnits -1) fprintf(fOutFile, ",\n");
1412 else fprintf(fOutFile, "\n");
1413 }
1414 }
1415 fprintf(fOutFile, "\n };\n\n");
1416 }
1417
1418 /*****************************************************************************
1419 void writeForwardDeclarationAllUnits(pUnit Units, int NoOfUnits, FILE *fOutFile)
1420 ----------------------------------------------------------------------------
1421 writes for all Units of the Net an forward decl. array of structs to the OutputFile
1422 -> pUnits : array of all units of the net
1423 NoOfUnits : #units in the net
1424 fOutFile : appreciated output stream
1425 Autor : Matthias Oberdorfer
1426 *****************************************************************************/
writeForwardDeclarationAllUnits(pUnit Units,int NoOfUnits,FILE * fOutFile)1427 void writeForwardDeclarationAllUnits(pUnit Units, int NoOfUnits, FILE *fOutFile)
1428 {
1429
1430 fprintf(fOutFile, " /* Forward Declaration for all unit types */\n");
1431
1432 /* Writing declaration of the Unit-Array */
1433 /* the 0-Element is left free because the comiler was easier
1434 * to implement this way. The only exeptions are the TDNNs
1435 * because here the Units are rewritten completely */
1436 if (is_TDNN_net()) {
1437 fprintf(fOutFile,
1438 " static UnitType Units[%d];\n", NoOfUnits
1439 );
1440 }
1441 else if (is_CPN_net() ){
1442 fflush(fOutFile);
1443 fprintf(fOutFile,
1444 " static UnitType Units[%d];\n",
1445 NoOfUnits + 1
1446 );
1447 fflush(fOutFile);
1448 }
1449 else if (is_BPTT_net() ) {
1450 fprintf(fOutFile,
1451 " static UnitType Units[%d];\n",
1452 NoOfUnits + 1
1453 );
1454 }
1455 else {
1456 fprintf(fOutFile,
1457 " static UnitType Units[%d];\n",
1458 NoOfUnits + 1
1459 );
1460 }
1461 }
1462
1463 /***************************************************************************
1464 int writeSource(pUnit unit, FILE *fOutFile)
1465 ----------------------------------------------------------------------------
1466 help-function for writeAllSources
1467 Autor : Matthias Oberdorfer
1468 ****************************************************************************/
writeSource(pUnit unit,FILE * fOutFile)1469 int writeSource(pUnit unit, FILE *fOutFile)
1470 {
1471 int i;
1472 /* There should be at least one element in the list */
1473 for(i = 0; i < NoOf(unit->sources); i++)
1474 {
1475 /* write the sources as pointer to the source units */
1476 fprintf(fOutFile, "Units + %d, ", element(unit->sources,i) );
1477 if(!((i+1) % 10) )
1478 fprintf(fOutFile, "\n");
1479 }
1480 return i;
1481 }
1482
1483 /*****************************************************************************
1484 void writeAllSources(pUnit Units, int NoOfUnits, FILE *fOutFile)
1485 ----------------------------------------------------------------------------
1486 writes all Units of the Net as an array of structs to the OutputFile
1487 -> pUnits : array of all units of the net
1488 NoOfUnits : #units in the net
1489 fOutFile : appreciated output stream
1490 Autor : Matthias Oberdorfer
1491 *****************************************************************************/
1492
writeAllSources(pUnit Units,int NoOfUnits,FILE * fOutFile)1493 void writeAllSources(pUnit Units, int NoOfUnits, FILE *fOutFile)
1494 {
1495 int nr;
1496
1497 fprintf(fOutFile, " /* Sources definition section */\n");
1498 fprintf(fOutFile, " static pUnit Sources[] = {\n");
1499
1500 for(nr = 0; nr < NoOfUnits; nr++)
1501 {
1502 if(writeSource(Units + nr, fOutFile))
1503 fprintf(fOutFile, "\n");
1504 }
1505 fprintf(fOutFile, "\n };\n\n");
1506 }
1507
1508 /***************************************************************************
1509 int writeWeigths(pUnit unit, FILE *fOutFile)
1510 ---------------------------------------------------------------------------
1511 help-function for writeAllWeigths
1512 Autor: Matthias Oberdorfer
1513 ****************************************************************************/
1514
writeWeigths(pUnit unit,FILE * fOutFile)1515 int writeWeigths(pUnit unit, FILE *fOutFile)
1516 {
1517 int i;
1518 /* ANSI-C needs at least one entry in an array */
1519 for(i = 0; i < NoOf(unit->sources); i++)
1520 {
1521 fprintf(fOutFile, "%f, ", unit->weights[i]);
1522 if(!((i+1) % 10) )
1523 fprintf(fOutFile, "\n");
1524 }
1525 return i;
1526 }
1527
1528 /*****************************************************************************
1529 void writeAllWeigths(pUnit Units, int NoOfUnits, FILE *fOutFile)
1530 ----------------------------------------------------------------------------
1531 writes all Units of the Net as an array of structs to the OutputFile
1532 -> pUnits : array of all units of the net
1533 NoOfUnits : #units in the net
1534 fOutFile : appreciated output stream
1535 Autor : Matthias Oberdorfer
1536 *****************************************************************************/
1537
writeAllWeights(pUnit Units,int NoOfUnits,FILE * fOutFile)1538 void writeAllWeights(pUnit Units, int NoOfUnits, FILE *fOutFile)
1539 {
1540 int nr;
1541
1542 fprintf(fOutFile, " /* Weigths definition section */\n");
1543 fprintf(fOutFile, " static float Weights[] = {\n");
1544
1545 for(nr = 0; nr < NoOfUnits; nr++)
1546 {
1547 if( writeWeigths(Units + nr, fOutFile))
1548 fprintf(fOutFile, "\n");
1549 }
1550 fprintf(fOutFile, "\n };\n\n");
1551 }
1552
1553 /***************************************************************************
1554 int NameLayers(pLayer globalLayers, int NoOfLayers)
1555 --------------------------------------------------------------------------
1556 name the Layers of the Net
1557 -> globalLayers : all layers of the net
1558 NoOfLayers : #layers of the net
1559 <- (func) OK : no errors
1560 MEM_ERR : not enough memory
1561 ***************************************************************************/
NameLayers(pLayer globalLayers,int NoOfLayers)1562 int NameLayers(pLayer globalLayers, int NoOfLayers)
1563 {
1564 #define NAME_LENGTH 11
1565
1566 int nr;
1567 int hcounter = 0, ocounter = 0, scounter =0;
1568 pLayer layer = NULL;
1569
1570 for(nr = 0; nr < NoOfLayers; nr++) {
1571 layer = (globalLayers + nr);
1572 layer->name = (char *)malloc(NAME_LENGTH * sizeof(char) );
1573 if (!(layer->name)) return(MEM_ERR);
1574
1575 switch( (globalLayers + nr)->type) {
1576 case INPUT : sprintf(layer->name, "Input");
1577 break;
1578
1579 case OUTPUT : sprintf(layer->name, "Output%d", ++ocounter);
1580 break;
1581
1582 case HIDDEN : sprintf(layer->name, "Hidden%d", ++hcounter);
1583 break;
1584
1585 default : sprintf(layer->name, "Special%d", ++scounter);
1586 }
1587
1588 }
1589
1590 return(OK);
1591 }
1592
1593
1594 /*****************************************************************************
1595 int writeTdnnNet(pLayer globalLayers, pUnit globalUnits,
1596 int NoOfLayers, int NoOfUnits,
1597 int *order, char *OutFile)
1598 ----------------------------------------------------------------------------
1599 writes a Net wich is discribed by globalLayers and globalUnits in the File
1600 named <OutFile>.
1601 The order for updating the Layers is discribed in order and in the single
1602 Layers there is a set of unit-numbers, wich will be updated when its the turn
1603 of the layer.
1604 -> globalLayers : all Layers of the Net
1605 -> globalUnits : all Units of the Net
1606 -> NoOfLayers : #Layers in the Net
1607 -> NoOfUnits : #Units in the Net
1608 -> order : in wich order the Layers have to be updated
1609 -> OutFile : Name of the Output-File
1610 <- (func) OK : no errors occured
1611 MEM_ERR : not enough memory
1612 CANT_OPEN : could not open the output-file
1613 ******************************************************************************/
writeTdnnNet(pLayer globalLayers,pUnit globalUnits,int NoOfLayers,int NoOfUnits,int * order,char * OutFile,char * ProcName)1614 int writeTdnnNet(pLayer globalLayers, pUnit globalUnits,
1615 int NoOfLayers, int NoOfUnits,
1616 int *order, char *OutFile, char *ProcName)
1617 {
1618 pLayer layer, source;
1619 pUnit unit;
1620 int nr, layerNo, unitNo, sourceNo, pos, maxSource = 0,
1621 maxFeature = 0, maxDelay = 0, maxTotalDelay = 0;
1622 FILE *fOutFile, *fHeaderFile;
1623 pList OutList, FunctionList;
1624 time_t timer;
1625 char HeaderFile[50];
1626
1627 /* calculate time for the date in the header of the output file */
1628 time(&timer);
1629
1630 /* Preparations for the Header-File */
1631 strcpy(HeaderFile, OutFile);
1632 HeaderFile[strlen(HeaderFile) - 1] = 'h';
1633 fHeaderFile = fopen(HeaderFile, "w");
1634 if (!fHeaderFile) return(CANT_OPEN);
1635
1636 /* prepare Output Stream */
1637 fOutFile = fopen(OutFile, "w");
1638 if (!fOutFile) return(CANT_OPEN);
1639
1640 /* maxSource is needed for writing the Unit-array */
1641 for(unit = globalUnits; unit < globalUnits + NoOfUnits; unit++) {
1642 maxSource = MAX(maxSource, NoOf(unit->sources) );
1643 /* Calculating the Maximum Feature-Width is harmless for non-TDNNs */
1644 maxFeature = MAX(maxFeature, unit->FeatureWidth);
1645 }
1646
1647 /* TDNN needs the Maximum Receptive Field */
1648 for(layer = globalLayers; layer < globalLayers + NoOfLayers; layer++) {
1649 maxDelay = MAX(maxDelay, layer->delay);
1650 maxTotalDelay = MAX(maxTotalDelay, layer->TotalDelay);
1651 }
1652
1653 /* Net-Output may consist of several (output) Layers */
1654 /* so there must be an extra merge-list : OutList */
1655 /* FunctionList will contain a set of all used functions */
1656 OutList = newList();
1657 if (!OutList) return (MEM_ERR);
1658
1659 FunctionList = newList();
1660 if (!FunctionList) return (MEM_ERR);
1661
1662 for(nr = 0; nr < NoOfLayers; nr ++)
1663 {
1664 layer = globalLayers + nr;
1665 if( layer->type == OUTPUT)
1666 {
1667 if (mergeList(OutList, layer->members) ) return (MEM_ERR);
1668 }
1669 else
1670 if (addList(FunctionList, layer->ActFunc) ) return(MEM_ERR);
1671 }
1672
1673 /** find Names for the Layers **/
1674 if (NameLayers(globalLayers, NoOfLayers+1)) return(MEM_ERR);
1675
1676
1677 /* ------------------------------------------------------------
1678 Beginning of the output-functions
1679 ------------------------------------------------------------ */
1680
1681 /** write Header-File **/
1682 fprintf(fHeaderFile, TdnnHeaderFileTemplate,
1683 HeaderFile, ctime(&timer), ProcName,
1684 ProcName, NoOf(globalLayers[order[0]].members),
1685 NoOf(OutList), globalLayers[order[0]].TotalDelay,
1686 ProcName);
1687 fclose(fHeaderFile);
1688
1689 /** write the Programm Header and Act-Functions **/
1690 fprintf(fOutFile, ProgHeader, OutFile, ctime(&timer) );
1691 for(nr = 0; nr < NoOf(FunctionList); nr ++) {
1692 fprintf(fOutFile, "%s\n", ACT_FUNCTIONS[element(FunctionList, nr)]);
1693 }
1694 /* to avoid unneeded include-files */
1695 fprintf(fOutFile, "#ifndef NULL\n");
1696 fprintf(fOutFile, "#define NULL (void *)0\n");
1697 fprintf(fOutFile, "#endif\n");
1698
1699 /* write Procedure-Header */
1700 fprintf(fOutFile, ProcHeader, ProcName);
1701
1702 /* if more than one net is included in the application,
1703 the types must be defined local to the procedure. So
1704 it's done generally */
1705 fprintf(fOutFile, TdnnTypeTemplate, maxTotalDelay,
1706 maxFeature, maxFeature, maxDelay);
1707
1708
1709 /* The Delays of the TDNN are organized as a ring-buffer
1710 e.g they needs a variable for the current number */
1711 for (layerNo = 0; layerNo < NoOfLayers; layerNo++) {
1712 layer = (globalLayers + layerNo);
1713
1714 /* one variable for the current read Position */
1715 layer->readCounter = malloc( (strlen(layer->name) + 11) * sizeof (char) );
1716 if (NULL == layer->readCounter) return(MEM_ERR);
1717 sprintf(layer->readCounter, "%sReadCounter", layer->name);
1718
1719 /* and one for the current write position */
1720 layer->writeCounter = malloc( (strlen(layer->name) + 12) * sizeof (char) );
1721 if (NULL == layer->writeCounter) return(MEM_ERR);
1722 sprintf(layer->writeCounter, "%sWriteCounter", layer->name);
1723
1724 /* write buffer-variables and their initialisation */
1725 fprintf(fOutFile, " static int %s = %d, %s = %d; \n",
1726 layer->readCounter, layer->TotalDelay - layer->SuccDelay,
1727 layer->writeCounter, layer->TotalDelay - 1);
1728 }
1729 /* a counter for the pattern is also needed */
1730 fprintf(fOutFile, " static int Pattern_counter = 0;\n");
1731 /* a universal variable for units */
1732 fprintf(fOutFile, " pUnit unit;\n");
1733
1734 /* write the Units, their weights and biases */
1735 writeAllUnits(globalUnits, NoOfUnits, fOutFile);
1736
1737 /** write Layers e.g. Member of the layers **/
1738 fprintf(fOutFile,
1739 "\n /* layer definition section (names & member units) */\n");
1740 for (nr = 0; nr < NoOfLayers; nr++) {
1741 writeLayer( (globalLayers + nr), fOutFile);
1742 }
1743 /* the Output list may be treated as a layer */
1744 fprintf(fOutFile, "\n static int Output[%d] = ", NoOf(OutList) );
1745 writeList(OutList, fOutFile);
1746 fprintf(fOutFile, ";\n\n");
1747
1748 /** last not least the Update-Function **/
1749 layer = globalLayers + order[0]; /* first in order e.g. Input-Layer */
1750
1751 fprintf(fOutFile, TdnnFirstTemplate);
1752 fprintf(fOutFile, TdnnInputTemplate, NoOf(layer->members) );
1753
1754 for (nr = 1; nr < NoOfLayers; nr++) {
1755 layerNo = order[nr]; /* update Layers in the right order */
1756 layer = globalLayers + layerNo; /* current Layer */
1757
1758 unitNo = element(layer->members, 0); /* Number of the first member unit */
1759 unit = (globalUnits + unitNo);
1760 sourceNo = element(unit->sources, 0); /* Number of the first source unit */
1761 unit = searchUnit(sourceNo, globalUnits, &pos);
1762 source = unit->layer; /* layer of the first source unit */
1763
1764 fprintf(fOutFile, TdnnTemplate,
1765 NoOf(layer->members),
1766 layer->name,
1767 source->readCounter, layer->delay, source->TotalDelay,
1768 source->readCounter, source->readCounter, layer->delay,
1769 source->readCounter,
1770 source->readCounter, source->TotalDelay,
1771 source->readCounter,
1772 source->readCounter, layer->delay, source->TotalDelay,
1773 source->readCounter, source->TotalDelay,
1774 layer->writeCounter, ACT_FUNC_NAMES[layer->ActFunc]);
1775 }
1776
1777 fprintf(fOutFile, TdnnOutputTemplate, NoOf(OutList) );
1778 /* Updating the counters of the ring-buffers */
1779 for (layer = globalLayers; layer < globalLayers + NoOfLayers; layer++) {
1780 fprintf(fOutFile, " %s = (++%s) %% %d;\n",
1781 layer->readCounter, layer->readCounter, layer->TotalDelay);
1782 fprintf(fOutFile, " %s = (++%s) %% %d;\n",
1783 layer->writeCounter, layer->writeCounter, layer->TotalDelay);
1784 }
1785
1786 /** the procedure should also have an end **/
1787 fprintf(fOutFile, TdnnExitTemplate, globalLayers[order[0]].TotalDelay);
1788 fprintf(fOutFile, "}\n");
1789
1790 /** that's all folks, or in German: "Ende gut, alles gut" **/
1791 killList(OutList);
1792 killList(FunctionList);
1793 return(OK);
1794 }
1795
1796
1797 /*****************************************************************************
1798 int writeNet(pLayer globalLayers, pUnit globalUnits,
1799 int NoOfLayers, int NoOfUnits,
1800 int *order, char *OutFile)
1801 ----------------------------------------------------------------------------
1802 writes a Net wich is discribed by globalLayers and globalUnits in the File
1803 named <OutFile>.
1804 The order for updating the Layers is discribed in order and in the single
1805 Layers there is a set of unit-numbers, wich will be updated when its the turn
1806 of the layer.
1807 -> globalLayers : all Layers of the Net
1808 -> globalUnits : all Units of the Net
1809 -> NoOfLayers : #Layers in the Net
1810 -> NoOfUnits : #Units in the Net
1811 -> order : in wich order the Layers have to be updated
1812 -> OutFile : Name of the Output-File
1813 <- (func) OK : no errors occured
1814 MEM_ERR : not enough memory
1815 CANT_OPEN : could not open the output-file
1816 ******************************************************************************/
writeNet(pLayer globalLayers,pUnit globalUnits,int NoOfLayers,int NoOfUnits,int * order,char * OutFile,char * ProcName)1817 int writeNet(pLayer globalLayers, pUnit globalUnits,
1818 int NoOfLayers, int NoOfUnits,
1819 int *order, char *OutFile, char *ProcName)
1820 {
1821 pLayer layer;
1822 pUnit unit;
1823 int nr, layerNo, maxSource = 0, maxFeature = 0;
1824 FILE *fOutFile, *fHeaderFile;
1825 pList OutList, FunctionList;
1826 time_t timer;
1827 char HeaderFile[50];
1828
1829 /* calculate time for the date in the header of the output file */
1830 time(&timer);
1831
1832 /* Preparations for the Header-File */
1833 strcpy(HeaderFile, OutFile);
1834 HeaderFile[strlen(HeaderFile) - 1] = 'h';
1835 fHeaderFile = fopen(HeaderFile, "w");
1836 if (!fHeaderFile) return(CANT_OPEN);
1837
1838 /* prepare Output Stream */
1839 fOutFile = fopen(OutFile, "w");
1840 if (!fOutFile) return(CANT_OPEN);
1841
1842 /* maxSource is needed for writing the Unit-array */
1843 for(unit = globalUnits; unit < globalUnits + NoOfUnits; unit++) {
1844 maxSource = MAX(maxSource, NoOf(unit->sources) );
1845 /* Calculating the Maximum Feature-Width is harmless for non-TDNNs */
1846 maxFeature = MAX(maxFeature, unit->FeatureWidth);
1847 }
1848
1849 /* Net-Output may consist of several (output) Layers */
1850 /* so there must be an extra merge-list : OutList */
1851 /* FunctionList will contain a set of all used functions */
1852 OutList = newList();
1853 if (!OutList) return (MEM_ERR);
1854 FunctionList = newList();
1855 if (!FunctionList) return (MEM_ERR);
1856 for(nr = 0; nr < NoOfLayers; nr ++) {
1857 layer = globalLayers + nr;
1858 if( layer->type == OUTPUT) {
1859 if (mergeList(OutList, layer->members) ) return (MEM_ERR);
1860 }
1861 if (addList(FunctionList, layer->ActFunc) ) return(MEM_ERR);
1862 }
1863
1864 /** find Names for the Layers **/
1865 if (NameLayers(globalLayers, NoOfLayers)) return(MEM_ERR);
1866
1867
1868 /* ------------------------------------------------------------
1869 Beginning of the output-functions
1870 ------------------------------------------------------------ */
1871
1872 /** write Header-File **/
1873 fprintf(fHeaderFile, HeaderFileTemplate,
1874 HeaderFile, ctime(&timer), ProcName,
1875 ProcName, NoOf(globalLayers[order[0]].members),
1876 NoOf(OutList), ProcName);
1877 fclose(fHeaderFile);
1878
1879 /** write the Programm Header and Act-Functions **/
1880 fprintf(fOutFile, ProgHeader, OutFile, ctime(&timer) );
1881 for(nr = 0; nr < NoOf(FunctionList); nr ++) {
1882 fprintf(fOutFile, "%s\n", ACT_FUNCTIONS[element(FunctionList, nr)]);
1883 }
1884 /* to avoid unneeded include-files */
1885 fprintf(fOutFile, "#ifndef NULL\n");
1886 fprintf(fOutFile, "#define NULL (void *)0\n");
1887 fprintf(fOutFile, "#endif\n");
1888
1889
1890 /* if more than one net is included in the application,
1891 the types must be defined local to the procedure
1892 so it's done generally */
1893 if (is_CPN_net() ) {
1894 fprintf(fOutFile, CpnTypeTemplate, maxSource, maxSource,
1895 NoOf(globalLayers[2].members));
1896 }
1897 else if (is_BPTT_net() ) {
1898 fprintf(fOutFile, BpttTypeTemplate, maxSource, maxSource);
1899 }
1900 else {
1901 fprintf(fOutFile, TypeTemplate);
1902 }
1903
1904 /* write the Units, their weights and biases */
1905 writeForwardDeclarationAllUnits(globalUnits, NoOfUnits, fOutFile);
1906
1907 if( ! is_CPN_net() && !is_BPTT_net())
1908 {
1909
1910 /* write the Units, their weights and biases */
1911 writeAllSources(globalUnits, NoOfUnits, fOutFile);
1912
1913 /* write the Units, their weights and biases */
1914 writeAllWeights(globalUnits, NoOfUnits, fOutFile);
1915 }
1916 if( !is_BPTT_net() )
1917 {
1918 /* write the Units, their weights and biases */
1919 writeAllUnits(globalUnits, NoOfUnits, fOutFile);
1920 }
1921 else
1922 {
1923 /* write the Units, their weights and biases */
1924 writeAllUnitsOld(globalUnits, NoOfUnits, fOutFile);
1925 }
1926
1927 /* write Procedure-Header */
1928 fprintf(fOutFile, ProcHeader, ProcName);
1929
1930 /* DLVQ needs the biggest Scalar Product */
1931 if(is_DLVQ_net() ) {
1932 fprintf(fOutFile, " float maxSum = -1.0;\n");
1933 fprintf(fOutFile, " pUnit unit;\n\n"); /* variable needed for update */
1934 }
1935 /* CounterPropagation needs a winner Unit */
1936 else if(is_CPN_net() ) {
1937 fprintf(fOutFile, " float maxSum = -1.0e30;\n"); /* biggest Scalar Product */
1938 fprintf(fOutFile, " pUnit winner, unit;\n\n"); /* winner unit and variable unit */
1939 }
1940 else {
1941 fprintf(fOutFile, " pUnit unit;\n\n"); /* variable needed for update */
1942 }
1943
1944
1945 /** write Layers e.g. Member of the layers **/
1946 fprintf(fOutFile,
1947 "\n /* layer definition section (names & member units) */\n");
1948 if (is_DLVQ_net() || is_CPN_net() ) {
1949 /* DLVQ and CPN don't need the output layer */
1950 for (nr = 0; nr < NoOfLayers; nr++) {
1951 if (globalLayers[nr].type != OUTPUT) {
1952 writeLayer( (globalLayers + nr), fOutFile);
1953 }
1954 }
1955 fprintf(fOutFile, "\n");
1956 }
1957 else { /* not (DLVQ or CPN) */
1958 for (nr = 0; nr < NoOfLayers; nr++) {
1959 writeLayer( (globalLayers + nr), fOutFile);
1960 }
1961 /* the Output list may be treated as a layer */
1962 fprintf(fOutFile, "\n static int Output[%d] = ", NoOf(OutList) );
1963 writeList(OutList, fOutFile);
1964 fprintf(fOutFile, ";\n\n");
1965 }
1966
1967 /* BPTT-nets may be inialised by a flag */
1968 if (is_BPTT_net() ) {
1969 fprintf(fOutFile, BpttFirstTemplate, NoOfUnits);
1970 }
1971
1972 /** last not least the Update-Function **/
1973 layer = globalLayers + order[0]; /* first in order e.g. Input-Layer */
1974
1975 if (is_BPTT_net() ) {
1976 fprintf(fOutFile, BpttInputTemplate, NoOf(layer->members) );
1977 }
1978 else {
1979 fprintf(fOutFile, InputTemplate, NoOf(layer->members) );
1980 }
1981
1982 for (nr = 1; nr < NoOfLayers; nr++) {
1983 layerNo = order[nr]; /* update Layers in the right order */
1984 layer = globalLayers + layerNo; /* current Layer */
1985
1986 if (is_DLVQ_net() ) {
1987 if (layer->type == HIDDEN) {
1988 fprintf(fOutFile, DlvqTemplate, NoOf(layer->members),
1989 layer->name);
1990 }
1991 /* Output Layer not needed (see DlvqOutputTemplate) */
1992 }
1993 else if (is_CPN_net() ) {
1994 if (layer->type == HIDDEN) {
1995 fprintf(fOutFile, CpnTemplate, NoOf(layer->members),
1996 layer->name);
1997 }
1998 /* Output Layer not needed (see CpnOutputTemplate) */
1999 }
2000 else if (is_BPTT_net() ) {
2001 fprintf(fOutFile, BpttTemplate, NoOf(layer->members),
2002 layer->name, ACT_FUNC_NAMES[layer->ActFunc]);
2003 }
2004 else if (layer->ActFunc >= ActRbfNumber) {
2005 fprintf(fOutFile, RbfTemplate, NoOf(layer->members),
2006 layer->name, ACT_FUNC_NAMES[layer->ActFunc]);
2007 }
2008 else {
2009 fprintf(fOutFile, NormalTemplate, NoOf(layer->members),
2010 layer->name, ACT_FUNC_NAMES[layer->ActFunc]);
2011 }
2012 }
2013
2014 if (is_DLVQ_net() ) {
2015 fprintf(fOutFile, DlvqOutputTemplate);
2016 }
2017 else if (is_CPN_net() ) {
2018 fprintf(fOutFile, CpnOutputTemplate, NoOf(globalLayers[2].members));
2019 }
2020 else if (is_BPTT_net() ) {
2021 fprintf(fOutFile, BpttOutputTemplate, NoOf(OutList) );
2022 fprintf(fOutFile, BpttExitTemplate);
2023 }
2024 else {
2025 fprintf(fOutFile, OutputTemplate, NoOf(OutList) );
2026 }
2027
2028 /** the procedure should also have an end **/
2029 fprintf(fOutFile, " return(OK);\n");
2030 fprintf(fOutFile, "}\n");
2031
2032 /** that's all folks, or in German: "Ende gut, alles gut" **/
2033 killList(OutList);
2034 killList(FunctionList);
2035 return(OK);
2036 }
2037
2038
2039 /*****************************************************************************
2040 void freeUnits(pUnit Units)
2041 ----------------------------------------------------------------------------
2042 releases memory of the Unit-array
2043 -> Units : Arrray which contains all Units of the network.
2044 The last unit must be empty (all entries 0 or NULL)
2045 *****************************************************************************/
freeUnits(pUnit Units)2046 void freeUnits(pUnit Units)
2047 {
2048 pUnit unit = Units;
2049
2050 while(unit->number) { /* e.g. non-empty unit */
2051 if (unit->members) killList(unit->members); /* make sure, that there is */
2052 if (unit->sources) killList(unit->sources); /* memory to release */
2053 if (unit->weights) free(unit->weights);
2054 if (unit->name) free(unit->name);
2055 if (unit->dest) free(unit->dest);
2056
2057 if(unit->FeatureWidth) {
2058 int i;
2059 for(i = 0; i < unit->FeatureWidth; i++) {
2060 if(unit->TDNNsources[i]) free(unit->TDNNsources[i]);
2061 if(unit->TDNNweights[i]) free(unit->TDNNweights[i]);
2062 }
2063 if(unit->TDNNsources) free(unit->TDNNsources);
2064 if(unit->TDNNweights) free(unit->TDNNweights);
2065 }
2066 unit++;
2067 }
2068
2069 free(Units);
2070 }
2071
2072
2073 /*****************************************************************************
2074 void freeLayers(pLayer Layers)
2075 ----------------------------------------------------------------------------
2076 releases memory of the Layer-array
2077 -> Units : Arrray which contains all Layer of the network.
2078 The last Layer must be empty (all entries 0 or NULL)
2079 *****************************************************************************/
freeLayers(pLayer Layers)2080 void freeLayers(pLayer Layers)
2081 {
2082 pLayer layer = Layers;
2083
2084 while(layer->members) { /* e.g. non-empty layer */
2085 if (layer->members) free(layer->members); /* make sure, that there is */
2086 if (layer->sources) free(layer->sources); /* memory to release */
2087 if (layer->name) free(layer->name);
2088 if (layer->readCounter) free(layer->readCounter);
2089 if (layer->writeCounter) free(layer->writeCounter);
2090
2091 layer++;
2092 }
2093
2094 free(Layers);
2095 }
2096
2097
2098 /*****************************************************************************
2099 int main(int argc, char **argv)
2100 ----------------------------------------------------------------------------
2101 -> arg c : must be 2, 3, or 4 e.g. 1 to 3 commandline-parameter
2102 argv[1] : the root of the filename of the network
2103 (e.g. without ".net")
2104 <- (func) status
2105 *****************************************************************************/
main(int argc,char ** argv)2106 int main(int argc, char **argv)
2107 {
2108 krui_err err; /* error code of SNNS - krui */
2109 char *netname; /* internal name of the SNNS-network */
2110 char NetFileName[200]; /* input file */
2111 char CFileName[200]; /* output file */
2112 pUnit Units, unit = NULL; /* all Units and unit variable */
2113 pLayer Layers, layer; /* all Layers and layer variable */
2114 int NoOfUnits, NoOfLayers; /* Number of units and layers */
2115 int *order; /* array with the order of the sorted layers */
2116 int nr, pos; /* help variables */
2117 int error; /* error code */
2118 pList HelpList; /* needed for exchange */
2119 char ProcName[50]; /* function name in the output */
2120
2121 /* Array with the numbers of the prototype units */
2122 int *TDNN_prot;
2123
2124 /* check Params */
2125 if ((argc < 2) || (argc > 4)) {
2126 fprintf(stderr, "usage : %s <netfile> [<output-file> [<function-name>] ]\n",
2127 argv[0]);
2128 return(WRONG_PARAM);
2129 }
2130 strcpy(NetFileName, argv[1]);
2131 if (argc >= 3) { /* C-File-Name mentioned in the command-line */
2132 strcpy(CFileName, argv[2]);
2133 }
2134 else {
2135 strcpy(CFileName, argv[1]); /* taking Netfile Name */
2136 /* if the ending is not ".net" surprising Names may occur */
2137 strcpy(CFileName + strlen(CFileName) - 3, "c\0");
2138 }
2139 if (argc ==4) { /* Function-Name mentioned in the command-line */
2140 strcpy(ProcName, argv[3]);
2141 toAlphaNum(ProcName); /* Function Name must not contain special chars */
2142 }
2143 else {
2144 /* define procedure-name for propagate-function */
2145 strncpy(ProcName, CFileName, strlen(CFileName) - 2);
2146 ProcName[strlen(CFileName) -2] = '\0';
2147 toAlphaNum(ProcName); /* Function Name must not contain special chars */
2148 }
2149
2150 /* Write a Message (what to do) on screen */
2151 printf(HeadingTemplate, NetFileName, CFileName, ProcName);
2152
2153 printf("loading net... \n");
2154
2155 /* load Net */
2156 err = krui_loadNet(NetFileName, &netname);
2157 if (err) {
2158 fprintf(stderr, "%s\n", krui_error(err) );
2159 return(CANT_LOAD);
2160 }
2161
2162 error = checkLearnFunc();
2163 if (error) {
2164 checkErr(error);
2165 return(error);
2166 }
2167
2168 NoOfUnits = krui_getNoOfUnits();
2169
2170 Units = (pUnit)calloc((NoOfUnits + 1), sizeof(tUnit) ); /* because of sentinels */
2171 if (! Units) {
2172 checkErr(MEM_ERR);
2173 return(MEM_ERR);
2174 }
2175
2176 Layers = (pLayer)calloc((NoOfUnits + 1), sizeof(tLayer) ); /* because of sentinels */
2177 if (! Layers) {
2178 free(Units);
2179 checkErr(MEM_ERR);
2180 return(MEM_ERR);
2181 }
2182
2183 /* TDNN_prot needs one more Element, because the enumeration
2184 of the units starts with one */
2185 TDNN_prot = (int *)malloc((NoOfUnits+1) * sizeof(int) );
2186 if (! TDNN_prot) {
2187 free(Units);
2188 free(Layers);
2189 checkErr(MEM_ERR);
2190 return(MEM_ERR);
2191 }
2192
2193 for (nr = 0; nr <= NoOfUnits; nr++) {
2194 Layers[nr].number = nr;
2195 }
2196
2197 printf("dividing net into layers ...\n");
2198
2199 /* part Net into groups */
2200 error = divideNet(Units, Layers, TDNN_prot);
2201 if (error) {
2202 checkErr(error);
2203 FREE_ALL;
2204 return(error);
2205 }
2206
2207 /* count the Non-empty Layers */
2208 for (nr = 0; Layers[nr].members != NULL; nr++);
2209 NoOfLayers = nr;
2210 order = (int *)malloc(NoOfLayers * sizeof(int) );
2211
2212
2213 /* count the real number of units (e.g. the prototype units in TDNN) */
2214 /* unused units have the number 0 the total Number can't exeed the */
2215 /* Number of Units given by the SNNS-Interface-Function */
2216 for(nr = 0; (Units[nr].number != 0) && (nr < NoOfUnits); nr++) {
2217 Units[nr].index = nr;
2218 }
2219 NoOfUnits = nr;
2220
2221 #ifdef debug
2222 for(nr = 0; nr < NoOfLayers; printLayer(Layers + nr++) );
2223 #endif
2224
2225 /* the TDNN_units must have a special format */
2226 if ( is_TDNN_net() ) {
2227 prepareTDNNunits(Units, TDNN_prot);
2228
2229 /* some values are passed to the layers for TDNNs */
2230 for(layer = Layers; layer < Layers + NoOfLayers; layer++) {
2231 unit = searchUnit(element(layer->members, 0), Units, &pos);
2232 layer->delay = unit->DelayLength;
2233 layer->TotalDelay = NoOf(unit->members);
2234 layer->SuccDelay = 0; /* only initalisation (see function checkOrder )*/
2235 }
2236 }
2237
2238 /* topological sort of the layers */
2239 printf("sorting layers ...\n");
2240 error = sortNet(Layers, NoOfLayers, order);
2241 if (error) {
2242 checkErr(error);
2243 FREE_ALL;
2244 return(error);
2245 }
2246
2247 if ( is_TDNN_net() ) {
2248 /* Update the entries in the member list of the layer */
2249 /* now the snns2c-indices are valid */
2250
2251 for(layer = Layers; layer < Layers + NoOfLayers; layer++) {
2252 HelpList = newList();
2253 for(nr = 0; nr < NoOf(layer->members); nr++) {
2254 searchUnit(element(layer->members, nr), Units, &pos);
2255 addList(HelpList, pos);
2256 }
2257 killList(layer->members);
2258 layer->members = HelpList;
2259 }
2260 }
2261 else if( is_CPN_net() ) {
2262 /* copy the weights from hidden to output
2263 units into hidden units */
2264 error = prepareCpnUnits(Units, Layers);
2265 if (error) {
2266 checkErr(error);
2267 FREE_ALL;
2268 return(error);
2269 }
2270 }
2271
2272 printf("writing net ...\n");
2273
2274 /* write the net as a C-source */
2275 if (is_TDNN_net() ) {
2276 error = writeTdnnNet(Layers, Units, NoOfLayers, NoOfUnits, order, CFileName, ProcName);
2277 if (error) {
2278 checkErr(error);
2279 FREE_ALL;
2280 return(error);
2281 }
2282 }
2283 else {
2284 error = writeNet(Layers, Units, NoOfLayers, NoOfUnits, order, CFileName, ProcName);
2285 if (error) {
2286 checkErr(error);
2287 FREE_ALL;
2288 return(error);
2289 }
2290 }
2291
2292 FREE_ALL;
2293 return(0);
2294 }
2295