\begin{align*}
\ket{0}^{\otimes n} = \overbrace{\ket{0} \otimes \cdots \otimes \ket{0}}^{n}
\end{align*}
ということに注意して読み進めていきたい。
p.106 から量子テレポーテーション。概要がざっくりしていてイメージしにくい。ニールセン&チャン I p.37 にもう少し長めのストーリーがある。しかし、“ERP 対のうちの 1 つの量子ビットを持って別れる” とはどういう感じなのだろう? p.36 によると ERP 対とは Bell 状態、特に Qiskit 本の p.106 の回路で言えば $\frac{1}{\sqrt{2}}(\ket{00} + \ket{11})$ だが、持って別れることでデコヒーレンスを起こさないのか?とか、そもそもこの 1 つの量子ビットとは何か?とか、ストーリーに言う “昔” だとコヒーレンス時間を超えているのではないだろうか・・・とか色々ありそうだが、たぶんそういうことは気にしてはならないのだろう。与えられた回路のような状況下で、古典情報を得ることで、状態ベクトルを復元できますよということを強引にストーリー化しているだけなのだろう・・・。
あえて書くと、並行世界が沢山 (例えば 1024 個) あって、宇宙 1 の Bob と Alice が EPR 対を分け合って、宇宙 2 の Bob と Alice が EPR 対を分け合って・・・としている状態で、それらすべての宇宙の Alice 達が自分の宇宙の Bob 達に測定結果を伝えて、Bob 達の側でも観測して、全宇宙の Bob 達が結果を持ち合うと q_0 が何だったか分かります、という話だと思う。
コード中の c_if
が少しひっかかるが、qiskit.circuit.Instruction.c_if — Qiskit 0.34.1 documentation とそこからリンクされているソースコードを見ても、本質的には
def c_if(self, classical, val): self.condition = (classical, val) return self
なので、これがいつ効いてくるんだろうなぁ〜という感想。qiskit.circuit.QuantumCircuit.x — Qiskit 0.34.1 documentation で X ゲートの作用を見ると、XGate — Qiskit 0.34.1 documentation を作成して qiskit.circuit.QuantumCircuit
に append
する実装になっている:
def append( self, instruction: Instruction, qargs: Optional[Sequence[QubitSpecifier]] = None, cargs: Optional[Sequence[ClbitSpecifier]] = None, ) -> InstructionSet: ... instructions = InstructionSet(resource_requester=requester) for qarg, carg in instruction.broadcast_arguments(expanded_qargs, expanded_cargs): instructions.add(appender(instruction, qarg, carg), qarg, carg) return instructions
ここで appender
が例えば self._append
が実体だったりして、それが QuantumCircuit._data
なるリストにインストラクションを追加する形になっている。そういう処理を済ませた上で、InstructionSet
を返すのが上記の append
の仕事ということになる。
ということで、
qc.x(2).c_if(crx, 1)
は、QuantumCircuit 内の q_2 に X ゲートを作用して得た InstructionSet
の c_if
を呼び出していて、これはセット内のすべてのゲートの c_if
を呼ぶので、Instruction <|--- Gate <|--- XGate
という継承関係を踏まえると、冒頭の qiskit.circuit.Instruction.c_if — Qiskit 0.34.1 documentation が呼ばれることになる。が、結局イマイチよく分からないな、という結論のままである。