Mô phỏng tế bào thần kinh kiểu mẫu


16

Một tế bào thần kinh Izhikevich là một mô hình đơn giản nhưng khá hiệu quả của một tế bào thần kinh sinh học, được thiết kế để sử dụng trong một mô phỏng bước thời gian rời rạc. Trong thử thách chơi gôn này, bạn sẽ thực hiện mô hình này.

Thông số

Mô hình này chỉ bao gồm 7 biến được tổ chức thành 2 phương trình vi phân, so với hàng chục tham số của mô hình chính xác về mặt sinh lý.

  • vulà hai biến trạng thái của nơron. Ở đây, vlà biến "nhanh" đại diện cho tiềm năng tế bào theo thời gian và ulà biến "chậm" đại diện cho các thuộc tính màng nhất định. Các vbiến là quan trọng nhất, vì đây là đầu ra của mô phỏng.
  • a, b, c, Và dđược cố định hằng số mô tả các thuộc tính của tế bào thần kinh. Các loại tế bào thần kinh khác nhau có hằng số khác nhau, tùy thuộc vào hành vi mong muốn. Đáng chú ý, clà tiềm năng thiết lập lại, đó là tiềm năng màng tế bào trở lại sau khi đạp xe.
  • Iđại diện cho dòng điện đầu vào của nơron. Trong mô phỏng mạng, điều này sẽ thay đổi theo thời gian, nhưng với mục đích của chúng tôi, chúng tôi sẽ coi Ilà một hằng số cố định.

Ngươi mâu

Mô hình này có mã giả rất đơn giản. Đầu tiên, chúng tôi lấy các giá trị không đổi của abcdvà sử dụng chúng để khởi tạo vu:

v = c
u = b * c

Tiếp theo, chúng tôi lặp qua mã mô phỏng nhiều lần như mong muốn. Mỗi lần lặp đại diện cho 1 mili giây thời gian.

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

Một số triển khai trong thế giới thực bao gồm các bước bổ sung cho độ chính xác bằng số, nhưng chúng tôi không bao gồm những bước ở đây.

Đầu vào

Như đầu vào, chương trình / chức năng của bạn nên đưa các giá trị của a, b, c, d, I, và t(số bước thời gian để mô phỏng). Sau khi được đặt, không có tham số nào trong số này sẽ thay đổi trong quá trình mô phỏng đơn giản của chúng tôi. Trình tự đầu vào không không quan trọng: bạn có thể chỉ định thứ tự mà chương trình của bạn có các thông số này.

Đầu ra

Đầu ra sẽ là một danh sách các số biểu thị tiềm năng màng của tế bào (được đưa ra bởi biến v) trong quá trình mô phỏng. Danh sách có thể ở bất kỳ định dạng thích hợp.

Bạn có thể chọn bao gồm giá trị 0 của mô phỏng (cấu hình ban đầu trước khi bất kỳ thời gian nào trôi qua) trong đầu ra của bạn. Ví dụ: đối với đầu vào của 0.02 0.2 -50 2 10 6(for a b c d I t), đầu ra của một trong hai

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

hoặc là

-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068

là chấp nhận được.

Các giá trị của bạn không nhất thiết phải giống hệt như ở trên, tùy thuộc vào cách ngôn ngữ của bạn xử lý nổi.

Thực hiện tham khảo

Đây là một triển khai TIO tôi đã viết trong Perl để trình diễn mô hình. Các tham số là của một tế bào thần kinh "huyên thuyên" từ tờ giấy được liên kết ở trên, và điều này đóng vai trò như một minh chứng về cách mô hình này có thể tái tạo một số tính chất phức tạp hơn của các tế bào thần kinh, như xen kẽ giữa các trạng thái hoạt động cao và thấp. Nếu bạn nhìn vào đầu ra, bạn có thể thấy nơ-ron ngay lập tức tăng vọt vài lần, nhưng sau đó đợi một lúc trước khi đạp thêm vài lần nữa (mặc dù điện áp đầu vào của tế bào Ikhông đổi trong toàn bộ thời gian).


Sẽ tbao giờ là tiêu cực?
kamoroso94

1
@ kamoroso94 Không, bạn không thể mô phỏng thời gian tiêu cực.
PhiNotPi

Câu trả lời:


6

R , 110 99 byte

Hàm ẩn danh có 6 đối số. Không có gì lạ mắt, chỉ là một cổng đơn giản của việc thực hiện tham chiếu. Việc cập nhật u, vvà in vtất cả đều được kết hợp thành một dòng duy nhất, nhờ vào thực tế là R của printlợi nhuận giá trị đang được in, vì vậy bạn có thể sử dụng nó trong chuyển nhượng. Rất cám ơn Giuseppe đã tiết kiệm 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}})

Hãy thử trực tuyến!


2
Điều này thật tuyệt, +1. Mặc dù, vì bạn đang dán nhãn rõ ràng cho các đối số, nên không có tiết kiệm byte giữa pryr::f()function(). Tuy nhiên, sau một số thử nghiệm, bạn có thể di chuyển vukhai báo vào thân hàm trong khi duy trì thứ tự các đối số, để lưu hàng tá byte: Hãy thử trực tuyến!
Giuseppe

vkhông nhất thiết phải lấy các giá trị nguyên v>=30, mặc dù vậy , bạn cần
Giuseppe

@Giuseppe Cảm ơn, những cải tiến đó thật tuyệt vời. Vì một số lý do, tôi đã không cân nhắc việc không dán nhãn rõ ràng cho các đối số ...
rturnbull

4

Sạch , 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)

Hãy thử trực tuyến!

Xác định hàm $ :: Real Real Real Real Real Int -> [Real], thực hiện thuật toán như được mô tả trong OP, bắt đầu từ số hạng 0.


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

