Computes the single qubit gate resulting from the composition of two single
qubit gates, by composing the Bloch sphere rotations of the two gates.
The first rotation (A) is applied and then the second (B):
As separate gates
A q
B q
As linear operations
(B * A) q
If the final single qubit gate is anonymous, we try to match it to a default gate.
Uses Rodrigues' rotation formula (see https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula).
Source code in opensquirrel/ir/semantics/bsr.py
| def __mul__(self, other: BlochSphereRotation) -> BlochSphereRotation:
"""Computes the single qubit gate resulting from the composition of two single
qubit gates, by composing the Bloch sphere rotations of the two gates.
The first rotation (A) is applied and then the second (B):
As separate gates:
A q
B q
As linear operations:
(B * A) q
If the final single qubit gate is anonymous, we try to match it to a default gate.
Uses Rodrigues' rotation formula (see https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula).
"""
acos_argument = cos(self.angle / 2) * cos(other.angle / 2) - sin(self.angle / 2) * sin(
other.angle / 2
) * np.dot(self.axis, other.axis)
combined_angle = 2 * acos(acos_argument)
if abs(sin(combined_angle / 2)) < ATOL:
return bsr_from_matrix([[1, 0], [0, 1]])
order_of_magnitude = abs(floor(log10(ATOL)))
combined_axis = np.round(
(
1
/ sin(combined_angle / 2)
* (
sin(self.angle / 2) * cos(other.angle / 2) * self.axis.value
+ cos(self.angle / 2) * sin(other.angle / 2) * other.axis.value
+ sin(self.angle / 2) * sin(other.angle / 2) * np.cross(other.axis, self.axis)
)
),
order_of_magnitude,
)
combined_phase = np.round(self.phase + other.phase, order_of_magnitude)
return BlochSphereRotation(
axis=combined_axis,
angle=combined_angle,
phase=combined_phase,
)
|