[ return ]

wire.c



/*
 * file: wire.c
 *
 * [DEFINE DESCRIPTION = Automatic network wiring module]
 *
 *  Name                Date        Description
 *  --------------      --------    -------------------------------------
 *  Andrew H. Fagg      01/22/95    Original
 *
 *
 *  High-level representation of cell response properties.  This information 
 * is used to compute a set of connections for the network.
 *
 */

#include "stdio.h"
/*
#include "nsl_include.h"
*/
#include "gen.h"
#include "wire.h"
#include "strings.h"

/*
  * int load_AIP(char * fname, struct AIP_type AIP[], int num_AIP)
  *
  *  Load an AIP description file.
  *   <fname> = the name of the file to load.
  *   <AIP> = output set of structures.
  *   <num_AIP> = the maximum number of structures that will fit in <AIP>
  *
  *  Return = 0 if an error occurs
  *         = the number of elements actually read.
  *
  *  Note: if there are more elements in the file than <num_AIP> allows
  *    for, then these are ignored and a warning is printed.
  *
  */

int load_AIP(char * fname, struct AIP_type AIP[], int num_AIP)
{
  FILE *fp;
  char strg[BUF_SIZE];
  int i, j;
  int ret;
  float f;
  int flag;

  i = 0;
  flag = 0;
				/* Open file */
  if((fp = fopen(fname, "r")) == NULL)
    {
      printf("load_AIP: Error opening input file (%s).\n", fname);
      return(0);
    }
				/* Read header */
  if(fscanf(fp, "%s\n", strg) != 1)
    {
      printf("load_AIP: Error reading header\n");
      fclose(fp);
      return(0);
    }
				/* Check header is valid */
  if(strcmp(strg, "AIP"))
    {
      printf("load_AIP: Error parsing header\n");
      fclose(fp);
      return(0);
    }

				/* Read records */
				/* Note iterates 1 extra time - this */
				/*  case will be caught below. */
  for(i = 0; i <= num_AIP; ++i)
    {
				/* Get Phase Descriptor */
      if((ret = fscanf(fp, "%s\n", strg)) != 1)
	{
	  if(ret == EOF)
	    {
	      flag = 1;
	      break;
	    }
	  printf("load_AIP: Error reading header\n");
	  fclose(fp);
	  return(0);
	}
				/* Have we found 1 too many records */
      if(i == num_AIP)
	{
	  printf("load_AIP: Warning: more records in file that will fit.\n");
	  break;		/* Terminate loop */
	}
				/* Figure out which Phase descriptor */
				/*  this is */
      if(!strcmp(strg, "SET"))
	{
	  AIP[i].phase = AIP_PHASE_SET;
	}
      else if(!strcmp(strg, "EARLY"))
	{
	  AIP[i].phase = AIP_PHASE_EARLY;
	}
      else if(!strcmp(strg, "LATE"))
	{
	  AIP[i].phase = AIP_PHASE_LATE;
	}
      else
	{
	  printf("load_AIP: Error parsing phase descriptor: %s\n", strg);
	  fclose(fp);
	  return(0);
	}

				/* Read grip type descriptor */
      for(j = 0; j < NUM_GRIP_TYPE; ++j)
	{
				/* If float not found, then just stop */
				/* reading for this unit. */
	  if(fscanf(fp, "%f", &f) != 1)
	    {
	      printf("load_AIP: Error parsing grip type descriptor.\n");
	      fclose(fp);
	      return(0);
	    }
	  AIP[i].grip_type[j] = f;	  
	}
				/* Read vm_index */
      if(fscanf(fp, "%f", &AIP[i].vm_index) != 1)
	{
	  printf("load_AIP: Error parsing vm_index.\n");
	  fclose(fp);
	  return(0);
	}

				/* Read grip_width */
      if(fscanf(fp, "%f", &AIP[i].grip_width) != 1)
	{
	  printf("load_AIP: Error parsing grip_width.\n");
	  fclose(fp);
	  return(0);
	}
    }
  fclose(fp);
  return(i);
}


/*
  * int load_F5(char * fname, struct F5_type F5[], int num_F5)
  *
  *  Load an F5 description file.
  *   <fname> = the name of the file to load.
  *   <F5> = output set of structures.
  *   <num_F5> = the maximum number of structures that will fit in <F5>
  *
  *  Return = 0 if an error occurs
  *         = the number of elements actually read.
  *
  *  Note: if there are more elements in the file than <num_F5> allows
  *    for, then these are ignored and a warning is printed.
  *
  */

