Skip to main content
IBM Quantum Platform

プロバイダーインターフェース

qiskit.providers

このモジュールには、Qiskitの外部プロバイダを構築するためのクラスが含まれています。 プロバイダとは、Qiskitに外部サービスを提供するものです。 この典型的な例は、バックエンド・プロバイダーである。 Backend オブジェクトを提供します。 QuantumCircuit オブジェクトを提供する。 このモジュールには、プロバイダとQiskitの間のインターフェイスを定義するために使用される抽象クラスが含まれています。


バージョン・サポート

プロバイダー・インターフェースの抽象クラスは、それぞれ個別にバージョン管理されている。 インターフェイスを変更する必要がある場合、新しいインターフェイスを定義するために新しい抽象クラスが作成される。 これらのインターフェイスの変更は、バージョン間の後方互換性を保証するものではありません。

バージョン変更

qiskit の各マイナーバージョンリリースは、バックエンドインターフェースのバージョンを1つのバージョン番号でインクリメントすることができる。 これは、そのインターフェイスにおける、そのリリースのすべてのインターフェイスの変更の集約となる。

バージョン・サポート・ポリシー

プロバイダーがこのインターフェイスの変更に適応する時間を持てるようにするため、Qiskitは各クラスの複数のバージョンを一度にサポートします。 リリースごとに1バージョンという性質を考えると、バージョンの非推奨方針は標準的な非推奨方針よりも少し保守的だ。 Qiskitは、最低3回のマイナーリリース、またはバージョンを導入したリリースから6ヶ月後の最初のリリースのいずれか長い方の期間、非推奨になる可能性がある前にプロバイダインターフェースのバージョンをサポートします。 それ以降は、標準の非推奨ポリシーがそのインターフェイスのバージョンに適用される。 これにより、プロバイダーとユーザーは、インターフェイスの変更に対応するための十分な時間を得ることができる。 例えば、 0.19.0 BackendV2 。 0.19.0 のリリースの3ヶ月後に、 0.20.0、 0.21.0、 0.22.0 をリリースし、 0.19.0 の7ヶ月後に、 0.23.0 をリリースするとする。 0.23.0 では、 BackendV2 を非推奨とすることができる。非推奨ポリシーが完了するまでは、まだサポートされる必要があり、削除することはできない。

Qiskitのバージョンサポート方針は、プロバイダー自身が同じサポートストーリーを持つことを意味するものではなく、プロバイダーはできる限り早く新しいバージョンにアップデートすることができる(そして間違いなくそうすべきです)。 非推奨化の前にこの長い期間を設けるのは、プロバイダーがバージョンを上げる前に、エンドユーザーに影響を与える可能性のあるインターフェイスの変更を、自ら非推奨化するのに十分な時間を与えるためである。 例えば、 BackendV34 、後方互換性のない方法でシグネチャーを Backend.run() に変更したとしよう。 Aerがその AerSimulator クラスをバージョン34をベースにしたものに更新する前に、古いシグネチャを非推奨にする必要がある。 そのため、バージョン33を削除する(つまりバージョン34を必須/最小バージョンとする)前に、Aerが非推奨サイクルを完了するのに十分な時間を確保する必要があります。


抽象クラス

バックエンド

Backend()すべてのバージョン管理された Backend 抽象クラスの基本共通型。
BackendV2([プロバイダ, 名前, 説明,...] )バックエンドの抽象クラス
QubitProperties( [t1, t2, frequency] )QubitProperties オブジェクトの表現。

オプション

Options(**kwargs)ベース・オプション・オブジェクト

ジョブ

Job()すべてのバージョン管理されたジョブ抽象クラスの基本共通型。
JobV1(backend, job_id, ˶***kwargs)ジョブを処理するクラス

ジョブ ステータス

JobStatus(*値)ジョブ・ステータス列挙型のクラス。

例外

QiskitBackendNotFoundError

exception qiskit.providers.QiskitBackendNotFoundError(*message)

GitHub

ベース: QiskitError

バックエンドを探す際に発生するエラーの基底クラス。

