퀸브 레이어 기반 백엔드
qiskit_addon_mpf.backends.quimb_layers
를 사용한 계층별 시간 진화 백엔드 quimb.
이 백엔드는 선택적 종속성이 설치된 경우에만 사용할 수 있습니다:
pip install "qiskit-addon-mpf[quimb]"LayerwiseEvolver | 의 특별한 경우 TEBDEvolver 레이어별 진화 모델을 기반으로 합니다. |
LayerModel | 시간 진화 상호작용의 레이어를 표현하기 위한 모델입니다. |
기본 방법
이 모듈은 TEBD 기반 모듈에서 제공하는 것과 유사한 시간 진화 백엔드를 제공합니다 quimb_tebd 모듈에서 제공하는 것과 유사한 시간 진화 백엔드를 제공합니다. 가장 큰 차이점은 이 모듈은 사용자가 제품 공식을 정의할 수 있는 완전한 유연성을 제공하므로 라이브러리에 내장된 옵션으로 제한되지 않는다는 것입니다 quimb 라이브러리에 내장된 옵션으로 제한하지 않는다는 것입니다.
이 모듈에서 제공하는 알고리즘의 핵심은 여전히 TEBD [1] 알고리즘입니다. 그러나 시간 진화 상태의 짝수 및 홀수 본드를 번갈아 업데이트하도록 강제하는 대신( quimb_tebd.TEBDEvolver.sweep()참조)이 구현은 본드를 번갈아 업데이트하는 책임을 여러 시간 진화 레이어의 정의에 아웃소싱합니다.
예를 들어 설명하는 것이 가장 좋습니다. 1차원 사이트 체인에서 작동하는 일반적인 해밀턴이 있다고 가정해 보겠습니다.
아래에서는 해밀턴의 파울리 항의 순서에 대해 매우 신중을 기했는데, 이는 나중에 시간 진화 회로의 구조에 직접적인 영향을 미치기 때문입니다.
>>> from qiskit.quantum_info import SparsePauliOp
>>> hamil = SparsePauliOp.from_sparse_list(
... [("ZZ", (i, i+1), 1.0) for i in range(1, 9, 2)] +
... [("Z", (i,), 0.5) for i in range(10)] +
... [("ZZ", (i, i+1), 1.0) for i in range(0, 9, 2)],
... num_qubits=10,
... )이제 2차 스즈키-트로터 공식을 사용하여 이 해밀턴의 시간 진화 회로를 살펴보겠습니다.
>>> from qiskit.synthesis import SuzukiTrotter
>>> from qiskit_addon_utils.problem_generators import generate_time_evolution_circuit
>>> circuit = generate_time_evolution_circuit(hamil, time=1.0, synthesis=SuzukiTrotter(order=2))
>>> circuit.draw("mpl")
<Figure size 956...x869... with 1 Axes>
위의 회로에서 레이어별 구조를 명확하게 확인할 수 있습니다. 아래 그림과 같이 회로를 여러 레이어로 분할하여 이를 더욱 강조할 수 있습니다(시각화를 쉽게 하기 위해 layers 을 단일 회로로 재결합하고 그 사이에 장벽을 두었습니다).
>>> from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types
>>> layers = slice_by_gate_types(circuit)
>>> combine_slices(layers, include_barriers=True).draw("mpl")
<Figure size 1374...x869... with 1 Axes>
중앙 레이어의 비대칭성은 키스킷의 SuzukiTrotter 공식을 구현한 결과입니다. 2차 형태에서는 해밀턴의 마지막 항의 두 하프타임 진화를 두 배 길이의 단일 항으로 결합한 것입니다. 이 회로를 트랜스파일하여 중앙의 두 레이어에 있는 모든 하위 게이트를 붕괴시킬 수도 있지만(마지막 예제처럼), 이 예제의 단순성을 위해 여기서는 그렇게 하지 않겠습니다.
위에 표시된 회로의 정확한 구조를 시뮬레이션하도록 Quimb의 TEBD 알고리즘에 지시하는 것은 불가능합니다. 그 이유는 미리 정의된 트로터 공식을 사용하여 시간 진화하는 전체 해밀턴만 제공되기 때문에 인터페이스의 한계 때문입니다. 그러나 이렇게 할 때 해밀턴식에서는 폴리 용어의 순서를 중요하게 다루지 않습니다(여기서처럼).
위의 예와 같이 Quimb에서 구현된 것과 다른 제품 공식 구조를 사용하여 시간 진화의 동적 MPF 계수를 계산하려는 경우 이 모듈에서 제공하는 시간 진화 알고리즘을 사용할 수 있습니다. 시간 진화를 모델링할 단일 모놀리식 해밀턴을 취하는 대신 LayerwiseEvolver 객체의 목록을 받아들입니다 LayerModel 객체 목록을 받아들이며, 각 객체는 제품 공식의 개별 레이어를 설명합니다. 이를 통해 사용자는 트로터 분해를 가장 세분화된 수준까지 유연하게 정의할 수 있습니다.
그러나 짝수 채권과 홀수 채권을 번갈아 업데이트하는 TEBD의 속성이 여전히 보장되도록 주의를 기울여야 합니다. 다행히도 최대 2큐비트 게이트로 구성된 양자 회로의 경우, 이 속성은 구성에 의해 충족됩니다.
코드 예
이 섹션에서는 위의 예제를 기반으로 사용자 정의 트로터 공식을 가져와 이를 사용하여 LayerwiseEvolver 를 만드는 방법을 설명합니다 quimb_tebd.TEBDEvolver 에 설명된 워크플로우에서 quimb_tebd.
이 모듈을 사용하는 전반적인 작업 흐름은 모듈의 quimb_tebd 모듈과 동일하므로 해당 지침도 반드시 읽어보세요.
간단히 말해, layers (위 참조)의 각 회로를 하나의 LayerModel 인스턴스로 변환해야 합니다. 이를 위해 from_quantum_circuit() 메서드를 사용할 수 있습니다.
>>> from qiskit_addon_mpf.backends.quimb_layers import LayerModel
>>> model0 = LayerModel.from_quantum_circuit(layers[0])
>>> layer_models = [model0]위의 코드에서 상호 배타적인 큐비트에 작용하는 2큐비트 게이트만 포함된 레이어(깊이 1의 레이어가 보장하는 레이어)의 변환이 얼마나 간단한지 확인할 수 있습니다.
그러나 단일 큐비트 게이트를 포함한 레이어에서는 더 주의해야 합니다. 그 이유는 TEBD 알고리즘의 기반이 되는 LayerwiseEvolver 는 짝수 본드와 홀수 본드를 번갈아 업데이트해야 하기 때문입니다. 단일 큐비트 게이트는 한 사이트에 적용되는 것이 아니라 반으로 분할되어 양쪽의 본드에 적용되기 때문에 모든 큐비트에 작용하는 단일 큐비트 게이트 레이어는 이 가정을 깨뜨릴 수 있습니다.
이 문제를 피하기 위해 단일 큐비트 게이트로만 구성된 레이어를 가져와 짝수 본드에 한 번, 홀수 본드에 한 번 두 번 적용하면 됩니다.
>>> model1a = LayerModel.from_quantum_circuit(layers[1], keep_only_odd=True)
>>> model1b = LayerModel.from_quantum_circuit(layers[1], keep_only_odd=False)
>>> layer_models.extend([model1a, model1b])이제 2큐비트와 단일 큐비트 게이트로 구성된 레이어를 처리하는 방법을 알았으니 나머지 레이어를 변환할 수 있습니다.
>>> for layer in layers[2:]:
... num_qubits = len(layer.data[0].qubits)
... if num_qubits == 2:
... layer_models.append(LayerModel.from_quantum_circuit(layer))
... else:
... layer_models.append(
... LayerModel.from_quantum_circuit(layer, keep_only_odd=True)
... )
... layer_models.append(
... LayerModel.from_quantum_circuit(layer, keep_only_odd=False)
... )
>>> assert len(layer_models) == 8결국 8개의 LayerModel4개 2큐비트 레이어에 각각 하나씩, 2개의 단일 큐비트 레이어에 각각 2개씩 총 8개의 큐비트가 있습니다.
마지막으로, 프로토콜을 정의할 수 있습니다 ApproxEvolverFactory 프로토콜을 정의할 수 있습니다 setup_dynamic_lse() 함수 내에서 사용할 프로토콜을 정의할 수 있습니다.
>>> from functools import partial
>>> from qiskit_addon_mpf.backends.quimb_layers import LayerwiseEvolver
>>> approx_evolver_factory = partial(
... LayerwiseEvolver,
... layers=layer_models,
... split_opts={"max_bond": 10, "cutoff": 1e-5},
... )이 워크플로에서는 트로터 공식에 사용되는 시간 단계를 아직 고정하지 않았다는 점에 유의해야 합니다. 또한 트로터 공식의 반복은 단 한 번만 설정했으며, 나머지는 내부 DynamicMPF 알고리즘에 의해 실행되므로 setup_dynamic_lse().
물론 이 기능을 사용하여 ExactEvolverFactory. 하지만 믹스 앤 매치할 수도 있습니다 quimb_layers.LayerwiseEvolver 와 quimb_tebd.TEBDEvolver.
자원
[1]: https://en.wikipedia.org/wiki/Time-evolving _block_decimation