コンテンツにスキップ

SDK ソルバープラグイン開発ガイド

[!NOTE] 最新の実装状況は 機能実装ステータス (Remaining Functionality) を参照してください。

概要

EvoSpikeNet は SolverPlugin 機構を持ちます。組み合わせ最適化・QAOA・量子アニーリングなど
任意のソルバーバックエンドをプラグインとして差し替え可能です。

実用ユースケース: - クラシカル SA / Greedy — リアルタイム制約が厳しい場合のデフォルト - QAOA シミュレータ — 古典近似でのプロトタイプ評価 - Qiskit (IBMQ / Aer) — 量子ハードウェア接続 - D-Wave — 量子アニーリングデバイス接続 - ABCI-Q / Toshiba SQBM+ — ABCI-QのSystem H上で動作する量子インスパイア型Ising machine


アーキテクチャ

QPFCQAOABridge
   └─ get_optimizer(name)          # evospikenet/optimizer.py
        ├─ PluginFactory.SOLVER    # プラグインレジストリ優先
        │     ├─ "classical"        → ClassicalSolverPlugin   (SA)
        │     ├─ "qaoa_simulator"   → QAOASimulatorSolverPlugin
        │     ├─ "qiskit"           → QiskitSolverPlugin       (Aer / IBMQ)
        │     └─ "dwave"            → DWaveSolverPlugin        (QPU / SA fallback)
        └─ 組み込みバックエンド (フォールバック)

インストール

最小構成(classical / qaoa_simulator のみ):

pip install -e .

Qiskit バックエンドを有効化する場合:

pip install qiskit qiskit-aer

D-Wave バックエンドを有効化する場合:

pip install dwave-ocean-sdk

ABCI-Q上のToshiba SQBM+を使う場合は、CoreをABCI-Qの許可された実行環境へ配置し、Amplify v1 extraを導入します。

pip install -e '.[abci_q]'

Amplify SDKはproprietary softwareのため、commercial/deployment環境では適用されるlicense/利用契約を確認してから導入します。Core側で ABCI_Q_SQBM_URL と必要な ABCI_Q_SQBM_TOKEN をsecret管理から設定します。アクセス権、System H上の配置、Amplify ToshibaSQBM2Client.health_check()、小規模QUBO実行を確認した後にだけ ABCI_Q_EXECUTION_CONFIRMED=true を設定してください。SQBM+は量子インスパイア型で、物理量子QPUではありません。Qiskit等の物理QPUとは別backendとして扱います。

医療アプリ等のremote clientは evospikenet-remote-sdk の solve_qubo(backend="abci_q") を使用します。Core plugin classや get_optimizer() を利用アプリから直接importしてはなりません。

OpenJij と Fixstars Amplify を含む量子系の依存をまとめて導入する場合:

pip install -r EvoSpikeNet-Core/requirements-quantum.txt

導入後は依存整合性を確認します。

python -m pip check

Python 3.14 では Qiskit 1.x が要求する symengine<0.14 の wheel が提供されない環境があり、指定範囲をそのまま導入できない場合があります。導入できた Qiskit の版が Core の指定範囲と一致することを確認してから実機接続へ進んでください。


SolverPlugin インターフェース

必須実装メソッド:

メソッド 説明
get_metadata() PluginMetadata を返す。plugin_type=PluginType.SOLVER を指定
initialize() 依存ライブラリのロード・デバイス接続確認
activate() プラグインをアクティブ状態へ遷移
deactivate() リソース解放
solve(problem, timeout, options) 最適化を実行しソルバー候補リストを返す

solve() の引数 / 戻り値:

def solve(
    self,
    problem: Dict[str, Any],   # vehicles/stops または problem["qubo"]
    timeout: float = 5.0,       # 秒
    options: Dict[str, Any] = None,  # solver 固有パラメータ
) -> List[Dict[str, Any]]:
    # 戻り値は score 昇順(小ほど良い)のリスト
    # 各要素: {"assignment": {...}, "score": float, "meta": {...}}

