void simulate_interaction(){ int i; int t; int j; double W; double ds[4] = {V.d1,-1*V.d1,V.d2,-1*V.d2}; //set action function according to strategy if(V.contrite1 == 0 || V.d1 < 0) V.action1 = &get_action_remorseless; else V.action1 = &get_action_contrite; if(V.contrite2 == 0 || V.d2 < 0) V.action2 = &get_action_remorseless; else V.action2 = &get_action_contrite; for(i = 0; i < 6; i++){ V.history[i] = 0;}//start history for(i = 0; i < 16; i++){ V.rep_hitory[i] = 0;}//start reputation state history for(t = 0; t < P.T; t++){ for(i = 0; i < 4; i++){ V.good[i] = 1;}//everyone starts off good if( V.d1 < 0){ V.good[0] = 0;V.good[1] = 0; } //defectors hate everyone if( V.d2 < 0){ V.good[2] = 0;V.good[3] = 0; } //defectors hate everyone //make sure new_good mirrors good, for efficient updates later for(i = 0; i<4; i++){V.new_good[i] = V.good[i];} //first turn, always happens act_and_record(); //simulate W **SUBSEQUENT** interactions W = rand_geo(V.w)-1; //Geometric number of *subsequent* turns for(j = 0; j < W; j++){ //update signals V.signals[1] = r4_nor ( &seed, kn, fn, wn ) + V.actions[1] * V.M; //A's signal of B V.signals[2] = r4_nor ( &seed, kn, fn, wn ) + V.actions[0] * V.M; //B's signal of A if(P.confused == 1){ //in a confused world, I know what I did, but not what you did... if(V.actions[0] > 0) V.signals[0] = INT_MAX; else V.signals[0] = INT_MIN; if(V.actions[1] > 0) V.signals[3] = INT_MAX; else V.signals[3] = INT_MIN; } else { //in a concordant world, we get the same signal V.signals[0] = V.signals[2]; //A's signal of A is B's signal of A V.signals[3] = V.signals[1]; //B's signal of B is A's signal of B } //update reputation, based on signals P.Reputation_function(ds); //act and record act_and_record(); } } V.print_function(); }
// generate random number in normal distribution // input: arr, number arr // input: size, size of the array // input: max_number, maximum number void random_number_generator_normal(float* arr, int size, int max_number){ uint32_t kn[128]; float fn[128], wn[128]; r4_nor_setup ( kn, fn, wn); float rnd; uint32_t seed = (uint32_t)time(NULL); float var = sqrt(max_number); for ( int i = 0; i < size; i++){ rnd = r4_nor(&seed, kn, fn, wn); arr[i] = max_number/2 + rnd*var; } }
double rnorm(){ return r4_nor( &seed, kn, fn, wn ); }
double rand_normal(int variance) { return variance*r4_nor( &seed, kn, fn, wn ); }
csr_matrix rand_csr(const unsigned int N,const unsigned int density, const double normal_stddev,unsigned long* seed,FILE* log) { unsigned int i,j,nnz_ith_row,nnz,update_interval,rand_col; double nnz_ith_row_double,nz_error,nz_per_row_doubled,high_bound; int kn[128]; float fn[128],wn[128]; char* used_cols; csr_matrix csr; csr.num_rows = N; csr.num_cols = N; csr.density_perc = (((double)(density))/10000.0); csr.nz_per_row = (((double)N)*((double)density))/1000000.0; csr.num_nonzeros = round(csr.nz_per_row*N); csr.stddev = normal_stddev * csr.nz_per_row; //scale normalized standard deviation by average NZ/row fprintf(log,"Average NZ/Row: %-8.3f\n",csr.nz_per_row); fprintf(log,"Standard Deviation: %-8.3f\n",csr.stddev); fprintf(log,"Target Density: %u ppm = %g%%\n",density,csr.density_perc); fprintf(log,"Approximate NUM_nonzeros: %d\n",csr.num_nonzeros); csr.Ap = (unsigned int *) int_new_array(csr.num_rows+1,"rand_csr() - Heap Overflow! Cannot Allocate Space for csr.Ap"); csr.Aj = (unsigned int *) int_new_array(csr.num_nonzeros,"rand_csr() - Heap Overflow! Cannot Allocate Space for csr.Aj"); csr.Ap[0] = 0; nnz = 0; nz_per_row_doubled = 2*csr.nz_per_row; //limit nnz_ith_row to double the average because negative values are rounded up to 0. This high_bound = MINIMUM(csr.num_cols,nz_per_row_doubled); //limitation ensures the distribution will be symmetric about the mean, albeit not truly normal. used_cols = (char *) malloc(csr.num_cols*sizeof(char)); check(used_cols != NULL,"rand_csr() - Heap Overflow! Cannot allocate space for used_cols"); r4_nor_setup(kn,fn,wn); srand(*seed); update_interval = round(csr.num_rows / 10.0); if(!update_interval) update_interval = csr.num_rows; for(i=0; i<csr.num_rows; i++) { if(i % update_interval == 0) fprintf(log,"\t%d of %d (%5.1f%%) Rows Generated. Continuing...\n",i,csr.num_rows,((double)(i))/csr.num_rows*100); nnz_ith_row_double = r4_nor(seed,kn,fn,wn); //random, normally-distributed value for # of nz elements in ith row, NORMALIZED nnz_ith_row_double *= csr.stddev; //scale by standard deviation nnz_ith_row_double += csr.nz_per_row; //add average nz/row if(nnz_ith_row_double < 0) nnz_ith_row = 0; else if(nnz_ith_row_double > high_bound) nnz_ith_row = high_bound; else nnz_ith_row = (unsigned int) round(nnz_ith_row_double); csr.Ap[i+1] = csr.Ap[i] + nnz_ith_row; if(csr.Ap[i+1] > csr.num_nonzeros) csr.Aj = (unsigned int *) realloc(csr.Aj,sizeof(unsigned int)*csr.Ap[i+1]); for(j=0; j<csr.num_cols; j++) used_cols[j] = 0; for(j=0; j<nnz_ith_row; j++) { rand_col = abs(gen_rand(0,csr.num_cols - 1)); //unsigned long is always non-negative if(used_cols[rand_col]) { j--; } else { csr.Aj[csr.Ap[i]+j] = rand_col; used_cols[rand_col] = 1; } } qsort((&(csr.Aj[csr.Ap[i]])),nnz_ith_row,sizeof(unsigned int),unsigned_int_comparator); } nz_error = ((double)abs((signed int)(csr.num_nonzeros - csr.Ap[csr.num_rows]))) / ((double)csr.num_nonzeros); if(nz_error >= .05) fprintf(stderr,"WARNING: Actual NNZ differs from Theoretical NNZ by %5.2f%%!\n",nz_error*100); csr.num_nonzeros = csr.Ap[csr.num_rows]; fprintf(log,"Actual NUM_nonzeros: %d\n",csr.num_nonzeros); csr.density_perc = (((double)csr.num_nonzeros)*100.0)/((double)csr.num_cols)/((double)csr.num_rows); csr.density_ppm = (unsigned int)round(csr.density_perc * 10000.0); fprintf(log,"Actual Density: %u ppm = %g%%\n",csr.density_ppm,csr.density_perc); free(used_cols); csr.Ax = (float *) float_new_array(csr.num_nonzeros,"rand_csr() - Heap Overflow! Cannot Allocate Space for csr.Ax"); for(i=0; i<csr.num_nonzeros; i++) { csr.Ax[i] = 1.0 - 2.0 * common_randJS(); while(csr.Ax[i] == 0.0) csr.Ax[i] = 1.0 - 2.0 * common_randJS(); } return csr; }