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

แมปการแทนค่าตัวดำเนินการ

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

พัฒนา mapper แบบกำหนดเอง​

โมดูล mappers ทำให้การพัฒนาการแมปแบบกำหนดเองตรงไปตรงมา Mapper ทำงานโดยแปลงการกระทำพื้นฐาน (การสร้าง การทำลาย มาจอรานา และอื่นๆ) ที่ประกอบเป็นตัวดำเนินการ แล้วรวมการกระทำที่แปลงแล้วเหล่านี้ตามกฎของการแทนค่าเป้าหมาย

ตัวอย่างที่เป็นรูปธรรม ลองดูการแปลง Jordan-Wigner ที่แมป MajoranaOperator ไปเป็นตัวดำเนินการ qubit โดยใช้ map_majorana_action_generators():

>>> from qiskit.quantum_info import SparseObservable
>>> from qiskit_fermions.mappers import map_majorana_action_generators
>>> from qiskit_fermions.operators import MajoranaOperator
>>>
>>> # Create a Majorana operator
>>> maj_op = MajoranaOperator.from_dict({(0, 1): 1.0, (2,): 0.5})
>>>
>>> # Define how each Majorana action maps to Pauli strings
>>> num_qubits = 2
>>> def map_action(mode: int) -> SparseObservable:
... idx = mode // 2
... qubits = list(range(idx + 1))
... pauli = "Y" if mode % 2 else "X"
... return SparseObservable.from_sparse_list(
... [("Z" * idx + pauli, qubits, 1.0)],
... num_qubits=num_qubits,
... )
>>>
>>> # Apply the mapping to transform the operator
>>> custom_observable = map_majorana_action_generators(
... maj_op,
... map_action,
... identity=lambda: SparseObservable.identity(num_qubits),
... compose=SparseObservable.compose,
... )
>>> print(custom_observable.simplify())
<SparseObservable with 2 terms on 2 qubits: (0+1j)(Z_0) + (0.5+0j)(X_1 Z_0)>

ขั้นตอนหลักในการสร้าง mapper แบบกำหนดเองมีดังนี้:

  1. กำหนดการแปลง action: ระบุว่าแต่ละ action (ที่ถูกจัดดัชนีด้วย mode) แมปไปเป็นการแทนค่าเป้าหมายอย่างไร ในตัวอย่างข้างต้น action แบบ Majorana จะแมปไปเป็น Pauli string ตามกฎของ Jordan-Wigner

  2. ใช้ฟังก์ชันแมปที่มีให้ตัวใดตัวหนึ่ง: โมดูล mappers มีฟังก์ชันอรรถประโยชน์สำหรับวนผ่านพจน์ของตัวดำเนินการและนำ action map แบบกำหนดเองไปใช้ต่อ สำหรับการแทนค่าตัวดำเนินการที่โมดูล operators จัดให้ เช่น map_majorana_action_generators() ใช้งานได้กับตัวดำเนินการ Majorana

  3. รับผลลัพธ์: ฟังก์ชันแมปจะคืนตัวดำเนินการในการแทนค่าเป้าหมายที่ใช้การแปลงอย่างสอดคล้องกันกับทุกพจน์

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

คำใบ้

คุณยังวนผ่านพจน์ของตัวดำเนินการด้วยตัวเองได้ แทนที่จะใช้ฟังก์ชัน iterator ที่มีให้ ดูรายละเอียดได้ในหัวข้อ การวนผ่านพจน์ ในคู่มือตัวดำเนินการ

การนำไปใช้ในไลบรารี​

โมดูล qiskit_fermions.mappers.library มีการนำการแมปที่ใช้กันทั่วไปไปใช้อย่างมีประสิทธิภาพและผ่านการทดสอบอย่างละเอียด การนำไปใช้เหล่านี้ใช้รูปแบบพื้นฐานเดียวกับ mapper แบบกำหนดเอง แต่ได้รับการปรับให้เหมาะกับการใช้งานจริง และมีให้ทั้งใน Python API และ C API

ตัวอย่างด้านล่างใช้ library mapper กับ MajoranaOperator ตัวเดียวกันจากหัวข้อ mapper แบบกำหนดเอง เพื่อแสดงผลลัพธ์ที่เทียบเท่ากัน:

