Category : Miscellaneous Language Source Code
Archive   : NETS_1.ZIP
Filename : NET.C

 
Output of file : NET.C contained in archive : NETS_1.ZIP
/*=============================*/
/* NETS */
/* */
/* a product of the AI Section */
/* NASA, Johnson Space Center */
/* */
/* principal author: */
/* Paul Baffes */
/* */
/* contributing authors: */
/* Bryan Dulock */
/* Chris Ortiz */
/*=============================*/


/*
----------------------------------------------------------------------
Code For Manipulation Of Net Structures (Prefix = N_)
----------------------------------------------------------------------
This code is divided into 3 major sections:

(1) include files
(2) externed functions
(3) subroutines

Each section is further explained below.
----------------------------------------------------------------------
*/


/*
----------------------------------------------------------------------
INCLUDE FILES
----------------------------------------------------------------------
*/
#include "common.h"
#include "weights.h"
#include "layer.h"
#include "net.h"
#include "netio.h"


/*
----------------------------------------------------------------------
EXTERNED FUNCTIONS AND GLOBALS
----------------------------------------------------------------------
Below are the functions defined in other files which are used by the
code here. They are organized by section.
----------------------------------------------------------------------
*/
extern void P_prop_input();
extern float IO_my_get_float();
extern int PS_get_float_from_file();
extern int PS_skip_tokens();
extern Sint C_float_to_Sint();
extern float C_Sint_to_float();
extern char *sys_alloc();
extern void IO_print();
extern void IO_reset_more();
extern int IO_more();
extern void IO_insert_format();

extern FILE *PA_open_binary();
extern void PA_write_signature();
extern int PA_check_signature();
extern int PA_get_from_workfile();
extern int PA_put_to_workfile();
extern void PA_flush();
extern void PA_put_ascii_wts();
extern Sint PA_get_ascii_wts();

extern char IO_str[MAX_LINE_SIZE];
extern char IO_wkstr[MAX_LINE_SIZE];


/*
======================================================================
ROUTINES IN NET.C
======================================================================
The routines in this file are grouped below by function. Each routine
is prefixed by the string "N_" indicating that it is defined in the
"net.c" file. The types returned by the routines are also shown here
so that cross checking is more easily done between these functions
and the other files which intern them.


Type Returned Routine
------------- -------
Layer * N_get_layer
void N_query_net
int N_propagate_and_print
int N_reset_wts
void N_save_wts
======================================================================
*/


Layer *N_get_layer(ptr_net, source)
Net *ptr_net;
int source;
/*
----------------------------------------------------------------------
This routine searches through the list of layers associated with a
net (pointed to by 'ptr_net') and returns a pointer to the layer
with an ID equal to the 'source' number passed in. If no such layer
is found, then an 'error layer' is returned; ie, a new layer is
created with an ID = -1 (see the net.h file).
----------------------------------------------------------------------
*/
BEGIN
Layer_lst *next_layer;
Layer *dummy;

if (ptr_net->input_layer->ID == source)
return(ptr_net->input_layer);

if (ptr_net->output_layer->ID == source)
return(ptr_net->output_layer);

next_layer = ptr_net->hidden_front;
while (next_layer != NULL) BEGIN
if (next_layer->value->ID == source)
return(next_layer->value);
next_layer = next_layer->next;
ENDWHILE

dummy = (Layer *) sys_alloc((unsigned)sizeof(Layer));
dummy->ID = ERROR;
return(dummy);

END /* N_get_layer */


void N_query_net(ptr_net, in_file, out_fp, num_props)
Net *ptr_net;
char *in_file;
FILE *out_fp;
int num_props;
/*
----------------------------------------------------------------------
This routine is used for passing input to the net to see what sort of
output comes out. In other words, once you have taught a net you
probably want to give it inputs and have outputs returned. This
routine takes care of that.

Most of the work for this routine has already been coded. All that
needs to be done is to read in the inputs that the user wants tested
and then propagate them through the net. Then the outputs are
printed to the screen or a file, depending on the users input.

The input for propagation can come either from the screen or a file,
and the same is true of the output. If the in_file is empty, then the
user is prompted from the screen. If the output file POINTER is NULL
the output goes to the screen.

NOTE if "num_props" comes in as -1, this means the routine should
propagate all the inputs it can find in the file. Otherwise, the
routine should propagate num_props number of inputs.
----------------------------------------------------------------------
*/
BEGIN
int i;
int count, N_propagate_and_print();
float tf1;
FILE *fp;

/*-----------------------------------------------*/
/* first reset the more function before printing */
/*-----------------------------------------------*/
IO_reset_more();

