ข้ามไปยังเนื้อหาหลัก

การเปลี่ยนเฟส Nishimori

ประมาณการใช้งาน: 3 นาทีบนโปรเซสเซอร์ Heron r2 (หมายเหตุ: นี่เป็นการประมาณการเท่านั้น เวลาที่ใช้จริงอาจแตกต่างกัน)

ผลลัพธ์การเรียนรู้

หลังจากผ่านบทช่วยสอนนี้แล้ว ผู้ใช้ควรคาดหวังผลลัพธ์ดังต่อไปนี้:

  • เข้าใจการเปลี่ยนเฟส Nishimori และวิธีที่มันแสดงออกมาในรูปของการปรากฏของการพันกันระยะยาวในแบบจำลอง random-bond Ising
  • นำโปรโตคอล การสร้างการพันกันด้วยการวัด (GEM) ไปใช้บนฮาร์ดแวร์ควอนตัมโดยใช้การวัดกลางวงจรและ Circuit ความลึกคงที่
  • ระบุลักษณะการเปลี่ยนผ่านโดยการดึงข้อมูลสหสัมพันธ์สองจุดและความแปรปรวนที่ปรับให้เป็นมาตรฐานของค่าแม่เหล็กจากข้อมูลการทดลอง

ข้อกำหนดเบื้องต้น

แนะนำให้มีความคุ้นเคยกับหัวข้อต่อไปนี้ก่อนผ่านบทช่วยสอนนี้:

พื้นหลัง

บทช่วยสอนนี้แสดงวิธีการสร้างการเปลี่ยนเฟส Nishimori บนโปรเซสเซอร์ควอนตัม การทดลองนี้ถูกอธิบายไว้ครั้งแรกใน Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits

การเปลี่ยนเฟส Nishimori หมายถึงการเปลี่ยนผ่านระหว่างเฟสที่มีลำดับระยะสั้นและระยะยาวในแบบจำลอง random-bond Ising บนคอมพิวเตอร์ควอนตัม เฟสที่มีลำดับระยะยาวแสดงออกมาในรูปของสถานะที่ Qubit ต่างๆ มีการพันกันทั่วทั้งอุปกรณ์ สถานะที่พันกันสูงนี้ถูกเตรียมโดยใช้โปรโตคอล การสร้างการพันกันด้วยการวัด (GEM) โดยใช้การวัดกลางวงจร โปรโตคอล GEM สามารถพัน Qubit ทั่วทั้งอุปกรณ์ได้โดยใช้ Circuit ที่มีความลึกคงที่เท่านั้น บทช่วยสอนนี้ใช้การนำโปรโตคอล GEM ไปใช้จากซอฟต์แวร์แพ็กเกจ GEM Suite

ข้อกำหนด

ก่อนเริ่มบทช่วยสอนนี้ ให้แน่ใจว่าคุณมีสิ่งต่อไปนี้ติดตั้งอยู่:

  • Qiskit SDK v1.0 หรือใหม่กว่า พร้อมการสนับสนุน การแสดงผล
  • Qiskit Runtime v0.22 หรือใหม่กว่า (pip install qiskit-ibm-runtime)
  • Qiskit Aer v0.14 หรือใหม่กว่า (pip install qiskit-aer)
  • GEM Suite (pip install gem-suite)

การตั้งค่า

# Added by doQumentation — required packages for this notebook
!pip install -q gem-suite matplotlib qiskit qiskit-aer qiskit-ibm-runtime
import matplotlib.pyplot as plt
import warnings

from collections import defaultdict

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_aer import AerSimulator

from qiskit.transpiler import generate_preset_pass_manager

from gem_suite import PlaquetteLattice
from gem_suite.experiments import GemExperiment

ตัวอย่างบน Simulator ขนาดเล็ก

ในส่วนนี้ เวิร์กโฟลว์ทั้งหมดจะถูกทดสอบบน AerSimulator แบบไม่มีสัญญาณรบกวน plaquette lattice ถูกจำกัดให้เหลือเพียง plaquette เดียว (12 Qubit) เพื่อให้การจำลองมีขนาดเล็กและเร็ว ในขณะที่ยังครอบคลุมทุกส่วนของโปรโตคอล GEM ได้แก่ การวัดกลางวงจร การสแกนมุม RZZR_{ZZ} การถอดรหัส และการวิเคราะห์ความแปรปรวนที่ปรับให้เป็นมาตรฐาน เวิร์กโฟลว์เดียวกันนี้จะถูกขยายไปยัง plaquette หลายอันและ plaquette เต็มบนฮาร์ดแวร์จริงในภายหลัง

