Mensimulasikan model neuron

16

Sebuah Izhikevich neuron adalah sederhana namun model yang cukup efektif dari neuron biologis, dirancang untuk digunakan dalam simulasi waktu-melangkah diskrit. Dalam tantangan golf ini, Anda akan menerapkan model ini.

Parameter

Model ini hanya melibatkan 7 variabel yang disusun dalam 2 persamaan diferensial, dibandingkan dengan lusinan parameter model fisiologis yang akurat.

  • vdan umerupakan dua variabel keadaan neuron. Di sini, vadalah variabel "cepat" yang mewakili potensi sel dari waktu ke waktu, dan umerupakan variabel "lambat" yang mewakili sifat membran tertentu. The vvariabel yang paling penting satu, karena ini adalah output dari simulasi.
  • a, b, c, Dan dyang konstanta yang menggambarkan sifat-sifat neuron tetap. Berbagai jenis neuron memiliki konstanta yang berbeda, tergantung pada perilaku yang diinginkan. Khususnya, cadalah potensi reset, yang merupakan potensi membran sel kembali setelah spiking.
  • Imewakili arus input ke neuron. Dalam simulasi jaringan, ini akan berubah seiring waktu, tetapi untuk tujuan kami, kami akan memperlakukannya Isebagai konstanta tetap.

Model

Model ini memiliki kodesemu yang sangat sederhana. Pertama, kami mengambil nilai konstan abcddan menggunakannya untuk menginisialisasi vdan u:

v = c
u = b * c

Selanjutnya, kita mengulang-ulang kode simulasi sebanyak yang diinginkan. Setiap iterasi mewakili 1 milidetik waktu.

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

Implementasi dunia nyata tertentu mencakup langkah-langkah tambahan untuk akurasi numerik, tetapi kami tidak memasukkannya di sini.

Memasukkan

Sebagai masukan, program anda / fungsi harus mengambil nilai-nilai a, b, c, d, I, dan t(jumlah langkah waktu untuk mensimulasikan). Setelah diatur, tidak ada parameter ini yang akan berubah selama simulasi sederhana kami. Urutan input tidak masalah: Anda dapat menentukan urutan program Anda mengambil parameter ini.

Keluaran

Output akan berupa daftar angka yang mewakili potensi membran sel (diberikan oleh variabel v) selama simulasi. Daftar dapat dalam format apa pun yang sesuai.

Anda memiliki pilihan apakah akan memasukkan nilai 0 simulasi (konfigurasi awal sebelum waktu berlalu) dalam output Anda. Misalnya, untuk input 0.02 0.2 -50 2 10 6(untuk a b c d I t), output dari keduanya

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

atau

-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068

bisa diterima.

Nilai Anda tidak harus persis sama dengan yang di atas, tergantung pada bagaimana bahasa Anda menangani float.

Implementasi Referensi

Berikut ini adalah implementasi TIO yang saya tulis di Perl untuk menunjukkan model. Parameternya adalah neuron "mengobrol" dari makalah yang dihubungkan di atas, dan ini berfungsi sebagai demonstrasi bagaimana model ini mampu menciptakan kembali beberapa sifat neuron yang lebih kompleks, seperti berganti-ganti antara keadaan aktivitas tinggi dan rendah. Jika Anda melihat outputnya, Anda dapat melihat di mana neuron segera melonjak beberapa kali, tetapi kemudian menunggu beberapa saat sebelum melonjak beberapa kali lagi (meskipun tegangan input sel Ikonstan sepanjang waktu).

PhiNotPi
sumber
Akankah tnegatif?
kamoroso94
1
@ kamoroso94 Tidak, Anda tidak dapat mensimulasikan waktu negatif.
PhiNotPi

Jawaban:

6

R , 110 99 byte

Fungsi anonim yang mengambil 6 argumen. Tidak ada yang mewah, hanya port langsung dari implementasi referensi. Memperbarui u, vdan pencetakan vsemuanya telah digabungkan menjadi satu baris, berkat fakta bahwa R printpengembalian nilai yang sedang dicetak, sehingga Anda dapat menggunakannya dalam tugas. Terima kasih banyak kepada Giuseppe karena telah menghemat 11 byte!

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

Cobalah online!

rturnbull
sumber
2
Ini bagus, +1. Meskipun, karena Anda secara eksplisit melabeli argumen, tidak ada penghematan byte di antara pryr::f()dan function(). Namun, Anda dapat, setelah beberapa percobaan, memindahkan vdan udeklarasi ke dalam fungsi tubuh sambil menjaga urutan argumen, untuk menyimpan selusin byte: Coba online!
Giuseppe
karena vtidak selalu mengambil nilai integer, Anda memang perlu v>=30,
Giuseppe
@ Giuseppe Terima kasih, peningkatan itu fantastis. Untuk beberapa alasan saya tidak mempertimbangkan untuk tidak secara eksplisit melabeli argumen ...
rturnbull
4

Bersih , 150 145 140 138 byte

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)

Cobalah online!

Menentukan fungsi $ :: Real Real Real Real Real Int -> [Real], mengimplementasikan algoritma seperti yang dijelaskan dalam OP, mulai dari istilah ke-0.

Suram
sumber
3

Python 2 , 100 byte

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

Cobalah online!

Disimpan 2 byte berkat pengguna71546 .