>>> from qiskit_fermions.mappers.library import majorana_to_fermion, jordan_wigner
>>>
>>> # Convert MajoranaOperator to FermionOperator using library mapper
>>> ferm_op = majorana_to_fermion(maj_op)
>>>
>>> # Apply Jordan-Wigner mapper to get qubit operator
>>> sparse_observable = jordan_wigner(ferm_op, num_qubits=2)
>>> difference = sparse_observable - custom_observable
>>> print(difference.simplify() == SparseObservable.zero(num_qubits))
True
หมายเหตุ

สองขั้นตอนข้างต้นเขียนแยกออกมาเพื่อแสดงการประกอบ library mapper สองตัวเข้าด้วยกัน ในทางปฏิบัติคุณจะแมป MajoranaOperator ในขั้นตอนเดียวแทน ด้วย majorana_jordan_wigner() (qf_maj_op_jordan_wigner() ใน C API) และทำนองเดียวกันกับตัวดำเนินการประเภทอื่น – edge_vertex_jordan_wigner() และ transfer_vertex_jordan_wigner() (qf_edge_op_jordan_wigner(), qf_transfer_op_jordan_wigner()) การผ่าน FermionOperator ยังทำให้ผลลัพธ์ระหว่างทางบวมขึ้นด้วย: ตัวสร้างทุกตัวของพีชคณิตเหล่านี้แมปไปเป็น Pauli string เพียงตัวเดียว ขณะที่แต่ละ action แบบเฟอร์มิออนแมปไปเป็นผลรวมสองพจน์ ดังนั้นพจน์ที่สร้างจากตัวสร้างหลายตัวจะขยายออกไปแล้วต้องรวมกลับลงมาอีกครั้ง การประหยัดนี้เพิ่มขึ้นตามความยาวของพจน์ สำหรับพจน์ที่มีตัวสร้างตัวเดียวของ Hamiltonian แบบ hopping ทั้งสองเส้นทางมีต้นทุนใกล้เคียงกัน

ใน Python API library mapper บางตัวเหล่านี้ยังเรียกใช้ผ่าน mapper อำนวยความสะดวกที่ไม่ขึ้นกับชนิดได้ด้วย fermion_operator() และ majorana_operator() ทำหน้าที่เป็นด่านหน้าของ majorana_to_fermion() และ fermion_to_majorana() (รวมถึงตัวอื่น ๆ) โดยส่งต่อไปยังการนำไปใช้ในไลบรารีที่เหมาะสมภายในตามชนิดของอ็อบเจกต์ที่ได้รับ แทนที่จะให้คุณเลือกฟังก์ชันที่ถูกต้องเอง เช่นเดียวกันกับ jordan_wigner() และ ternary_tree() (แนะนำด้านล่าง) ซึ่งแต่ละตัวจะส่งต่อไปยังการนำไปใช้โดยตรงที่ตรงกับตัวดำเนินการที่ได้รับ ดู qiskit_fermions.protocols เพื่อดูว่าการส่งต่อนี้ถูกนำไปใช้ภายในอย่างไร

เลือกการเข้ารหัสด้วย ternary tree​

Jordan-Wigner ไม่ใช่การเข้ารหัสจากเฟอร์มิออนไปเป็น qubit เพียงแบบเดียว และไม่ใช่แบบที่ถูกที่สุด สตริง ZZ ของมันยาวขึ้นตามดัชนี mode ดังนั้นตัวดำเนินการ Majorana บน mode สุดท้ายจากทั้งหมด nn mode จะแมปไปเป็น Pauli string ที่มีน้ำหนัก nn การเข้ารหัสที่กระจายข้อมูลพาริตีผ่านต้นไม้แทนที่จะเป็นโซ่จะทำได้ดีกว่าในเชิงอสมมาตร