int load_F5(char * fname, struct F5_type F5[], int num_F5)
{
  FILE *fp;
  char strg[BUF_SIZE];
  int i, j;
  int ret;
  float f;
  int flag;

  i = 0;
  flag = 0;
				/* Open file */
  if((fp = fopen(fname, "r")) == NULL)
    {
      printf("load_F5: Error opening input file (%s).\n", fname);
      return(0);
    }
				/* Read header */
  if(fscanf(fp, "%s\n", strg) != 1)
    {
      printf("load_F5: Error reading header\n");
      fclose(fp);
      return(0);
    }
				/* Check header is valid */
  if(strcmp(strg, "F5"))
    {
      printf("load_F5: Error parsing header\n");
      fclose(fp);
      return(0);
    }

				/* Read records */
				/* Note iterates 1 extra time - this */
				/*  case will be caught below. */
  for(i = 0; i <= num_F5; ++i)
    {
				/* Get Phase Descriptor Vector */

				/* First element */
      if((ret = fscanf(fp, "%f", &f)) != 1)
	{
	  flag = 1;		/* No more left. */
	  break;
	}
				/* Have we found 1 too many records? */
      if(i == num_F5)
	{
	  printf("load_F5: Warning: more records in file that will fit.\n");
	  break;		/* Terminate loop */
	}

      F5[i].phase[0] = f;	/* Store this first value */

				/* Get rest of the elements. */
      for(j = 1; j < NUM_PHASE_TYPE; ++j)
	{
	  if((ret = fscanf(fp, "%f", &f)) != 1)
	    {
				/* Interpret this as an error. */
	      printf("load_F5: Error parsing phase descriptor vector\n");
	      fclose(fp);
	      return(0);
	    }
	  F5[i].phase[j] = f;
	}


				/* Read grip type descriptor */
      for(j = 0; j < NUM_GRIP_TYPE; ++j)
	{
	  if(fscanf(fp, "%f", &f) != 1)
	    {
	      printf("load_F5: Error parsing phase descriptor vector\n");
	      fclose(fp);
	      return(0);
	    }
	  F5[i].grip_type[j] = f;	  
	}

				/* Read grip_width */
      if(fscanf(fp, "%f", &F5[i].grip_width) != 1)
	{
	  printf("load_F5: Error parsing grip_width.\n");
	  fclose(fp);
	  return(0);
	}
    }
  fclose(fp);
  return(i);
}


/*
  * float gauss(float value, float std)
  *
  *  
  *
  */

float gauss(float value, float std)
{
  return(exp(-(Square(value)/std)));
}


/*
  * float compare_grip_type(float gt1[NUM_GRIP_TYPE], float gt2[NUM_GRIP_TYPE],
  *			float std)
  *
  *  Provide a measure for how well the grip type of two cells match
  * one-another.
  *
  */

float compare_grip_type(float gt1[NUM_GRIP_TYPE], float gt2[NUM_GRIP_TYPE])
{
  int i;
  float out;
  
  for(out = 0, i = 0; i < NUM_GRIP_TYPE; ++i)
    {
      out += gt1[i] * gt2[i];
    }
  return(MIN(1.0, out));
}


/*
  * float compare_grip_width(float gw1, float gw2, float std)
  *
  *  Provide a measure for how well the grip width of two cells match.
  *
  *  Return = 0 .. 1 -> match factor
  *         = -1     -> no constraint
  *         = -2     -> projection from 1 to 2 is more specific
  *         = -3     -> projection from 1 to 2 is more general
  */

float compare_grip_width(float gw1, float gw2, float std)
{
  float out;

				/* Check to see if there are any */
				/*  degenerate conditions... */
  if(gw1 == -1 && gw2 == -1)
    return(-1);
  else if(gw1 == -1)
    return(-2);
  else if(gw2 == -1)
    return(-3);

  return(gauss(gw1-gw2, std));
}


/*
  * float compare_AIP_AIP(struct AIP_type * AIP1, struct AIP_type * AIP2,
  *		      float grip_std, int * flags)
  *
  *  Determine whether a supporting connection should be added between
  * two AIP units.
  *  Return = degree of match
  *         <flags> is set to:
  *           -1     -> no constraint
  *           -2     -> projection from 1 to 2 is more specific
  *           -3     -> projection from 1 to 2 is more general
  *            0     -> otherwise
  *
  */

float compare_AIP_AIP(struct AIP_type * AIP1, struct AIP_type * AIP2,
		      float grip_std, int * flags)
{
  float out;
  float gw;

				/* Grip Type */
  out = compare_grip_type(AIP1->grip_type, AIP2->grip_type);

				/* Grip Width */
  gw = compare_grip_width(AIP1->grip_width, AIP2->grip_width, grip_std);

				/* Filter if widths don't match. */
  if(gw >= 0.0)
    {
      out = out * gw;
      *flags = 0;
    }
  else
    {
      *flags = (int) gw;
    }
				/* Check phase. */

  switch (AIP2->phase)
    {
    case AIP_PHASE_EARLY:
      if(AIP1->phase == AIP_PHASE_SET)
	out = 0.0;
      break;
    case AIP_PHASE_LATE:
      if(AIP1->phase == AIP_PHASE_SET || AIP1->phase == AIP_PHASE_EARLY)
	out = 0.0;
      break;
    }
  
  return(out);
}


/*
  * float compare_AIP_F5(struct AIP_type * AIP,
  *		     struct F5_type * F5,
  *		     float grip_std)
  *
  *  Determine whether a supporting connection should be added
  * from an AIP to and F5 unit.
  *  Right now, we are ignoring phase information, since we are
  * only priming.
  *
  */

