mat_maker

概要

この関数では線型結合の係数を補助ビット部分にセットする行列を作成する 量子回路でもちいる行列はユニタリ性を満たす必要があるので複雑な過程が必要だが第一列目の要素と係数さえ入力すれば自動的に作成する

引数一覧

argument name

type

role

elelist

list(element:float)

線形結合で用いられている係数の一覧

coeff_list

list(element:float)

行列を計算する際に必要な値の一覧

戻り値

mat_ele_list(np.array): 作成したユニタリ行列が格納されたnp.array
格納されている要素はfloat型

Python code

def mat_maker(elelist, coeff_lst):
    mat_ele_list = []
    # append the first colum of the desired matrix
    mat_ele_list.append(elelist)
    # search the border between non-zero elements and zero elements
    for i in range(len(elelist)//2):
        zero_num = i*2
        if np.abs(elelist[i*2]) == 0:
            break
    if elelist[zero_num] != 0:
        zero_num = len(elelist)
    # copy list of coeffcients to use ".reverse()"
    cf_copy = copy.deepcopy(coeff_lst)
    cf_copy.reverse()
    for i in range(len(coeff_lst)):
        # copy elements of matrix, this copy will be append to returned matrix after some process
        mat_copy = copy.deepcopy(mat_ele_list)
        for j in range(len(mat_copy)):
            # calculate non-zero elements of unitary matrix as list
            app_list = vec_make(mat_copy[j], cf_copy[i])
            # append elemnets zero to list of non-zero elements
            if i < (len(coeff_lst) - 1.1):
                if zero_num < (len(elelist) - 0.1):
                    if zero_num%2**(i+2) != 0:
                        input_ele = 0
                        for s in range(2**(i+1) + 2*j):
                            input_ele += mat_copy[i][(zero_num//(2**(i+2)))*(2**(i+2)) + s]**2
                            app_list[(zero_num//(2**(i+2)))*(2**(i+2)) + s] = 0
                        app_list[zero_num] = np.sqrt(input_ele)
                        zero_num += 2
            mat_ele_list.append(np.array(app_list))
    base_mat = [[0, -1], [1, 0]]
    unit = np.eye(2)
    convert = np.kron(unit, base_mat)
    # exchange ith line and i+1th line (i = 0, 1, 2, ..., len(coeff_lst) - 1)
    for i in range(len(coeff_lst) - 1):
        convert = np.kron(unit, convert)
    mel_len = len(mat_ele_list)
    if (np.log2(len(elelist)) > 1):
        for i in range(mel_len):
            mat_ele_list.append(np.dot(convert, mat_ele_list[i]))
    if (np.log2(len(elelist)) < 1.1):
        mat_ele_list = [[elelist[0], elelist[1]], [elelist[1], -elelist[0]]]
    # transpose the matrix to make it the optimal shape for sandwiching between quantum states
    return np.array(mat_ele_list).T

実行例

[1]:
import numpy as np
import pitbe
[4]:
ele_lst = [0.5, 0.433, 0.25, 0.433, 0.433, 0.3536, 0., 0.]
cf_lst = [[1.483], [1.322, 0.5590]]
unit_mat = pitbe.mat_maker(ele_lst, cf_lst)
print(np.round(unit_mat, 4))
[[ 0.5    -0.3782 -0.3372  0.255  -0.433   0.3275  0.292  -0.2209]
 [ 0.433  -0.3275 -0.292   0.2209  0.5    -0.3782 -0.3372  0.255 ]
 [ 0.25    0.3305 -0.1686 -0.2229 -0.433  -0.5724  0.292   0.386 ]
 [ 0.433   0.5724 -0.292  -0.386   0.25    0.3305 -0.1686 -0.2229]
 [ 0.433   0.      0.6421  0.     -0.3536  0.     -0.5244  0.    ]
 [ 0.3536  0.      0.5244  0.      0.433   0.      0.6421  0.    ]
 [ 0.      0.559   0.      0.8291  0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.559   0.      0.8291]]

作成された行列がユニタリ行列であることは以下のように確認される。

[9]:
# Norm of all eigenvalues are one.
eigenvalue = np.linalg.eig(unit_mat)[0]
for i in range(len(eigenvalue)):
    print(np.round(np.linalg.norm(eigenvalue[i]), 3))
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
[8]:
# The product with the complex conjugate of the matrix is the identity matrix.
print(np.round(np.dot(unit_mat.T, unit_mat), 3))
[[ 1. -0. -0.  0.  0.  0. -0. -0.]
 [-0.  1.  0.  0.  0.  0.  0.  0.]
 [-0.  0.  1. -0.  0.  0.  0.  0.]
 [ 0.  0. -0.  1.  0.  0. -0.  0.]
 [ 0.  0.  0.  0.  1. -0. -0.  0.]
 [ 0.  0.  0.  0. -0.  1.  0.  0.]
 [-0.  0.  0. -0. -0.  0.  1. -0.]
 [-0.  0.  0.  0.  0.  0. -0.  1.]]