ternary tree บน nn node ครอบคลุมตระกูลนี้ทั้งหมด แต่ละ node คือ qubit ที่มีลิงก์ลงสามเส้นติดป้าย X, Y และ Z ลิงก์หนึ่งอาจลงไปยัง node ลูก (edge) หรือสิ้นสุด (leg) เส้นทางของแต่ละ leg ย้อนกลับไปถึงรากสะกดเป็น Pauli string: การข้ามลิงก์ที่ติดป้าย PP ซึ่งลงจาก node uu ให้ PP บน qubit uu ต้นไม้ทุกต้นให้การเข้ารหัสที่ถูกต้อง และแบบที่คุ้นเคยก็เป็นเพียงรูปร่างเฉพาะ – โซ่ตาม Z คือ Jordan-Wigner ส่วนต้นไม้ที่ทุก node มีลูกสามตัวเท่าที่จำนวน node เอื้ออำนวยคือแบบสมดุล

>>> from qiskit_fermions.mappers import TernaryTree, TernaryTreeEncoding
>>>
>>> # Jordan-Wigner is a chain descending along Z, with X and Y as legs at every node.
>>> TernaryTree.chain(13, "Z").max_weight
13
>>> # The balanced tree spreads the same information over depth log_3(2n+1).
>>> TernaryTree.breadth_first(13, 3).max_weight
3

น้ำหนักสูงสุดนั้นเหมาะสมที่สุดแล้ว Jiang et al. พิสูจน์ว่าตัวดำเนินการ Majorana ของการแมปจากเฟอร์มิออนไปเป็น qubit ใด ๆ ของ nn mode มีน้ำหนัก Pauli เฉลี่ยอย่างน้อย log⁡3(2n)\log_3(2n) จึงไม่มีการแมปใดลดตัวที่ใหญ่ที่สุดให้ต่ำกว่า ⌈log⁡3(2n+1)⌉\lceil \log_3(2n+1) \rceil ได้ ต้นไม้ทั้งสองใช้ qubit เท่ากับ nn พอดี ดังนั้นสิ่งที่ประหยัดได้คือน้ำหนัก Pauli ไม่ใช่จำนวน qubit

หากต้องการแมปตัวดำเนินการ ให้คอมไพล์ต้นไม้เป็น encoding แล้วส่งให้ mapper พร้อมจำนวน qubit ของผลลัพธ์ การคอมไพล์จะจับคู่ leg ของต้นไม้เป็นตัวดำเนินการ Majorana และสร้าง Pauli string ของมันเพียงครั้งเดียว ดังนั้นควรใช้ encoding เดียวกันซ้ำกับตัวดำเนินการหลายตัว จำนวน qubit อยู่กับการเรียกแมปแทนที่จะอยู่กับ encoding ดังนั้น encoding เดียวจึงรองรับรีจิสเตอร์ที่มีความกว้างต่างกันได้ จำนวนที่มากกว่าจำนวน node ของต้นไม้จะถูกเติมด้วยเอกลักษณ์

>>> from qiskit_fermions.mappers.library import fermion_ternary_tree
>>> from qiskit_fermions.operators import FermionOperator
>>>
>>> hamiltonian = FermionOperator.from_dict(
... {((True, 0), (False, 3)): 1.0, ((True, 3), (False, 0)): 1.0}
... )
>>> encoding = TernaryTreeEncoding(TernaryTree.breadth_first(4, 3))
>>> fermion_ternary_tree(hamiltonian, encoding, 4).simplify()
<SparseObservable with 2 terms on 4 qubits: (0.5+0j)(Y_3 Z_1 Y_0) + (0.5+0j)(X_3 Z_2 X_0)>

การแมปผ่านโซ่ตาม Z ให้ผลเหมือน fermion_jordan_wigner() (qf_ferm_op_jordan_wigner() ใน C API) ทุกประการ ซึ่งเป็นความหมายที่ว่าแบบนี้เป็นการสรุปความทั่วไปของมัน:

>>> from qiskit_fermions.mappers.library import fermion_jordan_wigner
>>> chain = TernaryTreeEncoding(TernaryTree.chain(4, "Z"))
>>> direct = fermion_jordan_wigner(hamiltonian, 4)
>>> (fermion_ternary_tree(hamiltonian, chain, 4) - direct).simplify().num_terms
0

