File size: 1,928 Bytes
9f8cf99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from __future__ import annotations

import numpy as np
from numpy.typing import ArrayLike, NDArray


def complex_statevector_to_ri(psi: ArrayLike) -> NDArray[np.float64]:
    psi_c = np.asarray(psi, dtype=np.complex128)
    if psi_c.ndim != 1:
        raise ValueError("psi must be a 1D complex array of length 2^n")
    out = np.empty((psi_c.shape[0], 2), dtype=np.float64)
    out[:, 0] = psi_c.real
    out[:, 1] = psi_c.imag
    return out


def ri_to_complex_statevector(psi_ri: ArrayLike) -> NDArray[np.complex128]:
    arr = np.asarray(psi_ri, dtype=np.float64)
    if arr.ndim != 2 or arr.shape[1] != 2:
        raise ValueError("psi_ri must have shape (2^n, 2)")
    return arr[:, 0].astype(np.complex128) + 1j * arr[:, 1]


def complex_matrix_to_ri(mat: ArrayLike) -> NDArray[np.float64]:
    mat_c = np.asarray(mat, dtype=np.complex128)
    if mat_c.ndim != 2:
        raise ValueError("mat must be a 2D complex array")
    out = np.empty((mat_c.shape[0], mat_c.shape[1], 2), dtype=np.float64)
    out[:, :, 0] = mat_c.real
    out[:, :, 1] = mat_c.imag
    return out


def ri_to_complex_matrix(mat_ri: ArrayLike) -> NDArray[np.complex128]:
    arr = np.asarray(mat_ri, dtype=np.float64)
    if arr.ndim != 3 or arr.shape[2] != 2:
        raise ValueError("mat_ri must have shape (N, M, 2)")
    return arr[:, :, 0].astype(np.complex128) + 1j * arr[:, :, 1]


def kraus_1q_to_ri(kraus_ops: ArrayLike) -> NDArray[np.float64]:
    """
    Convert a set of 1-qubit Kraus operators into the Rust-kernel format.

    Input shape: (k, 2, 2) complex
    Output shape: (k, 2, 2, 2) float64 with last dim [re, im]
    """
    k = np.asarray(kraus_ops, dtype=np.complex128)
    if k.ndim != 3 or k.shape[1:] != (2, 2):
        raise ValueError("kraus_ops must have shape (k, 2, 2) complex")
    out = np.empty((k.shape[0], 2, 2, 2), dtype=np.float64)
    out[:, :, :, 0] = k.real
    out[:, :, :, 1] = k.imag
    return out