Ejemplo n.º 1
0
    def _dressed_spectrum_sweep(
        self, ) -> Tuple[NamedSlotsNdarray, NamedSlotsNdarray]:
        """

        Returns
        -------
            NamedSlotsNdarray[<paramname1>, <paramname2>, ...] of eigenvalues,
            likewise for eigenvectors
        """
        multi_cpu = self._num_cpus > 1
        target_map = cpu_switch.get_map_method(self._num_cpus)
        total_count = np.prod(self._parameters.counts)

        with utils.InfoBar(
                "Parallel compute dressed eigensys [num_cpus={}]".format(
                    self._num_cpus),
                self._num_cpus,
        ) as p:
            spectrum_data = list(
                tqdm(
                    target_map(
                        functools.partial(
                            self._update_and_compute_dressed_esys,
                            self._hilbertspace,
                            self._evals_count,
                            self._update_hilbertspace,
                        ),
                        itertools.product(*self._parameters.ranges),
                    ),
                    total=total_count,
                    desc="Dressed spectrum",
                    leave=False,
                    disable=multi_cpu,
                ))

        spectrum_data = np.asarray(spectrum_data, dtype=object)
        spectrum_data = spectrum_data.reshape((*self._parameters.counts, 2))
        slotparamvals_by_name = OrderedDict(
            self._parameters.ordered_dict.copy())

        evals = np.asarray(spectrum_data[..., 0].tolist())
        evecs = spectrum_data[..., 1]

        return NamedSlotsNdarray(evals,
                                 slotparamvals_by_name), NamedSlotsNdarray(
                                     evecs, slotparamvals_by_name)
Ejemplo n.º 2
0
def generator(sweep: "ParameterSweep", func: callable, **kwargs) -> np.ndarray:
    """Method for computing custom data as a function of the external parameter,
    calculated via the function `func`.

    Parameters
    ----------
    sweep:
        ParameterSweep object containing HilbertSpace and spectral information
    func:
        signature: `func(parametersweep, [paramindex_tuple, paramvals_tuple,
        **kwargs])`, specifies how to calculate the data for a single choice of
        parameter(s)
    **kwargs:
        keyword arguments to be included in func

    Returns
    -------
        array of custom data
    """
    reduced_parameters = sweep._parameters.create_sliced(
        sweep._current_param_indices, remove_fixed=False)
    total_count = np.prod(reduced_parameters.counts)

    def func_effective(paramindex_tuple: Tuple[int], params, **kw) -> Any:
        paramvals_tuple = params[paramindex_tuple]
        return func(
            sweep,
            paramindex_tuple=paramindex_tuple,
            paramvals_tuple=paramvals_tuple,
            **kw,
        )

    if hasattr(func, "__name__"):
        func_name = func.__name__
    else:
        func_name = ""

    data_array = list(
        tqdm(
            map(
                functools.partial(
                    func_effective,
                    params=reduced_parameters,
                    **kwargs,
                ),
                itertools.product(*reduced_parameters.ranges),
            ),
            total=total_count,
            desc="sweeping " + func_name,
            leave=False,
            disable=settings.PROGRESSBAR_DISABLED,
        ))
    data_array = np.asarray(data_array)
    return NamedSlotsNdarray(
        data_array.reshape(reduced_parameters.counts),
        reduced_parameters.paramvals_by_name,
    )