ตัวดำเนินการทุกการแทนค่ามี ternary-tree mapper โดยสะท้อนชุดของ Jordan-Wigner ดูรายการทั้งหมดได้ที่ qiskit_fermions.mappers.library และ Mapper Library ใน C API ใน Python API ยังเรียกใช้ผ่าน ternary_tree() ซึ่งเป็น wrapper ที่ไม่ขึ้นกับชนิดและเลือกตัวที่ถูกต้องให้ตัวดำเนินการที่ได้รับ เช่นเดียวกับที่ jordan_wigner() ทำ:

>>> from qiskit_fermions.mappers.library import ternary_tree
>>> ternary_tree(hamiltonian, encoding, 4).simplify()
<SparseObservable with 2 terms on 4 qubits: (0.5+0j)(Y_3 Z_1 Y_0) + (0.5+0j)(X_3 Z_2 X_0)>
หมายเหตุ

เอกลักษณ์บางอย่างที่เป็นจริงภายใต้ Jordan-Wigner เป็นสมบัติของโซ่ ไม่ใช่ของ ternary tree ตัวดำเนินการจำนวนคือ nj=(1−Zj)/2n_j = (1 - Z_j)/2 เฉพาะบนโซ่เท่านั้น บนต้นไม้แบบอื่น ZjZ_j จะกลายเป็นสตริง ZZ บนเซตของ qubit ในทำนองเดียวกัน ตัวดำเนินการ vertex VjV_j เป็น Pauli น้ำหนัก 1 ZjZ_j เฉพาะบนโซ่ ที่ซึ่งโซ่ ZZ ของสตริง Majorana ทั้งสองหักล้างกัน

เนื่องจากตัวดำเนินการจำนวนทุกตัวยังคงแมปไปเป็นสตริง ZZ เพียงตัวเดียว สถานะ Fock จึงยังคงเป็นสถานะฐานการคำนวณภายใต้ ternary tree ใด ๆ แต่บิต qq ไม่ได้อ่านค่า occupation qq อีกต่อไป occupation jj คือพาริตีของบิตที่วัดได้บน support ของภาพของ njn_j ให้อ่าน support เหล่านั้นจาก mapper แทนที่จะอนุมานจากต้นไม้ เพื่อให้การถอดรหัสถูกต้องสำหรับรูปร่างหรือการสลับ mode ใด ๆ:

>>> for mode in range(4):
... number = FermionOperator.from_dict({((True, mode), (False, mode)): 1.0})
... print(mode, ternary_tree(number, encoding, 4).simplify())
0 <SparseObservable with 2 terms on 4 qubits: (0.5+0j)() + (-0.5+0j)(Z_2 Z_1 Z_0)>
1 <SparseObservable with 2 terms on 4 qubits: (0.5+0j)() + (-0.5+0j)(Z_1)>
2 <SparseObservable with 2 terms on 4 qubits: (0.5+0j)() + (-0.5+0j)(Z_2)>
3 <SparseObservable with 2 terms on 4 qubits: (0.5+0j)() + (-0.5+0j)(Z_3)>

บนต้นไม้สมดุลนี้ mode 0 ถูกครอบครองเมื่อ qubit 0, 1 และ 2 มีเลข 1 เป็นจำนวนคี่ ดังนั้นการเตรียมมันจึงหมายถึงการพลิก qubit 0 เพียงตัวเดียว ขณะที่การถอดรหัสบิตสตริงที่วัดได้ต้องหาพาริตีจากทั้งสามตัว ข้อผิดพลาดการพลิกบิตเดียวบน qubit 1 จึงทำให้ occupation ของทั้ง mode 0 และ mode 1 เสียหาย ซึ่งสำคัญกับเวิร์กโฟลว์ใดก็ตามที่อ่าน occupation จากตัวอย่างที่มีสัญญาณรบกวน

