Greenberger–Horne–Zeilinger (GHZ) State Fidelity

Greenberger–Horne–Zeilinger (GHZ) State Fidelity#

The aim of this benchmark is to show whether a GHZ state with high enough fidelity can be prepared such that the state is genuinely multipartite entangled. One can show that a fidelity larger than 0.5 is a sufficient condition (see Leibfried, D. et al., Creation of a six-atom ‘Schrödinger cat’ state. Nature 438, 639–642 (2005))

The benchmark currently offers two methods to estimate the fidelity:

  • Multiple quantum coherences (G. J. Mooney et al., Generation and verification of 27-qubit Greenberger-Horne-Zeilinger states in a superconducting quantum computer, J. Phys. Commun. 5, 095004 (2021))

  • Randomized measurements (Elben, A. et al., Statistical correlations between locally randomized measurements: A toolbox for probing entanglement in many-body quantum states, Phys. Rev. A 99, 052323 (2019))

Additionally, for a given set of n qubits, different circuits can be applied which lead to the same GHZ state. Currently there are the following implementations:

  • “naive”: The textbook ciruit of depth n, which starts from a Hadamrd gate on one qubit and entangles each additional qubit with a CNOT operation from the first.

  • “log_depth”: A logarithmic depth circuit utilizing parallel CNOT applications. Either the method in Cruz et al. https://arxiv.org/abs/1807.05572 or the method in Mooney et al. https://arxiv.org/abs/2101.08946 is used, depending on which yields the lower depth or the lower number of 2-qubit gates.

  • “tree”: An in-house logarithmic depth circuit utilizing calibration data of the CZ-fidelities and a tree-graph algorithm to find a circuit with minimal depth and high fidelity 2-qubit gates.

Note that the first two methods will always give the same circuit for the same qubit layout (and the same coupling map), while the “tree” method relies on the latest calibration fidelities and can give different circuits on different days. Thus for consistent comparisons one of the first two methods should be chosen, while for the best results, i.e. the largest possible GME entangled GHZ state, the tree-method is preferable.

from iqm.benchmarks.entanglement.ghz import *
backend = "fakeapollo"

Definition of the benchmark configuration#

The important parameters are:

  • custom_qubits_array: A list[list[int]] which includes all qubit layouts on which the benchmark is run.

  • shots: The number of shots for the fidelity measurement

  • fidelity_routine: Either “coherences” or “randomized_measurements”

  • rem: Boolean value that controls whether readout error mitigation is used

  • mit_shots: Whenever rem=True, this parameter controls the total number of shots used to calibrate readout error mitgation

  • num_RMs: The number of randomized measurement settings (only necessary when choosing fidelity_routine=randomized_measurements)

MINIMAL_GHZ = GHZConfiguration(
    state_generation_routine="tree",
            custom_qubits_array=[
                [18,19],
                [17,18,19],
                [0,1,3,4],
                [0,1,2,3,4],
                list(np.arange(10)),
            ],
    shots=1000,
    fidelity_routine="coherences", 
    rem=True,
    mit_shots=1000,
)

For thinking about which qubit layouts to use, the following visualization of the connectivity and CZ fidelities is helpful.

Requirements:

  • Access to the backend, in this example IQM Garnet.

  • An access token environment variable needs to be set via os.environ["IQM_TOKEN"] = <your_token>.

Use of the plot:

  • If the qubit_layouts argument is provided, the selected qubits are marked in orange.

  • CZ errors are indicated with edge width, thinner is better, where the edge width is given by wij=log(FCZij).

  • Each edge is also labeled with the width value.

  • Some graph layouts are predefined to match the layout as shown in IQM-Resonance. If the layout is not predefined, a graph in grid or star layout will be automatically generated, dependeing on the backend. Automatically generated graphs might need to be rerun a few times until a nice node layout is found.

from iqm.benchmarks.utils_plots import plot_layout_fidelity_graph
import os

print(f"Check if access token environment variable is set: {'IQM_TOKEN' in os.environ}")
cal_url = f"https://api.resonance.meetiqm.com/quantum-computers/v1/garnet/calibrations" 
qubit_layouts = [[0,1,3,4], [11,16,6]]
fig = plot_layout_fidelity_graph(cal_url, qubit_layouts = qubit_layouts)
Check if access token environment variable is set: True
../_images/3a2f42fd8dae61eccac479ec450f2914e51532118a2029d76a897b54ae745371.png

