def test_calc_permutation_matrix_big(self):
        I = np.identity(2, dtype=np.complex128)
        II = np.kron(I, I)
        IIII = np.kron(II, II)
        X = np.array([[0, 1], [1, 0]], dtype=np.complex128)
        XX = np.kron(X, X)
        XXI = np.kron(XX, I)
        IXX = np.kron(I, XX)
        IIXX = np.kron(I, IXX)
        IX = np.kron(I, X)
        IXIX = np.kron(IX, IX)
        XXXX = np.kron(XX, XX)
        IXIXIXIX = np.kron(IXIX, IXIX)

        U0 = sp.linalg.expm(-1j * IXX)
        U1 = sp.linalg.expm(-1j * XXI)
        P = calc_permutation_matrix(3, (1, 2))
        self.assertTrue(np.allclose(U0, P @ U1 @ P.T))

        U0 = sp.linalg.expm(-1j * IIXX)
        U1 = sp.linalg.expm(-1j * IXIX)
        P = calc_permutation_matrix(4, (0, 2))
        self.assertTrue(np.allclose(U0, P @ U1 @ P.T))

        U0 = sp.linalg.expm(-1j * IXIXIXIX)
        U1 = sp.linalg.expm(-1j * np.kron(XXXX, IIII))
        P = calc_permutation_matrix(8, (1, 3, 5, 7))
        self.assertTrue(np.allclose(U0, P @ U1 @ P.T))
Esempio n. 2
0
    def test_toffoli_tensor ( self ):
        toffoli = np.array( [ [ 1, 0, 0, 0, 0, 0, 0, 0 ],
                              [ 0, 1, 0, 0, 0, 0, 0, 0 ],
                              [ 0, 0, 1, 0, 0, 0, 0, 0 ],
                              [ 0, 0, 0, 1, 0, 0, 0, 0 ],
                              [ 0, 0, 0, 0, 1, 0, 0, 0 ],
                              [ 0, 0, 0, 0, 0, 1, 0, 0 ],
                              [ 0, 0, 0, 0, 0, 0, 0, 1 ],
                              [ 0, 0, 0, 0, 0, 0, 1, 0 ] ] )

        p12 = calc_permutation_matrix( 3, (1, 2) )
        p02 = calc_permutation_matrix( 3, (0, 2) )

        cnot = np.array( [ [ 1, 0, 0, 0 ],
                           [ 0, 1, 0, 0 ],
                           [ 0, 0, 0, 1 ],
                           [ 0, 0, 1, 0 ] ] )

        H = (np.sqrt(2)/2) * np.array( [ [ 1, 1 ],
                                         [ 1, -1 ] ] )

        T = np.array( [ [ 1, 0 ], [ 0, np.exp( 1j * np.pi/4 ) ] ] )
        I = np.identity( 2 )

        u1 = np.kron( I, T.conj().T ) @ cnot @ np.kron( I, H )
        u2 = np.kron( I, T ) @ cnot
        u3 = np.kron( I, T.conj().T ) @ cnot
        u4 = np.kron( I, H @ T ) @ cnot
        u5 = cnot @ np.kron( T, T.conj().T ) @ cnot @ np.kron( I, T )

        circuit = [ Gate( u1, (1, 2) ),
                    Gate( u2, (0, 2) ),
                    Gate( u3, (1, 2) ),
                    Gate( u4, (0, 2) ),
                    Gate( u5, (0, 1) ) ]


        c1 = p12 @ np.kron( u1, I ) @ p12.T
        c2 = p02 @ np.kron( u2, I ) @ p02.T
        c3 = p12 @ np.kron( u3, I ) @ p12.T
        c4 = p02 @ np.kron( u4, I ) @ p02.T
        c5 = np.kron( u5, I )
        self.assertTrue( np.allclose( toffoli, c5 @ c4 @ c3 @ c2 @ c1 ) )


        ct = CircuitTensor( toffoli, [] )
        self.assertTrue( np.allclose( ct.utry, toffoli.conj().T  ) )
        ct.apply_right( circuit[0] )
        self.assertTrue( np.allclose( ct.utry, c1 @ toffoli.conj().T ) )
        ct.apply_right( circuit[1] )
        self.assertTrue( np.allclose( ct.utry, c2 @ c1 @ toffoli.conj().T ) )
        ct.apply_right( circuit[2] )
        self.assertTrue( np.allclose( ct.utry, c3 @ c2 @ c1 @ toffoli.conj().T ) )
        ct.apply_right( circuit[3] )
        self.assertTrue( np.allclose( ct.utry, c4 @ c3 @ c2 @ c1 @ toffoli.conj().T ) )
        ct.apply_right( circuit[4] )
        self.assertTrue( np.allclose( ct.utry, c5 @ c4 @ c3 @ c2 @ c1 @ toffoli.conj().T ) )
        self.assertTrue( np.allclose( ct.utry, np.identity( 8 ) ) )
        ct = CircuitTensor( toffoli, circuit )
        self.assertTrue( np.allclose( ct.utry, np.identity( 8 ) ) )
    def test_calc_permutation_matrix(self):
        swap_012 = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0],
                             [0, 0, 0, 1]])

        perm = calc_permutation_matrix(2, (1, 0))
        self.assertTrue(np.allclose(perm, swap_012))

        perm = calc_permutation_matrix(2, (1, ))
        self.assertTrue(np.allclose(perm, swap_012))

        perm = calc_permutation_matrix(2, (0, 1))
        self.assertTrue(np.allclose(perm, np.identity(4)))