QUBO入力の表現契約

航路割当などのQUBO問題では、problem["qubo"] は次のいずれかを受け付ける。

  • 密行列: list[list[float]]
  • 疎辞書: {(row, column): coefficient}。ゼロ係数は省略する
  • 既存の問題辞書: vehicles、stops、distances などを持つレガシー形式

新しい大規模問題では疎辞書を標準とし、D-Wave、OpenJij、Amplifyなど辞書形式を扱えるプラグインへそのまま渡す。Qiskitなど密行列変換が必要なプラグインは、実行境界でのみ密行列化する。プラグインは入力を破壊的に変更せず、受け付けた表現と変換結果を meta に記録する。

QuboProblem は to_dense() と to_sparse() を提供し、密行列と疎辞書の数値が一致することを検証できる。候補数が多い場合でも、同一機体・時間スロット・軌道競合の候補だけを比較し、全候補の総当たりを避ける。


カスタムソルバープラグインの作成手順

1. SolverPlugin を継承する

from evospikenet.plugins.solver_plugin import SolverPlugin
from evospikenet.plugins import PluginMetadata, PluginStatus, PluginType

class MyAnnealerPlugin(SolverPlugin):

    def get_metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="my_annealer",
            version="1.0.0",
            plugin_type=PluginType.SOLVER,
            description="Custom annealing backend",
            author="Your Team",
        )

    def initialize(self) -> bool:
        # 依存ライブラリの確認・接続初期化
        self.status = PluginStatus.INITIALIZED
        return True

    def activate(self) -> bool:
        self.status = PluginStatus.ACTIVE
        return True

    def deactivate(self) -> bool:
        self.status = PluginStatus.UNLOADED
        return True

    def solve(self, problem, timeout=5.0, options=None):
        # 実装: problem を最適化してソルバー候補を返す
        ...
        return [{"assignment": result, "score": cost, "meta": {"backend": "my_annealer"}}]

2. PluginFactory に登録する

import evospikenet.plugin_factory as _pf_mod
from evospikenet.optimizer import get_optimizer

# グローバルファクトリに登録
factory = _pf_mod._global_factory  # or PluginFactory()
plugin = MyAnnealerPlugin()
plugin.initialize()
plugin.activate()
factory.register_plugin(plugin)

# 以降は get_optimizer() で名前で取得できる
opt = get_optimizer("my_annealer")
result = opt.solve(problem, timeout=5.0)

3. 環境変数で実行時に切り替える(EVOSPIKENET_PLUGIN_ALLOWLIST)

# 自組織プラグインを追加でロード可能にする
export EVOSPIKENET_PLUGIN_ALLOWLIST="evospikenet.plugins,myorg.plugins"

組み込みバックエンド詳細

classical(SimulatedAnnealing)

  • 依存: なし
  • 特徴: ランダムスワップによる SA。リアルタイム制約下のデフォルト。
  • options: seed (int)

qaoa_simulator

  • 依存: なし
  • 特徴: SA/SPSA/greedy を組み合わせた古典 QAOA 近似。
  • options: seed (int)

qiskit

  • 依存: qiskit, qiskit-aer
  • 特徴: execution_target="aer" のローカルシミュレータ、または execution_target="ibm_qpu" のIBM Quantum QPU
  • 認証: IBM実機では token_env が指す環境変数にtokenを設定。Core pluginの互換既定値は IBMQ_TOKEN。アプリ統合では QISKIT_IBM_TOKEN を指定
  • options: provider (instance)、backend_name、execution_target、token_env、reps、shots
  • 注記: problem["qubo"] をQAOAへ変換する。IBM実機はtoken・instance・backendの設定が必要で、QPU実行失敗をローカル実行成功として扱わない。
