Model nöronu simüle et


16

Bir Izhikevich nöronu , ayrık bir zaman atlama simülasyonunda kullanılmak üzere tasarlanmış, basit ama oldukça etkili bir biyolojik nöron modelidir. Bu golf mücadelesinde, bu modeli uygulayacaksınız.

Parametreler

Bu model, fizyolojik olarak doğru bir modelin düzinelerce parametresine kıyasla, 2 diferansiyel denklemde organize edilmiş sadece 7 değişken içerir.

  • vve unöronun iki durum değişkenidir. Burada, vzaman içinde hücre potansiyelini temsil eden "hızlı" değişken ve ubelirli membran özelliklerini temsil eden "yavaş" değişkendir. vBu simülasyonun çıkış olarak değişken, en önemli biridir.
  • a, b, cVe dnöronun özelliklerini tarif sabitler sabitlenir. Farklı nöron tipleri, istenen davranışa bağlı olarak farklı sabitlere sahiptir. Dikkat çekici bir şekilde, chücrenin, eklemeden sonra geri döndüğü zar potansiyeli olan sıfırlama potansiyeli vardır.
  • Inöronun giriş akımını temsil eder. Ağ simülasyonlarında bu zamanla değişecektir, ancak bizim amacımız Iiçin sabit bir sabit olarak ele alacağız .

Model

Bu modelin çok basit bir sözde kodu vardır. İlk olarak, sürekli değerleri alır abcdve başlatmak için bunları kullanmak vve u:

v = c
u = b * c

Ardından, simülasyon kodunu istediğiniz kadar tekrarlıyoruz. Her yineleme 1 milisaniyeyi temsil eder.

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

Bazı gerçek dünya uygulamaları sayısal doğruluk için ek adımlar içerir, ancak biz bunları buraya dahil etmiyoruz.

Giriş

Girdi olarak, programınız / fonksiyon değerlerini almalı a, b, c, d, I, ve t(simüle etmek için zaman adım sayısı). Ayarlandıktan sonra, basit simülasyonumuz sırasında bu parametrelerin hiçbiri değişmeyecektir. Giriş sırası değil önemli : programınızın bu parametreleri hangi sırada alacağını belirleyebilirsiniz.

Çıktı

Çıktı v, simülasyon süresince hücrenin zar potansiyelini (değişken tarafından verilen ) temsil eden sayıların bir listesi olacaktır . Liste uygun herhangi bir biçimde olabilir.

Çıktınıza simülasyonun 0. değerini (herhangi bir zaman geçmeden önceki ilk yapılandırma) dahil edip etmeyeceğinizi seçebilirsiniz. Örneğin, 0.02 0.2 -50 2 10 6(for a b c d I t) girdisi için ,

-50
-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068

veya

-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068

kabul edilebilir.

Kişisel değerler yok değil dil kolları yüzen nasıl bağlı olanlar yukarıdaki tamamen aynı olmak zorunda.

Referans uygulaması

İşte modeli göstermek için Perl'de yazdığım bir TIO uygulaması . Parametreler, yukarıda bağlantılı kağıttan bir "gevezelik" nöronunkidir ve bu, bu modelin, yüksek ve düşük aktivite durumları arasında dönüşüm yapma gibi nöronların daha karmaşık özelliklerini nasıl yeniden oluşturabildiğinin bir göstergesi olarak hizmet eder. Çıktıya bakarsanız, nöronun hemen birkaç kez nerede yükseldiğini görebilirsiniz, ancak daha sonra birkaç kez daha fazla eklemeden önce bir süre bekler (hücre giriş voltajının Isürekli sabit olmasına rağmen ).


Will thiç negatif?
kamoroso94

1
@ kamoroso94 Hayır, negatif zamanı simüle edemezsiniz.
PhiNotPi

Yanıtlar:


6

R, , 110 99 bayt

6 bağımsız değişken alan anonim işlev. Hiçbir şey fantezi, sadece referans uygulama basit bir bağlantı noktası. Güncellenmesi u, vve baskı arasındav tüm tek bir satır olarak birleştirilmiştir aslında sayesinde o R'ın printdöner Ödevi kullanabilirsiniz böylece basılıyor ve değer. Giuseppe'ya 11 bayt kurtardığı için çok teşekkürler!

pryr::f({v=c;u=b*c;for(i in 1:t){if(v>=30){v=c;u=u+d}
u=a*b*(v=print((.04*v+6)*v+140+I-u))-a*u+u}})

