Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 42 additions & 42 deletions demonstrations_v2/tutorial_clifford_circuit_simulations/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,21 @@

"""

import pennylane as qml
import pennylane as qp

dev = qml.device("default.clifford", wires=2, tableau=True)
dev = qp.device("default.clifford", wires=2, tableau=True)

@qml.qnode(dev)
@qp.qnode(dev)
def circuit(return_state=True):
qml.X(wires=[0])
qml.CNOT(wires=[0, 1])
qml.Hadamard(wires=[0])
qml.Hadamard(wires=[1])
qp.X(wires=[0])
qp.CNOT(wires=[0, 1])
qp.Hadamard(wires=[0])
qp.Hadamard(wires=[1])
return [
qml.expval(op=qml.X(0) @ qml.X(1)),
qml.var(op=qml.Z(0) @ qml.Z(1)),
qml.probs(),
] + ([qml.state()] if return_state else [])
qp.expval(op=qp.X(0) @ qp.X(1)),
qp.var(op=qp.Z(0) @ qp.Z(1)),
qp.probs(),
] + ([qp.state()] if return_state else [])


expval, var, probs, state = circuit(return_state=True)
Expand All @@ -163,9 +163,9 @@ def circuit(return_state=True):
import matplotlib.pyplot as plt

# Get the results with 10000 shots and assert them
shot_result = qml.set_shots(circuit, shots=10000)(return_state=False)
shot_result = qp.set_shots(circuit, shots=10000)(return_state=False)
shot_exp, shot_var, shot_probs = shot_result
assert qml.math.allclose([shot_exp, shot_var], [expval, var], atol=1e-3)
assert qp.math.allclose([shot_exp, shot_var], [expval, var], atol=1e-3)

# Define computational basis states
basis_states = ["|00⟩", "|01⟩", "|10⟩", "|11⟩"]
Expand Down Expand Up @@ -203,15 +203,15 @@ def circuit(return_state=True):
# preparation circuit:
#

dev = qml.device("default.clifford")
dev = qp.device("default.clifford")

@qml.qnode(dev)
@qp.qnode(dev)
def GHZStatePrep(num_wires):
"""Prepares the GHZ State"""
qml.Hadamard(wires=[0])
qp.Hadamard(wires=[0])
for wire in range(num_wires):
qml.CNOT(wires=[wire, wire + 1])
return qml.expval(qml.Z(0) @ qml.Z(num_wires - 1))
qp.CNOT(wires=[wire, wire + 1])
return qp.expval(qp.Z(0) @ qp.Z(num_wires - 1))


######################################################################
Expand All @@ -221,7 +221,7 @@ def GHZStatePrep(num_wires):

from timeit import timeit

dev = qml.device("default.clifford")
dev = qp.device("default.clifford")

num_shots = [None, 100000]
num_wires = [10, 100, 1000, 10000]
Expand All @@ -232,7 +232,7 @@ def GHZStatePrep(num_wires):
for ind, num_shot in enumerate(num_shots):
for idx, num_wire in enumerate(num_wires):
shots_times[ind][idx] = timeit(
"qml.set_shots(GHZStatePrep, shots=num_shot)(num_wire)", number=5, globals=globals()
"qp.set_shots(GHZStatePrep, shots=num_shot)(num_wire)", number=5, globals=globals()
) / 5 # average over 5 trials

# Figure set up
Expand Down Expand Up @@ -320,23 +320,23 @@ def tableau_to_pauli_rep(tableau):
# As previously suggested, the evolution of the stabilizer tableau after the application of
# each Clifford gate operation can be understood by learning how the generator set is
# transformed based on their Clifford tableaus. For example, the first circuit operation
# ``qml.X(0)`` has the following tableau:
# ``qp.X(0)`` has the following tableau:
#

def clifford_tableau(op):
"""Prints a Clifford Tableau representation for a given operation."""
# Print the op and set up Pauli operators to be conjugated
print(f"Tableau: {op.name}({', '.join(map(str, op.wires))})")
pauli_ops = [pauli(wire) for wire in op.wires for pauli in [qml.X, qml.Z]]
pauli_ops = [pauli(wire) for wire in op.wires for pauli in [qp.X, qp.Z]]
# obtain conjugation of Pauli op and decompose it in Pauli basis
for pauli in pauli_ops:
conjugate = qml.prod(qml.adjoint(op), pauli, op).simplify()
decompose = qml.pauli_decompose(conjugate.matrix(), wire_order=op.wires)
conjugate = qp.prod(qp.adjoint(op), pauli, op).simplify()
decompose = qp.pauli_decompose(conjugate.matrix(), wire_order=op.wires)
decompose_coeffs, decompose_ops = decompose.terms()
phase = "+" if list(decompose_coeffs)[0] >= 0 else "-"
print(pauli, "-—>", phase, list(decompose_ops)[0])

clifford_tableau(qml.X(0))
clifford_tableau(qp.X(0))

######################################################################
# We now have the two key components for studying the evolution of the stabilizer tableau of the
Expand All @@ -347,26 +347,26 @@ def clifford_tableau(op):
# :func:`~pennylane.snapshots` in the circuit using the following transform.
#

@qml.transform
@qp.transform
def state_at_each_step(tape):
"""Transforms a circuit to access state after every operation"""
# This builds list with a qml.Snapshot operation before every tape operation
# This builds list with a qp.Snapshot operation before every tape operation
operations = []
for op in tape.operations:
operations.append(qml.Snapshot())
operations.append(qp.Snapshot())
operations.append(op)
operations.append(qml.Snapshot()) # add a final qml.Snapshot operation at end
operations.append(qp.Snapshot()) # add a final qp.Snapshot operation at end
new_tape = type(tape)(operations, tape.measurements, shots=tape.shots)
postprocessing = lambda results: results[0] # func for processing results
return [new_tape], postprocessing

snapshots = qml.snapshots(state_at_each_step(circuit))()
snapshots = qp.snapshots(state_at_each_step(circuit))()

######################################################################
# We can now access the tableau state via the ``snapshots`` dictionary, where the integer keys
# represent each step. The step ``0`` corresponds to the initial all zero :math:`|00\rangle`
# state, which is stabilized by the Pauli operators :math:`Z_0` and :math:`Z_1.` Evolving
# it by a ``qml.X(0)`` would correspond to transforming its stabilizer generators
# it by a ``qp.X(0)`` would correspond to transforming its stabilizer generators
# from :math:`+Z_0` to :math:`-Z_0,` while keeping the destabilizer generators the same.
#

Expand All @@ -381,7 +381,7 @@ def state_at_each_step(tape):
# Let's examine the remaining operations to confirm this.
#

tape = qml.workflow.construct_tape(circuit)()
tape = qp.workflow.construct_tape(circuit)()
circuit_ops = tape.operations
print("Circ. Ops: ", circuit_ops)

Expand Down Expand Up @@ -410,18 +410,18 @@ def state_at_each_step(tape):
# Let's see this in action for the following two-qubit parameterized circuit:
#

dev = qml.device("default.qubit")
@qml.qnode(dev)
dev = qp.device("default.qubit")
@qp.qnode(dev)
def original_circuit(x, y):
qml.RX(x, 0)
qml.CNOT([0, 1])
qml.RY(y, 0)
return qml.probs()
qp.RX(x, 0)
qp.CNOT([0, 1])
qp.RY(y, 0)
return qp.probs()

x, y = np.pi / 2, np.pi / 4
unrolled_circuit = qml.transforms.clifford_t_decomposition(original_circuit)
unrolled_circuit = qp.transforms.clifford_t_decomposition(original_circuit)

qml.draw_mpl(unrolled_circuit, decimals=2, style="pennylane")(x, y)
qp.draw_mpl(unrolled_circuit, decimals=2, style="pennylane")(x, y)
plt.show()

######################################################################
Expand All @@ -434,7 +434,7 @@ def original_circuit(x, y):
#

original_probs, unrolled_probs = original_circuit(x, y), unrolled_circuit(x, y)
assert qml.math.allclose(original_probs, unrolled_probs, atol=1e-3)
assert qp.math.allclose(original_probs, unrolled_probs, atol=1e-3)

######################################################################
# Ultimately, one can use this decomposition to perform some basic resource analysis for
Expand All @@ -446,7 +446,7 @@ def original_circuit(x, y):
# `Eastin-Knill <https://en.wikipedia.org/wiki/Eastin%E2%80%93Knill_theorem>`__ theorem.
#

with qml.Tracker(dev) as tracker:
with qp.Tracker(dev) as tracker:
unrolled_circuit(x, y)

resources_lst = tracker.history["resources"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"executable_stable": true,
"executable_latest": true,
"dateOfPublication": "2024-04-12T00:00:00+00:00",
"dateOfLastModification": "2026-01-14T00:00:00+00:00",
"dateOfLastModification": "2026-04-17T00:00:00+00:00",
"categories": [
"Devices and Performance"
],
Expand Down
46 changes: 23 additions & 23 deletions demonstrations_v2/tutorial_coherent_vqls/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@

"""