エラーメッセージを設定する。

JobError

exception qiskit.providers.JobError(*message)

GitHub

ベース: QiskitError

ジョブによって発生するエラーの基本クラス。

エラーメッセージを設定する。

JobTimeoutError

exception qiskit.providers.JobTimeoutError(*message)

GitHub

ベース: JobError

ジョブが発生させるタイムアウトエラーの基底クラス。

エラーメッセージを設定する。


新しいバックエンドの記述

Qiskitと統合したい量子デバイスやシミュレータがある場合は、バックエンドを書く必要があります。 プロバイダはバックエンドの集合体であり、利用可能なオブジェクトを取得するメソッドをQiskitに提供する。 BackendV2 オブジェクトを取得するメソッドをQiskitに提供します。 この BackendV2 オブジェクトは、バックエンドを説明する情報とその動作を transpiler バックエンドで実行できるように最適化された回路にコンパイルできるようにするためです。 また run() メソッドも提供している。 QuantumCircuit オブジェクトを実行するメソッドも提供している。 これにより、ユーザーや他のQiskit APIは、バックエンドがどのように実装されているかに関係なく、デバイス上で回路を実行した結果を標準的な方法で取得することができます。 プロバイダーの基本的な書き方は次の通りだ:

  • バックエンドへのアクセスを処理する Provider クラスを実装する。

  • サブクラスと BackendV2 サブクラスとその run() メソッドを実装する。

    • バックエンドの基礎となるカスタムゲートをセッションに追加する。 EquivalenceLibrary インスタンスに追加します。
  • 実行中のジョブとのやりとりを処理する JobV1 実行中のジョブとのやり取りを処理するサブクラスを実装します。

プロバイダの簡単な例については、 qiskit-aqt-provider

プロバイダー

プロバイダ・クラスの目的はただ一つ、デバイスやシミュレータ上で回路を実行するためのバックエンド・オブジェクトを取得することです。 期待されるのは、必要とされるクレデンシャルや認証は、プロバイダ・オブジェクトの初期化で処理されることである。 プロバイダオブジェクトは、バックエンドのリストと、バックエンドをフィルタリングして取得するメソッドを提供します(必要であれば、提供された認証情報を使用します)。 プロバイダー・クラスの例は次のようになる:

from qiskit.providers.providerutils import filter_backends

from .backend import MyBackend

class MyProvider:

    def __init__(self, token=None):
        super().__init__()
        self.token = token
        self.backends = [MyBackend(provider=self)]

    def backends(self, name=None, **kwargs):
        if name:
            backends = [
                backend for backend in backends if backend.name() == name]
        return filter_backends(backends, filters=filters, **kwargs)

(必要な場合)認証に必要な情報がクラス内に含まれていること、およびバックエンドのメソッドが要求されるインターフェースに準拠していることを確認してください。 具体的な実装方法については、各プロバイダーの判断に委ねられます。

バックエンド

バックエンドのクラスはプロバイダーの中核をなすものだ。 これらのクラスは、Qiskitと回路を実行するハードウェアやシミュレータとのインターフェースを提供するものです。 これには、バックエンドを記述するのに必要な情報をコンパイラに提供し、コンパイラがバックエンド用の回路を組み込んで最適化できるようにすることも含まれる。 バックエンドオブジェクトには4つの必須項目がある。 target プロパティ、バックエンドが1つのバッチジョブで実行できる回路数の制限を定義するための max_circuits プロパティ、バックエンドが1つのバッチジョブで実行できる回路数の制限を定義するプロパティ (制限がない場合は None を使用できます)、ジョブの投入を受け付けるメソッド、そして run() メソッド、および _default_options メソッドで、ユーザーが設定可能なオプションとそのデフォルト値を定義します。 例えば、最低限実用的な例としては次のようなものがある:

from qiskit.providers import BackendV2 as Backend
from qiskit.transpiler import Target
from qiskit.providers import Options
from qiskit.circuit import Parameter, Measure
from qiskit.circuit.library import PhaseGate, SXGate, UGate, CXGate, IGate