Tuan Xcoder
sumber
@ Aduh Ups, kau benar. Harus diperbaiki sekarang.
Tn. Xcoder
Beralih 0.04*v*vke v*v/25.harus menyimpan 1 byte. Jika float selalu diberikan cmaka v*v/25cukup untuk -2 byte.
Shieru Asakoto
@ceilingcat Jika Anda melihat pada riwayat revisi saya, Anda akan melihat bahwa saya memiliki v>29versi awal saya. Namun, itu tidak valid karena vbelum tentu integer.
Tn. Xcoder
3

JavaScript (Node.js) , 107 ... 103 101 byte

Dikontribusikan oleh @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))

Cobalah online!

Pendekatan Asli: 105 103 byte. -1 byte Terima kasih Arnauld, dan -2 byte Terima kasih @ 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)}}

Cobalah online!

Atau jika pemberitahuan muncul tidak apa-apa, maka 101 ... 99 97 byte (-1 byte Thanks Arnauld, -2 byte Thanks @ 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()">

Shieru Asakoto
sumber
v>29tidak setara dengan v>=30untuk mengapung. Anda mungkin ingin melakukan v<30?0:(v=c,u+=d)sebaliknya, atau lebih baik lagi v<30||(v=c,u+=d)yang menghemat satu byte.
Arnauld
@Arnauld Oh ya, ketika saya melihat jawaban Python saya menyadari bahwa saya tidak mengoptimalkan itu tetapi saya tidak menyadari bahwa saya sedang memproses float juga.; P Tetap.
Shieru Asakoto
2
Anda dapat menyimpan dua byte dengan mengubah t-->0ke sederhana t--.
kamoroso94
1
Anda bisa berjalan turun ini untuk 101 oleh refactoring forlingkaran menjadi mapoperasi pada array panjang 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)). Fungsi mengembalikan array daripada nilai logging, yang muncul untuk memenuhi spesifikasi. Tidak mengalahkan alertsolusinya.
apsillers
2

Ruby , 94 byte

->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}}

Cobalah online!

Port langsung lain dari implementasi referensi, lambda menerima 6 argumen.

benj2240
sumber
2

Haskell , 112 111 byte

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

Cobalah online!

Tidak menampilkan kotak nol. Anggap itu ctidak pernah >=30karena itu tidak masuk akal.

Tidak pernah berpikir saya harus menggunakan whereklausa dalam kode golf tetapi ada terlalu banyak variabel.

EDIT: Terima kasih @Lynn untuk melepas byte! Saya lupa bahwa Anda dapat menempatkan letpernyataan di penjaga. Tentu membunuh keterbacaan

pengguna1472751
sumber
1
Anda dapat mengganti wheredengan f x|let g a=b=ysintaks aneh untuk menyimpan byte:(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

Elemen , 81 byte

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

Cobalah online! , Halaman Esolangs

Penjelasan:

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

Bagian dari program ini membutuhkan input. Ini menyimpan konstanta a, b, d, dan Imenjadi variabel. Input untuk ctidak pernah disimpan dalam variabel, tetapi tetap berada di tumpukan utama selama eksekusi. Tiga salinan dibuat: satu di atas untuk inisialisasi u, satu di tengah untuk dijadikan sebagai inisial v, dan satu di bawah untuk dijadikan sebagai konstanta c. Input untuk tdilemparkan segera ke tumpukan kontrol untuk dijadikan dasar loop FOR (the [...]) yang mengelilingi sisa program.

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

Bagian dari program ini mengambil nilai saat ini vdan menghitung nilai baru, dan kemudian empat salinan dari nilai baru vdibuat.

\
.`

Salinan pertama vmemiliki baris baru yang ditambahkan dan dicetak.

30<!

Salinan kedua vdigunakan untuk menguji apakah neuron telah berduri. Hasil tes ini diletakkan pada tumpukan kontrol untuk digunakan nanti.

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

Bagian ini menghitung "delta u", artinya jumlah yang ditambahkan u.

[d~+]

Blok IF ini menambah djumlah di atas jika neuron spiking. Ini menggabungkan apa yang biasanya menjadi dua tugas menjadi satu tugas.

u;

Ini menyimpan nilai pembaruan dari u.

[#2:]

Blok IF ini merupakan kelanjutan dari blok IF di atas. Jika neuron melonjak, hapus nilai saat ini v(yang sekarang ada di atas tumpukan utama), dan ganti dengan duplikat c(yang telah berada di bagian bawah tumpukan utama sepanjang waktu ini).

Dan pada dasarnya itu semua ada untuk itu. Satu catatan kecil adalah bahwa hal ini bocor memori: dibutuhkan tambahan "#di sana untuk menghapus bagian atas tumpukan kontrol (kondisi IF yang dievaluasi) setelah setiap iterasi loop.

Walaupun saya tidak akan menyebut Elemen bahasa golf yang paling anggun, tantangan ini memungkinkan saya untuk menampilkan fitur yang menarik: karena pembagian antara tumpukan utama dan tumpukan kontrol, saya dapat mengambil pernyataan IF dan membagi kondisi dan tubuh menjadi beberapa. bagian, terkait dengan kode tanpa syarat.

PhiNotPi
sumber
0

MATLAB, 111 byte

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

Implementasi yang cukup sederhana, mungkin dapat lebih ditingkatkan.

Chris Loonam
sumber