File size: 2,647 Bytes
dd1edb0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import numpy as np
import matplotlib.pyplot as plt

def generate_random_complex_gaussian_matrix(n):
    matrix = np.empty((n, n, n), dtype=np.complex128)
    for i in range(n):
        for j in range(n):
            real_part = np.random.normal(size=n)
            imag_part = np.random.normal(size=n)
            matrix[i, j] = (real_part + 1j * imag_part) / np.sqrt(2)
    return matrix

def orthonormalize_vectors_svd(vectors):
    u, _, v = np.linalg.svd(vectors)
    return u @ v

def error_QPM(u):
    err = -1;

    for i in range(u.shape[0]):
        slice = u[i, :, :]
        err = max(err, np.linalg.norm(slice @ slice.conj().T - np.eye(slice.shape[0])))
        slice = u[:, i, :]
        err = max(err, np.linalg.norm(slice @ slice.conj().T - np.eye(slice.shape[0])))

    return err

def random_quantum_permutation_matrix(n, error_tolerance=1e-6, max_iter=1000):
    u = generate_random_complex_gaussian_matrix(n)

    iter = 0
    error = error_QPM(u)
    errors = [error]  # Initialize a list to store errors
    
    while error > error_tolerance and iter < max_iter:

        # orthonormalize rows
        for i in range(n):
            u[i, :, :] = orthonormalize_vectors_svd(u[i, :, :]) 

        # orthonormalize columns
        for j in range(n):
            u[:, j, :] = orthonormalize_vectors_svd(u[:, j, :]) 

        error = error_QPM(u)
        errors.append(error)  # Append the current error to the list    
        iter += 1

    return u, errors  # Return both the matrix and the list of errors


# Example usage
u, errors = random_quantum_permutation_matrix(6)

# Create a figure with two subplots side by side
fig, axs = plt.subplots(1, 2, figsize=(12, 5))

# Plot the errors on a log scale in the first subplot
axs[0].semilogy(errors)
axs[0].set_xlabel('Iteration')
axs[0].set_ylabel('Error (log scale)')
axs[0].set_title('Error Convergence')
axs[0].grid(True)

# Calculate the absolute values squared of the scalar products of the vectors in the matrix u
scalar_products = []
for i in range(u.shape[0]):
    for j in range(1, u.shape[0]):
        for k in range(1, u.shape[0]):
            for l in range(1, u.shape[0]):
                scalar_product = np.abs(np.dot(u[i,j,:], u[k,l,:].conj()))**2
                scalar_products.append(scalar_product)

# Plot the histogram in the second subplot
axs[1].hist(scalar_products, bins=30, edgecolor='black')
axs[1].set_xlabel('Absolute Values Squared of Scalar Products')
axs[1].set_ylabel('Frequency')
axs[1].set_title('Histogram of Absolute Values Squared of Scalar Products')
axs[1].grid(True)

# Adjust layout to prevent overlap
plt.tight_layout()
plt.show()