class Mybackend(Backend):

    def __init__(self):
        super().__init__()

        # Create Target
        self._target = Target("Target for My Backend")
        # Instead of None for this and below instructions you can define
        # a qiskit.transpiler.InstructionProperties object to define properties
        # for an instruction.
        lam = Parameter("λ")
        p_props = {(qubit,): None for qubit in range(5)}
        self._target.add_instruction(PhaseGate(lam), p_props)
        sx_props = {(qubit,): None for qubit in range(5)}
        self._target.add_instruction(SXGate(), sx_props)
        phi = Parameter("φ")
        theta = Parameter("ϴ")
        u_props = {(qubit,): None for qubit in range(5)}
        self._target.add_instruction(UGate(theta, phi, lam), u_props)
        cx_props = {edge: None for edge in [(0, 1), (1, 2), (2, 3), (3, 4)]}
        self._target.add_instruction(CXGate(), cx_props)
        meas_props = {(qubit,): None for qubit in range(5)}
        self._target.add_instruction(Measure(), meas_props)
        id_props = {(qubit,): None for qubit in range(5)}
        self._target.add_instruction(IGate(), id_props)

        # Set option validators
        self.options.set_validator("shots", (1, 4096))
        self.options.set_validator("memory", bool)

    @property
    def target(self):
        return self._target

    @property
    def max_circuits(self):
        return 1024

    @classmethod
    def _default_options(cls):
        return Options(shots=1024, memory=False)

    def run(self, circuits, **kwargs):
        # serialize circuits submit to backend and create a job
        for kwarg in kwargs:
            if not hasattr(self.options, kwarg):
                warnings.warn(
                    "Option %s is not used by this backend" % kwarg,
                    UserWarning, stacklevel=2)
        options = {
            'shots': kwargs.get('shots', self.options.shots),
            'memory': kwargs.get('memory', self.options.memory),
        }
        job_json = convert_to_wire_format(circuit, options)
        job_handle = submit_to_backend(job_json)
        return MyJob(self.job_handle, job_json, circuit)

バックエンドのトランスパイラインターフェース

オブジェクトの重要な部分は Backend オブジェクトの重要な部分は、コンパイラにどのように自分自身を説明するかということである。 これは Target このクラスはトランスパイラのバックエンドのモデルを定義します。 バックエンドオブジェクトは Target オブジェクトを返す必要があります。 target 属性からオブジェクトを返す必要があります。 transpile() オブジェクトを返す必要があります。