export QISKIT_IBM_TOKEN="<your_ibm_quantum_token>"
export QISKIT_IBM_INSTANCE="<instance CRN>"
export QISKIT_IBM_BACKEND="<backend ID>"

dwave

  • 依存: dwave-ocean-sdk
  • 特徴: D-Wave QPU / SimulatedAnnealing / Tabu サンプラー
  • 認証: 環境変数 DWAVE_API_TOKEN, DWAVE_API_ENDPOINT
  • options: sampler ("QPU"|"SimulatedAnnealing"|"Tabu"), num_reads (int)
  • 注記: dwave-ocean-sdk 未導入時は SA フォールバック。
export DWAVE_API_TOKEN="<your_dwave_token>"

openjij

  • 依存: openjij
  • 特徴: OpenJij の SA / SQA / GPU sampler。ローカル SA/SQA は通常トークン不要。
  • options: sampler (SA、SQA、GPU)、num_reads、num_sweeps

fixstars_amplify

  • 依存: amplify
  • 特徴: Fixstars Amplify、Toshiba SQBM v2、Fujitsu Digital Annealer などの Amplify client を同じ plugin 契約で利用。
  • options: client (fixstars / toshiba_sbm / fujitsu_da3 / fujitsu_da4)、Toshiba用solver (Qubo / Qplib / Pubo)、token_env、url_env、timeout_ms
  • 認証: Fixstars AE は FIXSTARS_TOKEN。未設定時は古典 SA へフォールバック。
from evospikenet.optimizer import get_optimizer

fixstars = get_optimizer("fixstars_amplify", client="fixstars", token_env="FIXSTARS_TOKEN")
toshiba = get_optimizer("fixstars_amplify", client="toshiba_sbm", solver="Qubo", timeout_ms=3000)
fujitsu_da3 = get_optimizer("fixstars_amplify", client="fujitsu_da3", timeout_ms=3000)
fujitsu_da4 = get_optimizer("fixstars_amplify", client="fujitsu_da4", timeout_ms=3000)

アプリケーションの選択名 toshiba_sqbm_v2 は fixstars_amplify + client=toshiba_sbm に変換します。fujitsu_digital_annealer は client=fujitsu_da3 が既定ですが、client=fujitsu_da4 を明示すればDA4 clientを使用します。Toshibaのsolverは Qubo が既定で、AWS endpoint運用では AMPLIFY_TOSHIBA_URL、通常のtoken認証では AMPLIFY_TOSHIBA_TOKEN を使います。富士通DA3/DA4は AMPLIFY_FUJITSU_TOKEN を共有します。AMPLIFY_FUJITSU_URL はprovider指定のcustom endpointがある場合だけ設定してください。有効なQUBOの外部実行失敗は失敗として扱い、レガシーVRP形式の古典fallbackと混同しないでください。

Amplify のサービス別認証設定(2026-10-03)

キーはサーバーの環境変数へ置き、デバイス設定では client を切り替えます。キーの値を API の config やブラウザの保存設定へ渡す必要はありません。

config.client SDK client トークン環境変数 URL 環境変数
fixstars / fixstars_ae AmplifyAEClient FIXSTARS_AE_TOKEN FIXSTARS_AE_URL
fujitsu_da3 FujitsuDA3cClient AMPLIFY_FUJITSU_TOKEN 任意: AMPLIFY_FUJITSU_URL
fujitsu_da4 FujitsuDA4Client AMPLIFY_FUJITSU_TOKEN 任意: AMPLIFY_FUJITSU_URL
toshiba_sbm ToshibaSQBM2Client AMPLIFY_TOSHIBA_TOKEN またはAWS版URL認証 AMPLIFY_TOSHIBA_URL
dwave DWaveSamplerClient AMPLIFY_DWAVE_TOKEN AMPLIFY_DWAVE_URL
fixstars_se QUBO アダプタ未対応 FIXSTARS_SE_TOKEN(予約) FIXSTARS_SE_URL(予約)

