Example #1
0
    def test_construct_valid_phase_vector(self):
        # Check the p returned is unchanged when the seed is valid.
        s, p = symplectic.random_clifford(self.n)
        pvalid = symplectic.construct_valid_phase_vector(s, p)
        self.assertArraysEqual(p, pvalid)

        # Check that p returned is a valid Clifford when the input pseed is not
        pseed = (p - 1) % 2
        pvalid = symplectic.construct_valid_phase_vector(s, pseed)
        self.assertTrue(symplectic.check_valid_clifford(s, pvalid))
Example #2
0
    def test_inverse_clifford(self):
        # Check the inverse Clifford function runs, and gives a valid Clifford
        s, p = symplectic.random_clifford(self.n)
        sin, pin = symplectic.inverse_clifford(s, p)
        self.assertTrue(symplectic.check_valid_clifford(sin, pin))

        # Check the symplectic matrix part of the inverse Clifford works
        self.assertArraysEqual(matrixmod2.dotmod2(sin, s),
                               np.identity(2 * self.n, int))
        self.assertArraysEqual(matrixmod2.dotmod2(s, sin),
                               np.identity(2 * self.n, int))
Example #3
0
    def _apply_clifford_to_frame(self, s, p, qubit_filter):
        """
        Applies a clifford in the symplectic representation to this
        stabilize frame -- similar to `apply_clifford_to_stabilizer_state`
        but operates on an entire *frame*

        Parameters
        ----------
        s : numpy array
            The symplectic matrix over the integers mod 2 representing the Clifford

        p : numpy array
            The 'phase vector' over the integers mod 4 representing the Clifford
        """
        n = self.n
        assert (_symp.check_valid_clifford(
            s, p)), "The `s`,`p` matrix-vector pair is not a valid Clifford!"

        if qubit_filter is not None:
            s, p = _symp.embed_clifford(
                s, p, qubit_filter, n)  # for now, just embed then act normally
            #FUTURE: act just on the qubits we need to --> SPEEDUP!

        # Below we calculate the s and p for the output state using the formulas from
        # Hostens and De Moor PRA 71, 042315 (2005).
        out_s = _mtx.dot_mod2(s, self.s)

        inner = _np.dot(_np.dot(_np.transpose(s), self.u), s)
        vec1 = _np.dot(_np.transpose(self.s), p - _mtx.diagonal_as_vec(inner))
        matrix = 2 * _mtx.strictly_upper_triangle(
            inner) + _mtx.diagonal_as_matrix(inner)
        vec2 = _mtx.diagonal_as_vec(
            _np.dot(_np.dot(_np.transpose(self.s), matrix), self.s))

        self.s = out_s  # don't set this until we're done using self.s
        for i in range(len(self.ps)):
            self.ps[i] = (self.ps[i] + vec1 + vec2) % 4
Example #4
0
    def test_random_clifford(self):
        # Check the Clifford sampler runs.
        s, p = symplectic.random_clifford(self.n)

        # Check that a randomly sampled Clifford is a valid Clifford
        self.assertTrue(symplectic.check_valid_clifford(s, p))
Example #5
0
    def test_symplectic(self):
        # Tests that check the symplectic random sampler, check_symplectic, the convention converter,
        # and the symplectic form constructing function are working.

        # Randomly have odd or even dimension (so things might behave differently for odd or even)
        n = 4 + np.random.randint(0, 2)

        omega_S = symplectic.symplectic_form(n, convention='standard')
        #print(omega_S)
        omega_DS = symplectic.symplectic_form(n, convention='directsum')
        #print(omega_DS)
        omega_DStoS = symplectic.change_symplectic_form_convention(omega_DS)
        self.assertArraysEqual(omega_S, omega_DStoS)
        omega_StoDS = symplectic.change_symplectic_form_convention(
            omega_S, outconvention='directsum')
        self.assertArraysEqual(omega_DS, omega_StoDS)

        # Pick a random symplectic matrix in the standard convention and check it is symplectic
        s_S = symplectic.random_symplectic_matrix(n)
        self.assertTrue(symplectic.check_symplectic(s_S))

        # Pick a random symplectic matrix in the directsum convention and check it is symplectic
        s_DS = symplectic.random_symplectic_matrix(n, convention='directsum')
        self.assertTrue(
            symplectic.check_symplectic(s_DS, convention='directsum'))

        # Convert the directsum convention to the standard convention and check the output is symplectic in new convention
        s_DStoS = symplectic.change_symplectic_form_convention(s_DS)
        self.assertTrue(
            symplectic.check_symplectic(s_DStoS, convention='standard'))

        # Convert back to the directsum convention, and check the original matrix is recovered.
        s_DStoStoDS = symplectic.change_symplectic_form_convention(
            s_DStoS, outconvention='directsum')
        self.assertArraysEqual(s_DS, s_DStoStoDS)

        # Check that the inversion function is working.
        sin = symplectic.inverse_symplectic(s_S)
        self.assertArraysEqual(matrixmod2.dotmod2(sin, s_S),
                               np.identity(2 * n, int))
        self.assertArraysEqual(matrixmod2.dotmod2(s_S, sin),
                               np.identity(2 * n, int))

        # Check the Clifford sampler runs.
        s, p = symplectic.random_clifford(n)

        # Check that a randomly sampled Clifford is a valid Clifford
        self.assertTrue(symplectic.check_valid_clifford(s, p))

        # Check the inverse Clifford function runs, and gives a valid Clifford
        sin, pin = symplectic.inverse_clifford(s, p)
        self.assertTrue(symplectic.check_valid_clifford(sin, pin))

        # Check the symplectic matrix part of the inverse Clifford works
        self.assertArraysEqual(matrixmod2.dotmod2(sin, s),
                               np.identity(2 * n, int))
        self.assertArraysEqual(matrixmod2.dotmod2(s, sin),
                               np.identity(2 * n, int))

        # Check that the composite Clifford function runs, and works correctly in the special case whereby
        # one Clifford is the inverse of the other.
        scomp, pcomp = symplectic.compose_cliffords(s, p, sin, pin)
        self.assertArraysEqual(scomp, np.identity(2 * n, int))
        self.assertArraysEqual(pcomp, np.zeros(2 * n, int))

        # Check the p returned is unchanged when the seed is valid.
        pvalid = symplectic.construct_valid_phase_vector(s, p)
        self.assertArraysEqual(p, pvalid)

        # Check that p returned is a valid Clifford when the input pseed is not
        pseed = (p - 1) % 2
        pvalid = symplectic.construct_valid_phase_vector(s, pseed)
        self.assertTrue(symplectic.check_valid_clifford(s, pvalid))

        # Basic tests of the symp. rep. dictionary
        srep_dict = symplectic.get_internal_gate_symplectic_representations()

        H = (1 / np.sqrt(2)) * np.array([[1., 1.], [1., -1.]], complex)
        s, p = symplectic.unitary_to_symplectic(H)
        self.assertArraysEqual(s, srep_dict['H'][0])
        self.assertArraysEqual(p, srep_dict['H'][1])

        CNOT = np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 0., 1.],
                         [0., 0., 1., 0.]], complex)
        s, p = symplectic.unitary_to_symplectic(CNOT)
        self.assertArraysEqual(s, srep_dict['CNOT'][0])
        self.assertArraysEqual(p, srep_dict['CNOT'][1])