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

หลักการออกแบบการแทนตัวดำเนินการ

คู่มือนี้อธิบายว่า BosonOperator ถูกจัดโครงสร้างอย่างไรและใช้งานอย่างไร ได้แก่ วิธีสร้าง วิธีตรวจสอบและรวมตัวดำเนินการ และวิธีนำตัวดำเนินการสองตัวมาอยู่ในรูปที่เปรียบเทียบกันได้ เริ่มที่นี่เมื่อคุณเขียนแฮมิลโทเนียน

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

[bi,bj†]=δij,[bi,bj]=[bi†,bj†]=0 .[b_i, b_j^\dagger] = \delta_{ij}, \qquad [b_i, b_j] = [b_i^\dagger, b_j^\dagger] = 0 \, .

มีสองผลที่ตามมาซึ่งกำหนดอินเทอร์เฟซ ดัชนีโหมดซ้ำได้ภายในพจน์เดียว เพราะ bi†bi†b_i^\dagger b_i^\dagger เป็นตัวดำเนินการที่ใช้ได้ซึ่งสร้างโบซอนสองตัว นอกจากนี้ การสลับลำดับสองปัจจัยไม่เคยทำให้เกิดเครื่องหมาย แม้ว่าการย้ายตัวดำเนินการทำลายผ่านตัวดำเนินการสร้างบนโหมดเดียวกันจะเพิ่มพจน์ bibi†=bi†bi+1b_i b_i^\dagger = b_i^\dagger b_i + 1

การจัดเก็บ​

ตัวดำเนินการเก็บพจน์ของมันในอาร์เรย์แบนสี่ชุด คล้ายรูปแบบ compressed sparse row ของเมทริกซ์เบาบาง:

coeffsสัมประสิทธิ์เชิงซ้อนหนึ่งค่าต่อหนึ่งพจน์
actionsบูลีนหนึ่งค่าต่อหนึ่งปัจจัย: True สำหรับตัวดำเนินการสร้าง และ False สำหรับตัวดำเนินการทำลาย
modesดัชนีโหมดหนึ่งค่าต่อหนึ่งปัจจัย
boundariesตำแหน่งใน actions และ modes ที่แต่ละพจน์เริ่มและสิ้นสุด

คอนสตรักเตอร์รับอาร์เรย์ทั้งสี่นี้โดยตรง ตัวดำเนินการด้านล่างมีสามพจน์ คือ 2b0†b12 b_0^\dagger b_1, −ib1†b1†-i b_1^\dagger b_1^\dagger และค่าคงที่ 0.50.5 และคุณอ่านอาร์เรย์กลับได้ด้วยเมธอด get_*:

>>> from qiskit_bosons.operators import BosonOperator, ann, cre
>>> op = BosonOperator(
... coeffs=[2.0, -1.0j, 0.5],
... actions=[True, False, True, True],
... modes=[0, 1, 1, 1],
... boundaries=[0, 2, 4, 4],
... )
>>> op.get_coeffs()
[(2+0j), (-0-1j), (0.5+0j)]
>>> op.get_actions()
[True, False, True, True]
>>> op.get_modes()
[0, 1, 1, 1]
>>> op.get_boundaries()
[0, 2, 4, 4]
>>> len(op)
3

พจน์แรกครอบคลุมตำแหน่ง 0 ถึง 2 ของ actions และ modes พจน์ที่สองครอบคลุม 2 ถึง 4 และพจน์ที่สามครอบคลุม 4 ถึง 4 ซึ่งเป็นวิธีเก็บพจน์ค่าคงที่ คือพจน์ที่ไม่มีปัจจัย โหมด 1 ที่ซ้ำในพจน์ที่สองถูกคงไว้ตามที่เขียน พจน์จะไม่ถูกทิ้งหรือรวมเพียงเพราะดัชนีโหมดปรากฏสองครั้ง

หมายเหตุ

ตัวดำเนินการที่สร้างด้วย from_dict() ไม่เก็บพจน์ตามลำดับของดิกชันนารี อาร์เรย์ของมันจึงอาจแสดงพจน์ในลำดับต่างกันในแต่ละครั้งที่รัน ตัวดำเนินการเองเหมือนเดิม และไม่มีสิ่งใดด้านล่างที่เปรียบเทียบหรือพิมพ์ตัวดำเนินการขึ้นกับลำดับที่เก็บ

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