import pennylane as qml
import pennylane as qp
from pennylane import numpy as np
import matplotlib.pyplot as plt

Expand Down Expand Up @@ -247,16 +247,16 @@ def U_c():
"""Unitary matrix rotating the ground state of the ancillary qubits
to |sqrt(c)> = U_c |0>."""
# Circuit mapping |00> to sqrt_c[0] |00> + sqrt_c[1] |01> + sqrt_c[2] |10>
qml.RY(-2 * np.arccos(sqrt_c[0]), wires=ancilla_idx)
qml.CRY(-2 * np.arctan(sqrt_c[2] / sqrt_c[1]), wires=[ancilla_idx, ancilla_idx + 1])
qml.CNOT(wires=[ancilla_idx + 1, ancilla_idx])
qp.RY(-2 * np.arccos(sqrt_c[0]), wires=ancilla_idx)
qp.CRY(-2 * np.arctan(sqrt_c[2] / sqrt_c[1]), wires=[ancilla_idx, ancilla_idx + 1])
qp.CNOT(wires=[ancilla_idx + 1, ancilla_idx])


def U_c_dagger():
"""Adjoint of U_c."""
qml.CNOT(wires=[ancilla_idx + 1, ancilla_idx])
qml.CRY(2 * np.arctan(sqrt_c[2] / sqrt_c[1]), wires=[ancilla_idx, ancilla_idx + 1])
qml.RY(2 * np.arccos(sqrt_c[0]), wires=ancilla_idx)
qp.CNOT(wires=[ancilla_idx + 1, ancilla_idx])
qp.CRY(2 * np.arctan(sqrt_c[2] / sqrt_c[1]), wires=[ancilla_idx, ancilla_idx + 1])
qp.RY(2 * np.arccos(sqrt_c[0]), wires=ancilla_idx)


