Advertisement
Guest User

Izhikevich_model

a guest
Jan 28th, 2016
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.29 KB | None | 0 0
  1. /*
  2. Izhikevich in integer math
  3. Zach Fredin
  4. zach@neurotinker.com
  5. 1/21/2016
  6.  
  7. The MIT License (MIT)
  8. Copyright (c) 2016 by Zach Fredin
  9.  
  10. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  11.  
  12. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  13.  
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  15.  
  16.  
  17. This program attemts to convert Izhikevich's neuron model to purely
  18. integer math by iterating through test values and improving the
  19. model "fit" versus his original equations. I'm not sure it will work.
  20. */
  21.  
  22. /*  Izhikevich model
  23.  
  24.     dv/dt = 0.04v^2 + 5v +140 - u + I
  25.     du/dt = a(bv - u)
  26.     if v >= 30 (neuron fires)
  27.     v <- c; u <- u + d
  28.  
  29.     Typical parameters for a regular spiking neuron:
  30.     a   0.02
  31.     b   0.2
  32.     c   -65
  33.     d   8
  34.     I   6
  35.  
  36.     Model start at t=0
  37.     v0 = -65
  38.     u0 = 0
  39.  
  40.     Arbitrary names for the coefficients:
  41.     dv/dt = E*v^2 + F*v + G - u + I
  42.     du/dt = a(bv - u)
  43.     if v >= H (neuron fires)
  44.     v <- c; u <- u + d
  45.  
  46.     For speed, I'm going to force E to be a bit shift rather than a divide.
  47.     That means it's limited (in original Izhikevich terms) to 1, 0.25, 0.125, etc:
  48.  
  49.     dv/dt = ((v * v) >> E) + F*v + G - u + I
  50.  
  51.     Since a and b are also less than one in all neuron models, these will also be bit shifts:
  52.     a >> 5 (equal to *0.03125)
  53.     b >> 2 (equal to *0.25)
  54. */
  55.  
  56. /*  Measuring model "fit"
  57.     Various checks based on typical parameters listed above
  58.     Check conditions
  59.         0 <= t < 500
  60.         slope threshold = 1.0*t
  61.  
  62.     Number of firings       6
  63.     Fire ratio          0.132
  64.     Linear region avg slope     0.252
  65.     Linear region range pct     0.180
  66.  
  67.     Optimize for:
  68.     - fire ratio at a given slope
  69.     - number of firings
  70.     - linear region avg slope
  71.     - linear region range pct
  72.     - not overflowing 16-bit signed integers
  73. */
  74.  
  75. #include <stdio.h>
  76. #include <time.h>
  77. #include <tgmath.h>
  78. #include <stdlib.h>
  79.  
  80. /*  Izhikevich model inputs */
  81. const signed int inp_I = 30; //I-value for fast spiking
  82. const signed int inp_v = -65; //starting point for v
  83. const signed int inp_u = 0; //starting point for u
  84.  
  85. /*  Izhikevich model variable array */
  86. volatile signed int var_v[500];
  87. volatile signed int var_u[500];
  88.  
  89. /*  Izhikevich model parameters (constants for now)
  90.     Arbitrarily scaled to low integer values */
  91. volatile signed int para_a; //remember, this is now a bit shift: 1/a^2
  92. volatile signed int para_abest;
  93. volatile signed int para_b; //remember, this is now a bit shift: 1/b^2
  94. volatile signed int para_bbest;
  95. volatile signed int para_c;
  96. volatile signed int para_cbest;
  97. volatile signed int para_d;
  98. volatile signed int para_dbest;
  99.  
  100. volatile signed int max_a = 10;
  101. volatile signed int max_b = 5;
  102. volatile signed int max_c = 100; //this gets flipped negative after randomization
  103. volatile signed int max_d = 20;
  104.  
  105. /*  Izhikevich model coefficients (iteratively optimized) */
  106. volatile signed int coef_E; //v^2 * 1/E^2 (bit shift)
  107. volatile signed int coef_Ebest;
  108. volatile signed int coef_F; //v
  109. volatile signed int coef_Fbest;
  110. volatile signed int coef_G; //offset
  111. volatile signed int coef_Gbest;
  112. volatile signed int coef_H; //threshold to reset v and u
  113. volatile signed int coef_Hbest;
  114.  
  115. /*  Izhikevich model coefficient limts (all minimums are 0) */
  116. const signed int max_E = 7; //remember, this is now a bit shift: 1/E^2
  117. const signed int max_F = 10;
  118. const signed int max_G = 200;
  119. const signed int max_H = 200;
  120.  
  121. /*  Slope threshold */
  122. volatile signed int model_slopeThresh = 5;
  123.  
  124. /*  Calculated outputs */
  125. volatile float model_numFirings;
  126. volatile float model_numFiringsBest;
  127. volatile float model_fireRatio;
  128. volatile float model_fireRatioBest;
  129. volatile float model_linSlopeAvg;
  130. volatile float model_linSlopeAvgBest;
  131. volatile float model_linRangePct;
  132. volatile float model_linRangePctBest;
  133.  
  134. /*  Ideal values */
  135. const float ideal_numFirings = 12;
  136. const float ideal_fireRatio = 0.136;
  137. const float ideal_linSlopeAvg = 0.252;
  138. const float ideal_linRangePct = 0.180;
  139. const float min_numFirings = 5;
  140. const float max_numFirings = 20;
  141. const float max_fireRatio = 0.5;
  142.  
  143. /*  Optimization parameters */
  144. const int iterations = 1000000;
  145. const float wgt_numFirings = 0.4;
  146. const float wgt_fireRatio = 0.2;
  147. const float wgt_linSlopeAvg = 0.3;
  148. const float wgt_linRangePct = 0.1;
  149.  
  150. /* Model error variables */
  151. volatile float err_numFirings;
  152. volatile float err_numFiringsBest;
  153. volatile float err_fireRatio;
  154. volatile float err_fireRatioBest;
  155. volatile float err_linSlopeAvg;
  156. volatile float err_linSlopeAvgBest;
  157. volatile float err_linRangePct;
  158. volatile float err_linRangePctBest;
  159. volatile float totalError;
  160. volatile float totalErrorBest = 10;
  161.  
  162. /*  Execution time variables */
  163. clock_t start, end;
  164. double cpu_time_used;
  165.  
  166. int randomInt(int scale) {
  167.     srand((double)clock());
  168.     return (int)(((double)rand()/(double)(RAND_MAX)) * scale);
  169. }
  170.  
  171. double randomDouble(double scale) {
  172.     srand((double)clock());
  173.     return ((double)rand()/(double)(RAND_MAX)) * scale;
  174. }
  175.  
  176. void initializeOutputs(void) {
  177.     int i;
  178.     model_numFirings = 0;
  179.     model_fireRatio = 0;
  180.     model_linSlopeAvg = 0;
  181.     model_linRangePct = 0;
  182. }  
  183.  
  184. void calcError(void) {
  185.     err_numFirings = fabs(model_numFirings - ideal_numFirings) / ideal_numFirings;
  186.     if (model_numFirings < min_numFirings) {
  187.         err_numFirings += 100; //sick of lazy neurons, blow this up!
  188.     }
  189.     if (model_numFirings > max_numFirings) {
  190.         err_numFirings += 100;
  191.     }
  192.     err_fireRatio = fabs(model_fireRatio - ideal_fireRatio) / ideal_fireRatio;
  193.     if (model_fireRatio > max_fireRatio) {
  194.         err_fireRatio += 10;
  195.     }
  196.     err_linSlopeAvg = fabs(model_linSlopeAvg - ideal_linSlopeAvg) / ideal_linSlopeAvg;
  197.     if (model_linSlopeAvg == 0) {
  198.         err_linSlopeAvg += 10;
  199.     }
  200.     err_linRangePct = fabs(model_linRangePct - ideal_linRangePct) / ideal_linRangePct;
  201.     if (model_linRangePct == 0 ) {
  202.         err_linRangePct += 10;
  203.     }
  204.     totalError = wgt_numFirings * err_numFirings + wgt_fireRatio * err_fireRatio + wgt_linSlopeAvg * err_linSlopeAvg + wgt_linRangePct * err_linRangePct;
  205. }
  206.    
  207. void calcOutputs(void) {
  208.     initializeOutputs();
  209.     int i;
  210.     int counter_fireRatio = 0;
  211.     float acc_linSlopeAvg = 0;
  212.     float lin_min = 0;
  213.     float lin_max = 0;
  214.     for(i=1;i<500;i++) {
  215.         // calculate fire ratio
  216.         if(((var_v[i] - var_v[i-1]) > model_slopeThresh) | ((var_v[i-1] - var_v[i]) > model_slopeThresh)) {
  217.             counter_fireRatio++;
  218.         }
  219.  
  220.         else {
  221.             //calculate linear region average slope
  222.             acc_linSlopeAvg += ((float)var_v[i] - (float)var_v[i-1]);  
  223.  
  224.             //record min/max for linear region
  225.             if(lin_min == 0 | ((float)var_v[i] < lin_min)) {
  226.                 lin_min = (float)var_v[i];
  227.             }
  228.             if(lin_max == 0 | ((float)var_v[i] > lin_max)) {
  229.                 lin_max = (float)var_v[i];
  230.             }
  231.         }
  232.  
  233.         // calculate number of firings
  234.         if((var_v[i] > coef_H) & (var_v[i-1] < coef_H)) {
  235.             model_numFirings++;
  236.         }
  237.     }          
  238.  
  239.     model_fireRatio = (float)counter_fireRatio / 500;
  240.     model_linSlopeAvg = acc_linSlopeAvg / (500 - (float)counter_fireRatio);
  241.     model_linRangePct = (lin_max - lin_min) / ((float)coef_H - lin_min);
  242. }
  243.  
  244. void runModel(void) {
  245.     int i;
  246.     var_v[0] = inp_v;
  247.     var_u[0] = inp_u;  
  248.     for(i=1;i<500;i++) {
  249.         if(var_v[i-1] > coef_H) {
  250.             var_v[i] = para_c;
  251.             var_u[i] = var_u[i-1] + para_d;
  252.         }
  253.         else {
  254.             var_v[i] = var_v[i-1] + ((var_v[i-1] * var_v[i-1]) >> coef_E) + coef_F * var_v[i-1] + coef_G - var_u[i-1] + inp_I;
  255.             var_u[i] = var_u[i-1] + (((var_v[i-1] >> para_b) - var_u[i-1]) >> para_a);
  256.             }
  257.     }
  258. }
  259.  
  260. void printBest(void) {
  261.     printf("        best model  ideal       error       weight\n");
  262.     printf("numFirings  %f", model_numFiringsBest);
  263.     printf("    %f", ideal_numFirings);
  264.     printf("    %f", err_numFiringsBest);
  265.     printf("    %f\n", wgt_numFirings);
  266.     printf("fireRatio   %f", model_fireRatioBest);
  267.     printf("    %f", ideal_fireRatio);
  268.     printf("    %f", err_fireRatioBest);
  269.     printf("    %f\n", wgt_fireRatio);
  270.     printf("linSlopeAvg %f", model_linSlopeAvgBest);
  271.     printf("    %f", ideal_linSlopeAvg);
  272.     printf("    %f", err_linSlopeAvgBest);
  273.     printf("    %f\n", wgt_linSlopeAvg);
  274.     printf("linRangePct %f", model_linRangePctBest);
  275.     printf("    %f", ideal_linRangePct);
  276.     printf("    %f", err_linRangePctBest);
  277.     printf("    %f\n", wgt_linRangePct);   
  278.     printf("model fit error: %f\n", totalErrorBest);
  279. }
  280.  
  281. void updateBest(void) {
  282.     coef_Ebest = coef_E;
  283.     coef_Fbest = coef_F;
  284.     coef_Gbest = coef_G;
  285.     coef_Hbest = coef_H;
  286.     model_numFiringsBest = model_numFirings;
  287.     err_numFiringsBest = err_numFirings;
  288.     model_fireRatioBest = model_fireRatio;
  289.     err_fireRatioBest = err_fireRatio;
  290.     model_linSlopeAvgBest = model_linSlopeAvg;
  291.     err_linSlopeAvgBest = err_linSlopeAvg;
  292.     model_linRangePctBest = model_linRangePct;
  293.     err_linRangePctBest = err_linRangePct;
  294.     totalErrorBest = totalError;
  295. }
  296.  
  297. void printVU(void) {
  298.     int i;
  299.     printf("t       v(t)        u(t)\n");
  300.     for(i=0;i<500;i++) {
  301.         printf("%i", i);
  302.         printf("        %i", var_v[i]);
  303.         printf("        %i\n", var_u[i]);
  304.     }
  305. }
  306.  
  307. void printOutputs(void) {
  308.     printf("a = %i\n",para_a);
  309.     printf("b = %i\n",para_b);
  310.     printf("c = %i\n",para_c);
  311.     printf("d = %i\n",para_d);
  312.     printf("I = %i\n",inp_I);
  313.     printf("E = %i\n",coef_Ebest);
  314.     printf("F = %i\n",coef_Fbest);
  315.     printf("G = %i\n",coef_Gbest);
  316.     printf("H = %i\n",coef_Hbest);
  317. }
  318.  
  319. int main(void) {
  320.     int i;
  321.     start = clock();
  322.     printf("Izhikevich model optimizer \n");
  323.     for (i=0;i<iterations;i++) {
  324.         para_a = 5;
  325.         para_b = 2;
  326.         para_c = -65;
  327.         para_d = 8;
  328.         coef_E = randomInt(max_E);
  329.         coef_F = randomInt(max_F);
  330.         coef_G = randomInt(max_G);
  331.         coef_H = randomInt(max_H);
  332.         runModel();
  333.         calcOutputs();
  334.         calcError();
  335.         if (totalError < totalErrorBest) {
  336.             updateBest();
  337.         }
  338.     }
  339.     printOutputs();
  340.     printBest();
  341.     end = clock();
  342.     printf("iterations: %i\n", iterations);
  343.     printf("execution time (s): %f\n", ((double)(end-start))/CLOCKS_PER_SEC);
  344.     return 0;
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement