4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

量子コンピューターによるロボットの姿勢制御手法(論文解説)

Last updated at Posted at 2025-12-06

はじめまして、Classiqで量子エンジニアをしています。

最近プレスリリース[1-4]で見かけた論文が興味深かったため、今回はその内容について解説し、実装まで行っていきたいと思います。

この論文を取り上げた理由は、基本的な量子ゲート操作だけでロボットアームのシミュレーションを実行できる点にあります。量子コンピューティングの基礎理解にも役立つ内容だと感じたため、学習素材としても有用だと思いました。

Introduction

近年、量子コンピューティングのロボティクスへの応用が進みつつあります。特にロボットアームの姿勢制御では、逆運動学(Inverse Kinematics, IK)の計算が必要不可欠です。しかし、多関節ロボットのIKは,

  • 非線形で多峰性(?)の最適化問題
  • 解析解が存在しないことが多い
  • 数値最適化による反復計算が重い
  • 高精度かつ滑らかな動作には限界がある

といった課題があります。

論文では、量子計算で順運動学(Forward Kinematics)を実行し、古典的最適化と組み合わせてIKを解く QOA(Quantum Optimization Algorithm)が提案され、Fujitsu の 256 量子ビットプロセッサで実行まで行っています。

前提知識

ロボットアームの最適化を理解するため、まずロボット工学の基礎を簡単に振り返っておきます。ここでは説明を単純化するため、2 次元平面で動作する 2 関節ロボットアームを考えます。三角関数を用いることで、ロボットアーム先端の座標 $(x,y)$は次式で表せます:

Gemini_Generated_Image_jheb6mjheb6mjheb.png

ここで, ロボットの手先の座標$(x,y)$は以下で与えられます。
$$
x = L_1 \cos\theta_1 + L_2\cos(\theta_1+\theta_2)
\quad
y = L_1 \sin\theta_1 + L_2\sin(\theta_1+\theta_2)
$$
ここで順運動学は、与えられた関節角度 $(\theta_1,\theta_2)$から手先位置 $(x,y)$ を求める操作です。逆運動学はその逆で、目標位置 $\mathbf{x}$ を実現する関節角度 $\mathbf{\theta}$ を求める問題を指します。

3. 量子ビットでリンクの向きを表現する

スクリーンショット 2025-12-06 16.27.40.png

この論文の最大の特徴は、ロボットリンクの向きを「量子ビットの状態」として表現する点にあります。 量子ビットはブロッホ球による三次元ベクトルで表現でき、その期待値 $(\langle X\rangle,\langle Y\rangle,\langle Z\rangle)$がリンク方向と対応している、というアイデアです。

量子ビットはブロッホ球(3次元球面)で表すことができ、量子力学的にベクトル表現を表すと以下のようになります。
$$
|\psi\rangle = \cos\frac{\theta}{2}|0\rangle + e^{i\phi}\sin\frac{\theta}{2}|1\rangle
$$
アームの関節点はBloch球上の点に対応しており、その3次元座標は以下の関数と対応しているというアイデアです。
$$
(\langle X\rangle,\langle Y\rangle,\langle Z\rangle)
= (\sin\theta\cos\phi, \sin\theta\sin\phi, \cos\theta)
$$
図の回路を見ると、アームのリンク1とリンク2が独立しているように見えますが、一部のパラメータを共有することで、リンク2の状態にリンク1の回転が蓄積される構造が実現されています。論文では、アーム同士をエンタングルさせる拡張案も提案されています。 まとめると、量子回路における制御関係を用いて、リンク1 → リンク2 の階層構造を表現している形になります。

  • 親リンク L1 の回転は子リンク L2 に伝播
  • 各リンクは $RX,RY,RZ$ の回転ゲートでパラメタライズ
  • 測定によって期待値ベクトルを取り出し、これをリンク方向ベクトルと解釈

論文後半のエンドエフェクタ位置の推定は、期待値ベクトルの和として次のように定義されます(ここは論文に明示的記載がないため私の解釈です):

$$
(x, y, z)=
\begin{pmatrix}
\langle X_0\rangle,
\langle Y_0\rangle,
\langle Z_0\rangle
\end{pmatrix}
+
\begin{pmatrix}
\langle X_1\rangle,
\langle Y_1\rangle,
\langle Z_1\rangle
\end{pmatrix}
$$

