[PYTHON] Bases de la théorie de l'information quantique: calcul quantique universel par code de surface (1)

\def\bra#1{\mathinner{\left\langle{#1}\right|}} \def\ket#1{\mathinner{\left|{#1}\right\rangle}} \def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}

introduction

Dans Article précédent, la logique est créée en créant des défauts (zones sans opérateurs) dans les opérateurs de surface et les opérateurs de sommet répartis sur la grille plane. Nous avons vu que les bits quantiques et les opérateurs logiques $ X $ et logique $ Z $ peuvent être définis, et que les opérations CNOT peuvent être réalisées en déplaçant les défauts les uns autour des autres. Cependant, cette opération CNOT est en fait incomplète pour être un élément du calcul quantique universel. La raison sera expliquée plus tard. Dans cet article, je vais étudier comment un CNOT complet peut être réalisé. Afin de réaliser un calcul quantique universel, ce serait bien si nous pouvions préparer une opération unitaire arbitraire de 1 bit quantique, mais nous le ferons la prochaine fois. Maintenant que vous avez une compréhension générale, utilisez le simulateur de calcul quantique qlazy pour vérifier son fonctionnement.

Les documents suivants ont été utilisés comme références.

  1. Koshiba, Morimae, Fujii "Calcul quantique basé sur l'observation" Corona (2017)
  2. K.Fujii,"Quantum Computation with Topological Codes - from qubit to topological fault-tolerance",arXiv:1504.01444v1 [quant-ph] 7 Apr 2015
  3. Fujii "Introduction to Quantum Computation" (2012)
  4. Neilsen Chan "Quantum Computer and Quantum Communication II" (2005)

Explication de la théorie

Représentation topologique des opérations de tressage

Il y a un sujet que je voudrais garder à l'esprit avant d'entrer dans le sujet principal. Dans Article précédent, il a été constaté que le tressage peut exprimer l'opération logique de 2 bits quantiques, mais il est défectueux dans le schéma explicatif qui déplace le défaut dans le plan. Il est extrêmement difficile de comprendre quel type d'enroulement topologique est réalisé en changeant l'heure et à quel type d'opération logique il correspond. Par conséquent, nous allons introduire un diagramme schématique pour faciliter la compréhension des caractéristiques topologiques dans l'espace et le temps 3D.

Tout d'abord, considérons le mouvement des défauts de type p. Supposons que vous ayez une paire de défauts de type p comme indiqué à gauche dans la figure ci-dessous. En ajoutant une chaîne d'opérateurs $ X $ reliant ce défaut à la source, nous avons pu exprimer le $ \ ket {+} $ logique, qui est l'état propre du $ X $ logique (en haut dans la figure ci-dessous). Cet état est représenté par le symbole $ \ ket {+} ^ {p} $, ce qui signifie la logique $ \ ket {+} $ créée par le défaut de type p (indice L comme indiqué sur la figure). Je veux écrire sur le côté droit du ket, mais pour une raison quelconque, il ne rend pas bien, je suis désolé, veuillez penser qu'il y a un L, et ainsi de suite). Ceci est schématisé en haut à droite de la figure ci-dessous. Ici, la direction verticale représente la position spatiale (pensez à mapper un plan bidimensionnel sur une dimension), et la direction horizontale représente l'axe du temps. Ensuite, la variation temporelle de la chaîne $ X $ sera représentée par la surface courbe dans cet espace et ce temps. Imaginez que la chaîne reliant les défauts se déplace le long de l'axe du temps et trace une trajectoire en forme de ruban dans l'espace et le temps. Par contre, $ \ ket {0} ^ {p} $ peut être exprimé en ajoutant une boucle de l'opérateur $ Z $ qui entoure l'un des défauts de la paire de défauts au générateur (en bas au milieu de la figure ci-dessous). Ceci est schématisé en bas à droite de la figure ci-dessous. La variation temporelle de la boucle de cet opérateur $ Z $ est également représentée par cette surface courbe spatio-temporelle. Cependant, contrairement à la précédente, la boucle (comme un anneau en caoutchouc) qui entoure le défaut se déplace le long de l'axe du temps, de sorte que la trajectoire devient une surface courbe comme un tube.

fig01.png

La génération et la mesure des paires de défauts peuvent également être représentées dans ce diagramme schématique. Une paire de défauts de type p pourrait être générée en mesurant $ X $ en un point (bit quantique) dans l'état de vide. Ceci peut être schématiquement représenté de telle manière qu'une mesure est faite quelque part à partir d'un vide vide et qu'une paire de défauts est générée. L'état ainsi généré est l'état unique de la chaîne $ X $ qui relie les deux défauts. Ensuite, en mesurant cette chaîne $ X $, la valeur en tant que bit logique peut être déterminée, mais nous allons représenter l'opération dans un diagramme où les défauts sont appariés [^ 1](voir la figure ci-dessous). ..