カスタムベースゲート

  1. バックエンドがQiskit回路ライブラリ(qiskit.circuit.library)のゲートを使用しない場合は、このサポートをプロバイダに統合することができます。 これを行う基本的な方法は、まず基底セット内の各カスタム・ゲートに対して Gate サブクラスを定義することです。 例:

    import numpy as np
    
    from qiskit.circuit import Gate
    from qiskit.circuit import QuantumCircuit
    
    class SYGate(Gate):
        def __init__(self, label=None):
            super().__init__("sy", 1, [], label=label)
    
        def _define(self):
            qc = QuantumCircuit(1)
            qc.ry(np.pi / 2, 0)
            self.definition = qc

    重要なことは、バックエンドの基本設定にあるカスタム・ゲートのname属性(上記の __init__ 定義の super().__init__() の最初のパラメータ)が、他のゲートの名前と衝突しないようにすることです。 name属性は、トランスパイラの基底セットでゲートを識別するために使用されます。 もし競合があれば、トランスパイラーはどちらのゲートを使うべきかわからなくなる。

  2. カスタムゲートをバックエンドのターゲットに追加します。 これは Target.add_instruction() メソッドで行うことができる。 トランスパイラがその存在を認識できるように、 SYGate のインスタンスとそのパラメータをターゲットに追加する必要がある。 例えば、これがバックエンドの実装の一部だとすると BackendV2 実装の一部だとします:

    from qiskit.transpiler import InstructionProperties
    
    sy_props = {
        (0,): InstructionProperties(duration=2.3e-6, error=0.0002),
        (1,): InstructionProperties(duration=2.1e-6, error=0.0001),
        (2,): InstructionProperties(duration=2.5e-6, error=0.0003),
        (3,): InstructionProperties(duration=2.2e-6, error=0.0004),
    }
    self.target.add_instruction(SYGate(), sy_props)

    sy_props のキーは、バックエンド SYGate が使用できる量子ビットを定義し、値はその量子ビット上の SYGate のプロパティを定義する。 マルチクビット・ゲートの場合、タプル・キーはゲートが動作するすべての量子ビットの組み合わせを含む(順序は重要である。 (0, 1)(1, 0) と異なる。)

  3. バックエンドの基本セットに使用するカスタム・ゲートを定義したら、標準の等価ライブラリに等価ルールを追加する必要がある。 transpile() 関数と transpiler モジュールがカスタム基底セットを使って任意の回路を変換できるようにする必要があります。 これは、標準的なゲートに対して、カスタム・ゲートの観点から等価回路を定義することによって行うことができる。 通常 CXGate (あなたのベースに標準的な2量子ビットゲートが含まれていない場合)また、よく使われる1量子ビットの回転ゲートである HGateUGate などのよく使われる単一量子ビット回転ゲートから変換できれば、トランスパイラがどんな回路もカスタム基底ゲートに変換するのに十分でしょう。 しかし、標準ゲートからあなたの基底への等価ルールがより多く定義されていればいるほど、任意の回路からターゲット基底への翻訳がより効率的になる(ただし、必ずしもそうなるとは限らず、その差は次第に小さくなる)。

    例えば、上記のカスタム SYGate のルールを追加する場合、次のように定義できます。 U2GateHGate:

    from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary
    from qiskit.circuit.library import HGate
    from qiskit.circuit.library import ZGate
    from qiskit.circuit.library import RZGate
    from qiskit.circuit.library import U2Gate
    
    
    # H => Z SY
    q = qiskit.QuantumRegister(1, "q")
    def_sy_h = qiskit.QuantumCircuit(q)
    def_sy_h.append(ZGate(), [q[0]], [])
    def_sy_h.append(SYGate(), [q[0]], [])
    SessionEquivalenceLibrary.add_equivalence(
        HGate(), def_sy_h)
    
    # u2 => Z SY Z
    phi = qiskit.circuit.Parameter('phi')
    lam = qiskit.circuit.Parameter('lambda')
    q = qiskit.QuantumRegister(1, "q")
    def_sy_u2 = qiskit.QuantumCircuit(q)
    def_sy_u2.append(RZGate(lam), [q[0]], [])
    def_sy_u2.append(SYGate(), [q[0]], [])
    def_sy_u2.append(RZGate(phi), [q[0]], [])
    SessionEquivalenceLibrary.add_equivalence(
        U2Gate(phi, lam), def_sy_u2)

    プロバイダーのパッケージがインポートされるとすぐに実行されるように、インポート時に実行されるようにしたい。 これにより BasisTranslator パスがカスタム・ゲートで実行されるたびに、等価ルールが定義される。

    また、使用しているベースによっては、トランスパイラの最適化パス、たとえば Optimize1qGatesDecompositionなどのトランスパイラの最適化パスは、あなたのカスタム・ベースでは動作しないかもしれません。 SYGate の例では Optimize1qGatesDecomposition は単一量子ビットゲートの実行をSY基底に単純化することはできない。 これは、 OneQubitEulerDecomposer のクラスがSYベースで働く方法を知らないからだ。 これを解決するには、 SYGate クラスを Qiskit に追加し、 OneQubitEulerDecomposer を更新して、 SYGate への分解をサポートする必要があります。 長期的には、カスタムベースゲートにとってその方が良い方向性である可能性が高く、トランスパイラでの定義とサポートに貢献することで、Qiskitが今後もしっかりとサポートし続けることができるでしょう。

カスタムトランスパイラパス