เมื่อ Evolution ถูกลดระดับผ่าน mapper แบบนี้ ให้ครอบ mapper ด้วย group_wise() (ดู การสังเคราะห์ Evolution gate ในปริภูมิเฟอร์มิออน) พจน์ hopping แมปไปเป็น Pauli string สองตัวที่ commute กัน ซึ่งแต่ละตัวไม่อนุรักษ์จำนวนอนุภาคด้วยตัวเอง มีเพียงผลคูณของทั้งสองใน evolution เท่านั้นที่อนุรักษ์ ภายใต้ Jordan-Wigner สตริงทั้งสองกระทำบน qubit ชุดเดียวกัน ลำดับพจน์ที่ทำให้ง่ายขึ้นจึงทำให้สองตัวนี้อยู่ติดกัน ภายใต้ต้นไม้แบบอื่น support ของพวกมันต่างกัน (เช่น Y_3 Z_1 Y_0 และ X_3 Z_2 X_0 ก่อนหน้านี้) ทั้งลำดับดิบและลำดับที่ทำให้ง่ายขึ้นต่างสอดแทรกพวกมันกับภาพของพจน์อื่น และสูตรผลคูณฝั่ง qubit จะทำให้จำนวนอนุภาครั่วไหล

สร้างต้นไม้ตามต้องการ​

ตัวสร้างแบบโซ่และแบบ breadth-first ครอบคลุมตระกูลที่สม่ำเสมอ แต่อินเทอร์เฟซทั่วไปรับคู่ (parent, label) หนึ่งคู่ต่อ node โดยใช้ None สำหรับราก (C API รับดัชนีของรากแทน) ซึ่งสำคัญเพราะต้นไม้ที่น่าค้นหามักไม่ใช่ทั้งโซ่และไม่สม่ำเสมอ – เช่น อัลกอริทึม Bonsai สร้าง spanning tree ของกราฟการเชื่อมต่อของอุปกรณ์ การแตกกิ่งของมันจึงเป็นไปตามการเชื่อมต่อนั้น

>>> # Node 0 branches three ways, node 1 twice, and node 4 carries a single child.
>>> tree = TernaryTree([None, (0, "X"), (0, "Y"), (0, "Z"), (1, "X"), (1, "Z"), (4, "Y")])
>>> tree.num_nodes, tree.num_legs, tree.max_weight
(7, 15, 4)
>>> tree.children(0)
{'X': 1, 'Y': 2, 'Z': 3}

สังเกตจำนวน leg: เป็น 2n+12n+1 เสมอไม่ว่ารูปร่างจะเป็นอย่างไร node ที่มีลูกน้อยกว่าไม่ได้สร้าง Pauli string น้อยลง – ลิงก์ที่ไม่ได้ใช้ของมันคือ leg และ leg สะกดสตริงได้เหมือนกับที่ลูกหลานของ edge ทำ จากสตริง 2n+12n+1 ตัวนั้น 2n2n ตัวจับคู่เป็นตัวดำเนินการ Majorana ของ nn mode และเหลืออยู่ตัวเดียวพอดี

พาริตีรวม​

leg ที่เหลือนั้นคือพาริตีเฟอร์มิออนรวม ∏j(1−2nj)\prod_j (1 - 2 n_j) ซึ่งเป็นสมบัติของการเข้ารหัสมากกว่าจะเป็นการแมปของตัวดำเนินการใด ๆ จึงเป็นเมธอดของ encoding เอง:

>>> TernaryTreeEncoding(TernaryTree.chain(4, "Z")).total_parity(4)
<SparseObservable with 1 term on 4 qubits: (1+0j)(Z_3 Z_2 Z_1 Z_0)>
>>> TernaryTreeEncoding(TernaryTree.breadth_first(4, 3)).total_parity(4)
<SparseObservable with 1 term on 4 qubits: (1+0j)(Z_3 Z_0)>

ดังที่กรณีสมดุลแสดงให้เห็น โดยทั่วไปแล้วสิ่งนี้ ไม่ใช่ สตริง ZZ ทั้งหมด: มันคือ leg ที่ไปถึงได้ด้วยเส้นทาง ZZ ทั้งหมด ซึ่งกระทำเป็นเอกลักษณ์บนทุก node ที่ไม่อยู่บนเส้นทางนั้น

สำคัญ

