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_to_cc(gate) -> QCircuit: if not gate.is_controlled: return QCircuit.wrap_gate(gate) cl = len(gate.control) target = gate.target control = gate.control if cl <= 2: return QCircuit.wrap_gate(gate) name = gate.name back = QCircuit() if name in ['X', 'x', 'Y', 'y', 'Z', 'z', 'H', 'h']: if isinstance(gate, PowerGateImpl): power = gate.parameter else: power = 1.0 new = PowerGateImpl(name=name, power=power, target=target, control=control) back += compile_power_gate(gate=new, cut=True) elif isinstance(gate, RotationGateImpl): partial = compile_controlled_rotation(gate=gate) back += compile_to_cc(gate=partial) elif isinstance(gate, PhaseGateImpl): partial = compile_controlled_phase(gate=gate) back += compile_to_cc(gate=partial) else: print(gate) raise TequilaException('frankly, what the f**k is this gate?') return back
def _initialize_power_gate(name: str, target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None) -> QCircuit: if power is None or power in [1, 1.0]: return QCircuit.wrap_gate( QGateImpl(name=name, target=target, control=control)) else: return QCircuit.wrap_gate( PowerGateImpl(name=name, power=power, target=target, control=control))
def compile_to_single_control(gate) -> QCircuit: """ break down a gate into a sequence with no more than single-controlled gates. Parameters ---------- gate: the gate. Returns ------- A QCircuit; the result of compilation. """ if not gate.is_controlled: return QCircuit.wrap_gate(gate) cl = len(gate.control) target = gate.target control = gate.control if cl <= 1: return QCircuit.wrap_gate(gate) name = gate.name back = QCircuit() if name in ['X', 'x', 'Y', 'y', 'Z', 'z', 'H', 'h']: if isinstance(gate, PowerGateImpl): power = gate.parameter else: power = 1.0 new = PowerGateImpl(name=name, power=power, target=target, control=control, generator=gate.make_generator()) partial = compile_power_gate(gate=new) back += compile_to_single_control(gate=partial) elif isinstance(gate, RotationGateImpl): partial = compile_controlled_rotation(gate=gate) back += compile_to_single_control(gate=partial) elif isinstance(gate, PhaseGateImpl): partial = compile_controlled_phase(gate=gate) back += compile_to_single_control(gate=partial) else: print(gate) raise TequilaException('frankly, what the f**k is this gate?') return back
def PowerGate(name: str, target: typing.Union[list, int], power: bool = None, control: typing.Union[list, int] = None): """ Initialize a (potentially parametrized) gate which is supported on the backend Parameters ---------- name: str name of the gate on the backend target int or list of int power numeric type (fixed exponent) or hashable type (parametrized exponent) control int or list of int Returns ------- """ return QCircuit.wrap_gate(PowerGateImpl(name=name, power=power, target=target, control=control))