トランスパイラーは、ハードウェア固有の最適化や回路変換を容易にするために、バックエンドがカスタムのトランスパイラー・ステージ実装を提供する機能をサポートしている。 現在、 get_translation_stage_plugin()get_scheduling_stage_plugin() の2つのステージがサポートされており、バックエンドはそれぞれデフォルトの翻訳ステージとスケジューリングステージとして使用する文字列プラグイン名を指定することができます。 このような BackendV2 クラスのこれらのフック・ポイントは、バックエンドのコンパイル要件が現在のバックエンド/インターフェイスでは満たされない場合に使うことができます。Target のインターフェイスでは対応できないようなコンパイル要件がある場合に使用します。 また、より多くのハードウェア・アーキテクチャをより深く説明できるように、これらのインターフェースを改善することに関心があるので、あなたの使用例を記述したGithub issueを提出することも検討してください。

これらのフック・ポイントを活用するには、メソッドをあなたの BackendV2 を追加し、文字列のプラグイン名を返すようにすればよい。 例:

class Mybackend(BackendV2):

    def get_scheduling_stage_plugin(self):
        return "SpecialDD"

    def get_translation_stage_plugin(self):
        return "BasisTranslatorWithCustom1qOptimization"

このバックエンド実装のスニペットは、ターゲットが に設定されているときに transpile() 関数は、ターゲットが Mybackend に設定されている場合、デフォルトでスケジューリングステージに SpecialDD プラグインを使い、翻訳ステージに BasisTranslatorWithCustom1qOptimization プラグインを使います。 ユーザーは、別のプラグイン名を明示的に選択することで、これらの選択肢を上書きすることができることに注意してください。 このインターフェイスが機能するためには、返されたプラグイン名に対してトランスパイラ・ステージ・プラグインが実装されていなければならない。 プラグインの実装方法の詳細については qiskit.transpiler.preset_passmanagers.plugin モジュールのドキュメントを参照してください。 バックエンドがコンパイル・ステージの一部としてカスタム・パスを必要とする場合、プロバイダー・パッケージには、それらのパスを使用するトランスパイラー・ステージのプラグインが含まれるというのが一般的な予想です。 しかし、これは必須ではなく、(組み込みメソッドや外部プラグインの)有効なメソッドを使用することができます。

こうすることで、 Mybackend で実行したり、効率的な出力を提供するために、これら2つのコンパイル・ステップが必要になった場合、トランスパイラーは、ユーザーによる手動入力なしに、これらのカスタム・ステップを実行できるようになる。

リアルタイム変数

トランスパイラーは、リアルタイムに型付けされた古典変数を自動的に処理し ( qiskit.circuit.classical参照)を処理し Store 命令を組み込みの「指令」として扱います。 Barrier. これを許可するために、バックエンドが特別な処理をする必要はない。

バックエンドが古典的な変数やストレージを扱えない場合は、ドキュメントでそのことをコメントし、それらを含む回路を熱心に拒否するために、メソッドにチェックを挿入することをお勧めします( Methodを参照)。 run() メソッドにチェックを入れることをお勧めします ( Backend.run メソッドを参照)。 トップレベルで QuantumCircuit.num_vars トップレベルの変数の有無を調べることができる。 コントロール・フロー操作を受け入れる場合、それぞれの内部を再帰的に検索する必要があるかもしれない。 blocks でスコープ・ローカル変数を再帰的に検索する必要があるかもしれない。 QuantumCircuit.num_declared_vars.

例えば、手動で記憶している場所があるかどうかをチェックする機能や、メモリに手動で記憶している場所があるかどうかをチェックする機能などである:

from qiskit.circuit import Store, ControlFlowOp, QuantumCircuit

def has_realtime_logic(circuit: QuantumCircuit) -> bool:
    if circuit.num_vars:
        return True
    for instruction in circuit.data:
        if isinstance(instruction.operation, Store):
            return True
        elif isinstance(instruction.operation, ControlFlowOp):
            for block in instruction.operation.blocks:
                if has_realtime_logic(block):
                    return True
    return False

ゲイツの角度境界

バックエンドがターゲットのどのゲートに対しても許容されるパラメータ値に制約を持っている場合、これを Target. 命令を add_instruction()angle_bounds キーワード引数を使用すると、ゲートのパラメータの上限と下限のタプルのリストを取ることができます。