ขั้นตอนที่ 1: แปลงอินพุตแบบคลาสสิกเป็นปัญหาควอนตัม

โปรโตคอล GEM ทำงานบนโปรเซสเซอร์ควอนตัมที่มีการเชื่อมต่อ Qubit ที่อธิบายด้วย lattice โปรเซสเซอร์ IBM Quantum® ในปัจจุบันใช้ heavy-hex lattice Qubit ของโปรเซสเซอร์ถูกจัดกลุ่มเป็น plaquette ตามเซลล์หน่วยของ lattice ที่มันอยู่ เนื่องจาก Qubit หนึ่งอาจอยู่ในเซลล์หน่วยมากกว่าหนึ่งเซลล์ plaquette จึงไม่แยกออกจากกัน บน heavy-hex lattice แต่ละ plaquette มี 12 Qubit plaquette เองก็ก่อตัวเป็น lattice เช่นกัน โดย plaquette สองอันจะเชื่อมต่อกันหากมี Qubit ร่วมกัน บน heavy-hex lattice plaquette ที่อยู่ข้างกันจะมี Qubit ร่วมกัน 3 ตัว

ในซอฟต์แวร์แพ็กเกจ GEM Suite คลาสพื้นฐานสำหรับการนำโปรโตคอล GEM ไปใช้คือ PlaquetteLattice ซึ่งแทน lattice ของ plaquette (ซึ่งแตกต่างจาก heavy-hex lattice) PlaquetteLattice สามารถเริ่มต้นได้จาก qubit coupling map ปัจจุบันรองรับเฉพาะ coupling map แบบ heavy-hex เท่านั้น

โค้ดต่อไปนี้เริ่มต้น plaquette lattice จาก coupling map ของหน่วยประมวลผลควอนตัม (QPU) plaquette lattice ไม่ได้ครอบคลุมฮาร์ดแวร์ทั้งหมดเสมอไป ตัวอย่างเช่น ibm_torino มี Qubit ทั้งหมด 133 ตัว แต่ plaquette lattice ที่ใหญ่ที่สุดที่พอดีกับอุปกรณ์นี้ใช้เพียง 125 ตัวเท่านั้น ประกอบด้วย plaquette ทั้งหมด 18 อัน ส่วน ibm_pittsburgh (156 Qubit) ก็ใส่ได้ 144 Qubit ใน 21 plaquette เช่นกัน รูปแบบเดียวกันนี้ใช้ได้กับ QPU แบบ heavy-hex อื่นๆ ที่มีจำนวน Qubit ต่างกัน

# QiskitRuntimeService.save_account(channel="ibm_quantum", token="<YOUR_API_KEY>", overwrite=True,
# set_as_default=True)
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
aer_backend = AerSimulator.from_backend(backend)
plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)

print(f"Number of qubits in backend: {backend.num_qubits}")
print(
f"Number of qubits in plaquette lattice: {len(list(plaquette_lattice.qubits()))}"
)
print(f"Number of plaquettes: {len(list(plaquette_lattice.plaquettes()))}")

คุณสามารถแสดงผล plaquette lattice ได้โดยสร้างแผนภาพของการแทนกราฟ ในแผนภาพ plaquette จะแสดงด้วยรูปหกเหลี่ยมที่มีป้ายกำกับ และ plaquette สองอันจะเชื่อมต่อกันด้วยขอบหากมี Qubit ร่วมกัน

plaquette_lattice.draw_plaquettes()

Output of the previous code cell

คุณสามารถดึงข้อมูลเกี่ยวกับ plaquette แต่ละอัน เช่น Qubit ที่มีอยู่ โดยใช้เมธอด plaquettes

# Get a list of the plaquettes
plaquettes = list(plaquette_lattice.plaquettes())
# Display information about plaquette 0
plaquettes[0]
PyPlaquette(index=0, qubits=[3, 4, 5, 6, 7, 16, 17, 23, 24, 25, 26, 27], neighbors=[4, 3, 1])

คุณยังสามารถสร้างแผนภาพของ Qubit พื้นฐานที่ก่อตัวเป็น plaquette lattice ได้

plaquette_lattice.draw_qubits()

Output of the previous code cell

