Example #1
0
    def __init__(self,
                 hamiltonian=None,
                 qubit_freq_est=None,
                 meas_freq_est=None,
                 u_channel_lo=None,
                 control_channel_labels=None,
                 subsystem_list=None,
                 dt=None):
        """Initialize a PulseSystemModel.

        Args:
            hamiltonian (HamiltonianModel): The Hamiltonian of the system.
            qubit_freq_est (list): list of qubit lo frequencies defaults to be used in simulation
                                   if none are specified in the PulseQobj.
            meas_freq_est (list): list of qubit meas frequencies defaults to be used in simulation
                                  if none are specified in the PulseQobj.
            u_channel_lo (list): list of ControlChannel frequency specifications.
            control_channel_labels (list): list of labels for control channels, which can be of
                                           any type.
            subsystem_list (list): list of valid qubit indicies for the model.
            dt (float): pixel size for pulse Instructions.
        Raises:
            AerError: if hamiltonian is not None or a HamiltonianModel
        """

        # default type values
        self._qubit_freq_est = qubit_freq_est
        self._meas_freq_est = meas_freq_est

        # necessary values
        if hamiltonian is not None and not isinstance(hamiltonian,
                                                      HamiltonianModel):
            raise AerError("hamiltonian must be a HamiltonianModel object")
        self.hamiltonian = hamiltonian
        self.u_channel_lo = u_channel_lo
        self.control_channel_labels = control_channel_labels or []
        self.subsystem_list = subsystem_list
        self.dt = dt
    def from_backend(cls, backend, subsystem_list=None):
        """Returns a PulseSystemModel constructed from an OpenPulse enabled backend object.

        Args:
            backend (Backend): backend object to draw information from.
            subsystem_list (list): a list of ints for which qubits to include in the model.

        Returns:
            PulseSystemModel: the PulseSystemModel constructed from the backend.

        Raises:
            AerError: If channel or u_channel_lo are invalid.
        """

        if not isinstance(backend, BaseBackend):
            raise AerError("{} is not a Qiskit backend".format(backend))

        # get relevant information from backend
        defaults = backend.defaults()
        config = backend.configuration()

        if not config.open_pulse:
            raise AerError('{} is not an open pulse backend'.format(backend))

        # draw defaults
        qubit_freq_est = getattr(defaults, 'qubit_freq_est', None)
        meas_freq_est = getattr(defaults, 'meas_freq_est', None)

        # draw from configuration
        # if no subsystem_list, use all for device
        subsystem_list = subsystem_list or list(range(config.n_qubits))
        ham_string = config.hamiltonian
        hamiltonian = HamiltonianModel.from_dict(ham_string, subsystem_list)
        u_channel_lo = getattr(config, 'u_channel_lo', None)
        dt = getattr(config, 'dt', None)

        control_channel_labels = [None] * len(u_channel_lo)
        # populate control_channel_dict
        # for now it assumes the u channel drives a single qubit, and we return the index
        # of the driven qubit, along with the frequency description
        if u_channel_lo is not None:
            for u_idx, u_lo in enumerate(u_channel_lo):
                # find drive index
                drive_idx = None
                while drive_idx is None:
                    u_str_label = 'U{0}'.format(str(u_idx))
                    for h_term_str in ham_string['h_str']:
                        # check if this string corresponds to this u channel
                        if u_str_label in h_term_str:
                            # get index of X operator drive term
                            x_idx = h_term_str.find('X')
                            # if 'X' is found, and is not at the end of the string, drive_idx
                            # is the subsequent character
                            if x_idx != -1 and x_idx + 1 < len(h_term_str):
                                drive_idx = int(h_term_str[x_idx + 1])

                if drive_idx is not None:
                    # construct string for u channel
                    u_string = ''
                    for u_term_dict in u_lo:
                        scale = getattr(u_term_dict, 'scale', [1.0, 0])
                        q_idx = getattr(u_term_dict, 'q')
                        if len(u_string) > 0:
                            u_string += ' + '
                        if isinstance(scale, complex):
                            u_string += str(scale) + 'q' + str(q_idx)
                        else:
                            u_string += str(scale[0] + scale[1] * 1j) + 'q' + str(q_idx)
                    control_channel_labels[u_idx] = {'driven_q': drive_idx, 'freq': u_string}

        return cls(hamiltonian=hamiltonian,
                   qubit_freq_est=qubit_freq_est,
                   meas_freq_est=meas_freq_est,
                   u_channel_lo=u_channel_lo,
                   control_channel_labels=control_channel_labels,
                   subsystem_list=subsystem_list,
                   dt=dt)