|
8 | 8 | matrix_power,
|
9 | 9 | partial_trace,
|
10 | 10 | partial_transpose,
|
| 11 | + singular_value_decomposition, |
11 | 12 | )
|
12 | 13 | from qibo.quantum_info.metrics import purity
|
13 | 14 | from qibo.quantum_info.random_ensembles import random_density_matrix, random_statevector
|
@@ -218,3 +219,34 @@ def test_matrix_power(backend, power):
|
218 | 219 | float(backend.np.real(backend.np.trace(power))),
|
219 | 220 | purity(state, backend=backend),
|
220 | 221 | )
|
| 222 | + |
| 223 | + |
| 224 | +def test_singular_value_decomposition(backend): |
| 225 | + zero = np.array([1, 0], dtype=complex) |
| 226 | + one = np.array([0, 1], dtype=complex) |
| 227 | + plus = (zero + one) / np.sqrt(2) |
| 228 | + minus = (zero - one) / np.sqrt(2) |
| 229 | + plus = backend.cast(plus, dtype=plus.dtype) |
| 230 | + minus = backend.cast(minus, dtype=minus.dtype) |
| 231 | + base = [plus, minus] |
| 232 | + |
| 233 | + coeffs = np.random.rand(4) |
| 234 | + coeffs /= np.sum(coeffs) |
| 235 | + coeffs = backend.cast(coeffs, dtype=coeffs.dtype) |
| 236 | + |
| 237 | + state = np.zeros((4, 4), dtype=complex) |
| 238 | + state = backend.cast(state, dtype=state.dtype) |
| 239 | + for k, coeff in enumerate(coeffs): |
| 240 | + bitstring = f"{k:0{2}b}" |
| 241 | + a, b = int(bitstring[0]), int(bitstring[1]) |
| 242 | + ket = backend.np.kron(base[a], base[b]) |
| 243 | + state = state + coeff * backend.np.outer(ket, ket.T) |
| 244 | + |
| 245 | + _, S, _ = singular_value_decomposition(state, backend=backend) |
| 246 | + |
| 247 | + S_sorted = backend.np.sort(S) |
| 248 | + coeffs_sorted = backend.np.sort(coeffs) |
| 249 | + if backend.name == "pytorch": |
| 250 | + S_sorted, coeffs_sorted = S_sorted[0], coeffs_sorted[0] |
| 251 | + |
| 252 | + backend.assert_allclose(S_sorted, coeffs_sorted) |
0 commit comments