สร้างตัวดำเนินการ​

วิธีที่ตรงที่สุดในการสร้างตัวดำเนินการคือ from_dict() ซึ่งรับดิกชันนารีจากทูเพิลของปัจจัยไปเป็นสัมประสิทธิ์ ฟังก์ชัน cre() และ ann() สร้างปัจจัย และทูเพิลว่างคือพจน์ค่าคงที่:

>>> b = BosonOperator.from_dict({(ann(0),): 1.0})
>>> b_dag = BosonOperator.from_dict({(cre(0),): 1.0})
>>> number = BosonOperator.from_dict({(cre(0), ann(0)): 1.0})
>>> print(format(number))
1.000000e0 +0.000000e0j * (+0 -0)

ในรูปที่พิมพ์ +0 แทน b0†b_0^\dagger และ -0 แทน b0b_0 คอนสตรักเตอร์ zero() และ one() คืนเอกลักษณ์การบวกและเอกลักษณ์การคูณ และ from_terms() สร้างตัวดำเนินการขึ้นใหม่จากอิเทอเรเตอร์ของ iter_terms()

ไลบรารีตัวดำเนินการมีควอดราเจอร์ตำแหน่งและโมเมนตัมแบบไร้มิติ

q^=b†+b2,p^=i(b†−b)2 ,\hat{q} = \frac{b^\dagger + b}{\sqrt{2}}, \qquad \hat{p} = \frac{i \left(b^\dagger - b\right)}{\sqrt{2}} \, ,

เป็น position() และ momentum() เมื่อใช้ร่วมกับฟังก์ชันคอมมิวเตเตอร์ของโมดูลเดียวกัน คุณตรวจสอบพีชคณิตได้โดยตรง:

>>> from qiskit_bosons.operators.library import commutator, momentum, position
>>> q, p = position(0), momentum(0)
>>> q.is_hermitian() and p.is_hermitian()
True
>>> commutator(q, p).equiv(1j * BosonOperator.one())
True
>>> commutator(b, b_dag).equiv(BosonOperator.one())
True

โมดูลนี้ยังมี anti_commutator() และ double_commutator() ทั้งสามรับตัวดำเนินการชนิดเดียวกันและคืนตัวดำเนินการใหม่

ระวังลำดับของผลคูณ​

คูณตัวดำเนินการสองตัวได้สองวิธี และสับสนกันง่าย ตัวดำเนินการ @ คือผลคูณทางคณิตศาสตร์ ดังนั้น a @ b คือ ABAB ตัวดำเนินการ & คือ การประกอบ ซึ่งตามแบบแผนของ Qiskit ที่อ่านจากซ้ายไปขวา: a & b ใช้ a ก่อนแล้วจึงใช้ b ดังนั้นคือ BABA ฟังก์ชันคอมมิวเตเตอร์ใช้ @ ดังนั้น commutator(a, b) คือ [A,B][A, B] หากสร้างวงเล็บเองด้วย & ผลจะกลับเครื่องหมายอย่างเงียบ ๆ:

>>> (b @ b_dag).equiv(b_dag @ b + BosonOperator.one())
True
>>> (b & b_dag).equiv(b_dag @ b)
True
>>> ((b @ b_dag) - (b_dag @ b)).equiv(BosonOperator.one())
True
>>> ((b & b_dag) - (b_dag & b)).equiv(-BosonOperator.one())
True

ตรวจสอบตัวดำเนินการ​

ตัวดำเนินการวนซ้ำโดยตรงไม่ได้ เพราะพจน์ของมันอยู่ในอาร์เรย์แบนข้างต้น ให้ใช้ iter_terms() แทน ซึ่งให้รายการของคู่ (is_creation, mode) และสัมประสิทธิ์ของแต่ละพจน์ อิเทอเรเตอร์คืนสำเนา ดังนั้นการเปลี่ยนสำเนาจึงไม่เปลี่ยนตัวดำเนินการ

>>> hopping = BosonOperator.from_dict(
... {
... (cre(0), ann(1)): -1.0,
... (cre(1), ann(0)): -1.0,
... (cre(2), cre(2), ann(2), ann(2)): 0.5,
... }
... )
>>> len(hopping)
3
>>> sorted(hopping.iter_terms())
[([(True, 0), (False, 1)], (-1+0j)), ([(True, 1), (False, 0)], (-1+0j)), ([(True, 2), (True, 2), (False, 2), (False, 2)], (0.5+0j))]