例えば、上の例で PhaseGate を追加する代わりに

lam = Parameter("λ")
p_props = {(qubit,): None for qubit in range(5)}
self._target.add_instruction(PhaseGate(lam), p_props, angle_bounds=[(0, math.pi)])

PhaseGate の境界を0から π\pi (を含む)の間に設定する。 これは Targetlam パラメータの角度値に関するものである。 PhaseGate. トランス WrapAngles トランスパイラー・パスは PhaseGate を変換します。 ゲートの角度の値を取り込み、その値を返す関数を書く必要がある。 DAGCircuit. 例:

from qiskit.transpiler.passes import WrapAngles

def fold_phase(angles: List[float], qubits: List[int]) -> DAGCircuit:
    angle = angles[0]
    if angle > 0:
        number_of_gates = angle / math.pi
    else:
        number_of_gates = (6.28 - angle) / math.pi
    dag = DAGCircuit()
    dag.add_qubits([Qubit()])
    for _ in range(int(number_of_gates)):
        dag.apply_operation_back(PhaseGate(math.pi), [dag.qubits[0]])
    return dag

WrapAngles.DEFAULT_REGISTRY.add_wrapper("phase", fold_phase)

この関数は、アウトオブバウンズのゲートを、ターゲットの角度境界とターゲットの他の制約を(特にうまくはないが)尊重するものに変換する。

Backend.run 方法

最も重要なのは、回路をデバイスやシミュレータに実際に提出するために使用される手法 run() である。 runメソッドは、実行のためにバックエンドへ回路を送信し、オブジェクト Job を返す処理を担当します。 バックエンドの種類に応じて、これは通常、回路オブジェクトをバックエンドが使用するAPI形式にシリアライズすることを伴います。 バックエンドのシリアライズ要件は異なる可能性があるため(ローカルシミュレータの場合、シリアライズ自体が必要ない場合もある)、この変換処理はバックエンドの run メソッドで処理されることが想定される。

実行メソッドの例は次のようなものだ:

def run(self, circuits, **kwargs):
    for kwarg in kwargs:
        if not hasattr(self.options, kwarg):
            warnings.warn(
                "Option %s is not used by this backend" % kwarg,
                UserWarning, stacklevel=2)
    options = {
        'shots': kwargs.get('shots', self.options.shots),
        'memory': kwargs.get('memory', self.options.memory),
    }
    job_json = convert_to_wire_format(circuit, options)
    job_handle = submit_to_backend(job_json)
    return MyJob(self.job_handle, job_json, circuit)

バックエンドオプション

回路の動作を制御するバックエンドには、多くの場合、いくつかの選択肢があります。 その典型的な例として、回路が何回実行されるかを shots 示す「回数」などが挙げられます。 バックエンドで利用可能なオプションは、オブジェクト Options を使用して定義されます。 このオブジェクトは、バックエンドクラスの _default_options メソッドによって最初に作成されます。 デフォルトのオプションは、バックエンドがサポートするすべてのオプションに対してデフォルト値が設定された初期化済み Options オブジェクトを返します。 たとえば、バックエンドが のみをサポートしている場合 shots 、その _default_options メソッドは次のようになります:

@classmethod
def _default_options(cls):
    return Options(shots=1024)

また Options オブジェクトにバリデータを設定することもできます。 たとえば、上で定義した "shots" オプションに 1 から 4096 までの任意の値を設定できる場合、 バックエンドのオプションオブジェクトにバリデータを設定することができます:

self.options.set_validator("shots", (1, 4096))

検証オプションの全リストは set_validator() ドキュメントを参照してください。

ジョブ

メソッドからの出力は run メソッドからの出力は JobV1 オブジェクトです。 各プロバイダーは、プロバイダーの動作を定義するカスタムジョブサブクラスを実装することが期待される。 ジョブはバックエンドの実行方法によって2種類に分けられる。 デフォルトでは、ジョブは非同期とみなされ、 Backend.run() で提出された回路の非同期実行へのハンドルを表していると期待される。 非同期ジョブオブジェクトは、実行状況を問い合わせたり、実行中のジョブをキャンセルしたり、実行が終了するまでブロックしたりする機能をユーザーに提供します。 を返します。 result は、実行が完了するまでブロックし、ジョブの結果を持つ Result オブジェクトを返します。

