Skip to main content
IBM Quantum Platform

回路注釈

qiskit.circuit.annotation

このモジュールには、カスタム回路アノテーションを扱うためのインフラが含まれています。

ユーザー向けのメイン・クラスはベース・クラス qiskit.circuit.Annotationで、これもこのモジュールから再エクスポートされます。


カスタム注釈サブクラス

この Annotation クラスはサブクラス化されることを意図している。 サブクラスは namespace フィールドを設定しなければならない。 これはインスタンス固有のものでも、サブクラス全体の静的なものでもよい。 名前空間は、「 Namespacing 」で説明されているように、ディスパッチ・メカニズムの一部として使用される。

回路の等価検査は、順序に依存した方法でオブジェクトのアノテーションも比較する。 どのサブクラスでも __eq__() magic メソッドを実装したいことでしょう。

アノテーションを QPY または:ref: ` OpenQASM 3 <qiskit-qasm3> ■でシリアライズできるようにする場合は、 シリアライズとデシリアライズの項 で説明したように、シリアライズとデシリアライズのメソッドを別々に実装する必要があります。

名前空間

アノテーションの "namespace "は、コンシューマがどのハンドラを呼び出すかを決定する際のルックアップ・キーとして使用される。 これにはQPYや OpenQASM 3シリアライゼーションのコンテキストも含まれますが、一般的にトランスパイラ・パスはアノテーションの名前空間も見て、関連性があるかどうかなどを判断します。

これは、標準的な Python 識別子(例: my_namespace)である可能性があります または、ドットで区切られた識別子のリスト(例: my_namespace.subnamespace)。 この名前空間は、アノテーションを利用するすべてのコンポーネントが、どのハンドラを呼び出すべきかを判断するために使用されます。

スタンドアロン関数により、名前空間と親名前空間を、最も特定的なものから最も特定的でないものへと優先順位をつけて反復処理することができる。

iter_namespaces

qiskit.circuit.annotation.iter_namespaces(namespace)

GitHub

指定した名前空間を検索するために使用できる、すべての名前空間に対するイテレータ。

これには名前空間と、ルートの空文字列名前空間を含むすべての親が含まれる。

例:

from qiskit.circuit.annotation import iter_namespaces
assert list(iter_namespaces("hello.world")) == ["hello.world", "hello", ""]

パラメーター

namespace (str)

戻りの型

Iterator [ str ]

シリアライゼーションおよびデシリアライゼーション

アノテーションは完全にカスタム化されたデータを表し、コンパイル後も持続する可能性がある。 これには、バックエンド・コンパイラによって解釈される追加データなど、後で消費するためにシリアライズされるべきデータが含まれることがある。 QiskitのネイティブバイナリQPYフォーマット( qiskit.qpy参照)は、バージョン15以降、ペイロード内の任意の注釈の概念をサポートしています。 OpenQASM 3 ( qiskit.qasm3)では、アノテーションはコア言語機能であり、Qiskitの OpenQASM 3に対するインポート/エクスポートサポートにはアノテーションのシリアライズが含まれています。

しかし、アノテーションは一般的にカスタムサブクラスであり、Qiskitにとっては未知のものであるため、シリアライゼーションをビルトインでサポートすることはできません。 デシリアライズの面では、一般的にQiskitは既存の Annotation オブジェクトからデシリアライズメソッドを呼び出すことはできません。 また、アノテーションは、与えられた回路コンテキスト内のQiskitに未知の共有状態に関連する可能性があることも予想される。

これらの理由から、アノテーションのシリアライズとデシリアライズはカスタムオブジェクトによって処理され、関連するシリアライズ関数のインターフェイスポイントで渡されなければならない。 例えばQPYでは、 annotation_factories の引数は qpy.dump()qpy.load() はシリアライザを渡すために使われます。

QPYシリアライザ

class qiskit.circuit.annotation.QPYSerializer

GitHub

ベース: ABC

オブジェクトのシリアライザおよびデシリアライザのためのインタフェース。 Annotation オブジェクトのためのインタフェースです。

QPYの詳細については、以下を参照のこと。 qiskit.qpy.

このインターフェイス定義クラスはサブクラス化されるように設計されている。 個々のメソッドには、その契約と、どのように呼び出されるかが記述されている。

QPY のシリアル化とデシリアライズの間に、QPY のメイン・ロジックはファクトリ関数を呼び出して、このクラスのサブクラスのインスタンスを作成します。 指定されたファクトリー関数の戻り値は、シリアライズまたはデシリアライズのどちらかのコンテキストで使用されますが、両方では使用されません。

1つの回路を直列化する際の呼び出しの構造は以下の通りである:

  1. dump_annotation()を何度も呼び出すことになるが、それらはすべて同じ namespace 引数を共有することになる。 Annotation オブジェクトの接頭辞になります。
  2. dump_state()

QPYペイロードから1つの回路をデシリアライズする際の呼び出しの一般的な構造は、以下のとおりである:

  1. load_state() namespace (「シリアライジング」形式と同じ、厳密でない接頭辞の動作)を渡す。
  2. その名前空間接頭辞ルックアップの下で直列化された注釈に対応する、 load_annotation() への多数の呼び出し。

これをサブクラス化する場合は、QPYが厳格な後方互換性の保証を意図していることを思い出してください。 特に、自明でないシリアライザは、そのシリアライザ全体の「状態」に「バージョン」情報を含むことが提案されています( dump_state() 参照)。また、デシリアライゼーションは、同じシリアライザの以前のバージョンとの後方互換性をサポートするためにあらゆる努力を払うべきです。

QPYFromOpenQASM3Serializer

class qiskit.circuit.annotation.QPYFromOpenQASM3Serializer(inner)

GitHub

ベース: QPYSerializer

を変換するアダプター。 OpenQASM3SerializerQPYSerializer.

これは、 OpenQASM 3注釈シリアライザーがステートレスで、 UTF-8-encoded 単一行のテキストを返すことを要求されているためです。

一般的には、 OpenQASM 3 アノテーション・シリアライザーの as_qpy() メソッドを使って作成します。

例:

このクラスのインスタンスは、引数ゼロの関数のように呼び出すことができ、自分自身を返す。 これにより、QPYのエントリーポイントへのファクトリー関数として直接使用することができる:

import io
from qiskit.circuit import OpenQASM3Serializer, Annotation
from qiskit import qpy

class MyAnnotation(Annotation):
    namespace = "my_namespace"

class MySerializer(OpenQASM3Serializer):
    def dump(self, annotation):
        if not isinstance(annotation, MyAnnotation):
            return NotImplemented
        return ""

    def load(self, namespace, payload):
        assert namespace == "my_namespace"
        assert payload == ""
        return MyAnnotation()

qc = QuantumCircuit(2)
with qc.box(annotations=[MyAnnotation()]):
    qc.cx(0, 1)

with io.BytesIO() as fptr:
    qpy.dump(fptr, qc, annotation_serializers = {"my_namespace": MySerializer().as_qpy()})

ベースとなる OpenQASM 3シリアライザーは必然的にステートレスであるため、個別のインスタンスを返すことなく、これは安全である。

パラメーター

inner (OpenQASM3Serializer) – OpenQASM 3 のシリアライザから派生したものです。

OpenQASM3Serializer

class qiskit.circuit.annotation.OpenQASM3Serializer

GitHub

ベース: ABC

オブジェクトのシリアライザーとデシリアライザーのインターフェイス。 Annotation オブジェクトを OpenQASM 3.

Qiskit の OpenQASM 3 サポートの詳細については、以下を参照してください。 qiskit.qasm3.

このインターフェイス定義クラスはサブクラス化されるように設計されている。 OpenQASM 3 アノテーションはプログラム内でステートレスであるため、サブクラスはステートを追跡してはならない。


ブロックコレクショントランスパイラパス

アノテーション・フレームワークの主な目標は、カスタム解析とコマンドを命令ローカルな方法で回路上に保存できるようにすることである。

例えば、単一量子ビット演算の実行を収集する単純なトランスパイラ・パスを書くことができます。 BoxOpそして、ユニタリーアクションの合計を計算し、カスタムアノテーションとして添付することで、各ブロックの内部が最適化されても、同じ解析を後で繰り返す必要がなくなります。

from qiskit.circuit import annotation, QuantumCircuit, BoxOp
from qiskit.quantum_info import Operator
from qiskit.transpiler import TransformationPass

class PerformsUnitary(annotation.Annotation):
    namespace = "unitary"
    def __init__(self, matrix):
        self.matrix = matrix

class Collect1qRuns(TransformationPass):
    def run(self, dag):
        for run in dag.collect_1q_runs():
            block = QuantumCircuit(1)
            for node in run:
                block.append(node.op, [0], [])
            box = BoxOp(block, annotations=[PerformsUnitary(Operator(block).data)])
            dag.replace_block_with_op(run, box, {run[0].qargs[0]: 0})
        return dag

アノテーションを OpenQASM 3にシリアライズするには、カスタムロジックを定義しなければならない。 シリアライゼーションはアノテーションとは別個のものであり、シリアライゼーションを別の方法で行うべき状況があるかもしれない。

import ast
import numpy as np

class Serializer(annotation.OpenQASM3Serializer):
    def dump(self, annotation):
        if annotation.namespace != "unitary":
            return NotImplemented
        line = lambda row: "[" + ", ".join(repr(x) for x in row) + "]"
        return "[" + ", ".join(line(row) for row in annotation.matrix.tolist()) + "]"

    def load(self, namespace, payload):
        if namespace != "unitary":
            return NotImplemented
        return PerformsUnitary(np.array(ast.literal_eval(payload), dtype=complex))

最後に、この出力をまとめて、 OpenQASM 3。

from qiskit import qasm3

qc = QuantumCircuit(3)
qc.s(0)
qc.t(0)
qc.y(1)
qc.x(1)
qc.h(2)
qc.s(2)
collected = Collect1qRuns()(qc)

handlers = {"unitary": Serializer()}
dumped = qasm3.dumps(collected, annotation_handlers=handlers)
print(dumped)
OPENQASM 3.0;
include "stdgates.inc";
qubit[3] q;
@unitary[[(1+0j), 0j], [0j, (-0.7071067811865475+0.7071067811865475j)]]
box {
  s q[0];
  t q[0];
}
@unitary[[1j, 0j], [0j, -1j]]
box {
  y q[1];
  x q[1];
}
@unitary[[(0.7071067811865475+0j), (0.7071067811865475+0j)], [0.7071067811865475j, -0.7071067811865475j]]
box {
  h q[2];
  s q[2];
}
このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。