Skip to main content
IBM Quantum Platform

빠른 시작

이 가이드에서는 해당 qiskit-addon-sqd 패키지의 최소 실행 가능한 예제를 보여줍니다. 우리는 화학 해밀토니안의 기저 상태를 근사하는 양자 회로에서 추출한 잡음이 포함된 샘플을 정제하기 위해 샘플 기반 양자 대각화(SQD)를 사용합니다. 기저 상태 에너지는 정제된 표본들로 구성된 부분공간에서 해밀토니안을 대각화함으로써 근사화된다.

양자 하드웨어에서 실행되는 엔드투엔드 워크플로우에 대한 자세한 설명은 다음 튜토리얼을 참고하세요:


1. SQD에 필요한 입력 데이터를 준비합니다

먼저, 화학 해밀토니안과 그 기저 상태를 근사하는 양자 회로를 정의합니다. 이 예제에서 연구한 시스템은 두 개의 코어 궤도가 고정된 STO-3G 기저에서 평형 기하 구조를 갖는 N₂입니다. 이 시스템에는 개의 공간 궤도와 10 개의 전자가 있으며 8 , 이는 양자 회로가 개의 16 큐비트로 정의됨을 의미합니다. 여기서 큐비트 0-7 는 스핀-업 궤도를, 큐비트 8-15 는 스핀-다운 궤도를 나타냅니다. 5``10이 시스템은 개의 전자를 가진 10 폐쇄 껍질 시스템이므로, 물리적으로 타당한 각 샘플의 해밍 가중치는 여야 함을 알 수 있으며, 이때 비트열의 좌우 양쪽 절반 모두의 해밍 가중치는 이다.

from pyscf import ao2mo, gto, mcscf, scf

# Construct the Hamiltonian, pull out integrals and other information about the system
mol = gto.M(
    atom="N 0 0 0; N 0 0 1.09768", basis="sto-3g", spin=0, charge=0, verbose=0
)
mf = scf.RHF(mol).run()
cas = mcscf.CASCI(mf, ncas=8, nelecas=10)
hcore, nuclear_repulsion_energy = cas.get_h1eff()
eri = cas.get_h2eff()
num_orbitals = cas.ncas
eri = ao2mo.restore(1, eri, num_orbitals)
n_alpha, n_beta = cas.nelecas
nelec = (n_alpha, n_beta)

print(
    f"Spatial orbitals: {num_orbitals}\nQubits: {num_orbitals * 2}\nElectrons (alpha, beta): {nelec}"
)

Output:

Spatial orbitals: 8
Qubits: 16
Electrons (alpha, beta): (5, 5)

2. 노이즈가 포함된 샘플 생성하기

실제 워크플로우에서는 안자츠 회로를 설계하고, 하드웨어에 맞게 최적화한 다음, QPU에서 샘플링하게 됩니다. 여기서는 그 과정을 생략하고, 대신 균일하게 무작위 비트열을 생성합니다 10,000 . 비록 우리의 샘플에는 실제 기저 상태에 대한 정보가 포함되어 있지 않지만, SQD 프로토콜이 이러한 샘플을 반복적으로 정제하고 대각화한 뒤, 각 반복 단계에서 구한 에너지를 다음 단계의 비트열 정제에 반영함으로써 여전히 진정한 기저 상태를 복원할 수 있음을 보게 될 것입니다. 기저 상태를 포함하는 부분공간이 충분히 작아서 정확히 계산할 수 있기 때문에, 우리는 결국 이러한 방식으로 정확한 기저 상태를 복원할 수 있다. 5구체적으로, 각 비트열(8 bits)의 각 반쪽이 해밍 가중치 를 가져야 한다는 사실을 알고 있으므로, 이 시스템의 전체 힐베르트 부분공간은 크기 (85)2=3136\binom{8}{5}^2=3136 임을 알 수 있다.

import numpy as np
from qiskit_addon_sqd.counts import generate_bit_array_uniform

# Generate some uniformly-random bitstrings to simulate QPU samples
rng = np.random.default_rng(24)
bit_array = generate_bit_array_uniform(
    10_000, num_orbitals * 2, rand_seed=rng
)
print(
    f"Generated {bit_array.num_shots} uniformly-random, {bit_array.num_bits}-qubit samples."
)

Output:

Generated 10000 uniformly-random, 16-qubit samples.

3. SQD를 이용한 후처리

