LoginSignup
2
1

More than 3 years have passed since last update.

Qiskit: WeightedPauliOperator, MatrixOperator, InitialStateなどなど

Last updated at Posted at 2020-01-23

はじめに

Qiskitで量子プログラミングをするのに際して重要なclassの使い方を記します。
特に、Qiskit AquaなどでQAOAだったりを使うときに必要かなと思います。
まだまだ未熟なところもあると思いますが、参考にしてくれると嬉しいです。

WeightedPailiOperator

QAOAだったり、VQEだったりにハミルトニアンを読み込ませるときに使うclass methodです。
qiskit.aqua.optimization.ising ではmax cutやtspなどのWeigthedPauliOperatorを返してくれるclass methodが提供されていますが、実際に自分で作ろうとすると少し大変です。
WeightedPauliOperatorに入れるclass methodはPauli classと呼ばれるものです。この説明を行いたいと思い餡巣。

Pauli

まずは、sample code
とりあえず、使う物すべてimport

import numpy as np

from qiskit.aqua.operators import WeightedPauliOperator, MatrixOperator
from qiskit.aqua.operators.op_converter import to_weighted_pauli_operator
from qiskit.aqua.components.initial_states import Custom, InitialState
from qiskit.quantum_info import Pauli
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

次に一番簡単な例

pauli_list = []
num_qubit = 3
z_p = np.zeros(num_qubit, dtype=bool)
x_p = np.zeros(num_qubit, dtype=bool)
pauli_list.append([1, Pauli(z_p, x_p)])

この場合はIIIをハミルトニアンに追加します。
次に、ZIZを追加したいとき

z_p[0] = True
z_p[2] = True
pauli_list.append([1, Pauli(z_p, x_p)])

ちなみに、appendしているlistの一つ目の要素(今は1)のところにはcomplex numberを入れることができます。次に、XXXを追加したいとき。

for i in range(num_qubit):
    x_p[i] = True
z_p = np.zeros(num_qubit, dtype=bool)
pauli_list.append([1, Pauli(z_p, x_p)])

Yを入れたいときはxもzもTrueにすればいいですね。
これを直接QAOAなどには入力できないので

qubitOp = WeightedPauliOperator(paulis=pauli_list)

で、完了です。
ちなみに、中身を見たい場合は

print(qubitOp.print_details())

でok
出力は

III (1+0j)
ZIZ (1+0j)
XXX (1+0j)

MatrixOperator

このclassはもっと直感的に記述したい人におすすめです。
例えばZ operatorを入れたいときは

z = np.array([[1, 0], [0, -1]])
z = MatrixOperator(z)
# 中身を見てみる
print(z.print_details())

出力は

  (0, 0)    1
  (1, 1)    -1

この形はなんだろう??と思うかもしれませんが、

|0><0|-|1><1| 

のことですね。
しかし、このままではQAOAなどに入力することができません。そこでconvertします。

z = to_weighted_pauli_operator(z)
# 中身を見てみる
print(z.print_details())

出力は

Z   (1+0j)

しっかり変形されましたね。しかしながら、複数のqubitを使っていきたい場合はtensorを計算しないといけないので、少し大変です。

InitialState

QAOAの関数の四つ目の引数のinitial_state
使い方がいまいちわからずInitialStateを使えばよいことは分かるが、いまいち、、、
調べてみてもなかなか出なかったのでここに記します。

Custom

circuitをInitialStateに変換するmethodがCustomです。
例えば

\frac{|00>+|01>+|10>+|11>}{2}

をinitial stateとして使いたいとき

qr = QuantumRegister(2)
qc = QuantumCircuit(qr)
qc.h(qr)

Custom(2, circuit=qc)

とすれば、QuantumCircuit classをInitialState classに変換することができます。

追記

Customを使うにあたって,qiskitのライブラリーを書き換える箇所があります.
qiskit/aqua/algorithms/minimum_eigen_solvers/qaoa/var_form.pyの中の

def construct_circuit(self, parameters, q=None):
    """ construct circuit """
    angles = parameters
    if not len(angles) == self.num_parameters:
        raise ValueError('Incorrect number of angles: expecting {}, but {} given.'.format(
            self.num_parameters, len(angles)
        ))
    # initialize circuit, possibly based on given register/initial state
    if q is None:
        q = QuantumRegister(self._num_qubits, name='q')
    if self._initial_state is not None:
        circuit = self._initial_state.construct_circuit('circuit', q)
    else:
        circuit = QuantumCircuit(q)
    circuit.u2(0, np.pi, q)
    for idx in range(self._p):
        beta, gamma = angles[idx], angles[idx + self._p]
        circuit += self._cost_operator.evolve(
            evo_time=gamma, num_time_slices=1, quantum_registers=q
        )
        circuit += self._mixer_operator.evolve(
            evo_time=beta, num_time_slices=1, quantum_registers=q
        )
    return circuit

def construct_circuit(self, angles):
    if not len(angles) == self.num_parameters:
        raise ValueError('Incorrect number of angles: expecting {}, but {} given.'.format(
            self.num_parameters, len(angles)
        ))
    circuit = QuantumCircuit()
    if self._initial_state:
        circuit += self._initial_state.construct_circuit('circuit')
    if len(circuit.qregs) == 0:
        q = QuantumRegister(self._cost_operator.num_qubits, name='q')
        circuit.add_register(q)
    elif len(circuit.qregs) == 1:
        q = circuit.qregs[0]
    else:
        raise NotImplementedError
    circuit.u2(0, np.pi, q)
    for idx in range(self._p):
        beta, gamma = angles[idx], angles[idx + self._p]
        circuit += self._cost_operator.evolve(None, evo_time=gamma, num_time_slices=1, quantum_registers=q)
        circuit += self._mixer_operator.evolve(None, evo_time=beta, num_time_slices=1, quantum_registers=q)
    return circuit

まとめ

自分で作ったHamiltonianでQAOAを実行してみたかったので勉強しました。
Qiskitの資料がネットに少ないので少しでも助けになればと思っています。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1