นอกจากป้ายกำกับ Qubit และขอบที่แสดงว่า Qubit ตัวใดเชื่อมต่อกัน แผนภาพยังมีข้อมูลเพิ่มเติมสามส่วนที่เกี่ยวข้องกับโปรโตคอล GEM:

  • Qubit แต่ละตัวจะมีเฉดสี (สีเทา) หรือไม่มีเฉดสี Qubit ที่มีเฉดสีคือ Qubit "ไซต์" ที่แทนไซต์ของแบบจำลอง Ising และ Qubit ที่ไม่มีเฉดสีคือ Qubit "พันธะ" ที่ใช้เป็นตัวกลางสำหรับปฏิสัมพันธ์ระหว่าง Qubit ไซต์
  • Qubit ไซต์แต่ละตัวจะถูกติดป้ายว่า (A) หรือ (B) ซึ่งบ่งบอกถึงหนึ่งในสองบทบาทที่ Qubit ไซต์สามารถมีได้ในโปรโตคอล GEM (บทบาทจะอธิบายในภายหลัง)
  • แต่ละขอบจะถูกระบายสีโดยใช้หนึ่งในหกสี ทำให้ขอบถูกแบ่งออกเป็นหกกลุ่ม การแบ่งพาร์ทิชันนี้กำหนดวิธีที่ Gate สองคิวบิตสามารถทำแบบขนานได้ รวมถึงรูปแบบการจัดกำหนดการต่างๆ ที่มีแนวโน้มจะเกิดข้อผิดพลาดในปริมาณต่างกันบนโปรเซสเซอร์ควอนตัมที่มีสัญญาณรบกวน เนื่องจากขอบในกลุ่มเดียวกันไม่มีจุดร่วม จึงสามารถใช้ชั้นของ Gate สองคิวบิตกับขอบเหล่านั้นพร้อมกันได้ จริงๆ แล้ว สามารถแบ่งสีหกสีออกเป็นสามกลุ่ม กลุ่มละสองสี ได้ โดยที่สหภาพของแต่ละกลุ่มสองสียังคงไม่มีจุดร่วม ดังนั้น จำเป็นต้องใช้เพียงสามชั้นของ Gate สองคิวบิตเพื่อเปิดใช้งานทุกขอบ มี 12 วิธีในการแบ่งพาร์ทิชันหกสีดังกล่าว และแต่ละพาร์ทิชันให้กำหนดการ Gate 3 ชั้นที่แตกต่างกัน

เมื่อสร้าง plaquette lattice แล้ว ขั้นตอนถัดไปคือการเริ่มต้นออบเจ็กต์ GemExperiment โดยส่งทั้ง plaquette lattice และ Backend ที่ต้องการรันการทดลองนั้น คลาส GemExperiment จัดการการนำโปรโตคอล GEM ไปใช้จริง รวมถึงการสร้าง Circuit การส่งงาน และการวิเคราะห์ข้อมูล โค้ดต่อไปนี้เริ่มต้นคลาสการทดลองขณะจำกัด plaquette lattice ให้เหลือเพียง plaquette เดียว (12 Qubit) เพื่อให้การจำลองมีขนาดเล็กและเร็ว plaquette lattice เต็มจะถูกใช้ในภายหลังเมื่อขยายไปยังฮาร์ดแวร์จริง

# Filter the plaquette lattice down to a single plaquette (12 qubits)
# so the AerSimulator run stays fast. The full lattice is used later
# in the large-scale hardware example.
gem_exp = GemExperiment(plaquette_lattice.filter([9]), backend=aer_backend)

# visualize the plaquette lattice after filtering
plaquette_lattice.filter([9]).draw_qubits()

Output of the previous code cell

Circuit ของโปรโตคอล GEM ถูกสร้างขึ้นโดยใช้ขั้นตอนต่อไปนี้:

  1. เตรียมสถานะ all-+|+\rangle โดยใช้ Hadamard Gate กับ Qubit ทุกตัว
  2. ใช้ RZZR_{ZZ} Gate ระหว่าง Qubit ที่เชื่อมต่อกันทุกคู่ ซึ่งทำได้โดยใช้สามชั้นของ Gate แต่ละ RZZR_{ZZ} Gate ทำงานบน Qubit ไซต์และ Qubit พันธะ หาก Qubit ไซต์ถูกติดป้าย (B) มุมจะถูกกำหนดไว้ที่ π2\frac{\pi}{2} หาก Qubit ไซต์ถูกติดป้าย (A) มุมจะได้รับอนุญาตให้เปลี่ยนแปลงได้ ทำให้ Circuit แตกต่างกัน โดยค่าเริ่มต้น ช่วงของมุมถูกตั้งค่าให้เป็น 21 จุดที่เว้นระยะเท่ากันระหว่าง 00 ถึง π2\frac{\pi}{2} รวมจุดสุดท้าย
  3. วัด Qubit พันธะแต่ละตัวในฐาน Pauli XX เนื่องจาก Qubit ถูกวัดในฐาน Pauli ZZ จึงสามารถทำได้โดยใช้ Hadamard Gate ก่อนวัด Qubit

