From 88a3a179e73948d15193286a4a0f77f4bc2ce7c8 Mon Sep 17 00:00:00 2001 From: Christina Lee Date: Fri, 10 Jan 2025 15:52:04 -0500 Subject: [PATCH] Updates to quantum volume and how to use qiskit (#1289) Gets the Quantum Volume and how to use qiskit demos working --------- Co-authored-by: Astral Cai --- ...o_use_qiskit1_with_pennylane.metadata.json | 2 +- .../how_to_use_qiskit1_with_pennylane.py | 10 +++- demonstrations/quantum_volume.metadata.json | 2 +- demonstrations/quantum_volume.py | 55 +++++++++---------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/demonstrations/how_to_use_qiskit1_with_pennylane.metadata.json b/demonstrations/how_to_use_qiskit1_with_pennylane.metadata.json index 3c9d27a9ba..c5a0361540 100644 --- a/demonstrations/how_to_use_qiskit1_with_pennylane.metadata.json +++ b/demonstrations/how_to_use_qiskit1_with_pennylane.metadata.json @@ -6,7 +6,7 @@ } ], "dateOfPublication": "2024-07-02T00:00:00+00:00", - "dateOfLastModification": "2024-10-07T00:00:00+00:00", + "dateOfLastModification": "2025-01-08T00:00:00+00:00", "categories": [ "Quantum Computing", "How-to" diff --git a/demonstrations/how_to_use_qiskit1_with_pennylane.py b/demonstrations/how_to_use_qiskit1_with_pennylane.py index 1a6e0ca61a..83d39d546f 100644 --- a/demonstrations/how_to_use_qiskit1_with_pennylane.py +++ b/demonstrations/how_to_use_qiskit1_with_pennylane.py @@ -242,7 +242,7 @@ def qiskit_GHZ_circuit(n): # pl_circuit = qml.QNode(pl_qfunc, device=qml.device("lightning.qubit", wires=n)) -pl_circuit() +print(pl_circuit()) ###################################################################### # .. rst-class:: sphx-glr-script-out @@ -263,7 +263,7 @@ def qiskit_GHZ_circuit(n): pl_qfunc = qml.from_qiskit(qc, measurements=measurements) pl_circuit = qml.QNode(pl_qfunc, device=qml.device("default.qubit", wires=n)) -pl_circuit(shots=5) +print(pl_circuit(shots=5)) ###################################################################### # .. rst-class:: sphx-glr-script-out @@ -304,6 +304,7 @@ def qiskit_GHZ_circuit(n): # from qiskit.circuit import ParameterVector, Parameter +from matplotlib import pyplot as plt n = 3 @@ -316,6 +317,8 @@ def qiskit_GHZ_circuit(n): qc.ry(angle2, [2]) qc.draw("mpl") +plt.show() + ###################################################################### # .. rst-class:: image-no-text-wrap @@ -349,7 +352,8 @@ def differentiable_circuit(phis, theta): theta = np.array([0.19]) print(differentiable_circuit(phis, theta)) -print(qml.draw_mpl(differentiable_circuit)(phis, theta)) +qml.draw_mpl(differentiable_circuit, style="pennylane")(phis, theta) +plt.show() ###################################################################### # .. rst-class:: sphx-glr-script-out diff --git a/demonstrations/quantum_volume.metadata.json b/demonstrations/quantum_volume.metadata.json index 9e45b3ab88..4a626d10ed 100644 --- a/demonstrations/quantum_volume.metadata.json +++ b/demonstrations/quantum_volume.metadata.json @@ -6,7 +6,7 @@ } ], "dateOfPublication": "2020-12-15T00:00:00+00:00", - "dateOfLastModification": "2024-10-11T00:00:00+00:00", + "dateOfLastModification": "2025-01-08T00:00:00+00:00", "categories": [ "Quantum Hardware", "Quantum Computing" diff --git a/demonstrations/quantum_volume.py b/demonstrations/quantum_volume.py index 7dc9e43f48..08d3783992 100644 --- a/demonstrations/quantum_volume.py +++ b/demonstrations/quantum_volume.py @@ -343,19 +343,17 @@ def permute_qubits(num_qubits): ############################################################################## # -# Next, we need to apply SU(4) gates to pairs of qubits. PennyLane doesn't have -# built-in functionality to generate these random matrices, however its cousin -# `Strawberry Fields `_ does! We will use the -# ``random_interferometer`` method, which can generate unitary matrices uniformly +# Next, we need to apply SU(4) gates to pairs of qubits. +# We can use scipy to generate unitary matrices uniformly # at random. This function actually generates elements of U(4), but they are # essentially equivalent up to a global phase. -from strawberryfields.utils import random_interferometer +from scipy.stats import unitary_group def apply_random_su4_layer(num_qubits): for qubit_idx in range(0, num_qubits, 2): if qubit_idx < num_qubits - 1: - rand_haar_su4 = random_interferometer(N=4) + rand_haar_su4 = unitary_group.rvs(4) qml.QubitUnitary(rand_haar_su4, wires=[qubit_idx, qubit_idx + 1]) @@ -386,9 +384,10 @@ def qv_circuit_layer(num_qubits): m = 3 # number of qubits with qml.tape.QuantumTape() as tape: - qml.layer(qv_circuit_layer, m, num_qubits=m) + for _ in range(m): + qv_circuit_layer(m) -expanded_tape = tape.expand(stop_at=lambda op: isinstance(op, qml.QubitUnitary)) +(expanded_tape, ), _ = qml.transforms.decompose(tape, gate_set={qml.QubitUnitary, qml.SWAP}) print(qml.drawer.tape_text(expanded_tape, wire_order=dev_ideal.wires, show_all_wires=True, show_matrices=True)) @@ -487,12 +486,11 @@ def heavy_output_set(m, probs): # # Adds a measurement of the first m qubits to the previous circuit -with tape: - qml.probs(wires=range(m)) +tape = tape.copy(measurements=[qml.probs(wires=range(m))]) # Run the circuit, compute heavy outputs, and print results -output_probs = qml.execute([tape], dev_ideal, None) # returns a list of result ! -output_probs = output_probs[0].reshape(2 ** m, ) +[output_probs] = qml.execute([tape], dev_ideal) # returns a list of result ! +output_probs = output_probs.reshape(2 ** m, ) heavy_outputs, prob_heavy_output = heavy_output_set(m, output_probs) print("State\tProbability") @@ -583,10 +581,6 @@ def heavy_output_set(m, probs): # Lima noise model. Again, we won't be running on Lima directly --- # we'll set up a local device to simulate its behaviour. # - -dev_noisy = qml.device("qiskit.remote", wires=5, shots=1000, backend=FakeLimaV2()) - -############################################################################## # # As a final point, since we are allowed to do as much optimization as we like, # let's put the compiler to work. The compiler will perform a number of @@ -594,14 +588,15 @@ def heavy_output_set(m, probs): # qubit placement and routing techniques [#sabre]_ in order to fit the circuits # on the hardware graph in the best way possible. -dev_noisy.set_transpile_args( - **{ + +transpile_args = { "optimization_level": 3, "coupling_map": FakeLimaV2().coupling_map, "layout_method": "sabre", "routing_method": "sabre", } -) + +dev_noisy = qml.device("qiskit.remote", wires=5, shots=1000, backend=FakeLimaV2(), **transpile_args) ############################################################################## @@ -625,28 +620,28 @@ def heavy_output_set(m, probs): for trial in range(num_trials): # Simulate the circuit analytically - with qml.tape.QuantumTape() as tape: - qml.layer(qv_circuit_layer, m, num_qubits=m) + with qml.tape.QuantumTape() as tape_probs: + for _ in range(m): + qv_circuit_layer(m) qml.probs(wires=range(m)) + + # when using qml.execute, shots must be on the tape + tape_counts = tape_probs.copy(measurements=[qml.counts()], shots=1000) - output_probs = qml.execute([tape], dev_ideal, None) + output_probs = qml.execute([tape_probs], dev_ideal) output_probs = output_probs[0].reshape(2 ** m, ) heavy_outputs, prob_heavy_output = heavy_output_set(m, output_probs) # Execute circuit on the noisy device - qml.execute([tape], dev_noisy, None) - - # Get the output bit strings; flip ordering of qubits to match PennyLane - counts = dev_noisy._current_job.result().get_counts() - reordered_counts = {x[::-1]: counts[x] for x in counts.keys()} + [counts] = qml.execute([tape_counts], dev_noisy) device_heavy_outputs = np.sum( [ - reordered_counts[x] if x[:m] in heavy_outputs else 0 - for x in reordered_counts.keys() + counts[x] if x[:m] in heavy_outputs else 0 + for x in counts.keys() ] ) - fraction_device_heavy_output = device_heavy_outputs / dev_noisy.shots + fraction_device_heavy_output = device_heavy_outputs / dev_noisy.shots.total_shots probs_ideal[m - min_m, trial] = prob_heavy_output probs_noisy[m - min_m, trial] = fraction_device_heavy_output