Hãy thử trực tuyến!

Đã lưu 2 byte nhờ user71546 .


@ovs Rất tiếc, bạn đã đúng. Nên sửa ngay.
Ông Xcoder

Chuyển 0.04*v*vsang v*v/25.nên tiết kiệm 1 byte. Nếu các float luôn được đưa ra cthì v*v/25đủ cho -2 byte.
Shieru Asakoto

@ceilingcat Nếu bạn xem lịch sử sửa đổi của tôi, bạn sẽ nhận thấy rằng tôi đã có v>29trong phiên bản ban đầu của mình. Tuy nhiên, đó là becuause không hợp lệ vkhông nhất thiết phải là số nguyên.
Ông Xcoder

3

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

Được đóng góp bởi @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))

Hãy thử trực tuyến!

Cách tiếp cận gốc: 105 103 byte. -1 byte Cảm ơn Arnauld và -2 byte Cảm ơn @ 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)}}

Hãy thử trực tuyến!

Hoặc nếu cảnh báo popping là OK, thì 101 ... 99 97 byte (-1 byte Cảm ơn Arnauld, -2 byte Cảm ơn @ 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>29không tương đương v>=30với phao. Bạn có thể muốn làm v<30?0:(v=c,u+=d)thay thế, hoặc tốt hơn là v<30||(v=c,u+=d)tiết kiệm một byte.
Arnauld

@Arnauld Ồ vâng, khi tôi nhìn vào câu trả lời của Python, tôi nhận ra rằng tôi đã không tối ưu hóa điều đó nhưng tôi cũng không nhận ra rằng mình đang xử lý các float .; P Đã sửa.
Shieru Asakoto

2
Bạn có thể lưu hai byte bằng cách thay đổi t-->0thành đơn giản t--.
kamoroso94

1
Bạn có thể giảm xuống 101 bằng cách tái cấu trúc forvòng lặp thành một mapthao tác trên một mảng có độ dài 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)). Hàm trả về một mảng thay vì các giá trị ghi nhật ký, xuất hiện để đáp ứng đặc tả. Không đánh bại alertgiải pháp, mặc dù.
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}}

Hãy thử trực tuyến!

Một cổng đơn giản khác của việc thực hiện tham chiếu, lambda chấp nhận 6 đối số.


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

Hãy thử trực tuyến!

Không xuất ra trường hợp không. Giả định rằng điều đó csẽ không bao giờ >=30có ý nghĩa.

Không bao giờ nghĩ rằng tôi phải sử dụng một wheremệnh đề trong một mã golf nhưng có quá nhiều biến.

EDIT: Cảm ơn @Lynn vì đã lấy ra một byte! Tôi quên rằng bạn có thể đưa các lettuyên bố trong bảo vệ. Chắc chắn giết chết khả năng đọc


1
Bạn có thể thay thế wherebằng f x|let g a=b=ycú pháp lạ để lưu một 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

Phần tử , 81 byte

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

Hãy thử trực tuyến! , Trang Esolang

Giải trình:

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

Phần này của chương trình có đầu vào. Nó lưu trữ các hằng số a, b, d, và Ivào các biến. Đầu vào cho ckhông bao giờ được lưu trữ trong một biến, nhưng vẫn còn trên ngăn xếp chính trong suốt quá trình thực thi. Ba bản sao được tạo ra: một ở trên cùng để khởi tạo u, một ở giữa để đóng vai trò ban đầu vvà một ở phía dưới để phục vụ như là hằng số c. Đầu vào cho tđược ném ngay lập tức vào ngăn xếp điều khiển để làm cơ sở cho vòng lặp FOR (the [...]) xung quanh phần còn lại của chương trình.

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

Phần này của chương trình lấy giá trị hiện tại vvà tính giá trị mới, và sau đó bốn bản sao của vgiá trị mới được tạo.

\
.`

Bản sao đầu tiên vcó một dòng mới được nối thêm và được in.

30<!

Bản sao thứ hai vđược sử dụng để kiểm tra nếu tế bào thần kinh đã tăng vọt. Kết quả của bài kiểm tra này được đưa vào ngăn xếp điều khiển để sử dụng sau.

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

Phần này tính "delta u", nghĩa là số tiền cần thêm vào u.

[d~+]

Khối IF này dcộng vào tổng trên nếu nơron đang tăng vọt. Điều này kết hợp những gì thường sẽ là hai bài tập thành một bài tập duy nhất.

u;

Điều này lưu trữ giá trị cập nhật của u.

[#2:]

Khối IF này là sự tiếp nối của khối IF ở trên. Nếu nơ-ron đang tăng tốc, hãy xóa giá trị hiện tại của v(hiện nằm trên đỉnh của ngăn xếp chính) và thay thế nó bằng một bản sao c(đã ở dưới cùng của ngăn xếp chính trong toàn bộ thời gian này).

Và đó là cơ bản tất cả là có nó. Một lưu ý nhỏ là điều này làm rò rỉ bộ nhớ: cần thêm một phần "#trong đó để xóa phần trên cùng của ngăn điều khiển (điều kiện IF được đánh giá) sau mỗi lần lặp.

Mặc dù tôi sẽ không gọi Element là ngôn ngữ chơi golf duyên dáng nhất, nhưng thử thách này cho phép tôi thể hiện một tính năng thú vị: do sự phân chia giữa ngăn xếp chính và ngăn điều khiển, tôi có thể lấy một câu lệnh IF và chia điều kiện và cơ thể thành nhiều phần các bộ phận, xen kẽ với mã vô điều kiện.


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

Thực hiện khá đơn giản, có lẽ có thể được cải thiện hơn nữa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.