หลายเมธอดสรุปโครงสร้างของตัวดำเนินการ:

>>> hopping.get_support()
{0, 1, 2}
>>> hopping.min_num_modes()
3
>>> hopping.max_rank()
4

get_support() คือเซตของโหมดที่ตัวดำเนินการกระทำ min_num_modes() คือรีจิสเตอร์ที่เล็กที่สุดที่รองรับมันได้ และ max_rank() คือความยาวของพจน์ที่ยาวที่สุด

หมายเหตุ

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

เมธอดการครอบครองรายงานว่าหนึ่งพจน์วางโบซอนในหนึ่งโหมดได้กี่ตัว นี่เป็นขอบล่างของค่าตัดที่การแมปต้องใช้ แต่ไม่เพียงพอ เพราะการใช้ตัวดำเนินการซ้ำ ๆ เช่นในการวิวัฒน์ตามเวลา อาจเติมระดับที่สูงขึ้น (ดู ตัดทอนปริภูมิ Fock):

>>> hopping.mode_occupations()
[1, 1, 2]
>>> hopping.mode_occupations([2, 0])
[2, 1]
>>> hopping.max_occupation()
2

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

>>> hopping.conserves_particle_number()
True
>>> move = BosonOperator.from_dict({(cre(0), ann(2)): 1.0})
>>> move.conserves_sector([3])
True
>>> move.conserves_sector([2, 1])
False

สุดท้าย relabel_modes() เปลี่ยนชื่อโหมด: โหมด i กลายเป็น permutation[i] รายการต้องยาวพอจะอ้างอิงทุกโหมดของตัวดำเนินการ และต้องไม่มีรายการซ้ำ:

>>> print(format(move.relabel_modes([5, 6, 7])))
1.000000e0 +0.000000e0j * (+5 -7)

ทำเลขคณิต​

ตัวดำเนินการรองรับการบวก การลบ การเปลี่ยนเครื่องหมาย และการคูณและหารด้วยจำนวน ทั้งในรูปตัวดำเนินการปกติหรือในที่เดิม:

>>> total = 2 * b_dag + b_dag - 3j * b
>>> len(total)
3
>>> len(total.simplify())
2
>>> total.simplify().equiv(3 * b_dag - 3j * b)
True

สามพจน์ของ total ไม่เคยถูกรวมกัน ตัวดำเนินการจึงมี b_dag สองครั้งจนกว่า simplify() จะรวมมัน เมธอดนี้บวกสัมประสิทธิ์ของพจน์ที่เหมือนกันและทิ้งพจน์ที่ขนาดรวมต่ำกว่าค่าความคลาดเคลื่อน มันเป็นการดำเนินการเชิงโครงสร้าง: เปรียบเทียบปัจจัยที่เขียนไว้และ ไม่ ใช้ความสัมพันธ์การสลับที่ เมธอดที่เกี่ยวข้อง ichop() ลบสัมประสิทธิ์เล็ก ๆ ในที่เดิมโดยไม่รวมก่อน ดังนั้นให้เรียก simplify() ก่อน ichop() เมื่อตัวดำเนินการอาจมีพจน์ซ้ำ

ผลคูณใช้ @ หรือ & ตามที่อธิบายข้างต้น และ ** ยกตัวดำเนินการเป็นเลขยกกำลังจำนวนเต็ม:

>>> x = b_dag + b
>>> print(format((x ** 2).simplify()))
1.000000e0 +0.000000e0j * (-0 -0)
1.000000e0 +0.000000e0j * (-0 +0)
1.000000e0 +0.000000e0j * (+0 -0)
1.000000e0 +0.000000e0j * (+0 +0)

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

ตัวร่วมเสริมจะกลับลำดับของปัจจัยในแต่ละพจน์ สลับตัวดำเนินการสร้างกับทำลาย และสังยุคสัมประสิทธิ์ เมธอด is_hermitian() ทดสอบว่าตัวดำเนินการเท่ากับตัวร่วมเสริมของมันหรือไม่:

>>> hop = BosonOperator.from_dict({(cre(0), ann(1)): 1j})
>>> print(format(hop.adjoint()))
0.000000e0 -1.000000e0j * (+1 -0)
>>> hop.is_hermitian()
False
>>> (hop + hop.adjoint()).is_hermitian()
True

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

