Оптимизация руководителя группы для разложения унитарных матриц с образованием квантовых цепей - PullRequest
0 голосов
/ 19 февраля 2019

Я реализовал оптимизацию лидера группы для формирования квантовых цепей из унитарных матриц.Я взял четыре переменные, чтобы представить ворота, и взял в качестве одного члена 20 переменных, представляющих 5 ворот (фиксированное количество ворот).В группе 15 таких членов и всего 25 групп, которые я рассмотрел.

Мой код сводит к минимуму только ошибку верности и выбирает строку, представляющую схему с минимальной ошибкой верности (число вентилейнеподвижная = 5).То, что я хочу сделать, это установить максимальное количество вентилей равным 20 и иметь строку переменной длины для представления цепей с переменным числом вентилей.Это сводит к минимуму ошибку верности, а также стоимость (меньшее количество шлюзов = меньшую стоимость)

Как мне это сделать?

Это вывод моего кода.Первые четыре переменные представляют затвор, целевой кубит, управляющий кубит и угол поворота для первых затворов.Остальное, представляющее следующие 4 шлюза аналогичным образом, сгруппированные в четыре переменные, представляет собой

Код (для разложения унитарной матрицы Тоффоли Гейт):

import matplotlib.pyplot as plt
import numpy,random
import functions    

num_x = 20
num_groups=25
pop_per_group = 15
pop_size = (num_groups,pop_per_group,num_x) 
leaders= numpy.empty((num_groups, num_x))
r1=0.8
r2=0.1
r3=0.1
new_mem=numpy.random.uniform(low=0, high=4, size=20)

new_population = numpy.random.uniform(low=0, high=4, size=pop_size)

for g in range (num_groups):#num_groups

    fitness=functions.cal_fitness(new_population[g, : ,:])
    #print("fitness of group", g+1)
    #print (fitness)
    leaders[g,:]=functions.select_leader(new_population[g,: ,:],num_groups,g)
print (leaders)

y=numpy.zeros(shape=600)
for i in range (600):
        print("-----------------------------")
        print ("Generation:" ,i)

        #print("-----------------------------")
        print("-----------------------------")
        for g in range (num_groups):
                for p in range (pop_per_group):
                        rand_mem=numpy.random.uniform(low=0, high=4, size=20)
                        new_mem=r1*new_population[g,p,:]+r2*leaders[g,:]+r3*rand_mem
                        #print(new_population[g,p,:])
                        new_population[g,p,:] = functions.select_new_mem(new_population[g,p,:],new_mem)
                        #print(new_population[g,p,:])
        for g in range (num_groups):
                t=random.randint(0,9)
                #print ('old',g,k)
                #print(new_population[g,k,:])
                for t in range (t+1):
                        x=int(random.random()*num_groups) 
                        k=int(random.random()*pop_per_group)
                        pr=random.randint(0,19)
                        new_mem=new_population[g,k,:].copy()
                        new_mem[pr]=new_population[x,k,pr]
                        next_mem=functions.select_new_mem(new_population[g,k,:],new_mem)
                        new_population[g,k,:]=next_mem
                #print (new_population[g,k,:])
                #print (next_mem)

                #print ('new',g,k)
                #print(new_population[g,k,:])

        for g in range (num_groups):#num_groups

                fitness=functions.cal_fitness(new_population[g, : ,:])
                #print("fitness of group", g+1)
                #print (fitness)
                leaders[g,:]=functions.select_leader(new_population[g,: ,:],num_groups,g)
        print (leaders)
        print (functions.cal_fitness(leaders))        
        y[i]=functions.select_best_leader(leaders)

xl = numpy.linspace(0, 600,600)

#Plot the data
plt.plot(xl, y, label='Fitness')

Функции (Код):

import numpy
from math import pi,sqrt,e
import UnitaryCalculation
from qiskit.quantum_info import process_fidelity 

def val_pop(one_mem):
    i=1
    for var in range (20):
        if (i%4==0):
            one_mem[var]=one_mem[var] % (2*3.14)
            i+=1
        elif ((i-1)%4==0):
            one_mem[var]=int(one_mem[var])
            i+=1
        else:#Nq = 3
            one_mem[var]=int(one_mem[var] %3 )
            i+=1
    return one_mem


def ifitness(mem):
    unitary_t=[[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,0,1],[0,0,0,0,0,0,1,0]]
    unitary_a=UnitaryCalculation.cal_unitary(mem)
    fit=process_fidelity(unitary_t, unitary_a)
    fit_mem=1-fit**2
    return fit_mem

def cal_fitness(pop):
    unitary_t=[[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,0,1],[0,0,0,0,0,0,1,0]]
    #print(unitary_t)
    fitness=numpy.ndarray(shape=(0))
    for p in range (pop.shape[0]):
        unitary_a=UnitaryCalculation.cal_unitary(pop[p, :])
        fit=process_fidelity(unitary_t, unitary_a)
        fitness=numpy.append(fitness, values=1-fit**2)
    #print (fitness)
    return (fitness)

