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>