주 콘텐츠로 건너뛰기
이 프로젝트는 베타 단계입니다. 버그를 발견하셨나요? GitHub 이슈 만들기. 질문이나 아이디어가 있으신가요? Discussions에서 질문하기 — 피드백을 기다립니다!
이 페이지의 번역 품질은 어떻습니까?

이 패키지와 ffsim의 관계

중요

이 가이드의 개념은 Python API에서만 사용할 수 있습니다.

ffsim과 이 패키지는 서로 겹치지 않고 하나의 기준선을 따라 역할을 나눕니다.

ffsim이 담당하는 것qiskit-fermions가 담당하는 것
결합 클러스터 진폭이나 매개변수 벡터로 만들어지는 고수준 앤자츠 연산자(UCJOpSpinBalanced, UCCSDOpRestrictedReal 및 그 유사 연산자)이러한 연산자가 변환되는 페르미온 회로(FermionicCircuit)와, 임의의 페르미온-큐비트 인코딩에 따른 큐비트 회로로의 트랜스파일
입자 수가 고정된 압축 공간에서의 빠른 시뮬레이션회로를 구성하는 데 쓰이는 매퍼 프레임워크와 연산자 데이터 구조

이러한 구분의 실질적인 결과는 양방향으로 나타납니다. 앤자츠 수학은 ffsim에 있으므로 UCJ와 UCC는 ffsim 연산자를 입력으로 직접 받습니다. 반대로 ffsim 자체의 Qiskit 게이트는 Jordan-Wigner 변환에 한정되므로, ffsim 앤자츠 연산자를 다른 인코딩으로 낮추는 것이 이를 이 패키지로 가져오면 얻는 이점입니다.

시뮬레이션은 두 패키지가 만나는 지점이며, 이 가이드에서 그 방법을 설명합니다. ffsim은 이 패키지의 시뮬레이션 백엔드이며, 래퍼가 아니라 자체 프로토콜을 통해 연결됩니다. SKQD 가이드는 ffsim.apply_unitary(), ffsim.linear_operator(), ffsim.sample_state_vector()를 FermionicCircuit객체와 FermionOperator객체에 변환 단계 없이 직접 호출합니다.

ffsim의 시뮬레이션 인터페이스에 연결하기​

ffsim은 입자 수와 spin-Z 보존을 활용해 일반적인 2n2^n차원 큐비트 상태 벡터보다 더 간결하게 상태 벡터를 표현하는, 페르미온 양자 회로를 위한 고성능 시뮬레이터입니다. ffsim은 어떤 객체든 시뮬레이션 체계에 참여하도록 구현할 수 있는 프로토콜을 정의합니다(같은 설계를 따르는 이 패키지 자체의 프로토콜은 qiskit_fermions.protocols 참고).

이 패키지는 해당 인터페이스를 구현합니다. qiskit_fermions.circuit.library의 모든 페르미온 게이트는 _apply_unitary_를 제공하고, FermionOperator는 _linear_operator_와 _trace_를 제공합니다. 이 덕분에 이 패키지의 연산자와 회로가 ffsim과 호환되어, ffsim의 도구가 변환 단계 없이 이들에 바로 작동합니다. ffsim.apply_unitary()는 FermionicCircuit을 처음부터 끝까지 시뮬레이션할 수 있고, ffsim.linear_operator()는 FermionOperator를 대각화할 수 있으며, ffsim.sample_state_vector()와 같은 샘플링 유틸리티(SKQD 가이드에서 시뮬레이션된 상태 벡터를 측정 카운트로 바꾸는 데 사용)도 수정 없이 작동합니다.

_linear_operator_가 반환하는 것은 일반적인 SciPy LinearOperator이므로, 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을 사용하는 사용자는 다른 시뮬레이션 API를 배우지 않고도 이 패키지의 게이트와 연산자를 섞어 쓸 수 있습니다.

ffsim은 선택적 의존성입니다​

ffsim은 선택적 extra(pip install "qiskit-fermions[ffsim]", 또는 [all]을 통한 간접 설치)로 선언되어 있으며, 런타임에 HAS_FFSIM으로 보호됩니다(위에서 설명한 대로). 이를 설치하면 시뮬레이션을 사용할 수 있습니다. ffsim.SupportsLinearOperator와 ffsim.SupportsTrace는 이 패키지의 FermionOperator를 ffsim.FermionOperator로 변환하는 방식으로 구현되므로, ffsim이 없으면 MissingOptionalLibraryError가 발생합니다. 시뮬레이션하지 않는 모든 작업(연산자 구성, 매핑, 결과 회로 트랜스파일)에는 ffsim이 전혀 필요하지 않습니다.

페르미온 시뮬레이션은 입자 수가 고정된 섹터에서 이루어집니다​

