V2.H

00001 /*
00002  *  V2.H
00003  *
00004  *
00005  *  Created by Randolph Voorhies on 11/26/07.
00006  *
00007  */
00008 #ifndef V2_H
00009 #define V2_H
00010 
00011 #define PI 3.14159265f
00012 
00013 
00014 //Parameters
00015 #define alpha_x 1.0f
00016 #define alpha_y 1.0f
00017 #define x_th        1.0f
00018 #define x_sat        2.0f
00019 #define y_th1        1.0f
00020 #define y_th2        1.2f
00021 #define g1                0.21f
00022 #define g2                2.5f
00023 #define y_sat        300.0f
00024 #define I_o                0.1f
00025 #define I_c                1.0f
00026 #define THETA_LEVELS 24
00027 
00028 #include "Image/Point2D.H"
00029 #include "Image/Image.H"
00030 #include "Image/Pixels.H"
00031 #include "Raster/Raster.H"
00032 #include <vector>
00033 #include <math.h>
00034 
00035 
00036 using namespace std;
00037 
00038 class V2 {
00039 public:
00040         V2(Dims size);
00041 
00042         //Run the simulation for t steps
00043         void step();
00044 
00045         void setInput(vector< Image<float> > input);
00046 
00047 
00048         //Helper Functions
00049         float g_x(float x);
00050         float g_y(float y);
00051         float psi(float theta);
00052         float tau();
00053         float I_normalization(Point2D<int> i, int theta_index);
00054         float phi(float x, float y);
00055         float beta(Point2D<int> i, Point2D<int> j);
00056         float sign(float x);
00057         float theta_one(Point2D<int> i, int i_theta_index, Point2D<int> j);
00058         float theta_two(Point2D<int> i, Point2D<int> j, int j_theta_index);
00059         float theta_one_prime(Point2D<int> i, int i_theta_index, Point2D<int> j);
00060         float theta_two_prime(Point2D<int> i, Point2D<int> j, int j_theta_index);
00061         float theta_plus(float theta_a, float theta_b);
00062         float theta_minus(float theta_a, float theta_b);
00063         void theta_a_b(float &theta_a, float &theta_b, Point2D<int> i, Point2D<int> j, int i_theta_index, int j_theta_index);
00064         float f_1(float d);
00065         float f_2(float d);
00066         float f_T(float d);
00067         float W(Point2D<int> i, int i_theta_index, Point2D<int> j, int j_theta_index);
00068         float J(Point2D<int> i, int i_theta_index, Point2D<int> j, int j_theta_index);
00069         float sumPsiGy(Point2D<int> i, int theta_index);
00070         float sumJGx(Point2D<int> i, int theta_index);
00071         float sumWGx(Point2D<int> i, int theta_index);
00072 
00073         float ind2rad(int theta_index);
00074 
00075 
00076 private:
00077         //The Pyramidal and Inhibitory cells are layed out into the itsX and itsY matrices (respectively). The itsXprime and itsYprime matrices are used to store the next
00078         //step differences which are then added to the itsX and itsY matrices at the end of every step.
00079         vector< Image<float> > itsX;
00080         vector< Image<float> > itsY;
00081         vector< Image<float> > itsXprime;
00082         vector< Image<float> > itsYprime;
00083 
00084         //The input, arranged as a matrix
00085         vector< Image<float> > I;
00086 
00087         Dims itsDims;
00088         int t;
00089 };
00090 
00091 
00092 V2::V2(Dims size) {
00093         itsDims = size;
00094         itsX.resize(THETA_LEVELS, Image<float>(size, ZEROS));
00095         itsY.resize(THETA_LEVELS, Image<float>(size, ZEROS));
00096         itsXprime.resize(THETA_LEVELS, Image<float>(size, ZEROS));
00097         itsYprime.resize(THETA_LEVELS, Image<float>(size, ZEROS));
00098 
00099         t=0;
00100 
00101         //Init the random number generator
00102         srand((unsigned) (time(0)));
00103 }
00104 
00105 void V2::setInput(vector < Image<float> > input) {
00106         I = input;
00107 }
00108 
00109 //This function progresses through one time step for the neural network. First, the pyramidal and inhibitory differentials are computed,
00110 //and then added to their respective activity matrices.
00111 void V2::step() {
00112         float xprime, yprime;
00113 
00114         for(int theta_index=0; theta_index<THETA_LEVELS; theta_index++) {
00115                 for(int i=0; i<itsDims.w();i++) {
00116                         for(int j=0; j<itsDims.h(); j++) {
00117                                 xprime = -alpha_x*itsX[theta_index].getVal(i,j) - g_y(itsY[theta_index].getVal(i,j)) - sumPsiGy(Point2D<int>(i,j), theta_index) + sumJGx(Point2D<int>(i,j),theta_index) + /*I + */ + I_o + /*N_x*/ + I_normalization(Point2D<int>(i,j),theta_index);
00118                                 yprime = -alpha_y*itsY[theta_index].getVal(i,j) + g_x(itsX[theta_index].getVal(i,j)) + sumWGx(Point2D<int>(i,j), theta_index) + I_c /*+ N_y*/;
00119 
00120                                 itsXprime[theta_index].setVal(i,j,xprime);
00121                                 itsYprime[theta_index].setVal(i,j,yprime);
00122                         }
00123                 }
00124         }
00125 
00126         for(int theta_index=0; theta_index<THETA_LEVELS; theta_index++) {
00127                 itsX[theta_index] += itsXprime[theta_index];
00128                 itsY[theta_index] += itsYprime[theta_index];
00129         }
00130 
00131         t++;
00132 }
00133 
00134 float V2::sumPsiGy(Point2D<int> i, int theta_index) {
00135         float sum = 0;
00136 
00137         for(int d_theta_index=1; d_theta_index<THETA_LEVELS; d_theta_index++) {
00138                 for(int x=0; x<itsDims.w();x++) {
00139                         for(int y=0; y<itsDims.h(); y++) {
00140                                 sum += psi(ind2rad(d_theta_index)) * g_y(itsY[((theta_index + d_theta_index)%THETA_LEVELS)].getVal(i));
00141                         }
00142                 }
00143         }
00144         return sum;
00145 }
00146 
00147 //NOTE: May need to provide constant Taus here?
00148 float V2::sumJGx(Point2D<int> i, int theta_index) {
00149         float sum = 0;
00150 
00151         for(int x=0; x<itsDims.w(); x++) {
00152                 for(int y=0; y<itsDims.h(); y++) {
00153                         if(Point2D<int>(x,y) == i) continue;
00154                         for(int theta_prime_index = 0; theta_prime_index < THETA_LEVELS; theta_prime_index++) {
00155                                 sum += J(i, theta_index, Point2D<int>(x,y), theta_prime_index) * g_x(itsX[theta_prime_index].getVal(x,y) * (t - tau()));
00156                         }
00157                 }
00158         }
00159         return sum;
00160 }
00161 
00162 //NOTE: May need to provide constant Taus here?
00163 float V2::sumWGx(Point2D<int> i, int theta_index) {
00164         float sum = 0;
00165         for(int x=0; x<itsDims.w(); x++) {
00166                 for(int y=0; y<itsDims.h(); y++) {
00167                         if(i == Point2D<int>(x,y)) continue;
00168                         for(int theta_prime_index = 0; theta_prime_index < THETA_LEVELS; theta_prime_index++) {
00169                                 sum += W(i, theta_index, Point2D<int>(x,y),theta_prime_index) * g_x(itsX[theta_prime_index].getVal(x,y)*(t-tau()));
00170                         }
00171                 }
00172         }
00173         return sum;
00174 }
00175 
00176 
00177 //Takes a theta index (an integer specifying a level of theta), and returns the actual radians which that level represents between 0 and 2PI
00178 float V2::ind2rad(int theta_index) {
00179         return (theta_index/THETA_LEVELS)*(2.0f*PI);
00180 }
00181 
00182 float V2::g_x(float x) {
00183         if(x < x_th)
00184                 return 0.0f;
00185         else if(x >= x_th && x <= x_sat)
00186                 return x - x_th;
00187         else if(x > x_sat)
00188                 return x_sat - x_th;
00189         else {
00190                 LERROR("ERROR! x out of bounds");
00191                 return -1.0f;
00192         }
00193 }
00194 
00195 float V2::g_y(float y) {
00196         if(y < y_th1)
00197                 return 0.0f;
00198         else if(y >= y_th1 && y <= y_th2)
00199                 return g1*(y - y_th1);
00200         else if(y >= y_th2 && y <= y_sat)
00201                 return g2*(y - y_th2) + g1*(y_th2 - y_th1);
00202         else if(y > y_sat)
00203                 return g2*(y_sat - y_th2) + g1*(y_th2 - y_th1);
00204         else {
00205                 LERROR("ERROR! y out of bounds");
00206                 return -1.0f;
00207         }
00208 }
00209 
00210 float V2::psi(float theta) {
00211         if(fabs(theta) == PI/12.0f)
00212                 return 0.8f;
00213         if(fabs(theta) == PI/6.0f)
00214                 return 0.1f;
00215         else
00216                 return 0.0f;
00217 }
00218 
00219 float V2::tau() {
00220         return rand()/(float(RAND_MAX)+1.0f)*(1.0f - 0.8f)+0.8f;
00221 }
00222 
00223 float V2::I_normalization(Point2D<int> i, int theta_index) {
00224 
00225         float a_hat = 0.0f;
00226         Point2D<int> index;
00227 
00228         for(int _x = i.i-2; _x < i.i+2; _x++) {
00229                 for(int _y = i.j-2; _y < i.j+2; _y++) {
00230                         index = Point2D<int>(_x, _y);
00231                         index.clampToDims(itsDims);
00232                         a_hat += itsX[theta_index].getVal(index);
00233                 }
00234         }
00235 
00236         return pow(a_hat, 2.0f)/128.0f;
00237 }
00238 
00239 float V2::phi(float x, float y) {
00240         float diff = x-y;
00241 
00242         if(diff > -PI && diff <= PI) {
00243                 return diff;
00244         }
00245         else if(diff <= -PI) {
00246                 return diff + 2.0f*PI;
00247         }
00248         else if(diff > PI) {
00249                 return diff - 2.0f*PI;
00250         }
00251         LERROR("Diff Out Of Bounds!");
00252         exit(0);
00253         return 1.0f;
00254 
00255 }
00256 
00257 float V2::beta(Point2D<int> i, Point2D<int> j) {
00258         float beta;
00259 
00260         float o = j.j - i.j;
00261         float a = j.i - i.i;
00262 
00263         //float o = i.j - j.j;
00264         //float a = i.i - j.i;
00265 
00266         if(a == 0.0f) {
00267                 if(o > 0.0f)
00268                         return PI/2.0f;
00269                 else
00270                         return 3.0f*PI/2.0f;
00271         }
00272 
00273         beta = atan(o/a);
00274         if(o > 0.0f && a < 0.0f) {
00275                 beta = PI+beta;
00276         }
00277         else if(o <= 0.0f && a < 0.0f) {
00278                 beta = PI + beta;
00279         }
00280         else if(o < 0.0f && a > 0.0f) {
00281                 beta = 2.0f*PI + beta;
00282         }
00283 
00284         return beta;
00285 }
00286 
00287 float V2::sign(float x) {
00288         if(x >= 0.0f)
00289                 return 1.0f;
00290         else
00291                 return -1.0f;
00292 }
00293 
00294 float V2::theta_one(Point2D<int> i, int i_theta_index, Point2D<int> j) {
00295         return phi(2.0f*(PI/(float)THETA_LEVELS)*(float)i_theta_index, beta(i,j));
00296 }
00297 
00298 float V2::theta_two(Point2D<int> i, Point2D<int> j, int j_theta_index) {
00299         return phi(beta(i,j), 2.0f*(PI/(float)THETA_LEVELS)*(float)j_theta_index);
00300 }
00301 
00302 float V2::theta_one_prime(Point2D<int> i, int i_theta_index, Point2D<int> j) {
00303         float _theta_one = theta_one(i,i_theta_index,j);
00304         return sign(_theta_one)*fabs(PI-fabs(_theta_one));
00305 }
00306 
00307 float V2::theta_two_prime(Point2D<int> i, Point2D<int> j, int j_theta_index) {
00308         float _theta_two = theta_two(i,j,j_theta_index);
00309         return sign(_theta_two)*fabs(PI-fabs(_theta_two));
00310 }
00311 
00312 void V2::theta_a_b(float &theta_a, float &theta_b, Point2D<int> i, Point2D<int> j, int i_theta_index, int j_theta_index) {
00313         float _theta_one = theta_one(i, i_theta_index, j);
00314         float _theta_two = theta_two(i, j, j_theta_index);
00315         float _theta_one_prime = theta_one_prime(i, i_theta_index, j);
00316         float _theta_two_prime = theta_two_prime(i, j, j_theta_index);
00317 
00318         if(fabs(_theta_one) + fabs(_theta_two) <= fabs(_theta_one_prime) + fabs(_theta_two_prime)) {
00319                 theta_a = _theta_one;
00320                 theta_b = _theta_two;
00321         }
00322         else {
00323                 theta_a = _theta_one_prime;
00324                 theta_b = _theta_two_prime;
00325         }
00326 }
00327 
00328 float V2::theta_plus(float theta_a, float theta_b) {
00329         float theta_prime_plus = theta_a + theta_b;
00330 
00331         if(theta_prime_plus >= -PI && theta_prime_plus <= PI)
00332                 return theta_prime_plus;
00333         else if(theta_prime_plus > PI)
00334                 return 2.0f*PI - theta_prime_plus;
00335         else
00336                 return -2.0f*PI - theta_prime_plus;
00337 }
00338 
00339 float V2::theta_minus(float theta_a, float theta_b) {
00340         float theta_prime_minus = theta_a - theta_b;
00341 
00342         if(theta_prime_minus >= -PI && theta_prime_minus <= PI)
00343                 return theta_prime_minus;
00344         else if(theta_prime_minus > PI)
00345                 return 2.0f*PI - theta_prime_minus;
00346         else
00347                 return -2.0f*PI - theta_prime_minus;
00348 }
00349 
00350 float V2::f_1(float d) {
00351         if(d > 10.0f || d == 0.0f)
00352                 return 0.0f;
00353 
00354         return exp(-pow(d/9.0f,2.0f));
00355 }
00356 
00357 float V2::f_2(float d) {
00358         if(d > 10.0f || d == 0.0f)
00359                 return 0.0f;
00360 
00361         return exp(-d/5.0f);
00362 }
00363 
00364 float V2::f_T(float d) {
00365         return (11.0f/90.0f)*exp(-d/6.0f);
00366 }
00367 
00368 //Calculate the synaptic strength between pyramidal neurons
00369 float V2::J(Point2D<int> i, int i_theta_index, Point2D<int> j, int j_theta_index) {
00370         float theta_a, theta_b;
00371         float _theta_plus, _theta_minus;
00372         float d = fabs(i.distance(j));
00373         float ret;
00374 
00375         //Calculate theta_a and theta_b
00376         theta_a_b(theta_a, theta_b, i, j, i_theta_index, j_theta_index);
00377         //Calculate theta_plus and theta_minus
00378         _theta_plus = theta_plus(theta_a, theta_b);
00379         _theta_minus = theta_minus(theta_a, theta_b);
00380 
00381         //LINFO("\ntheta_a=%f\ntheta_b=%f\ni.i=%d\ni.j=%d\nj.i=%d\nj.j=%d\ntheta_plus=%f\ntheta_minus=%f\n", theta_a, theta_b, i.i, i.j, j.i,j.j,theta_plus,theta_minus);
00382 
00383         if(d > 0.0f && d <= 2.0f && fabs(theta_a*d) < 0.5f && fabs(theta_b) > PI/3.1f && fabs(theta_b) < 2.0f*PI/3.1f) {
00384 
00385                 if(theta_b < 0.0f)
00386                         return f_T(d)*exp(-2.0f*fabs(theta_a*d));
00387                 else
00388                         return 0.0f;
00389         }
00390         else if(d > 0.0f && d <= 2.0f && fabs(theta_b*d) < 0.5f && fabs(theta_a) > PI/3.1f && fabs(theta_a) < 2.0f*PI/3.1f) {
00391 
00392                 if(theta_a < 0.0f)
00393                         return 3.0f*f_T(d)*exp(-2.0f*fabs(theta_b*d));
00394                 else
00395                         return 0.0f;
00396         }
00397 
00398 
00399 
00400         if(fabs(theta_a) <= PI/11.0f && fabs(theta_b) <= PI/11.0f) {
00401                 //LINFO("1");
00402                 ret = (11.0f/108.0f) * exp(-(3.0f - 2.5f*sign(_theta_plus))*fabs(_theta_plus)/(5.0f*PI) - 2.0f * pow(_theta_minus, 2.0f)/pow(PI, 2.0f))*f_1(d);
00403         }
00404         else if(theta_a >= 0.0f && theta_b >= 0.0f && _theta_plus < PI/2.01f) {
00405                 //LINFO("2");
00406                 ret = (11.0f/81.0f) * exp(-3.0f*_theta_plus/(5.0f*PI) - 2.0f*pow(_theta_minus,2.0f)/pow(PI,2.0f))/f_2(d);
00407         }
00408         else if(theta_a >= 0.0f && theta_b >= 0.0f && _theta_plus >= PI/2.01f && fabs(_theta_minus) < PI/2.01f) {
00409                 //LINFO("3");
00410                 ret = (11.0f/81.0f) * exp(-pow((9.0f*_theta_plus)/(8.0f*PI),2.0f) - 2.0f*pow(_theta_minus,2.0f)/pow(PI,2.0f))*f_2(d);
00411         }
00412         else if(theta_a >= 0.0f && theta_b >= 0.0f && _theta_plus >= PI/2.01f && fabs(_theta_minus) >= PI/2.01f) {
00413                 //LINFO("4");
00414                 ret = (11.0f/81.0f) * exp(-pow(9.0f*_theta_plus/(8.0f*PI),2.0f) - 0.5f*pow((_theta_minus/(PI/2.0f)),6.0f))*f_2(d);
00415         }
00416         else if(theta_a <= 0.0f && theta_b <= 0.0f) {
00417                 //LINFO("5");
00418                 ret = (11.0f/81.0f) * exp(-4.0f*pow(_theta_plus/PI,2.0f) - 9.0f*pow(_theta_minus, 2.0f)/pow(PI, 2.0f))*f_2(d);
00419         }
00420         else if(theta_a*theta_b <= 0.0f && fabs(_theta_minus) < PI/2.01f) {
00421                 //LINFO("6\n11./81.=%f\nf_2(d)=%f",11./81., f_2(d));
00422                 ret = (11.0f/81.0f) * exp(11.5f*sign(_theta_plus)*pow(_theta_plus,2.0f)/pow(PI,2.0f) - 14.0f*pow(_theta_minus,2.0f)/pow(PI,2.0f))*f_2(d);
00423         }
00424         else if(theta_a*theta_b <= 0.0f && fabs(_theta_minus) >= PI/2.01f) {
00425                 //LINFO("7");
00426                 ret = (11.0f/81.0f) * exp(11.5f*sign(_theta_plus)*pow(_theta_plus,2.0f)/pow(PI,2.0f) - (15.0f/4.0f)*pow((2.0f*_theta_minus/PI),6.0f))*f_2(d);
00427         }
00428         else {
00429                 LERROR("theta_a and theta_b slipped through the cracks! \n  theta_a=%f \n  theta_b=%f \n  theta_plus=%f  \n  theta_minus=%f\n", theta_a, theta_b, _theta_plus, _theta_minus);
00430                 LINFO("ERROR!");
00431                 exit(0);
00432                 return 1.0f;
00433         }
00434 
00435         //LINFO("\ntheta_a=%f\ntheta_b=%f\nd=%f\nret=%f", theta_a, theta_b,d,ret);
00436         //Raster::waitForKey();
00437 
00438         return ret;
00439 }
00440 
00441 float V2::W(Point2D<int> i, int i_theta_index, Point2D<int> j, int j_theta_index) {
00442         float theta_a, theta_b, c;
00443         float d = fabs(i.distance(j));
00444 
00445         theta_a_b(theta_a, theta_b, i, j, i_theta_index, (j_theta_index+THETA_LEVELS/2)%THETA_LEVELS);
00446 
00447         if(d > 0.0f && d <= 2.0f && fabs(theta_a*d) < 0.5f && fabs(theta_b) > PI/3.1f && fabs(theta_b) < 2.0f*PI/3.1f) {
00448                 if(theta_b < 0.0f)
00449                         return 0.0f;
00450                         //return f_T(d)*exp(-2*fabs(theta_a*d));
00451                 else
00452                         return 0.0f;
00453         }
00454         else if(d > 0.0f && d <= 2.0f && fabs(theta_b*d) < 0.5f && fabs(theta_a) > PI/3.1f && fabs(theta_a) < 2.0f*PI/3.1f) {
00455                 if(theta_a < 0.0f)
00456                         return 0.0f;
00457                         //return 3*f_T(d)*exp(-2*fabs(theta_b*d));
00458                 else
00459                         return 0.0f;
00460         }
00461 
00462 
00463         if(fabs(theta_a) <= PI/11.0f && fabs(theta_b) <= PI/11.0f)
00464                 c = 0.0147f;
00465         else
00466                 c = 0.02646f;
00467 
00468         return c*(J(i, (i_theta_index+THETA_LEVELS/2)%THETA_LEVELS, j, j_theta_index) + J(i,  i_theta_index, j, (j_theta_index+THETA_LEVELS/2)%THETA_LEVELS)/J(i, 0, Point2D<int>(i.i+1, i.j), 0));
00469 
00470 
00471 }
00472 
00473 #endif
Generated on Sun May 8 08:41:12 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3