Running the benchmark#

benchmark_ghz = GHZBenchmark(backend, MINIMAL_GHZ)
run_ghz = benchmark_ghz.run()
2025-03-13 10:58:42,067 - iqm.benchmarks.logging_config - INFO - Now generating a 2-qubit GHZ state on qubits [18, 19]
2025-03-13 10:58:42,072 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:42,504 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:42,589 - iqm.benchmarks.logging_config - INFO - Submitting batch with 7 circuits corresponding to qubits [18, 19]
2025-03-13 10:58:42,600 - iqm.benchmarks.logging_config - INFO - Now generating a 3-qubit GHZ state on qubits [17, 18, 19]
2025-03-13 10:58:42,865 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:43,074 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:43,176 - iqm.benchmarks.logging_config - INFO - Submitting batch with 9 circuits corresponding to qubits [17, 18, 19]
2025-03-13 10:58:43,183 - iqm.benchmarks.logging_config - INFO - Now generating a 4-qubit GHZ state on qubits [0, 1, 3, 4]
2025-03-13 10:58:43,397 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:43,616 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:43,761 - iqm.benchmarks.logging_config - INFO - Submitting batch with 11 circuits corresponding to qubits [0, 1, 3, 4]
2025-03-13 10:58:43,769 - iqm.benchmarks.logging_config - INFO - Now generating a 5-qubit GHZ state on qubits [0, 1, 2, 3, 4]
2025-03-13 10:58:43,968 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:44,070 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:44,452 - iqm.benchmarks.logging_config - INFO - Submitting batch with 13 circuits corresponding to qubits [0, 1, 2, 3, 4]
2025-03-13 10:58:44,464 - iqm.benchmarks.logging_config - INFO - Now generating a 10-qubit GHZ state on qubits [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2025-03-13 10:58:44,646 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:44,972 - iqm.benchmarks.logging_config - INFO - Transpiling for backend IQMFakeApolloBackend with optimization level 3, sabre routing method including SQG optimization all circuits
2025-03-13 10:58:45,559 - iqm.benchmarks.logging_config - INFO - Submitting batch with 23 circuits corresponding to qubits [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2025-03-13 10:58:45,585 - iqm.benchmarks.logging_config - INFO - Retrieving all counts
2025-03-13 10:58:51,564 - iqm.benchmarks.logging_config - INFO - Applying readout error mitigation
2025-03-13 10:58:51,916 - iqm.benchmarks.logging_config - INFO - Retrieving all counts
2025-03-13 10:58:51,962 - iqm.benchmarks.logging_config - INFO - Applying readout error mitigation
2025-03-13 10:58:52,464 - iqm.benchmarks.logging_config - INFO - Retrieving all counts
2025-03-13 10:58:52,529 - iqm.benchmarks.logging_config - INFO - Applying readout error mitigation
2025-03-13 10:58:53,126 - iqm.benchmarks.logging_config - INFO - Retrieving all counts
2025-03-13 10:58:53,212 - iqm.benchmarks.logging_config - INFO - Applying readout error mitigation
2025-03-13 10:58:53,782 - iqm.benchmarks.logging_config - INFO - Retrieving all counts
2025-03-13 10:58:53,968 - iqm.benchmarks.logging_config - INFO - Applying readout error mitigation
result = benchmark_ghz.analyze()

Accessing the results#

To see individual fidelitiy and uncertainty values of a given qubit layout, one can filter the result.observations-list by layout as shown below.

The plot allows a comparison of all layout results with and without REM, where the data point description labels “L0”, “L1”, … enumerate the layouts in the order defined in the configuration.

qubit_layout = [0,1,3]
for observation in result.observations:
    if observation.identifier.string_identifier == str(qubit_layout):
        print(f"{observation.name}: {observation.value} +/- {observation.uncertainty}")
result.plot_all()
../_images/9c15d6d46af009acc54b721f6ada147126b886877ca548721d2f1f9108a7700a.png