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 ** num_qubits ) self.sigmav = pauli.get_pauli_n_qubit_projection( num_qubits, location ) self.sigmav = self.Hcoef * self.sigmav
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 )
def __init__(self, utry, location): """ Gate Class Constructor Args: utry (np.ndarray): The gate's unitary operation. location (tuple[int]): The set of qubits the gate acts on. Raises: TypeError: If unitary or location are invalid. """ if not utils.is_unitary(utry, tol=1e-14): raise TypeError("Invalid unitary.") self.utry = utry self.num_qubits = utils.get_num_qubits(self.utry) if not utils.is_valid_location(location): raise TypeError("Invalid location.") if len(location) != self.num_qubits: raise ValueError("Invalid size of location.") self.location = location
def test_is_valid_location_invalid1(self): self.assertFalse(is_valid_location("a")) self.assertFalse(is_valid_location(0)) self.assertFalse(is_valid_location("a", 256)) self.assertFalse(is_valid_location(0, 256))
def test_is_valid_location_valid(self): self.assertTrue(is_valid_location((0, 1, 2))) self.assertTrue(is_valid_location((0, 1, 2), 3)) self.assertTrue(is_valid_location((0, 1, 2, 17))) self.assertTrue(is_valid_location((0, 1, 2, 17), 18))
def test_is_valid_location_empty(self): self.assertTrue(is_valid_location(tuple())) self.assertTrue(is_valid_location(tuple(), 0)) self.assertTrue(is_valid_location(tuple(), 3))
def test_is_valid_location_invalid4(self): self.assertFalse(is_valid_location((0, 1, 2), 1)) self.assertFalse(is_valid_location((0, 1, 2), 0))
def test_is_valid_location_invalid3(self): self.assertFalse(is_valid_location((0, 0))) self.assertFalse(is_valid_location((0, 0), 256))
def test_is_valid_location_invalid2(self): self.assertFalse(is_valid_location((0, "a", 2))) self.assertFalse(is_valid_location((0, "a", 2), 256))
def calc_permutation_matrix(num_qubits, location): """ Creates the permutation matrix specified by arguments. This is done by moving the first len( locations ) qubits into positions defined by location. Args: num_qubits (int): Total number of qubits location (Tuple[int]): The desired locations to swap the starting qubits to. Returns: (np.ndarray): The permutation matrix Examples: calc_permutation_matrix( 2, (0, 1) ) = [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ] Here the 4x4 identity is returned because their are 2 total qubits, specified by the first parameter, and the desired permutation is [0, 1] -> [0, 1]. calc_permutation_matrix( 2, (1,) ) = calc_permutation_matrix( 2, (1, 0) ) = [ [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ] This is a more interesting example. The swap gate is returned here since we are working with 2 qubits and want the permutation that swaps the two qubits, giving by the permutation [0] -> [1] or in the second case [0, 1] -> [1, 0]. Both calls produce identical permutations. """ if not utils.is_valid_location(location, num_qubits): raise TypeError("Invalid location.") max_qubit = np.max(location) num_core_qubits = max_qubit + 1 num_gate_qubits = len(location) perm = cb.Permutation(2**num_core_qubits) temp_pos = list(range(num_gate_qubits)) for q in range(num_gate_qubits): perm *= swap(temp_pos[q], location[q], num_core_qubits) if location[q] < num_gate_qubits: temp_pos[location[q]] = temp_pos[q] matrix = np.identity(2**num_core_qubits) for transpos in reversed(perm.transpositions()): matrix[list(transpos), :] = matrix[list(reversed(transpos)), :] if num_qubits - num_core_qubits > 0: matrix = np.kron(matrix, np.identity(2**(num_qubits - num_core_qubits))) return np.array(matrix)