จำลองเซลล์ประสาทจำลอง


16

Izhikevich เซลล์ประสาทจะง่ายยังรูปแบบค่อนข้างมีประสิทธิภาพของเซลล์ประสาทชีววิทยาที่ออกแบบมาสำหรับการใช้งานในแบบจำลองเวลาก้าวต่อเนื่อง ในการแข่งขันกอล์ฟนี้คุณจะต้องใช้โมเดลนี้

พารามิเตอร์

โมเดลนี้มีเพียง 7 ตัวแปรที่จัดเป็นสมการเชิงอนุพันธ์ 2 แบบเมื่อเทียบกับพารามิเตอร์หลายสิบตัวของแบบจำลองทางกายภาพที่แม่นยำ

  • vและuเป็นตัวแปรสถานะสองอย่างของเซลล์ประสาท นี่vคือตัวแปร "เร็ว" ที่แสดงถึงศักยภาพของเซลล์เมื่อเวลาผ่านไปและuเป็นตัวแปร "ช้า" ที่แสดงถึงคุณสมบัติของเมมเบรนบางอย่าง vตัวแปรหนึ่งที่สำคัญที่สุดเช่นนี้เป็นผลลัพธ์ของการจำลอง
  • a, b, cและdได้รับการแก้ไขค่าคงที่อธิบายคุณสมบัติของเซลล์ประสาท เซลล์ประสาทประเภทต่าง ๆ มีค่าคงที่ต่างกันขึ้นอยู่กับพฤติกรรมที่ต้องการ ยวดcเป็นศักยภาพการรีเซ็ตซึ่งเป็นศักยภาพเยื่อหุ้มเซลล์กลับไปหลังจาก spiking
  • Iแสดงถึงกระแสไฟฟ้าที่ป้อนเข้าสู่เซลล์ประสาท ในการจำลองเครือข่ายสิ่งนี้จะเปลี่ยนแปลงตลอดเวลา แต่สำหรับวัตถุประสงค์ของเราเราจะถือว่าIเป็นค่าคงที่ที่แน่นอน

นางแบบ

รุ่นนี้มีรหัสเทียมที่ง่ายมาก อันดับแรกเรารับค่าคงที่abcdและใช้เพื่อเริ่มต้นvและu:

v = c
u = b * c

ต่อไปเราวนซ้ำรหัสจำลองหลาย ๆ ครั้งตามที่ต้องการ การวนซ้ำแต่ละครั้งแสดงเวลา 1 มิลลิวินาที

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

การใช้งานจริงบางอย่างรวมถึงขั้นตอนเพิ่มเติมสำหรับความแม่นยำเชิงตัวเลข แต่เราไม่ได้รวมสิ่งเหล่านี้ไว้ที่นี่

อินพุต

เป็น input / โปรแกรมการทำงานของคุณควรจะใช้ค่าของa, b, c, d, Iและt(จำนวนของขั้นตอนเวลาในการจำลอง) เมื่อตั้งค่าแล้วจะไม่มีการเปลี่ยนแปลงพารามิเตอร์เหล่านี้ในระหว่างการจำลองอย่างง่ายของเรา ลำดับของอินพุตไม่สำคัญ: คุณสามารถระบุลำดับที่โปรแกรมของคุณใช้พารามิเตอร์เหล่านี้

เอาท์พุต

ผลลัพธ์จะเป็นรายการตัวเลขที่แสดงถึงศักยภาพของเซลล์เยื่อหุ้มเซลล์ (ที่กำหนดโดยตัวแปรv) ตลอดระยะเวลาของการจำลอง รายการสามารถอยู่ในรูปแบบที่เหมาะสม

คุณมีตัวเลือกว่าจะรวมค่าที่ 0 ของการจำลอง (การกำหนดค่าเริ่มต้นก่อนเวลาใดก็ได้) ในผลลัพธ์ของคุณ ตัวอย่างเช่นสำหรับอินพุตของ0.02 0.2 -50 2 10 6(สำหรับa b c d I t) เอาต์พุตของทั้งคู่

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

หรือ

-40
-16.04
73.876224
-42.667044096
-25.8262335380956
29.0355029192068

เป็นที่ยอมรับ

ค่าของคุณไม่จำเป็นต้องเหมือนกับที่กล่าวมาข้างต้นขึ้นอยู่กับว่าภาษาของคุณจัดการกับลอย

การดำเนินการอ้างอิง

นี่คือการใช้งาน TIO ที่ฉันเขียนใน Perl เพื่อสาธิตโมเดล พารามิเตอร์นั้นเป็นของเซลล์ประสาท "พูดพล่อย" จากกระดาษที่เชื่อมโยงด้านบนและสิ่งนี้ทำหน้าที่เป็นการสาธิตว่ารุ่นนี้สามารถสร้างคุณสมบัติที่ซับซ้อนมากขึ้นของเซลล์ประสาทได้อย่างไรเช่นการสลับระหว่างสถานะของกิจกรรมระดับสูงและระดับต่ำ หากคุณดูที่เอาต์พุตคุณสามารถดูว่าเซลล์ประสาทใดที่ spikes ทันทีหลาย ๆ ครั้ง แต่จากนั้นรอสักครู่ก่อนที่จะ spiking หลาย ๆ ครั้ง (แม้ว่าแรงดันอินพุตของเซลล์Iจะคงที่ตลอดเวลา)


