อยากรู้พื้นฐาน Quantum Computing? งั้นก็ลองสร้างมันขึ้นมาสิ!
มาทำความรู้จักกับ Quantum Circuit ผ่านการสร้าง Quantum Circuit Simulator ในภาษา JavaScript รับรองได้เลยว่า ปัง!
Last updated
Was this helpful?
มาทำความรู้จักกับ Quantum Circuit ผ่านการสร้าง Quantum Circuit Simulator ในภาษา JavaScript รับรองได้เลยว่า ปัง!
Last updated
Was this helpful?
สวัสดีท่านผู้เจริญซึ่งมากไปด้วยปัญญาที่อยากจะมาสัมผัสว่า Quantum Computing เนี่ยมันเป็นยังไง ในบทความนี้เราจะพาทุกท่านมาลองเขียน Quantum Circuit Simulator กัน พร้อมกับอธิบายคณิตศาสตร์คร่าวๆ ไปด้วย (ตามสไตล์ Developer/Engineer) ทั้งนี้ทั้งนั้น ตัว math เองอาจจะ simplified ไปสักหน่อย ในตอนจบบทความนี้เราเลยรวบรวมเว็บและแหล่งข้อมูลอื่นๆ ไว้ให้สำหรับคนที่อยากอ่านหรือศึกษาต่อได้ไปเรียนรู้กัน
ไม่รอช้า ไปเริ่มกันเลย!
จ๊ะเอ๋ ตัวเอง! ถ้ายังไม่รู้ว่าจริงๆ แล้ว Quantum Computing มันคืออะไรกันแน่ ทำไมต้อง Quantum นะ? เรียนเชิญไปอ่านบทความที่เขียนไว้คร่าวๆ ด้านล่างก่อนเลยจ้า 👇
บทความนี้ ประกอบไปด้วยคณิตศาสตร์และภาษา JavaScript ซึ่งจริงๆ แล้วคนอ่านไม่จำเป็นจะต้องรู้ทั้งสองอย่างก็ได้ อ่านไปเพลินๆ แต่ถ้าอยากทำความเข้าใจกับคณิตศาสตร์ให้มากขึ้น หรืออยากเขียนโค้ดตามไปด้วย แนะนำว่าถ้ามีพื้นฐานเหล่านี้ก่อนอ่านสักหน่อยจะดีมาก:
JavaScript: รู้จัก Array Method (filter
, map
, reduce
, etc.) รู้จักการ Spread รู้จัก Higher-order Function รู้ว่าการ Currying คืออะไร
Linear Algebra: ถ้าฟังภาษาอังกฤษได้แนะนำซีรีส์ Essence of linear algebra ของ 3Blue1Brown (https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)
Complex Number: มาทบทวนเนื้อหา ม.5 กันค่ะ http://www.tewlek.com/anet_complex.html
ปกติเวลาเราเขียนโปรแกรม เราก็เขียนโค้ดถูกมะ แต่ในควอนตัมคอมพิวเตอร์อ่ะ เราจะเขียนสิ่งที่เรียกว่า "Quantum Circuit" เข้าไป ถ้าจะให้เปรียบเทียบง่ายๆ ก็เหมืนกับการที่เราใส่ Logic Gate ลงไปในวงจร Digital เพื่อให้ได้ Output ตามที่เราต้องการ Quantum Computer ก็คือเป็นแบบนั้นเลย
แน่นอนว่า ใน Circuit เองก็ต้องมีส่วนประกอบที่น่าจะคุ้นเคยกัน 2 อย่าง นั่นก็คือ
Registers: ถ้าพูดกันแบบ Digital Circuit ก็จะหมายถึงหน่วยความจำอะไรกันแบบนี้ใช่ไหม แต่ถ้าเป็น Quantum เราจะพูดถึงกลุ่มของเส้น Qubit หรือ Bit กัน ก็คือเส้นตามแนวนอนที่เห็นกันนั่นเอง โดย q
ย่อมาจาก Quantum Register และ c
มาจากคำว่า Classical Register
Gates: ก็คือสิ่งที่แก้ไขให้ค่าใน Register เปลี่ยนแปลงไป ถ้าใน Digital Circuit เราก็อาจจะคุ้นกับ Logic Gate เช่น AND
, OR
, NOT
, XOR
, etc. ส่วนใน Quantum เราก็จะมี Quantum Gate กันมากมาย เช่น X
, Y
, Z
, Hadamard
, etc. ซึ่งในภาพก็คือสัญลักษณ์ที่วางอยู่บนเส้น Register นั่นเอง
มาถึงตรงนี้หลายๆ คนคงสงสัย "เอ้า ในเมื่อมี Quantum Gate แล้ว ทำไมยังต้องวัดกลับมาอีก? ประมวลผลไปด้วยเครื่องควอนตัมคอมพิวเตอร์เลยไม่ได้หรอ?" คำตอบคือ เราจะใช้เครื่องควอนตัมคอมพิวเตอร์ในการแก้ปัญหาบางปัญหาที่ต้องพึ่งพาคุณสมบัติทางควอนตัมเท่านั้น บางปัญหานั้นก็สามารถทำได้หรือทำได้ดีกว่าด้วยเครื่องคอมพิวเตอร์ธรรมดา (Classical Computer) ที่เราใช้กันอยู่ ดังนั้น เราจึงมักจะทำวงจรควอนตัมมาเพื่อแก้ปัญหาบางอย่างเท่านั้น แล้วเอาข้อมูลที่ได้มาประมวลผลต่อด้วยคอมพิวเตอร์ปกติอีกที
ข้อสังเกตอีกอย่างหนึ่งที่น่าสนใจ คือ Logic Gate ที่อยู่ใน Digital Circuit เนี่ย อาจจะให้ผลลัพธ์ออกมาน้อยกว่าจำนวน Bit ที่เข้าไปก็ได้ ซึ่งใน Quantum เราไม่ทำกันแบบนั้นด้วยเหตุผลง่ายๆ ว่า สสารไม่มีวันสูญหายไป (ซึ่งจริงๆ ถ้าไม่ใช้ต่อก็ไม่ต้องสนใจมันแค่นั้นเอง)
ทั้งหมดที่เล่ามาก็คือ Quantum Circuit แบบคร่าวๆ ว่าคืออะไร และต่อจากนี้เราจะมาเขียนตัว Simulate เจ้านี่กัน ตั้งแต่การตั้ง Qubit การใส่ Gate ต่างๆ และการวัดผลลัพธ์ออกมาเลย
ในช่วงหลังจากนี้ จะมีการสอนทฤษฎีไปพร้อมๆ กับการเขียนโค้ด สำหรับคนที่มาอ่านเพลินๆ หรือมาเรียนเอาทฤษฎี Quantum Computing อย่างเดียว อาจจะเขียนโค้ดไม่เป็นหรือไม่อยากเขียนโค้ด ก็สามารถอ่านไปเพลินๆ โดยไม่ต้องสนใจโค้ดได้เลยจ้า ส่วนใครอยากต่อ Quantum Circuit ไปพร้อมๆ กับบทความ สามารถไปต่อได้ที่ Quirk: Quantum Circuit Simulator (https://algassert.com/quirk)
ก่อนที่จะไปทำ Simulator กันได้ เราต้องมาทบทวนเนื้อหาพื้นฐานกันก่อน
ถ้าเราย้อนกลับไปในวิชาฟิสิกส์ ม.ปลาย เราสามารถเขียนเวกเตอร์อันหนึ่งให้ออกมาในรูปองค์ประกอบของแกนได้ คือ
เจ้าตัว กับ นี่แหละ เขาเรียกว่า Basis
Basis คือเวกเตอร์ 1 หน่วยที่อยู่ในแกนใดแกนหนึ่งก่อนที่จะถูกสเกลด้วยสเกลาร์ ตัวอย่างเช่นสมมติว่าเรามี
เราก็จะสามารถตอบได้ทันทีว่า เป็นเวกเตอร์ที่มีขนาด 3 ในแนวแกน x โดยมี เป็นเวกเตอร์ 1 หน่วยในแนวแกน x ที่ถูกสเกลโดยสเกลาร์ ทำให้มันกลายเป็นเวกเตอร์ขนาด 3 ในแนวแกน x
โดยเราสามารถนำเวกเตอร์ใดเวกเตอร์หนึ่งมาเขียนในรูปของ matrix ได้แบบนี้
ถ้าเราลองกระจาย matrix ออกมา เราจะได้ว่า
ถ้ายังนึกไม่ออก ให้นึงถึงการแตกแรง
แต่! ถ้าเรายังไม่ลืม เราสามารถเขียนเวกเตอร์ในรูปของสเกลาร์คูณกับ Basis รวมกันได้ ซึ่งจะได้ว่า
ก็คือ และ นั่นแหละ
ถ้าเป็นสามมิติก็แค่ขยาย matrix ออกอีก จะได้ว่า , และ นั่นเอง
ใน Quantum Computing, เราจะเขียนแทนสถานะด้วยการใช้ Bra-ket Notation ซึ่งส่วนมากก็เขียนด้วย Ket อย่างเดียวแหละ เช่น ก็อ่านว่า "เค็ต "
การเขียนด้วยสัญลักษณ์ Ket เนี่ยเป็นการเขียนบ่งบอกสถานะของคิวบิตหรือกลุ่มคิวบิต เช่น คือสถานะ 0, คือสถานะ 1 โดยในทาง Quantum Computing ก็มี Basis อยู่ด้วยกัน 2 ตัวคือ กับ เรียกว่า Computational Basis (ใช้ matrix เดียวกับ , ) ดังนั้นเราจึงสามารถเขียนสถานะสถานะหนึ่งทาง Quantum ได้ว่า
เช่น
สถานะทางควอนตัมที่เราใช้โดยทั่วไปเนี่ย ถ้าให้พูดแบบหยาบๆ คือต้อง normalized
สมมติว่ามีสถานะ ตัวที่ยกตัวอย่างไป สถานะดังกล่าวจะต้องมีสมบัติว่า ซึ่งสถานะที่มีสมบัตินี้จะเรียกว่า Pure State ถ้าสถานะนั้นไม่มีสมบัตินี้ จะถือว่าเป็น Mixed State และต้องทำการ normalize ก่อน
เวลาเราหา Absolute ของ Complex Number เช่น สมมติว่าเรามี เราจะได้ว่า
โอเค ตอนนี้เราก็ทบทวนพื้นฐานที่ต้องรู้กันเสร็จแล้ว เราไปเขียนโค้ดเพื่อสร้าง Simulator ของเรากันเลย!
เนื่องจากการทำ Quantum Circuit ต้องใช้การคำนวณ Matrix อย่างมหาศาล และต้องใช้ Complex Number อีกด้วย ดังนั้น เราจะมาใช้ library math.js
กัน
เอาล่ะ ว่าแต่พวกนายอยากจะรันโปรเจกต์แบบไหนกันล่ะ?
1. สร้างไฟล์ index.html
มาก่อน แล้วใส่โค้ดนี้ไป
2. พอเสร็จแล้ว ก็สร้างไฟล์ชื่อ script.js
มาไว้ข้างๆ แล้วลองใส่คำสั่งข้างล่างดู
3. หลังจากนั้น ลองเข้าไฟล์ index.html
แล้วเปิด Developer Console ขึ้นมา (ถ้าใช้ Chrome คำสั่งคือ Ctrl+Shift+J
)
4. ถ้าเห็นข้อความว่า "Hello i
" แสดงว่าถูก ไปต่อได้
หลังจากนี้ ให้แก้ไขโค้ดในไฟล์ script.js
แล้วพอเซฟ ก็ refresh หน้า index.html
ใหม่
หลังจาก setup Project ของเราเสร็จแล้ว ก็ถึงเวลาสร้าง Quantum Circuit Simulator ละ ไปกันต่อเลย!
สำหรับใครที่อยากได้ Source Code ทั้งหมดของบทความนี้ สามารถไปตาม Copy Paste ได้ที่ https://gist.github.com/rootEnginear/642a5bba638a840a01765bd3eed49c7e
ก่อนหน้านี้ เราได้เรียนรู้มาแล้วว่า และ เรามาลองโค้ดสถานะทั้งสองกันเลยดีกว่า
ระวังวิธีการใส่ Matrix ใน Math.js
• math.matrix([[1], [0]])
=
• math.matrix([1, 0])
=
ลอง console.log
ออกมาดูกันว่าจะได้อะไรออกมานะ
เย้ ตอนนี้เราได้ Basis State กันแล้ว ไปต่อกันเลย!
อย่างที่ได้พูดไปแล้วในตอน Quantum Circuit ว่า Gate คือสิ่งที่ทำการเปลี่ยนแปลงสถานะของ Qubit ไป ตอนนี้เรามีสถานะ Qubit แล้ว เรามาทำ Gate เพื่อเปลี่ยนสถานะของมันกัน
โดยเรามาเริ่มจาก Gate พื้นฐานที่สุด ก็คือ gate โดย gate มี matrix คือ
อีก Gate ที่เป็นพื้นฐานก็คือ gate โดยมี matrix คือ
โดยวิธีการเอา Gate พวกนี้มาเปลี่ยนสถานะ Qubit คือให้เรานำ gate เหล่านี้ มาคูณกับสถานะที่เรามี เช่น ถ้าเราต้องการเอา gate มาเปลี่ยนสถานะ เราก็จะได้ว่า
ซึ่งก็ถูกต้อง เพราะถ้าใครจำหน้าตาของ Matrix ได้ มันคือ Identity Matrix ที่คูณกับอะไรก็ได้ตัวเดิม
คราวนี้ถ้าสมมติเราจะทำสองครั้ง เช่น เอา gate มาเปลี่ยนสถานะ แล้วนำผลลัพธ์ไปทำกับ gate อีกเราก็จะได้ว่า
ซึ่งก็ถูกต้อง เพราะ gate จะทำตัวคล้ายๆ กับ NOT
gate คือเปลี่ยน 0 เป็น 1 เปลี่ยน 1 เป็น 0
เราสามารถสังเกตได้ว่า เวลาเราทำการคูณ เราจะเรียงลำดับจากขวาไปซ้าย แต่เวลาเราเขียนวงจรควอนตัม เราจะเขียนจากซ้ายไปขวา
เรามาลอง implement ใน simulator ของเรากันดีกว่า ก่อนอื่นเราจะทำ wrapper function มาคอยรับส่งสถานะของเราก่อน แล้วก็ห่อ gate matrix ของเราไว้
Matrix ที่เก็บค่าสถานะของ Qubit จะเรียกว่า State Vector
หลังจากนั้น เราจะทำฟังก์ชันอีกอันมาใช้รันวงจรของเรา
ลองเอามาใช้รันวงจรเมื่อสักครู่กันเลย ว่าให้ผลลัพธ์ถูกไหม
สุดยอด ตอนนี้เราได้ Gate มาแล้ว 2 ตัวโดยการใช้ Matrix เราลองไปดู Gate อื่นๆ กันต่อเลย!
Quantum Gate ทุกตัวสามารถสร้างได้จาก Universal Gate ที่มีสมการว่า
ตัวอย่างเช่น gate ซึ่งสามารถเขียนได้ว่า
มาลองโค้ดกัน เนื่องจากเราขี้เกียจที่จะมาเขียนฟังก์ชันอะไรยุ่งยาก เราให้ math.js
parse จาก string เอาจะง่ายกว่า
อีก Gate นึงที่เราจะมาทำกันก็คือ Hadamard Gate หรือเรียกกันสั้นๆ ว่า gate
Hadamard Gate เป็นสิ่งที่น่าตื่นตาตื่นใจมาก เพราะมันจะทำให้สถานะ กลายเป็น หรือก็คือสิ่งที่เรียกว่า Superposition ที่เราพูดถึงกันนั่นเอง (เห็นใช่มะว่ามันเป็นได้ทั้ง 0 และ 1 ในเวลาเดียวกัน) ซึ่งวงจรส่วนใหญ่ก็ใช้ประโยชน์จากตรงนี้นี่แหละที่ทำให้เกิดเรื่องของ Quantum Advantage ขึ้น
เรามาลองทดสอบ Gate ทั้งสองอันที่สร้างขึ้นมาดีกว่า โดยปกติแล้ว gate จะไม่ได้ทำอะไรกับ แต่เราจะใช้สมบัติอันนึง คือ มาตรวจกัน
เราอาจจะพบว่า ที่เราทำจะได้ผลลัพธ์แปลกๆ ออกมา ([[2.220446049250313e-16 + 1.224646799147353e-16i], [1 - 1.2246467991473532e-16i]]
) ซึ่งตรงนี้เกิดจากการคำนวณแล้วมันคลาดเคลื่อน ถ้าเราดูดีๆ e-16
นี่เรียกว่าเหยียบ 0 ได้เลย ดังนั้นคำตอบแบบปัดๆ ก็คือ [[0], [1]]
() นั่นแหละ
เจ๋งมาก! เราไปดูกันต่อในส่วนที่สำคัญอีกส่วนหนึ่งของวงจร Quantum กันเลยดีกว่า นั่นก็คือ...
หลังจากที่เราทำการสร้าง Qubit แล้วก็จับมันเปลี่ยนค่าไปเปลี่ยนค่ามาแล้ว เรามาทำการวัดมันดีกว่า
การวัดสถานะหรือ Measurement คือการที่เราเอาสถานะทาง Quantum มาดูว่ามันอยู่สถานะอะไร แต่สิ่งที่จะเกิดขึ้นเมื่อเราทำการวัดมันคือ สถานะมันจะ collapse ลงเป็นสถานะ หรือ เท่านั้น ต่อให้มันอยู่ในสถานะ Superposition มันก็จะโดนบังคับให้เลือกว่ามันจะเป็น หรือ
แต่... ถึงแม้ว่ามันจะโดนบังคับให้เลือกเป็น หรือ แต่สิ่งหนึ่งที่เราสามารถทำได้ ก็คือ ดูว่ามันมีโอกาสในการได้ค่า หรือ เท่าไร ซึ่งวิธีการที่ง่ายที่สุดก็คือเอาสถานะที่อยากรู้มา absolute แล้วยกกำลัง 2 เช่น
สมมติว่ามีสถานะทางควอนตัม เราสามารถรู้ได้ว่า
วิธีการจริงๆ ของมัน คือเอา project เข้า Computational Basis (Inner Product) แล้วคำนวณหาค่าที่อยู่ในโดเมน ออกมา
ความสำคัญของค่าความน่าจะเป็นพวกนี้ คือ ถ้าเรารันวงจรเดิมๆ ซ้ำๆ หลายๆ ครั้ง ผลลัพธ์ที่ได้จะออกมาในสัดส่วนที่ใกล้เคียงกับความน่าจะเป็นที่คำนวณได้ เช่น เรามีสถานะ ซึ่งเมื่อวัดแล้วจะได้ และ แปลว่าถ้ารันวงจร สัก 1000 ครั้ง โอกาสที่จะวัดค่า Qubit แล้วได้ ก็จะมีประมาณ 500 ครั้ง และก็วัดได้ อีกสักประมาณ 500 ครั้ง ประมาณนะ อาจจะได้น้อยกว่ามากกว่าหน่อยๆ แต่รวมๆ แล้วสัดส่วนจะอยู่แถวๆ 50/50 แหละ
ถ้าเราเอาวิธีการคำนวณความน่าจะเป็นดังกล่าว มาคูณจำนวนรอบที่จะทำ เราก็จะได้ค่าแบบตรงเป๊ะๆ มาเลย ซึ่งแน่นอนว่าผลลัพธ์มัน too perfect ไปไม่เหมือนเครื่องควอนตัมคอมพิวเตอร์จริงๆ ที่มี uncertainty และปัจจัยหลายๆ อย่าง อีกทั้งวิธีดังกล่าวจะสามารถใช้วัดวงจรตอนได้แค่ตอนท้ายเท่านั้น ซึ่งจะมีปัญหากับวงจรหลายๆ Qubit เพราะอาจจะวัดแต่ละ Qubit ไม่พร้อมกันก็ได้ ดังนั้นเราจึงไม่สามารถใช้วิธีที่ obvious แบบนี้ได้
โอเค แล้วเราจะ implement ตัว Measurement ของเรายังไงถ้าไม่ใช้วิธีการนี้?
เราก็เขียนฟังก์ชันการ measure ด้วยการจำลองการ collapse ของสถานะเลยยังไงล่ะ!
ขั้นตอนการทำคำสั่ง measurement แบบนี้มีอยู่ 3 ขั้นตอน
คำนวณว่าความน่าจะเป็นของแต่ละสถานะมีค่าเท่าไรด้วยสูตรที่สอนไปแล้ว
เอาความน่าจะเป็นมาสุ่มจริงๆ ด้วย Math.random()
เพื่อ simulate uncertainty ด้วยวิธีนี้เราจะได้สถานะที่ Win มา
ทำให้สถานะอื่นที่ไม่ Win กลายเป็น 0 โดยการทำ Post-selecting ซึ่งการ post-selecting นี้จะทำให้ State Vector ไม่ normalized
ทำการ Normalize State
โอเค เรามาเริ่ม implement ฟังก์ชันต่างๆ กัน
วิธีการ normalize State เราสามารถทำได้โดยการนำสถานะนั้น (เช่น ) มาหารด้วย square root ของ norm ของสถานะนั้น คือ
การ Post-selecting คือการเลือกเฉพาะ State ที่เราอยากได้ แล้วโยน State ที่เหลือทิ้ง วิธีการนี้อย่างที่บอกไปแล้วว่ามันจะทำให้ State ไม่ Normalized เนื่องจากเวลาเราโยนบาง State ทิ้งแล้ว จะทำให้ความน่าจะเป็นรวมกันแล้วไม่ได้ 1 โดยการ Post-select ก็มี 2 แบบ คือ เลือก กับเลือก
ตอนนี้เราเตรียมฟังก์ชันสำหรับการ Normalize State กับ Post-selecting ไว้แล้ว เรามา implement ฟังก์ชันสำหรับการทำ Measurement กัน
โอเค ขั้นตอนแรก เราต้องทำการคำนวณความน่าจะเป็นออกมาก่อน แต่ก่อนที่เราจะทำได้ เราต้องนึกถึงเวลาที่มีหลาย Qubit อยู่ด้วย เอาเป็นว่าในตอนนี้แบบคร่าวๆ คือ เวลาเรามีหลาย Qubit ใน Quantum Circuit, State Vector ก็จะแสดงสถานะของทุก state ออกมาเลย แบบนี้
เวลาทำการ Measurement เราจะต้องเลือกวัด qubit ตัวใดตัวหนึ่ง ในกรณีนี้ ถ้าเราเลือกที่จะวัด ความน่าจะเป็นของมันคือ
จะเห็นว่า การที่เราจะหาว่าความน่าจะเป็นของการวัด แล้วจะได้ เนี่ย เราต้องเอาความน่าจะเป็นของ กับ มารวมกัน เพราะทั้งสองตัวมี เหมือนกัน (สำหรับวัดแล้วได้ 1 ก็ใช้วิธีเดียวกัน)
แน่นอนว่าถ้าเราวัดที่ ก็จะได้เป็น
น่าจะพอเห็นภาพเนอะ กลับไปที่ฟังก์ชันของเรา
ในการหาความน่าจะเป็นแบบนี้ เราจะเอา State Vector มาเลือกเฉพาะตัวที่มี (เมื่อ คือ Qubit ที่จะวัด) เป็น เท่านั้น แล้วคิดความน่าจะเป็นออกมาตามสูตร
ถึงพาร์ทที่น่าสนุกของเราแล้ว โดยในพาร์ทนี้เราจะเอาความน่าจะเป็นในรอบที่แล้วมาเป็นตัวเลือกว่าจะโดน Post-selecting แบบไหน โดยเราจะทำการ
สร้าง Array ตามจำนวน qubit ขึ้นมาก่อน แล้วเติมทั้งหมดด้วย gate
เปลี่ยนค่าที่ เป็น Post-selecting หรือ ตามผลการสุ่ม
เอา Array มาสร้าง Matrix เพื่อ post-selecting State Vector โดยใช้ Tensor Product (ซึ่งจะอธิบายในอนาคตตอนเราขยายวงจรเป็นหลาย qubit กัน 😉)
เราจะได้ implementation ดังนี้
อันนี้ก็ตรงไปตรงมาตามชื่อเลยเพราะเราทำฟังก์ชันไว้แล้ว
เสร็จสักที มาลองกันเลยว่าจะปังหรือพัง โดยเราจะรันวงจร สัก 10 ทีว่าจะได้ผลลัพธ์ออกมายังไง
ลองกดเล่นแล้วกด Rerun ดูว่าได้ผลลัพธ์ออกมายังไงบ้าง จากทฤษฎีก็ควรจะได้ 50/50 ระหว่าง กับ เนอะ
ไปต่อกันค่ะ
อย่างที่บอกไปในส่วนที่แล้ว เวลาเรารัน Quantum Circuit เราก็ต้องรันวงจรเดิมซ้ำๆ ไปหลายๆ รอบ เพื่อให้เรามั่นใจได้ว่าผลลัพธ์ของเราจะถูกต้องหรือมีความน่าจะเป็นตามทฤษฎีจริงๆ ในส่วนนี้ เราจะมาเขียนฟังก์ชันที่ทำให้ชีวิตเราง่ายขึ้นกัน
อย่างแรก เราจะเขียนฟังก์ชันที่เอาไว้รันซ้ำๆ ตามจำนวนที่เราต้องการ แล้วคืนค่าผลลัพธ์ใส่ Array มาให้เรา
ไหนลอง
อลังการ แต่แอบอ่านยากนะ เรามาเขียนฟังก์ชันที่รวบรวมข้อมูลให้เราดีกว่า จะได้เข้าใจง่ายๆ
เสร็จแล้ว เราก็ทำฟังก์ชันที่รันวงจรตามจำนวนที่บอก แล้วก็สรุปผลออกมาให้เราด้วยเลย
ไหนลอง
เก่งมากท่านผู้เจริญที่ผ่านมาถึงจุดนี้ได้ ในตอนนี้เราก็สามารถสร้างสถานะของ Qubit ตัวหนึ่งขึ้นมา ทำการเปลี่ยนแปลงสถานะ แล้ววัดเอาผลลัพธ์ของสถานะนั้นๆ ได้แล้ว หลังจากนี้ เราจำทำการเพิ่มจำนวน Qubit ลงไปใน Simulator ของเรากัน
เดี๋ยวเรามาพักเบรกกันก่อน ระหว่างนี้ เชิญรับชมสิ่งที่น่าสนใจกันก่อนดีกว่า
หลังจากที่เราทำวงจรขนาด 1 qubit กันมาได้แล้ว เรามาลองเพิ่มจำนวน qubit ในระบบกัน โดยวิธีการเพิ่มเข้าไปก็ง่ายมาก คือใช้สิ่งที่เรียกว่า "Tensor Product"
สมมติว่าเรามี matrix และ matrix Tensor Product ของ A และ B ก็คือ
\begin{align*} A\otimes B&=\begin{bmatrix}a_{00}B&a_{01}B\\a_{10}B&a_{11}B\end{bmatrix}\\ &=\begin{bmatrix} a_{00}\begin{bmatrix}b_{00}&b_{01}\\b_{10}&b_{11}\end{bmatrix} &a_{01}\begin{bmatrix}b_{00}&b_{01}\\b_{10}&b_{11}\end{bmatrix} \\ a_{10}\begin{bmatrix}b_{00}&b_{01}\\b_{10}&b_{11}\end{bmatrix} &a_{11}\begin{bmatrix}b_{00}&b_{01}\\b_{10}&b_{11}\end{bmatrix} \end{bmatrix}\\ A\otimes B&=\begin{bmatrix} a_{00}b_{00}&a_{00}b_{01}&a_{01}b_{00}&a_{01}b_{01}\\ a_{00}b_{10}&a_{00}b_{11}&a_{01}b_{10}&a_{01}b_{11}\\ a_{10}b_{00}&a_{10}b_{01}&a_{11}b_{00}&a_{11}b_{01}\\ a_{10}b_{10}&a_{10}b_{11}&a_{11}b_{10}&a_{11}b_{11}\\ \end{bmatrix} \end{align*}
วิธีการจำคือ เอาขวาใส่ซ้าย แล้วก็คูณให้เรียบร้อยก็จะได้ออกมาแล้ว
เราลองเอา Basis State มารวมกันด้วย Tensor Product กันดีกว่า
สังเกตว่าตอนนี้เราได้ Basis States ต่างๆ ของ 2 qubit มาแล้ว ซึ่งเราจะสามาระเอาไปใช้กับวงจรขนาด 2 qubit ได้
คราวนี้เราลองเอา gate มารวมกันดีกว่า เดี๋ยวเรามาดูกันว่า การเอา gate กับ gate มารวมกันจะได้ผลลัพธ์อย่างไรบ้าง และสามารถวาดออกมาเป็น Quantum Circuit ได้อย่างไร
เราจะเห็นว่าในกรณีที่มี Gate อยู่ที่ qubit ใด qubit หนี่ง เราจะต้อง Tensor Product qubit ที่ไม่มีการเปลี่ยนแปลงกับ gate ด้วย เพื่อทำให้ matrix ของเรามีขนาดเท่ากับ State Vector และสามารถทำการคำนวณได้นั่นเอง
มาลองโค้ดกันเถอะ! เดี๋ยวเรามาลองทำวงจร กัน
ตอนนี้เราก็อาจจะรู้แล้วว่าเราสามารถสร้าง Gate ขนาด 2 qubit ได้จากการเอา Gate ขนาด 1 qubit มา Tensor Product กัน ในคราวนี้ เราจะมารู้จักกับ Gate ขนาด 2 qubit ที่ใช้บ่อยๆ กัน
Controlled-not Gate () เป็น Gate ชนิดหนึ่งที่จะประกอบไปด้วยส่วนประกอบสองส่วน คือ
Control คือจุดสีดำ
Target คือเครื่องหมาย
โดยมันจะทำการสลับสถานะ กับ ใน State Vector ที่ถูกทำ
โดย มี matrix คือ
บางครั้งคนก็จะเรียก ว่า Controlled- gate เพราะ implementation ของมันก็คือการเอา gate มาผูกกับ Control นั่นแหละ
เรามาลองทำวงจร... เอ่อ ใช้ภาพละกัน
ก่อนอื่น เราจะต้องสร้าง gate มาก่อน แล้วก็แปะ ต่อ แล้วปิดท้ายด้วยการ Measurement
เนื่องจากตอนเราทำฟังก์ชัน Measurement เราทำให้มันสามารถทำงานแยก Qubit ได้ เราจึงไม่ต้องไป Tensor Product อะไรกับ gate แค่บอก qubit ที่จะวัดก็พอ
สังเกตว่า เราจะได้ผลลัพธ์เป็น หรือ ออกมาประมาณ 50/50 โดยสิ่งที่เราเพิ่งทำไปก็คือการทำ Entanglement ระหว่าง Qubit นั่นเอง
หลายๆ คนอาจจะเคยได้ยินปรากฏการณ์ทางควอนตัมอันหนึ่ง คือ Entanglement ซึ่งหลายๆ คนอาจจะเคยได้ยินมาทำนองว่า "ถ้าเรารู้สถานะของตัวหนึ่ง เราก็จะสามารถรู้สถานะของอีกตัวหนึ่งที่ entangle อยู่ได้" ซึ่ง roughly speaking ก็ถูกนะ
แต่สิ่งหนึ่งที่ทุกคนต้องเข้าใจคือ Entanglement ทำให้เราแค่ "รู้" อีกตัว ไม่ใช่ว่าเปลี่ยนตัวหนึ่งแล้วอีกตัวหนึ่งจะเปลี่ยนตาม ตรงนี้มองว่าคนหลายคนเข้าใจผิดกันไปเยอะมาก คือเราแค่รู้อีกตัวนะ ไม่ใช่ว่ามันจะเปลี่ยนตามกัน
เรามาทดลองกันเพิ่มดีกว่า จะเกิดอะไรขึ้นถ้าเราวัดแค่ ล่ะ?
สังเกตว่าก็จะได้คำตอบเหมือนเดิม คือ หรือ วัดบิตเดียว รู้อีกอัน นี่แหละคือพลังของ Entanglement
เรามาลองดู math เบื้องหลังวงจรนั้นดีกว่า
จากข้างบน เราก็จะเห็นแล้วว่าวงจรมีโอกาสออก หรือ อย่างละ 50/50 โดยถ้าเราทำการวัดที่ เราก็จะได้ว่า
นั่นก็คือ จะทำให้ State หลงเหลือ เมื่อวัด และเหลือแค่ เมื่อวัด
Partial Measurement: เลือก Related State ก่อน (Post-selecting; เลือก State ที่มีตัวบังคับเหมือนกัน) แล้ว Normalization
เราก็จะเห็นแล้วว่า มีความสำคัญต่อวงจรควอนตัมในแง่ที่ว่า จะเป็นตัวสลับสถานะและสามารถทำให้เกิดการ Entanglement กันขึ้นระหว่าง Qubit ได้
เดี๋ยวเรามารู้จัก 2-qubit Gate อีกตัวนึงกันดีกว่า มันคือ
gate เป็น Gate ที่จะสลับ 2 Qubit ที่อยู่ติดกัน มีประโยชน์มากโดยเฉพาะในกรณีที่ต้องการสลับ Control กับ Target ของ gate
โดย gate มี matrix คือ
gate มีสมบัติที่สำคัญ คือ
มาลอง implement gate กัน แล้วทดสอบด้วยวงจร
สังเกตว่าตอนแรกเราสร้างสถานะ พอเราเอาไปผ่าน gate ปุ๊บ สถานะที่ได้ก็จะกลายเป็น เลย ปังสุด
หลายๆ Gate ที่เราเรียนรู้ไป เช่น , , จะสามารถหักล้างตัวเอง (self-inverse) ได้ เช่น
สังเกตว่าลำดับการหักล้างสำคัญ
ตัวที่ไม่ได้หักล้างก็จะเหลือในวงจร
แต่บาง Gate ก็ไม่สามารถหักล้างตัวเองได้ เช่น gate โดย gate มีสมบัติคือ
อย่างที่เห็นคือ มันไม่ได้หักล้างไปเหมือน gate อื่นๆ ในกรณีแบบนี้ เราจะต้องทำสิ่งที่เรียกว่า Conjugate Transpose
การทำ Conjugate Transpose ประกอบไปด้วย 2 ขั้นตอน ก็คือ
Conjugate (สังยุค) ค่าใน matrix
Transpose matrix
การ Conjugate คือการกลับ ในส่วนจินตภาพของจำนวนเชิงซ้อน เช่น สมมติว่าเรามี เราจะได้ว่า conjugate ของ คือ
การทำ Conjugate Transpose ของ Gate นั้น จะเขียนด้วยสัญลักษณ์ Dagger () เช่น Conjugate Transpose ของ gate คือ gate ซึ่งจะได้ว่า
พอเราลองเอา gate มาวางติดกับ gate ดู ก็จะได้ว่า
โชคดีมากที่ math.js
มีฟังก์ชันสำหรับการทำ Conjugate Transpose เรามาลองพิสูจน์กันด้วยวงจรง่ายๆ กัน
เหมือนเดิมเนอะ e-17
ก็คือ 0 แหละ
ตอนนี้เราก็รู้วิธีการทำให้ Gate บางตัวที่ไม่มีสมบัติ self-inverse ให้สามารถ inverse ได้แล้วด้วยการทำ Conjugate Transpose ในส่วนต่อไป เราจะขยับขยายวงจรของเราให้มีจำนวน Qubit มากขึ้น และเรียนรู้วิธีการเพิ่ม Control ให้กับ Gate อะไรก็ได้แบบ unlimited กัน
วิธีการก็ทำเหมือนกับวงจรแบบ 2 qubit เลย ก็แค่เอา qubit หรือ gate มาทำ Tensor Product กัน เรามาลองทำวงจรง่ายๆ ด้านล่างกัน
ง่ายใช่มะ เราสามารถใช้วิธีนี้กับวงจรขนาดกี่ Qubit ก็ได้ แต่ข้อควรระวังก็คือ ขนาดของ matrix จะใหญ่ขึ้นแบบ ดังนั้นระวังคอมไหม้กันด้วยนาจา
ก่อนหน้านี้เราเรียนรู้เกี่ยวกับ Controlled-not Gate ไปแล้ว ซึ่งในความเป็นจริง เราสามารถเพิ่ม Control เข้ากับ Gate อะไรก็ได้ ไม่จำเป็นต้องเป็น gate อย่างเดียว ในส่วนนี้ เราจะมาลองสร้าง Controlled-controlled-not Gate หรือรู้จักกันในชื่อทั่วไปว่า Toffoli Gate () ด้วยวิธีนี้กัน โดยก่อนอื่น เรามาทำกันในทฤษฎีก่อน แล้วค่อยมาโค้ดกัน โดย gate มีหน้าตาและ matrix แบบนี้
โดยอย่างแรกในการสร้าง gate เราต้องมี gate ก่อน
โอเค เสร็จแล้ว เราจะเอา Control ใส่ลงไปด้วยการทำสิ่งที่เรียกว่า Direct Sum
Direct Sum คือการเอา matrix สองตัว มาวางต่อกันในแนวเฉียง ที่เหลือใส่ 0 เช่น สมมติว่าเรามี และ เราจะได้ว่า
แน่นอนว่า Operator นี้ไม่ Communicative นาจา () ยกเว้น
วิธีการก็คือ เราจะเอา (Identity Matrix ขนาด เมื่อ เป็นจำนวน Qubit) มา Direct Sum กับ Gate ที่ต้องการ ในที่นี้คือ gate ซึ่งเราจะได้ว่า
ตอนนี้เราได้ มาแล้ว เราจะเพิ่ม Controlled เข้าไปอีก 1 ตัว
ซึ่งตอนนี้ เราจะได้ gate ของเราออกมาแบบนี้
จะเห็นว่าตอนนี้มันกลับหัวกลับหางกับที่เราอยากได้อยู่ ตรงนี้เราสามารถใช้ gate มาสลับให้ถูก qubit ได้ดังภาพ (ตรงนี้ไม่ขอเขียน math นะ มันเยอะ เดี๋ยวข้ามไป implement เลย)
ก่อนที่เราจะไป implement ตัว gate กัน เราต้องเขียนฟังก์ชันทำ Direct Sum ก่อน
พอเรามีฟังก์ชันไว้ทำ Direct Sum แล้ว ก็มาทำตัว gate กันเลย
เสร็จแล้ว เรามาทำตัวสลับ กับ โดยเราจะต่อ gate หลายๆ ตัว ตามแบบ โดยตรงนี้เราได้เขียนฟังก์ชัน composeGates
ลงไปเพื่อคำนวณ matrix ของหลายๆ Gate รวมกันด้วย
พอได้ครบทุกอย่างแล้ว เราลองมาทดสอบด้วยวงจรข้างล่างกัน โดยผลลัพธ์ที่เป็นไปได้ของวงจรข้างล่างคือ และ
เย้ ในตอนนี้เราก็รู้วิธีการเพิ่ม Control ไปยัง Gate ต่างๆ ที่เราอยากได้แล้ว ปรบมือให้ตัวเองค่ะ 👏👏👏
ก่อนที่จะปิดคอร์ด ก็ขอทิ้งชาเลนจ์เล็กๆ อันนึงไว้ให้ทุกท่านที่อ่านมาจนถึงตรงนี้ นั่นก็คือ ให้ลอง implement วงจรทางด้านล่างดู ลองดูว่าสามารถทำได้แบบไหนบ้าง
ยินดีกับท่านผู้เจริญทุกท่านที่สามารถเรียนรู้และทนอ่านมาได้จนจบบทความนี้ ถึงแม้ว่าในปัจจุบันนี้ควอนตัมคอมพิวเตอร์จะยังดูเป็นเรื่องที่ล้ำเกินยุค หรือค่อนข้างไกลตัวไปสักหน่อย แต่อย่างน้อยทุกท่านที่เข้ามาอ่านก็เปิดใจพร้อมรับสิ่งใหม่ๆ และถึงแม้ว่าจะอ่านแล้วเข้าใจหรือไม่เข้าใจ แค่เปิดใจก็ถือว่าเป็นสิ่งที่ดีแล้ว ขอบคุณทุกท่านมากๆ ค่ะ
ยังไงถ้าใครสนใจที่จะศึกษาเพิ่มเติมเกี่ยวกับ Quantum Computing เราขอแนะนำแหล่งเรียนรู้ดังต่อไปนี้
Xanadu Quantum Codebook (https://codebook.xanadu.ai/)
Qiskit Textbook (https://qiskit.org/textbook/)
Quantum algorithms for data analysis (https://quantumalgorithms.org/) อันนี้ math แน่นมาก
Quantum computing for the determined (https://www.youtube.com/playlist?list=PL1826E60FD05B44E4)
Computer Science courses with video lectures (https://github.com/Developer-Y/cs-video-courses#quantum-computing) อันนี้มีของวิชาอื่นด้วย ไปตำ
Quantumic Math — Are You Ready For The Red Pill? (https://towardsdatascience.com/quantumic-math-are-you-ready-for-the-red-pill-4860f0ad79bf)
มีอีกหรอ เมลมาบอกด้วย!
บอกตามตรงเลยว่า ไม่คิดเลยว่าบทความนี้จะออกมามีเนื้อหาที่เยอะมากขนาดนี้ ตอนแรกก็คือแค่อยากลองเขียน Quantum Circuit Simulator ในภาษา JavaScript เฉยๆ แต่กลับกลายเป็นว่าระหว่างทางที่เราได้ลองทำเนี่ย เราได้อ่าน ค้นคว้า ลองผิดลองถูกจนเข้าใจจนทำออกมาได้ เราก็เลยรู้สึกว่า Hmm... น่าจะเรียบเรียงเนื้อหาพวกนี้มาให้คนอื่นศึกษาได้นะ แต่ถึงจะค้นคว้ามาเยอะแค่ไหนก็เถอะ ถ้าเจอข้อผิดพลาดหรือรู้สึกว่าตรงไหนไม่โอเค oversimplify มากเกินไป ไม่ชัดเจน ไม่เข้าใจ รันไม่ได้ รบกวนรีบ email มาหาเราเลยนะ คนอ่านคนอื่นๆ จะได้ไม่ผิด
ก่อนจะจากลากันไป ขอขอบคุณทุกคนดังต่อไปนี้
พี่กอล์ฟ ที่คอย support ในสิ่งที่อยากทำตลอด คอยไปบ่น ถาม สอน ถกเถียงได้เสมอเลย เป็นคนทำให้มีพลังในการเขียนโปรแกรมกลับมาอีกครั้ง
เพื่อนบอส ที่ถาม math ได้ทุกอย่าง แค่ถามก็รู้คำตอบได้โดยไม่ต้องรอตอบเหมือนโทรจิตกัน
เพื่อนแบงค์ ที่เวลาทักอะไรไปก็ตอบกลับมาว่า "สุดยอดครับ" ตลอด
เพื่อนพีร์ พี่นิติ พี่ลูกคิด และเพื่อนๆ ทุกคนที่ช่วย proofread ก่อนจะโยนบล็อกนี่สู่สายตามหาชน
อาจารย์ทุกท่านผู้สอนวิชา CPE494 Quantum Computing ที่คอยประสิทธิ์ประสาทและทำให้คนที่เรียน Quantum เพื่อความโก้เฉยๆ passionate ในเรื่องแบบนี้ได้
เพื่อนๆ ใน Discord ที่คอยทำให้ background ไม่เงียบ เวลาตอนที่นี่เขียนบล็อกเงียบๆ 55555
ไรเดอร์ Grab, Lineman, Robinhood ทุกๆ ท่านที่จัดหาอาหารมาให้กินตามอยาก
และที่สำคัญ ทุกท่านเลยที่เข้ามาอ่านค่ะ 🎉
ขอให้ทุกคนโชคดีนะคะ แล้วเจอกันค่า 🦄
จากแผนภาพ เราจะเห็นว่าการเขียนวงจรจะเขียนจากซ้ายไปขวา บนลงล่าง โดยเราจะเขียน Quantum Register ไว้ข้างบน แล้วเขียน Classical Register ไว้ด้านล่าง (สังเกตว่า Classical Register จะเป็นเส้นคู่ทั้งหมด) อย่างเส้นที่อยู่บนสุด () ก็คือคิวบิต 0 เส้นล่างสุด () ก็คือบิต 2 แล้วเราจะทำการเปลี่ยนแปลง Qubit ยังไง ก็ใส่ Quantum Gate ทับเส้นไปเลย หลังจากที่เราทำการเปลี่ยนแปลง Qubit แล้ว เราก็จะทำการวัดหรือ Measurement (สัญลักษณ์มิเตอร์ ) qubit ที่เราต้องการไปยัง bit ที่เราต้องการ (โดยทั่วไปก็วัดลงตรงๆ เลย )
เอาเป็นว่า ตอนนี้สรุปได้ว่าที่อุตสาห์ทำมา เวิร์คค่ะ
ข้อควรระวัง: Operator นี้ไม่ Communicative นาจา () ยกเว้น
ถ้าไปเปิดหนังสือฟิสิกส์บางเล่ม อาจจะเจอว่า ซึ่งจริงๆ นี่ก็เป็นรูปหนึ่งของ เช่นกัน ความแตกต่างคือ ใน Tutorial นี้เราจะเรียง Qubit ในสัญลักษณ์ Ket โดยเอา LSB ไว้ทางขวาและเอา MSB ไว้ทางซ้าย พูดง่ายๆ คือ จะอยู่ทางซ้ายสุด และ จะอยู่ทางขวาสุดเสมอ (เหมือนเขียนเลขฐาน 2) เมื่อเราใช้การเรียงลำดับของ Qubit ตามที่บอกแล้ว ก็จะเป็น matrix ตามที่บอกไปเลย ส่วน จะมีวงจรควอนตัมเป็น แทน (คือ qubit 1 จะเป็น Control และ qubit 0 จะเป็น Target)
หลังจากนี้ อาจจะโผล่มาในบทความบ้าง ขอเรียกว่า นะ