พาริตีรวมในที่นี้เป็น observable ที่ต้องวัด ไม่ใช่ข้อจำกัดที่ต้องบังคับใช้ ค่าลักษณะเฉพาะทั้งสองของมันเป็นค่าทางกายภาพ ดังนั้นอย่าโปรเจกต์สถานะลงบนเซกเตอร์ +1+1: การเข้ารหัสแบบ ternary tree ใช้ qubit หนึ่งตัวต่อ mode และครอบคลุมปริภูมิ 2n2^n มิติเต็ม จึงไม่มีปริภูมิย่อยที่ไม่เป็นกายภาพให้โปรเจกต์ทิ้ง

ตัวอย่างใช้งานจริง: ต้นไม้ Bravyi-Kitaev​

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

ต้นไม้ของมันสร้างโดยการแบ่งแบบเวียนเกิดเหนือ node ซึ่งมีหนึ่ง node ต่อหนึ่ง mode ภายในช่วงของ node [l,r][l, r] ให้ hh เป็นกำลังสองที่ใหญ่ที่สุดที่พอดี node ที่วางสำหรับช่วงนั้นคือ l+h−1l + h - 1 ซึ่งเป็นตัวสุดท้ายในบล็อกนั้น ลิงก์ X ของมันลงไปยังต้นไม้ที่สร้างจากบล็อกก่อนหน้า และลิงก์ Z ลงไปยังต้นไม้ที่สร้างจากส่วนที่เหลือหลังมัน โดยปล่อยลิงก์ Y เป็น leg:

>>> def bravyi_kitaev_tree(num_modes: int) -> TernaryTree:
... """Builds the ternary tree of the Bravyi-Kitaev encoding on ``num_modes`` modes."""
... spec: list[tuple[int, str] | None] = [None] * num_modes
... def build(left: int, right: int) -> int | None:
... if left > right:
... return None # an empty range: the parent's link stays a leg
... block = 1
... while 2 * block <= right - left + 1:
... block *= 2
... node = left + block - 1
... for child, label in (
... (build(left, node - 1), "X"), # the block before this node
... (build(node + 1, right), "Z"), # the remainder after it
... ):
... if child is not None:
... spec[child] = (node, label)
... return node
... build(0, num_modes - 1)
... return TernaryTree(spec)

ที่สี่ mode ช่วงทั้งหมดเป็นบล็อกเดียว ดังนั้น node ที่วางก่อนคือ 3 โดยมี [0,2][0, 2] อยู่ก่อนหน้าและไม่มีอะไรอยู่หลัง ช่วงย่อยนั้นให้ node 1 เหนือ node เดี่ยว 0 และ 2 การคอมไพล์ต้นไม้ยืนยันว่า encoding เป็น Bravyi-Kitaev จริง ไม่ใช่แค่ต้นไม้ที่มีรูปร่างในคลาสเดียวกัน – ภาพ Majorana ตัวแรกของมันคือ X0X1X3X_0 X_1 X_3:

>>> tree = bravyi_kitaev_tree(4)
>>> tree.children(1)
{'X': 0, 'Z': 2}
>>> encoding = TernaryTreeEncoding(tree)
>>> encoding.majorana_image(0)
[(0, 'X'), (1, 'X'), (3, 'X')]

พาริตีรวมของมันทำให้ประเด็นของหัวข้อก่อนหน้าเป็นรูปธรรม: leg ที่เหลือคือตัวที่ไปถึงได้ด้วยเส้นทาง ZZ ทั้งหมด และในที่นี้เส้นทางนั้นหยุดที่ราก ดังนั้น observable จึงเป็น Z3Z_3 ของ qubit เดียว ไม่ใช่สตริงบนทั้งสี่ qubit:

>>> encoding.total_parity(4)
<SparseObservable with 1 term on 4 qubits: (1+0j)(Z_3)>

การขยายขนาดไม่ต้องการอะไรนอกจากอาร์กิวเมนต์ที่ใหญ่ขึ้น เนื่องจากไม่มี node ใดใช้ลิงก์ Y เป็น edge แต่ละ node จึงแตกกิ่งได้มากสุดสองทาง น้ำหนัก Pauli จึงโตแบบลอการิทึมแทนที่จะเป็นเชิงเส้น:

>>> [bravyi_kitaev_tree(n).max_weight for n in (4, 8, 16, 32, 64)]
[3, 4, 5, 6, 7]