إزاي الحزمة دي بترتبط بـ ffsim
المفاهيم في هذا الدليل متاحة في واجهة Python البرمجية فقط.
ffsim والحزمة دي بيقسموا الشغل بدل ما يتداخلوا، على خط واحد:
| ffsim بتمتلك | qiskit-fermions بتمتلك |
|---|---|
مُشغّلات الـ ansatz عالية المستوى (UCJOpSpinBalanced، UCCSDOpRestrictedReal وأخواتهم)، المبنية من سعات coupled-cluster أو متجه معاملات | الدائرة الفرميونية (FermionicCircuit) اللي المُشغّلات دي بتتحول ليها، وترجمتها لدائرة كيوبتات تحت أي ترميز فرميون-لكيوبت |
| محاكاة سريعة في فضاء مدمج بعدد جسيمات ثابت | إطار الـ mapper وهياكل بيانات المُشغّلات اللي الدائرة بتتبني منها |
النتيجة العملية بتمشي في الاتجاهين. رياضيات الـ ansatz موجودة في ffsim، فـ UCJ وUCC بياخدوا مُشغّل ffsim مباشرةً كمدخل. وبالعكس، بوابات Qiskit الخاصة بـ ffsim مخصصة لتحويل Jordan-Wigner، فخفض واحد من مُشغّلات الـ ansatz بتاعتها عبر ترميز مختلف هو اللي بيجيبه لك الجيب هنا.
المحاكاة هي المكان اللي الاتنين بيتقابلوا فيه، والدليل ده بيشرح إزاي. ffsim هي الـ backend بتاع المحاكاة في الحزمة دي، بيتوصل ليها عبر بروتوكولاتها الخاصة مش عبر wrapper: دليل SKQD بيستدعي ffsim.apply_unitary()، ffsim.linear_operator()، وffsim.sample_state_vector() مباشرةً على كائنات FermionicCircuitوكائنات FermionOperator، من غير خطوة تحويل.
التوصيل بواجهة المحاكاة في ffsim
ffsim هو محاكي عالي الأداء للدوائر الكمّية الفرميونية بيستغل حفظ عدد الجسيمات وسبين-Z لتمثيل متجهات الحالة بشكل أكثر إحكامًا من متجه حالة كيوبتات عام ذي بُعد . بيعرّف بروتوكولات تقدر أي كائن ينفّذها عشان يشارك في آلية المحاكاة بتاعته (شوف qiskit_fermions.protocols للبروتوكولات الخاصة بالحزمة دي، واللي بتتبع نفس التصميم):
-
ffsim.SupportsApplyUnitary، عن طريق الدالة_apply_unitary_(vec, norb, nelec, copy)، بتطبّق الكائن كوحدوي على متجه حالة بعدد جسيمات ثابت -
ffsim.SupportsLinearOperator، عن طريق الدالة_linear_operator_(norb, nelec)، بترجّع عرضscipy.sparse.linalg.LinearOperatorللكائن على نفس القطاع ده -
ffsim.SupportsTrace، عن طريق الدالة_trace_(norb, nelec)، بترجّع أثر الكائن على القطاع ده.
الحزمة دي بتنفّذ الواجهة دي: كل بوابة فرميونية في qiskit_fermions.circuit.library بتوفّر _apply_unitary_، وFermionOperator بيوفّر _linear_operator_ و_trace_. ده اللي بيخلّي مُشغّلات ودوائر الحزمة دي متوافقة مع ffsim، فأدواتها بتشتغل عليهم بشكل أصلي، من غير خطوة تحويل. ffsim.apply_unitary() تقدر تحاكي FermionicCircuit من أولها لآخرها، وffsim.linear_operator() تقدر تقطّر FermionOperator، وأدوات العيّنات زي ffsim.sample_state_vector() (المستخدمة في دليل SKQD لتحويل متجه حالة محاكى لعدّادات قياس) بتشتغل من غير تعديل.
اللي بترجّعه _linear_operator_ هو LinearOperator عادي من SciPy، فـ scipy.sparse.linalg.eigsh() وأخواتها بتشتغل عليه كمان.
>>> import ffsim
>>> import numpy as np
>>>
>>> from qiskit_fermions.circuit import FermionicCircuit
>>> from qiskit_fermions.circuit.library import Evolution
>>> from qiskit_fermions.operators import FermionOperator, ann, cre
>>>
>>> norb, nelec = 2, (1, 1)
>>> hamiltonian = FermionOperator.from_terms([
... ([cre(0), ann(1)], 0.5),
... ([cre(1), ann(0)], 0.5),
... ])
>>>
>>> circuit = FermionicCircuit(2 * norb)
>>> circuit.append(Evolution(2 * norb, hamiltonian, time=1.0), circuit.modes)
>>>
>>> reference = ffsim.hartree_fock_state(norb, nelec)
>>> state = ffsim.apply_unitary(reference, circuit, norb=norb, nelec=nelec) # native ffsim call
الربط عبر بروتوكولات ffsim هو اللي بيجيب ده: منظومتها النشطة التطوير من أدوات المحاكاة والعيّنات بتنطبق على دوائر ومُشغّلات الحزمة دي من غير تغيير، والمستخدمين اللي شغالين أصلًا مع ffsim يقدروا يخلطوا بوابات ومُشغّلات الحزمة دي من غير ما يتعلموا واجهة محاكاة تانية.
ffsim اعتماد اختياري
ffsim متعرّفة كإضافة اختيارية (pip install "qiskit-fermions[ffsim]"، أو بشكل متعدٍّ عبر [all])، ومحروسة وقت التشغيل بـ HAS_FFSIM (زي ما اتوضّح فوق). تثبيتها بيفتح المحاكاة: ffsim.SupportsLinearOperator وffsim.SupportsTrace بيتنفّذوا بتحويل FermionOperator بتاع الحزمة دي لـ ffsim.FermionOperator، فمن غير ffsim بيرفعوا MissingOptionalLibraryError. كل اللي مش بيحاكي (بناء المُشغّلات، وتحويلها، وترجمة الدوائر الناتجة) مش محتاج منها حاجة.
المحاكاة الفرميونية بتعيش في قطاع عدد جسيمات ثابت
كل من _apply_unitary_ و_linear_operator_ بياخدوا معامل nelec وبيمثّلوا متجه الحالة على أساس المحددات بعدد جسيمات ثابت للقطاع (norb, nelec) ده، عاكسين إعداد فضاء FCI بتاع ffsim (وبالتبعية PySCF)، بدل الفضاء الكامل ذي البُعد اللي محاكي كيوبتات عام هيستخدمه. ده فضاء أصغر بكتير (حجمه حاصل ضرب معاملات ثنائية الحد مش أس لاتنين)، لكن جاي معاه قيد صارم. المُشغّلات والبوابات اللي بتحافظ على عدد الجسيمات بس (وفي الحالة ذات السبين، على عدد جسيمات كل نوع سبين على حدة) هي اللي تتمثّل فيه. المُشغّل اللي فعله هينقل السعة لعدد جسيمات مختلف مالوش مكان يحطها فيه.
ffsim بتحل ده برفض المُشغّل ده تمامًا: تحويل واحد منهم لمُشغّل خطي بيرفع ValueError بيسمّي قانون الحفظ اللي بيفشل. ده الافتراضي الصح، لأن تطبيق لهاميلتوني فيه حد مش بيحافظ على عدد الجسيمات هيحوّل اللي كان المفروض يكون وحدوي لتطبيق غير وحدوي وملوش معنى فيزيائي.
-
Evolutionبتظهر الرفض ده من المُشغّل اللي بتطوّره. -
تتحقق
OrbitalRotationمن أن مصفوفة الدوران (المضمَّنة) الخاصة بها قطرية الكتل عبر تقسيم ألفا/بيتا في حالة الأنظمة ذات السبين، وتُطلقValueErrorإذا كانت تخلط بين قطاعات السبين.
>>> from qiskit_fermions.circuit.library import Evolution
>>>
>>> non_conserving = FermionOperator.from_terms([([cre(0), cre(1)], 1.0)]) # creates 2 particles
>>> gate = Evolution(2 * norb, non_conserving, time=1.0)
>>>
>>> try:
... gate._apply_unitary_(reference, norb, nelec, copy=True)
... except ValueError as exc:
... print("rejected:", exc)
rejected: The given FermionOperator could not be converted to a LinearOperator because it does not conserve particle number and the z component of spin. Conserves particle number: False Conserves spin z: False
لذلك فإن المحاكاة التي لا تحافظ على عدد الجسيمات بعيدة المنال في الفضاء الفرميوني، بحكم تصميم تمثيل القطاع الثابت، وهذا هو ثمن فضاء FCI المضغوط الذي يجعل المحاكاة الفرميونية عملية أصلاً. إذا كانت خوارزميتك تحتاج إلى مؤثرات تنتهك عدد الجسيمات (مثلاً قناة خطأ أصلية على مستوى الكيوبت، أو مؤثر مبني لهاملتونيان مُحوَّل لا يحافظ على أعداد الجسيمات حدًّا بحد)، فحوِّله إلى كيوبتات أولاً (transpile) ثم حاكِ QuantumCircuit الناتجة بمحاكي على مستوى الكيوبت بدلاً من ذلك. أي مسار تحويل يصلح لهذا؛ يتناول دليلا الدارة الفرميونية والتحويل (transpilation) المزيد من التفاصيل، لكن generate_preset_jw_pass_manager() خيار افتراضي معقول.
اصطلاح السبين الكتلي للأنظمة ذات السبين
نوع nelec هو int | tuple[int, int]، ونوعه، وليس علَمًا منفصلاً، هو الذي يحدد أحد تخطيطات الأنماط المدعومة:
-
العدد الصحيح int يحدد التفسير عديم السبين. تُعامَل الأنماط
norbمباشرةً كمدارات عديمة السبين، وnelecهو العدد الكلي للجسيمات. -
الزوج pair
(n_alpha, n_beta)يحدد التفسير ذا السبين لعدد2 * norbمن الأنماط وفق اصطلاح السبين الكتلي الثابت. الأنماط0 .. norbهي مدارات ألفا (سبين لأعلى) والأنماطnorb .. 2 * norbهي مدارات بيتا (سبين لأسفل). يُحفَظ كل نوع من السبين بشكل مستقل؛ يمكن لحد خاص بألفا فقط أن ينقل إلكترونًا بين أنماط ألفا لكنه لا ينقله أبدًا إلى نمط بيتا، والعكس صحيح.
يحدث هذا التوزيع عند كل نقطة دخول لبروتوكول ffsim في هذه الحزمة (منشئات البوابات، وتطبيقات _apply_unitary_placed_، وتجميع القطاعات في نواة Rust الأصلية)، وهو الاصطلاح المستخدم في دليلي LUCJ وSKQD (مثلاً، تملأ InitializeModes.from_hartree_fock() إشغالات ألفا في الأنماط 0 .. n_alpha وإشغالات بيتا في الأنماط norb .. norb + n_beta). ومن المفيد مقارنة ذلك بوحدة qiskit_fermions.operators وبـ FermionicCircuit عمومًا، اللتين تستخدمان فهارس أنماط عامة دون أي دلالة سبين جوهرية (راجع دليل الدارة الفرميونية). لا يُفرَض معنى السبين الكتلي إلا عند تمرير nelec ذي سبين إلى استدعاء محاكاة، وليس مدمجًا في تمثيل المؤثر أو الدارة نفسه.
>>> from qiskit_fermions.circuit.library import InitializeModes
>>>
>>> norb, nelec = 3, (2, 1)
>>> init = InitializeModes.from_hartree_fock(norb, nelec)
>>> print([bool(occ) for occ in init.occupation]) # alpha modes 0,1; beta mode 3 (= norb + 0)
[True, True, False, True, False, False]
الخطوات التالية
-
اطّلع على دليل SKQD لترى كيف تُستخدم
ffsim.apply_unitary()وffsim.sample_state_vector()معًا لأخذ عينات من دارات مبنية من بوابات هذه الحزمة، ولتقييم القيمة المتوقعة لهاملتونيان عبرffsim.linear_operator()(التي تعتمد بدورها على طريقة البروتوكول_linear_operator_الموصوفة هنا). -
اطّلع على دليل LUCJ للنصف الآخر من القصة: أخذ مؤثر ansatz من ffsim عبر مسار التحويل (transpilation) في هذه الحزمة ثم إلى خريطة اقتران الجهاز.
-
اقرأ دليل الدارة الفرميونية لمعرفة فهرسة الأنماط العامة غير المرتبطة بالسبين المستخدمة خارج استدعاءات المحاكاة.
-
اقرأ دليل التحويل (transpilation) لمعرفة كيفية مغادرة الفضاء الفرميوني
والمحاكاة على الكيوبتات، وهو أمر مطلوب للمؤثرات التي لا تحافظ على عدد الجسيمات.
-
تصفّح
qiskit_fermions.protocolsللاطلاع على الكتالوج الكامل للبروتوكولات التي تعرّفها هذه الحزمة، بما فيها بروتوكولات التحويل (SupportsFermionOperator،SupportsMajoranaOperator) التي لا علاقة لها بـ ffsim. -
اقرأ أدلة ffsim الخاصة لمعرفة سير العمل الذي تملكه، وخصوصًا بناء ansatz من نوع UCJ وتحسينه تغايُريًّا. متجهات المعاملات التي تقودها تلك الأدلة هي ما تقبله
UCJوUCCعبر المؤثرات التي تبنيانها.