[^ 1]: Vous pouvez avoir l'impression que la paire de défauts disparaît ici, mais je pense que la valeur propre du bit quantique logique n'est fixée qu'à +1 ou -1, et il ne revient pas à l'état de vide. (Peut être). Pour revenir à l'état de vide, je pense que vous devez mesurer l'un ou l'autre des opérateurs de surface (boucle de l'opérateur $ Z $) avec deux défauts adjacents l'un à l'autre (veuillez préciser si vous faites une erreur). L'opérateur $ Z $ placé autour d'une des paires de défauts de type p peut représenter l'état propre de l'opérateur logique $ Z $, mais même s'il est mesuré, le défaut ne disparaît pas. Non, je pense).

fig02.png

Ensuite, considérez le défaut de type D. L'image est exactement la même que le type p sauf que les positions de l'opérateur $ X $ et de l'opérateur $ Z $ sont inversées, donc ça se passe bien. Supposons que vous ayez une paire de défauts de type d comme indiqué à gauche dans la figure ci-dessous. En ajoutant une chaîne d'opérateurs $ Z $ reliant ce défaut au générateur, $ \ ket {0} ^ {d} $ peut être représenté (en haut dans la figure ci-dessous), et ce changement d'heure est schématiquement en haut à droite de la figure ci-dessous. Il est représenté par une surface courbe (ruban) comme. De plus, $ \ ket {+} ^ {d} $ peut être représenté par une boucle de l'opérateur $ X $ qui entoure l'une de ces paires de défauts (en bas dans la figure ci-dessous), et ce changement d'heure est schématisé à droite dans la figure ci-dessous. Il est représenté par une surface courbe (tube) comme illustré ci-dessous.

fig03.png

La génération de paires de défauts de type d peut être exprimée par la génération de paires à partir du vide par la mesure $ Z $, qui devient l'état propre $ \ ket {0} ^ {d} $ du $ Z $ logique. Enfin, la valeur sous forme de bit logique peut être obtenue en mesurant la chaîne $ Z $, mais cette opération sera représentée par un diagramme dans lequel la paire de défauts disparaît (voir la figure ci-dessous).

fig04.png

Dernier CNOT

Maintenant, utilisons le diagramme schématique présenté dans la section précédente pour représenter l'opération CNOT réalisée dans Article précédent. La figure ci-dessous montre comment une paire de défauts de type p crée un état unique de logique $ X $ $ \ ket {+} ^ {p} $ et enveloppe l'un des défauts autour d'un défaut de type d [^] 2]. La chaîne reliant les défauts de type p s'enroule autour des défauts de type d, et un nouveau tube (opérateur logique $ X $) apparaît dans les défauts de type d, et le ruban de type p d'origine conserve sa forme d'origine. c'est,

[^ 2]: Ceci est une citation de la figure de Référence 3. J'en ai cité certains dans d'autres parties de cet article. Cette diapositive du Dr Fujii est facile à comprendre avec de nombreux diagrammes topologiques. c'est recommandé!

X_1 \otimes I_2 \rightarrow X_1 \otimes X_2  \tag{1}

Cela correspond à l'opération logique. Comment le sais-tu? Considérez le défaut en forme de D ci-dessous comme deux tiges. Au-dessus se trouve une chaîne qui représente un défaut en forme de p, qui se déplace de gauche à droite et le bord inférieur de la chaîne s'enroule autour de la barre inférieure. Ensuite, vous pouvez imaginer qu'un anneau est né d'une chaîne [^ 3].

[^ 3]: Je pense que ce serait plus facile à comprendre si vous pouviez expliquer cette situation avec une vidéo, mais je suis désolé, je n'ai pas le background pour faire des vidéos. Faites de votre mieux et créez une vidéo dans votre esprit.

fig05.png

La figure ci-dessous montre la même opération avec différents états initiaux. Ici, l'état propre $ \ ket {0} ^ {d} $ de l'opérateur logique $ Z $ est créé avec la paire de défauts de type d, et l'un des défauts de type p est enroulé autour du défaut de type d. .. Vous pouvez voir que la chaîne reliant les défauts de type d est enroulée par les défauts de type p et un nouveau tube (opérateur logique $ Z $) apparaît dans les défauts de type p. La surface d'origine en forme de D conserve sa forme d'origine. c'est,

I_1 \otimes Z_2 \rightarrow Z_1 \otimes Z_2  \tag{2}

Cela correspond à l'opération logique. Le fonctionnement est le même que précédemment, mais cette fois il y a un film mince entre les deux tiges représentant le défaut de type d, et l'un des défauts supérieurs de type p s'enroule autour de la tige de type d et autour d'un des défauts de type p. C'est une image qu'un nouveau cercle est né.

fig06.png

