/*********************** * Simulation of TODAM * *********************** * * October 1992 * * Peter Nobel & David Huber * Indiana University * Bloomington, IN 47405 * * pnobel@ucs.indiana.edu & dhuber@ucs.indiana.edu * * This program simulates the following test-conditions: * single item recognition * associative recognition: intact - rearranged * associative recognition: intact - mixed * associative recognition: intact - new * cued recall * */ #include #include #include #include #include #include #include #define MAX_ENTRIES 10000 typedef struct { char *name; char *val; } entry; char *makeword(char *line, char stop); char *fmakeword(FILE *f, char stop, int *len); char x2c(char *what); void unescape_url(char *url); void plustospace(char *str); #define RAND_MAX 2147483648.0 /* the maximum number returned by rand */ #define NSIM 500 /* maximum number of simulations */ #define NMAX 32 /* maximum number of pairs on a list */ #define FMAX 63 /* maximum number of features */ #define SMAXW 3 /* maximum strength weak items */ #define SMAXS 5 /* maximum strength strong items */ #define TRUE 1 #define SIZE1 7 /* number of items menu 1 */ #define SIZE2 6 /* number of items menu 2 */ #define SIZE3 2 /* number of items menu 3 */ #define SIZE4 4 /* number of items menu 4 */ #define SIZE5 8 /* number of items menu 5 */ #define SIZE6 3 /* number of items menu 6 */ #define integer int /* used in d-prime function */ #define real float static integer c__9 = 9; static integer c__1 = 1; static integer c__4 = 4; float hrate; float farate; float dp; FILE *fp; /* file pointer to output file */ char fout[100]; /* output file name */ FILE *fptemp; /*********************** * function prototypes * ***********************/ void menu(void); void making_matrix(void); void study(void); void recognition_single(void); void recognition_ass_rearr(void); void recognition_ass_mixed(void); void recognition_ass_new(void); void cued_recall(void); void ranset(void); void perm(int *, int); void simulate(void); void results(void); void settings(void); void screen(void); void action1(int); void action2(int); void action3(int); void action4(int); void action5(int); void action6(int); float rand1(void); float gau(double, double); int randw(int); int cor_win(int); float single_fam(int); float double_fam(int, int); int decision(float); void convolve(int, int); void correlate(int); /******************** * menu definitions * ********************/ char *menu1[] = { "Select type of test", "Set length of list", "Set strength of list", "Set parameters", "Simulation", "Write results", "Exit", }; char *menu2[] = { "Single item recognition", "Assoc. recog. - rearranged", "Assoc. recog. - mixed", "Assoc. recog. - new", "Cued recall", "Return to Main Menu", }; char *menu3[] = { "Set length of list (number of pairs)", "Return to Main Menu", }; char *menu4[] = { "Pure weak", "Pure strong", "Mixed", "Return to Main Menu", }; char *menu5[] = { "Number of Features", "Power", "Forgetting parameter", "Weights", "Criterion (recog.)", "Decision system", "Criterion (recall)", "Return to Main Menu", }; char *menu6[] = { "Number of simulations", "Simulate", "Return to Main Menu", }; /****************************** * variables for menu control * ******************************/ int curpos; /* keeps track of the cursor in the menu (rows) */ int code; /* reads in the (extended) code of key pressed */ int back; /* switch between menus: 0 = stay, 1 = return */ /*************************************** * global variables for the simulation * ***************************************/ int nsim=50; /* number of simulations */ int cond=1; /* type of test */ int n=8; /* the length of the list (# of pairs): multiples of 8 */ int length; /* actual number of presentations */ int strength=1; /*strength of the list: 1-pure weak, 2-pure strong, 3-mixed */ int s1=1; /* strength of weak items */ int s2=2; /* strength of strong items */ /********************************** * global variables for the model * **********************************/ float mu; /* mean of noise */ float sigma; /* std dev of noise */ float new_memory[FMAX][FMAX]; float matrix1[FMAX][FMAX]; float crit; float recall_crit; int features; float learn; float items[NMAX*4][FMAX]; /* max no. of different items of FMAX features */ float memory[FMAX]; /* memory vector */ float convolved[FMAX]; /* two convolved items */ float correlated[FMAX]; /* item correlated with memory vector */ int order[NMAX*SMAXS]; /* order of presentation of pairs */ int count, /* counter for the number of simulations */ count_cw, /* counter for weak corrects in cued recall */ count_cs, /* counter for strong corrects in cued recall */ count_hw, /* counter for weak hits in recognition */ count_hs, /* counter for strong hits in recognition */ count_f, /* counter for false alarms in recognition */ count_fs; /* counter for strong false alarms (ass) */ float famtw, /* total sum familiarity: weak targets */ famtw2, /* total sum familiarity squared: weak targets */ famts, /* total sum familiarity: strong targets */ famts2, /* total sum familiarity squared: strong targets */ famd, /* total sum familiarity: distractors */ famd2, /* total sum familiarity squared: distractors */ famds, /* total sum familiarity: strong distractors */ famds2; /* total sum familiarity squared: strong distractors */ float VARTW[NSIM], /* array for variance familiarity: weak targets */ VARTS[NSIM], /* array for variance familiarity: strong targets */ VARD[NSIM], /* array for variance familiarity: distractors */ VARDS[NSIM], /* array for variance familiarity: distractors */ DPRPW[NSIM], /* array for d-prime (weak) based on proportions */ DPRPS[NSIM], /* array for d-prime (strong) based on proportions */ DPRDW[NSIM], /* array for d-prime (weak) based on distributions */ DPRDS[NSIM]; /* array for d-prime (strong) based on distributions */ /**************************** * parameters for the model * ****************************/ int features=15; /* number of features chosen */ float power=1.0; /* power of vector */ float alpha=0.9; /* forgetting parameter */ float gamma1=1.0; /* weight item 1 */ float gamma2=1.0; /* weight item 2 */ float gamma3=1.0; /* weight associative information */ float upper=0.1; /* upper criterion recognition */ float lower=0.1; /* lower criterion recognition */ float noise=0.0; /* variance for decision system */ float rate=0.9; /* convergence rate */ float giveup=0.3; /* cut-off for correlation in recall */ /************************ * variables for output * ************************/ /* cued recall */ float pcw; /* final result recall: weak items */ float pcs; /* final result recall: strong items */ float corw; /* output variable of average correlation for weak targets */ float cors; /* output variable of average correlation for strong targets */ float mycorw; /* output variable of average correlation for weak targets */ float mycors; /* output variable of average correlation for strong targets */ /* recognition: variance and d' for both averaged and total */ float hw; /* final result recognition: weak hits */ float mtw; /* mean familiarity weak targets */ float vartw; /* variance familiarity weak targets (avg.) */ float tvartw; /* variance familiarity weak targets (total) */ float hs; /* final result recognition: strong hits */ float mts; /* mean familiarity strong targets */ float varts; /* variance familiarity strong targets (avg.) */ float tvarts; /* variance familiarity strong targets (total) */ float f; /* final result recognition: false alarms */ float fs; /* final result recognition: strong false alarms */ float md; /* mean familiarity distractors */ float mds; /* mean familiarity strong distractors */ float vard; /* variance familiarity distractors (avg.) */ float vards; /* variance familiarity strong distractors (avg.) */ float tvard; /* variance familiarity distractors (total) */ float tvards; /* variance familiarity strong distractors (total) */ float dprpw; /* dprime based on proportions: weak items (avg.) */ float tdprpw; /* dprime based on proportions: weak items (total) */ float dprps; /* dprime based on proportions: strong items (avg.) */ float tdprps; /* dprime based on proportions: strong items (total) */ float dprdw; /* dprime based on distributions: weak items (avg.) */ float tdprdw; /* dprime based on distributions: weak items (total) */ float dprds; /* dprime based on distributions: strong items (avg.) */ float tdprds; /* dprime based on distributions: strong items (total) */ /******** * MAIN * ********/ main() { entry entries[MAX_ENTRIES]; register int x,m=0; int cl; printf("Content-type: text/html%c%c",10,10); if(strcmp(getenv("REQUEST_METHOD"),"POST")) { printf("This script should be referenced with a METHOD of POST.\n"); printf("If you don't understand this, see this "); printf("forms overview.%c",10); exit(1); } if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) { printf("This script can only be used to decode form results. \n"); exit(1); } cl = atoi(getenv("CONTENT_LENGTH")); for(x=0;cl && (!feof(stdin));x++) { m=x; entries[x].val = fmakeword(stdin,'&',&cl); plustospace(entries[x].val); unescape_url(entries[x].val); entries[x].name = makeword(entries[x].val,'='); if (strcmp(entries[x].name, "TypeOfTest") == 0){ if (strcmp(entries[x].val, "Single item recognition") == 0) cond = 1; else if (strcmp(entries[x].val, "Associative recognition - rearranged") == 0) cond = 2; else if (strcmp(entries[x].val, "Associative recognition - mixed") == 0) cond = 3; else if (strcmp(entries[x].val, "Associative recognition - new") == 0) cond = 4; else if (strcmp(entries[x].val, "Cued recall") == 0) cond = 5; } else if (strcmp(entries[x].name, "ListLength") == 0){ sscanf(entries[x].val, "%d", &n); if (n > NMAX) { printf("Maximum number of pairs is %d!", NMAX); n = NMAX; } if (n % 8 != 0) { /* if not a multiple of 8 */ printf("Number of pairs should be a multiple of 8! Setting list length to 8."); n=8; } } else if (strcmp(entries[x].name, "ListStrength") == 0){ if (strcmp(entries[x].val, "Pure Weak") == 0) strength = 1; else if (strcmp(entries[x].val, "Pure Strong") == 0) strength = 2; else if (strcmp(entries[x].val, "Mixed") == 0) strength = 3; } else if (strcmp(entries[x].name, "WeakStrength") == 0){ sscanf(entries[x].val, "%d", &s1); if (s1 > SMAXW) { printf("Maximum strength for weak items is %d!", SMAXW); s1 = SMAXW; } else if (s1 < 1) { printf("Minimum strength for weak items is 1!"); s1 = 1; } } else if (strcmp(entries[x].name, "StrongStrength") == 0) { sscanf(entries[x].val, "%d", &s2); if (s2 > SMAXS) { printf("Maximum strength for strong items is %d!", SMAXS); s2 = SMAXS; } else if (s2 < 2) { printf("Minimum strength for strong items is 2!"); s2 = 2; } } else if (strcmp(entries[x].name, "NumberOfFeatures") == 0) { sscanf(entries[x].val, "%d", &features); if (features > 32) { printf("Maximum number of features is 32!"); features = 32; } else if (features < 4) { printf("Minimum number of features is 4!"); features = 4; } } else if (strcmp(entries[x].name, "power") == 0) sscanf(entries[x].val, "%f", &power); else if (strcmp(entries[x].name, "alpha") == 0) sscanf(entries[x].val, "%f", &alpha); else if (strcmp(entries[x].name, "gamma1") == 0) sscanf(entries[x].val, "%f", &gamma1); else if (strcmp(entries[x].name, "gamma2") == 0) sscanf(entries[x].val, "%f", &gamma2); else if (strcmp(entries[x].name, "gamma3") == 0) sscanf(entries[x].val, "%f", &gamma3); else if (strcmp(entries[x].name, "upper") == 0) sscanf(entries[x].val, "%f", &upper); else if (strcmp(entries[x].name, "lower") == 0) sscanf(entries[x].val, "%f", &lower); else if (strcmp(entries[x].name, "noise") == 0) sscanf(entries[x].val, "%f", &noise); else if (strcmp(entries[x].name, "rate") == 0) sscanf(entries[x].val, "%f", &rate); else if (strcmp(entries[x].name, "giveup") == 0) sscanf(entries[x].val, "%f", &giveup); else if (strcmp(entries[x].name, "NumberOfSimulations") == 0){ sscanf(entries[x].val, "%d", &nsim); if (nsim > NSIM) { printf("Maximum number simulatoins is %d!", NSIM); nsim = NSIM; } } } printf("

Query Results

"); if (s2 <= s1) printf("Strong items should be stronger than weak ones!
\n"); printf("
\n");
    ranset();                                 /* init the random no generator */
    simulate();
    screen();
    printf("
\n"); } /********************* * FUNCTION SIMULATE * ********************* * * main simulation routine * */ void simulate(void) { int i; count_cw = 0; /* initialize the counters */ count_cs = 0; count_hw = 0; count_hs = 0; count_f = 0; count_fs = 0; count = 0; famtw = 0.0; famtw2 = 0.0; famts = 0.0; famts2 = 0.0; famd = 0.0; famd2 = 0.0; famds = 0.0; famds2 = 0.0; corw = 0.0; cors = 0.0; /* initialize the storage arrays */ for (i=0; i= n/2)) { famts += fam; famts2 += fam * fam; fts += fam; fts2 += fam * fam; } win = decision(fam); if (win == 1) { if ((strength == 1) || (strength == 3 && i < n/2)) { count_hw++; chw++; } if ((strength == 2) || (strength == 3 && i >= n/2)) { count_hs++; chs++; } } } for (i=2*n; i<(2*n)+n; i++) { /* distractors */ fam = single_fam(i); famd += fam; famd2 += fam * fam; fd += fam; fd2 += fam * fam; win = decision(fam); if (win == 1) { count_f++; cf++; } } /* compute results and store in arrays */ if (strength == 3) t = (float)n/2; else t = (float)n; vtw = ((t*ftw2)-(ftw*ftw))/(t*(t-1)); if (vtw < 0.0001) vtw = 0.0001; VARTW[count] = vtw; vts = ((t*fts2)-(fts*fts))/(t*(t-1)); if (vts < 0.0001) vts = 0.0001; VARTS[count] = vts; vdw = (((float)n * fd2)-(fd*fd))/((float)n*((float)n-1)); if (vdw < 0.0001) vdw = 0.0001; VARD[count] = vdw; hrate = (float)chw/t; farate = (float)cf/(float)n; dprime_(&hrate, &farate, &dp); DPRPW[count] = dp; hrate = (float)chs/t; farate = (float)cf/(float)n; dprime_(&hrate, &farate, &dp); DPRPS[count] = dp; DPRDW[count] = ((ftw/t)-(fd/(float)n))/(sqrt(VARD[count])); DPRDS[count] = ((fts/t)-(fd/(float)n))/(sqrt(VARD[count])); count++; } /********************************** * FUNCTION RECOGNITION_ASS_REARR * ********************************** * * associative recognition simulation routine * targets : A-B (intact) * distractors: A-D (rearranged) * */ void recognition_ass_rearr(void) { static real hrate, farate, dp; extern int dprime_(); int i, j; int win; float t; float fam; /* familiarity of test-item */ int chw = 0, chs = 0, cf = 0, cfs = 0; float ftw = 0.0, /* variables to compute means and variances */ ftw2 = 0.0, /* for the target and distractor distibutions */ fts = 0.0, fts2 = 0.0, fd = 0.0, fd2 = 0.0, fds = 0.0, fds2 = 0.0, vtw = 0.0, vts = 0.0, vdw = 0.0, vds = 0.0; for (i=0; i=n/2) count_cs++; } } } /* end function */ /********************* * function CONVOLVE * ********************* * * convolves two vectors, truncates to the number of features, * and centers the result * */ void convolve(int word1, int word2) { int i, j, k; int shift; /* shift for truncated convolution */ float temp[(FMAX*2)-1]; /* temporary storage for full convolution */ for (i=0; i<(2*features)-1; i++) /* initialize */ temp[i] = 0.0; for (i=0; i= hi) /* "yes" response */ win = 1; else if (temp < lo) /* "no" response */ win = 0; else { /* wait */ done=0; do { temp = fam + gau((double)0,(double)noise); adjust = ((hi-lo) - ((hi-lo)*rate))/2; hi -= adjust; lo += adjust; if (temp > hi) { win = 1; done = 1; } if (temp < lo) { win = 0; done = 1; } } while (done == 0); } return win; } /* end function DECISION */ /******************** * FUNCTION COR_WIN * ******************** * * The item in memory with the highest correlation (dot-product) to the * retrieved vector (correlated) is found * */ int cor_win(int wordnr) { int i, k, t; float cor, wincor, total; int win; total=0.0; win=64; wincor=-10.0; for (i=0; i<2*n; i++) { cor=0.0; for (k=0; kwincor) { win=i; wincor=cor; } } if (strength == 1) corw += total/(float)n; else if (strength == 2) cors += total/(float)n; else { if (wordnr < (n/2)) corw += total/(float)n*(float)2.0; else cors += total/(float)n*(float)2.0; } if (wincor NMAX) { printf("Maximum number of pairs is %d!", NMAX); n = NMAX; } if (n % 8 != 0) { /* if not a multiple of 8 */ printf("Number of pairs should be a multiple of 8!"); } break; case 1: back = 1; curpos = 0; break; } } /******************** * FUNCTION ACTION4 * ******************** * * performs action for MENU4 based on cursor position * Strength of list */ void action4(int pos) { int done, i; switch(pos) { case 0: strength = 1; printf("Strength selected: %s. Value = ", menu4[pos]); scanf("%d", &s1); if (s1 > SMAXW) { printf("Maximum strength for weak items is %d!", SMAXW); s1 = SMAXW; } else if (s1 < 1) { printf("Minimum strength for weak items is 1!"); s1 = 1; } break; case 1: strength = 2; printf("Strength selected: %s. Value = ", menu4[pos]); scanf("%d", &s2); if (s2 > SMAXS) { printf("Maximum strength for strong items is %d!", SMAXS); s2 = SMAXS; } else if (s2 < 2) { printf("Minimum strength for strong items is 2!"); s2 = 2; } break; case 2: done=0; strength = 3; while (done==0) { for (i=0; i<1; i++) { printf("Strength selected: %s. Weak item strength = ", menu4[pos]); scanf("%d", &s1); done=1; if (s1 > SMAXW) { printf("Maximum strength for weak items is %d!", SMAXW); done=0; break; } else if (s1 < 1) { printf("Minimum strength for weak items is 1!"); done=0; break; } printf("Strength selected: %s. Strong item strength = ", menu4[pos]); scanf("%d", &s2); if (s2 > SMAXS) { printf("Maximum strength for strong items is %d!", SMAXS); done=0; break; } else if (s2 <= s1) { printf("Strong items must be stronger than weak ones!"); done=0; break; } } } break; case 3: back = 1; curpos = 0; break; } } /******************** * FUNCTION ACTION5 * ******************** * * performs action for MENU5 based on cursor position * Parameters of the model */ void action5(int pos) { int i, done; char c; switch(pos) { case 0: printf("%s = ",menu5[0]); scanf("%d", &features); if (features % 2 == 0) { /* if even */ printf("Number of features should be odd!"); } else { if (features > FMAX) { printf("Maximum number of features is %d!", FMAX); features = FMAX; } else if (features < 3) { printf("Minimum number of features is 3!"); features = 3; } } break; case 1: printf("%s = ",menu5[1]); scanf("%f", &power); if (power < 0) { printf("Power can't be negative!"); power=1.0; } break; case 2: printf("Alpha = "); scanf("%f", &alpha); if (alpha <= 0 || alpha > 1) { printf("Alpha is between 0 and 1!"); alpha=1.0; } break; case 3: done=0; while (done==0) { for (i=0; i<1; i++) { printf("Weight item 1 = "); scanf("%f", &gamma1); done=1; if (gamma1 < 0 || gamma1 > 1) { printf("Weight should be between 0 and 1!"); done=0; break; } printf("Weight item 2 = "); scanf("%f", &gamma2); done=1; if (gamma2 < 0 || gamma2 > 1) { printf("Weight should be between 0 and 1!"); done=0; break; } printf("Weight associative information = "); scanf("%f", &gamma3); if (gamma3 < 0 || gamma3 > 1) { printf("Weight should be between 0 and 1!"); done=0; break; } } } break; case 4: done=0; while (done==0) { for (i=0; i<1; i++) { printf("Lower criterion = "); scanf("%f", &lower); done=1; printf("Upper criterion = "); scanf("%f", &upper); if (upper < lower) { printf("Upper criterion must be higher than lower!"); done=0; break; } } } break; case 5: done=0; while (done==0) { for (i=0; i<1; i++) { printf("Noise variance = "); scanf("%f", &noise); done=1; if (noise < 0) { printf("Variance cannot be negative!"); done=0; break; } printf("Convergence rate = "); scanf("%f", &rate); if (rate <= 0 || rate >= 1) { printf("Rate must be between 0 and 1!"); done=0; break; } } } break; case 6: printf("%s = ",menu5[6]); scanf("%f", &giveup); break; case 7: back = 1; curpos = 0; break; } } /******************** * FUNCTION ACTION6 * ******************** * * performs action for MENU6 based on cursor position * Simulation */ void action6(int pos) { switch(pos) { case 0: if (nsim > 500) { printf("Maximum number of simulations is 500!"); nsim = 500; } break; case 1: simulate(); screen(); back = 1; curpos = 0; break; case 2: back = 1; curpos = 0; break; } } /********************* * FUNCTION SETTINGS * ********************* * * displays values for variables under the menus * */ void settings(void) { printf("Current settings:\n"); printf("\tTest:\t\t\t\t%s (%d sim.)\n", menu2[cond-1], nsim); printf("\tLength:\t\t\t\t%d\n", n); if (strength == 1) printf("\tStrength:\t\t\t%s; value = %d\n", menu4[strength-1], s1); if (strength == 2) printf("\tStrength:\t\t\t%s; value = %d\n", menu4[strength-1], s2); if (strength == 3) printf("\tStrength:\t\t\t%s; weak = %d, strong = %d\n", menu4[strength-1], s1, s2); printf("\t%s:\t\t%d\n", menu5[0], features); printf("\t%s:\t\t\t\t%2.2f\n", menu5[1], power); printf("\t%s:\t\tAlpha = %2.2f\n", menu5[2], alpha); printf("\t%s:\t\t\tGamma1= %2.2f, Gamma2= %2.2f, Gamma3= %2.2f\n", menu5[3], gamma1, gamma2, gamma3); if (cond == 5) { printf("\t%s:\t\tCrit. = %2.3f\n", menu5[6], giveup); } else { printf("\t%s:\t\tLower = %2.3f, Upper = %2.3f\n", menu5[4], lower, upper); printf("\t%s:\t\tNoise var. = %2.3f, Conv. rate = %2.3f\n", menu5[5], noise, rate); } } /******************* * FUNCTION SCREEN * ******************* * * put settings() and results of simulation on screen * */ void screen(void) { char junk; int i; float t, N, S; static real hrate, farate, dp; extern int dprime_(); /* intialize the variables */ pcw = pcs = 0.0; hw = mtw = vartw = tvartw = 0.0; hs = mts = varts = tvarts = 0.0; f = md = vard = tvard = 0.0; fs = mds = vards = tvards = 0.0; dprpw = tdprpw = dprps = tdprps = 0.0; dprdw = tdprdw = dprds = tdprds = 0.0; settings(); N = (float)nsim; if (cond == 2 || cond == 3) { if (strength == 3) t = (float)n/4.0; else t = (float)n/2.0; } else { if (strength == 3) t = (float)n/2.0; else t = (float)n; } S = t*N; if (cond == 5) { /* results cued recall */ pcw=(float)count_cw/(N*t); pcs=(float)count_cs/(N*t); if (strength == 3) { printf("\n\nWeak items:\tP(C) = %.3f\n", pcw); printf("Average correlation = %1.3f\n\n",corw/(float)nsim); printf("Strong items:\tP(C) = %.3f\n", pcs); printf("Average correlation = %1.3f\n",cors/(float)nsim); } else if (strength == 2) { printf("\n\nStrong items:\tP(C) = %.3f\n", pcs); printf("Average correlation = %1.3f\n",cors/(float)nsim); } else { printf("\n\nWeak items:\tP(C) = %.3f\n", pcw); printf("Average correlation = %1.3f\n",corw/(float)nsim); } } else { /* results recognition */ for (i=0; i