Esempio n. 4
0
    def __init__ ( self, num_qubits, gate_size, location ):
        """
        FixedGate Constructor

        Args:
            num_qubits (int): The number of qubits in the entire circuit

            gate_size (int): The number of qubits this gate acts on

            location (tuple[int]): The qubits this gate acts on
        """

        super().__init__( num_qubits, gate_size )

        if not utils.is_valid_location( location, num_qubits ):
            raise TypeError( "Specified location is invalid." )

        if len( location ) != gate_size:
            raise ValueError( "Location does not match gate size." )

        self.location = location

        self.Hcoef = -1j / ( 2 ** self.num_qubits )
        self.paulis = pauli.get_norder_paulis( self.gate_size )
        self.sigmav = self.Hcoef * np.array( self.paulis )
        self.I = np.identity( 2 ** ( num_qubits - gate_size ) )
        self.perm_matrix = perm.calc_permutation_matrix( num_qubits, location )
Esempio n. 5
0
    def __init__ ( self, num_qubits, gate_size, locations ):
        """
        GenericGate Constructor

        Args:
            num_qubits (int): The number of qubits in the entire circuit

            gate_size (int): The number of qubits this gate acts on

            locations (list[tuple[int]]): The potential locations of this gate
        """

        super().__init__( num_qubits, gate_size )

        if not utils.is_valid_locations( locations, num_qubits, gate_size ):
            raise TypeError( "Specified locations is invalid." )

        self.locations = locations

        self.Hcoef = -1j / ( 2 ** self.num_qubits )
        self.paulis = pauli.get_norder_paulis( self.gate_size )
        self.sigmav = self.Hcoef * np.array( self.paulis )
        self.I = np.identity( 2 ** ( num_qubits - gate_size ) )
        self.perms = np.array( [ perm.calc_permutation_matrix( num_qubits, l )
                                 for l in self.locations ] )

        self.working_locations = deepcopy( locations )
        self.working_perms = np.copy( self.perms )
Esempio n. 6
0
def get_utry(circ):
    """Converts a qiskit circuit into a numpy unitary."""

    backend = qiskit.BasicAer.get_backend('unitary_simulator')
    utry = qiskit.execute(circ, backend).result().get_unitary()
    num_qubits = int(np.log2(len(utry)))
    qubit_order = tuple(reversed(range(num_qubits)))
    P = perm.calc_permutation_matrix(num_qubits, qubit_order)
    return P @ utry @ P.T
Esempio n. 7
0
File: qs.py Progetto: BQSKit/qfast
    def synthesize(self, utry, **kwargs):
        """
        Synthesis function with this tool.

        Args:
            utry (np.ndarray): The unitary to synthesize.

        Returns
            qasm (str): The synthesized QASM output.

        Raises:
            TypeError: If utry is not a valid unitary.

            ValueError: If the utry has invalid dimensions.
        """

        if not utils.is_unitary(utry, tol=1e-14):
            raise TypeError("utry must be a valid unitary.")

        if utry.shape[0] > 2**self.get_maximum_size():
            raise ValueError("utry has incorrect dimensions.")

        # Parse kwargs
        basis_gates = ["cx"]
        coupling_graph = [(0, 1), (1, 2)]
        if "basis_gates" in kwargs:
            basis_gates = kwargs["basis_gates"] or basis_gates
        if "coupling_graph" in kwargs:
            coupling_graph = kwargs["coupling_graph"] or coupling_graph

        # Prepermute unitary to line up coupling_graph
        # This is done because qsearch handles pure linear topologies best
        if utils.get_num_qubits(utry) == 3:
            a = (0, 1) in coupling_graph
            b = (1, 2) in coupling_graph
            c = (0, 2) in coupling_graph

            if not (a and b):
                if (a and c):
                    # Permute 0 and 1
                    P = perm.calc_permutation_matrix(3, (1, 0, 2))
                    utry = P @ utry @ P.T
                elif (b and c):
                    # Permute 1 and 2
                    P = perm.calc_permutation_matrix(3, (0, 2, 1))
                    utry = P @ utry @ P.T
                else:
                    raise ValueError("Invalid coupling graph.")

        # Pass options into qsearch, being maximally quiet,
        # and set the target to utry
        opts = options.Options()
        opts.target = utry
        opts.gateset = self.map_basis_str_to_gateset(basis_gates)
        opts.verbosity = 0
        opts.write_to_stdout = False
        opts.reoptimize_size = 7

        # use the LEAP compiler, which scales better than normal qsearch
        compiler = leap_compiler.LeapCompiler()
        output = compiler.compile(opts)

        # LEAP requires some post-processing
        pp = post_processing.LEAPReoptimizing_PostProcessor()
        output = pp.post_process_circuit(output, opts)
        output = assemblers.ASSEMBLER_IBMOPENQASM.assemble(output)

        # Renumber qubits in circuit if we flipped the unitary
        if utils.get_num_qubits(utry) == 3:
            a = (0, 1) in coupling_graph
            b = (1, 2) in coupling_graph
            c = (0, 2) in coupling_graph

            if not (a and b):
                if (a and c):
                    # Permute 0 and 1
                    str0 = "[0]"
                    str1 = "[1]"

                elif (b and c):
                    # Permute 1 and 2
                    str0 = "[1]"
                    str1 = "[2]"

                output = output.replace(str0, "[tmp]")
                output = output.replace(str1, str0)
                output = output.replace("[tmp]", str1)

        return output