Dans article précédent, il a dit que CNOT avait été réalisé avec cela. Cependant, si vous regardez de près, le côté contrôle est un défaut de type p et le côté cible est un défaut de type D. CNOT ne peut pas être effectué sans cette combinaison. Alors, qu'est-ce qui ne va pas? Il semble être dit, mais ce n'est pas très bon. Par exemple

fig07.png

Seules les combinaisons CNOT telles que possibles. La porte SWAP est une opération unitaire typique pour 2 quantiques,

fig08.png

Comme vous pouvez le voir en écrivant comme, ce n'est pas faisable si le défaut de type p ne peut être utilisé que du côté commande de l'opération CNOT. En général, les opérations unitaires pour tout état de N bits quantiques peuvent être décomposées en le produit d'une opération unitaire à 1 bit quantique et à une opération CNOT à 2 bits quantiques (Référence 4. (Voir jp / book / 9784274200083 /)), mais s'il existe une restriction selon laquelle seuls des bits quantiques spécifiques peuvent être utilisés comme bits de contrôle (ou seuls des bits quantiques spécifiques peuvent être utilisés comme bits cibles), une telle décomposition est impossible. En d'autres termes, afin de réaliser un calcul quantique universel en utilisant le code de surface des paires de défauts, il est nécessaire de réaliser une opération CNOT dans laquelle au moins le bit de contrôle et le bit cible sont des défauts de type p.

Ce CNOT

Alors, comment pouvons-nous réaliser une telle opération CNOT que le côté contrôle et le côté cible soient des défauts de type p? Pour être honnête, je ne sais pas comment cela a été dérivé, alors je vais simplement dire la réponse dans la référence. La réponse est de considérer le circuit équivalent suivant de l'opération CNOT [^ 4].

[^ 4]: C'est certainement CNOT, n'est-ce pas? Je pense que c'est facile à comprendre si vous pensez à l'entrée et à la sortie dans un format de stabilisateur. Autrement dit, lorsque l'entrée est $ X \ otimes I $, la sortie est $ X \ otimes X $, ou lorsque l'entrée est $ I \ otimes Z $, la sortie est $ Z \ otimes Z . Si vous vérifiez etc., vous pouvez voir qu'il s'agit certainement de CNOT. Cependant, il y a une mise en garde. Si la valeur mesurée lorsque le 4ème défaut de type p disparaît est -1, les 1er et 3ème bits quantiques logiques sont inversés ( \ ket {+} $ est changé en $ \ ket {-} $ et $ Vous devez retourner \ ket {-} $ à $ \ ket {+} $). Vous pouvez le voir en calculant soigneusement le format du stabilisateur.

fig09.png

Il s'agit d'un circuit quantique ordinaire qui n'est pas un code de surface, mais les premier, troisième et quatrième bits quantiques du haut sont utilisés comme bits de contrôle, et le deuxième bit quantique est utilisé comme bit cible. Il est en forme. Donc, si vous réimprimez ceci tel quel sur le code de surface et effectuez les 1er, 3ème et 4ème défauts de type p et les 2ème défauts de type d comme indiqué ci-dessous, CNOT en utilisant uniquement les défauts de type p Peut être réalisé.

fig10.png

Si vous écrivez dans le diagramme schématique expliqué précédemment, il ressemblera à la figure de gauche. La figure à droite ci-dessous montre une simple ré-expression afin que les valeurs soient topologiquement les mêmes tout en gardant la structure d'enroulement inchangée.

fig11.png

De plus, puisque la dimension spatiale était à l'origine bidimensionnelle, si la topologie est exprimée avec précision dans l'espace-temps tridimensionnel,

fig12.png

Ce sera. Comment c'est? Un objet d'art contemporain mystérieux est apparu, qui représente l'opération CNOT dans le code de surface à l'aide de défauts.

Contrôle de fonctionnement

Maintenant, utilisons le simulateur de calcul quantique qlazy pour voir si l'opération CNOT peut vraiment être réalisée avec cela. Comme le tressage est plus compliqué que la dernière fois, la taille de la grille plane à préparer sera plus grande de cette quantité, mais il n'y a pas de problème si vous utilisez le format de stabilisateur car vous n'avez besoin que du calcul et de la mesure de Clifford.

Tout d'abord, concevez le type de tressage à effectuer. Tant que le défaut et son mouvement sont dans la topologie expliquée ci-dessus, il devrait être possible de décider, donc pour le moment, j'ai essayé de le déplacer comme le montre la figure ci-dessous.

fig13.png

fig14.png

Commencez par créer un état de vide dans (1) (répartissez l'opérateur de surface et l'opérateur de sommet sur toute la grille).