สังเกตว่าเอกสารอ้างอิงในบทนำของบทช่วยสอนนี้ใช้แบบแผนที่ต่างกันสำหรับมุม RZZR_{ZZ} ซึ่งแตกต่างจากแบบแผนที่ใช้ในบทช่วยสอนนี้ด้วยปัจจัย 2

ในขั้นตอนที่ 3 มีเพียง Qubit พันธะเท่านั้นที่ถูกวัด เพื่อเข้าใจว่า Qubit ไซต์อยู่ในสถานะอะไร เป็นเรื่องน่าพิจารณาถึงกรณีที่มุม RZZR_{ZZ} ที่ใช้กับ Qubit ไซต์ (A) ในขั้นตอนที่ 2 เท่ากับ π2\frac{\pi}{2} ในกรณีนี้ Qubit ไซต์จะอยู่ในสถานะที่พันกันสูงคล้ายกับสถานะ GHZ

GHZ=0000+1111.\lvert \text{GHZ} \rangle = \lvert 00 \cdots 00 \rangle + \lvert 11 \cdots 11 \rangle.

เนื่องจากความสุ่มในผลลัพธ์การวัด สถานะจริงของ Qubit ไซต์อาจเป็นสถานะที่ต่างกันที่มีลำดับระยะยาว ตัวอย่างเช่น 00110+11001\lvert 00110 \rangle + \lvert 11001 \rangle อย่างไรก็ตาม สถานะ GHZ สามารถกู้คืนได้โดยการใช้การดำเนินการถอดรหัสตามผลการวัด เมื่อมุม RZZR_{ZZ} ถูกปรับลดจาก π2\frac{\pi}{2} ลำดับระยะยาวยังคงกู้คืนได้จนถึงมุมวิกฤต ซึ่งในกรณีที่ไม่มีสัญญาณรบกวนอยู่ที่ประมาณ 0.3π0.3 \pi ต่ำกว่ามุมนี้ สถานะที่ได้จะไม่แสดงการพันกันระยะยาวอีกต่อไป การเปลี่ยนผ่านระหว่างการมีและไม่มีลำดับระยะยาวนี้คือการเปลี่ยนเฟส Nishimori

ในคำอธิบายข้างต้น Qubit ไซต์ถูกปล่อยไว้โดยไม่ได้วัด และการดำเนินการถอดรหัสสามารถทำได้โดยการใช้ Gate ควอนตัม ในการทดลองตามที่นำไปใช้ใน GEM suite Qubit ไซต์ถูกวัดจริงๆ และการดำเนินการถอดรหัสจะถูกนำไปใช้ในขั้นตอนหลังประมวลผลแบบคลาสสิก

ในคำอธิบายข้างต้น การดำเนินการถอดรหัสสามารถทำได้โดยการใช้ Gate ควอนตัมกับ Qubit ไซต์เพื่อกู้คืนสถานะควอนตัม อย่างไรก็ตาม หากเป้าหมายคือการวัดสถานะทันที (เช่น เพื่อวัตถุประสงค์ในการระบุลักษณะ) คุณสามารถวัด Qubit ไซต์พร้อมกับ Qubit พันธะและนำการดำเนินการถอดรหัสไปใช้ในขั้นตอนหลังประมวลผลแบบคลาสสิกได้

นอกจากขึ้นอยู่กับมุม RZZR_{ZZ} ในขั้นตอนที่ 2 ซึ่งโดยค่าเริ่มต้นสแกนผ่าน 21 ค่า Circuit ของโปรโตคอล GEM ยังขึ้นอยู่กับรูปแบบการจัดกำหนดการที่ใช้ในการนำสามชั้นของ RZZR_{ZZ} Gate ไปใช้ด้วย ดังที่กล่าวไว้ก่อนหน้า มี 12 รูปแบบการจัดกำหนดการดังกล่าว ดังนั้น จำนวน Circuit ทั้งหมดในการทดลองคือ 21×12=25221 \times 12 = 252

