예제 #1
0
    def addCoupling(self, initial_state, final_state, rabi_rate, omega):
        """
        Add a coupling between two states

        Parameters:
        initial_state  : initial coupled state
        final_state    : final coupled state
        rabi_rate      : rabi rate of coupling between initial and final, Symbol
        omega          : requency of coupling between initial and final, Symbol
        """
        if  (initial_state > self.hamiltonian.shape[0]) or \
            (final_state > self.hamiltonian.shape[0]):
            raise AssertionError('Specified state exceeds size of Hamiltonian')

        # setting the frequency and rabi rate of the coupling to the symbolic
        # matrices
        self.couplings[initial_state, final_state] = omega
        self.rabi[initial_state, final_state] = rabi_rate

        # adding the coupling frequency to the frequencies list if not already
        # present
        if omega not in self.frequencies:
            self.frequencies.append(omega)

        # adding the appropriote terms to the symbolic Hamiltonian matrix
        t = Symbol('t', real=True)
        self.hamiltonian[initial_state, final_state] = \
                                            -rabi_rate/2*symb_exp(1j*omega*t)
        self.hamiltonian[final_state, initial_state] = \
                                -conjugate(rabi_rate)/2*symb_exp(-1j*omega*t)
        # incrementing the number of couplings counter from a specific initial
        # state
        self.cpl[initial_state] += 1
예제 #2
0
    def generalTransform(self, graph):
        """
        """
        if not self.zero_energy:
            raise AssertionError(
                'Zero energy has to be specified for this transformation method.'
            )

        t = Symbol('t', real=True)

        T = eye(self.levels)
        for i in range(self.levels):
            phase = self.shortestCouplingPath(graph, i)
            T[i, i] = T[i, i] * symb_exp(1j * phase * t)
        T = simplify(T)

        self.transformed = T.adjoint()@self.hamiltonian@T \
                                -1j*T.adjoint()@diff(T,Symbol('t', real = True))

        if self.detunings:
            print(self.detunings)
            for i in range(len(self.detunings)):
                detuning = self.detunings[i]
                self.transformed = self.transformed.subs(
                    detuning[3], detuning[1] - detuning[0] - detuning[2])

        if self.zero_energy:
            self.transformed = self.transformed.subs(self.zero_energy, 0)

        self.T = T
예제 #3
0
    def addPolyCoupling(self, initial_state, final_state, rabi_rate, omega):
        """
        """
        if (initial_state > self.levels) or (final_state > self.levels):
            raise AssertionError('Specified state exceeds size of Hamiltonian')

        self.couplings[initial_state, final_state] = omega
        self.rabi[initial_state, final_state] = rabi_rate

        if omega not in self.frequencies:
            self.frequencies.append(omega)

        t = Symbol('t', real=True)
        self.hamiltonian[initial_state, final_state] -= \
                                                rabi_rate/2*symb_exp(1j*omega*t)
        self.hamiltonian[final_state, initial_state] -= \
                                    conjugate(rabi_rate)/2*symb_exp(-1j*omega*t)
        self.cpl[initial_state] += 1
예제 #4
0
    def eqnTransform(self):
        """
        Calculate the rotational wave approximation by solving a system of 
        equations, only usable if the number of couplings does not exceed the 
        number of states
        """
        A = symbols(f'a0:{self.levels}')

        Eqns = []
        for i in range(len(A)):
            for j in range(len(A)):
                if self.couplings[i, j] != 0:
                    Eqns.append(self.couplings[i, j] - (A[i] - A[j]))

        sol = solve(Eqns, A)
        free_params = [value for value in A if value not in list(sol.keys())]
        for free_param in free_params:
            for key, val in sol.items():
                sol[key] = val.subs(free_param, 0)

        T = zeros(*self.hamiltonian.shape)
        for i in range(self.hamiltonian.shape[0]):
            try:
                T[i, i] = symb_exp(1j * sol[Symbol(f'a{i}')] *
                                   Symbol('t', real=True))
            except KeyError:
                T[i, i] = 1
        self.T = T

        self.transformed = T.adjoint()@self.hamiltonian@T \
                                -1j*T.adjoint()@diff(T,Symbol('t', real = True))
        self.transformed = simplify(self.transformed)

        for i in range(self.levels):
            for j in range(i + 1, self.levels):
                if self.transformed[i, j] != 0:
                    if self.rabi[i, j] != 0:
                        val = self.transformed[i, j] * 2 / self.rabi[i, j]
                    else:
                        val = self.transformed[j, i] * 2 / self.rabi[j, i]
                    if not np.any(np.isclose(float(val), [-1, 1])):
                        raise AssertionError(
                            'Could not find unitary transformation')