Générez 4 paires de défauts dans (2) (mesurez l'endroit approprié et déplacez le défaut). Nommez les nombres de bits quantiques 0e, 1er, 2e et 3e à partir du haut du schéma de circuit CNOT montré précédemment [^ 5], et organisez-les comme indiqué dans (2). Les 0ème, 2ème et 3ème sont des paires de défauts de type p et sont dans l'état propre de $ X $ logique, et les premiers sont des paires de défauts de type d et sont dans l'état propre de $ Z $ logique. Vous pouvez préparer un état unique de $ + 1 $ en appliquant l'opérateur logique $ Z $ ou logique $ X $ en fonction de la valeur mesurée.

[^ 5]: En raison de la commodité de la mise en œuvre du programme, le nombre de bits quantiques commencera à partir du 0. C'est presque le cas dans ce blog car il est plus facile d'expliquer la théorie en partant du premier, mais dans la plupart des langages de programmation, l'index du tableau commence au 0 (FORTRAN a certainement l'indice du tableau 1). Je pense que c'était de la seconde). Parfois, je suis confus, mais je dois m'y habituer.

Tressez le défaut en (3). Enroulez l'une de la 0ème paire de défauts autour de l'une de la 1ère paire de défauts et l'une des 2ème et 3ème paires de défauts autour de l'autre de la 1ère paire de défauts.

Dans (4), mesurez la première paire de défauts pour $ Z $ et la troisième paire de défauts pour $ X $.

Cela devrait implémenter CNOT. Si vous souhaitez exprimer la relation entrée / sortie basée sur $ X $

Contrôle côté entrée et cible Contrôle et cible côté sortie
\ket{++} \ket{++}
\ket{+-} \ket{-+}
\ket{+-} \ket{--}
\ket{--} \ket{+-}

Cela devient [^ 6]. Dans (2) ci-dessus, $ \ ket {+} $ a été préparé comme bit de contrôle (0e bit quantique) du côté entrée, et $ \ ket {+} $ a été préparé comme bit cible (3e bit quantique) côté entrée. Ensuite, à partir de la première ligne de ce tableau, le bit de contrôle (0ème bit quantique) du côté sortie est $ \ ket {+} $, et le bit cible (2ème bit quantique) du côté sortie est $ \ ket {+. } Ce sera $. En d'autres termes, si vous mesurez les 0ème et 2ème bits quantiques pour $ X $, vous devriez observer $ (+ 1, + 1) $ avec une probabilité de 100 $ % $. De plus, préparez $ \ ket {+} $ comme bit de contrôle côté entrée, et appliquez l'opérateur logique $ Z $ au bit cible $ \ ket {+} $ côté entrée pour définir $ \ ket {-} $. Si préparé, à partir de la deuxième ligne de ce tableau, les bits de contrôle et de cible du côté sortie seront $ \ ket {-} $ et $ \ ket {+} $. En d'autres termes, si vous mesurez les 0ème et 2ème bits quantiques pour $ X $, vous devriez observer $ (-1, + 1) $ avec une probabilité de 100 $ % $. De même, vous pouvez vérifier les relations d'entrée / sortie des 3e et 4e lignes de ce tableau.

[^ 6]: Est-ce que ça va? Si vous y pensez dans un format stabilisateur, vous le saurez tout de suite. La première ligne du tableau est $ \ <XI, IX > \ rightarrow \ <XX, IX > = \ <XI, IX > $, la deuxième ligne est $ \ <XI, -IX > \ rightarrow \ < -XX, IX > = \ <-XI, IX > $, etc.

la mise en oeuvre

Voici l'intégralité du code Python.

from collections import Counter
from qlazypy import Stabilizer

XBASE = {'0':'+', '1':'-'}
OBJECT = {'p':'face', 'd':'vertex'}

def get_common_qid(obj_A, obj_B):

    return list(set(obj_A['dat']) & set(obj_B['dat']))

def get_path(pos_A, pos_B):

    path = []

    if pos_A[1] < pos_B[1]: h_list = list(range(pos_A[1], pos_B[1] + 1))
    else: h_list = list(reversed(range(pos_B[1], pos_A[1] + 1)))
    for j in h_list: path.append([pos_A[0], j])

    if pos_A[0] < pos_B[0]: v_list = list(range(pos_A[0] + 1, pos_B[0] + 1))
    else: v_list = list(reversed(range(pos_B[0], pos_A[0])))
    for i in v_list: path.append([i, pos_B[1]])

    return path