Circuit ของการทดลองสามารถสร้างได้โดยใช้เมธอด circuits ของคลาส GemExperiment

circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")
Total number of circuits: 252

สำหรับจุดประสงค์ของบทช่วยสอนนี้ การพิจารณารูปแบบการจัดกำหนดการเพียงรูปแบบเดียวก็เพียงพอ โค้ดต่อไปนี้จำกัดการทดลองให้เหลือรูปแบบการจัดกำหนดการแรก ส่งผลให้การทดลองมีเพียง 21 Circuit หนึ่งสำหรับมุม RZZR_{ZZ} แต่ละค่าที่สแกนผ่าน

# Restrict experiment to the first scheduling pattern
gem_exp.set_experiment_options(schedule_idx=0)

# There are less circuits now
circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")

# Print the RZZ angles swept over
print(f"RZZ angles:\n{gem_exp.parameters()}")
Total number of circuits: 21
RZZ angles:
[0. 0.07853982 0.15707963 0.23561945 0.31415927 0.39269908
0.4712389 0.54977871 0.62831853 0.70685835 0.78539816 0.86393798
0.9424778 1.02101761 1.09955743 1.17809725 1.25663706 1.33517688
1.41371669 1.49225651 1.57079633]

โค้ดต่อไปนี้วาดแผนภาพของ Circuit ที่อินเด็กซ์ 5 เพื่อลดขนาดของแผนภาพ เกตการวัดที่ท้าย Circuit จะถูกลบออก

# Get the circuit at index 5
circuit = circuits[5]
# Remove the final measurements to ease visualization
circuit.remove_final_measurements()
# Draw the circuit
circuit.draw("mpl", fold=-1, scale=0.5)

Output of the previous code cell

ขั้นตอนที่ 2: ปรับปรุงปัญหาสำหรับการประมวลผลบนฮาร์ดแวร์ควอนตัม

การ Transpile Circuit ควอนตัมสำหรับการรันบนฮาร์ดแวร์มักเกี่ยวข้องกับ หลายขั้นตอน โดยทั่วไป ขั้นตอนที่มีโอเวอร์เฮดการคำนวณมากที่สุดคือการเลือกเลย์เอาต์ Qubit การกำหนดเส้นทาง Gate สองคิวบิตให้สอดคล้องกับการเชื่อมต่อ Qubit ของฮาร์ดแวร์ และการปรับแต่ง Circuit เพื่อลดจำนวน Gate และความลึก ในโปรโตคอล GEM ขั้นตอนเลย์เอาต์และการกำหนดเส้นทางไม่จำเป็น เนื่องจากการเชื่อมต่อฮาร์ดแวร์ถูกรวมไว้ในการออกแบบโปรโตคอลแล้ว Circuit มีเลย์เอาต์ Qubit อยู่แล้ว และ Gate สองคิวบิตถูกแมปกับการเชื่อมต่อ native แล้ว นอกจากนี้ เพื่อรักษาโครงสร้างของ Circuit ขณะที่มุม RZZR_{ZZ} เปลี่ยนแปลง ควรทำการปรับแต่ง Circuit เพียงขั้นพื้นฐานเท่านั้น

คลาส GemExperiment ทำการ Transpile Circuit อย่างโปร่งใสเมื่อรันการทดลอง ขั้นตอนเลย์เอาต์และการกำหนดเส้นทางถูกแทนที่โดยค่าเริ่มต้นให้ไม่ทำอะไร และการปรับแต่ง Circuit จะทำในระดับที่ปรับแต่งเฉพาะ Gate คิวบิตเดี่ยวเท่านั้น อย่างไรก็ตาม คุณสามารถแทนที่หรือส่งตัวเลือกเพิ่มเติมโดยใช้เมธอด set_transpile_options เพื่อแสดงให้เห็นด้านภาพ โค้ดต่อไปนี้ทำการ Transpile Circuit ที่แสดงก่อนหน้าด้วยตนเองและวาด Circuit ที่ถูก Transpile แล้ว

# Demonstrate setting transpile options
gem_exp.set_transpile_options(
optimization_level=1 # This is the default optimization level
)
pass_manager = generate_preset_pass_manager(
backend=aer_backend,
initial_layout=list(gem_exp.physical_qubits),
**dict(gem_exp.transpile_options),
)
transpiled = pass_manager.run(circuit)
transpiled.draw("mpl", idle_wires=False, fold=-1, scale=0.5)

Output of the previous code cell