Çevrimiçi deneyin!


2
Bu harika, +1. Her ne kadar, argümanları açıkça etiketlediğinizden, pryr::f()ve arasında hiçbir bayt tasarrufu yoktur function(). Bununla birlikte, bazı deneylerden sonra , argümanların sırasını koruyarak bir düzine bayt kaydetmek için işlev gövdesine vve ubildirimlerini işlev gövdesine taşıyabilirsiniz : Çevrimiçi deneyin!
Giuseppe

çünkü vmutlaka tam sayı değerlerini almaz, sen gereğini yapmakv>=30 , buna
Giuseppe

@Giuseppe Teşekkürler, bu gelişmeler harika. Nedense argümanları açıkça etiketlemediğimi
düşünmemiştim

4

Temiz , 150 145 140 138 bayt

import StdEnv
$a b c d i t=map snd(iterate(\(u,v)#(w,n)=if(30.0<v)(c,u+d)(v,u)
#y=0.04*w*w+6.0*w+140.0-n+i
=(a*b*y-a*n+n,y))(b*c,c))%(0,t)

Çevrimiçi deneyin!

$ :: Real Real Real Real Real Int -> [Real]0. terimden başlayarak OP'de açıklandığı gibi algoritmayı uygulayan işlevi tanımlar .


3

Python 2,100 bayt

a,b,c,d,I,t=input();v=c;u=b*c
exec"if v>=30:v=c;u+=d\nv=v*v/25+6*v+140-u+I;u+=a*(b*v-u);print v\n"*t

Çevrimiçi deneyin!

User71546 sayesinde 2 bayt kaydedildi .


@ovs Hata! Haklısın. Şimdi düzeltilmelidir.
Bay Xcoder

Torna 0.04*v*viçin v*v/25.1 bayt kaydetmek gerekir. Yüzer daima verildiyse co zaman v*v/25için yeterli -2 bayt.
Shieru Asakoto

@ceilingcat Düzeltme geçmişime bir göz atarsanız, ilk sürümümde olduğumu fark edeceksiniz v>29. Ancak, geçersiz olduğundan vbir tamsayı değildir.
Bay Xcoder

3

JavaScript (node.js) , 107 ... 103 101 bayt

Katkıda bulunan @apsillers

(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))

Çevrimiçi deneyin!

Orijinal Yaklaşım: 105 103 bayt. -1 bayt Teşekkürler Arnauld ve -2 bayt Teşekkürler @ Kamoroso94.

(a,b,c,d,I,t)=>{for(u=b*(v=c);t--;){v<30||(v=c,u+=d);v=v*(v/25+6)+140-u+I;u+=a*(b*v-u);console.log(v)}}

Çevrimiçi deneyin!

Veya haşhaş uyarıları tamamsa, 101 ... 99 97 bayt (-1 bayt Teşekkürler Arnauld, -2 bayt Teşekkürler @ Kamoroso94):

(a,b,c,d,I,t)=>{for(u=b*(v=c);t--;){v<30||(v=c,u+=d);v=v*(v/25+6)+140-u+I;u+=a*(b*v-u);alert(v)}}

var u, v;
var f = 
(a,b,c,d,I,t)=>{for(u=b*(v=c);t--;){v<30||(v=c,u+=d);v=v*(v/25+6)+140-u+I;u+=a*(b*v-u);alert(v)}}

function run() {
 f(...["a", "b", "c", "d", "I", "t"].map(x => document.getElementById(x).value * 1));
}
a = <input id="a" value="0.02"><br>
b = <input id="b" value="0.2"><br>
c = <input id="c" value="-50"><br>
d = <input id="d" value="2"><br>
I = <input id="I" value="10"><br>
t = <input id="t" value="6"><br>
<input type="button" value="Run" onclick="run()">


v>29v>=30şamandıralar ile eşdeğer değildir . Muhtemelen v<30?0:(v=c,u+=d)bunun yerine, ya da daha iyisi yapmak istersiniz , bu da v<30||(v=c,u+=d)bayt tasarrufu sağlar.
Arnauld

@Arnauld Oh evet, Python cevabına baktığımda bunu optimize etmediğimi fark ettim ama şamandıraları da işlediğimi fark etmedim.; P Sabit.
Shieru Asakoto

2
t-->0Basitçe değiştirerek iki bayt kaydedebilirsiniz t--.
kamoroso94

