ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

ทำงานกับ Circuit แบบโบซอน

BosonicCircuit แสดงการคำนวณโดยตรงบนโหมดโบซอน มันไม่มีการตัดทอน ไม่มีการเข้ารหัส และไม่มีจำนวน Qubit: สิ่งเหล่านั้นเข้ามาทีหลังระหว่าง transpilation ซึ่งทำให้ Circuit หนึ่งแปลงลงได้ภายใต้หลายการเข้ารหัสและหลายการตัดทอนโดยไม่ต้องสร้างใหม่

มันเปิดเผย API ที่ลดรูปเมื่อเทียบกับ QuantumCircuit ของ Qiskit โดยตั้งใจ เพื่อไม่ให้ใช้ Gate ของ Qubit กับโหมดโบซอนได้ ซึ่งจะไม่ใช่การดำเนินการที่นิยามได้ชัดเจน คู่มือนี้ครอบคลุมการดำเนินการที่ เปิดเผย ไว้สำหรับประกอบ Circuit ใหญ่จาก Circuit เล็ก

ทำไมจึงใช้ Circuit แบบโบซอน​

ลองพิจารณาเวิร์กโฟลว์แบบดั้งเดิมในการนำวิวัฒนาการตามเวลาของแฮมิลโทเนียนแบบโบซอนไปไว้บนสถาปัตยกรรมที่ใช้ Qubit:

  1. นิยามแฮมิลโทเนียนแบบโบซอน เช่น H=−∑ijbi†bjH = -\sum_{ij} b^\dagger_i b_j

  2. เลือกการตัดทอนและการเข้ารหัส แล้วแมปแฮมิลโทเนียนเป็นตัวดำเนินการ Qubit ด้วยสิ่งเหล่านั้น

  3. ทำวิวัฒนาการตามเวลาในปริภูมิ Qubit ด้วย Trotterization หรือวิธีอื่น

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

BosonicCircuit ย้ายการตัดสินใจเหล่านั้นไปไว้ท้ายสุด:

  1. นิยามแฮมิลโทเนียนแบบโบซอน

  2. แสดงวิวัฒนาการตามเวลาโดยตรงบนโหมดโบซอน ด้วย Gate แบบโบซอน

  3. เลือกการตัดทอนและการเข้ารหัสเป็นส่วนหนึ่งของ transpilation

Circuit อธิบายว่าจะคำนวณ อะไร และ transpilation ตัดสินว่าจะวางมันบน Qubit อย่างไร จากนั้น Circuit เดียวกันจะถูกแปลงลงที่ทุกค่าตัดและภายใต้ทุกการเข้ารหัส และการจัดกลุ่มของตัวดำเนินการยังอยู่ให้ pass ที่ใช้ประโยชน์ได้ ส่วนถัดไปแสดงวิธีประกอบ Circuit เช่นนี้ Transpile Circuit แบบโบซอน แสดงการแปลงลง

การทำดัชนีโหมดแบบทั่วไป​

โมดูล operators และ Circuit ใช้ข้อตกลงเดียวกันสำหรับโหมด โหมดเป็นเพียงดัชนีที่ติดป้ายระดับขั้นความเสรีแบบโบซอน และไม่มีความหมายในตัวเอง ดังนั้นคุณจึงทำวิวัฒนาการตัวดำเนินการใดก็ได้ที่ implement โปรโตคอล OperatorTrait ไม่ว่ามันจะแทนอะไร และ Circuit ไม่จำเป็นต้องรู้ว่าโหมด 2 หมายถึงอะไร เช่นเดียวกันกับขนาดของโหมด: Circuit ไม่มีค่าตัดการครอบครอง ดังนั้นไม่มีอะไรที่นี่บอกว่าโหมดมีกี่ระดับ

ต่อ Gate​

Gate ถูกต่อลงบนโหมด รับเฉพาะอินสแตนซ์ของ BosonicGate เท่านั้น:

>>> from qiskit_bosons.circuit import BosonicCircuit
>>> from qiskit_bosons.circuit.library import Evolution, InitializeModes
>>> from qiskit_bosons.operators import BosonOperator, ann, cre
>>>
>>> hopping = BosonOperator.from_dict({(cre(0), ann(1)): -1.0, (cre(1), ann(0)): -1.0})
>>> hopping.groups = [0] * len(hopping) # the pair is Hermitian, its terms alone are not
>>>
>>> prepare = BosonicCircuit(2)
>>> prepare.append(InitializeModes([2, 0]), prepare.modes)
>>> step = BosonicCircuit(2)
>>> step.append(Evolution(2, hopping, time=0.1), step.modes)

อย่างอื่นจะถูกปฏิเสธ และข้อผิดพลาดระบุชนิดที่ผิด:

>>> from qiskit.circuit.library import HGate
>>> try:
... prepare.append(HGate(), [0])
... except ValueError as error:
... print(error)
Unsupported instruction type: <class '...HGate'>

ประกอบ Circuit​

compose() วางคำสั่งของ Circuit หนึ่งลงบนอีกอัน คำสั่งเหล่านั้นถูก inline ไม่ได้ห่อเป็น Gate เดียว ผลลัพธ์จึงเป็น Circuit ธรรมดาที่คุณแยกส่วนและ transpile ต่อได้

>>> program = prepare.compose(step)
>>> program.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A composed BosonicCircuit.