ここで、添え字は第0量子ビットまたは第一量子ビットになります。

5. Quantum Optimization Algorithm (QOA)

逆運動学は、量子計算+古典最適化のハイブリッドで解かれます。

  1. 量子回路に関節角度 $\theta$ を入力
  2. 測定により順運動学の結果(エンドエフェクタ位置)を取得
  3. 計算誤差
    $$
    |P_\text{target}-P_\text{est}|^2
    $$
    を評価(ここで, $P_\text{target}$は目標座標, $P_{\rm est}$はQOAによって与えられる座標.)
  4. 古典最適化(COBYLA)で $\theta$ を更新
  5. 収束まで 1–4 を繰り返す

CLASSIQのQmodで実装

論文では Qiskit を使用していますが、本記事では Classiq が提供する量子言語 Qmod を使って実装します。Qmodは他社言語と違い、ハイレベルな記述から回路生成の自動化を行いますが、もちろん通常のようなゲートレベルでの記述も対応しています。特に、今回のような固定 ansatz を最適化するというケースでは、どの量子プログラミング言語を使っても大きな違いは出ません。

まずは、必要なPackageを読み込みます。

import math
import matplotlib.pyplot as plt
import numpy as np
import scipy
from tqdm import tqdm

量子回路の測定回数とQOAで必要とするパラメータ数に一致する初期パラメータを適当に準備します。

NUM_SHOTS = 1000
MAX_ITERATIONS = 50
DOF = 6
initial_params = (
    (np.linspace(0, 1,DOF))
    * math.pi
)
print(initial_params)

ここで、$\texttt{MAX_ITERATIONS}$はCOBYLAの最適化回数で、$\texttt{DOF}$は論文中に記載のロボットアームの自由度です。

次に論文記載のansatzを設計します。論文ではエンタングルメントあり/なしの量子回路をansatzとして提案していますが、この論文ではエンタングルなしでansatzを実装してみます。

スクリーンショット 2025-12-06 0.30.39.png

上記のansatzをQmodで冗長的に書くことができます。ここで, コード内のthetaはQOAで使用する学習用パラメータになります。これは, COBYLAでロス関数を使用して最適化されます。現状では外部パラメータとして設定することができます。

@qfunc 
def q0_rotate(theta: CArray[CReal], q0:QBit):
    RZ(theta[2], q0)
    RY(theta[1], q0)
    RX(theta[0], q0)

@qfunc 
def q1_rotate(theta: CArray[CReal], q1:QBit):
    RZ(theta[5], q1)
    RY(theta[4], q1)
    RX(theta[3], q1)

@qfunc 
def pauli_Y_measure(q:QArray):
    S(q[0])
    H(q[0])
    S(q[1])
    H(q[1])
    

def main_project_measure(pauli_term):
    @qfunc 
    def main(theta:CArray[CReal,6], q:Output[QArray[QBit,2]]):
        allocate(q)
        q0_rotate(theta,q[0])
        q1_rotate(theta,q[1])
        q0_rotate(theta,q[1])
        if pauli_term == "Z":
            pass
        elif pauli_term == "X":
            H(q[0])
            H(q[1])
        elif pauli_term == "Y":
            pauli_Y_measure(q)
    return main

上記で作成した回路を合成します。

#X基底回路
qmod_X = create_model(main_project_measure("X"))
qprog_X = synthesize(qmod_X)
#Y基底回路
qmod_Y = create_model(main_project_measure("Y"))
qprog_Y = synthesize(qmod_Y)
#Z基底回路
qmod_Z = create_model(main_project_measure("Z"))
qprog_Z = synthesize(qmod_Z)

これで、Ansatz回路に対して、$\braket{X}$, $\braket{Y}$, $\braket{Z}$基底測定用の回路の準備ができました。射影測定に関しては他の方の記事を参考にしていただければと思います。

期待値計算はそれぞれの量子ビットで0がでた回数と1が出た回数から計算します。

def expected_value(counts):
    expect_value_qubit0 = ((counts.get('00', 0) + counts.get('01', 0)) - (counts.get('10', 0) + counts.get('11', 0))) / NUM_SHOTS
    expect_value_qubit1 = ((counts.get('00', 0) + counts.get('10', 0)) - (counts.get('01', 0) + counts.get('11', 0))) / NUM_SHOTS
    return expect_value_qubit0, expect_value_qubit1

