예제 #1
0
    def __init__(self,
                 N: int,
                 V: float,
                 geometry: BaseGeometry,
                 Omega: np.ndarray,
                 Delta: np.ndarray,
                 t_list: np.ndarray,
                 ghz_state: BaseGHZState,
                 solve_points_per_timestep: int = 1):
        super().__init__(N, V, geometry)

        self.Omega = Omega
        self.Delta = Delta
        self.t_list = t_list

        assert len(t_list) - 1 == len(Omega) == len(Delta), \
            "Omega and Delta need to be of equal length, and of length one less than t_list"

        self.psi_0 = q.kron(*states_quimb.get_ground_states(N))
        self.ghz_state = ghz_state

        self.solve_points_per_timestep = solve_points_per_timestep

        self.evo: Optional[q.Evolution] = None
        self.solved_states: List[q.qarray] = []
        self.solved_t_list = []
예제 #2
0
    def get_fidelity_with(self,
                          target_state: Union[str, q.qarray] = "ghz") -> float:
        """
        :param target_state:
            One of "ghz", "ghz_antisymmetric", "ground", and "excited".
            Can also be ghz_component_1 or ghz_component_2
        :return:
        """
        assert (
            self.evo
            is not None), "evo attribute cannot be None (call solve method)"

        final_state = self.solved_states[-1]
        if target_state == "ghz":
            return q.fidelity(final_state,
                              self.ghz_state.get_state_tensor(symmetric=True))
        elif target_state == "ghz_antisymmetric":
            return q.fidelity(final_state,
                              self.ghz_state.get_state_tensor(symmetric=False))
        elif target_state == "ghz_component_1":
            return q.fidelity(final_state, self.ghz_state._get_components()[0])
        elif target_state == "ghz_component_2":
            return q.fidelity(final_state, self.ghz_state._get_components()[1])
        elif target_state == "ground":
            return q.fidelity(final_state,
                              q.kron(*states_quimb.get_ground_states(self.N)))
        elif target_state == "excited":
            return q.fidelity(final_state,
                              q.kron(*states_quimb.get_excited_states(self.N)))
        elif isinstance(target_state, q.qarray):
            return q.fidelity(final_state, target_state)
        else:
            raise ValueError(
                f"target_state has to be one of 'ghz', 'ground', or 'excited', not {target_state}."
            )
예제 #3
0
def plot_detuning_energy_levels(s_qs: StaticQubitSystem,
                                crossings: np.ndarray,
                                ax: Axes,
                                highlighted_indices: Sequence[int] = (-1, )):
    if s_qs.Omega_zero_energies is None:
        s_qs.get_energies()

    crossings_range = crossings.max() - crossings.min()
    xlims = crossings_range * -0.1, crossings.max() * 1.1
    s_qs = StaticQubitSystem(s_qs.N,
                             s_qs.V,
                             s_qs.geometry,
                             Omega=0,
                             Delta=np.linspace(xlims[0], xlims[1], 20))
    s_qs.get_energies()

    g = states_quimb.get_ground_states(1)[0]
    for i, state in enumerate(s_qs.states):
        is_highlight_state = any(state is s_qs.states[i]
                                 for i in highlighted_indices)
        is_ground_state = all((_state == g).all() for _state in state)

        color = 'g' if is_ground_state else 'r' if is_highlight_state else 'grey'
        linewidth = 5 if is_ground_state or is_highlight_state else 1
        z_order = 2 if is_ground_state or is_highlight_state else 1
        energies = s_qs.Omega_zero_energies[:, i]
        ax.plot(s_qs.Delta,
                energies,
                color=color,
                alpha=0.6,
                lw=linewidth,
                zorder=z_order,
                label=states_quimb.get_label_from_state(state),
                picker=3)

    def on_pick(event):
        line = event.artist
        print(f'Clicked on: {line.get_label()}')

    plt.gcf().canvas.mpl_connect('pick_event', on_pick)

    ax.grid()
    scaled_xaxis_ticker = ticker.EngFormatter(unit="Hz")
    scaled_yaxis_ticker = ticker.EngFormatter(unit="Hz")
    ax.xaxis.set_major_formatter(scaled_xaxis_ticker)
    ax.yaxis.set_major_formatter(scaled_yaxis_ticker)
    ax.locator_params(nbins=4)

    # plt.title(rf"Energy spectrum with $N = {self.N}$, $V = {self.V:0.2e}$, $\Omega = {self.Omega:0.2e}$")
    _m, _s = f"{s_qs.V:0.2e}".split('e')
    V_text = rf"{_m:s} \times 10^{{{int(_s):d}}}"
    plt.title(rf"Energy spectrum with $N = {s_qs.N}$, $V = {V_text:s}$ Hz")
    plt.xlabel(r"Detuning $\Delta$")
    plt.ylabel("Eigenenergy")

    plt.xlim(xlims)
    plt.tight_layout()