_apply_unitary_와 _linear_operator_는 모두 nelec 인수를 받으며, 일반 큐비트 시뮬레이터가 사용하는 2num_modes2^{\text{num\_modes}}차원 전체 공간이 아니라 해당 (norb, nelec) 섹터의 입자 수가 고정된 행렬식 기저에 대해 상태 벡터를 표현합니다. 이는 ffsim(그리고 간접적으로 PySCF)의 FCI 공간 설정을 그대로 따른 것입니다. 이 공간은 훨씬 작지만(크기가 2의 거듭제곱이 아니라 이항 계수의 곱입니다) 엄격한 제약이 따릅니다. 입자 수(스핀이 있는 경우에는 각 스핀 종의 입자 수도 각각)를 보존하는 연산자와 게이트만 이 공간에서 표현할 수 있습니다. 진폭을 다른 입자 수로 옮기게 되는 연산자는 그 진폭을 둘 곳이 없습니다.

ffsim은 이러한 연산자를 아예 거부하는 방식으로 이를 해결합니다. 이런 연산자를 선형 연산자로 변환하면 어떤 보존 법칙이 깨지는지를 알려 주는 ValueError가 발생합니다. 입자 수를 보존하지 않는 항이 있는 해밀토니안 HH에 대해 exp⁡(−itH)\exp(-i t H)를 적용하면 유니터리여야 할 것이 비유니터리이고 물리적으로 의미 없는 사상이 되어 버리므로, 이것이 올바른 기본 동작입니다.

  • 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 공간의 대가입니다. 알고리즘에 입자 수를 바꾸는 연산자(예: 큐비트 기반 오류 채널, 또는 항별로 입자 수를 보존하지 않는 매핑된 해밀토니안용 연산자)가 필요하다면, 먼저 큐비트로 트랜spile한 다음 결과로 나온 QuantumCircuit을 큐비트 수준 시뮬레이터로 시뮬레이션하세요. 어떤 트랜spile 경로든 사용할 수 있습니다. 페르미온 회로 가이드와 트랜spile 가이드에서 더 자세히 다루지만, generate_preset_jw_pass_manager()가 무난한 기본 선택입니다.

스핀이 있는 시스템의 블록 스핀 규약​

nelec의 타입은 int | tuple[int, int]이며, 별도의 플래그가 아니라 이 타입이 지원되는 모드 배치 중 하나를 결정합니다.

  • int는 스핀 없는 해석을 선택합니다. norb개의 모드는 그대로 스핀 없는 오비탈로 취급되며, nelec은 전체 입자 수입니다.

  • 쌍 (n_alpha, n_beta)는 고정된 블록 스핀 규약에 따라 2 * norb개 모드의 스핀이 있는 해석을 선택합니다. 모드 0 .. norb는 알파(스핀 업) 오비탈이고 모드 norb .. 2 * norb는 베타(스핀 다운) 오비탈입니다. 각 스핀 종은 독립적으로 보존됩니다. 알파 전용 항은 알파 모드 사이에서 전자를 옮길 수 있지만 베타 모드로는 절대 옮기지 못하며, 그 반대도 마찬가지입니다.

이 분기는 이 패키지의 모든 ffsim 프로토콜 진입점(Gate 생성자, _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()를 함께 사용해 이 패키지의 Gate로 만든 회로를 샘플링하고, ffsim.linear_operator()를 통해 해밀토니안 기댓값을 평가하는 방법을 확인해 보세요(이는 여기서 설명한 것과 같은 _linear_operator_ 프로토콜 메서드를 기반으로 합니다).

  • 나머지 절반인 ffsim ansatz 연산자를 이 패키지의 트랜spile 파이프라인에 통과시켜 디바이스 커플링 맵에 올리는 과정은 LUCJ 가이드를 따라가며 확인해 보세요.

  • 시뮬레이션 호출 밖에서 사용하는, 스핀과 무관한 일반 모드 인덱싱은 페르미온 회로 가이드를 읽어 보세요.

  • 페르미온 공간을 벗어나는 방법은 트랜spile 가이드를 읽어 보세요​

    큐비트에서 시뮬레이션하는 방법을 다루며, 입자 수를 보존하지 않는 연산자에는 이것이 필요합니다.

  • 이 패키지가 정의하는 전체 프로토콜 목록은 qiskit_fermions.protocols에서 살펴보세요. ffsim과 무관한 변환 프로토콜(SupportsFermionOperator, SupportsMajoranaOperator)도 포함되어 있습니다.

  • ffsim이 담당하는 워크플로, 특히 UCJ ansatz 구성과 변분 최적화는 ffsim 자체 가이드를 읽어 보세요. 이 가이드들이 다루는 파라미터 벡터는 UCJ와 UCC가 그들이 만드는 연산자를 통해 받아들이는 것입니다.