1 /*****************************************************************************
2   FILE           : $Source: /projects/higgs1/SNNS/CVS/SNNS/tools/sources/ff_bignet.c,v $
3   SHORTNAME      : ff_bignet
4   SNNS VERSION   : 4.2
5 
6   PURPOSE        : Creates feedforward network
7   NOTES          :
8 
9   AUTHOR         : Michael Vogt (xgui Version by Michael Schmalzl)
10   DATE           : 4.7.1997
11 
12   CHANGED BY     : Guenter Mamier
13   RCS VERSION    : $Revision: 1.11 $
14   LAST CHANGE    : $Date: 1998/04/22 16:48:06 $
15 
16     Copyright (c) 1990-1995  SNNS Group, IPVR, Univ. Stuttgart, FRG
17     Copyright (c) 1996-1998  SNNS Group, WSI, Univ. Tuebingen, FRG
18 
19 ******************************************************************************/
20 #include <config.h>
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #include "kr_typ.h"
28 #include "kernel.h"
29 #include "glob_typ.h"
30 #include "kr_ui.h"
31 
32 #include "ff_bignet.ph"
33 
34 
35 
36 /*****************************************************************************
37   FUNCTION : create_net_PROC
38 
39   PURPOSE  : creates a SNNS-net in two steps:
40              1. calls up a function, which creates SNNS-units
41              2. calls up a function, which connections the SNNS-units.
42   NOTES    : There are nine different ways (PLANE_TO_PLANE,
43              PLANE_TO_CLUSTER ...) two different planes can be connected.
44   RETURNS  :
45 
46   UPDATE   : 20.12.1991
47 ******************************************************************************/
48 
create_net_PROC(void)49 static void create_net_PROC(void)
50 
51 {
52     LINK  *LINK_element = LINK_first_element;
53     PLANE *source_plane, *target_plane;
54     int move,type_of_connection=1;
55 
56     if(PLANE_length == 0)
57 	return;
58 
59     calculate_first_snns_unit_no_of_plane();
60     create_snns_unit();
61 
62     while(LINK_element != NULL) {
63 
64 	move               = (*LINK_element).move;
65 	type_of_connection = (*LINK_element).type_of_connection;
66 	source_plane       =  get_plane((*LINK_element).SOURCE.plane);
67 	target_plane       =  get_plane((*LINK_element).TARGET.plane);
68 
69 	switch(type_of_connection) {
70 	case PLANE_TO_PLANE:
71 	    make_link(source_plane, 0, 0, (*source_plane).width,
72 		      (*source_plane).height, target_plane, 0, 0,
73 		      (*target_plane).width,(*target_plane).height);
74 	    break;
75 	case PLANE_TO_CLUSTER:
76 	    make_link(source_plane, 0, 0, (*source_plane).width,
77 		      (*source_plane).height, target_plane,
78 		      (*LINK_element).TARGET.CLUSTER.x-1,
79 		      (*LINK_element).TARGET.CLUSTER.y-1,
80 		      (*LINK_element).TARGET.CLUSTER.width,
81 		      (*LINK_element).TARGET.CLUSTER.height);
82 	    break;
83 	case PLANE_TO_UNIT:
84 	    make_link(source_plane, 0, 0, (*source_plane).width,
85 		      (*source_plane).height, target_plane,
86 		      (*LINK_element).TARGET.UNIT.x-1,
87 		      (*LINK_element).TARGET.UNIT.y-1, 1, 1);
88 	    break;
89 	case CLUSTER_TO_PLANE:
90 	    make_link(source_plane, (*LINK_element).SOURCE.CLUSTER.x-1,
91 		      (*LINK_element).SOURCE.CLUSTER.y-1,
92 		      (*LINK_element).SOURCE.CLUSTER.width,
93 		      (*LINK_element).SOURCE.CLUSTER.height,
94 		      target_plane, 0, 0, (*target_plane).width,
95 		      (*target_plane).height);
96 	    break;
97 	case CLUSTER_TO_CLUSTER:
98 	    if(move) {
99 		make_move_link(source_plane,
100 			       (*LINK_element).SOURCE.CLUSTER.x-1,
101 			       (*LINK_element).SOURCE.CLUSTER.y-1,
102 			       (*LINK_element).SOURCE.CLUSTER.width,
103 			       (*LINK_element).SOURCE.CLUSTER.height,
104 			       target_plane,
105 			       (*LINK_element).TARGET.CLUSTER.x-1,
106 			       (*LINK_element).TARGET.CLUSTER.y-1,
107 			       (*LINK_element).TARGET.CLUSTER.width,
108 			       (*LINK_element).TARGET.CLUSTER.height,
109 			       (*LINK_element).SOURCE.MOVE.delta_x,
110 			       (*LINK_element).SOURCE.MOVE.delta_y,
111 			       (*LINK_element).TARGET.MOVE.delta_x,
112 			       (*LINK_element).TARGET.MOVE.delta_y);
113 	    } else {
114 		make_link(source_plane, (*LINK_element).SOURCE.CLUSTER.x-1,
115 			  (*LINK_element).SOURCE.CLUSTER.y-1,
116 			  (*LINK_element).SOURCE.CLUSTER.width,
117 			  (*LINK_element).SOURCE.CLUSTER.height,
118 			  target_plane, (*LINK_element).TARGET.CLUSTER.x-1,
119 			  (*LINK_element).TARGET.CLUSTER.y-1,
120 			  (*LINK_element).TARGET.CLUSTER.width,
121 			  (*LINK_element).TARGET.CLUSTER.height);
122 	    }
123 	    break;
124 	case CLUSTER_TO_UNIT:
125 	    if(move) {
126 		make_move_link(source_plane,
127 			       (*LINK_element).SOURCE.CLUSTER.x-1,
128 			       (*LINK_element).SOURCE.CLUSTER.y-1,
129 			       (*LINK_element).SOURCE.CLUSTER.width,
130 			       (*LINK_element).SOURCE.CLUSTER.height,
131 			       target_plane,
132 			       (*LINK_element).TARGET.UNIT.x-1,
133 			       (*LINK_element).TARGET.UNIT.y-1, 1, 1,
134 			       (*LINK_element).SOURCE.MOVE.delta_x,
135 			       (*LINK_element).SOURCE.MOVE.delta_y,
136 			       (*LINK_element).TARGET.MOVE.delta_x,
137 			       (*LINK_element).TARGET.MOVE.delta_y);
138 	    } else {
139 		make_link(source_plane, (*LINK_element).SOURCE.CLUSTER.x-1,
140 			  (*LINK_element).SOURCE.CLUSTER.y-1,
141 			  (*LINK_element).SOURCE.CLUSTER.width,
142 			  (*LINK_element).SOURCE.CLUSTER.height,
143 			  target_plane,(*LINK_element).TARGET.UNIT.x-1,
144 			  (*LINK_element).TARGET.UNIT.y-1, 1, 1);
145 	    }
146 	    break;
147 	case UNIT_TO_PLANE:
148 	    make_link(source_plane, (*LINK_element).SOURCE.UNIT.x-1,
149 		      (*LINK_element).SOURCE.UNIT.y-1, 1, 1, target_plane,
150 		      0, 0, (*target_plane).width, (*target_plane).height);
151 	    break;
152 	case UNIT_TO_CLUSTER:
153 	    if(move) {
154 		make_move_link(source_plane,
155 			       (*LINK_element).SOURCE.UNIT.x-1,
156 			       (*LINK_element).SOURCE.UNIT.y-1, 1, 1,
157 			       target_plane,
158 			       (*LINK_element).TARGET.CLUSTER.x-1,
159 			       (*LINK_element).TARGET.CLUSTER.y-1,
160 			       (*LINK_element).TARGET.CLUSTER.width,
161 			       (*LINK_element).TARGET.CLUSTER.height,
162 			       (*LINK_element).SOURCE.MOVE.delta_x,
163 			       (*LINK_element).SOURCE.MOVE.delta_y,
164 			       (*LINK_element).TARGET.MOVE.delta_x,
165 			       (*LINK_element).TARGET.MOVE.delta_y);
166 	    } else {
167 		make_link(source_plane, (*LINK_element).SOURCE.UNIT.x-1,
168 			  (*LINK_element).SOURCE.UNIT.y-1, 1, 1,
169 			  target_plane, (*LINK_element).TARGET.CLUSTER.x-1,
170 			  (*LINK_element).TARGET.CLUSTER.y-1,
171 			  (*LINK_element).TARGET.CLUSTER.width,
172 			  (*LINK_element).TARGET.CLUSTER.height);
173 	    }
174 	    break;
175 	case UNIT_TO_UNIT:
176 	    if(move) {
177 		make_move_link(source_plane,
178 			       (*LINK_element).SOURCE.UNIT.x-1,
179 			       (*LINK_element).SOURCE.UNIT.y-1, 1, 1,
180 			       target_plane,
181 			       (*LINK_element).TARGET.UNIT.x-1,
182 			       (*LINK_element).TARGET.UNIT.y-1, 1, 1,
183 			       (*LINK_element).SOURCE.MOVE.delta_x,
184 			       (*LINK_element).SOURCE.MOVE.delta_y,
185 			       (*LINK_element).TARGET.MOVE.delta_x,
186 			       (*LINK_element).TARGET.MOVE.delta_y);
187 	    } else {
188 		make_link(source_plane, (*LINK_element).SOURCE.UNIT.x-1,
189 			  (*LINK_element).SOURCE.UNIT.y-1, 1, 1,
190 			  target_plane,(*LINK_element).TARGET.UNIT.x-1,
191 			  (*LINK_element).TARGET.UNIT.y-1, 1, 1);
192 	    }
193 	    break;
194 	} /* switch */
195 	LINK_element = (*LINK_element).next;
196 
197     } /* while */
198 }
199 
200 
201 /*****************************************************************************
202   FUNCTION : calculate_first_snns_unit_no_of_plane
203 
204   PURPOSE  : calculates the SNNS unit no of the left upper corner of every
205              plane.
206 
207   NOTES    : relative to this unit no, knowing the width and the height of the
208              planes, all other SNNS unit numbers of every plane can be
209              calculated. That's important for the function create_snns_unit.
210   RETURNS  :
211 
212   UPDATE   : 20.12.1991
213 ******************************************************************************/
214 
calculate_first_snns_unit_no_of_plane(void)215 static void calculate_first_snns_unit_no_of_plane(void)
216 
217 {
218     PLANE *PLANE_element = PLANE_first_element;
219 
220     (*PLANE_element).begin = 1;
221     PLANE_element = (*PLANE_element).next;
222 
223     while(PLANE_element != NULL) {
224 	(*PLANE_element).begin = (*(*PLANE_element).before).width *
225 	    (*(*PLANE_element).before).height +
226 	    (*(*PLANE_element).before).begin;
227 	PLANE_element = (*PLANE_element).next;
228     }
229 }
230 
231 
232 
233 /*****************************************************************************
234   FUNCTION : calculate_x_begin
235 
236   PURPOSE  : calculates the x-coordinate of a plane, where the plane is
237              positioned in the display window.
238              plane.
239   NOTES    :
240   RETURNS  : The X-Position
241 
242   UPDATE   : 20.12.1991
243 ******************************************************************************/
244 
calculate_x_begin(int * new_x_begin,int * old_x_begin,int * x_max,int width,int pos)245 static int calculate_x_begin(int *new_x_begin, int *old_x_begin, int *x_max,
246 			     int width, int pos)
247 
248 {
249     if(pos == BN_RIGHT) {
250 	*new_x_begin = *x_max + 2;
251 	*x_max = *new_x_begin + width;
252 	*old_x_begin = *new_x_begin;
253 	return *new_x_begin;
254     } else if(pos == BN_BELOW) {
255 	if(*x_max < (*old_x_begin + width)) {
256 	    *x_max = *old_x_begin + width;
257 	}
258 	return *old_x_begin;
259     } else if(pos == BN_LEFT) {
260 	*x_max = 0;
261 	*old_x_begin = 2;
262 
263 	*new_x_begin = *x_max + 2;
264 	*x_max = *new_x_begin + width;
265 	return *new_x_begin;
266     }
267     return 0;
268 }
269 
270 
271 /*****************************************************************************
272   FUNCTION : calculate_y_begin
273 
274   PURPOSE  : calculates the y-coordinate of a plane, where the plane is
275              positioned in the display window.
276              plane.
277 
278   NOTES    :
279   RETURNS  : The Y-Position
280 
281   UPDATE   : 20.12.1991
282 ******************************************************************************/
283 
calculate_y_begin(int * absolute_y_max,int * relative_y_max,int * y_offset,int height,int pos)284 static int calculate_y_begin(int *absolute_y_max, int *relative_y_max,
285 			     int *y_offset, int height, int pos)
286 {
287     int y_begin;
288 
289     if(pos == BN_RIGHT) {
290 	y_begin = *y_offset + 2;
291 	*relative_y_max = y_begin + height;
292 	if(*absolute_y_max < *relative_y_max) {
293 	    *absolute_y_max = *relative_y_max;
294 	}
295     } else if(pos == BN_BELOW) {
296 	y_begin = *relative_y_max + 2;
297 	*relative_y_max = y_begin + height;
298 	if(*absolute_y_max < *relative_y_max) {
299 	    *absolute_y_max = *relative_y_max;
300 	}
301     } else if(pos == BN_LEFT) {
302 	*y_offset = *absolute_y_max;
303 	y_begin = *y_offset + 2;
304 	*absolute_y_max = y_begin + height;
305 	*relative_y_max = y_begin + height;
306     }
307     return y_begin;
308 }
309 
310 
311 /*****************************************************************************
312   FUNCTION : create_snns_unit
313 
314   PURPOSE  : creates for every unit of a plane a SNNS default unit.
315 
316   NOTES    :
317   RETURNS  :
318 
319   UPDATE   : 20.12.1991
320 ******************************************************************************/
321 
create_snns_unit(void)322 static void create_snns_unit(void)
323 {
324     struct PosType unit_pos;
325 
326     PLANE *PLANE_element = PLANE_first_element;
327     int x,y,width,height,unit_no,pos,ret;
328     int y_offset=0,relative_y_max=0,absolute_y_max=0,y_begin;
329     int x_max=0,old_x_begin=2,new_x_begin,x_begin;
330 
331     ret = krui_allocateUnits((*PLANE_last_element).width *
332                              (*PLANE_last_element).height +
333 			     (*PLANE_last_element).begin-1);
334     if(ret != 0){
335 	fprintf(stderr, "%s\n", krui_error(ret));
336 	exit(1);
337     }
338 
339     while(PLANE_element != NULL) {
340 
341 	height = (*PLANE_element).height;
342 	width  = (*PLANE_element).width;
343 	pos    = (*PLANE_element).pos;
344 
345 	y_begin = calculate_y_begin(&absolute_y_max, &relative_y_max,
346 				    &y_offset, height, pos);
347 	x_begin = calculate_x_begin(&new_x_begin, &old_x_begin,
348 				    &x_max, width, pos);
349 
350 	for(y=0;y<height;y++){
351 	    for(x=0;x<width;x++){
352 		unit_no = krui_createUnit("unit", (*PLANE_element).out_func,
353 					  (*PLANE_element).act_func, 0.0, 0.0);
354 		if(unit_no<0){
355 		    fprintf(stderr, "%s\n", krui_error(unit_no));
356 		    exit(1);
357 		}
358 
359 		ret = krui_setUnitTType(unit_no,(*PLANE_element).type+1);
360 		if(ret != 0){
361 		    fprintf(stderr, "%s\n", krui_error(ret));
362 		    exit(1);
363 		}
364 
365 		unit_pos.x = x_begin + x;
366 		unit_pos.y = y_begin + y;
367 
368 		krui_setUnitPosition(unit_no,&unit_pos);
369 	    }/*for*/
370 	}/*for*/
371 
372 	PLANE_element = (*PLANE_element).next;
373     }/*while*/
374 }
375 
376 
377 /*****************************************************************************
378   FUNCTION : make_link
379 
380   PURPOSE  : creates the links between two planes.
381 
382   NOTES    :
383   RETURNS  :
384 
385   UPDATE   : 20.12.1991
386 ******************************************************************************/
387 
make_link(PLANE * LINK_source_plane,int LINK_source_cluster_x,int LINK_source_cluster_y,int LINK_source_cluster_width,int LINK_source_cluster_height,PLANE * LINK_target_plane,int LINK_target_cluster_x,int LINK_target_cluster_y,int LINK_target_cluster_width,int LINK_target_cluster_height)388 static void make_link(PLANE *LINK_source_plane, int LINK_source_cluster_x,
389 		      int LINK_source_cluster_y,int LINK_source_cluster_width,
390 		      int LINK_source_cluster_height, PLANE *LINK_target_plane,
391 		      int LINK_target_cluster_x, int LINK_target_cluster_y,
392                       int LINK_target_cluster_width,
393 		      int LINK_target_cluster_height)
394 
395 {
396     int i,j,k,l,ret,target_unit,source_unit;
397 
398     for(i = LINK_target_cluster_y;
399 	i < LINK_target_cluster_height+LINK_target_cluster_y; i++)
400 	for(j = LINK_target_cluster_x;
401 	    j < LINK_target_cluster_width+LINK_target_cluster_x; j++)
402 	{
403 	    target_unit = (*LINK_target_plane).begin +
404 		(*LINK_target_plane).width * i + j;
405 	    ret = krui_setCurrentUnit(target_unit);
406 	    if(ret != 0){
407 		fprintf(stderr, "%s\n", krui_error(ret));
408 		exit(1);
409 	    }
410 	    for(k = LINK_source_cluster_y;
411 		k < LINK_source_cluster_height+LINK_source_cluster_y; k++)
412 		for(l = LINK_source_cluster_x;
413 		    l < LINK_source_cluster_width+LINK_source_cluster_x; l++)
414 		{
415 		    source_unit = (*LINK_source_plane).begin +
416 			(*LINK_source_plane).width * k + l;
417 		    if((ret = krui_createLink(source_unit,0.0)) != 0){
418 			fprintf(stderr, "%s\n", krui_error(ret));
419 			exit(1);
420 		    }
421 		}
422 	}
423 }
424 
425 
426 /*****************************************************************************
427   FUNCTION : make_move_link
428 
429   PURPOSE  : while "moving" (see docu)  is possible the function make_link
430              is called up.
431   NOTES    :
432   RETURNS  :
433 
434   UPDATE   : 20.12.1991
435 ******************************************************************************/
436 
make_move_link(PLANE * LINK_source_plane,int LINK_source_cluster_x,int LINK_source_cluster_y,int LINK_source_cluster_width,int LINK_source_cluster_height,PLANE * LINK_target_plane,int LINK_target_cluster_x,int LINK_target_cluster_y,int LINK_target_cluster_width,int LINK_target_cluster_height,int LINK_source_move_delta_x,int LINK_source_move_delta_y,int LINK_target_move_delta_x,int LINK_target_move_delta_y)437 static void make_move_link(PLANE *LINK_source_plane, int LINK_source_cluster_x,
438 			   int LINK_source_cluster_y,
439                            int LINK_source_cluster_width,
440 			   int LINK_source_cluster_height,
441                            PLANE * LINK_target_plane, int LINK_target_cluster_x,
442 			   int LINK_target_cluster_y,
443                            int LINK_target_cluster_width,
444 			   int LINK_target_cluster_height,
445                            int LINK_source_move_delta_x,
446 			   int LINK_source_move_delta_y,
447                            int LINK_target_move_delta_x,
448 			   int LINK_target_move_delta_y)
449 
450 {
451     int xs_pivot=LINK_source_cluster_x;
452     int xt_pivot=LINK_target_cluster_x;
453 
454     do {
455 	make_link(LINK_source_plane,LINK_source_cluster_x,LINK_source_cluster_y,
456 		  LINK_source_cluster_width,LINK_source_cluster_height,
457 		  LINK_target_plane,LINK_target_cluster_x,LINK_target_cluster_y,
458 		  LINK_target_cluster_width,LINK_target_cluster_height);
459     } while(move_p(LINK_source_plane, &LINK_source_cluster_y,
460 		   &LINK_source_cluster_x, LINK_source_cluster_width,
461 		   LINK_source_cluster_height, xs_pivot,
462 		   LINK_source_move_delta_x, LINK_source_move_delta_y)  &&
463 	    move_p(LINK_target_plane, &LINK_target_cluster_y,
464 		   &LINK_target_cluster_x, LINK_target_cluster_width,
465 		   LINK_target_cluster_height, xt_pivot,
466 		   LINK_target_move_delta_x, LINK_target_move_delta_y));
467 }
468 
469 
470 /*****************************************************************************
471   FUNCTION : move_p
472 
473   PURPOSE  : tests whether the boundaries of a plane are crossed while
474              "moving" (see docu)
475 
476   NOTES    :
477   RETURNS  :
478 
479   UPDATE   : 20.12.1991
480 ******************************************************************************/
481 
move_p(PLANE * plane_no,int * y,int * x,int width,int height,int x_pivot,int x_step,int y_step)482 static int move_p(PLANE *plane_no, int *y, int *x, int width, int height,
483 		  int x_pivot, int x_step, int y_step)
484 
485 {
486     if(x_step > 0 && ((*x)+width+x_step<=(*plane_no).width))
487 	(*x)+= x_step;
488     else
489 	if(y_step > 0 && ((*y)+height+y_step<=(*plane_no).height)){
490 	    (*y) += y_step;
491 	    (*x) = x_pivot;
492 	}else
493 	    return 0;
494 
495     return 1;
496 }
497 
498 
499 /*****************************************************************************
500   FUNCTION : more_data
501 
502   PURPOSE  : read command line integer value or "+"
503 
504   NOTES    :
505   RETURNS  :
506 
507   UPDATE   :
508 ******************************************************************************/
509 
more_data(char ** rest,char ** argv[],int * argc)510 static int more_data(char **rest, char **argv[], int *argc)
511 {
512     int retval = 0;
513 
514     if (*argc > 0 && strcmp(**argv, "+") != 0)
515     {
516 	retval = atoi(**argv);
517 	*rest = **argv;
518 	while (**rest != '\0' && isspace((int) **rest))
519 	    (*rest)++;
520 	while (**rest != '\0' && isdigit((int) **rest))
521 	    (*rest)++;
522 	(*argc)--;
523 	(*argv)++;
524     }
525 
526     return retval;
527 }
528 
529 /*****************************************************************************
530   FUNCTION : read_link_elements
531 
532   PURPOSE  : reads the input datas of the link editor (Edit Link).
533 
534   NOTES    :
535   RETURNS  : @@@
536 
537   UPDATE   : 20.12.1991
538 ******************************************************************************/
539 
540 #define RETURN_IF_FAULT(x) { if ((x) != NULL && *(x) != '\0') return 0; }
541 
read_link_elements(int * argc,char ** argv[])542 static int read_link_elements(int *argc, char **argv[])
543 
544 {
545     /* the + character may be used to fill the remaining parameters
546        of one link definition column (compare bignet for xgui).
547        e.g. argv values like '1 + 2 +' result in a full connection
548        between plane 1 and plane 2 */
549     char *rest = NULL;
550 
551     if (*argc <= 0)
552 	return 0;
553     LINK_source_plane          = more_data(&rest, argv, argc);
554     RETURN_IF_FAULT(rest);
555 
556     LINK_source_cluster_x      = more_data(&rest, argv, argc);
557     RETURN_IF_FAULT(rest);
558 
559     LINK_source_cluster_y      = more_data(&rest, argv, argc);
560     RETURN_IF_FAULT(rest);
561 
562     LINK_source_cluster_width  = more_data(&rest, argv, argc);
563     RETURN_IF_FAULT(rest);
564 
565     LINK_source_cluster_height = more_data(&rest, argv, argc);
566     RETURN_IF_FAULT(rest);
567 
568     LINK_source_unit_x         = more_data(&rest, argv, argc);
569     RETURN_IF_FAULT(rest);
570 
571     LINK_source_unit_y         = more_data(&rest, argv, argc);
572     RETURN_IF_FAULT(rest);
573 
574     LINK_source_move_delta_x   = more_data(&rest, argv, argc);
575     RETURN_IF_FAULT(rest);
576 
577     LINK_source_move_delta_y   = more_data(&rest, argv, argc);
578     RETURN_IF_FAULT(rest);
579     if (*argc > 0 && strcmp(**argv, "+") == 0)
580     {
581 	(*argc)--;
582 	(*argv)++;
583     }
584 
585     if (*argc <= 0)
586 	return 0;
587     LINK_target_plane          = more_data(&rest, argv, argc);
588     RETURN_IF_FAULT(rest);
589 
590     LINK_target_cluster_x      = more_data(&rest, argv, argc);
591     RETURN_IF_FAULT(rest);
592 
593     LINK_target_cluster_y      = more_data(&rest, argv, argc);
594     RETURN_IF_FAULT(rest);
595 
596     LINK_target_cluster_width  = more_data(&rest, argv, argc);
597     RETURN_IF_FAULT(rest);
598 
599     LINK_target_cluster_height = more_data(&rest, argv, argc);
600     RETURN_IF_FAULT(rest);
601 
602     LINK_target_unit_x         = more_data(&rest, argv, argc);
603     RETURN_IF_FAULT(rest);
604 
605     LINK_target_unit_y         = more_data(&rest, argv, argc);
606     RETURN_IF_FAULT(rest);
607 
608     LINK_target_move_delta_x   = more_data(&rest, argv, argc);
609     RETURN_IF_FAULT(rest);
610 
611     LINK_target_move_delta_y   = more_data(&rest, argv, argc);
612     RETURN_IF_FAULT(rest);
613 
614     if (*argc > 0 && strcmp(**argv, "+") == 0)
615     {
616 	(*argc)--;
617 	(*argv)++;
618     }
619 
620     return correct_link_input();
621 }
622 
623 #undef RETURN_IF_FAULT
624 
625 /*****************************************************************************
626   FUNCNCTION : correct_link_input
627 
628   PURPOSE  : tests whether the input datas of Edit Link are correct and decides
629              what kind of link (PLANE_TO_PLANE, PLANE_TO_LINK...) we have.
630 
631   NOTES    :
632   RETURNS  : Correct = 1 ; ERROR = 0
633 
634   UPDATE   : 20.12.1991
635 ******************************************************************************/
correct_link_input(void)636 static int correct_link_input(void)
637 {
638     PLANE *PLANE_source_no, *PLANE_target_no;
639 
640     int link_type;
641     int target_plane=0, source_plane=0;
642     int target_cluster=0, source_cluster=0;
643     int target_unit=0, source_unit=0;
644     int a,b,c,d;
645 
646     PLANE_source_no = get_plane(LINK_source_plane);
647     PLANE_target_no = get_plane(LINK_target_plane);
648 
649     LINK_move = 0;
650 
651 
652     /* check plane numbers */
653     if((PLANE_source_no == NULL) || (PLANE_target_no == NULL))
654 	return 0;
655 
656     /* check source plane dimensions */
657     if((LINK_source_cluster_x + LINK_source_cluster_width
658 	> (*PLANE_source_no).width + 1) ||
659        (LINK_source_cluster_y + LINK_source_cluster_height
660 	> (*PLANE_source_no).height + 1) ||
661        (LINK_source_unit_x > (*PLANE_source_no).width) ||
662        (LINK_source_unit_y > (*PLANE_source_no).height))
663 	return 0;
664 
665     /* check target plane dimensions */
666     if((LINK_target_cluster_x + LINK_target_cluster_width
667 	> (*PLANE_target_no).width + 1) ||
668        (LINK_target_cluster_y + LINK_target_cluster_height
669 	> (*PLANE_target_no).height + 1) ||
670        (LINK_target_unit_x > (*PLANE_target_no).width) ||
671        (LINK_target_unit_y > (*PLANE_target_no).height))
672 	return 0;
673 
674     target_plane = TARGET_PLANE;
675     source_plane = SOURCE_PLANE;
676 
677     a = b = c = d = 0;
678 
679     if(((a=LINK_source_cluster_x) >= 1) && ((b=LINK_source_cluster_y) >= 1) &&
680        ((c=LINK_source_cluster_width) >= 1) &&
681        ((d=LINK_source_cluster_height) >= 1)) {
682 	source_cluster = SOURCE_CLUSTER;
683     }
684 
685     if((! source_cluster) && a+b+c+d)
686 	return 0;
687 
688     a = b = 0;
689 
690     if(((a=LINK_source_unit_x) >= 1) && ((b=LINK_source_unit_y) >= 1))
691 	source_unit = SOURCE_UNIT;
692 
693     if((! source_unit) && a+b)
694 	return 0;
695 
696     a = b = c = d = 0;
697 
698     if(((a=LINK_target_cluster_x) >= 1) && ((b=LINK_target_cluster_y) >= 1) &&
699        ((c=LINK_target_cluster_width) >= 1) &&
700        ((d=LINK_target_cluster_height) >= 1)) {
701 	target_cluster = TARGET_CLUSTER;
702     }
703 
704     if((! target_cluster) && a+b+c+d)
705 	return 0;
706 
707     a = b = 0;
708 
709     if(((a=LINK_target_unit_x) >= 1) && ((b=LINK_target_unit_y) >= 1))
710 	target_unit = TARGET_UNIT;
711 
712     if((! target_unit) && a+b)
713 	return 0;
714 
715     link_type = target_plane + source_plane + target_cluster+
716 	source_cluster + target_unit + source_unit;
717 
718     if((link_type == PLANE_TO_PLANE) || (link_type == PLANE_TO_CLUSTER) ||
719        (link_type == PLANE_TO_UNIT) ||  (link_type == CLUSTER_TO_PLANE) ||
720        (link_type == CLUSTER_TO_CLUSTER) || (link_type == CLUSTER_TO_UNIT) ||
721        (link_type == UNIT_TO_PLANE) ||(link_type == UNIT_TO_CLUSTER) ||
722        (link_type == UNIT_TO_UNIT)) {
723 
724 	LINK_type_of_connection = link_type;
725 
726 	if((LINK_source_move_delta_x || LINK_source_move_delta_y ||
727 	    LINK_target_move_delta_x || LINK_target_move_delta_y) &&
728 	   ((link_type==CLUSTER_TO_CLUSTER) || (link_type==CLUSTER_TO_UNIT) ||
729 	    (link_type==UNIT_TO_CLUSTER)    || (link_type == UNIT_TO_UNIT))) {
730 	    LINK_move = 1;
731 	} else {
732 	    LINK_source_move_delta_x =
733 		LINK_source_move_delta_y =
734 		LINK_target_move_delta_x =
735 		LINK_target_move_delta_y = 0;
736 	}
737     }
738 
739     return 1;
740 }
741 
742 
743 /*****************************************************************************
744   FUNCTION : enter_link
745 
746   PURPOSE  : enters a link element at the end of the link list.
747 
748   NOTES    :
749   RETURNS  :
750 
751   UPDATE   : 20.12.1991
752 ******************************************************************************/
753 
enter_link(void)754 static void enter_link(void)
755 
756 {
757     LINK *LINK_element;
758 
759     LINK_element = (LINK *)malloc(sizeof(LINK));
760 
761     (*LINK_element).SOURCE.plane          = LINK_source_plane;
762     (*LINK_element).SOURCE.CLUSTER.x      = LINK_source_cluster_x;
763     (*LINK_element).SOURCE.CLUSTER.y      = LINK_source_cluster_y;
764     (*LINK_element).SOURCE.CLUSTER.width  = LINK_source_cluster_width;
765     (*LINK_element).SOURCE.CLUSTER.height = LINK_source_cluster_height;
766     (*LINK_element).SOURCE.UNIT.x         = LINK_source_unit_x;
767     (*LINK_element).SOURCE.UNIT.y         = LINK_source_unit_y;
768     (*LINK_element).SOURCE.MOVE.delta_x   = LINK_source_move_delta_x;
769     (*LINK_element).SOURCE.MOVE.delta_y   = LINK_source_move_delta_y;
770 
771     (*LINK_element).TARGET.plane          = LINK_target_plane;
772     (*LINK_element).TARGET.CLUSTER.x      = LINK_target_cluster_x;
773     (*LINK_element).TARGET.CLUSTER.y      = LINK_target_cluster_y;
774     (*LINK_element).TARGET.CLUSTER.width  = LINK_target_cluster_width;
775     (*LINK_element).TARGET.CLUSTER.height = LINK_target_cluster_height;
776     (*LINK_element).TARGET.UNIT.x         = LINK_target_unit_x;
777     (*LINK_element).TARGET.UNIT.y         = LINK_target_unit_y;
778     (*LINK_element).TARGET.MOVE.delta_x   = LINK_target_move_delta_x;
779     (*LINK_element).TARGET.MOVE.delta_y   = LINK_target_move_delta_y;
780 
781     (*LINK_element).move                  = LINK_move;
782     (*LINK_element).type_of_connection    = LINK_type_of_connection;
783 
784     (*LINK_element).next   = NULL;
785     (*LINK_element).before = LINK_last_element;
786 
787     if(LINK_last_element != NULL) {
788 	(*LINK_last_element).next = LINK_element;
789     }
790 
791     if(LINK_first_element == NULL) {
792 	LINK_first_element = LINK_element;
793     }
794 
795     LINK_last_element = LINK_element;
796     LINK_current_element = LINK_last_element;
797 
798     LINK_length++;
799 }/* enter_link */
800 
801 
802 
803 /*****************************************************************************
804   FUNCTION : read_plane_elements
805 
806   PURPOSE  : reads the input datas of the plane editor (Edit Plane).
807 
808   NOTES    :
809   RETURNS  :  Error = 0 ; Succes = 1
810 
811   UPDATE   : 20.12.1991
812 ******************************************************************************/
813 
read_plane_elements(int * argc,char ** argv[])814 static int read_plane_elements(int *argc, char **argv[])
815 {
816 
817     if (*argc > 0)
818     {
819 	PLANE_width = atoi(**argv);
820 	(*argv)++;
821 	(*argc)--;
822     }
823     else return 0;
824 
825     if (*argc > 0)
826     {
827 	PLANE_height = atoi(**argv);
828 	(*argv)++;
829 	(*argc)--;
830     }
831     else return 0;
832 
833     PLANE_type = BN_HIDDEN;
834     PLANE_type_was_set = 0;
835     PLANE_act_func = DEFAULT_ACT_FUNC;
836     PLANE_out_func = DEFAULT_OUT_FUNC;
837 
838     if (*argc > 0 && krui_isFunction(**argv, ACT_FUNC))
839     {
840 	PLANE_act_func = **argv;
841 	(*argv)++;
842 	(*argc)--;
843 	if (*argc > 0 && krui_isFunction(**argv, OUT_FUNC))
844 	{
845 	    PLANE_out_func =  **argv;
846 	    (*argv)++;
847 	    (*argc)--;
848 
849 	    if (*argc > 0)
850 	    {
851 		if (strcasecmp(**argv, "input") == 0)
852 		{
853 		    PLANE_type = BN_INPUT;
854 		    PLANE_type_was_set = 1;
855 		    (*argv)++;
856 		    (*argc)--;
857 		}
858 		else if (strcasecmp(**argv, "hidden") == 0)
859 		{
860 		    PLANE_type = BN_HIDDEN;
861 		    PLANE_type_was_set = 1;
862 		    (*argv)++;
863 		    (*argc)--;
864 		}
865 		else if (strcasecmp(**argv, "output") == 0)
866 		{
867 		    PLANE_type = BN_OUTPUT;
868 		    PLANE_type_was_set = 1;
869 		    (*argv)++;
870 		    (*argc)--;
871 		}
872 	    }
873 	}
874     }
875 
876     return (PLANE_width > 0 && PLANE_height > 0) ? 1 : 0;
877 }
878 
879 
880 /*****************************************************************************
881   FUNCTION : enter_plane
882 
883   PURPOSE  : enters a plane element at the end of the plane list.
884 
885   NOTES    :
886   RETURNS  :
887 
888   UPDATE   : 20.12.1991
889 ******************************************************************************/
890 
enter_plane(void)891 static void enter_plane(void)
892 
893 {
894     PLANE *PLANE_element;
895 
896     PLANE_element = (PLANE *)malloc(sizeof(PLANE));
897     (*PLANE_element).width  = PLANE_width;
898     (*PLANE_element).height = PLANE_height;
899     (*PLANE_element).pos    = BN_RIGHT;
900     (*PLANE_element).type   = PLANE_type;
901     (*PLANE_element).type_was_set = PLANE_type_was_set;
902     (*PLANE_element).act_func = PLANE_act_func;
903     (*PLANE_element).out_func = PLANE_out_func;
904     (*PLANE_element).next   = NULL;
905     (*PLANE_element).before = PLANE_last_element;
906 
907     if(PLANE_last_element != NULL) {
908 	(*PLANE_last_element).next = PLANE_element;
909     }
910 
911     if(PLANE_first_element == NULL) {
912 	PLANE_first_element = PLANE_element;
913     }
914 
915     PLANE_last_element = PLANE_element;
916     PLANE_current_element = PLANE_last_element;
917 
918     PLANE_no = ++PLANE_length;
919 }
920 
921 
922 /*****************************************************************************
923   FUNCTION : get_plane
924 
925   PURPOSE  : returns a pointer to the plane element "plane_no"
926 
927   NOTES    :
928   RETURNS  : returns a pointer to the plane element "plane_no"
929 
930   UPDATE   : 20.12.1991
931 ******************************************************************************/
932 
get_plane(int plane_no)933 static PLANE *get_plane(int plane_no)
934 
935 {
936     PLANE *PLANE_element = PLANE_first_element;
937     int counter = 1;
938 
939     while((PLANE_element != NULL) &&
940 	  (counter != plane_no)) {
941 	counter++;
942 	PLANE_element = (*PLANE_element).next;
943 
944     }
945     return PLANE_element;
946 }
947 
948 
949 /*****************************************************************************
950   FUNCTION : usage
951 
952   PURPOSE  : gives usage information
953 
954   NOTES    :
955   RETURNS  :
956 
957   UPDATE   :
958 ******************************************************************************/
usage(void)959 void usage(void)
960 {
961 
962     fprintf(stderr, "usage: ff_bignet <plane definition> ... <link definition> ... [<output file>]\n");
963     fprintf(stderr, "\n");
964     fprintf(stderr, "<plane definition> : -p <x> <y> [<act> [<out> [<type>]]]\n");
965     fprintf(stderr, "                      <x>   : number of units in x-direction\n");
966     fprintf(stderr, "                      <y>   : number of units in y-direction\n");
967     fprintf(stderr, "                      <act> : opt. activation function\n");
968     fprintf(stderr, "                              e.g.: Act_Logistic\n");
969     fprintf(stderr, "                      <out> : opt. activation function, <act> must be given too\n");
970     fprintf(stderr, "                              e.g.: Out_Identity\n");
971     fprintf(stderr, "                      <type>: opt. layer type, <act> and <out> must be given too\n");
972     fprintf(stderr, "                              valid types: input, hidden, or output\n\n");
973     fprintf(stderr, "<link defintion>   : -l <sp> ... [+] <tp> ... [+]\n");
974     fprintf(stderr, "                      Link parameters must be given in the following order.\n");
975     fprintf(stderr, "                      All remaing Parameters within one section may be filled\n");
976     fprintf(stderr, "                      with 0 by giving the '+' character (0 means: not used)\n\n");
977     fprintf(stderr, "                      Source section:\n");
978     fprintf(stderr, "                      <sp>  : source plane (1, 2, ...)\n");
979     fprintf(stderr, "                      <scx> : x position of source cluster\n");
980     fprintf(stderr, "                      <scy> : y position of source cluster\n");
981     fprintf(stderr, "                      <scw> : width of source cluster\n");
982     fprintf(stderr, "                      <sch> : height of source cluster\n");
983     fprintf(stderr, "                      <sux> : x position of a distinct source unit\n");
984     fprintf(stderr, "                      <suy> : y position of a distinct source unit\n");
985     fprintf(stderr, "                      <smx> : delta x for multiple source fields\n");
986     fprintf(stderr, "                      <smy> : delta y for multiple source fields\n\n");
987     fprintf(stderr, "                      Target section:\n");
988     fprintf(stderr, "                      <tp>  : target plane (1, 2, ...)\n");
989     fprintf(stderr, "                      <tcx> : x position of target cluster\n");
990     fprintf(stderr, "                      <tcy> : y position of target cluster\n");
991     fprintf(stderr, "                      <tcw> : width of target cluster\n");
992     fprintf(stderr, "                      <tch> : height of target cluster\n");
993     fprintf(stderr, "                      <tux> : x position of a distinct target unit\n");
994     fprintf(stderr, "                      <tuy> : y position of a distinct target unit\n");
995     fprintf(stderr, "                      <tmx> : delta x for multiple target fields\n");
996     fprintf(stderr, "                      <tmy> : delta y for multiple target fields\n\n");
997     fprintf(stderr, "<output file>      : name of the output file (default SNNS_FF_NET.net)\n");
998     exit(1);
999 }
1000 
1001 /*****************************************************************************
1002   FUNCTION : main
1003 
1004   PURPOSE  :
1005 
1006   NOTES    :
1007   RETURNS  :
1008 
1009   UPDATE   :
1010 ******************************************************************************/
1011 
main(int argc,char * argv[])1012 int main(int argc, char *argv[])
1013 {
1014     char *file_name;
1015     int err;
1016 
1017     file_name = "SNNS_FF_NET.net";
1018 
1019     if (argc <= 1)
1020 	usage();
1021 
1022     argc--;
1023     argv++;
1024     while (argc > 0)
1025     {
1026 	if (strcmp(*argv, "-p") == 0)
1027 	{
1028 	    argc--;
1029 	    argv++;
1030 
1031 	    if (!read_plane_elements(&argc, &argv)){
1032 		fprintf(stderr, "Illegal plane definition\n");
1033 		exit(1);
1034 	    }
1035 
1036 	    enter_plane();
1037 	}
1038 	else if (strcmp(*argv, "-l") == 0)
1039 	{
1040 	    argc--;
1041 	    argv++;
1042 
1043 	    if (!read_link_elements(&argc, &argv)){
1044 		fprintf(stderr, "Illegal link definition\n");
1045 		exit(1);
1046 	    }
1047 
1048 	    enter_link();
1049 	}
1050 	else
1051 	{
1052 	    if (argc != 1)
1053 	    {
1054 		fprintf(stderr, "Parameters not understood. Invalid function or type name?\n");
1055 		exit(1);
1056 	    }
1057 	    file_name = *argv;
1058 	    argc--;
1059 	    argv++;
1060 	}
1061     }
1062 
1063     if(PLANE_first_element != NULL && !PLANE_first_element->type_was_set)
1064     {
1065 	PLANE_first_element -> type = BN_INPUT;
1066     }
1067 
1068     if(PLANE_last_element != NULL && !PLANE_last_element->type_was_set)
1069     {
1070 	PLANE_last_element -> type = BN_OUTPUT;
1071     }
1072 
1073     create_net_PROC();
1074 
1075     err = krui_setUpdateFunc("Topological_Order");
1076     if (err != KRERR_NO_ERROR){
1077 	fprintf(stderr, "%s\n", krui_error(err));
1078 	exit(1);
1079     }
1080     err = krui_setLearnFunc("Std_Backpropagation");
1081     if (err != KRERR_NO_ERROR){
1082 	fprintf(stderr, "%s\n", krui_error(err));
1083 	exit(1);
1084     }
1085     err = krui_saveNet(file_name, "SNNS_FF_NET");
1086     if (err != KRERR_NO_ERROR){
1087 	fprintf(stderr, "%s\n", krui_error(err));
1088 	exit(1);
1089     }
1090 
1091     exit(0);
1092 }
1093 
1094 /* end of file */
1095