คุณรู้หรือไม่ว่าเครื่องอบควอนตัมที่มีชื่อเสียงของ D-Wave ไม่สามารถแม้แต่รันลอจิกเกตพื้นฐานได้ เทคโนโลยีควอนตัมคือสิ่งที่ยิ่งใหญ่ต่อไปในโลกของคอมพิวเตอร์ พวกเขาก้าวหน้ามาก พวกเขาสามารถแก้สมการทางคณิตศาสตร์ได้เร็วกว่าซุปเปอร์คอมพิวเตอร์ที่ดีที่สุดของเรามาก แต่หากไม่มีการสนับสนุน พวกเขาจะไม่สามารถแม้แต่รันลอจิกเกตแบบธรรมดา เช่น เกท AND ได้ แต่ด้วยความมหัศจรรย์ในการเขียนโค้ดเพียงเล็กน้อย เราก็สามารถทำให้สิ่งนี้เกิดขึ้นได้

มีลอจิคัลเกตหลายตัวในการคำนวณแบบคลาสสิก เช่น เกต AND, XOR, OR และ NAND มีวงจรดิจิตอลเช่นวงจรบวกเต็มครึ่ง ในบทความนี้ เราจะแสดงวิธีเขียนโค้ดเกท AND วงจรบวกครึ่ง และวงจรบวกเต็มบนเครื่องอบควอนตัม D-Wave

ประตูและ

มาเริ่มกันที่สิ่งที่ง่ายที่สุดก่อน: ประตู AND ประตู AND จะคืนค่าเป็นจริงหากอินพุตทั้งสองเหมือนกัน และคืนค่าเป็นเท็จหากไม่เหมือนกัน ในตารางความจริงต่อไปนี้ ตัวแปร “a” และ “b” แทนอินพุตทั้งสองของเรา และตัวแปร “p” แทนเอาต์พุต เราจะมีตัวแปรอีกตัวหนึ่งเรียกว่า “v1” ซึ่งเป็นตัวแปรเพิ่มเติมที่จำเป็นสำหรับการคำนวณ

ในเอกสาร D-Wave เรื่อง "การเพิ่มประสิทธิภาพการแยกตัวประกอบจำนวนเต็มผ่านการชดเชยการอบอ่อนด้วยควอนตัม" ผู้เขียนได้อธิบายโครงร่างพื้นฐานสำหรับค่าของ AND gate ในคอมพิวเตอร์ควอนตัม เราจะใช้ไดอะแกรมจากบทความนี้เป็นข้อมูลอ้างอิงสำหรับโค้ดของเรา

รูปภาพด้านบน (รูปที่ 4) แสดงตารางความจริงของเกต AND เช่นเดียวกับแผนภาพที่แสดงค่าของคิวบิต (วงกลม) และการเชื่อมต่อระหว่างสิ่งเหล่านั้น (เส้น) ตามรหัสสีที่แสดง ในการสร้าง BQM เราจะสร้างพจนานุกรมที่เต็มไปด้วยค่า qubit และพจนานุกรมอื่นที่มีค่าการเชื่อมต่อ เราเรียกเทอมเชิงเส้นและกำลังสองเหล่านี้ ตามลำดับ

เราจะใช้แบบจำลองกำลังสองแบบไบนารี (BQM) เพื่อเป็นตัวแทนของเกท AND ซึ่งเป็นโครงสร้างข้อมูลที่สร้างขึ้นสำหรับคอมพิวเตอร์ควอนตัมโดยเฉพาะ เราจะเพิ่มมูลค่าให้กับ qubits ของเรา รวมถึงมูลค่าของการเชื่อมต่อระหว่างพวกเขาด้วย ค่าเหล่านี้สามารถกำหนดได้สองวิธี: QUBO หรือ Ising เอกสาร "การเร่ง" ที่อ้างอิงข้างต้นใช้แบบจำลอง Ising ดังนั้นเราจะใช้แบบจำลอง Ising ใน BQM