จัดลำดับปกติและเปรียบเทียบตัวดำเนินการ​

ผลคูณของตัวดำเนินการแลดเดอร์สองชุดอาจเป็นตัวดำเนินการเดียวกันแต่ดูต่างกัน เพราะ b b†b\,b^\dagger และ b†b+1b^\dagger b + 1 เท่ากันในพีชคณิต ตัวดำเนินการที่เท่ากันในความหมายนี้ไม่จำเป็นต้องถูกเก็บเหมือนกัน การเปรียบเทียบจึงต้องใช้ความสัมพันธ์การสลับที่ เมธอด normal_ordered() ใช้ความสัมพันธ์เหล่านั้น: มันย้ายตัวดำเนินการสร้างทุกตัวไปไว้ทางซ้ายของตัวดำเนินการทำลายทุกตัว และเพิ่มพจน์ทุกครั้งที่สลับคู่บนโหมดเดียวกัน

>>> product = BosonOperator.from_dict({(ann(0), cre(0), ann(0), cre(0)): 1.0})
>>> ordered = product.normal_ordered()
>>> len(ordered)
5
>>> print(format(ordered.simplify()))
1.000000e0 +0.000000e0j * ()
3.000000e0 +0.000000e0j * (+0 -0)
1.000000e0 +0.000000e0j * (+0 +0 -0 -0)

ตัวดำเนินการที่จัดลำดับแล้วถูกคืนเป็นผลรวมที่ยังไม่รวมพจน์ มีห้าพจน์ที่เก็บไว้ ซึ่งลดเหลือสามหลังจาก simplify() รวมพวกมัน การจัดลำดับปกติไม่เคยทำให้พจน์หายไป: b†b†b^\dagger b^\dagger และปัจจัยซ้ำอื่นทุกตัวยังอยู่

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

>>> pair = BosonOperator.from_dict({(cre(0), cre(1), ann(0), ann(1)): 1.0})
>>> list(pair.normal_ordered().iter_terms())
[([(True, 1), (True, 0), (False, 1), (False, 0)], (1+0j))]
>>> list(pair.normal_ordered(sandwich=True).iter_terms())
[([(True, 0), (True, 1), (False, 1), (False, 0)], (1+0j))]

ตัวดำเนินการ == ทดสอบความเท่ากันแบบตรงตัวของพจน์ที่เก็บ โดยไม่มีความคลาดเคลื่อนและไม่ทำให้ง่ายขึ้น จึงอาจรายงานความต่างระหว่างตัวดำเนินการสองตัวที่เท่ากันทางคณิตศาสตร์ เมธอด equiv() นำผลต่างของตัวดำเนินการทั้งสองมาจัดลำดับปกติก่อน แล้วทดสอบว่าทุกสัมประสิทธิ์ต่ำกว่าค่าความคลาดเคลื่อน มันคือการเปรียบเทียบที่คุณแทบจะต้องการเสมอ:

>>> reordered = BosonOperator.from_dict({(cre(0), ann(0)): 1.0, (): 1.0})
>>> contracted = BosonOperator.from_dict({(ann(0), cre(0)): 1.0})
>>> contracted == reordered
False
>>> contracted.simplify() == reordered.simplify()
False
>>> contracted.equiv(reordered)
True

เมธอด simplify เพียงอย่างเดียวปล่อยให้สองรูปแยกกัน เพราะมันรวมเฉพาะพจน์ที่เขียนเหมือนกันเท่านั้น เช่นเดียวกัน is_hermitian() เปรียบเทียบตัวดำเนินการกับตัวร่วมเสริมในรูปจัดลำดับปกติ จึงรู้ว่า b b†+b†bb\,b^\dagger + b^\dagger b เป็นเฮอร์มีเชียนโดยไม่ต้องทำอะไรเพิ่ม

หมายเหตุ

การจัดลำดับปกติเป็นเอกลักษณ์ที่แน่นอนในพีชคณิตที่ยังไม่ตัดทอน และ equiv พึ่งพาสิ่งนั้น แต่ ไม่ใช่ เอกลักษณ์หลังการตัดทอน ตัวดำเนินการที่แมปแล้วขึ้นกับรูปที่คุณแมป ดังนั้นภาพที่แมปของ contracted และ reordered ข้างต้นจึงต่างกัน เฉพาะที่ระดับสูงสุดที่คงไว้ ดู ตัดทอนปริภูมิ Fock สำหรับขนาดของความต่างและวิธีเลือกรูป

