/* structure.cpp uses data input from connections_in.dat to generate the full set of connection strengths between subpopulations of neurons */ #include "MersenneTwister.h" #include "dnet.h" extern MTRand rand1; extern MTRand rand2; void NET::WDatin(){ string dummy; int NIpops = NIpops0; ifstream connectin; connectin.open("connections_in.dat"); double state; double W_amp; double W_diag; double W_sigma; double WEE_amp[NEpops]; double WEE_sigma[NEpops]; double Eaxon_sig; double Iaxon_sig; /* The parameters sigma_EE etc. are standard deviations for connection weights (set to zero as default) */ connectin >> sigma_EE >> dummy; connectin >> sigma_EI >> dummy; connectin >> sigma_IE >> dummy; connectin >> sigma_II >> dummy; /* Eaxon_sig and Iaxon_sig can be set to give standard deviation for heterogeneity in synaptic weights (zero by default) */ connectin >> Eaxon_sig >> dummy; connectin >> Iaxon_sig >> dummy; logOut << " Eaxon_sig " << Eaxon_sig << endl; logOut << " Iaxon_sig " << Iaxon_sig << endl; for ( int i = 0; i < NE ; i++){ Eaxonfact[i] = 1.0 + Eaxon_sig*Ran_Gaussian(); if ( Eaxonfact[i] < 0.0 ) Eaxonfact[i] = 0.0; if ( Eaxonfact[i] > 2.0 ) Eaxonfact[i] = 2.0; } for ( int i = 0; i < NE ; i++){ Eaxonfact2[i] = 1.0 + Eaxon_sig*Ran_Gaussian(); if ( Eaxonfact2[i] < 0.0 ) Eaxonfact2[i] = 0.0; if ( Eaxonfact2[i] > 2.0 ) Eaxonfact2[i] = 2.0; } for ( int i = 0; i < NI ; i++){ Iaxonfact[i] = 1.0 + Iaxon_sig*Ran_Gaussian(); if ( Iaxonfact[i] < 0.0 ) Iaxonfact[i] = 0.0; if ( Iaxonfact[i] > 2.0 ) Iaxonfact[i] = 2.0; } for ( int i = 0; i < NI ; i++){ Iaxonfact2[i] = 1.0 + Iaxon_sig*Ran_Gaussian(); if ( Iaxonfact2[i] < 0.0 ) Iaxonfact2[i] = 0.0; if ( Iaxonfact2[i] > 2.0 ) Iaxonfact2[i] = 2.0; } /* Now the main connection strengths */ double WEEij; connectin >> WEEij >> dummy; for ( int j = 0; j < NEpops; j++){ connectin >> state >> dummy; WEE_amp[j] = state*(1.0+sigma_EE*Ran_Gaussian()); } for ( int j = 0; j < NEpops; j++){ connectin >> state >> dummy; WEE_sigma[j] = state; } /* W_asym is an asymmetry factor, set to 1 for symmetric connections between numbered memory subpopulations. W_asym > 1 means slower decay, hence stronger connections from high threshold to low threshold. */ connectin >> state >> dummy; double W_asym = state; ofstream WEEout; WEEout.open("WEEout.dat"); for ( int i = 0; i < NEpops ; i++){ float frac_i = float(i)/float(NEpops-1); for ( int j = 0; j < i ; j++){ float frac_j = float(j)/float(NEpops-1); double d_ij = -frac_j + frac_i; double sig_ij = WEE_sigma[i]; /* Reduce s.d. by a factor W_asym and weaken (strengthen) connections if j < i when W_asym is greater (less) than one */ sig_ij /= W_asym; /* WEEpop[i][j] is strength from j to i */ WEEpop[i][j] = WEEij*exp(-d_ij/sig_ij)/float(NEpops); if ( WEEpop[i][j] < 0.0 ) WEEpop[i][j] = 0.0; } WEEpop[i][i] = WEE_amp[i]; logOut << " WEE " << i+1 << "," << i+1 << " " << WEEpop[i][i] << endl; WEEout << i+1 << " " << i+1 << " " << WEEpop[i][i] << endl; for ( int j = i+1; j < NEpops ; j++){ float frac_j = float(j)/float(NEpops-1); double d_ij = frac_j - frac_i; double sig_ij = WEE_sigma[i]; /* Increase s.d. by a factor W_asym and strengthen (weaken) connections if j > i when W_asym is greater (less) than one */ sig_ij *= W_asym; /* WEEpop[i][j] is strength from j to i */ WEEpop[i][j] = WEEij*exp(-d_ij/sig_ij)/float(NEpops); if ( WEEpop[i][j] < 0.0 ) WEEpop[i][j] = 0.0; // logOut << " WEE " << i+1 << "," << j+1 << " " << WEEpop[i][j] << endl; // WEEout << i+1 << " " << j+1 << " " << WEEpop[i][j] << endl; } } connectin >> state >> dummy; W_amp = state*(1.0+sigma_EI*Ran_Gaussian()); connectin >> state >> dummy; W_diag = state; connectin >> state >> dummy; W_asym = state; connectin >> state >> dummy; W_sigma = state; logOut << " WEI_amp " << W_amp << " WEI_diag " << W_diag << endl; logOut << " WEI_asym " << W_asym << " WEI_sigma " << W_sigma << endl; for ( int i = 0; i < NEpops ; i++){ float frac_i = float(i)/float(NEpops-1); for ( int j = 0; j < NIpops ; j++){ float frac_j; if ( NIpops > 1 ) frac_j = float(j)/float(NIpops-1); else frac_j = 0.5; double d_ij = frac_j - frac_i; if ( d_ij >= 0.0 ) // WEIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) WEIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*double(2*i-NEpops)/double(NEpops)) * exp(-d_ij/W_sigma) / float(NIpops); else // WEIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) WEIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*double(2*i-NEpops)/double(NEpops)) * exp(d_ij/W_sigma) / float(NIpops); if ( WEIpop[i][j] < 0.0 ) WEIpop[i][j] = 0.0; // logOut << " WEI " << i+1 << "," << j+1 << " " << WEIpop[i][j] << endl; } } connectin >> state >> dummy; W_amp = state*(1.0+sigma_IE*Ran_Gaussian()); connectin >> state >> dummy; W_diag = state; connectin >> state >> dummy; W_asym = state; connectin >> state >> dummy; W_sigma = state; logOut << " WIE_amp " << W_amp << " WIE_diag " << W_diag << endl; logOut << " WIE_asym " << W_asym << " WIE_sigma " << W_sigma << endl; for ( int i = 0; i < NIpops ; i++){ float frac_i; if ( NIpops > 1 ) frac_i = float(i)/float(NIpops-1); else frac_i = 0.5; for ( int j = 0; j < NEpops ; j++){ float frac_j = float(j)/float(NEpops-1); double d_ij = frac_j - frac_i; if ( d_ij >= 0.0 ) // WIEpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) WIEpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*double(2*j-NEpops)/double(NEpops) ) * exp(-d_ij/W_sigma) / float(NEpops); else // WIEpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) WIEpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*double(2*j-NEpops)/double(NEpops) ) * exp(d_ij/W_sigma) / float(NEpops); if ( WIEpop[i][j] < 0.0 ) WIEpop[i][j] = 0.0; // logOut << " WIE " << i+1 << "," << j+1 << " " << WIEpop[i][j] << endl; } } connectin >> state >> dummy; W_amp = state*(1.0+sigma_II*Ran_Gaussian()); connectin >> state >> dummy; W_diag = state; connectin >> state >> dummy; W_asym = state; connectin >> state >> dummy; W_sigma = state; logOut << " WII_amp " << W_amp << " WII_diag " << W_diag << endl; logOut << " WII_asym " << W_asym << " WII_sigma " << W_sigma << endl; for ( int i = 0; i < NIpops ; i++){ float frac_i; if ( NIpops > 1 ) frac_i = float(i)/float(NIpops-1); else frac_i = 0.5; for ( int j = 0; j < NIpops ; j++){ float frac_j; if ( NIpops > 1 ) frac_j = float(j)/float(NIpops-1); else frac_j = 0.5; double d_ij = frac_j - frac_i; if ( d_ij >= 0.0 ) WIIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) * exp(-d_ij/W_sigma) / float(NIpops); else WIIpop[i][j] = W_amp*(1.0 + W_diag*frac_j + W_asym*d_ij) * exp(d_ij/W_sigma) / float(NIpops); if ( WIIpop[i][j] < 0.0 ) WIIpop[i][j] = 0.0; // logOut << " WII " << i+1 << "," << j+1 << " " << WIIpop[i][j] << endl; } } for (int j = 0; j < NEpops; j++) { for ( int i = 0; i < NEpops ; i++){ for ( int k = 0; k< NEsub; k++ ){ double fact = 1.0 + sigma_EE*Ran_Gaussian(); if ( fact < 0.0 ) fact = 0.0; if ( fact > 2.0 ) fact = 2.0; WEE[i*NEsub + k][j] = WEEpop[i][j]*fact; // WEEout << i*NEsub + k << " " << j << " " << WEE[i*NEsub + k][j] << endl; } WEEout << i << " " << j << " " << WEE[i*NEsub][j] << endl; } } for (int j = 0; j < NIpops; j++) { for ( int i = 0; i < NEpops ; i++){ for ( int k = 0; k< NEsub; k++ ){ double fact = 1.0 + sigma_EI*Ran_Gaussian(); if ( fact < 0.0 ) fact = 0.0; if ( fact > 2,0 ) fact = 2.0; WEI[i*NEsub + k][j] = WEIpop[i][j]*fact; } } } for (int j = 0; j < NEpops; j++) { for ( int i = 0; i < NIpops ; i++){ for ( int k = 0; k< NIsub; k++ ){ double fact = 1.0 + sigma_IE*Ran_Gaussian(); if ( fact < 0.0 ) fact = 0.0; if ( fact > 2,0 ) fact = 2.0; WIE[i*NIsub + k][j] = WIEpop[i][j]*fact; } } } for (int j = 0; j < NIpops; j++) { for ( int i = 0; i < NIpops ; i++){ for ( int k = 0; k< NIsub; k++ ){ double fact = 1.0 + sigma_II*Ran_Gaussian(); if ( fact < 0.0 ) fact = 0.0; if ( fact > 2,0 ) fact = 2.0; WII[i*NIsub + k][j] = WIIpop[i][j]*fact; } } } /* Now add in connections to readout group */ for (int i = 0; i < NEpops; i++){ connectin >> state >> dummy; WER[i] = state / float(NEpops);; logOut << " WER " << i+1 << " " << WER[i] << endl; } /* Now add in input-integrator connections */ double WEf; // Average feedforward excitation double WEfv; // If non-zero gives a range of excitation (= 0) double WEb; // Excitatory feedback (= 0) double WIf; // Feedforward inhibition (= 0) double WIb; // Feedback inhibition strength from interneurons connectin >> WEf >> dummy; connectin >> WEfv >> dummy; connectin >> WEb >> dummy; connectin >> WIf >> dummy; connectin >> WIb >> dummy; connectin >> WEEin >> dummy; logOut << " WEf " << WEf << endl; logOut << " WEfvary " << WEfv << endl; logOut << " WEb " << WEb << endl; logOut << " WIf " << WIf << endl; logOut << " WIb " << WIb << endl; logOut << " WEEin " << WEEin << endl; for (int i = 0; i< NEpops; i++ ){ WEforward[i] = WEf + WEfv*(double(NEpops-1)/2.0-i)/double(NEpops-1); WEback[i] = WEb/double(NEpops); } for (int i = 0; i< NIpops; i++ ){ WIforward[i] = WIf; WIback[i] = WIb/double(NIpops); } /* Now add in cross-connections to oppositely tuned groups. Note that in the discrete integrator used in the basic discrimination model, there is no negatively tuned set of memory neurons, so all cross-connections are zero */ connectin >> WEEcross >> dummy; connectin >> WEIcross >> dummy; connectin >> WIEcross >> dummy; connectin >> WIIcross >> dummy; logOut << " WEEcross " << WEEcross << endl; logOut << " WEIcross " << WEIcross << endl; logOut << " WIEcross " << WIEcross << endl; logOut << " WIIcross " << WIIcross << endl; /* WIRO is connection strength from Readout to Inhibitory neurons*/ connectin >> WIRO >> dummy; logOut << " WIRO " << WIRO << endl; /* WEon is strength of excitation from ON cells to Comparison cells. WEEon is recurrent excitation within ON cells to make the ON populations bistable */ connectin >> WEon >> dummy; connectin >> WEEon >> dummy; logOut << " WEon " << WEon << endl; logOut << " WEEon " << WEEon << endl; }