예제 #4
0
    def __init__(self,
                 N: int,
                 V: float,
                 geometry: BaseGeometry,
                 t_list: np.ndarray,
                 ghz_state: BaseGHZState,
                 Omega_range: Tuple[float, float],
                 Delta_range: Tuple[float, float],
                 verbose: bool = False):
        self.verbose = verbose

        self.ti_evolving_qubit_system_kwargs = {
            'N': N,
            'V': V,
            'geometry': geometry,
            'ghz_state': ghz_state,
            't_list': np.linspace(0, t_list[1], 10)
        }
        self.psi_0 = q.kron(*states_quimb.get_ground_states(N))
        self.t_list = t_list

        self.required_steps = len(t_list) - 1
        # Actions for all ts except the end.

        self.recorded_steps = {
            'Omega': [],
            'Delta': [],
        }
        self.step_number = 0
        self.latest_evolving_qubit_system: Optional[
            TimeIndependentEvolvingQubitSystem] = None
        self.total_solve_time = 0

        self.action_normalisation = Omega_range, Delta_range
        self.action_space = gym.spaces.Box(low=np.array([0, 0],
                                                        dtype=np.float32),
                                           high=np.array([1, 1],
                                                         dtype=np.float32))
        # Using action_normalisation as PPO policy generates actions of order 1

        self.observation_space = gym.spaces.Discrete(self.required_steps)

        self._maximum_fidelity_achieved = 0.505
예제 #5
0
    def __init__(self,
                 N: int,
                 V: float,
                 geometry: BaseGeometry,
                 Omega: float,
                 Delta: float,
                 t_list: np.ndarray,
                 ghz_state: BaseGHZState,
                 psi_0: q.qarray = None):
        super().__init__(N, V, geometry)

        self.Omega = Omega
        self.Delta = Delta
        self.t_list = t_list

        self.psi_0 = q.kron(*states_quimb.get_ground_states(
            N, sparse=True)) if psi_0 is None else psi_0
        self.ghz_state = ghz_state

        self.evo: Optional[q.Evolution] = None
        self.solved_states: List[q.qarray] = []
예제 #6
0
    def plot_basis_states_overlaps(self,
                                   ax,
                                   plot_title: bool = True,
                                   plot_others_as_sum: bool = False):
        states = states_quimb.get_states(self.N) if not plot_others_as_sum \
            else [states_quimb.get_excited_states(self.N), states_quimb.get_ground_states(self.N)]
        fidelities = []

        plot_individual_orthogonal_state_labels = len(states) <= 4
        plotted_others = False
        # for i, state in enumerate(tqdm(states)):
        for i, state in enumerate(states):
            label = states_quimb.get_label_from_state(state)
            state_product_basis_index = states_quimb.get_product_basis_states_index(
                state)
            state_fidelities = [
                np.abs(_instantaneous_state.flatten()
                       [state_product_basis_index])**2
                for _instantaneous_state in self.solved_states
            ]

            if 'e' not in label or 'g' not in label:
                fidelities.append(state_fidelities)

            if ('e' not in label or 'g' not in label):
                plot_label = r"$P_{" + f"{label.upper()[0]}" + "}$"
            elif plot_individual_orthogonal_state_labels:
                plot_label = r"$P_{" + f"{label.upper()}" + "}$"
            else:
                plot_label = 'Others'

            if plot_label == 'Others':
                if plotted_others:
                    plot_label = None
                else:
                    plotted_others = True

            ax.plot(
                self.solved_t_list,
                state_fidelities,
                label=plot_label,
                color='g'
                if 'e' not in label else 'r' if 'g' not in label else 'k',
                linewidth=1 if 'e' not in label or 'g' not in label else 0.5,
                alpha=0.5)

        fidelities_sum = np.array(fidelities).sum(axis=0)
        ax.plot(self.solved_t_list,
                fidelities_sum,
                label="$P_{E} + P_{G}$",
                color='C0',
                linestyle=":",
                linewidth=1,
                alpha=0.7)

        if plot_others_as_sum:
            others_sum = 1 - fidelities_sum

            ax.plot(self.solved_t_list,
                    others_sum,
                    label=r"$\sum{\textrm{Others}}$",
                    color='C1',
                    linestyle=":",
                    linewidth=1,
                    alpha=0.7)

        ax.set_ylabel("Population")
        if plot_title:
            ax.set_title("Basis state populations")
        ax.set_ylim((-0.1, 1.1))
        ax.yaxis.set_ticks([0, 0.5, 1])

        # ax.legend()
        handles, labels = ax.get_legend_handles_labels()
        # sort both labels and handles by labels
        labels, handles = zip(*sorted(zip(labels, handles)))
        ax.legend(handles, labels)
예제 #7
0
 def _get_components(self) -> Tuple[q.qarray, q.qarray]:
     return q.kron(*get_ground_states(self.N, sparse=True)), q.kron(
         *get_excited_states(self.N, sparse=True))