Ejemplo n.º 3
0
    def energy_by_bare_index(
        self: "ParameterSweep",
        bare_tuple: Tuple[int, ...],
        subtract_ground: bool = False,
        param_indices: Optional[NpIndices] = None,
    ) -> NamedSlotsNdarray:
        """
        Look up dressed energy most closely corresponding to the given bare-state labels

        Parameters
        ----------
        bare_tuple:
            bare state indices
        subtract_ground:
            whether to subtract the ground state energy
        param_indices:
            indices specifying the set of parameters

        Returns
        -------
            dressed energies, if lookup successful, otherwise nan;
        """
        param_indices = param_indices or self._current_param_indices
        dressed_index = self.dressed_index(bare_tuple, param_indices)

        if dressed_index is None:
            return np.nan
        if isinstance(dressed_index, int):
            energy = self["evals"][param_indices + (dressed_index, )]
            if subtract_ground:
                energy -= self["evals"][param_indices + (0, )]
            return energy

        dressed_index = np.asarray(dressed_index)
        energies = np.empty_like(dressed_index)
        it = np.nditer(dressed_index, flags=["multi_index", "refs_ok"])
        sliced_energies = self["evals"][param_indices]

        for location in it:
            location = location.tolist()
            if location is None:
                energies[it.multi_index] = np.nan
            else:
                energies[it.multi_index] = sliced_energies[
                    it.multi_index][location]
                if subtract_ground:
                    energies[it.multi_index] -= sliced_energies[
                        it.multi_index][0]
        return NamedSlotsNdarray(energies,
                                 sliced_energies._parameters.paramvals_by_name)
Ejemplo n.º 4
0
    def _bare_spectrum_sweep(
            self) -> Tuple[NamedSlotsNdarray, NamedSlotsNdarray]:
        """
        The bare energy spectra are computed according to the following scheme.
        1. Perform a loop over all subsystems to separately obtain the bare energy
            eigenvalues and eigenstates for each subsystems.
        2. If `update_subsystem_info` is given, remove those sweeps that leave the
            subsystems fixed.
        3. If self._num_cpus > 1, parallelize.

        Returns
        -------
            NamedSlotsNdarray[<paramname1>, <paramname2>, ..., "subsys"] for evals,
            likewise for evecs;
            here, "subsys": 0, 1, ... enumerates subsystems and
        """
        bare_evals = np.empty((self.subsystem_count, ), dtype=object)
        bare_evecs = np.empty((self.subsystem_count, ), dtype=object)

        for subsys_index, subsystem in enumerate(self._hilbertspace):
            bare_esys = self._subsys_bare_spectrum_sweep(subsystem)
            bare_evals[subsys_index] = NamedSlotsNdarray(
                np.asarray(bare_esys[..., 0].tolist()),
                self._parameters.paramvals_by_name,
            )
            bare_evecs[subsys_index] = NamedSlotsNdarray(
                np.asarray(bare_esys[..., 1].tolist()),
                self._parameters.paramvals_by_name,
            )

        return (
            NamedSlotsNdarray(bare_evals,
                              {"subsys": np.arange(self.subsystem_count)}),
            NamedSlotsNdarray(bare_evecs,
                              {"subsys": np.arange(self.subsystem_count)}),
        )
Ejemplo n.º 5
0
    def generate_lookup(self: "ParameterSweep") -> NamedSlotsNdarray:
        """
        For each parameter value of the parameter sweep, generate the map between
        bare states and
        dressed states.

        Returns
        -------
            each list item is a list of dressed indices whose order corresponds to the
            ordering of bare indices (as stored in .canonical_bare_labels,
            thus establishing the mapping)
        """
        dressed_indices = np.empty(shape=self._parameters.counts, dtype=object)

        param_indices = itertools.product(*map(range, self._parameters.counts))
        for index in param_indices:
            dressed_indices[index] = self._generate_single_mapping(index)
        dressed_indices = np.asarray(dressed_indices[:].tolist())

        parameter_dict = self._parameters.ordered_dict.copy()
        return NamedSlotsNdarray(dressed_indices, parameter_dict)
Ejemplo n.º 6
0
def test_named_slice():
    tst = NamedSlotsNdarray(data, paramvals_by_name)
    assert np.allclose(tst["p2":2:-1], data[:, 2:-1, :])
    assert np.allclose(tst["p2":2, "p1":0], tst["p1":0, "p2":2])
Ejemplo n.º 7
0
def test_value_access():
    tst = NamedSlotsNdarray(data, paramvals_by_name)
    param_val = float(paramvals1[4])
    assert np.allclose(tst["p1":param_val], data[4, :, :])