一部のバックエンド(主にローカル・シミュレータ)では、回路の実行は同期操作であり、実行中のジョブへのハンドルを他の場所に返す必要はありません。 同期ジョブでは run オブジェクトが生成されるまでバックエンドの Result オブジェクトが生成され、同期ジョブがその内部 Result オブジェクトを返します。

非同期APIベースのバックエンドのジョブクラスの例は以下のようになる:

from qiskit.providers import JobV1 as Job
from qiskit.providers import JobError
from qiskit.providers import JobTimeoutError
from qiskit.providers.jobstatus import JobStatus
from qiskit.result import Result


class MyJob(Job):
    def __init__(self, backend, job_id, job_json, circuits):
        super().__init__(backend, job_id)
        self._backend = backend
        self.job_json = job_json
        self.circuits = circuits

    def _wait_for_result(self, timeout=None, wait=5):
        start_time = time.time()
        result = None
        while True:
            elapsed = time.time() - start_time
            if timeout and elapsed >= timeout:
                raise JobTimeoutError('Timed out waiting for result')
            result = get_job_status(self._job_id)
            if result['status'] == 'complete':
                break
            if result['status'] == 'error':
                raise JobError('Job error')
            time.sleep(wait)
        return result

    def result(self, timeout=None, wait=5):
        result = self._wait_for_result(timeout, wait)
        results = [{'success': True, 'shots': len(result['counts']),
                    'data': result['counts']}]
        return Result.from_dict({
            'results': results,
            'backend_name': self._backend.configuration().backend_name,
            'backend_version': self._backend.configuration().backend_version,
            'job_id': self._job_id,
            'success': True,
        })

    def status(self):
        result = get_job_status(self._job_id)
        if result['status'] == 'running':
            status = JobStatus.RUNNING
        elif result['status'] == 'complete':
            status = JobStatus.DONE
        else:
            status = JobStatus.ERROR
        return status

    def submit(self):
        raise NotImplementedError

そして同期の仕事だ:

class MySyncJob(Job):
    _async = False

    def __init__(self, backend, job_id, result):
        super().__init__(backend, job_id)
        self._result = result

    def submit(self):
        return

    def result(self):
        return self._result

    def status(self):
        return JobStatus.DONE

プリミティブ

プロバイダー・インターフェースの直接の一部ではないが、モジュールはプロバイダーと緊密に結合している。 qiskit.primitives モジュールはプロバイダと緊密に結合している。 具体的には、 BaseSamplerBaseEstimator のようなプリミティブなインターフェイスは、プロバイダの実装が、プロバイダのバックエンドに最適化されたカスタム実装を提供できるように設計されている。 これには、回路変換、追加の前後処理、バッチ処理、キャッシング、エラー緩和などのカスタマイズが含まれる。 モジュールのコンセプトは qiskit.primitives プリミティブオブジェクトは、処理されたより高いレベルの出力(確率分布や期待値など)を生成するためのより高いレベルの抽象化であり、効率的に最良の結果を得るための仕組みを抽象化し、これらの出力を使用したより高いレベルのアプリケーションに集中するためである。

例えば、バックエンドが mthreeの測定緩和を活用して結果の質を向上させるのに適している場合、 M3Mitigation クラスを内部的に活用して回路を実行し、mthreeから直接準確率を結果に返すプロバイダ固有の Sampler 実装を実装することができる。 こうすることで、バックエンドから直接適用される軽減措置によって、アルゴリズムが最良の結果を得ることができる。 カスタム実装の書き方については qiskit.primitives のドキュメントを参照されたい。 また、組み込みの実装もある: Sampler Estimator, BackendSampler, BackendEstimator も、これらの実装方法のリファレンス/モデルとして役立つ。

このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。