AE は専用キーが空の場合に従来の FIXSTARS_TOKEN、D-Wave は DWAVE_API_TOKEN / DWAVE_API_ENDPOINT を互換設定として参照します。富士通や東芝が AE のキーを流用することはありません。token_env と url_env を明示すれば独自の環境変数名に切り替えられます。富士通 DA3 と DA4 の資格情報が異なる場合も、この方法で分離できます。

PUT /api/v1/control/route-optimization/device
Content-Type: application/json

{"device_id":"fixstars-amplify","config":{"client":"fujitsu_da4","token_env":"FUJITSU_DA4_TOKEN","url_env":"FUJITSU_DA4_URL","timeout_ms":3000}}

D-Wave の solver は AMPLIFY_DWAVE_SOLVER または config.solver、サンプル数は AMPLIFY_DWAVE_NUM_READS または config.num_reads で指定します。timeout_ms は AE、富士通、東芝の SDK の対応する時間パラメータに変換されます。D-Wave ではサンプル数を使い、同じ実行時間パラメータを送信しません。

Compose 運用では EvoMobilitySim の .env から管制コンテナへこれらの環境変数を転送します。キーを変更した後はコンテナの再作成が必要です。単独起動では uav_swarm_control/.env に設定します。

SDK 1.7.3 の公開 client には SE 専用 client を確認できないため、fixstars_se は NotImplementedError を返します。SE のキーを AE へ送信しません。SE 実行の実装には、契約対象の SE SDK/API の入力・出力・認証仕様が必要です。環境変数の予約は SE の実行対応を意味しません。

ionq(IonQ Quantum Cloud)

  • 依存: qiskit, qiskit-ionq または Core の IonQ plugin
  • 特徴: IonQ Simulator と IonQ QPU を backend で切り替える
  • options: api_key、project_id、backend、api_url、shots
  • 認証: IONQ_API_KEY または IONQ_API_TOKEN
simulator = get_optimizer(
    "ionq_quantum_cloud",
    project_id="project-name",
    backend="simulator",
    shots=1024,
)
qpu = get_optimizer(
    "ionq",
    project_id="project-name",
    backend="qpu.aria-1",
    token_env="IONQ_API_KEY",
)

IonQ の API key は config や options に直接書かず、環境変数または Secret 管理から読み込む。ionq_quantum_cloud は Core の ionq canonical plugin 名へ解決される。

Qiskit 実行先の分離

local = get_optimizer("qiskit", execution_target="aer")
ibm = get_optimizer(
    "qiskit",
    execution_target="ibm_qpu",
    provider="ibm-cloud-instance",
    backend_name="ibm_brisbane",
    token_env="QISKIT_IBM_TOKEN",
)

aer / local_simulator はローカル実行、ibm_qpu は IBM Quantum 実機実行である。ibm_qpu では token と provider/instance を要求し、初期化に失敗した場合にローカル Aer として成功扱いにしない。

Alias と CPU Classical

get_optimizer() は solver 名を小文字・underscore 形式へ正規化します。fixstars、fixstars_amplify_sdk、amplify は fixstars_amplify に、jij と open_jij は openjij に解決されます。

classical も同じ SolverPlugin 互換インターフェースから取得します。アプリケーション側で CPU だけ別 API を呼び出す必要はありません。

UAV 管制 API からの設定渡し

UAV 管制 API では、選択したデバイスの設定を次の API で保存します。

PUT /api/v1/control/route-optimization/device
Content-Type: application/json

{"device_id":"qiskit-local","config":{"solver_backend":"qiskit","backend_name":"aer_simulator","execution_target":"aer","shots":256}}

次回の backend=auto 実行で設定がplugin factoryへ渡されます。航路計画UIは実行時の device_id と非秘密solver設定をrequestの solver_config にsnapshotします。tokenそのものをJSONやUIのlocalStorageへ保存しないでください。