หมายเหตุ: โมเดล Ising แสดงถึงเลขฐานสอง เช่น 0 และ 1 เป็น -1 และ 1 ตามลำดับ

ขั้นแรก เรานำเข้าไลบรารี “dimod” ไลบรารีนี้จะอนุญาตให้เราเขียนโค้ดบนเครื่องอบอ่อน D-Wave ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้ง D-Wave Ocean SDK ไม่เช่นนั้นจะไม่ทำงาน อ้างถึงวิดีโอที่เชื่อมโยงสำหรับคำแนะนำในการติดตั้งตามระบบปฏิบัติการของคุณ: Mac OS, Windows หรือ Linux

import dimod

ต่อไป เราสามารถสร้างฟังก์ชันเพื่อแสดงเกต AND ได้ พารามิเตอร์ของเราจะเป็นสองอินพุต (a, b) เอาต์พุต (p) และตัวแปรพิเศษของเรา v1

def and_gate(a, b, p, v1):
     linear = {a: -0.5, b: -0.5, p: 1.0, v1: 0}
     quadratic = {(a, b): 0.5, (a, v1): 1, (b, p): -1, (p, v1): 1}
     return dimod.BinaryQuadraticModel(linear, quadratic, dimod.SPIN)

การใช้รหัสสี (รูปที่ 3) และแผนภาพ (รูปที่ 4) เราสามารถกำหนดค่าของ qubit ของเราในพจนานุกรม "เชิงเส้น" และค่าการเชื่อมต่อ qubit ในพจนานุกรม "กำลังสอง" ต่อไป เราจะส่งคืน BQM โดยใช้เงื่อนไขเชิงเส้นและกำลังสองเหล่านี้ พารามิเตอร์ dimod.SPIN ระบุว่า BQM ของเราจะใช้โมเดล Ising แทนโมเดล QUBO เราใช้ Ising ที่นี่เนื่องจากค่าทั้งหมดใน D-Wave แสดงในรูปแบบ Ising

สุดท้ายนี้เราสามารถเพิ่มโค้ดไดรเวอร์เพื่อทดสอบฟังก์ชันของเราได้

and_bqm = and_gate('a', 'b', 'p', 'v1')
sampler = dimod.ExactSolver()
print(sampler.sample(and_bqm))

ที่นี่ เรากำลังเรียกใช้ฟังก์ชันของเรา จากนั้นเรียกใช้ฟังก์ชันผ่าน ExactSolver ซึ่งเป็นเครื่องอบอ่อนด้วยควอนตัม ExactSolver จะพิมพ์ชุดค่าผสมของอินพุต (a, b) และเอาต์พุตทั้งหมดที่ตรวจดู โดยเรียงลำดับจากน้อยไปหามากตามพลังงาน

    a  b  p v1  energy   num_oc.
1  +1 -1 -1 -1   -2.5       1
5  +1 +1 +1 -1   -2.5       1
12 -1 +1 -1 +1   -2.5       1
14 +1 -1 -1 +1   -2.5       1
15 -1 -1 -1 +1   -2.5       1
2  +1 +1 -1 -1   -0.5       1
4  -1 +1 +1 -1   -0.5       1
6  +1 -1 +1 -1   -0.5       1
11 -1 +1 +1 +1   -0.5       1
13 +1 +1 -1 +1   -0.5       1
0  -1 -1 -1 -1    1.5       1
3  -1 +1 -1 -1    1.5       1
10 +1 +1 +1 +1    1.5       1
7  -1 -1 +1 -1    3.5       1
8  -1 -1 +1 +1    3.5       1
9  +1 -1 +1 +1    3.5       1
['SPIN', 16 rows, 16 samples, 4 variables]

