def compile_controlled_power(gate: PowerGateImpl) -> QCircuit: """ Recompilation of a controlled-power gate Basis change into Z then recompilation of controled Z, then change basis back :param gate: The power gate :return: set of gates wrapped in QCircuit class """ if not gate.is_controlled(): return QCircuit.wrap_gate(gate) if not isinstance(gate, PowerGateImpl): return QCircuit.wrap_gate(gate) if len(gate.target) > 1: return compile_controlled_power(gate=compile_multitarget(gate=gate)) power = gate.power target = gate.target control = gate.control result = QCircuit() result += Phase(target=control[0], control=control[1:], phi=power * pi / 2) result += change_basis(target=target, name=gate.name) result += Rz(target=target, control=control, angle=power * pi) result += change_basis(target=target, name=gate.name, daggered=True) result.n_qubits = result.max_qubit() + 1 return result
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