プロバイダ別のデバイス定義

[
    {"id":"qiskit-aer","backend":"qiskit","solver_backend":"qiskit","execution_target":"aer"},
    {"id":"ibm-qpu","backend":"qiskit","solver_backend":"qiskit","backend_name":"ibm_brisbane","execution_target":"ibm_qpu"},
    {"id":"amplify","backend":"amplify","solver_backend":"fixstars_amplify","client":"fixstars"},
    {"id":"toshiba-sqbm-v2","backend":"toshiba_sqbm_v2","solver_backend":"fixstars_amplify","client":"toshiba_sbm"},
    {"id":"fujitsu-da","backend":"fujitsu_digital_annealer","solver_backend":"fixstars_amplify","client":"fujitsu_da3"},
    {"id":"ionq-cloud","backend":"ionq_quantum_cloud","solver_backend":"ionq","backend_name":"simulator"}
]

backend=auto はアクティブデバイスを使い、リクエストで backend を明示した場合はその provider を優先する。execution_target は Qiskit のローカル/IBM 切り替えに使用し、Amplify 系は client、IonQ は backend で実行先を分ける。token、API key、秘密鍵は環境変数だけに置く。

検証コマンド

PYTHONPATH=EvoSpikeNet-Core python -m pytest \
    EvoSpikeNet-Core/tests/unit/test_priority2_type_safety_contracts.py -q
python -m pytest EvoSpikeNet-Core/tests/unit/test_qiskit_solver_plugin_optimization.py -q
python -m pytest future_apps/uav_swarm_control/tests/integration/test_route_optimization.py -q

認証情報がない環境で確認できるのは、型注釈、plugin 解決、ローカル sampler、依存不足時の古典フォールバックです。IBM Quantum、D-Wave QPU、Fixstars AE の live 接続は、それぞれの認証情報を Secret または環境変数から注入した環境で別途実行してください。


Q-PFC との統合

QPFCQAOABridge から直接バックエンド名を渡すだけで切り替え可能です。

from evospikenet.qpfc_qaoa_bridge import QPFCQAOABridge

# クラシカル(デフォルト)
bridge = QPFCQAOABridge(backend="classical")

# QAOA シミュレータ
bridge = QPFCQAOABridge(backend="qaoa_simulator")

# Qiskit / IBMQ
bridge = QPFCQAOABridge(backend="qiskit")

# D-Wave
bridge = QPFCQAOABridge(backend="dwave")

ベンチマーク

# 100 試行 × 4 サイズ × 2 バックエンドでベンチ
PYTHONPATH=.:EvoSpikeNet-Core python EvoSpikeNet-Core/scripts/bench_qpfc_qaoa_bulk.py --n 100

# 効果量レポートを確認
cat EvoSpikeNet-Core/bench_reports/qpfc_qaoa_effect_sizes.md

動作確認済みバックエンド(2026年9月)

バックエンド 確認内容 meta.backend
classical SAフォールバックなしで実行確認 simulated_annealing
qaoa_simulator SA/SPSA 古典近似実行確認 qaoa_simulator
openjij OpenJij SASampler のローカル実行 openjij_sa
fixstars_amplify plugin 解決とトークンなしの古典フォールバック simulated_annealing
dwave ローカル SimulatedAnnealing sampler dwave
qiskit plugin と Qiskit テスト。実機 QPU は資格情報が必要 qiskit

環境変数・.env 設定

.env ファイルは Products/.env に一元管理します。evospikenet.optimizer インポート時に自動読み込まれます。

# Products/.env  (すでに .gitignore 済み)
FIXSTARS_TOKEN=<your_fixstars_amplify_token>
IBMQ_TOKEN=<your_ibmq_token>
DWAVE_API_TOKEN=<your_dwave_token>
DWAVE_API_ENDPOINT=<your_dwave_endpoint>

関連ドキュメント