Utility functions
Utility functions.
- ionizer.utils.are_mats_equivalent(unitary1, unitary2)
Checks the equivalence of two unitary matrices up to a global phase.
- Parameters:
unitary1 (tensor) – First unitary matrix.
unitary2 (tensor) – Second unitary matrix.
- Returns:
True if the two matrices are equivalent up to a global phase, False otherwise.
- Return type:
bool
Example
>>> matrix_T = np.diag([1, 1j]) >>> matrix_RZ = np.diag([np.exp(-1j * np.pi / 4), np.exp(1j * np.pi / 4)]) >>> are_mats_equivalent(matrix_T, matrix_RZ) True
- ionizer.utils.extract_gpi2_gpi_gpi2_angles(unitary)
Given unitary matrix, recovers a set of three angles \(\alpha\), \(\beta\), and \(\gamma\) such that
\[U = GPI2(\alpha) GPI(\beta) GPI2(\gamma)\]up to a global phase.
This function is loosely based on PennyLane’s zyz_decomposition.
- Parameters:
unitary (tensor) – A unitary matrix.
- Returns:
Rotation angles for the \(GPI\) and \(GPI2\) gates. The order of the returned angles corresponds to the order in which they would appear in a circuit, i.e.,
[gamma, beta, alpha].- Return type:
tensor
Example
>>> matrix_RZ = np.diag([np.exp(-1j * np.pi / 4), np.exp(1j * np.pi / 4)]) >>> angles = extract_gpi2_gpi_gpi2_angles(matrix_RZ) >>> angles [ 2.35619449 3.14159265 -2.35619449] >>> recovered_matrix = np.linalg.multi_dot( ... [op.compute_matrix(angle) for op, angle in zip([GPI2, GPI, GPI2], angles[::-1])] ... ) >>> are_mats_equivalent(matrix_RZ, recovered_matrix) True
- ionizer.utils.flag_non_equivalence(tape1, tape2)
Check equivalence of two circuits up to a global phase.
- Parameters:
tape1 (pennylane.QuantumTape) – a quantum tape
tape2 (pennylane.QuantumTape) – quantum tape to compare with
tape1
- Raises:
ValueError if the two circuits are not equivalent. –
Example
with qml.tape.QuantumTape() as tape1: qml.Hadamard(wires=0) qml.CNOT(wires=[0, 1]) qml.T(wires=1) with qml.tape.QuantumTape() as tape2_equiv: qml.Hadamard(wires=0) qml.CNOT(wires=[0, 1]) qml.RZ(np.pi/4, wires=1) with qml.tape.QuantumTape() as tape3_nonequiv: qml.Hadamard(wires=0) qml.CNOT(wires=[0, 1]) qml.RZ(np.pi/2, wires=1)
>>> flag_non_equivalence(tape1, tape2_equiv) >>> flag_non_equivalence(tape1, tape3_nonequiv) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "ionizer/utils.py", line 98, in flag_non_equivalence raise ValueError("Quantum circuits are not equivalent after transform.") ValueError: Quantum circuits are not equivalent after transform.
- ionizer.utils.rescale_angles(angles, renormalize_for_json=False)
Rescale gate rotation angles into a fixed range.
By default, rescales between \(-\pi\) and \(\pi\). However, IonQ’s native gate parameters are defined in terms of “turns”, rather than radians, where 1 turn is equivalent to \(2\pi\). Setting
renormalize_for_jsontoTrueconverts radians to turns. See the IonQ documentation for more information.- Parameters:
angles (tensor) – The angles to rescale.
renormalize_for_json (bool) – If
True, rescale angles into the range \(-1\) to \(1\) (\(-2\pi\) to \(2\pi\)). Otherwise, rescale to within \(-\pi\) to \(\pi\).
- Returns:
The rescaled angles.
- Return type:
tensor
Example
>>> angles = np.array([-4, -2, 0, -2, 4]) >>> rescale_angles(angles) [ 2.28318531 -2. 0. -2. -2.28318531] >>> rescale_angles(angles, renormalize_for_json=True) [ 0.36338023 -0.31830989 0. -0.31830989 -0.36338023]
- ionizer.utils.tape_to_json(tape, name, shots=100, target='simulator')
Convert a quantum tape consisting of \(GPI\), \(GPI2\) and \(MS\) operations into a JSON object suitable for job submission to hardware.
Please see the IonQ webpage for full documentation of the job submission API.
Note that this function is not tested against the API in an automated, or manual way. If this function needs to be updated to work with API changes, please open an issue.
- Parameters:
tape (QuantumTape) – The quantum tape of the circuit to send.
name (str) – Desired name of the job.
shots (int) – Number of shots to be executed by the job.
target (str) – Where the job will be executed, e.g., “simulator” or a particular hardware device.
- Returns:
JSON formatted for submission to IonQ hardware.
- Return type:
Dict
Example
dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) @ionize def circuit(): qml.Hadamard(wires=0) qml.CNOT(wires=[0, 1]) return qml.probs() # Note that the circuit must be executed once to generate the tape. circuit() json_object = tape_to_json(circuit.qtape, "job_name", 1024, "simulator")
>>> pprint(json_object) {'input': {'circuit': [{'gate': 'gpi2', 'phase': 0.0, 'target': 0}, {'gate': 'gpi2', 'phase': 0.5, 'target': 1}, {'gate': 'ms', 'phases': [0, 0], 'targets': [0, 1]}, {'gate': 'gpi2', 'phase': -0.25, 'target': 0}], 'gateset': 'native', 'qubits': 2}, 'lang': 'json', 'name': 'job_name', 'shots': 1024, 'target': 'simulator'}