Ejemplo n.º 8
0
def test_name_access():
    tst = NamedSlotsNdarray(data, paramvals_by_name)
    assert np.allclose(tst["p2":1], data[:, 1, :])
Ejemplo n.º 9
0
def test_index_access():
    tst = NamedSlotsNdarray(data, paramvals_by_name)
    assert np.allclose(tst[0], data[0])
Ejemplo n.º 10
0
def test_initialize():
    tst = NamedSlotsNdarray(data, paramvals_by_name)
Ejemplo n.º 11
0
    def _dispersive_coefficients(
        self,
    ) -> Tuple[NamedSlotsNdarray, NamedSlotsNdarray, NamedSlotsNdarray]:
        energy_0 = self[:].energy_by_dressed_index(0).toarray()

        lamb_data = np.empty(self.subsystem_count, dtype=object)
        kerr_data = np.empty((self.subsystem_count, self.subsystem_count),
                             dtype=object)

        for subsys_index1, subsys1 in enumerate(self._hilbertspace):
            energy_subsys1_all_l1 = self._energies_1(subsys1)
            bare_energy_subsys1_all_l1 = self["bare_evals"][
                subsys_index1].toarray()
            lamb_subsys1_all_l1 = (
                energy_subsys1_all_l1 - energy_0[..., None] -
                bare_energy_subsys1_all_l1 +
                bare_energy_subsys1_all_l1[..., 0][..., None])
            lamb_data[subsys_index1] = NamedSlotsNdarray(
                lamb_subsys1_all_l1, self._parameters.paramvals_by_name)

            for subsys_index2, subsys2 in enumerate(self._hilbertspace):
                energy_subsys2_all_l2 = self._energies_1(subsys2)
                energy_subsys1_subsys2_all_l1_l2 = self._energies_2(
                    subsys1, subsys2)
                kerr_subsys1_subsys2_all_l1_l2 = (
                    energy_subsys1_subsys2_all_l1_l2 +
                    energy_0[..., None, None] -
                    energy_subsys1_all_l1[..., :, None] -
                    energy_subsys2_all_l2[..., None, :])
                if subsys1 is subsys2:
                    kerr_subsys1_subsys2_all_l1_l2 /= 2.0  # self-Kerr needs factor 1/2

                kerr_data[subsys_index1, subsys_index2] = NamedSlotsNdarray(
                    kerr_subsys1_subsys2_all_l1_l2,
                    self._parameters.paramvals_by_name)

        sys_indices = np.arange(self.subsystem_count)
        lamb_data = NamedSlotsNdarray(lamb_data, {"subsys": sys_indices})
        kerr_data = NamedSlotsNdarray(kerr_data, {
            "subsys1": sys_indices,
            "subsys2": sys_indices
        })
        chi_data = kerr_data.copy()

        for subsys_index1, subsys1 in enumerate(self._hilbertspace):
            for subsys_index2, subsys2 in enumerate(self._hilbertspace):
                if subsys1 in self.osc_subsys_list:
                    if subsys2 in self.qbt_subsys_list:
                        chi_data[subsys_index1,
                                 subsys_index2] = chi_data[subsys_index1,
                                                           subsys_index2][...,
                                                                          1, :]
                        kerr_data[subsys_index1,
                                  subsys_index2] = np.asarray([])
                    else:
                        chi_data[subsys_index1, subsys_index2] = np.asarray([])
                elif subsys1 in self.qbt_subsys_list:
                    if subsys2 in self.osc_subsys_list:
                        chi_data[subsys_index1, subsys_index2] = chi_data[
                            subsys_index1, subsys_index2][..., :, 1]
                        kerr_data[subsys_index1,
                                  subsys_index2] = np.asarray([])
                    else:
                        chi_data[subsys_index1, subsys_index2] = np.asarray([])

        return lamb_data, chi_data, kerr_data