##############################################################################
Expand All @@ -269,11 +269,11 @@ def U_c_dagger():
def CA_all():
"""Controlled application of all the unitary components A_l of the problem matrix A."""
# Controlled-A_1
qml.CNOT(wires=[ancilla_idx, 0])
qml.CZ(wires=[ancilla_idx, 1])
qp.CNOT(wires=[ancilla_idx, 0])
qp.CZ(wires=[ancilla_idx, 1])

# Controlled-A2
qml.CNOT(wires=[ancilla_idx + 1, 0])
qp.CNOT(wires=[ancilla_idx + 1, 0])


##############################################################################
Expand All @@ -284,7 +284,7 @@ def U_b():
"""Unitary matrix rotating the system ground state to the
problem vector |b> = U_b |0>."""
for idx in range(n_qubits):
qml.Hadamard(wires=idx)
qp.Hadamard(wires=idx)


##############################################################################
Expand All @@ -308,11 +308,11 @@ def variational_block(weights):
"""Variational circuit mapping the ground state |0> to the ansatz state |x>."""
# We first prepare an equal superposition of all the states of the computational basis
for idx in range(n_qubits):
qml.Hadamard(wires=idx)
qp.Hadamard(wires=idx)

# A very minimal variational circuit
for idx, element in enumerate(weights):
qml.RY(element, wires=idx)
qp.RY(element, wires=idx)


##############################################################################
Expand Down Expand Up @@ -357,25 +357,25 @@ def full_circuit(weights):
# To evaluate the two probabilities appearing on the right hand side of the previous equation
# we initialize a ``default.qubit`` device and we define two different ``qnode`` circuits.

dev = qml.device("default.qubit", wires=tot_qubits)
dev = qp.device("default.qubit", wires=tot_qubits)

@qml.qnode(dev, interface="autograd")
@qp.qnode(dev, interface="autograd")
def global_ground(weights):
# Circuit gates
full_circuit(weights)
# Projector on the global ground state
P = np.zeros((2 ** tot_qubits, 2 ** tot_qubits))
P[0, 0] = 1.0
return qml.expval(qml.Hermitian(P, wires=range(tot_qubits)))
return qp.expval(qp.Hermitian(P, wires=range(tot_qubits)))

@qml.qnode(dev, interface="autograd")
@qp.qnode(dev, interface="autograd")
def ancilla_ground(weights):
# Circuit gates
full_circuit(weights)
# Projector on the ground state of the ancillary system
P_anc = np.zeros((2 ** m, 2 ** m))
P_anc[0, 0] = 1.0
return qml.expval(qml.Hermitian(P_anc, wires=range(n_qubits, tot_qubits)))
return qp.expval(qp.Hermitian(P_anc, wires=range(n_qubits, tot_qubits)))


##############################################################################
Expand All @@ -399,7 +399,7 @@ def cost(weights):

##############################################################################
# To minimize the cost function we use the gradient-descent optimizer.
opt = qml.GradientDescentOptimizer(eta)
opt = qp.GradientDescentOptimizer(eta)

##############################################################################
# We initialize the variational weights with random parameters (with a fixed seed).
Expand Down Expand Up @@ -485,10 +485,10 @@ def cost(weights):
# For this task, we initialize a new PennyLane device and define the associated
# QNode.

dev_x = qml.device("default.qubit", wires=n_qubits)
dev_x = qp.device("default.qubit", wires=n_qubits)

@qml.set_shots(n_shots)
@qml.qnode(dev_x, interface="autograd")
@qp.set_shots(n_shots)
@qp.qnode(dev_x, interface="autograd")
def prepare_and_sample(weights):

# Variational circuit generating a guess for the solution vector |x>
Expand All @@ -497,7 +497,7 @@ def prepare_and_sample(weights):
# We assume that the system is measured in the computational basis.
# Therefore, sampling from the device will give us a value of 0 or 1 for each qubit (n_qubits)
# this will be repeated for the total number of shots provided (n_shots).
return qml.sample()
return qp.sample()


##############################################################################
Expand Down
2 changes: 1 addition & 1 deletion demonstrations_v2/tutorial_coherent_vqls/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"executable_stable": true,
"executable_latest": true,
"dateOfPublication": "2019-11-06T00:00:00+00:00",
"dateOfLastModification": "2025-10-15T00:00:00+00:00",
"dateOfLastModification": "2026-04-17T00:00:00+00:00",
"categories": [
"Optimization"
],
Expand Down
Loading
Loading