เมื่อเรารันโค้ดแล้ว ผลลัพธ์ของคุณควรมีลักษณะเหมือนภาพด้านบน คอลัมน์แรกแสดงถึงหมายเลขของกรณีทดสอบ คอลัมน์ที่สองและสาม (a, b) เป็นอินพุตที่หนึ่งและที่สองตามลำดับ คอลัมน์ “p” คือเอาต์พุต และ “v1” คือตัวแปรเพิ่มเติม

เมื่อระบบ D-Wave ทำงาน ระบบจะค้นหาคำตอบซึ่งแสดงเป็น BQM ที่นี่ด้วยค่าพลังงานต่ำสุด ในที่นี้ ค่าพลังงานต่ำสุดซึ่งอยู่ในคอลัมน์ที่เรียกว่า “พลังงาน” คือ -2.5 BQM ทั้งหมดที่มีค่า -2.5 แสดงอินพุตที่ถูกต้องซึ่งจับคู่กับเอาต์พุต คอลัมน์ “num_oc” แสดงถึงจำนวนครั้งที่ ExactSolver ตรวจสอบชุดค่าผสม

ในผลลัพธ์ เราจะเห็นว่าค่า Ising ปรากฏในคอลัมน์ a, b และ p เมื่อเปรียบเทียบกับคอลัมน์จากตารางความจริงก่อนหน้า

จากภาพนี้ เราจะเห็นว่าค่า Ising ของเราสอดคล้องกันอย่างถูกต้องกับค่าไบนารี่ที่เกี่ยวข้องในตารางความจริงอย่างไร อย่างไรก็ตาม การรันครั้งที่ 1 และ 14 มีค่า a, b และ p เท่ากัน และทั้งสองค่าจะแสดงด้วยพลังงานต่ำสุด นี่เป็นเพราะการมีตัวแปรพิเศษ v1 และเหตุการณ์นี้จะปรากฏที่ประตูอื่นเมื่อเรารวมตัวแปรพิเศษเช่น v1 ไว้ด้วย สิ่งนี้ไม่ส่งผลกระทบต่อความแม่นยำของแบบจำลองของเรา มันเป็นเพียงผลพลอยได้จากการมีอยู่ของตัวแปร v1

แอดเดอร์ครึ่งและเต็ม

เราสามารถใช้วิธีเดียวกับที่เราใช้กับเกท AND เพื่อเขียนโค้ดวงจรที่มีประโยชน์อื่นๆ อีกสองวงจร: วงจรบวกครึ่งและวงจรบวกเต็ม ตัวบวกครึ่งหนึ่งใช้เลขฐานสองสองตัว แล้วส่งคืนผลรวมและยกยอด ตัวบวกเต็มรับเลขฐานสองสามตัว แล้วส่งคืนผลรวม และดำเนินการตามตัวเลขทั้งสามตัวนี้ นี่คือตาราง:

ตารางเหล่านี้แสดงพฤติกรรมพื้นฐานของวิธีที่วงจรเหล่านี้ตอบสนองต่ออินพุตต่างๆ หากเราย้อนกลับไปดูกระดาษ D-Wave ที่เรามองหาเกต AND แบบจำลอง Ising สำหรับตัวบวกครึ่งตัวจะปรากฏขึ้น

การใช้รหัสสีเดียวกันกับเกต AND (รูปที่ 3) ทำให้เราสามารถเขียนฟังก์ชันสำหรับบวกครึ่งหนึ่งได้อย่างง่ายดาย เราต้องการตัวแปรเพิ่มเติมสองตัวในครั้งนี้ นอกจากนี้เรายังเปลี่ยนตัวแปรของเราเป็น t1 และ t2 สำหรับอินพุต เพื่อความเท่าเทียมกับกระดาษ