def select_leader(pop,num_groups,g):
    #print(pop.shape[0])
    fitness=cal_fitness(pop)
    max_fitness_idx = numpy.where(fitness == numpy.min(fitness))
    max_fitness_idx = max_fitness_idx[0][0]
    fitness[max_fitness_idx] = +99999999999
    return (pop[max_fitness_idx, :])

def select_new_mem(old_mem,new_mem):
    of=ifitness(old_mem)
    #print(of)
    nf=ifitness(new_mem)
    #print(new_mem)
    #print(nf)
    if (nf < of):
        #print('changed')
        return new_mem
    else :
        return old_mem


def select_best_leader(leaders):
    best_leader = numpy.zeros((leaders.shape[1]))
    fitness=cal_fitness(leaders)
    max_fitness_idx = numpy.where(fitness == numpy.min(fitness))
    max_fitness_idx = max_fitness_idx[0][0]
    best_leader= leaders[max_fitness_idx, :]
    print ("Best Soln is: ")
    print (best_leader)
    print ("Its fitness is: ")
    print (fitness[max_fitness_idx])
    return (fitness[max_fitness_idx])

Унитарный расчет (код):

import numpy
from math import sqrt,e,pi
from qiskit.quantum_info import process_fidelity

def get_gate(num):
    i_=numpy.complex(0,1)
    H=1./sqrt(2)*numpy.matrix('1 1; 1 -1') 
    X=numpy.matrix('0 1; 1 0')
    Y=numpy.matrix([[0, -i_],[i_, 0]])
    Z=numpy.matrix([[1,0],[0,-1]])
    W=1/sqrt(2)*(X+Z)
    V=numpy.matrix([[1+i_,1-i_],[1-i_,1+i_]]) * 1/2
    Vdagger = V.conjugate().transpose()
    S=numpy.matrix([[1,0],[0,i_]])
    Sdagger=numpy.matrix([[1,0],[0,-i_]]) # convenience Sdagger = S.conjugate().transpose()
    T=numpy.matrix([[1,0],[0, e**(i_*pi/4.)]])
    Tdagger=numpy.matrix([[1,0],[0, e**(-i_*pi/4.)]]) # convenience Tdagger= T.conjugate().transpose()
    if (num==0):
        return V
    elif (num==1):
        return Z
    elif (num==2):
        return S 
    elif (num==3):
        return Vdagger

def cal_mc_gate(gate):

    Nq=3
    zeros=[[1,0],[0,0]]
    ones=[[0,0],[0,1]]
    mat_to_tensor=numpy.empty(shape=(Nq,2,2),dtype=complex)
    for n in range(Nq):
        mat_to_tensor[n]=numpy.identity(2)
    Cq=int(gate[2] %3)
    Tq=int(gate[1] %3)
    theta=gate[3]
    g_matrix=get_gate(gate[0])
    #print (g_matrix)
    if (Cq!=Tq):
        mat_to_tensor[Cq]=zeros
        u1=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        mat_to_tensor[Cq]=ones
        mat_to_tensor[Tq]=g_matrix
        u2=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        unitary=numpy.add(u1,u2)
    else:
        mat_to_tensor[Tq]=g_matrix
        unitary=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        #print (unitary)
    return unitary

def cal_u_gate(gate):
    Nq=3
    zeros=[[1,0],[0,0]]
    ones=[[0,0],[0,1]]
    mat_to_tensor=numpy.empty(shape=(Nq,2,2),dtype=complex)
    for n in range(Nq):
        mat_to_tensor[n]=numpy.identity(2)
    Cq=int(gate[2] %3)
    Tq=int(gate[1] %3)
    theta=gate[3]
    g_matrix=get_gate(gate[0])
    #print (g_matrix)
    if (Cq!=Tq):
        mat_to_tensor[Cq]=zeros
        u1=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        mat_to_tensor[Cq]=ones
        mat_to_tensor[Tq]=g_matrix
        u2=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        unitary=numpy.add(u1,u2)
    else:
        mat_to_tensor[Tq]=g_matrix
        unitary=numpy.kron(numpy.kron(mat_to_tensor[0],mat_to_tensor[1]),mat_to_tensor[2])
        #print (unitary)
    return unitary #[[0,2,1,0],[1,2,0,0],[2,1,0,0],[3,2,1,0],[1,0,2,0]]

def cal_unitary(one_mem):
    #one_mem=[0,2,1,0,1,2,0,0,2,1,0,0,3,2,1,0,1,0,2,0]
    x=numpy.zeros(shape=(5,4))
    u=numpy.zeros(shape=(5,8,8),dtype=complex)
    k=0
    for gate in range (5):
        for var in range (0,3):
            x[gate][var]=int(one_mem[k])
            k+=1
        x[gate][var+1]=one_mem[k]
        k+=1
    for gate in range (5):
        u[gate]=cal_u_gate(x[gate,:])
        #print ("The unitary matrix of U", gate )
        #print (u[gate])
    unitary=numpy.dot(numpy.dot(numpy.dot(numpy.dot(u[0],u[1]),u[2]),u[3]),u[4])
    #np.set_printoptions(precision=1)
    return unitary
...