/*-------------------------------------------*/
/* input from the screen if in_file is empty */
/*-------------------------------------------*/
if (in_file[0] == ENDSTRING) BEGIN
for (i = 0; i < ptr_net->input_layer->num_nodes; i++) BEGIN
sprintf(IO_str, "\n Enter input for node %d: ", i);
IO_more(0);
tf1 = IO_my_get_float();
ptr_net->input_layer->node_outputs[i] = C_float_to_Sint(tf1);
ENDFOR
N_propagate_and_print(ptr_net, out_fp, 1);
ENDIF

/*------------------------------------*/
/* Otherwise, get input from the file */
/*------------------------------------*/
else BEGIN

/*---------------------------------------*/
/* open file; quit if it can't be opened */
/*---------------------------------------*/
if((fp = fopen(in_file, "rt")) == NULL) BEGIN
sprintf(IO_str, "\n*** can't open file %s for propagation ***\n", in_file);
IO_more(0);
return;
ENDIF

/*-----------------------------------*/
/* next, loop for as many pairs as */
/* the user specified in "num_props" */
/*-----------------------------------*/
count = 1;
while (PS_skip_tokens(fp, "(") == OK) BEGIN
/*-------------------------------------------*/
/* if past number of props, quit propagating */
/*-------------------------------------------*/
if (num_props >= 0)
if (count > num_props) break;

/*--------------------------*/
/* Read inputs from in_file */
/*--------------------------*/
for (i = 0; i < ptr_net->input_layer->num_nodes; i++) BEGIN
if (PS_get_float_from_file(fp, &tf1) == OK)
ptr_net->input_layer->node_outputs[i] = C_float_to_Sint(tf1);

/*-----------------------------------*/
/* quit if not enough inputs in file */
/*-----------------------------------*/
else BEGIN
sprintf(IO_str, "\n*** error: input %d too short ***\n",
count);
IO_more(0);
return;
ENDELSE
ENDFOR

if (N_propagate_and_print(ptr_net, out_fp, count) == ERROR) return;
count++;
ENDWHILE

/*----------------------*/
/* close file when done */
/*----------------------*/
fclose(fp);
ENDELSE

END /* N_query_net */


int N_propagate_and_print(ptr_net, out_fp, input_num)
Net *ptr_net;
FILE *out_fp;
int input_num;
/*
----------------------------------------------------------------------
This routine is used for passing input to the net to see what sort of
output comes out. In other words, once you have taught a net you
probably want to give it inputs and have outputs returned. This
routine takes care of that. The inputs are passed to this function
by the pointer ptr_net. The inputs are propagated through the network
and displayed at the terminal or written to a file depending of out_fp.
The "input_num" indicates the number of the input being processed
which is used as part of the output.
NOTE that this guy assumes the inputs have been properly setup on the
input layer of the network BEFORE this routine is called.
---------------------------------------------------------------------
*/
BEGIN
int i, num_outs;
float tf1;

/*---------------------*/
/* propagate the input */
/*---------------------*/
P_prop_input(ptr_net);

/*--------------------------------------------*/
/* send output to screen if out_fp is == NULL */
/*--------------------------------------------*/
if (out_fp == NULL) BEGIN
sprintf(IO_str, "\n\nThe Outputs for Input %d are:\n", input_num);
if (IO_more(0) == ERROR)
return(ERROR);
for (i = 0; i < ptr_net->output_layer->num_nodes; i++) BEGIN
tf1 = C_Sint_to_float(ptr_net->output_layer->node_outputs[i]);
sprintf(IO_wkstr, " for node %d the value %%.f\n", i);
IO_insert_format(IO_wkstr);
sprintf(IO_str, IO_wkstr, tf1);
if (IO_more(0) == ERROR)
return(ERROR);
ENDFOR
ENDIF

/*--------------------------------------------*/
/* otherwise, try to open the output file and */
/* write out the results of the propagation */
/*--------------------------------------------*/
else BEGIN
num_outs = ptr_net->output_layer->num_nodes;
fprintf(out_fp, "\nOutputs for Input %d:\n(", input_num);
for (i = 0; i < num_outs; i++) BEGIN
tf1 = C_Sint_to_float(ptr_net->output_layer->node_outputs[i]);
sprintf(IO_wkstr, "%%.f%c", ((i%6 == 5) || (i==num_outs-1) ? '\n' : ' ') );
IO_insert_format(IO_wkstr);
fprintf( out_fp, IO_wkstr, tf1);
ENDFOR
fprintf(out_fp, ")\n");
ENDELSE
return(OK);

END /* N_propagate_and_print */