これで、それぞれの期待値が算出できるので、コスト関数が作成できます。ここで、論文記載のターゲット座標を

target_pos = np.array([0.6, 1.0, 0.2])

と設定します。これがロボットアームの手先が目標とする座標になります。

cost_trace = []
L1, L2 = 1.0, 1.0
cost_trace = []
def evaluate_params(es_X, es_Y, es_Z, params):
    X_sample = es_X.sample(parameters={"theta": params.tolist()})
    Y_sample = es_Y.sample(parameters={"theta": params.tolist()})
    Z_sample = es_Z.sample(parameters={"theta": params.tolist()})
    X0_expect, X1_expect = expected_value(X_sample.counts)
    Y0_expect, Y1_expect = expected_value(Y_sample.counts)
    Z0_expect, Z1_expect = expected_value(Z_sample.counts)
    # 各リンクのBloch測定期待値
    v0 = np.array([X0_expect, Y0_expect, Z0_expect])
    v1 = np.array([X1_expect, Y1_expect, Z1_expect])
    # エンドエフェクタ推定位置
    estimate_pos = L1 * v0 + L2 * v1
    cost_estimation = np.sum(( target_pos - estimate_pos )**2)
    cost_trace.append(float(cost_estimation))
    return cost_estimation
evaluate_params(es_X, es_Y, es_Z, initial_params)

最後に、COBYLAを使用してパラメータ最適化を行いターゲット位置に到達するためのそれぞれのアームのパラメータを求めます。

with tqdm(total=MAX_ITERATIONS, desc="Optimization Progress", leave=True) as pbar:

    def progress_bar(xk: np.ndarray) -> None:
        pbar.update(1)  # increment progress bar

    final_params = scipy.optimize.minimize(
        fun=lambda params: evaluate_params(es_X, es_Y, es_Z, params),
        x0=initial_params,
        method="COBYLA",
        options={"maxiter": MAX_ITERATIONS},
        callback=progress_bar,
    ).x.tolist()

print(f"Optimized parameters: {final_params}")
plt.plot(cost_trace)
plt.xlabel("Iterations")
plt.ylabel("Cost")
plt.title("Cost convergence")

横軸をCOBYLAの回数、縦軸がターゲット座標との近さを表したコスト関数になります。0近くまで収束している、すなわちおおむねターゲット座標に近づいていることがわかります。

スクリーンショット 2025-12-06 16.57.57.png

ここから、最適なパラメータから算出したQOAの結果とターゲット座標を比べると

predict_arm_position : [0.666 1.28  0.18 ]
target_arm_position : [0.6 1.  0.2]

となり、おおむねターゲット位置にロボットアームを持ってこれたことができました。
これまでの量子計算結果を使用してCGで量子結果を踏まえてシミュレーションすることが可能です。今回のケースではアームのそれぞれの関節角の座標がCOBYLAのitrationごとに取得できます。

#itr=1
v0= [-0.334 -0.822  0.564]
v1= [-0.334 -0.822  0.564]
#itr=2
v0= [-0.324 -0.052  0.95 ]
v1= [-0.324 -0.052  0.95 ]
....
#itr=10
v0= [ 0.138  0.896 -0.412]
v1= [ 0.138  0.896 -0.412]

そうすると以下のように視覚的にロボットアームがどういった形で量子計算によって制御されているのか確認できます。(*動画は自前で作成しましたが、あくまでイメージ例です。空中に浮かんでいる球が目標座標になります。)
arm_opt.gif

Summary & Outlook

  • QOA により、量子回路を介してロボットアームを目標位置へ移動させる手法を実装
  • 論文では entangled ansatz を用いることで、精度向上が実機で確認されている
  • 今後の発展としては、より高度な QOA バリエーションの導入、可動域制約を組み込んだコスト関数の設計、アーム長が異なるケースの拡張などが考えられる

Reference

[1]https://global.fujitsu/ja-jp/pr/news/2025/08/25-01
[2]https://www.shibaura-it.ac.jp/headline/detail/20250825-7070-001.html
[3]https://www.waseda.jp/inst/research/news/81826
[4]https://www.nature.com/articles/s41598-025-12109-0

4
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?