Source code for qugradlab.systems.skeletons.qubits.qubit_skeleton

  1"""
  2Defines functions for constructing the skeleton out of Pauli operators.
  3"""
  4
  5import functools
  6
  7import numpy as np
  8
  9from .... import hilbert_spaces
 10
 11PAULI = np.array([[[ 0,  1 ],  # Pauli-X
 12                   [ 1,  0 ]],
 13                  [[ 0,  1j],  # Pauli-Y
 14                   [-1j, 0 ]],
 15                  [[-1,  0 ],  # Pauli-Z
 16                   [ 0,  1 ]]])
 17
 18LADDER_BASIS = np.array([[[ 0,  1],
 19                          [ 0,  0]],
 20                         [[ 0,  0],
 21                          [ 1,  0]],
 22                         [[-1, 0],
 23                          [ 0,  1]]])
 24
[docs] 25def second_order_tensor(hilbert_space: hilbert_spaces.QubitSpace, 26 xyz_basis: bool = True): 27 r""" 28 Generates a tensor given by the following expression 29 $$ 30 t_{i,j,\alpha,\beta}\coloneqq \left(\sigma^{(i)}_j\right)_{\alpha,\beta} 31 $$ 32 where $\sigma^{(i)}_j$ is the $j$th Pauli operator acting on the $i$th 33 qubit, and $\alpha$ and $\beta$ are the rows and columns of the matrix 34 representation of the operator $\sigma^{(i)}_j$ in the computational basis. 35 36 Parameters 37 ---------- 38 hilbert_space: QubitSpace 39 The hilbert space of the qubits 40 xyz_basis: bool 41 Uses the Pauli basis if ``True`` and the 42 $\sigma_{\pm}\coloneqq(\sigma_1\pm i\sigma_2)/2$ and Pauli-z basis if 43 ``False``, by default ``True`` 44 45 Returns 46 ------- 47 NDArray[Shape[``hilbert_space.qubits``, 3, ``hilbert_space.dim``, ``hilbert_space.dim``], int] 48 The second order skeleton tensor 49 """ 50 basis = PAULI if xyz_basis else LADDER_BASIS 51 qubits = hilbert_space.qubits 52 t = np.zeros((qubits, 3, len(hilbert_space), len(hilbert_space)), 53 dtype=complex) 54 for i in range(qubits): 55 for j, operator in enumerate(basis): 56 t[i, j] = functools.reduce(np.kron, [np.identity(2**(qubits-1-i)), 57 operator, 58 np.identity(2**i)]) 59 return t
60
[docs] 61def fourth_order_tensor(hilbert_space: hilbert_spaces.QubitSpace, 62 xyz_basis: bool = True): 63 r""" 64 Generates a tensor given by the following expression 65 $$ 66 u_{i,j,k,l,\alpha,\beta}\coloneqq \left(\sigma^{(i)}_k\sigma^{(j)}_l\right)_{\alpha,\beta} 67 $$ 68 where $\sigma^{(i)}_j$ is the $j$th Pauli operator acting on the $i$th 69 qubit, and $\alpha$ and $\beta$ are the rows and columns of the matrix 70 representation of the operator $\sigma^{(i)}_k\sigma^{(j)}_l$ in the 71 computational basis. 72 73 Parameters 74 ---------- 75 hilbert_space: QubitSpace 76 The hilbert space of the qubits 77 xyz_basis: bool 78 Uses the Pauli basis if ``True`` and the 79 $\sigma_{\pm}\coloneqq(\sigma_1\pm i\sigma_2)/2$ and Pauli-z basis if 80 ``False``, by default ``True`` 81 82 Returns 83 ------- 84 NDArray[Shape[``hilbert_space.qubits``, ``hilbert_space.qubits``, 3, 3, ``hilbert_space.dim``, ``hilbert_space.dim``], int] 85 The fourth order skeleton tensor 86 """ 87 basis = PAULI if xyz_basis else LADDER_BASIS 88 qubits = hilbert_space.qubits 89 u = np.zeros((qubits, 90 qubits, 91 3, 92 3, 93 hilbert_space.dim, 94 hilbert_space.dim), 95 dtype=complex) 96 for i in range(qubits): 97 for j in range(qubits): 98 if i != j: 99 for k, operator1 in enumerate(basis): 100 for l, operator2 in enumerate(basis): 101 indices = np.array([i, j]) 102 operators = np.array([operator1, operator2]) 103 order = np.argsort(indices) 104 indices = indices[order] 105 operators = operators[order] 106 u[i, j, k, l] = \ 107 functools.reduce(np.kron, 108 [np.identity(2**(qubits-1-indices[1])), 109 operators[1], 110 np.identity(2**(indices[1]-indices[0]-1)), 111 operators[0], 112 np.identity(2**indices[0])]) 113 return u