int N_reset_wts(ptr_net, file_name, format)
Net *ptr_net;
char file_name[];
int format;
/*
----------------------------------------------------------------------
This routine resets the weights of a net using a file specified by
the user. The idea is to move through the hidden layers list from
the front, reading in values for all the incoming weights to a layer
Note that both the incoming and outgoing weight values do not need
to be read in since the outgoing weights of one layer are the same
as the incoming weights of the target layer. Note also that the
order of the movement through the hidden layers list is significant.
By starting at the front we skip over the input layer, thus we must
use INCOMING weights, otherwise we would never set the weights
coming OUT of layer 0! Of course, we don't have to worry about any
weights coming out of layer 1 (the output) because the output layer
is defined as having no outgoing weights.
A new addition to this routine (8-16-89) checks to see if the file
has a "signature" which matches the format desired by the user. This
is done using the BIN_SIG (see common.h file) which is a hexidecimal
code written to a binary file (ie FAST_FORMAT file) at the very top.
If this signature is not present, the file is assumed to be PORTABLE_
FORMAT. If the presence/lack of the signature does not match with
the desired format, then an error is returned (see PA_check_signature).
----------------------------------------------------------------------
*/
BEGIN
Weights_lst *cur_weight;
Layer_lst *cur_layer;
Sint *wt_values, tmp_Sint, *bias_values;
int STATUS, flag, s_size, t_size, j;
int32 num_weights, i;
FILE *fp;

/*---------------------------------------------*/
/* check that the file format matches "format" */
/*---------------------------------------------*/
if (PA_check_signature(file_name, format) == ERROR)
return(ERROR);

if (format == PORTABLE_FORMAT)
fp = fopen(file_name, "rt");
else
fp = PA_open_binary(file_name, READ_MODE);

if (fp == NULL) BEGIN
sprintf(IO_str, "\n*** error, file %s cannot be opened ***\n", file_name);
IO_print(0);
STATUS = ERROR;
ENDIF
else BEGIN
/*-------------------------------------------------*/
/* once the file is open, init the value of STATUS */
/* and if a bin file, throw away the first 2-bytes */
/* since it will be the binary signature value */
/*-------------------------------------------------*/
STATUS = OK;
if (format == FAST_FORMAT)
fread((char *)(&tmp_Sint), SIG_SIZE, 1, fp);

cur_layer = ptr_net->hidden_front;
while ((cur_layer != NULL) && (STATUS == OK)) BEGIN /* for each layer */
/*--------------------------------------*/
/* then read in weight values for layer */
/*--------------------------------------*/
cur_weight = cur_layer->value->in_weights;
while ((cur_weight != NULL) && (STATUS == OK)) BEGIN
wt_values = cur_weight->value->values;
s_size = cur_weight->value->source_size;
t_size = cur_weight->value->target_size;
if (cur_weight->value->type == CONNECT_ALL)
num_weights = ((int32) s_size) * ((int32) t_size);
else if (s_size < t_size)
num_weights = ((int32) s_size) * ((int32) cur_weight->value->map_area);
else
num_weights = ((int32) t_size) * ((int32) cur_weight->value->map_area);
for (i = 0; i < num_weights; i++) BEGIN
/*--------------------------------------------*/
/* read in the next Sint from the appropriate */
/* file, depending upon the reading format */
/*--------------------------------------------*/
if ( format == PORTABLE_FORMAT )
flag = PA_get_ascii_wts(fp, &tmp_Sint);
else
flag = PA_get_from_workfile(fp, &tmp_Sint);

/*-------------------------------------*/
/* if everything went well, keep going */
/*-------------------------------------*/
if (flag == OK)
wt_values[i] = tmp_Sint;
else BEGIN
STATUS = ERROR;
break; /* break out of 'for' loop */
ENDELSE
ENDFOR
cur_weight = cur_weight->next;
ENDWHILE
cur_layer = cur_layer->next;
ENDWHILE

/*--------------------------------------------*/
/* if not enough values for weights then quit */
/*--------------------------------------------*/
if (STATUS == ERROR) BEGIN
sprintf(IO_str, "\n*** Not enough values to reset all weights ***\n");
IO_print(0);
ENDIF
/*--------------------------------*/
/* otherwise, get the bias values */
/*--------------------------------*/
else BEGIN
STATUS = OK;
cur_layer = ptr_net->hidden_front;
while ((cur_layer != NULL) && (STATUS == OK)) BEGIN /* for each layer */
/*-------------------------------*/
/* read in bias values for layer */
/*-------------------------------*/
bias_values = cur_layer->value->node_bias;
for (j = 0; j < cur_layer->value->num_nodes; j++) BEGIN
if (format == PORTABLE_FORMAT)
flag = PA_get_ascii_wts(fp, &tmp_Sint);
else
flag = PA_get_from_workfile(fp, &tmp_Sint);
if (flag == OK)
bias_values[j] = tmp_Sint;
else BEGIN
STATUS = ERROR;
break; /* break out of 'for' loop */
ENDELSE
ENDFOR
cur_layer = cur_layer->next;
ENDWHILE
ENDELSE