def half_adder(t1, t2, s, c, v1, v2):
    linear = {c: 1, v1: 0, v2: 1, t1: 0, t2: 0, s: 1}
    quadratic = {(c, t1): -1, (c, t2): -1, (c, s): 1, (v1, t1): -1, 
                 (v1, t2): 1, (v2, t1): 1, (v2, t2): 1, (v2, s): 1}
    return dimod.BinaryQuadraticModel(linear, quadratic, dimod.SPIN)

ด้วยจุดข้อมูลจากแผนภาพครึ่งบวก (รูปที่ 7) เราสามารถแทนค่าสำหรับเทอมเชิงเส้นและเทอมกำลังสองของเราได้ ต่อไป เราสามารถคืนค่า BQM ของเราเป็นโมเดล Ising สำหรับค่าต่างๆ ได้ โครงสร้างของโค้ดส่วนใหญ่ไม่เปลี่ยนแปลงเมื่อเทียบกับเกท AND โดยมีความแตกต่างเพียงอย่างเดียวคือค่าในพจนานุกรม จากนั้นเราสามารถเรียกใช้ฟังก์ชันด้วยรหัสไดรเวอร์ต่อไปนี้

half_adder_bqm = half_adder('t1', 't2', 's', 'c', 'v1', 'v2')
sampler = dimod.ExactSolver()
print(sampler.sample(half_adder_bqm))

ฟังก์ชันควรให้ผลลัพธ์ต่อไปนี้

    c  s t1 t2 v1 v2 energy num_oc.
4  -1 -1 -1 -1 +1 +1   -5.0       1
7  -1 -1 -1 -1 -1 +1   -5.0       1
17 +1 -1 +1 +1 -1 -1   -5.0       1
18 +1 -1 +1 +1 +1 -1   -5.0       1
32 -1 +1 -1 +1 -1 -1   -5.0       1
51 -1 +1 +1 -1 +1 -1   -5.0       1
10 +1 -1 +1 -1 +1 +1   -3.0       1
11 -1 -1 +1 -1 +1 +1   -3.0       1
12 -1 -1 +1 -1 +1 -1   -3.0       1
13 +1 -1 +1 -1 +1 -1   -3.0       1

จริงๆ แล้วเอาต์พุตควรเป็น 64 แถว แต่ฉันแสดงเฉพาะเอาต์พุต 10 ตัวแรกซึ่งสำคัญที่สุด ในที่นี้ คอลัมน์ “c” คือค่าดำเนินการ “s” คือผลรวม “t1” และ “t2” คืออินพุต และ “v1” และ “v2” เป็นตัวแปรเพิ่มเติม เราจะเห็นว่าพลังงานต่ำสุดคือ -5.0 ดังนั้น BQM หกตัวแรกที่มีพลังงานนี้จึงเป็นคำตอบที่ถูกต้องซึ่งสอดคล้องกับตารางความจริงในรูป 7. เราสามารถยืนยันสิ่งนี้ได้โดยเปรียบเทียบกับตารางความจริง:

ผลลัพธ์สอดคล้องกับตารางความจริงอย่างถูกต้อง แต่คล้ายกับเกต AND เราได้รับค่าที่ซ้ำกัน ที่กล่าวมาข้างต้น นี่เป็นเพราะตัวแปรพิเศษของเรา คราวนี้เป็น v1 และ v2 เช่นเดียวกับครั้งที่แล้วจะไม่เกิดปัญหากับความแม่นยำของรุ่นนี้

ตัวบวกเต็มซึ่งสามารถเพิ่มเลขฐานสองได้สามตัวนั้น มีความคล้ายคลึงมากในการใช้งานกับตัวบวกครึ่งตัว นี่คือแผนภาพของวงจรบวกเต็มจากกระดาษ D-Wave

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

