Source code for qutip_qip.compiler.cavityqedcompiler

import numpy as np

from qutip_qip.circuit import GateInstruction
from qutip_qip.compiler import GateCompiler, PulseInstruction
from qutip_qip.operations.gates import RX, RZ, ISWAP, SQRTISWAP, GLOBALPHASE


[docs] class CavityQEDCompiler(GateCompiler): """ Compiler for :obj:`.DispersiveCavityQED`. Compiled pulse strength is in the unit of GHz. Supported native gates: "RX", "RY", "RZ", "ISWAP", "SQRTISWAP". Default configuration (see :obj:`.GateCompiler.args` and :obj:`.GateCompiler.compile`): +-----------------+--------------------+ | key | value | +=================+====================+ | ``shape`` | ``rectangular`` | +-----------------+--------------------+ |``params`` | Hardware Parameters| +-----------------+--------------------+ Parameters ---------- num_qubits: int The number of qubits in the system. params: dict A Python dictionary contains the name and the value of the parameters. See :obj:`.CavityQEDModel` for the definition. global_phase: float, optional Record of the global phase change and will be returned. Attributes ---------- gate_compiler: dict The Python dictionary in the form of {gate_name: decompose_function}. It saves the decomposition scheme for each gate. Examples -------- >>> import numpy as np >>> from qutip_qip.circuit import QubitCircuit >>> from qutip_qip.compiler import CavityQEDCompiler >>> from qutip_qip.device import ModelProcessor, CavityQEDModel >>> from qutip_qip.operations.gates import ISWAP >>> >>> qc = QubitCircuit(2) >>> qc.add_gate(ISWAP, targets=[0, 1]) >>> >>> model = CavityQEDModel(2) >>> processor = ModelProcessor(model=model) >>> compiler = CavityQEDCompiler(2, params=model.params) >>> processor.load_circuit( ... qc, compiler=compiler) ({'sz0': array([ 0. , 2500. , 2500.01316]), 'sz1': array([ 0. , 2500. , 2500.01316]), 'g0': array([ 0. , 2500. , 2500.01316]), 'g1': array([ 0. , 2500. , 2500.01316])}, {'sz0': array([-0.5, -9.5]), 'sz1': array([-0.5, -9.5]), 'g0': array([0.01, 0. ]), 'g1': array([0.01, 0. ])}) Notice that the above example is equivalent to using directly the :obj:`.DispersiveCavityQED`. """ def __init__(self, num_qubits, params, global_phase=0.0, pulse_dict=None, N=None): super().__init__(num_qubits, params=params, pulse_dict=pulse_dict, N=N) self.gate_compiler.update( { ISWAP: self.iswap_compiler, SQRTISWAP: self.sqrtiswap_compiler, RZ: self.rz_compiler, RX: self.rx_compiler, } ) self.wq = np.sqrt(self.params["eps"] ** 2 + self.params["delta"] ** 2) self.Delta = self.wq - self.params["w0"] self.global_phase = global_phase def _rotation_compiler(self, circuit_instruction, op_label, param_label, args): """ Single qubit rotation compiler. Parameters ---------- gate : :obj:`~.operations.Gate`: The quantum gate to be compiled. op_label : str Label of the corresponding control Hamiltonian. param_label : str Label of the hardware parameters saved in :obj:`GateCompiler.params`. args : dict The compilation configuration defined in the attributes :obj:`.GateCompiler.args` or given as a parameter in :obj:`.GateCompiler.compile`. Returns ------- A list of :obj:`.PulseInstruction`, including the compiled pulse information for this gate. """ targets = circuit_instruction.targets coeff, tlist = self.generate_pulse_shape( args["shape"], args["num_samples"], maximum=self.params[param_label][targets[0]], # The operator is Pauli Z/X/Y, without 1/2. area=circuit_instruction.operation.arg_value[0] / (4.0 * np.pi), ) pulse_info = [(op_label + str(targets[0]), coeff)] return [PulseInstruction(circuit_instruction, tlist, pulse_info)]
[docs] def rz_compiler(self, circuit_instruction, args): """ Compiler for the RZ gate Parameters ---------- gate : :obj:`~.operations.Gate`: The quantum gate to be compiled. args : dict The compilation configuration defined in the attributes :obj:`.GateCompiler.args` or given as a parameter in :obj:`.GateCompiler.compile`. Returns ------- A list of :obj:`.PulseInstruction`, including the compiled pulse information for this gate. """ return self._rotation_compiler(circuit_instruction, "sz", "sz", args)
[docs] def rx_compiler(self, circuit_instruction, args): """ Compiler for the RX gate Parameters ---------- gate : :obj:`~.operations.Gate`: The quantum gate to be compiled. args : dict The compilation configuration defined in the attributes :obj:`.GateCompiler.args` or given as a parameter in :obj:`.GateCompiler.compile`. Returns ------- A list of :obj:`.PulseInstruction`, including the compiled pulse information for this gate. """ return self._rotation_compiler(circuit_instruction, "sx", "sx", args)
def _swap_compiler(self, circuit_instruction, area, correction_angle, args): q1, q2 = circuit_instruction.targets pulse_info = [] pulse_name = "sz" + str(q1) coeff = self.wq[q1] - self.params["w0"] pulse_info += [(pulse_name, coeff)] pulse_name = "sz" + str(q2) coeff = self.wq[q2] - self.params["w0"] pulse_info += [(pulse_name, coeff)] pulse_name = "g" + str(q1) coeff = self.params["g"][q1] pulse_info += [(pulse_name, coeff)] pulse_name = "g" + str(q2) coeff = self.params["g"][q2] pulse_info += [(pulse_name, coeff)] J = ( self.params["g"][q1] * self.params["g"][q2] * (1.0 / self.Delta[q1] + 1.0 / self.Delta[q2]) / 2.0 ) coeff, tlist = self.generate_pulse_shape( args["shape"], args["num_samples"], maximum=J, area=area ) instruction_list = [PulseInstruction(circuit_instruction, tlist, pulse_info)] # corrections compiled_gate1 = self.gate_compiler[RZ]( GateInstruction(operation=RZ(correction_angle), qubits=(q1,)), args, ) instruction_list += compiled_gate1 compiled_gate2 = self.gate_compiler[RZ]( GateInstruction(operation=RZ(correction_angle), qubits=(q2,)), args, ) instruction_list += compiled_gate2 self.gate_compiler[GLOBALPHASE](correction_angle) return instruction_list
[docs] def sqrtiswap_compiler(self, circuit_instruction, args): """ Compiler for the SQRTISWAP gate. Parameters ---------- gate : :obj:`~.operations.Gate`: The quantum gate to be compiled. args : dict The compilation configuration defined in the attributes :obj:`.GateCompiler.args` or given as a parameter in :obj:`.GateCompiler.compile`. Returns ------- A list of :obj:`.PulseInstruction`, including the compiled pulse information for this gate. Notes ----- This version of sqrtiswap_compiler has very low fidelity, please use iswap """ # FIXME This decomposition has poor behaviour. return self._swap_compiler( circuit_instruction, area=1 / 4, correction_angle=-np.pi / 4, args=args, )
[docs] def iswap_compiler(self, circuit_instruction, args): """ Compiler for the ISWAP gate. Parameters ---------- gate : :obj:`~.operations.Gate`: The quantum gate to be compiled. args : dict The compilation configuration defined in the attributes :obj:`.GateCompiler.args` or given as a parameter in :obj:`.GateCompiler.compile`. Returns ------- A list of :obj:`.PulseInstruction`, including the compiled pulse information for this gate. """ return self._swap_compiler( circuit_instruction, area=1 / 2, correction_angle=-np.pi / 2, args=args, )