001 package cnslab.cnsnetwork; 002 003 import java.util.*; 004 005 import org.slf4j.Logger; 006 import org.slf4j.LoggerFactory; 007 008 import cnslab.cnsmath.*; 009 import edu.jhu.mb.ernst.model.Synapse; 010 import edu.jhu.mb.ernst.util.slot.Slot; 011 012 /*********************************************************************** 013 * Implementation of MN model, 014 * Same as VSICLIFNeuronV2, but no STDP is available. 015 * Please refer to VSICLIFNeuronV2 for details 016 * See Mihalas and Niebur 2009 paper 017 * 018 * @version 019 * $Date: 2012-08-04 13:43:22 -0500 (Sat, 04 Aug 2012) $ 020 * $Rev: 104 $ 021 * $Author: croft $ 022 * @author 023 * Yi Dong 024 * @author 025 * David Wallace Croft, M.Sc. 026 * @author 027 * Jeremy Cohen 028 ***********************************************************************/ 029 public final class VSICLIFNeuron 030 implements Neuron 031 //////////////////////////////////////////////////////////////////////// 032 //////////////////////////////////////////////////////////////////////// 033 { 034 035 private static final Logger 036 LOGGER = LoggerFactory.getLogger ( VSICLIFNeuron.class ); 037 038 // 039 040 // public Axon axon; 041 // private double[] curr;//0 is exc current, 1 is inhib current 042 // private double memV; 043 044 private double timeOfNextFire; 045 046 private double timeOfLastUpdate; 047 048 private boolean record; 049 050 // public static PrintStream p; 051 // public static boolean print=false; 052 053 /** minimum rising time for neuron to fire */ 054 public static double MINRISETIME = 1e-4; 055 056 /** time accuracy */ 057 public static double tEPS = 1e-12; 058 059 /** the criteria for removing synapses */ 060 public static double rEPS = 1e-22; 061 062 public static double maxWeight=0; 063 064 public static double cost_Update = 10; 065 066 public static double cost_Schedule = 1; 067 068 public static double cost; 069 070 /** average time interval a neuron received spikes */ 071 public double tAvg; 072 073 /** last time the neuron received a spike */ 074 public double lastInputTime; 075 076 /** clamp the membrane voltage during absolute refractory period */ 077 public double clamp_v; 078 079 /** clamp the threshold during absolute refractory period */ 080 public double clamp_t; 081 082 /** judge whether the neuron fires or not */ 083 public boolean fire; 084 085 public long tHost; 086 087 public VSICLIFNeuronPara para; 088 089 /** linked list for state variables */ 090 public TreeSet<State> state; 091 092 /** pointer to the state variables */ 093 public State[] sta_p; 094 095 //////////////////////////////////////////////////////////////////////// 096 //////////////////////////////////////////////////////////////////////// 097 098 public final class State 099 implements Comparable<State> 100 //////////////////////////////////////////////////////////////////////// 101 //////////////////////////////////////////////////////////////////////// 102 { 103 104 public double time; 105 106 public double value; 107 108 public byte id; 109 110 //////////////////////////////////////////////////////////////////////// 111 //////////////////////////////////////////////////////////////////////// 112 113 public State ( 114 final double time, 115 final double value, 116 final int id ) 117 //////////////////////////////////////////////////////////////////////// 118 { 119 this.time=time; 120 121 this.value=value; 122 123 this.id = ( byte ) id; 124 } 125 126 //////////////////////////////////////////////////////////////////////// 127 //////////////////////////////////////////////////////////////////////// 128 129 @Override 130 public int compareTo ( final State arg0 ) 131 //////////////////////////////////////////////////////////////////////// 132 { 133 if ( para.allDecays[this.id] < para.allDecays[arg0.id]) 134 { 135 return 1; 136 } 137 else if ( para.allDecays[this.id] > para.allDecays[arg0.id]) 138 { 139 return -1; 140 } 141 else 142 { 143 if( this.id < arg0.id) 144 { 145 return -1; 146 } 147 else if ( this.id > arg0.id) 148 { 149 return 1; 150 } 151 else 152 { 153 return 0; 154 } 155 } 156 } 157 158 @Override 159 public String toString ( ) 160 //////////////////////////////////////////////////////////////////////// 161 { 162 String out; 163 164 out = "time:" + time + " value:" + value + " id:" + id + " decay:" 165 + para.allDecays [ id ]; 166 167 return out; 168 } 169 170 //////////////////////////////////////////////////////////////////////// 171 //////////////////////////////////////////////////////////////////////// 172 } 173 174 //////////////////////////////////////////////////////////////////////// 175 //////////////////////////////////////////////////////////////////////// 176 177 public VSICLIFNeuron ( final VSICLIFNeuronPara para ) 178 //////////////////////////////////////////////////////////////////////// 179 { 180 LOGGER.trace ( "constructor entered" ); 181 182 this.para = para; 183 184 if ( maxWeight < para.CAP * ( para.THRESHOLD - para.VRESET ) 185 / para.MINRISETIME ) 186 { 187 maxWeight = para.CAP * ( para.THRESHOLD - para.VRESET ) 188 / para.MINRISETIME; 189 } 190 } 191 192 //////////////////////////////////////////////////////////////////////// 193 // interface Neuron accessor methods 194 //////////////////////////////////////////////////////////////////////// 195 196 /* 197 public Axon getAxon() 198 { 199 return this.axon; 200 } 201 */ 202 203 @Override 204 public double [ ] getCurr ( final double currTime ) 205 //////////////////////////////////////////////////////////////////////// 206 { 207 final double [ ] out = new double [ para.DECAY.length ]; 208 209 for(int a=0;a<para.DECAY.length;a++) 210 { 211 if(sta_p[a+2]==null) 212 { 213 out[a]=0; 214 } 215 else 216 { 217 out[a] = sta_p[a+2].value 218 * Math.exp ( -( currTime - sta_p[a+2].time ) *para.DECAY[a] ) 219 * para.GLCAPDECAY[a] / (1 - para.ABDECAY[a]); 220 } 221 } 222 223 return out; 224 } 225 226 @Override 227 public double getMemV ( final double currTime ) 228 //////////////////////////////////////////////////////////////////////// 229 { 230 // if input comes inside the refractory period, memV not changed 231 if ( currTime < timeOfLastUpdate ) 232 { 233 return memVoltage ( timeOfLastUpdate ); 234 } 235 else 236 { 237 return memVoltage (currTime); 238 } 239 } 240 241 @Override 242 public boolean getRecord ( ) 243 //////////////////////////////////////////////////////////////////////// 244 { 245 return record; 246 } 247 248 @Override 249 public long getTHost ( ) 250 //////////////////////////////////////////////////////////////////////// 251 { 252 return tHost; 253 } 254 255 @Override 256 public double getTimeOfNextFire ( ) 257 //////////////////////////////////////////////////////////////////////// 258 { 259 return timeOfNextFire; 260 } 261 262 @Override 263 public boolean isSensory ( ) 264 //////////////////////////////////////////////////////////////////////// 265 { 266 return false; 267 } 268 269 @Override 270 public boolean realFire ( ) 271 //////////////////////////////////////////////////////////////////////// 272 { 273 return fire; 274 } 275 276 //////////////////////////////////////////////////////////////////////// 277 // interface Neuron mutator methods 278 //////////////////////////////////////////////////////////////////////// 279 280 @Override 281 public void setRecord ( final boolean record ) 282 //////////////////////////////////////////////////////////////////////// 283 { 284 this.record = record; 285 } 286 287 @Override 288 public void setTHost ( final long id ) 289 //////////////////////////////////////////////////////////////////////// 290 { 291 this.tHost = id; 292 } 293 294 @Override 295 public void setTimeOfNextFire ( final double timeOfNextFire ) 296 //////////////////////////////////////////////////////////////////////// 297 { 298 this.timeOfNextFire = timeOfNextFire; 299 } 300 301 //////////////////////////////////////////////////////////////////////// 302 // interface Neuron lifecycle methods 303 //////////////////////////////////////////////////////////////////////// 304 305 @Override 306 public void init ( 307 final int expid, 308 final int trialid, 309 final Seed idum, 310 final Network net, 311 final int id ) 312 //////////////////////////////////////////////////////////////////////// 313 { 314 // initialization all the initial parameters. 315 316 cost = Math.log ( cost_Schedule / cost_Update + 1.0 ); 317 318 this.tAvg = 0.005; // initial value is 5 ms 319 320 this.lastInputTime = 0.0; 321 322 this.timeOfLastUpdate = 0.0; 323 324 this.timeOfNextFire = -1; 325 326 final double 327 memV = para.ini_mem + para.ini_memVar * Cnsran.ran2 ( idum ); 328 329 final double instantaneousThreshold = para.ini_threshold; 330 331 final double [ ] curr = new double [ para.ini_curr.length ]; 332 333 for ( int a = 0; a < curr.length; a++ ) 334 { 335 curr [ a ] = para.ini_curr [ a ]; 336 } 337 338 para.CON_v = para.IEXT / para.GL; 339 340 para.CON = para.IEXT / para.GL - ( para.THRESHOLD - para.VREST 341 + para.A / para.B * para.IEXT / para.GL ); 342 343 // state variables setup 344 345 // create linked table 346 347 state = new TreeSet<State> ( ); 348 349 sta_p = new State [ para.DECAY.length + 2 ]; 350 351 // First state is Ng term 352 353 sta_p [ 0 ] = new State ( 0, getNG ( memV, curr ), 0 ); 354 355 state.add ( sta_p [ 0 ] ); 356 357 sta_p[1] = new State(0,getNB(instantaneousThreshold,memV,curr),1); 358 359 state.add(sta_p[1]); 360 361 for(int i=2; i< para.DECAY.length+2; i++) 362 { 363 sta_p[i] = new State(0,getCurr(i-2,curr),i); 364 365 state.add(sta_p[i]); 366 } 367 368 /* 369 //System.out.println("starting"); 370 Iterator<State> iter= state.iterator(); 371 while(iter.hasNext()) 372 { 373 //System.out.println(iter.next()); 374 } 375 //System.out.println("ending"); 376 */ 377 378 double dt,vc; 379 380 double de = safeD(0.0) ; 381 382 double nextTime = (-(memV-instantaneousThreshold)/de); 383 384 dt=nextTime; 385 386 // if(nowV-nowT>0)return -1.0; 387 388 while (de >0 && nextTime < 1.0 && !(dt>0?dt<tEPS:-dt<tEPS)) 389 { 390 de = safeD(nextTime); 391 392 vc = memStheta(nextTime); 393 394 dt = (-vc/de); 395 396 //System.out.print( 397 // "n:"+nextTime+" s:"+(-vc)+"/"+de+"="+dt+" Etime:" 398 // +(time+nextTime)); 399 400 nextTime += dt; 401 } 402 403 if( de <0 || nextTime > 1.0) 404 { 405 fire = false; 406 nextTime = -1.0; 407 } 408 else if((dt>0?dt<tEPS:-dt<tEPS)) 409 { 410 fire = true; 411 } 412 else 413 { 414 //System.out.println("error condition in init"); 415 } 416 417 if(nextTime<0) //neuron will not fire at all 418 { 419 420 } 421 else 422 { 423 final Slot<FireEvent> fireEventSlot = net.getFireEventSlot ( ); 424 425 // nextTime = (timeOfLastUpdate>0.0) 426 // ?(timeOfLastUpdate-0.0-Math.log(nextTime)/para.K) 427 // :(-1.0*Math.log(nextTime)/para.K); 428 429 if(net.getClass().getName().equals("cnslab.cnsnetwork.ANetwork")) 430 { 431 fireEventSlot.offer ( 432 new AFireEvent( 433 id, 434 nextTime, 435 net.info.idIndex, 436 ((ANetwork) net).aData.getId((ANetwork) net))); 437 } 438 else if ( net.getClass ( ).getName ( ).equals ( 439 "cnslab.cnsnetwork.Network" ) ) 440 { 441 fireEventSlot.offer ( new FireEvent(id, nextTime)); 442 } 443 else 444 { 445 throw new RuntimeException("Other Network Class doesn't exist"); 446 } 447 timeOfNextFire = nextTime; 448 } 449 } 450 451 @Override 452 public double updateFire ( ) 453 //////////////////////////////////////////////////////////////////////// 454 { 455 // //System.out.println("fire at:"+timeOfNextFire); 456 457 // update state variables containing membrane voltage and threshold 458 // because of the resetting. 459 460 double baseline; 461 462 double nowV, nowT; 463 464 if(fire) // for real fire 465 { 466 // backup current threshold 467 final double backCT 468 = memVoltage(timeOfNextFire) - memStheta(timeOfNextFire); 469 470 sta_p[0].value 471 *= Math.exp(-(timeOfNextFire-sta_p[0].time+para.ABSREF) 472 *para.allDecays[0]); 473 474 sta_p[0].time = timeOfNextFire+para.ABSREF; 475 476 sta_p[1].value 477 *= Math.exp(-(timeOfNextFire-sta_p[1].time+para.ABSREF) 478 *para.allDecays[1]); 479 480 sta_p[1].time = timeOfNextFire+para.ABSREF; 481 482 //membrane voltage reset. 483 484 //future memVoltage 485 486 double cVoltage = memVoltage(timeOfNextFire+para.ABSREF); 487 488 // change memStheta(timeOfNextFire) to 0 later on may be beneficial 489 490 // double cThreshold = cVoltage - memStheta(timeOfNextFire); 491 492 // change memStheta(timeOfNextFire) to 0 later on may be beneficial 493 494 // double cThreshold 495 // = memVoltage(timeOfNextFire) - memStheta(timeOfNextFire); 496 497 //System.out.println( 498 //"abT:"+backCT+" memV:"+memVoltage(timeOfNextFire)); 499 500 //System.out.println( 501 // "abT2:"+(memVoltage(timeOfNextFire) 502 // - memStheta(timeOfNextFire))); 503 504 //membrane voltage offset 505 506 double vOffset = para.VRESET - cVoltage; 507 508 //threshold in future; 509 510 double cdiff = (cVoltage - memStheta(timeOfNextFire+para.ABSREF)); 511 512 //threshold offset 513 514 final double tOffset 515 = Math.max ( para.RRESET, backCT + para.THRESHOLDADD ) 516 - cdiff; 517 518 sta_p[0].value += (1-para.ABGLCAP)*vOffset; 519 520 sta_p[1].value += para.ABGLCAP*vOffset - tOffset; 521 522 // System.out.println("after fire voltage:" 523 // +memVoltage(timeOfNextFire+para.ABSREF) 524 // +" v-t:"+memStheta(timeOfNextFire+para.ABSREF)); 525 526 // if(clamp_v==Double.MAX_VALUE) //if clamp_v is not set; 527 528 clamp_v= para.VRESET; 529 530 clamp_t= Math.max(para.RRESET,backCT+para.THRESHOLDADD); 531 532 // this section is for spike triggered current 533 534 for(int a=0;a<para.DECAY.length;a++) 535 { 536 //update the currents if spike trigger current is non zero 537 538 if( para.IRATIO[a]!=1.0 || para.IADD[a] !=0) 539 { 540 // System.out.println("added"); 541 542 //update current to fire time; 543 544 if(sta_p[a+2]==null) //activate it 545 { 546 //System.out.println("act"); 547 sta_p[a+2] = new State(timeOfNextFire+para.ABSREF,0,a+2); 548 state.add(sta_p[a+2]); 549 } 550 else 551 { 552 sta_p[a+2].value 553 *= Math.exp(-(timeOfNextFire-sta_p[a+2].time+para.ABSREF) 554 *para.allDecays[a+2]); 555 556 sta_p[a+2].time = timeOfNextFire+para.ABSREF; 557 } 558 559 // current at timeofnextfire 560 561 double currNow = sta_p[a+2].value*para.GLCAPDECAY[a] 562 / (1 - para.ABDECAY[a]); 563 564 double currAfter = ( para.IRATIO [ a ] * currNow 565 * Math.exp ( para.ABSREF * para.allDecays [ a + 2 ] ) 566 + para.IADD [ a ] ) 567 * Math.exp ( -para.ABSREF * para.allDecays [ a + 2 ] ); 568 569 double changeCurr = currAfter - currNow; 570 571 // System.out.print ( 572 // "after:" + currAfter + " now:" + currNow + " " ); 573 574 sta_p [ 0 ].value 575 += changeCurr / para.GLCAPDECAY [ a ] * ( para.ABGLCAP - 1 ); 576 577 sta_p [ 1 ].value -= changeCurr/para.BCAPDECAY[a]*para.ABGLCAP; 578 579 sta_p [ a + 2 ].value 580 += ( changeCurr / para.GLCAPDECAY [ a ] ) 581 * ( 1 - para.ABDECAY [ a ] ); 582 583 /* 584 sta_p[0].value 585 += input.weight/para.GLCAPDECAY[a]*(para.ABGLCAP-1); 586 587 sta_p[1].value 588 -= input.weight/para.BCAPDECAY[a]*para.ABGLCAP; 589 590 sta_p[a+2].value 591 += (changeCurr/para.GLCAPDECAY[a])*(1 - para.ABDECAY[a]); 592 */ 593 //System.out.print( 594 // " bycalcu:"+sta_p[a+2].value*para.GLCAPDECAY[a] 595 // / (1 - para.ABDECAY[a])+" "); 596 } 597 } 598 599 // System.out.println ( "after fire curr:" 600 // +getCurr(timeOfNextFire+para.ABSREF)[0]+" " 601 // +getCurr(timeOfNextFire+para.ABSREF)[1]); 602 603 timeOfLastUpdate = timeOfNextFire+para.ABSREF; 604 605 baseline = timeOfNextFire+para.ABSREF; 606 607 nowV = para.VRESET; 608 609 nowT = Math.max(para.RRESET,backCT+para.THRESHOLDADD); 610 } 611 else 612 { 613 baseline = timeOfNextFire; 614 615 nowV = memStheta(baseline); 616 617 nowT = 0; 618 } 619 620 double dt,vc; 621 622 double de = safeD(baseline); 623 624 double nextTime = (-(nowV - nowT))/de; 625 626 dt=nextTime; 627 628 while (de >0 && nextTime < cost*tAvg) 629 { 630 de = safeD(baseline+nextTime); 631 632 vc = memStheta(baseline+nextTime); 633 634 dt = (-vc/de); 635 636 if(dt>0?dt<tEPS:-dt<tEPS) 637 { 638 fire=true; 639 640 //no spike within absolute refractory period. 641 642 //if(nextTime < para.ABSREF) return -1.0; 643 644 //System.out.println( 645 // "Again:"+(nextTime+baseline - timeOfNextFire)); 646 647 return nextTime+baseline - timeOfNextFire; 648 } 649 650 nextTime += dt; 651 } 652 653 if ( de < 0 || nextTime > 1.0 ) 654 { 655 fire = false; 656 657 return -1.0; 658 } 659 else 660 { 661 fire = false; 662 663 return nextTime+baseline - timeOfNextFire; 664 } 665 } 666 667 @Override 668 public double updateInput ( 669 final double time, 670 final Synapse input ) 671 //////////////////////////////////////////////////////////////////////// 672 { 673 // System.out.println( 674 // "get input at:"+time+ " syn:"+input+ " membrane voltage is:" 675 // +memVoltage(time)); 676 // System.out.println("beg: t:"+time+ " s:"+input+ " mV:" 677 // + memVoltage(time) +" mtV:"+memStheta(time)); 678 679 // update the tAvg; 680 681 tAvg = tAvg * 0.8 + ( time - lastInputTime ) * 0.2; 682 683 lastInputTime = time; 684 685 // System.out.println("before updateInput: memV: " + memV 686 // + " instantThresh: " + instantaneousThreshold + " curr0: " 687 // + curr[0] + " curr1: " + curr[1]); 688 // p.println("updateInput"+time); 689 // p.flush(); 690 691 /* 692 double [] oldcurr = new double [curr.length]; 693 oldcurr[0] = curr[0]; 694 oldcurr[1] = curr[1]; 695 double oldMem=memV ; 696 double VACC = 1E-9; // accuracy in voltage for spike to be generated 697 */ 698 // System.out.println("0t:"+time+ " s:"+input+ " mV:" 699 // + memVoltage(time) +" mtV:"+memStheta(time)+ " th:" 700 // +(memVoltage(time)-memStheta(time))); 701 702 // update state 0,1 to current time; 703 704 sta_p [ 0 ].value *= Math.exp ( 705 -( time - sta_p [ 0 ].time ) * para.allDecays [ 0 ] ); 706 707 // System.out.println("ng decay:"+Math.exp(-(time-sta_p[0].time) 708 // *para.allDecays[0])); 709 710 sta_p [ 0 ].time = time; 711 712 sta_p [ 1 ].value *= Math.exp ( 713 -( time - sta_p [ 1 ].time ) * para.allDecays [ 1 ] ); 714 715 sta_p [ 1 ].time = time; 716 717 // System.out.println("mid1: t:"+time+ " s:"+input+ " mV:" 718 // + memVoltage(time) +" mtV:"+memStheta(time)); 719 720 //check whether the input is deleted 721 722 if ( sta_p [ input.getType ( ) + 2 ] == null ) //activate it 723 { 724 //System.out.println("act"); 725 726 sta_p [ input.getType ( ) + 2 ] = new State ( time, 0, input.getType ( ) + 2 ); 727 728 state.add ( sta_p [ input.getType ( ) + 2 ] ); 729 } 730 else 731 { 732 sta_p [ input.getType ( ) + 2 ].value *= Math.exp ( 733 -( time - sta_p [ input.getType ( ) + 2 ].time ) 734 * para.allDecays [ input.getType ( ) + 2 ] ); 735 736 sta_p [ input.getType ( ) + 2 ].time = time; 737 } 738 739 // System.out.println("mid2: t:"+time+ " s:"+input+ " mV:" 740 // + memVoltage(time) +" mtV:"+memStheta(time)); 741 742 // add the extra state values (0,2,this synapse) by getting input 743 // spike. 744 745 sta_p [ 0 ].value += input.getWeight ( ) 746 / para.GLCAPDECAY [ input.getType ( ) ] * ( para.ABGLCAP - 1 ); 747 748 sta_p [ 1 ].value 749 -= input.getWeight ( ) / para.BCAPDECAY [ input.getType ( ) ] * para.ABGLCAP; 750 751 sta_p [ input.getType ( ) + 2 ].value 752 += ( input.getWeight ( ) / para.GLCAPDECAY [ input.getType ( ) ] ) 753 * ( 1 - para.ABDECAY [ input.getType ( ) ] ); 754 755 double nextTime; 756 757 double baseline; 758 759 double nowV = memVoltage ( time ); 760 761 double nowT = nowV - memStheta ( time ); 762 763 if ( time < timeOfLastUpdate ) 764 { 765 // set the offset of the membraneVoltage to make sure at the 766 // timeOfLastUpdate the membraneVoltage is not changed at all 767 // CON_v = CON_v - (memStheta(timeOfLastUpdate) - nowMem); 768 769 /* 770 if(clamp_v==Double.MAX_VALUE) //if clamp_v is not set; 771 { 772 clamp_v= nowV; 773 clamp_t= nowT; 774 } 775 */ 776 777 final double vFuture = memVoltage ( timeOfLastUpdate ); 778 779 final double voltageOffset = ( vFuture - clamp_v ); 780 781 final double 782 tOffset = vFuture - memStheta ( timeOfLastUpdate ) - clamp_t; 783 784 sta_p [ 0 ].value += -( 1 - para.ABGLCAP ) * voltageOffset 785 * Math.exp ( ( timeOfLastUpdate - time ) * para.allDecays [ 0 ] ); 786 787 sta_p [ 1 ].value += -( para.ABGLCAP * voltageOffset - tOffset ) 788 * Math.exp ( ( timeOfLastUpdate - time ) * para.allDecays [ 1 ] ); 789 790 //System.out.println("nowV:"+nowV+" futV:" 791 // +memVoltage(timeOfLastUpdate)+" clamp_v:"+clamp_v); 792 793 //System.out.println("nowT:"+nowT+" futT:" 794 // +(memVoltage(timeOfLastUpdate)-memStheta(timeOfLastUpdate)) 795 // +" clamp_6:"+clamp_t); 796 797 // sta_p[0].value += (1-para.ABGLCAP)*vOffset; 798 799 // sta_p[1].value += para.ABGLCAP*vOffset - tOffset; 800 801 nowV = clamp_v; 802 803 nowT = clamp_t; 804 805 baseline = timeOfLastUpdate; 806 } 807 else 808 { 809 clamp_v = Double.MAX_VALUE; 810 811 clamp_t = Double.MAX_VALUE; 812 813 //if(input.to==1) 814 { 815 // System.out.println("t:"+time+ " s:"+input+ " mV:" 816 // + memVoltage(time) +" mtV:"+memStheta(time)+ " th:" 817 // +(memVoltage(time)-memStheta(time))+ " last:" 818 // +timeOfLastUpdate); 819 // 820 // System.out.println("t:"+time+ " s:"+input+ " mV:"+memV 821 // +" mtV:"+ (memV- instantaneousThreshold)+ " th:" 822 // +instantaneousThreshold); 823 824// TODO: Is this for debugging only or does it have side-effects? 825 final double [ ] out = getCurr ( time ); 826 827 //System.out.println("c0:"+out[0]+ " c1:"+out[1]); 828 } 829 830 timeOfLastUpdate=time; 831 832 baseline = time; 833 } 834 835 double dt, vc; 836 837 double de = safeD ( baseline ); 838 839 nextTime = ( -( nowV - nowT ) / de ); 840 841 dt = nextTime; 842 843 // if ( nowV - nowT > 0 ) return -1.0; 844 845 if ( ( nowV - nowT ) < 0 ) 846 { 847 848 while ( de > 0 && nextTime < cost * tAvg ) 849 { 850 de = safeD ( baseline + nextTime ); 851 852 vc = memStheta ( baseline + nextTime ); 853 854 dt = ( -vc / de ); 855 856 // System.out.print("n:"+nextTime+" s:"+(-vc)+"/"+de+"="+dt 857 // +" Etime:"+(time+nextTime)); 858 859 if ( dt > 0 ? dt < tEPS : -dt < tEPS ) 860 { 861 fire = true; 862 863 // System.out.println(); 864 865 // if(nextTime < timeOfLastUpdate - time) 866 // { 867 // //System.out.println("fail to fire nextTime:"+nextTime 868 // // +" smaller than:"+(timeOfLastUpdate - time)); 869 // return -1.0; //no spike within absolute refractory period. 870 // } 871 872 // System.out.println("N :"+input.to+" fire:" 873 // +(time>timeOfLastUpdate?nextTime:nextTime 874 // +timeOfLastUpdate-time) 875 // + " memV:"+memStheta(baseline+nextTime)); 876 877 return ( time > timeOfLastUpdate 878 ? nextTime : nextTime + timeOfLastUpdate - time ); 879 } 880 881 nextTime += dt; 882 } 883 } 884 885 if ( de < 0 || nextTime > 1.0 ) 886 { 887 fire = false; 888 889 return -1.0; 890 } 891 else 892 { 893 fire = false; 894 895 return ( time > timeOfLastUpdate 896 ? nextTime : nextTime + timeOfLastUpdate - time ); 897 } 898 899 // System.out.println(); 900 901 // System.out.println("fail to fire dt:"+dt+ " nextTime:"+nextTime 902 // + " test:"+memStheta(time+0.10316241162745285)+ " deri:"+de 903 // + " safeD:"+safeD(time+0.10316241162745285)); 904 // 905 // return -1.0; 906 } 907 908 //////////////////////////////////////////////////////////////////////// 909 // overridden Object methods 910 //////////////////////////////////////////////////////////////////////// 911 912 @Override 913 public String toString() 914 //////////////////////////////////////////////////////////////////////// 915 { 916 String tmp=""; 917 // tmp=tmp+"MemVol:"+memV+"\n"; 918 tmp=tmp+"Current:"+"\n"; 919 // for(int i=0;i<curr.length;i++) 920 // { 921 // tmp=tmp+" curr"+i+" "+curr[i]+"\n"; 922 // } 923 // tmp=tmp+axon; 924 return tmp; 925 } 926 927 //////////////////////////////////////////////////////////////////////// 928 // non-interface accessor methods 929 //////////////////////////////////////////////////////////////////////// 930 931 /*********************************************************************** 932 * get the current which is the last updated current 933 ***********************************************************************/ 934 public double [ ] getCurr ( ) 935 //////////////////////////////////////////////////////////////////////// 936 { 937 double [] out = new double[para.DECAY.length]; 938 939 for(int a=0;a<para.DECAY.length;a++) 940 { 941 if(sta_p[a+2]==null) 942 { 943 out[a]=0; 944 } 945 else 946 { 947 out[a] = sta_p[a+2].value*para.GLCAPDECAY[a] 948 / (1 - para.ABDECAY[a]); 949 } 950 } 951 952 return out; 953 } 954 955 public double getCurr ( 956 final int a, 957 final double [ ] curr ) 958 //////////////////////////////////////////////////////////////////////// 959 { 960 // Nj terms 961 962 return (curr[a]/para.GLCAPDECAY[a])*(1 - para.ABDECAY[a]); 963 } 964 965 /*********************************************************************** 966 * return nb term 967 ***********************************************************************/ 968 public double getNB ( 969 double instantaneousThreshold, 970 double memV, 971 double curr[] ) 972 //////////////////////////////////////////////////////////////////////// 973 { 974 double nbTerm=para.VREST-memV+para.IEXT/(para.B*para.CAP); 975 976 for(int a=0;a<curr.length;a++) 977 { 978 nbTerm+=curr[a]/para.BCAPDECAY[a];//replace b*cap for para.GL 979 } 980 981 nbTerm*=para.ABGLCAP; 982 983 nbTerm+=instantaneousThreshold-para.THRESHOLD; 984 985 return -nbTerm; 986 } 987 988 /*********************************************************************** 989 * return ng term ( membrane voltage - ABGLCAP * membranevoltageNg ) 990 ***********************************************************************/ 991 public double getNG ( 992 final double memV, 993 final double [ ] curr ) 994 //////////////////////////////////////////////////////////////////////// 995 { 996 double ngTerm1 = memV - para.VREST - para.IEXT / para.GL; 997 998 // LOGGER.debug ( "curr.length: {}", curr.length ); 999 1000 for ( int a = 0; a < curr.length; a++ ) 1001 { 1002 ngTerm1 -= curr [ a ] / para.GLCAPDECAY [ a ]; 1003 } 1004 1005 return ngTerm1 - ngTerm1 * para.ABGLCAP; 1006 } 1007 1008 public double getSensoryWeight ( ) 1009 //////////////////////////////////////////////////////////////////////// 1010 { 1011 throw new RuntimeException ( 1012 "This neuron type doesn't use the Sensory Weight Functions!" ); 1013 } 1014 1015 public double getTimeOfLastUpdate ( ) 1016 //////////////////////////////////////////////////////////////////////// 1017 { 1018 return timeOfLastUpdate; 1019 } 1020 1021 //////////////////////////////////////////////////////////////////////// 1022 // non-interface mutator methods 1023 //////////////////////////////////////////////////////////////////////// 1024 1025 public void setMemV ( final double memV ) 1026 //////////////////////////////////////////////////////////////////////// 1027 { 1028// TODO: Why is this method body empty? 1029 1030 return; 1031 } 1032 1033 public void setTimeOfLastUpdate ( final double timeOfLastUpdate ) 1034 //////////////////////////////////////////////////////////////////////// 1035 { 1036 this.timeOfLastUpdate = timeOfLastUpdate; 1037 } 1038 1039 //////////////////////////////////////////////////////////////////////// 1040 //////////////////////////////////////////////////////////////////////// 1041 1042 public double memStheta(double t) //absolute time t; 1043 //////////////////////////////////////////////////////////////////////// 1044 { 1045// double V=0.0; 1046// Iterator<State> iter = state.iterator(); 1047// while(iter.hasNext()) 1048// { 1049// State tmpState = iter.next(); 1050// if(t-tmpState.time!=0) 1051// { 1052// V += Math.exp(-(t-tmpState.time) 1053// *para.allDecays[(int)tmpState.id])*tmpState.value; 1054// } 1055// else 1056// { 1057// V += tmpState.value; 1058// } 1059// } 1060// return V+para.CON; 1061 1062 double V=0,constant=0.0; 1063 1064 Iterator<State> iter = state.iterator(); 1065 1066 State first = iter.next(); 1067 1068 State second; 1069 1070 double firstV,secondV; 1071 1072 if(Math.abs(first.value)<rEPS && (int)first.id>1) 1073 { 1074 iter.remove(); //delete the synapse if it is small 1075 1076 sta_p[(int)first.id]=null; 1077 } 1078 1079 if(first.time == t) // ignore no time change term 1080 { 1081 constant += first.value; 1082 1083 if(iter.hasNext()) 1084 { 1085 first = iter.next(); 1086 } 1087 else 1088 { 1089 return V+constant+para.CON; 1090 } 1091 } 1092 1093 firstV = first.value; 1094 1095 V = firstV; 1096 1097 while(iter.hasNext()) 1098 { 1099 second = iter.next(); 1100 1101 if(Math.abs(second.value)<rEPS && (int)second.id>1) 1102 { 1103 iter.remove(); //delete the synapse if it is small 1104 1105 sta_p[(int)second.id]=null; 1106 } 1107 1108 secondV = 0.0; 1109 1110 if(second.time == t) // ignore no time change term 1111 { 1112 constant += second.value; 1113 1114 if(iter.hasNext()) 1115 { 1116 second = iter.next(); 1117 } 1118 else 1119 { 1120 break; 1121 } 1122 } 1123 1124 secondV = second.value; 1125 1126 V = Math.exp(-((para.allDecays[(int)first.id] 1127 - para.allDecays[(int)second.id])*t 1128 - (para.allDecays[(int)first.id]*first.time 1129 - para.allDecays[(int)second.id]*second.time)))*V 1130 + secondV; 1131 1132 first=second; 1133 } 1134 1135 V = Math.exp ( -(para.allDecays[(int)first.id] 1136 *t - para.allDecays[(int)first.id]*first.time))*V; 1137 1138 ////System.out.println("V:"+(V+para.CON_v+para.VREST)); 1139 1140 return V+para.CON+constant; 1141 } 1142 1143 /** absolute time t */ 1144 public double memVoltage ( final double t ) 1145 //////////////////////////////////////////////////////////////////////// 1146 { 1147// double V=0.0; 1148// Iterator<State> iter = state.iterator(); 1149// while(iter.hasNext()) 1150// { 1151// State tmpState = iter.next(); 1152// if((int)tmpState.id != 1 ) // nb term will be ignored. 1153// { 1154// if(t-tmpState.time!=0) 1155// { 1156// if((int)tmpState.id == 0 ) // ng term 1157// { 1158// V += Math.exp(-(t-tmpState.time) 1159// *para.allDecays[(int)tmpState.id]) 1160// *tmpState.value/(1-para.ABGLCAP); 1161// // System.out.print("ng:"+(tmpState.value/(1-para.ABGLCAP)) 1162// + " de:"+Math.exp(-(t-tmpState.time) 1163// *para.allDecays[(int)tmpState.id])); 1164// } 1165// else //current terms 1166// { 1167// V += Math.exp(-(t-tmpState.time) 1168// *para.allDecays[(int)tmpState.id]) 1169// *tmpState.value/(1 - para.ABDECAY[(int)tmpState.id-2]); 1170// // System.out.print(" c:"+(tmpState.id-2)+" " 1171// +(tmpState.value/(1 - para.ABDECAY[(int)tmpState.id-2])) 1172// + " de:"+Math.exp(-(t-tmpState.time) 1173// *para.allDecays[(int)tmpState.id])); 1174// } 1175// } 1176// else 1177// { 1178// if((int)tmpState.id == 0 ) // ng term 1179// { 1180// V += tmpState.value/(1-para.ABGLCAP); 1181// // System.out.print( 1182// // " ng:"+(tmpState.value/(1-para.ABGLCAP))+ " de:0"); 1183// } 1184// else //current terms 1185// { 1186// V += tmpState.value/(1 - para.ABDECAY[(int)tmpState.id-2]); 1187// 1188// // System.out.print(" c:"+(tmpState.id-2)+" " 1189// // +(tmpState.value/(1 - para.ABDECAY[(int)tmpState.id-2])) 1190// // +" de:0"); 1191// } 1192// } 1193// } 1194// } 1195// 1196 // System.out.print("V:"+V+" memV:"+(V+para.CON_v+para.VREST)+"\n"); 1197 // System.out.println("V:"+V+" memV:"+(V+para.CON_v+para.VREST)); 1198 // System.out.println((V+para.CON_v+para.VREST)); 1199 1200 double V=0; 1201 1202 double constant=0; 1203 1204 Iterator<State> iter = state.iterator(); 1205 1206 State first = iter.next(); 1207 1208 State second; 1209 1210 double firstV,secondV; 1211 1212 if(first.id ==1) //ignore nb term 1213 { 1214 if(iter.hasNext()) 1215 { 1216 first = iter.next(); 1217 } 1218 else 1219 { 1220 return V+constant+para.CON_v+para.VREST; 1221 } 1222 } 1223 1224 if(first.time == t) // ignore no time change term 1225 { 1226 if(first.id ==0) 1227 { 1228 constant += first.value/(1-para.ABGLCAP); 1229 } 1230 else 1231 { 1232 constant += first.value/(1 - para.ABDECAY[(int)first.id-2]); 1233 } 1234 if(iter.hasNext()) 1235 { 1236 first = iter.next(); 1237 } 1238 else 1239 { 1240 return V+constant+para.CON_v+para.VREST; 1241 } 1242 } 1243 1244 if(first.id ==1) //ignore nb term 1245 { 1246 if(iter.hasNext()) 1247 { 1248 first = iter.next(); 1249 } 1250 else 1251 { 1252 return V+constant+para.CON_v+para.VREST; 1253 } 1254 } 1255 1256 if(first.id ==0) 1257 { 1258 firstV = first.value/(1-para.ABGLCAP); 1259 } 1260 else 1261 { 1262 //System.out.println(first.id); 1263 firstV = first.value/(1 - para.ABDECAY[(int)first.id-2]); 1264 } 1265 1266 V = firstV; 1267 while(iter.hasNext()) 1268 { 1269 second = iter.next(); 1270 secondV=0.0; 1271 1272 if( second.time == t && second.id != 1) 1273 { 1274 if(second.id ==0) 1275 { 1276 constant += second.value/(1-para.ABGLCAP); 1277 } 1278 else 1279 { 1280 constant += second.value/(1 - para.ABDECAY[(int)second.id-2]); 1281 } 1282 if(iter.hasNext()) 1283 { 1284 second = iter.next(); 1285 } 1286 else 1287 { 1288 break; 1289 } 1290 } 1291 1292 1293 if(second.id == 1) 1294 { 1295 if(iter.hasNext()) 1296 { 1297 second = iter.next(); 1298 } 1299 else 1300 { 1301 break; 1302 } 1303 1304 } 1305 1306 1307 if(second.id ==0) 1308 { 1309 secondV = second.value/(1-para.ABGLCAP); 1310 } 1311 else 1312 { 1313 secondV = second.value/(1 - para.ABDECAY[(int)second.id-2]); 1314 } 1315 1316 V = Math.exp(-((para.allDecays[(int)first.id] 1317 - para.allDecays[(int)second.id])*t 1318 - (para.allDecays[(int)first.id]*first.time 1319 - para.allDecays[(int)second.id]*second.time)))*V 1320 + secondV; 1321 1322 first=second; 1323 } 1324 1325 V = Math.exp ( -(para.allDecays[(int)first.id]*t 1326 - para.allDecays[(int)first.id]*first.time))*V; 1327 1328 //System.out.println("V:"+(V+para.CON_v+para.VREST)); 1329 1330 return V+para.CON_v+para.VREST+constant; 1331 } 1332 1333 /** absolute time t */ 1334 public double safeD ( final double t ) 1335 //////////////////////////////////////////////////////////////////////// 1336 { 1337 // the smallest inverse decay of all negative state variables 1338 1339 double tauSafe=Double.MAX_VALUE; 1340 1341 //find the tauSafe 1342 1343 Iterator<State> iter = state.descendingIterator(); 1344 1345 while(iter.hasNext()) 1346 { 1347 State tmpState = iter.next(); 1348 1349 // System.out.println("value:"+tmpState.value+" delay:" 1350 // + para.allDecays[(int)tmpState.id] 1351 // + " id:"+(int)tmpState.id+ " time:"+tmpState.time); 1352 1353 if(tmpState.value<0) 1354 { 1355 tauSafe = para.allDecays[(int)tmpState.id]; 1356 1357 break; 1358 } 1359 } 1360 1361 ////System.out.println(" 1362 // //System.out.println("safe:"+tauSafe); 1363 //calculate the dV 1364 // 1365 1366 double constant=0; 1367 1368 double V=0; 1369 1370 iter = state.iterator(); 1371 1372 State first = iter.next(); 1373 1374 State second; 1375 1376 double firstV,secondV; 1377 1378 if(first.time == t) // ignore no time change term 1379 { 1380 if(first.value>0) 1381 { 1382 double maxDecay = Math.min(para.allDecays[(int)first.id],tauSafe); 1383 1384 constant += -first.value*maxDecay; 1385 } 1386 else 1387 { 1388 constant += -first.value*para.allDecays[(int)first.id]; 1389 } 1390 1391 if(iter.hasNext()) 1392 { 1393 first = iter.next(); 1394 } 1395 else 1396 { 1397 return V+constant; 1398 } 1399 } 1400 1401 if(first.value>0) 1402 { 1403 double maxDecay = Math.min(para.allDecays[(int)first.id],tauSafe); 1404 1405 firstV = -first.value*maxDecay; 1406 } 1407 else 1408 { 1409 firstV = -first.value*para.allDecays[(int)first.id]; 1410 } 1411 1412 V = firstV; 1413 1414 while(iter.hasNext()) 1415 { 1416 second = iter.next(); 1417 1418 secondV = 0.0; 1419 1420 if( second.time == t) 1421 { 1422 if(second.value>0) 1423 { 1424 double maxDecay 1425 = Math.min(para.allDecays[(int)second.id],tauSafe); 1426 1427 constant += -second.value*maxDecay; 1428 } 1429 else 1430 { 1431 constant += -second.value*para.allDecays[(int)second.id]; 1432 } 1433 1434 if(iter.hasNext()) 1435 { 1436 second = iter.next(); 1437 } 1438 else 1439 { 1440 break; 1441 } 1442 } 1443 1444 if(second.value>0) 1445 { 1446 double maxDecay 1447 = Math.min(para.allDecays[(int)second.id],tauSafe); 1448 1449 secondV = -second.value*maxDecay; 1450 } 1451 else 1452 { 1453 secondV = -second.value*para.allDecays[(int)second.id]; 1454 } 1455 1456 V = Math.exp(-((para.allDecays[(int)first.id] 1457 - para.allDecays[(int)second.id])*t 1458 - (para.allDecays[(int)first.id]*first.time 1459 - para.allDecays[(int)second.id]*second.time)))*V+secondV; 1460 1461 first=second; 1462 } 1463 1464 V = Math.exp( -(para.allDecays[(int)first.id]*t 1465 - para.allDecays[(int)first.id]*first.time))*V; 1466 1467// double dV=0; 1468// iter = state.iterator(); 1469// while(iter.hasNext()) 1470// { 1471// State tmpState = iter.next(); 1472// if(tmpState.value>0) 1473// { 1474// double maxDecay 1475// = Math.min(para.allDecays[(int)tmpState.id],tauSafe); 1476// if(t-tmpState.time!=0) 1477// { 1478// // dV -= Math.exp(-(t-tmpState.time)*maxDecay) 1479// // *tmpState.value*maxDecay; 1480// dV -= Math.exp(-(t-tmpState.time) 1481// *para.allDecays[(int)tmpState.id])*tmpState.value*maxDecay; 1482// } 1483// else 1484// { 1485// dV -= tmpState.value*maxDecay; 1486// } 1487// } 1488// else 1489// { 1490// if(t-tmpState.time!=0) 1491// { 1492// dV -= Math.exp(-(t-tmpState.time)*para.allDecays[ 1493// (int)tmpState.id])*tmpState.value 1494// *para.allDecays[(int)tmpState.id]; 1495// } 1496// else 1497// { 1498// dV -= tmpState.value*para.allDecays[(int)tmpState.id]; 1499// } 1500// } 1501// } 1502 1503 return V + constant; 1504 } 1505 1506 //////////////////////////////////////////////////////////////////////// 1507 //////////////////////////////////////////////////////////////////////// 1508 }