def create_lattice(row, col):

    face = [[None]*col for _ in range(row)]
    vertex = [[None]*(col+1) for _ in range(row+1)]

    q_row = 2 * row + 1
    q_col = 2 * col + 1
    q_id = 0
    for i in range(q_row):
        for j in range(q_col):
            if i%2 == 1 and j%2 == 1: # face
                dat = []
                dat.append((i - 1) * q_col + j)  # up
                dat.append((i + 1) * q_col + j)  # down
                dat.append(i * q_col + (j - 1))  # left
                dat.append(i * q_col + (j + 1))  # right
                face[i//2][j//2] = {'anc': q_id, 'dat': dat}

            elif i%2 == 0 and j%2 == 0: # vertex
                dat = []
                if i > 0: dat.append((i - 1) * q_col + j)          # up
                if i < q_row - 1: dat.append((i + 1) * q_col + j)  # down
                if j > 0: dat.append(i * q_col + (j - 1))          # left
                if j < q_col - 1: dat.append(i * q_col + (j + 1))  # right
                vertex[i//2][j//2] = {'anc': q_id, 'dat': dat}
                
            q_id += 1
            
    return {'face': face, 'vertex': vertex}

def initialize(sb, lattice):

    i = 0  # generator id
    for face_list in lattice['face']:
        for face in face_list:
            [sb.set_pauli_op(i, q, 'Z') for q in face['dat']]
            i += 1
            sb.set_pauli_op(i, face['anc'], 'Z')
            i += 1

    for vertex_list in lattice['vertex']:
        for vertex in vertex_list:
            [sb.set_pauli_op(i, q, 'X') for q in vertex['dat']]
            i += 1
            sb.set_pauli_op(i, vertex['anc'], 'Z')
            i += 1

def get_chain(pos_list, dtype, lattice):

    chain = []
    for i in range(1,len(pos_list)):
        pos_A = pos_list[i-1]
        pos_B = pos_list[i]
        chain.append(get_common_qid(lattice[OBJECT[dtype]][pos_A[0]][pos_A[1]],
                                    lattice[OBJECT[dtype]][pos_B[0]][pos_B[1]])[0])
    return chain

def move_defect(sb, pos_A, pos_B, path, dtype, lattice, create=False, annihilate=False):

    obj = OBJECT[dtype]
    if create == True:
        obj_A = lattice[obj][pos_A[0]][pos_A[1]]
        obj_B = lattice[obj][pos_B[0]][pos_B[1]]
        q = get_common_qid(obj_A, obj_B)[0]
        if dtype == 'p':
            md = sb.mx(qid=[q])
            if md.last == '1': [sb.z(i) for i in obj_B['dat']]
        elif dtype == 'd':
            md = sb.m(qid=[q])
            if md.last == '1': [sb.x(i) for i in obj_B['dat']]
        
    chain = get_chain(get_path(pos_A, pos_B), dtype, lattice)
    for i in range(1,len(path)):
        # extend defect
        obj_A = lattice[obj][path[i-1][0]][path[i-1][1]]
        obj_B = lattice[obj][path[i][0]][path[i][1]]
        q = get_common_qid(obj_A, obj_B)[0]
        if dtype == 'p':
            md = sb.mx(qid=[q])
            if md.last == '1': [sb.z(i) for i in obj_B['dat']]
        elif dtype == 'd':
            md = sb.m(qid=[q])
            if md.last == '1': [sb.x(i) for i in obj_B['dat']]
            
        # remove defect
        sb.h(obj_A['anc'])
        if dtype == 'p': [sb.cz(obj_A['anc'], target) for target in obj_A['dat']]
        elif dtype == 'd': [sb.cx(obj_A['anc'], target) for target in obj_A['dat']]
        sb.h(obj_A['anc'])
        md = sb.m(qid=[obj_A['anc']])
        if md.last == '1':
            if dtype == 'p': [sb.x(i) for i in chain]
            elif dtype == 'd': [sb.z(i) for i in chain]
            sb.x(obj_A['anc'])

        chain.append(q)

    if annihilate == True:
        obj_A = lattice[obj][pos_A[0]][pos_A[1]]
        obj_B = lattice[obj][path[-1][0]][path[-1][1]]
        q = get_common_qid(obj_A, obj_B)[0]
        if dtype == 'p': md = sb.mx(qid=[q])
        elif dtype == 'd': md = sb.m(qid=[q])
        return md.last
    
    return None

def measure_logical_X(sb, chain_A, chain_B, shots=1):

    mval_list = []
    for _ in range(shots):
        sb_tmp = sb.clone()
        mval_A = sb_tmp.mx(qid=chain_A).last
        mval_B = sb_tmp.mx(qid=chain_B).last
        mval_A_bin = str(sum([int(s) for s in list(mval_A)])%2)
        mval_B_bin = str(sum([int(s) for s in list(mval_B)])%2)
        mval = (XBASE[mval_A_bin] + XBASE[mval_B_bin])
        mval_list.append(mval)
        sb_tmp.free()
        
    return Counter(mval_list)

def operate_logical_Z(sb, lq, lattice):

    if lq == 0: face = lattice['face'][0][0]
    elif lq == 2: face = lattice['face'][0][7]
    elif lq == 3: face = lattice['face'][6][0]
    [sb.z(q) for q in face['dat']]

def operate_logical_cnot(lq, shots=5):

    # set lattice
    lattice_row, lattice_col = 7, 8
    lattice = create_lattice(lattice_row, lattice_col)

    # make vacuum state
    qubit_num = (2 * lattice_row + 1) * (2 * lattice_col + 1)
    sb = Stabilizer(qubit_num=qubit_num, gene_num=qubit_num+1)
    initialize(sb, lattice)

    # set logical qubit #0
    p0_pos_A, p0_pos_B = [0,0], [0,1]
    p0_path = [[0,1],[0,2]]
    move_defect(sb, p0_pos_A, p0_pos_B, p0_path, 'p', lattice, create=True)
    if lq[0] == '-': operate_logical_Z(sb, 0, lattice)

    # set logical qubit #1
    d1_pos_A, d1_pos_B = [2,5], [3,5]
    d1_path = [[3,5],[4,5],[5,5]]
    move_defect(sb, d1_pos_A, d1_pos_B, d1_path, 'd', lattice, create=True)

    # set logical qubit #2
    p2_pos_A, p2_pos_B = [0,7], [1,7]
    p2_path = [[1,7],[2,7],[3,7]]
    move_defect(sb, p2_pos_A, p2_pos_B, p2_path, 'p', lattice, create=True)

    # set logical qubit #3
    p3_pos_A, p3_pos_B = [6,0], [6,1]
    p3_path = [[6,1],[6,2]]
    move_defect(sb, p3_pos_A, p3_pos_B, p3_path, 'p', lattice, create=True)
    if lq[1] == '-': operate_logical_Z(sb, 3, lattice)

    # braid logical qubit #0
    p0_pos_A, p0_pos_B = [0,0], [0,2]
    p0_path = [[0,2],[1,2],[2,2],[3,2],[3,3],[3,4],[3,5],[3,6],
               [2,6],[1,6],[0,6],[0,5],[0,4],[0,3],[0,2]]
    move_defect(sb, p0_pos_A, p0_pos_B, p0_path, 'p', lattice)
    
    # braid logical qubit #2
    p2_pos_A, p2_pos_B = [0,7], [3,7]
    p2_path = [[3,7],[3,6],[3,5],[3,4],[3,3],[4,3],[5,3],
              [6,3],[6,4],[6,5],[6,6],[6,7],[5,7],[4,7],[3,7]]
    move_defect(sb, p2_pos_A, p2_pos_B, p2_path, 'p', lattice)

    # braid and annihilate logical qubit #3
    p3_pos_A, p3_pos_B = [6,0], [6,2]
    p3_path = [[6,2],[6,3],[6,4],[6,5],[6,6],[5,6],[4,6],[3,6],
               [3,5],[3,4],[3,3],[3,2],[4,2],[5,2],[6,2],[6,1]]
    mval_p = move_defect(sb, p3_pos_A, p3_pos_B, p3_path, 'p', lattice, annihilate=True)

    # braid and annihilate logical qubit #1
    d1_pos_A, d1_pos_B = [2,5], [5,5]
    d1_path = [[5,5],[4,5],[3,5]]
    mval_d = move_defect(sb, d1_pos_A, d1_pos_B, d1_path, 'd', lattice, annihilate=True)

    if mval_p == '1':
        operate_logical_Z(sb, 0, lattice)
        operate_logical_Z(sb, 2, lattice)
    
    # measure logical qubits: #0 and #2
    chain_0 = get_chain(get_path([0,0],[0,2]), 'p', lattice)
    chain_2 = get_chain(get_path([0,7],[3,7]), 'p', lattice)
    freq = measure_logical_X(sb, chain_0, chain_2, shots=shots)
    print("Input('{0:}') == [CNOT] ==> {1:}".format(lq, freq))

    sb.free()

if __name__ == '__main__':

    operate_logical_cnot('++', shots=10)  # --> '++'
    operate_logical_cnot('+-', shots=10)  # --> '--'
    operate_logical_cnot('-+', shots=10)  # --> '-+'
    operate_logical_cnot('--', shots=10)  # --> '+-'

Cela fait assez longtemps, je vais donc l'expliquer grossièrement. La fonction operer_logical_cnot est la partie principale de ce temps. En donnant l'état d'entrée sous forme de chaîne de caractères ('++', '+ -', '- +', '-') comme premier argument et en donnant le nombre de mesures sous forme de valeur entière dans le deuxième argument, le résultat de la mesure Afficher.

Regardez à l'intérieur de la fonction operation_logical_cnot.

# set lattice
lattice_row, lattice_col = 7, 8
lattice = create_lattice(lattice_row, lattice_col)

Ensuite, définissez les tailles verticale et horizontale de la grille à 7 $ \ fois 8 $ comme expliqué dans la figure ci-dessus et créez les données de la grille avec la fonction create_lattice. C'est la même chose que Article précédent, je vais donc omettre l'explication.

# make vacuum state
qubit_num = (2 * lattice_row + 1) * (2 * lattice_col + 1)
sb = Stabilizer(qubit_num=qubit_num, gene_num=qubit_num+1)
initialize(sb, lattice)

Ensuite, donnez le nombre de bits quantiques et le nombre de sources de génération correspondant au réseau créé au constructeur de stabilisateur Stabilizer pour créer l'instance sb. Utilisez ensuite la fonction initialize pour le mettre dans un état vide. Autrement dit, répartissez les opérateurs de face et de sommet sur la grille. Voir la définition de fonction ci-dessus pour plus de détails. Je viens de définir l'opérateur $ X $ ou $ Z $ sur chaque bit quantique en utilisant la méthode set_pauli_op de sb.

# set logical qubit #0
p0_pos_A, p0_pos_B = [0,0], [0,1]
p0_path = [[0,1],[0,2]]
move_defect(sb, p0_pos_A, p0_pos_B, p0_path, 'p', lattice, create=True)
if lq[0] == '-': operate_logical_Z(sb, 0, lattice)

Générera le 0ème bit quantique logique. Avec la fonction move_defect, les bits quantiques aux limites des coordonnées de l'opérateur plan [0,0], [0,1] sont mesurés par $ X $ pour générer une paire de défauts de type p, et les défauts de [0,1] sont générés. Nous sommes en train de passer aux coordonnées [0,2]. Si l'option create de la fonction move_defect est définie sur True, la génération et le mouvement ultérieur seront exécutés. Si False (par défaut), déplacez uniquement (en supposant qu'il a déjà été généré) sans le générer. De plus, comme nous le verrons plus tard, si vous spécifiez Vrai pour l'option d'annihilation, la mesure sera effectuée après le déplacement (en supposant que les paires de défauts sont adjacentes). Voir la définition de la fonction pour plus d'informations sur la fonction make_defect. Cela vous donnera un $ \ ket {+} $ logique. Le dernier if lq [0] == '-' est une opération à inverser en appliquant l'opérateur logique $ Z $ lorsque le 0ème état d'entrée donné à la fonction operer_logical_cnot est "-". Voir également la définition de la fonction pour plus d'informations sur la fonction Operate_logical_Z.

# set logical qubit #1
d1_pos_A, d1_pos_B = [2,5], [3,5]
d1_path = [[3,5],[4,5],[5,5]]
move_defect(sb, d1_pos_A, d1_pos_B, d1_path, 'd', lattice, create=True)

# set logical qubit #2
p2_pos_A, p2_pos_B = [0,7], [1,7]
p2_path = [[1,7],[2,7],[3,7]]
move_defect(sb, p2_pos_A, p2_pos_B, p2_path, 'p', lattice, create=True)

# set logical qubit #3
p3_pos_A, p3_pos_B = [6,0], [6,1]
p3_path = [[6,1],[6,2]]
move_defect(sb, p3_pos_A, p3_pos_B, p3_path, 'p', lattice, create=True)
if lq[1] == '-': operate_logical_Z(sb, 3, lattice)

donc. Génère les premier, deuxième et troisième bits quantiques logiques. Ceci termine l'état initial.

# braid logical qubit #0
p0_pos_A, p0_pos_B = [0,0], [0,2]
p0_path = [[0,2],[1,2],[2,2],[3,2],[3,3],[3,4],[3,5],[3,6],
           [2,6],[1,6],[0,6],[0,5],[0,4],[0,3],[0,2]]
move_defect(sb, p0_pos_A, p0_pos_B, p0_path, 'p', lattice)

Ensuite, le 0ème bit quantique logique (défaut de type p) est enroulé autour du 1er bit quantique logique (défaut de type d).

# braid logical qubit #2
p2_pos_A, p2_pos_B = [0,7], [3,7]
p2_path = [[3,7],[3,6],[3,5],[3,4],[3,3],[4,3],[5,3],
          [6,3],[6,4],[6,5],[6,6],[6,7],[5,7],[4,7],[3,7]]
move_defect(sb, p2_pos_A, p2_pos_B, p2_path, 'p', lattice)

Ensuite, enroulez le deuxième bit quantique logique (défaut de type p) autour du premier bit quantique logique (défaut de type d).

# braid and annihilate logical qubit #3
p3_pos_A, p3_pos_B = [6,0], [6,2]
p3_path = [[6,2],[6,3],[6,4],[6,5],[6,6],[5,6],[4,6],[3,6],
           [3,5],[3,4],[3,3],[3,2],[4,2],[5,2],[6,2],[6,1]]
mval_p = move_defect(sb, p3_pos_A, p3_pos_B, p3_path, 'p', lattice, annihilate=True)

Ensuite, le troisième bit quantique logique (défaut de type p) est enroulé autour du premier bit quantique logique (défaut de type d), et finalement il disparaît. La fonction move_defect est conçue pour renvoyer la valeur mesurée au moment de l'extinction, conservez-la donc sous la forme mval_p (sera utilisée plus tard).

# braid and annihilate logical qubit #1
d1_pos_A, d1_pos_B = [2,5], [5,5]
d1_path = [[5,5],[4,5],[3,5]]
mval_d = move_defect(sb, d1_pos_A, d1_pos_B, d1_path, 'd', lattice, annihilate=True)

Mesure le premier bit quantique logique (défaut de type d). Soit la valeur mesurée mval_d.

if mval_p == '1':
    operate_logical_Z(sb, 0, lattice)
    operate_logical_Z(sb, 2, lattice)

Ainsi, si la valeur de mval_p (valeur mesurée au moment de l'extinction du 3ème bit quantique logique) est -1 (1 comme indice de mesure), les derniers 0ème et 2ème bits quantiques logiques sont inversés. Je vais.

# measure logical qubits: #0 and #2
chain_0 = get_chain(get_path([0,0],[0,2]), 'p', lattice)
chain_2 = get_chain(get_path([0,7],[3,7]), 'p', lattice)
freq = measure_logical_X(sb, chain_0, chain_2, shots=shots)
print("Input('{0:}') == [CNOT] ==> {1:}".format(lq, freq))

Donc, pour vérifier s'il s'agit d'une opération CNOT, mesurez le 0ème bit quantique logique et le 2ème bit quantique logique pour $ X $. Puisque les deux sont des défauts de type p, vous pouvez mesurer la chaîne d'opérateurs $ X $ qui connectent les défauts. Je fais cela avec l'opérateur measure_logical_X. Le résultat de la mesure est stocké en fréquence au format Compteur, il est donc affiché à la fin. c'est tout.

résultat

Le résultat de l'exécution est le suivant.

Input('++') == [CNOT] ==> Counter({'++': 10})
Input('+-') == [CNOT] ==> Counter({'--': 10})
Input('-+') == [CNOT] ==> Counter({'-+': 10})
Input('--') == [CNOT] ==> Counter({'+-': 10})

Pour les quatre modèles d'entrée, il y avait une chance de 100 $ % $ d'obtenir les bons résultats d'opération CNOT.

en conclusion

Il est très intéressant de pouvoir effectuer des opérations logiques avec le Braiding comme celui-ci, mais il est assez difficile de l'implémenter sur du matériel réel. Il y a beaucoup de défauts sur le plan de la grille et nous devons effectuer le calcul pour les enrouler, mais la disposition initiale et la méthode d'enroulement ne sont pas les mêmes, et en premier lieu ce n'est pas bon devant beaucoup de défauts. Une fois implémenté, le programme circuit = peut être à l'état spaghetti (ou plutôt, des opérations logiques pourraient être effectuées en le mettant à l'état spaghetti, hmm). C'est peut-être le rôle du compilateur, donc le grand public peut ne pas s'en soucier, mais c'est un gros problème pour ceux qui vont faire un compilateur à partir de maintenant. Après tout, la chirurgie du treillis est-elle plus propre et de meilleures perspectives que le tressage (bien que je n'ai pas encore étudié).

Quand j'y pensais en écrivant le brouillon de cet article, j'ai fait l'annonce suivante.

Il semble que la compression de circuit puisse être effectuée efficacement en utilisant quelque chose appelé calcul ZX basé sur le tressage au lieu de la chirurgie en treillis (comment). Vous devrez peut-être le vérifier! (Mais que faire avant ça ...)

c'est tout

Recommended Posts

Bases de la théorie de l'information quantique: calcul quantique universel par code de surface (1)
Bases de la théorie de l'information quantique: codes de surface topologique
Bases de la théorie de l'information quantique: opération logique par code de surface (Brading)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code CSS)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code du stabilisateur: 4)
Bases de la théorie de l'information quantique: Entropie (2)
Bases de la théorie de l'information quantique: correction d'erreur quantique (code linéaire classique)
Bases de la théorie de l'information quantique: limites d'Horebaud
Bases de la théorie de l'information quantique: distance de trace
Bases de la théorie de l'information quantique: tomographie d'état quantique
Bases de la théorie de l'information quantique: compression de données (2)
Bases de la théorie de l'information quantique: calcul quantique tolérant aux pannes
Calcul de similitude par MinHash
Quantification de la "conscience" en théorie de l'information intégrée (IIT3.0), méthode de calcul de Φ
Lire "Principes de base du recuit quantique" Jour 5
Lire "Les bases du recuit quantique" Jour 6
Exemple de réécriture de code par ast.NodeTransformer
Principes de base de Tableau (visualisation à l'aide d'informations géographiques)