ขั้นตอนที่ 3: ประมวลผลโดยใช้ Qiskit primitives

เพื่อรัน Circuit ของโปรโตคอล GEM บนฮาร์ดแวร์ ให้เรียกเมธอด run ของออบเจ็กต์ GemExperiment คุณสามารถระบุจำนวน shot ที่ต้องการสุ่มตัวอย่างจากแต่ละ Circuit เมธอด run คืนค่าออบเจ็กต์ ExperimentData ซึ่งควรบันทึกไว้ในตัวแปร สังเกตว่าเมธอด run เพียงแค่ส่งงานโดยไม่รอให้เสร็จ ดังนั้นจึงเป็นการเรียกแบบ non-blocking

exp_data = gem_exp.run(shots=10_000)

เพื่อรอผลลัพธ์ ให้เรียกเมธอด block_for_results ของออบเจ็กต์ ExperimentData การเรียกนี้จะทำให้ตัวแปลโปรแกรมหยุดรอจนกว่างานจะเสร็จ

# The noiseless AerSimulator produces zero-variance UFloat objects in the
# analysis, which triggers a harmless warning from the `uncertainties`
# library. Suppress it so the output stays clean.
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", message="Using UFloat objects with std_dev==0"
)
exp_data.block_for_results()
exp_data
ExperimentData(GemExperiment, 90bf2a90-f729-4c4e-a6da-664aecb11039, job_ids=['04a7c405-47fd-46ca-aa4b-aaf7e339cfbe'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])

ขั้นตอนที่ 4: หลังประมวลผลและแสดงผลในรูปแบบคลาสสิกที่ต้องการ

ที่มุม RZZR_{ZZ} เท่ากับ π2\frac{\pi}{2} สถานะที่ถอดรหัสแล้วจะเป็นสถานะ GHZ ในกรณีที่ไม่มีสัญญาณรบกวน ลำดับระยะยาวของสถานะ GHZ สามารถแสดงได้โดยการพล็อตค่าแม่เหล็กของบิตสตริงที่วัดได้ ค่าแม่เหล็ก MM ถูกนิยามเป็นผลรวมของตัวดำเนินการ Pauli ZZ คิวบิตเดี่ยว

M=j=1NZj,M = \sum_{j=1}^N Z_j,

โดยที่ NN คือจำนวน Qubit ไซต์ ค่าสำหรับบิตสตริงหนึ่งเท่ากับความแตกต่างระหว่างจำนวนศูนย์และจำนวนหนึ่ง การวัดสถานะ GHZ จะให้สถานะ all-zeros หรือ all-ones ด้วยความน่าจะเป็นเท่ากัน ดังนั้นค่าแม่เหล็กจะเป็น +N+N ครึ่งหนึ่งของเวลาและ N-N อีกครึ่งหนึ่ง เมื่อมีข้อผิดพลาดจากสัญญาณรบกวน ค่าอื่นก็จะปรากฏขึ้นด้วย แต่ถ้าสัญญาณรบกวนไม่มากเกินไป การกระจายก็ยังคงมียอดอยู่ใกล้ +N+N และ N-N

สำหรับบิตสตริงดิบก่อนการถอดรหัส การกระจายของค่าแม่เหล็กจะเทียบเท่ากับบิตสตริงแบบสุ่มสม่ำเสมอในกรณีที่ไม่มีสัญญาณรบกวน

โค้ดต่อไปนี้พล็อตค่าแม่เหล็กของบิตสตริงดิบและบิตสตริงที่ถอดรหัสแล้วที่มุม RZZR_{ZZ} เท่ากับ π2\frac{\pi}{2}

def magnetization_distribution(
counts_dict: dict[str, int],
) -> dict[str, float]:
"""Compute magnetization distribution from counts dictionary."""
# Construct dictionary from magnetization to count
mag_dist = defaultdict(float)
for bitstring, count in counts_dict.items():
mag = bitstring.count("0") - bitstring.count("1")
mag_dist[mag] += count
# Normalize
shots = sum(counts_dict.values())
for mag in mag_dist:
mag_dist[mag] /= shots
return mag_dist

# Get counts dictionaries with and without decoding
data = exp_data.data()
# Get the last data point, which is at the angle for the GHZ state
raw_counts = data[-1]["counts"]
# Without decoding
site_indices = [
i for i, q in enumerate(gem_exp.plaquettes.qubits()) if q.role == "Site"
]
site_raw_counts = defaultdict(int)
for key, val in raw_counts.items():
site_str = "".join(key[-1 - i] for i in site_indices)
site_raw_counts[site_str] += val
# With decoding
_, site_decoded_counts = gem_exp.plaquettes.decode_outcomes(
raw_counts, return_counts=True
)

