Ein Izhikevich-Neuron ist ein einfaches, aber sehr effektives Modell eines biologischen Neurons, das für die Verwendung in einer diskreten Zeitschritt-Simulation entwickelt wurde. In dieser Golfherausforderung implementieren Sie dieses Modell.
Parameter
Dieses Modell umfasst nur 7 Variablen, die in 2 Differentialgleichungen organisiert sind, verglichen mit den Dutzenden von Parametern eines physiologisch genauen Modells.
v
undu
sind die beiden Zustandsvariablen des Neurons. Hierbeiv
handelt es sich um die "schnelle" Variable, die das Zellpotential über die Zeit darstellt, undu
um die "langsame" Variable, die bestimmte Membraneigenschaften darstellt. Diev
Variable ist die wichtigste, da dies die Ausgabe der Simulation ist.a
,b
,c
, Undd
sind Konstanten festgelegt, die die Eigenschaften des Neurons beschreiben. Verschiedene Arten von Neuronen haben je nach gewünschtem Verhalten unterschiedliche Konstanten. Bemerkenswertc
ist das Rücksetzpotential, dh das Membranpotential, auf das die Zelle nach dem Aufstocken zurückkehrt.I
repräsentiert den Eingangsstrom zum Neuron. In Netzwerksimulationen wird sich dies mit der Zeit ändern, aber für unsere Zwecke werden wir diesI
als feste Konstante behandeln.
Das Model
Dieses Modell hat einen sehr einfachen Pseudocode. Zunächst nehmen wir die konstanten Werte von abcd
und verwenden sie zur Initialisierung v
und u
:
v = c
u = b * c
Als nächstes durchlaufen wir den Simulationscode so oft wie gewünscht. Jede Iteration entspricht einer Millisekunde.
for 1..t:
if v >= 30: # reset after a spike
v = c
u = u + d
v += 0.04*v^2 + 5*v + 140 - u + I
u += a * (b*v - u)
print v
Bestimmte Real-World-Implementierungen enthalten zusätzliche Schritte für die numerische Genauigkeit, die hier jedoch nicht berücksichtigt werden.
Eingang
Als Eingabe Ihr Programm / Funktion die Werte nehmen soll a
, b
, c
, d
, I
, und t
(die Anzahl der Zeitschritte zu simulieren). Einmal eingestellt, ändert sich keiner dieser Parameter während unserer einfachen Simulation. Die Reihenfolge der Eingabe spielt keine Rolle: Sie können die Reihenfolge angeben, in der Ihr Programm diese Parameter verwendet.
Ausgabe
Es wird eine Liste von Zahlen ausgegeben, die das Membranpotential der Zelle (gegeben durch Variable v
) im Verlauf der Simulation darstellen. Die Liste kann in jedem geeigneten Format vorliegen.
Sie haben die Wahl, ob Sie den 0. Wert der Simulation (die Erstkonfiguration, bevor eine Zeit verstrichen ist) in Ihre Ausgabe einbeziehen möchten. Zum Beispiel für eine Eingabe von 0.02 0.2 -50 2 10 6
(für a b c d I t
) eine Ausgabe von entweder
-50
-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068
oder
-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068
ist akzeptabel.
Ihre Werte müssen nicht exakt mit den oben genannten Werten übereinstimmen , je nachdem, wie Ihre Sprache mit Gleitkommazahlen umgeht.
Referenzimplementierung
Hier ist eine TIO-Implementierung, die ich in Perl geschrieben habe, um das Modell zu demonstrieren. Die Parameter sind die eines "klappernden" Neurons aus dem oben verlinkten Artikel, und dies dient als Demonstration, wie dieses Modell einige der komplexeren Eigenschaften von Neuronen wiederherstellen kann, wie z. B. das Wechseln zwischen Zuständen hoher und niedriger Aktivität. Wenn Sie sich den Ausgang ansehen, können Sie sehen, wo das Neuron sofort mehrere Male spitzt, aber dann eine Weile wartet, bevor es mehrere Male spitzt (obwohl die Zelleingangsspannung I
die ganze Zeit konstant ist).
quelle
t
jemals negativ sein?Antworten:
R ,
11099 BytesAnonyme Funktion, die 6 Argumente akzeptiert. Nichts Besonderes, nur eine einfache Portierung der Referenzimplementierung. Die Aktualisierung von
u
,v
und das Drucken vonv
wurden alle in einer einzigen Zeile zusammengefasst, da R denprint
zu druckenden Wert zurückgibt, sodass Sie ihn bei der Zuweisung verwenden können. Vielen Dank an Giuseppe für das Speichern von 11 Bytes!Probieren Sie es online!
quelle
pryr::f()
und kein Byte gespeichertfunction()
. Sie können jedoch nach einigen Experimenten bewegenv
undu
‚s Erklärungen in den Funktionskörper , während die Reihenfolge der Argumente zu bewahren, ein Dutzend speichern Bytes Online ausprobieren!v
nicht unbedingt ganzzahlige Werte verwendet werden müssenv>=30
, ist dies jedoch erforderlichSauber ,
150145140138 BytesProbieren Sie es online!
Definiert die Funktion
$ :: Real Real Real Real Real Int -> [Real]
, die den Algorithmus wie im OP beschrieben ab dem 0. Term implementiert.quelle
Python 2 , 100 Bytes
Probieren Sie es online!
2 Bytes dank user71546 gespeichert .
quelle
0.04*v*v
zu wechseln ,v*v/25.
sollte 1 Byte gespart werden. Wenn immer für floats angegebenc
wird,v*v/25
reicht das für -2 Bytes.v>29
in meiner ursprünglichen Version hatte. Dies ist jedoch ungültig, dav
es sich nicht unbedingt um eine Ganzzahl handelt.JavaScript (Node.js) ,
107...103101 BytesBeigetragen von @apsillers
Probieren Sie es online!
Ursprünglicher Ansatz:
105103 Bytes. -1 Byte Danke Arnauld und -2 Byte Danke @ Kamoroso94.Probieren Sie es online!
Oder wenn das Poppen von Warnungen in Ordnung ist, dann
101...9997 Bytes (-1 Bytes Danke Arnauld, -2 Bytes Danke @ Kamoroso94):quelle
v>29
ist nicht gleichbedeutend mitv>=30
für Schwimmer. Sie möchten wahrscheinlichv<30?0:(v=c,u+=d)
stattdessen oder noch besser,v<30||(v=c,u+=d)
was ein Byte speichert.t-->0
zu einfach wechselnt--
.for
Schleife in einenmap
Betrieb auf einer Anordnung von Länget
:(a,b,c,d,I,t)=>[...Array(t)].map(_=>(v<30||(v=c,u+=d),v=v*(v/25+6)+140-u+I,u+=a*(b*v-u),v),u=b*(v=c))
. Die Funktion gibt ein Array zurück, anstatt Werte zu protokollieren, die anscheinend der Spezifikation entsprechen. Aber diealert
Lösung ist nicht zu schlagen .Ruby , 94 Bytes
Probieren Sie es online!
Ein weiterer einfacher Port der Referenzimplementierung: Ein Lambda, das 6 Argumente akzeptiert.
quelle
Haskell ,
112111 BytesProbieren Sie es online!
Gibt den Nullfall nicht aus. Nimmt an, dass dies
c
niemals der Fall ist,>=30
da dies keinen Sinn ergibt .Ich hätte nie gedacht, dass ich einewhere
Klausel in einem Codegolf verwenden muss, aber es gibt einfach zu viele Variablen.EDIT: Danke @Lynn für das Abheben eines Bytes! Ich habe vergessen, dass Sie
let
Aussagen in Wachen setzen können. Klar, aber die Lesbarkeit ist nicht gutquelle
where
durch die seltsamef x|let g a=b=y
Syntax ersetzen , um ein Byte zu speichern:(a#b)c d i t|let r(v,u)|v>=30=r(c,u+d)|p<-0.04*v^2+6*v+140-u+i=(p,u+a*(b*p-u))=fst<$>take t(iterate r$r(c,b*c))
Element , 81 Bytes
Probieren Sie es online! , Esolangs Seite
Erläuterung:
Dieser Teil des Programms nimmt Eingaben vor. Es speichert Konstanten
a
,b
,d
, undI
in Variablen. Die Eingabe fürc
wird nie in einer Variablen gespeichert, sondern verbleibt während der Ausführung auf dem Hauptstapel. Es werden drei Kopien erstellt: eine oben zum Initialisierenu
, eine in der Mitte als Initialev
und eine unten als Konstantec
. Die Eingabe fürt
wird sofort auf den Steuerstapel geworfen, um als Grundlage für die FOR-Schleife (die FOR-Schleife[...]
) zu dienen, die den Rest des Programms umgibt.Dieser Teil des Programms nimmt den aktuellen Wert von
v
und berechnet den neuen Wert. Anschließend werden vier Kopien des neuenv
Werts erstellt.Die erste Kopie von
v
hat einen Zeilenvorschub angehängt und wird gedruckt.Die zweite Kopie von
v
wird verwendet, um zu testen, ob das Neuron einen Spitzenwert aufweist. Das Ergebnis dieses Tests wird zur späteren Verwendung auf dem Kontrollstapel abgelegt.Dieser Teil berechnet das "Delta
u
", dh den Betrag, zu dem hinzugefügt werden sollu
.Dieser IF-Block addiert sich
d
zu der obigen Summe, wenn das Neuron spitzt. Dadurch werden normalerweise zwei Aufgaben zu einer einzigen Aufgabe zusammengefasst.Hier wird der aktualisierte Wert von gespeichert
u
.Dieser IF-Block ist eine Fortsetzung des obigen IF-Blocks. Wenn das Neuron einen Spitzenwert aufweist, löschen Sie den aktuellen Wert von
v
(der sich jetzt oben auf dem Hauptstapel befindet) und ersetzen Sie ihn durch ein Duplikat vonc
(das sich die ganze Zeit unten auf dem Hauptstapel befunden hat).Und das ist im Grunde alles, was dazu gehört. Eine kleine Anmerkung ist, dass diese Sache Gedächtnis verliert: es nimmt ein Extra
"#
, um die Oberseite des Kontrollstapels (die ausgewertete IF-Bedingung) nach jeder Schleifeniteration zu löschen.Obwohl ich Element nicht als die eleganteste Golfsprache bezeichnen würde, kann ich mit dieser Herausforderung ein interessantes Feature präsentieren: Aufgrund der Aufteilung zwischen Hauptstapel und Kontrollstapel kann ich eine IF-Anweisung nehmen und die Bedingung und den Körper in mehrere aufteilen Teile, mit unbedingtem Code verschachtelt.
quelle
MATLAB, 111 Bytes
Ziemlich einfache Implementierung, kann wahrscheinlich weiter verbessert werden.
quelle