จัดลำดับและกรองพจน์​

การจัดลำดับ พจน์ ของตัวดำเนินการใหม่ ต่างจากปัจจัยภายในพจน์ ไม่เปลี่ยนตัวดำเนินการ แต่อาจเปลี่ยนพฤติกรรมของอัลกอริทึมที่อ่านพจน์ตามลำดับ เช่นสูตรผลคูณแบบสุ่ม ฟังก์ชันของ qiskit_bosons.operators.terms คืนตัวดำเนินการใหม่และคงดัชนีกลุ่มที่ผูกกับพจน์ไว้

canonical_order() เรียงพจน์ตามลำดับคงที่ที่ขึ้นกับปัจจัยที่เขียนไว้เท่านั้น ตัวดำเนินการจึงอ่านเหมือนกันไม่ว่าประกอบขึ้นอย่างไร order_terms() เรียงตามคีย์ที่คุณให้ ซึ่งรับแต่ละพจน์เป็นทูเพิลที่ iter_terms() ให้:

>>> from qiskit_bosons.operators.terms import canonical_order, order_terms
>>> mixed = BosonOperator.from_dict({(cre(1), ann(0)): 1.0, (cre(0), ann(1)): 3.0, (): 2.0})
>>> list(canonical_order(mixed).iter_terms())
[([], (2+0j)), ([(True, 0), (False, 1)], (3+0j)), ([(True, 1), (False, 0)], (1+0j))]
>>> by_weight = order_terms(mixed, key=lambda term: abs(term[1]), reverse=True)
>>> [coeff for _, coeff in by_weight.iter_terms()]
[(3+0j), (2+0j), (1+0j)]

หากตัวดำเนินการมีดัชนีกลุ่ม (ดู จัดกลุ่มพจน์ตัวดำเนินการ: ใช้โครงสร้างของตัวดำเนินการ) ฟังก์ชัน group_order() จะทำให้แต่ละกลุ่มเป็นช่วงของพจน์ที่ต่อเนื่องกัน:

>>> from qiskit_bosons.operators.terms import group_order
>>> grouped = BosonOperator.from_dict({(cre(1), ann(0)): 1.0, (cre(0), ann(1)): 3.0, (): 2.0})
>>> grouped.groups = [1, 0, 1]
>>> group_order(grouped).groups
[0, 1, 1]

ตัวช่วยสุดท้ายลบพจน์แทนที่จะจัดลำดับใหม่ พจน์ที่เป็นผลคูณของตัวดำเนินการจำนวน bi†bib_i^\dagger b_i เพียงคูณแต่ละสถานะ Fock ด้วยเฟส ดังนั้น filter_diagonal_terms() จึงทิ้งค่าคงที่ ตัวดำเนินการจำนวน และผลคูณของมันได้ เมื่อเฟสนั้นไม่เกี่ยวกับสิ่งที่คุณคำนวณ มันเปลี่ยนตัวดำเนินการ ในที่เดิม และต้องการตัวดำเนินการที่จัดลำดับปกติ ซึ่งมันไม่ตรวจสอบ:

>>> from qiskit_bosons.operators.terms import filter_diagonal_terms
>>> model = BosonOperator.from_dict(
... {
... (cre(0), ann(1)): -1.0,
... (cre(1), ann(0)): -1.0,
... (cre(0), cre(0), ann(0), ann(0)): 0.5,
... (cre(0), ann(0)): 0.2,
... (): 0.1,
... }
... )
>>> filter_diagonal_terms(model)
>>> len(model)
2
>>> model.is_hermitian()
True

เหลือเพียงสองพจน์การกระโดด อันตรกิริยาบนไซต์และตัวดำเนินการจำนวนเป็นแนวทแยงในฐานการครอบครอง จึงถูกลบพร้อมกับค่าคงที่ โหมดที่ซ้ำในอันตรกิริยาถูกจัดการอย่างถูกต้อง: b0†b0†b0b0b_0^\dagger b_0^\dagger b_0 b_0 เป็นแนวทแยง ขณะที่ b0†b0†b0b_0^\dagger b_0^\dagger b_0 ไม่ใช่

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