# Compute magnetization distribution
raw_magnetization = magnetization_distribution(site_raw_counts)
decoded_magnetization = magnetization_distribution(site_decoded_counts)

# Plot
plt.bar(*zip(*raw_magnetization.items()), label="raw")
plt.bar(*zip(*decoded_magnetization.items()), label="decoded", width=0.3)
plt.legend()
plt.xlabel("Magnetization")
plt.ylabel("Frequency")
plt.title("Magnetization distribution with and without decoding")
Text(0.5, 1.0, 'Magnetization distribution with and without decoding')

Output of the previous code cell

เพื่อระบุลักษณะลำดับระยะยาวอย่างเข้มงวดมากขึ้น คุณสามารถตรวจสอบค่าสหสัมพันธ์สองจุดเฉลี่ย ff ที่นิยามเป็น

f=1N2(M2M2).f = \frac{1}{N^2} \left(\langle M^2 \rangle - \langle M \rangle ^2\right).

ค่าที่สูงขึ้นบ่งบอกถึงระดับการพันกันที่มากขึ้น คลาส GemExperiment คำนวณค่านี้สำหรับบิตสตริงที่ถอดรหัสแล้วโดยอัตโนมัติเป็นส่วนหนึ่งของการประมวลผลข้อมูลการทดลอง มันเก็บรูปภาพที่เข้าถึงได้ผ่านเมธอด figure ของคลาสข้อมูลการทดลอง ในกรณีนี้ ชื่อของรูปภาพคือ two_point_correlation

exp_data.figure("two_point_correlation")

Output of the previous code cell

เพื่อกำหนดจุดวิกฤตของการเปลี่ยนเฟส Nishimori คุณสามารถดูความแปรปรวนที่ปรับให้เป็นมาตรฐานของ M2/NM^2 / N ที่นิยามเป็น

g=1N3(M4M22),g = \frac{1}{N^3} \left(\langle M^4 \rangle - \langle M^2 \rangle^2\right),

ซึ่งวัดปริมาณความผันแปรในค่าแม่เหล็กกำลังสอง ค่านี้จะสูงสุดที่จุดวิกฤตของการเปลี่ยนเฟส Nishimori ในกรณีที่ไม่มีสัญญาณรบกวน จุดวิกฤตจะอยู่ที่ประมาณ 0.3π0.3 \pi เมื่อมีสัญญาณรบกวน จุดวิกฤตจะเลื่อนขึ้น แต่การเปลี่ยนเฟสยังคงสังเกตได้ตราบเท่าที่จุดวิกฤตอยู่ต่ำกว่า 0.5π0.5 \pi

exp_data.figure("normalized_variance")

Output of the previous code cell

ตัวอย่างฮาร์ดแวร์ขนาดใหญ่

หลังจากตรวจสอบโปรโตคอลบน Simulator แล้ว คุณสามารถขยายการทดลองและรันบน Backend ฮาร์ดแวร์ควอนตัมจริงที่เลือกไว้ในส่วน การตั้งค่า ตัวอย่างนี้ใช้ขนาดปัญหาที่ใหญ่ขึ้นสองขนาด:

  • หก plaquette (~49 Qubit): การรันขนาดกลางที่แสดงให้เห็นการเลื่อนไปทางขวาของจุดวิกฤตภายใต้สัญญาณรบกวนของฮาร์ดแวร์แล้ว
  • plaquette lattice เต็ม: ทุก plaquette ที่โทโพโลยี heavy-hex ของอุปกรณ์รองรับ (ตัวอย่างเช่น 18 plaquette / 125 Qubit บน ibm_torino หรือ 21 plaquette / 144 Qubit บน ibm_pittsburgh) ซึ่งพัน Qubit ทั่วทั้งอุปกรณ์ด้วย Circuit ความลึกคงที่

โค้ดต่อไปนี้เป็น Cell เดียวที่ครบสมบูรณ์ในตัวเอง: มันสร้าง plaquette lattice จาก coupling map ของ Backend และรันการทดลองทั้งสอง ดังนั้นส่วนนี้สามารถดำเนินการได้หลังจาก Cell ใน การตั้งค่า โดยไม่ต้องรันส่วนขนาดเล็กก่อน

