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