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    }