โดยค่าเริ่มต้นจะคืน Circuit ใหม่และไม่แตะตัวถูกดำเนินการทั้งสอง ส่ง inplace=True เพื่อแก้ไขตัวแรกแทน และ front=True เพื่อวางตัวถูกดำเนินการ ก่อน คำสั่งที่มีอยู่:

>>> step.compose(prepare, front=True)._inner.data == program._inner.data
True

Circuit ที่แคบกว่าสามารถวางลงบนเซตย่อยของโหมดที่เลือกได้:

>>> single = BosonicCircuit(1)
>>> single.append(Evolution(1, BosonOperator.from_dict({(cre(0), ann(0)): 1.0}), 0.1), single.modes)
>>> wide = BosonicCircuit(3).compose(single, [2])
>>> wide.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A narrow-composed BosonicCircuit.

รับเฉพาะ BosonicCircuit อื่นเป็นตัวถูกดำเนินการ เพราะ compose ของ Qiskit เองจะ inline Gate ของ Qubit และข้ามการตรวจสอบที่ append บังคับใช้

ทำซ้ำ Circuit​

repeat() ทำซ้ำ Circuit ต่อกันตั้งแต่ต้นจนจบ การทำซ้ำถูก แผ่ราบ: ผลลัพธ์เก็บคำสั่ง reps ครั้งต่อเนื่องกัน แทนที่จะเป็น Gate เดียวที่ห่อ Circuit ดังนั้นจำนวนการดำเนินการจึงเพิ่มตาม reps และ decompose ทำงานบนส่วนที่ซ้ำแทนที่จะลบการทำซ้ำหนึ่งครั้ง

>>> len(step.repeat(0)._inner.data) # zero repetitions is the identity
0
>>> step.repeat(5).draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A repeated BosonicCircuit.

นี่คือวิธีระดับ Circuit ในการทำ Trotterize: วิวัฒน์ในเวลาสั้น ๆ แล้วทำซ้ำ ดู สังเคราะห์ Gate Evolution ในปริภูมิโบซอน สำหรับทางเลือกในการเลือกสูตรผลคูณบน Gate เอง และเหตุผลที่สองสิ่งนี้เป็นคนละเรื่องที่บังเอิญใช้คำว่า "repetitions" ร่วมกัน

คั่นขั้นตอนด้วย barrier​

barrier ทำเครื่องหมายจุดซิงโครไนซ์ที่ pass การปรับให้เหมาะสมจะไม่รวม Gate ข้ามไป barrier() วางหนึ่งอันบนทุกโหมด หรือบนโหมดที่คุณระบุ:

>>> program = BosonicCircuit(2)
>>> program.append(InitializeModes([2, 0]), program.modes)
>>> program.barrier()
>>> program.barrier(program.modes[0], label="zero")
>>> program.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A BosonicCircuit with barriers.

repeat(..., insert_barriers=True) ใส่หนึ่งอันระหว่างการทำซ้ำที่ต่อเนื่องกัน และไม่ใส่หลังอันสุดท้าย:

>>> step.repeat(3, insert_barriers=True).draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A repeated BosonicCircuit with barriers.

barrier และการเข้ารหัส​

การเข้ารหัสต้องใช้หลาย Qubit ต่อโหมด ดังนั้นรีจิสเตอร์ของโหมดและรีจิสเตอร์ของ Qubit จึงมีขนาดต่างกัน และ layout เชื่อมโยง ทั้งรีจิสเตอร์ โหมดจึงไม่มี Qubit ของตัวเองให้จำกัด barrier ลงไป ระหว่างการสังเคราะห์โบซอนเป็น Qubit barrier ถูกแมปไปยัง ทุก Qubit ของแต่ละรีจิสเตอร์ที่มันแตะ ซึ่งถูกต้องภายใต้ layout ใด ๆ:

>>> from qiskit_bosons.mappers import LevelSpec
>>> from qiskit_bosons.transpiler.presets import generate_preset_occupation_pass_manager
>>> lowered = generate_preset_occupation_pass_manager(LevelSpec(2, "unary_projected")).run(program)
>>> lowered.draw("mpl", fold=-1)
<Figure size ... with 1 Axes>

A QuantumCircuit showing the expansion of barrier to cover the entire qubit register.

อ่านค่าจาก Circuit แบบโบซอน​

BosonicCircuit ไม่มี measure หรือ measure_all ความหมายของบิตที่วัดได้ขึ้นอยู่กับการเข้ารหัส ภายใต้การเข้ารหัสแบบยูนารี การครอบครองของโหมดกระจายอยู่บนหลาย Qubit และต้องอ่านจากรูปแบบของบิต ส่วนแบบกะทัดรัดเป็นเลขฐานสอง ดังนั้นการวัดที่ระบุโหมดจะต้องรู้การเข้ารหัส ซึ่ง Circuit แบบโบซอนไม่รู้โดยตั้งใจ ให้วัด QuantumCircuit ที่ transpile แล้วแทน และถอดรหัสบิตสตริงด้วย LevelEncoding.level_to_bits() และออฟเซตของ LevelSpec ที่คุณใช้แปลงลง จำลองพลวัต Bose-Hubbard ด้วยการเลือกการเข้ารหัส ทำสิ่งนี้กับโมเดลที่สมบูรณ์

>>> hasattr(BosonicCircuit, "measure_all")
False

ขั้นตอนถัดไป​