จะtเป็นลบหรือไม่?
kamoroso94

1
@ kamoroso94 ไม่คุณไม่สามารถจำลองเวลาเชิงลบได้
PhiNotPi

คำตอบ:


6

R , 110 99 ไบต์

ฟังก์ชันไม่ระบุชื่อที่รับ 6 อาร์กิวเมนต์ ไม่มีอะไรแฟนซีเพียงแค่พอร์ตที่ตรงไปตรงมาของการดำเนินการอ้างอิง อัพเดตของu, vและการพิมพ์ของvทั้งหมดได้รับการรวมกันเป็นเส้นเดียวขอบคุณความจริงที่ว่าอาร์เอสprintจะส่งกลับค่าที่มีการพิมพ์เพื่อให้คุณสามารถใช้มันในการกำหนด ขอขอบคุณ Giuseppe ที่ช่วยประหยัด 11 ไบต์!

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

ลองออนไลน์!


2
นี่ยอดเยี่ยม +1 แม้ว่าตั้งแต่คุณแปะขัดแย้งอย่างชัดเจนไม่มีการประหยัดระหว่างไบต์และpryr::f() function()อย่างไรก็ตามคุณสามารถย้ายvและuประกาศไปยังเนื้อหาของฟังก์ชั่นในขณะที่รักษาลำดับของการขัดแย้งเพื่อบันทึกไบต์จำนวนหนึ่ง: ลองออนไลน์!
Giuseppe

เนื่องจากvไม่จำเป็นต้องใช้ค่าจำนวนเต็มคุณจะต้องv>=30แม้ว่า
จูเซปเป้

@Giuseppe ขอบคุณการปรับปรุงเหล่านั้นยอดเยี่ยม ด้วยเหตุผลบางอย่างฉันไม่ได้พิจารณาไม่ติดป้ายข้อโต้แย้งอย่างชัดเจน ...
rturnbull

4

ทำความสะอาด , 150 145 140 138 ไบต์

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)

ลองออนไลน์!

กำหนดฟังก์ชัน$ :: Real Real Real Real Real Int -> [Real]โดยใช้อัลกอริทึมตามที่อธิบายไว้ใน OP โดยเริ่มจากคำที่ 0


3

Python 2 , 100 ไบต์

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

ลองออนไลน์!

ที่บันทึกไว้ 2 ไบต์ขอบคุณที่user71546


@ โอ๊ะโอคุณพูดถูก ควรได้รับการแก้ไขแล้ว
Mr. Xcoder

การหัน0.04*v*vไปv*v/25.ควรบันทึก 1 ไบต์ ถ้าลอยจะได้รับเสมอสำหรับcแล้วv*v/25พอเพียงสำหรับ -2 ไบต์
Shieru Asakoto

@ceilingcat หากคุณดูประวัติการแก้ไขของฉันคุณจะสังเกตเห็นว่าฉันมีv>29ในรุ่นเริ่มต้นของฉัน อย่างไรก็ตามนั่นไม่ถูกต้องเพราะvไม่จำเป็นต้องเป็นจำนวนเต็ม
Mr. Xcoder

3

JavaScript (Node.js) , 107 ... 103 101 ไบต์

เขียนโดย @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))

ลองออนไลน์!

วิธีการดั้งเดิม: 105 103 ไบต์ -1 ไบต์ขอบคุณ Arnauld และ -2 ไบต์ขอบคุณ @ 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)}}

ลองออนไลน์!

หรือถ้า popping การแจ้งเตือนตกลงแล้ว101 ... 99 97 ไบต์ (-1 ไบต์ขอบคุณ Arnauld, -2 ไบต์ขอบคุณ @ 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>29ไม่เท่ากับv>=30ลอย คุณอาจต้องการทำv<30?0:(v=c,u+=d)แทนหรือดีกว่าv<30||(v=c,u+=d)ซึ่งจะช่วยประหยัดไบต์
Arnauld

@Arnauld โอ้ใช่เมื่อฉันดูคำตอบของ Python ฉันรู้ว่าฉันไม่ได้ปรับให้เหมาะสม แต่ฉันก็ไม่ได้ตระหนักว่าฉันกำลังประมวลผลลอยเช่นกัน; P แก้ไข
Shieru Asakoto

2
คุณสามารถบันทึกไบต์ที่สองโดยการเปลี่ยนเพียงแค่t-->0 t--
kamoroso94

1
คุณจะได้รับนี้ลง 101 โดยการ refactoring forห่วงเป็นmapดำเนินการในอาร์เรย์ของความยาว: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))ฟังก์ชั่นจะส่งกลับอาร์เรย์แทนค่าการบันทึกซึ่งดูเหมือนจะเป็นไปตามข้อกำหนด ไม่สามารถalertแก้ปัญหาได้
apsillers