def full_adder(t1, t2, t3, s, c, v1, v2, v3):\n",
     linear = {t1: 0, t2: 0, t3: 0, s: 0, c: 0, v1: 0, v2: 0, v3: 0}
     quadratic = {(t3, v3): 1, (c, t1): -1, (c, t2): -1, (c, s): 1,      (c, v3): 1, (v1, t1): 1,(v1, t2): -1, (v1, s): 1, (v1, v3): -1, (v2, t1): -1, (v2, t2): 1,(v2, s): 1, (v2, v3): -1}
     return dimod.BinaryQuadraticModel(linear, quadratic, dimod.SPIN

สิ่งเดียวที่เราเปลี่ยนจากฟังก์ชัน half-adder คือชื่อตัวแปร รวมถึงค่าสำหรับตัวแปรเหล่านี้

หลังจากรันด้วยโค้ดไดรเวอร์เดียวกันแล้ว เราจะได้ผลลัพธ์ดังนี้:

     c  s t1 t2 t3 v1 v2 v3 energy num_oc.
8   -1 +1 -1 -1 +1 -1 -1 -1   -7.0       1
21  +1 +1 +1 +1 +1 -1 -1 -1   -7.0       1
36  +1 -1 -1 +1 +1 +1 -1 -1   -7.0       1
102 +1 -1 +1 -1 +1 -1 +1 -1   -7.0       1
142 -1 +1 +1 -1 -1 -1 +1 +1   -7.0       1
162 +1 -1 +1 +1 -1 +1 +1 +1   -7.0       1
191 -1 -1 -1 -1 -1 +1 +1 +1   -7.0       1
204 -1 +1 -1 +1 -1 +1 -1 +1   -7.0       1
9   -1 +1 +1 -1 +1 -1 -1 -1   -5.0       1
11  -1 +1 -1 +1 +1 -1 -1 -1   -5.0       1

ผลลัพธ์ควรเป็น 256 แถว แต่ขอย้ำอีกครั้งว่าฉันแสดงเฉพาะ 10 แถวแรกเท่านั้น เนื่องจากเป็นสิ่งที่สำคัญที่สุดสำหรับเรา เราจะเห็นได้ว่าฟังก์ชันนี้ให้ค่าอินพุตและเอาต์พุตที่ถูกต้องแก่เรา และแสดงว่าแปดค่าแรกมีค่าพลังงานต่ำสุดคือ -7.0 สิ่งนี้สามารถยืนยันได้ด้วยการเปรียบเทียบกับตารางความจริงบวกแบบเต็ม:

เอาต์พุตทั้งหมดที่มีค่าพลังงานต่ำสุด (-7.0) สอดคล้องกับแถวในตารางความจริง ซึ่งหมายความว่าขณะนี้แบบจำลองมีพฤติกรรมเหมือนตัวบวกเต็ม

ยินดีด้วย! คุณสามารถสร้างและดำเนินการประตูลอจิคัลได้ ซึ่งเป็นงานที่คอมพิวเตอร์ควอนตัมส่วนใหญ่ไม่สามารถทำได้ตามปกติ เกตและแอดเดอร์เหล่านี้อาจดูเรียบง่ายในตอนแรก แต่สิ่งเหล่านี้เป็นองค์ประกอบพื้นฐานที่จำเป็นในการสร้างอะไรก็ได้ในโลกของคอมพิวเตอร์ การใช้สิ่งนี้เป็นฐาน คุณสามารถสร้างโปรแกรมที่ใหญ่กว่าและดีกว่าเพื่อแก้ไขปัญหาที่ซับซ้อนมากขึ้นได้ ขอให้โชคดี!

หมายเหตุ: ขอขอบคุณเป็นพิเศษสำหรับ Alex Khan และ Terrill Frantz จาก Harrisburg University สำหรับความช่วยเหลือในบทความนี้

ที่มา:
1. https://www.dwavesys.com/media/l0tjzis2/14-1002a_b_tr_boosting_integer_factorization_via_quantum_annealing_offsets.pdf

2. https://en.wikipedia.org/wiki/AND_gate

3. https://en.wikipedia.org/wiki/Adder_(อิเล็กทรอนิกส์)