if (STATUS == ERROR) BEGIN
sprintf(IO_str, "\n*** Not enough values to reset all biases ***\n");
IO_print(0);
ENDIF
fclose(fp);
ENDELSE
return(STATUS);

END /* N_reset_wts */


void N_save_wts(ptr_net, file_name, format)
Net *ptr_net;
char file_name[];
int format;
/*
----------------------------------------------------------------------
This routine is identical to the one above, except for the error
messages and the fact that the weights are being saved and not re-
stored. Note that a call to 'PA_flush' is made here. That is done
to make sure that the contents of the buffer are emptied to the
output file.
----------------------------------------------------------------------
*/
BEGIN
Weights_lst *cur_weight;
Layer_lst *cur_layer;
Sint *wt_values, *bias_values;
int STATUS, j, s_size, t_size;
int32 num_weights, i;
FILE *fp;

if (format == PORTABLE_FORMAT)
fp = fopen(file_name, "wt");
else
fp = PA_open_binary(file_name, WRITE_MODE);

if ( fp == NULL ) BEGIN
sprintf(IO_str, "\n*** error, file %s cannot be opened ***\n", file_name);
IO_print(0);
ENDIF
else BEGIN
/*-----------------------------------------------*/
/* once the file is open, set the status flag to */
/* OK and output the binsignature if bin file */
/*-----------------------------------------------*/
STATUS = OK;
if (format == FAST_FORMAT)
PA_write_signature(fp, BIN_SIG);

cur_layer = ptr_net->hidden_front;
while ((cur_layer != NULL) && (STATUS == OK)) BEGIN
/*-----------------------------*/
/* write out weights for layer */
/*-----------------------------*/
cur_weight = cur_layer->value->in_weights;
while ((cur_weight != NULL) && (STATUS == OK)) BEGIN
wt_values = cur_weight->value->values;
s_size = cur_weight->value->source_size;
t_size = cur_weight->value->target_size;
if (cur_weight->value->type == CONNECT_ALL)
num_weights = ((int32) s_size) * ((int32) t_size);
else if (s_size < t_size)
num_weights = ((int32)s_size) * ((int32)cur_weight->value->map_area);
else
num_weights = ((int32)t_size) * ((int32)cur_weight->value->map_area);

/*------------------------------------------------*/
/* after setting up, either print out as ascii or */
/* as binary, depending on the value of "format" */
/*------------------------------------------------*/
if (format == PORTABLE_FORMAT)
PA_put_ascii_wts(wt_values, num_weights, fp);
else
for (i = 0; i < num_weights; i++)
if ((PA_put_to_workfile(fp, wt_values[i])) == ERROR) BEGIN
STATUS = ERROR;
break; /* break out of 'for' loop */
ENDIF
cur_weight = cur_weight->next;
ENDWHILE
cur_layer = cur_layer->next;
ENDWHILE

/*----------------------------------------*/
/* if error writing out weights then quit */
/*----------------------------------------*/
if (STATUS == ERROR) BEGIN
sprintf(IO_str, "\n*** error, not all weights were written ***\n");
IO_print(0);
ENDIF
/*--------------------------------------*/
/* otherwise, write out the bias values */
/*--------------------------------------*/
else BEGIN
STATUS = OK;
cur_layer = ptr_net->hidden_front;
while ((cur_layer != NULL) && (STATUS == OK)) BEGIN
/*---------------------------------*/
/* write out bias values for layer */
/*---------------------------------*/
bias_values = cur_layer->value->node_bias;
if ( format == PORTABLE_FORMAT )
PA_put_ascii_wts(bias_values, (int32)cur_layer->value->num_nodes, fp);
else
for (j = 0; j < cur_layer->value->num_nodes; j++)
if ((PA_put_to_workfile(fp, bias_values[j])) == ERROR) BEGIN
STATUS = ERROR;
break; /* break out of 'for' loop */
ENDIF
cur_layer = cur_layer->next;
ENDWHILE
ENDELSE /* loop for biases */

/*---------------------------------------*/
/* check again for error before flushing */
/* the file and quitting the routine */
/*---------------------------------------*/
if (STATUS == ERROR) BEGIN
sprintf(IO_str, "\n*** error, not all biases were written ***\n");
IO_print(0);
ENDIF
if ( format == FAST_FORMAT ) PA_flush(fp);
fclose(fp);
ENDELSE

END /* N_save_wts */


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : NETS_1.ZIP
Filename : NET.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/