/*     @(#)bignet.c	1.9 2/28/94  */

/*****************************************************************************
  FILE           : bignet.c
  SHORTNAME      : bignet.c
  SNNS VERSION   : 3.2

  PURPOSE        :  SNNS-Network Generator for special 3 Layer Feedforward Networks
  NOTES          :

  AUTHOR         : Niels Mache
  DATE           : 01.10.90

  CHANGED BY     : Sven Doering
  IDENTIFICATION : @(#)bignet.c	1.9 2/28/94
  SCCS VERSION   : 1.9
  LAST CHANGE    : 2/28/94

             Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG

******************************************************************************/
#include <stdio.h>
#include <stdlib.h>

/*  SNNS-Kernel constants and data type definitions  */
#include "glob_typ.h"
/*  SNNS-Kernel User-Interface Function Prototypes   */
#include "kr_ui.h"



static void  errChk( err_code )
int  err_code;
{
  if (err_code != KRERR_NO_ERROR)  {
    printf( "%s\n", krui_error( err_code ));
    exit( 1 );
  }
}

int main()
{
  int	ret_code, i, j, unit_no;
  int   IUnits, OUnits, HUnits;
  char	 netname[80], file_name[80];
  struct PosType    unit_pos;
  float  initialize_params[5];


  printf( "\n%s\n", krui_getVersion() );
  printf( "----  Network Generator for 3 Layer Feedforward Networks  ----\n\n" );

  printf( "No. of input units: " );
  scanf( "%i", &IUnits );
  printf( "No. of output units: " );
  scanf( "%i", &OUnits );
  printf( "No. of hidden units: " );
  scanf( "%i", &HUnits );

  if ((IUnits <= 0) || (OUnits <= 0) || (HUnits <= 0))  {
     printf( "\nInvalid no. of units !\n" );
     exit( 1 );
  }

  /*  Allocate units (the user may or may not use this function,
      there is no need to do this but it's useful for the kernel memory
      management to call this function before creating units)
  */
  printf( "\nCreate Units now ...\n" );
  ret_code = krui_allocateUnits( OUnits + HUnits + IUnits );
  errChk( ret_code );

  /*  Create standard (input) Units  */
  unit_pos.x = 0;
  for (i = 1; i <= IUnits; i++)  {
    unit_no = krui_createDefaultUnit();
    if (unit_no < 0)  errChk( unit_no );
    ret_code = krui_setUnitTType( unit_no, INPUT );
    errChk( ret_code );

    unit_pos.y = i;
    krui_setUnitPosition( unit_no, &unit_pos );
  }

  /*  Create standard (hidden) Units  */
  unit_pos.x = 10;
  for (i = 1; i <= HUnits; i++)  {
    unit_no = krui_createDefaultUnit();
    if (unit_no < 0)  errChk( unit_no );
    ret_code = krui_setUnitTType( unit_no, HIDDEN );
    errChk( ret_code );

    unit_pos.y = i;
    krui_setUnitPosition( unit_no, &unit_pos );
  }

  /*  Create standard (output) Units  */
  unit_pos.x = 20;
  for (i = 1; i <= OUnits; i++)  {
    unit_no = krui_createDefaultUnit();
    if (unit_no < 0)  errChk( unit_no );
    ret_code = krui_setUnitTType( unit_no, OUTPUT );
    errChk( ret_code );

    unit_pos.y = i;
    krui_setUnitPosition( unit_no, &unit_pos );
  }


  /* Make Connections now */
  /* Make connections between hidden units and output units first !  */
printf("make connections\n");

  for (i = IUnits + HUnits + 1; i <= IUnits + HUnits + OUnits; i++)
    {  /*  Make output unit to current unit  */
    ret_code = krui_setCurrentUnit( i );
    errChk( ret_code );

    for (j = IUnits + 1; j <= IUnits + HUnits; j++)
      {  /*  connect current (output) unit with hidden unit. REMEMBER: The hidden unit #j
	     is the predecessor of the (output) unit #i (it is a backward connection) */
      ret_code = krui_createLink( j, 0.0 );
      errChk( ret_code );
    }
  }

  /* Make connections between input units and hidden units  */
  for (i = IUnits + 1; i <= IUnits + HUnits; i++)
    {  /*  Make hidden unit to current unit  */
    ret_code = krui_setCurrentUnit( i );
    errChk( ret_code );

    for (j = 1; j <= IUnits; j++)
      {  /*  (backward) connect current (hidden) unit with input unit  */
      ret_code = krui_createLink( j, 0.0 );
      errChk( ret_code );
    }
  }

  /*  initialize the pseudo random generator with a really random value  */
  krui_setSeedNo( 0 );

  /*  randomize all link weights in the range [-1.0,+1.0] */
  ret_code = krui_setInitialisationFunc( "Randomize_Weights" );
  errChk( ret_code );

  initialize_params[ 0 ] = -1.0;  /*  lower bound  */
  initialize_params[ 1 ] = 1.0;   /*  upper bound  */
  ret_code = krui_initializeNet( initialize_params, 2 );
  errChk( ret_code );
  /*  set the update function  */
  ret_code = krui_setUpdateFunc( "Topological_Order" );
  errChk( ret_code );

  /*  save the network	*/
  printf( "\nName of the network: " );
  scanf( "%s", netname );
  printf( "Filename of the network to save: " );
  scanf( "%s", file_name );
  printf( "Saving the network ...\n" );
  ret_code = krui_saveNet( file_name, netname );
  errChk( ret_code );

  /*  before exiting: delete network  */
  krui_deleteNet();

  return( 0 );
}
