/* * 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); }