float compare_AIP_F5(struct AIP_type * AIP,
		     struct F5_type * F5,
		     float grip_std,
		     int * flags)
{
  float out;
  float gw;

				/* Grip type */
  out = compare_grip_type(AIP->grip_type, F5->grip_type);

				/* How large of a grip? */
  gw = compare_grip_width(AIP->grip_width, F5->grip_width, grip_std);
  
				/* Interpret grip */
  if(gw >= 0.0)
    {
      out = out * gw;		/* There is a grip constraint */
      *flags = 0;
    }
  else
    {
      *flags = (int) gw;	/* No grip constraint - what type? */
    }

				/* Check phase - irrelevant right now. */
  
  return(out);
}


float compare_F5_AIP(struct F5_type * F5,
		     struct AIP_type * AIP,
		     float grip_std,
		     int * flags)
{
  float out;
  float gw;

				/* Grip type */
  out = compare_grip_type(AIP->grip_type, F5->grip_type);

				/* How large of a grip? */
  gw = compare_grip_width(F5->grip_width, AIP->grip_width, grip_std);
  
				/* Interpret grip */
  if(gw >= 0.0)
    {
      out = out * gw;		/* There is a grip constraint */
      *flags = 0;
    }
  else
    {
      *flags = (int) gw;	/* No grip constraint - what type? */
    }

				/* Modulate by input influence of F5 units */
  out *= AIP->vm_index;

				/* Check phase. */

  switch (AIP->phase)
    {
    case AIP_PHASE_EARLY:
      if(F5->phase[F5_PHASE_SET] > 0.0 || F5->phase[F5_PHASE_PREMOVEMENT]        //OVERLOAD CALL: F5_PHASE_SET: net.h(?), wire.h(?)
	 || F5->phase[F5_PHASE_FLEXION])        //OVERLOAD CALL: F5_PHASE_FLEXION: net.h(?), wire.h(?)
	out = 0.0;
      break;
    case AIP_PHASE_LATE:
      if(F5->phase[F5_PHASE_SET] > 0.0 || F5->phase[F5_PHASE_PREMOVEMENT]        //OVERLOAD CALL: F5_PHASE_SET: net.h(?), wire.h(?)
	 || F5->phase[F5_PHASE_FLEXION])        //OVERLOAD CALL: F5_PHASE_FLEXION: net.h(?), wire.h(?)
	out = 0.0;
      break;
    }
  return(out);
}

/*
  * float compute_time(float phase[NUM_PHASE_TYPE])
  *
  *  Compute the mean position of the activity in the PHASE vector for
  * an F5 unit.  Here, we are assuming that phases are separated
  * by a constant number of time units, which is not true, but it should
  * give us a useable measure...
  *
  */

float compute_time(float phase[NUM_PHASE_TYPE])
{
  int i;
  float out;
  float sum;
 
  for(out = sum = 0.0, i = 0; i < NUM_PHASE_TYPE; ++i)
    {
      out += phase[i] * i;
      sum += phase[i];
    }
  
  if(sum > 0.0001)		/* Make sure it is a legal division. */
    return(out/sum);
  else
    return(0.0);
}

/*
  * float compare_F5_F5(struct F5_type * F5_1,
  *                     struct F5_type * F5_2,
  *     		float grip_std,
  *                     float phase_epsilon,
  *		        float distant_factor,
  *		        float good_threshold,
  *		        int * flags)
  *
  *  Computes the level of support an F5 unit should be giving another
  * F5 unit.
  *  Return >0 if positive
  *          0 if none
  *         <0 if negative.
  *
  *  Assumption: generalization/specialization relationiship is not
  * considered in this computation: probably will need to fix.
  *
  */

float compare_F5_F5(struct F5_type * F5_1,
		    struct F5_type * F5_2,
		    float grip_std,        /*  How well do grip sizes need */
				           /* to match?  */
		    float phase_epsilon,   /*  Allow small mismatch in phase*/
		    float distant_factor,  /*  How much to discount in P> */
		                           /* case.   */
		    float good_threshold,  /*  What do we consider a good */
		                           /* match.  */
		    int * flags)

{
  float out;
  float gw;
  float ph1;
  float ph2;
  
				/* Grip type */
  out = compare_grip_type(F5_1->grip_type, F5_2->grip_type);

				/* How large of a grip? */
  gw = compare_grip_width(F5_1->grip_width, F5_2->grip_width, grip_std);
  
				/* Interpret grip */
  if(gw >= 0.0)
    {
      out = out * gw;		/* There is a grip constraint */
      *flags = 0;
    }
  else
    {
      *flags = (int) gw;	/* No grip constraint - what type? */
    }

				/* Check phase. */

  ph1 = compute_time(F5_1->phase);
  ph2 = compute_time(F5_2->phase);

  if(out >= good_threshold)	/* Good match or not? */
    {
      if(ph1-phase_epsilon > ph2) /* Yes, but does T1 come after T2? */
	{
	  out *= -1;		/* Yes, then it should inhibit */
	}
    }
  else
    {				/* Inhibit in all cases */
      out = 1 - out;
      if(ph1-phase_epsilon > ph2) /* Lessen damage when match is bad. */
	out *= distant_factor;
    }
  return(out);
}


[ return ]