# -------------------------Step 1-------------------------
# Initialize the runtime service, pick a real quantum hardware backend,
# and build the plaquette lattice from its coupling map. This is repeated
# from the small-scale example so this cell can run standalone after the
# Setup section. The full plaquette lattice is the "large-scale" target;
# a six-plaquette subset (range(3, 9)) is also used to show an intermediate
# scaling step.
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)

# Build a GemExperiment for the full plaquette lattice and one for the
# six-plaquette subset, each restricted to a single scheduling pattern so
# the experiment has one circuit per RZZ angle (21 circuits total).
gem_exp_full = GemExperiment(plaquette_lattice, backend=backend)
gem_exp_full.set_experiment_options(schedule_idx=0)
gem_exp_6 = GemExperiment(
plaquette_lattice.filter(range(3, 9)), backend=backend
)
gem_exp_6.set_experiment_options(schedule_idx=0)

circuits = gem_exp_full.circuits()
print(f"Total number of circuits (full lattice): {len(circuits)}")

# -------------------------Step 2-------------------------
# GemExperiment transpiles internally for the target backend: the layout
# and routing stages are overridden because the plaquette lattice already
# matches the hardware connectivity, and optimization is restricted so the
# RZZ angle structure is preserved. The code below manually transpiles one
# circuit from the six-plaquette experiment with the same settings this
# experiment will use, and draws it for inspection. (The full-lattice
# transpiled circuit has too many qubits to visualize cleanly, so the
# six-plaquette circuit is used here as a representative example.)
gem_exp_6.set_transpile_options(optimization_level=1)
circuits_6 = gem_exp_6.circuits()
pass_manager = generate_preset_pass_manager(
backend=backend,
initial_layout=list(gem_exp_6.physical_qubits),
**dict(gem_exp_6.transpile_options),
)
transpiled = pass_manager.run(circuits_6[5])
display(transpiled.draw("mpl", idle_wires=False, fold=-1, scale=0.5))

# -------------------------Step 3-------------------------
# Run both problem sizes on real hardware:
# 1. Six plaquettes (~49 qubits) — an intermediate scale-up.
# 2. The full plaquette lattice — every plaquette the device supports.
exp_data_6 = gem_exp_6.run(shots=10_000, job_tags=["TUT_NPT"])
exp_data_full = gem_exp_full.run(shots=10_000, job_tags=["TUT_NPT"])
exp_data_6.block_for_results()
exp_data_full.block_for_results()

# -------------------------Step 4-------------------------
# Plot the normalized variance at each scale. The peak marks the critical
# point of the Nishimori transition; as the system grows, hardware noise
# shifts the peak rightward.
display(exp_data_6.figure("normalized_variance"))
exp_data_full.figure("normalized_variance")
Total number of circuits (full lattice): 21

Output of the previous code cell

Output of the previous code cell

Output of the previous code cell

สังเกตว่า ขึ้นอยู่กับระดับสัญญาณรบกวนของ Backend ที่ใช้ เส้นโค้งความแปรปรวนที่ปรับให้เป็นมาตรฐานที่ขนาดใหญ่กว่าอาจไม่แสดงยอดที่ชัดเจนในช่วงมุมที่สแกน ในการรันข้างต้น ยอดถูกผลักไปจนถึง 0.5π0.5 \pi ซึ่งเป็นขอบขวาของการสแกน (การวิเคราะห์รายงาน critical_angle = 0.5000 สำหรับทั้งการรันหก plaquette และ full-lattice) ซึ่งหมายความว่าสัญญาณรบกวนของฮาร์ดแวร์ได้เลื่อนจุดวิกฤตไปถึง (หรือเลยออกไปเล็กน้อย) ขอบเขตของช่วงมุมที่มีความหมายทางฟิสิกส์ของโปรโตคอล ดังนั้นการเปลี่ยนผ่านจึงอยู่ที่ขอบของสิ่งที่การสแกนนี้สามารถระบุได้

สรุป

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

ขั้นตอนต่อไป

คำแนะนำ

หากคุณพบว่างานนี้น่าสนใจ คุณอาจสนใจเนื้อหาต่อไปนี้:

อ้างอิง

[1] E. H. Chen, G.-Y. Zhu, R. Verresen, A. Seif, E. Bäumer, D. Layden, N. Tantivasadakarn, G. Zhu, S. Sheldon, A. Vishwanath, S. Trebst, A. Kandala. Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits. arXiv:2309.02863 (2023).

[2] GEM Suite software package.