2

Ruby , 94 ไบต์

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

ลองออนไลน์!

อีกพอร์ตตรงไปตรงมาของการดำเนินการอ้างอิงแลมบ์ดายอมรับข้อโต้แย้งที่ 6


2

Haskell , 112 111 ไบต์

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

ลองออนไลน์!

ไม่ส่งออกตัวพิมพ์ใหญ่เป็นศูนย์ สันนิษฐานว่าcไม่เป็นเช่นนั้น>=30เพราะมันไม่สมเหตุสมผล

ไม่เคยคิดว่าฉันจะต้องใช้ whereประโยคใน code golf แต่มีตัวแปรมากเกินไป

แก้ไข: ขอบคุณ @Lynn สำหรับการปิดไบต์! ฉันลืมว่าคุณสามารถใส่letข้อความลงในการ์ดได้ แน่นอนว่าฆ่าอ่านได้ว่า


1
คุณสามารถแทนที่whereด้วยf x|let g a=b=yไวยากรณ์แปลก ๆเพื่อบันทึกไบต์:(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))
ลินน์

1

องค์ประกอบ , 81 ไบต์

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

ลองออนไลน์! , หน้า Esolangs

คำอธิบาย:

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

ส่วนนี้ของโปรแกรมรับอินพุต มันเก็บค่าคงที่a, b, dและIเข้าไปในตัวแปร อินพุตสำหรับcจะไม่ถูกเก็บไว้ในตัวแปร แต่จะยังคงอยู่ในสแต็กหลักตลอดการดำเนินการ สามฉบับจะทำ: หนึ่งอยู่ด้านบนสำหรับการเริ่มต้นuหนึ่งที่อยู่ตรงกลางเพื่อใช้เป็นครั้งแรกและหนึ่งที่ด้านล่างเพื่อทำหน้าที่เป็นอย่างต่อเนื่องv cอินพุตสำหรับtจะถูกโยนลงในสแต็กควบคุมทันทีเพื่อทำหน้าที่เป็นพื้นฐานของการวนรอบ FOR (( [...])) รอบส่วนที่เหลือของโปรแกรม

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

ส่วนนี้ของโปรแกรมใช้ค่าปัจจุบันของvและคำนวณค่าใหม่จากนั้นทำการคัดลอกvค่าใหม่สี่ชุด

\
.`

สำเนาแรกของvมีการขึ้นบรรทัดใหม่ต่อท้ายและถูกพิมพ์

30<!

สำเนาที่สองvถูกใช้เพื่อทดสอบว่าเซลล์ประสาทได้ถูกแทงหรือไม่ ผลลัพธ์ของการทดสอบนี้จะถูกวางไว้บนกองควบคุมเพื่อใช้ในภายหลัง

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

ส่วนนี้คำนวณ "เดลต้าu" ซึ่งหมายถึงจำนวนเงินที่จะเพิ่มuหมายถึงจำนวนเงินที่จะเพิ่ม

[d~+]

ถ้าบล็อกนี้เพิ่ม dไปยังผลรวมข้างต้นถ้าเซลล์ประสาทนั้น spiking สิ่งนี้จะรวมสิ่งที่ปกติจะเป็นสองการมอบหมายเข้าในการมอบหมายเดี่ยว

u;

สิ่งนี้จะเก็บค่าที่อัพเดตของ uนี้จะจัดเก็บค่าปรับปรุงของ

[#2:]

บล็อก IF นี้คือความต่อเนื่องของบล็อก IF ด้านบน ถ้าเซลล์ประสาทหมุนเร็วให้ลบค่าปัจจุบันของv (ซึ่งตอนนี้อยู่ด้านบนสุดของสแต็กหลัก) และแทนที่ด้วยซ้ำc(ซึ่งอยู่ที่ด้านล่างของสแต็กหลักตลอดเวลา)

และนั่นคือทั้งหมดที่มีให้ โน้ตเล็กน้อยหนึ่งคือสิ่งนี้รั่วหน่วยความจำ: ใช้เวลาพิเศษ"#ในการลบส่วนบนของกองควบคุม (เงื่อนไข IF ที่ประเมิน) หลังจากวนซ้ำแต่ละรอบ

แม้ว่าฉันจะไม่เรียก Element ว่าภาษากอล์ฟที่งดงามที่สุด แต่ความท้าทายนี้ทำให้ฉันสามารถแสดงคุณสมบัติที่น่าสนใจ: เนื่องจากการแบ่งระหว่างสแต็คหลักและสแต็คควบคุมฉันสามารถใช้คำสั่ง IF และแยกสภาพและร่างกายเป็นหลาย ๆ ส่วน interlaced ด้วยรหัสที่ไม่มีเงื่อนไข


0

MATLAB, 111 ไบต์

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

การใช้งานที่เรียบง่ายค่อนข้างน่าจะดีขึ้นอีก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.