1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

100マス量子回路計算やってみよう〜中級編〜

大好評だった初級編に引き続き、中級編もやってみましょう。
今回、2量子ビットに増えて、CNOTゲートが加わりました。

それに伴い、状態の数がめちゃくちゃに増えました。
|0>, |1>, |+>, |->, |i>, |-i>の直積で書けるものや、4つのベル状態

|\Phi_+>=(|00>+|11>)/ \sqrt{2}
|\Phi_->=(|00>-|11>)/ \sqrt{2}
|\Psi_+>=(|01>+|10>)/ \sqrt{2}
|\Psi_->=(|01>-|10>)/ \sqrt{2}

で書けるものもありますが、位相が違っていてそのような書き方ができないものも多数出来ました。

なので、今回は、直積やベル状態で書くか、1/√2|00> - 1/√2|10>のように書くか、各状態の成分を書くかのいずれかで回答してください。
また、1/2と1/√2は省略してもいいものとします。

暗算でやるのはかなり難しいと思いますが、がんばってみてください。

100マス量子計算中級編

100マス量子計算中級編.png

答え

今回は、左列から順に縦方向で答えを表示しています。

from cmath import phase
from math import pi
import math
import numpy as np
from blueqat import Circuit

# 中級編
tate = [
    Circuit().h[0].cx[0, 1],
    Circuit().h[0].cx[0, 1].h[1],
    Circuit().x[0].h[0].cx[0, 1],
    Circuit().h[0, 1],
    Circuit().x[0].h[1],
    Circuit().h[:].s[0].sdg[1],
    Circuit().h[0].sdg[0].y[1],
    Circuit().h[0].cx[0, 1].s[1],
    Circuit().h[0].cx[0, 1].y[0],
    Circuit().h[0].cx[0, 1].y[:],
]

yoko = [
    Circuit().h[0].cx[0, 1],
    Circuit().cx[1, 0].h[1],
    Circuit().y[0, 1],
    Circuit().s[1].cx[0, 1].h[1],
    Circuit().h[:].s[0].sdg[1],
    Circuit().z[1].cx[1, 0].h[1],
    Circuit().x[0].z[1].cx[0, 1].h[0],
    Circuit().h[0].cx[0, 1].y[0],
    Circuit().h[0].cx[0, 1].s[1],
    Circuit().cx[0, 1].cx[1, 0],
]

states = [
    (np.array([1, 0], dtype=complex), '|0>'),
    (np.array([0, 1], dtype=complex), '|1>'),
    (np.array([1, 1], dtype=complex) / np.sqrt(2), '|+>'),
    (np.array([1, -1], dtype=complex) / np.sqrt(2), '|->'),
    (np.array([1, 1j], dtype=complex) / np.sqrt(2), '|i>'),
    (np.array([1, -1j], dtype=complex) / np.sqrt(2), '|-i>'),
]
sqrt2_inv = 1/2**0.5

def to_str(val, label, is_firstterm):
    val_abs = abs(val)

    if abs(val_abs) < 1e-5:
        return '' # Zero
    if abs(val_abs - 1) < 1e-5:
        val_s = ''
    elif abs(val_abs - sqrt2_inv) < 1e-5:
        val_s = '/√2'
    elif abs(val_abs - 0.5) < 1e-5:
        val_s = '/2'
    else:
        raise ValueError('Strange value. val = ', val)

    if is_firstterm:
        sign = ''
    else:
        sign = '+'
    imag = '1' # if real '1' else 'i'
    val_phase = phase(val)
    if abs(val_phase) < 1e-5:
        pass
    elif abs(val_phase - 0.5 * pi) < 1e-5:
        imag = 'i'
    elif abs(val_phase + 0.5 * pi) < 1e-5:
        sign = '-'
        imag = 'i'
    elif abs(val_phase - pi) < 1e-5 or abs(val_phase + pi) < 1e-5:
        sign = '-'
    else:
        raise ValueError('Strange phase. val = ', val)

    if imag == '1' and val_s == '':
        imag = ''
    if is_firstterm:
        return sign + imag + val_s + '|' + label + '>'
    return sign + ' ' + imag + val_s + '|' + label + '>'



def to_phasearr(state):
    zeros = np.isclose(state, 0.j)
    factor = math.sqrt(4 - sum(zeros))

    def to_phase(val, is_zero):
        if is_zero:
            return 0
        if np.isclose(val * factor, 1):
            return 1
        if np.isclose(val * factor, -1):
            return -1
        if np.isclose(val * factor, 1j):
            return 1j
        if np.isclose(val * factor, -1j):
            return -1j
        raise ValueError(f'val: {val}')

    return [to_phase(val, zero) for val, zero in zip(state, zeros)]


def check_bell(state):
    if np.allclose(state, np.array([sqrt2_inv, 0, 0, sqrt2_inv])):
        return '|Φ+>'
    if np.allclose(state, np.array([sqrt2_inv, 0, 0, -sqrt2_inv])):
        return '|Φ->'
    if np.allclose(state, np.array([0, sqrt2_inv, sqrt2_inv, 0])):
        return '|ψ+>'
    if np.allclose(state, np.array([0, sqrt2_inv, -sqrt2_inv, 0])):
        return '|ψ->'
    return None

single = {
        '|0>': np.array([1, 0], dtype=complex),
        '|1>': np.array([0, 1], dtype=complex),
        '|+>': np.array([sqrt2_inv, sqrt2_inv], dtype=complex),
        '|->': np.array([sqrt2_inv, -sqrt2_inv], dtype=complex),
        '|i>': np.array([sqrt2_inv, 1j * sqrt2_inv], dtype=complex),
        '|-i>': np.array([sqrt2_inv, -1j * sqrt2_inv], dtype=complex)
}
double = {k2 + k1: np.kron(s1, s2) for k1, s1 in single.items() for k2, s2 in single.items()}

def check_kron(state):
    for k, v in double.items():
        if np.allclose(state, v):
            return k
    return None

def get_answer(c1, c2):
    state = (c1.copy() + c2).run(ignore_global=True)
    bell = check_bell(state)
    kron = check_kron(state)
    ss = []
    for val, label in zip(state, ['00', '10', '01', '11']):
        s = to_str(val, label, not ss)
        if s:
            ss.append(s)
    s = ' '.join(ss)
    if bell:
        s = bell + '\t= ' + s
    elif len(ss) > 1 and kron:
        s = kron + '\t= ' + s
    return s

for c1 in yoko:
    for c2 in tate:
        print(get_answer(c2, c1))
    print('')

上級編?

量子ビット増やすとか、ゲート増やすとか、いくらでも難しくしようはあるんですが、ぶっちゃけこれ以上いりますかね……

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?