1
Sen üstlenmeden tarafından 101 bu hakkı elde edebilir forbir ilmeği mapuzunlukta bir dizi üzerinde operasyon t: (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)). İşlev, belirtimi karşılayan değerlerin günlüğe kaydedilmesi yerine bir dizi döndürür. alertYine de çözümü yenmez.
apsillers

2

Ruby , 94 bayt

->a,b,c,d,i,t{v=c
u=b*c
t.times{v>=30?(v=c;u+=d):0
v+=0.04*v**2+5*v+140-u+i
u+=a*(b*v-u)
p v}}

Çevrimiçi deneyin!

Referans uygulamasının bir başka basit limanı, 6 argümanı kabul eden bir lambda.


2

Haskell , 112 111 bayt

(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))

Çevrimiçi deneyin!

Sıfır durum çıktısı vermez. cAsla >=30bunun o zamandan beri geçerli olmadığını varsayar .

whereBir kod golf bir madde kullanmak zorunda olacağını hiç düşünmemiştim ama çok fazla değişken var.

EDIT: @Lynn bayt ayırdığınız için teşekkürler! letMuhafızlara ifade koyabileceğinizi unuttum . Tabii ki okunabilirliği öldürür


1
Bir bayt kaydetmek whereiçin tuhaf f x|let g a=b=ysözdizimi ile değiştirebilirsiniz :(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))
Lynn

1

Öğe , 81 bayt

_a;_b;_3:b~*u;_d;_I;_'[3:\.04*5+*140+u~-+I~++4:\
.`30<!b~*u~-+a~*u~+[d~+]u;[#2:]]

Çevrimiçi deneyin! , Esolangs sayfası

Açıklama:

_a;_b;_3:b~*u;_d;_I;_'[ ... ]

Programın bu kısmı girdi alır. Bu sabitleri depolar a, b, d, ve Ideğişkenlere. İçin girdi chiçbir zaman bir değişkende saklanmaz, bunun yerine yürütme boyunca ana yığın üzerinde kalır. Üç kopya yapılır: biri başlatma için üstte u, biri başlangıçta hizmet etmek için v, diğeri sabit olarak hizmet etmek için altta c. Girişi , programın geri kalanını çevreleyen tFOR döngüsünün ( [...]) temelini oluşturmak üzere hemen kontrol yığınına atılır .

3:\.04*5+*140+u~-+I~++4:

Programın bu kısmı vyeni değeri alır ve yeni değeri hesaplar ve sonra yeni değerin dört kopyası vyapılır.

\
.`

vÖğesinin ilk kopyasına bir satırsonu eklenir ve yazdırılır.

30<!

İkinci kopyası v, nöronun yükselip yükselmediğini test etmek için kullanılır. Bu testin sonucu daha sonra kullanılmak üzere kontrol istifine konur.

b~*u~-+a~*u~+

Bu bölüm "delta u" yı, yani eklenecek miktarı hesaplar u.

[d~+]

Bu IF bloğu d, nöronun yükselmesi durumunda yukarıdaki toplamı ekler . Bu, normalde iki atamanın ne olacağını tek bir atamada birleştirir.

u;

Bu işlemin güncellenmiş değeri saklanır u.

[#2:]

Bu IF bloğu, yukarıdaki IF bloğunun devamıdır. Nöron ani yükseliyorsa, v(şimdi ana yığının üstünde olan) geçerli değerini silin ve (bu süre boyunca ana yığının altında olan) bir kopyasıyla değiştirin c.

Ve temelde hepsi bu kadar. Küçük bir not, bu şeyin hafızayı sızdırmasıdır:"# her döngü yinelemesinden sonra kontrol yığınının üstünü (değerlendirilen IF koşulu) silmek için .

Element'i en zarif golf dili olarak adlandırmasam da, bu meydan okuma ilginç bir özellik sergilememe izin veriyor: ana yığın ve kontrol yığını arasındaki bölünme nedeniyle, bir IF ifadesi alıp koşulu ve gövdeyi çoklu koşulsuz kodla karıştırılmış parçalar.


0

MATLAB, 111 bayt

function z(a,b,c,d,I,t)
v=c;u=b*c;for i=1:t if v>=30 v=c;u=u+d;end
v=.04*v^2+6*v+140-u+I
u=u+a*(b*v-u);
end
end

Oldukça basit bir uygulama, muhtemelen daha da geliştirilebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.