def compile_ry(gate: RotationGateImpl, controlled_rotation: bool = False) -> QCircuit: """ Compile Ry gates into Rx and Rz. Parameters ---------- gate: the gate. controlled_rotation: determines if the decomposition of the controlled-Ry gate will be performed in compile_controlled_rotation, if not, decomposition will be performed here Returns ------- QCircuit, the result of compilation. """ if gate.name.lower() == "ry": if not (gate.is_controlled() and controlled_rotation): return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \ + Rx(target=gate.target, control=gate.control, angle=gate.parameter) \ + Rz(target=gate.target, control=None, angle=numpy.pi / 2) return QCircuit.wrap_gate(gate)
def compile_controlled_rotation(gate: RotationGateImpl, angles: list = None) -> QCircuit: """ Recompilation of a controlled-rotation gate Basis change into Rz then recompilation of controled Rz, then change basis back :param gate: The rotational gate :param angles: new angles to set, given as a list of two. If None the angle in the gate is used (default) :return: set of gates wrapped in QCircuit class """ if not gate.is_controlled(): return QCircuit.wrap_gate(gate) if not isinstance(gate, RotationGateImpl): return QCircuit.wrap_gate(gate) if angles is None: angles = [gate.parameter / 2, -gate.parameter / 2] if len(gate.target) > 1: return compile_controlled_rotation(gate=compile_multitarget(gate=gate), angles=angles) target = gate.target control = gate.control result = QCircuit() result += change_basis(target=target, axis=gate._axis) result += RotationGateImpl(axis="z", target=target, angle=angles[0]) result += QGateImpl(name="X", target=target, control=control) result += RotationGateImpl(axis="Z", target=target, angle=angles[1]) result += QGateImpl(name="X", target=target, control=control) result += change_basis(target=target, axis=gate._axis, daggered=True) result.n_qubits = result.max_qubit() + 1 return result
def compile_controlled_rotation(gate: RotationGateImpl) -> QCircuit: """ Recompilation of a controlled-rotation gate Basis change into Rz then recompilation of controled Rz, then change basis back :param gate: The rotational gate :return: set of gates wrapped in QCircuit class """ if not gate.is_controlled(): return QCircuit.wrap_gate(gate) if not isinstance(gate, RotationGateImpl): return QCircuit.wrap_gate(gate) if len(gate.target) > 1: return compile_controlled_rotation(gate=compile_multitarget(gate=gate)) target = gate.target control = gate.control k = len(control) cind = _pattern(k) + [k - 1] result = QCircuit() result += change_basis(target=target, axis=gate._axis) coeff = -1 / pow(2, k) for i, ci in enumerate(cind): coeff *= -1 result += Rz(target=target, angle=coeff * gate.parameter) result += CNOT(control[ci], target) result += change_basis(target=target, axis=gate._axis, daggered=True) result.n_qubits = result.max_qubit() + 1 return result