SQD 알고리즘의 목적은 QPU에서 추출한 잡음이 섞인 샘플을 정제하고, 궁극적으로 해당 정제된 샘플들이 생성하는 부분공간에서 해밀토니안을 대각화하는 데 있습니다. 이는 다음과 같이 반복적으로 수행됩니다:

  • 스핀-업 및 스핀-다운 하위 시스템 모두에서 올바른 입자 수를 가진 샘플만을 사후 선택하여 샘플을 정제합니다
  • 정제된 샘플들이 생성하는 작은 부분공간에서 대각화를 수행하고, 가장 좋은(가장 낮은) 에너지를 나타내는 부분공간에 대한 정보를 수집한다.
  • 반복될 때마다,
    • 입자 수가 잘못된 샘플의 비트를 확률적으로 뒤집어 노이즈가 많은 샘플을 정제합니다. 확률은 가장 최근의 대각화 과정에서 얻은 부분공간 정보를 사용하여 계산됩니다.
    • 정제된 표본들이 생성하는 작은 부분공간에서 대각화하기
    • 최적(최저) 에너지를 갖는 부분공간에 대한 정보를 수집한다

출력 결과를 통해, 알고리즘이 회 반복 후 6 정확한 기저 상태 에너지로 수렴하며, 차원 (85)2=3136\binom{8}{5}^2=3136 인 전체 힐베르트 부분공간에 대해 대각화가 수행됨을 알 수 있다. 물론, 전체 부분공간에 대한 대각화는 일반적으로 실현하기 어려우므로, 기저 상태의 지지 영역이 드문 시스템일수록 SQD와 같은 부분공간 대각화 기법의 이점을 가장 크게 누릴 가능성이 높다.

diagonalize_fermionic_hamiltonian 함수에 대한 자세한 내용은 API 문서를 참조하십시오.

from functools import partial

from pyscf import fci
from qiskit_addon_sqd.fermion import (
    SCIResult,
    diagonalize_fermionic_hamiltonian,
    solve_sci_batch,
)

exact_energy, _ = fci.direct_spin1.kernel(
    hcore, eri, int(num_orbitals), nelec
)
exact_energy += nuclear_repulsion_energy
print(f"Exact (FCI) reference energy: {exact_energy:.6f} Ha\n")

sci_solver = partial(solve_sci_batch, spin_sq=0.0, max_cycle=200)

result_history = []


def callback(results: list[SCIResult]):
    result_history.append(results)
    iteration = len(result_history)
    print(f"Iteration {iteration}")
    for i, result in enumerate(results):
        error = result.energy + nuclear_repulsion_energy - exact_energy
        print(f"  Subsample {i}")
        print(f"    Energy: {result.energy + nuclear_repulsion_energy:.6f}")
        print(
            f"    Subspace dimension: {np.prod(result.sci_state.amplitudes.shape)}"
        )
        print(f"    Error vs exact: {error:.6f} Ha")


samples_per_batch = 20
result = diagonalize_fermionic_hamiltonian(
    hcore,
    eri,
    bit_array,
    samples_per_batch=samples_per_batch,
    norb=num_orbitals,
    nelec=nelec,
    occupancies_tol=1e-7,
    max_iterations=30,
    sci_solver=sci_solver,
    symmetrize_spin=True,
    callback=callback,
    seed=np.random.default_rng(32),
)

Output:

Exact (FCI) reference energy: -107.652521 Ha

Iteration 1
  Subsample 0
    Energy: -106.908481
    Subspace dimension: 784
    Error vs exact: 0.744040 Ha
Iteration 2
  Subsample 0
    Energy: -106.934921
    Subspace dimension: 1764
    Error vs exact: 0.717600 Ha
Iteration 3
  Subsample 0
    Energy: -106.953430
    Subspace dimension: 2209
    Error vs exact: 0.699091 Ha
Iteration 4
  Subsample 0
    Energy: -107.651946
    Subspace dimension: 2916
    Error vs exact: 0.000575 Ha
Iteration 5
  Subsample 0
    Energy: -107.652003
    Subspace dimension: 3025
    Error vs exact: 0.000518 Ha
Iteration 6
  Subsample 0
    Energy: -107.652521
    Subspace dimension: 3136
    Error vs exact: 0.000000 Ha
Iteration 7
  Subsample 0
    Energy: -107.652521
    Subspace dimension: 3136
    Error vs exact: 0.000000 Ha
이 페이지가 도움이 되었습니까?
GitHub에서 버그, 오타를 보고하거나 컨텐츠를 요청하십시오.