はじめの一歩

前提条件

  • Python3
  • numpy
  • scipy

インストール

$ git clone https://github.com/Blueqat/Blueqat
$ cd blueqat
$ pip3 install -e .

または

$ pip3 install blueqat

基本

回路の作り方

from blueqat import Circuit
import math

#number of qubit is not specified
c = Circuit()

#if you want to specified the number of qubit
c = Circuit(3) #3qubits

メソッド・チェーン

# write as chain
Circuit().h[0].x[0].z[0]

# write in separately
c = Circuit().h[0]
c.x[0].z[0]

Sliceによる複数ビット操作

Circuit().z[1:3] # Zgate on 1,2
Circuit().x[:3] # Xgate on (0, 1, 2)
Circuit().h[:] # Hgate on all qubits
Circuit().x[1, 2] # 1qubit gate with comma

ローテーション操作

Circuit().rz(math.pi / 4)[0]

測定

Circuit().m[0]

実行

Circuit().h[0].cx[0,1].run()

回数を指定した実行

c = Circuit().h[0].cx[0,1].m[:]
c.run(shots=100) # => Counter({'00': 48, '11': 52}) (random value.)

ハミルトニアン

from blueqat.pauli import *

hamiltonian1 = (1.23 * Z[0] + 4.56 * X[1] * Z[2]) ** 2
hamiltonian2 = (2.46 * Y[0] + 5.55 * Z[1] * X[2] * X[1]) ** 2
hamiltonian = hamiltonian1 + hamiltonian2
print(hamiltonian)

ハミルトニアンの単純化

hamiltonian = hamiltonian.simplify()
print(hamiltonian)

VQE

from blueqat import vqe
from blueqat.pauli import qubo_bit as q

hamiltonian = -3*q(0)-3*q(1)-3*q(2)-3*q(3)-3*q(4)+2*q(0)*q(1)+2*q(0)*q(2)+2*q(0)*q(3)+2*q(0)*q(4)+2*q(1)*q(2)+2*q(1)*q(3)+2*q(1)*q(4)+2*q(2)*q(3)+2*q(2)*q(4)+2*q(3)*q(4)
step = 2

result = vqe.Vqe(vqe.QaoaAnsatz(hamiltonian, step)).run()
print(result.most_common(12))

イジングモデルのハミルトニアンを作る場合は、q(x)ではなくZ(x)を使ってください。

hamiltonian = Z(0)-3*Z(1)+2*Z(0)*Z(1)+2*Z(0)*Z(2)

Ising Model

import blueqat.wq as wq
a = wq.Opt()
a.qubo = [[4,-4,-4],[0,4,-4],[0,0,4]]
a.sa() #=> [1, 1, 1]
print(a.E[-1]) #=>[0.0]

BlueqatからQiskit

qiskit.register(APItoken)
sampler = blueqat.vqe.get_qiskit_sampler(backend="backend name")
result = blueqat.vqe.Vqe(QaoaAnsatz(...), sampler=sampler).run(verbose=True)

BlueqatからQASM

Circuit.to_qasm()

#OPENQASM 2.0;
#include "qelib1.inc";
#qreg q[1];
#creg c[1];
#h q[0];

2-qubit Grover

from blueqat import Circuit
c = Circuit().h[:2].cz[0,1].h[:].x[:].cz[0,1].x[:].h[:].m[:]
c.run()
print(c.last_result()) # => (1, 1)

Maxcut QAOA

from blueqat import vqe, pauli
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (1, 3), (0, 2), (4, 0), (4, 3)]
ansatz = vqe.QaoaAnsatz(sum([pauli.Z(i) * pauli.Z(j) for i, j in edges]), 1)
result = vqe.Vqe(ansatz).run()
print(
"""   {4}
  / \\
 {0}---{3}
 | x |
{1}---{2}""".format(*result.most_common()[0][0]))

Optimization

import blueqat.wq as wq
c = wq.Opt().add([[1,1],[1,1]]).add("(q0+q1)^2")

#qaoa
print(c.qaoa().most_common(5))
#=>(((0, 0), 0.7639901896866), ((1, 0), 0.10321404014639714), ((0, 1), 0.10321404014639707), ((1, 1), 0.029581730020605202))

#annealing
print(c.run())
#=>[0, 0]

SA Annealing

import blueqat.wq as wq
a = wq.Opt()
a.qubo = wq.sel(3,1) #creating QUBO matrix
result = a.sa(shots=100,sampler="fast")
wq.counter(result)

Counter({'010': 29, '100': 34, '001': 37})

SA Parameters

シミュレーションにおけるいくつかのパラメータは調整可能です。

#for sa
a.Ts  = 10    #default 5
a.R   = 0.99  #default 0.95
a.ite = 10000 #default 1000

SA Energy Function

計算されたエネルギー関数は配列としてアトリビュート E に保存されます。

print(a.E[-1]) #=>[0.0]

#if you want to check the time evolution
a.plot()

SA Sampling

ショット数だけサンプリング、カウントを行う関数です。

result = a.sa(shots=100,sampler="fast")

print(result)

[[0, 1, 0],
[0, 0, 1],
[0, 1, 0],
[0, 0, 1],
[0, 1, 0],

counter(result) # => Counter({'001': 37, '010': 25, '100': 38})

D-Wave クラウドとの接続

APIトークンを用いたD-Waveマシンとの接続
import blueqat.wq as wq
a = wq.Opt()
a.dwavetoken = "your token here"
a.qubo = [[0,0,0,0,-4],[0,2,0,0,-4],[0,0,0,0,0],[0,0,0,0,0],[0,0,0,0,4]]
a.dw()

# => [1, 1, 0, 1, 1]

QUBO Functions

N個の量子ビットからK個を選択するQUBOを自動生成します

print(wq.sel(5,2))
#=>
[[-3  2  2  2  2]
[ 0 -3  2  2  2]
[ 0  0 -3  2  2]
[ 0  0  0 -3  2]
[ 0  0  0  0 -3]]

3番目の変数で指定した配列により量子ビットを選択できます

print(wq.sel(5,2,[0,2]))
#=>
[[-3.5  2.   2.   2.   2. ]
[ 0.  -3.   2.   2.   2. ]
[ 0.   0.  -3.5  2.   2. ]
[ 0.   0.   0.  -3.   2. ]
[ 0.   0.   0.   0.  -3. ]]

配列で指定したエッジを持つサイズNのグラフについて、エッジの値1である隣接行列QUBOを自動生成します

print(wq.net([[0,1],[1,2]],4))
#=>
[[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]

0番目と1番目、1番目2番目の量子ビット間の接続がそれぞれ1である4x4 QUBOを生成しました

zeros(N) は全要素が0のQUBOを生成します

print(wq.zeros(3))
#=>
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]

diag(list) は配列で指定した対角要素をもつQUBOを生成します

print(wq.diag([1,2,1]))
#=>
[[1 0 0]
[0 2 0]
[0 0 1]]

rands(N) ランダムな要素をもつQUBOを生成します

print(wq.rands(2))
#=>
[[0.89903411 0.68839641]
[0.         0.28554602]]