Source code for blueqat.circuit_funcs.flatten

# Copyright 2019-2026 The Blueqat Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module provides a feature to flatten circuit operations by expanding multi-targets."""

import typing
from typing import Any, List

from .. import Circuit
from .. import gate as g


[docs] def flatten(c: Circuit) -> Circuit: """Expands slice and multiple targets into single target operations. This function normalizes the circuit so that each gate or measurement operation applies to explicit, un-sliced single qubits (or single pairs for two-qubit gates). Args: c (Circuit): The quantum circuit to flatten. Returns: Circuit: A new flattened Circuit object. Raises: ValueError: If an unexpected or unprocessable operation type is encountered. """ n_qubits = c.n_qubits ops: List[g.Operation] = [] for op in c.ops: if isinstance(op, g.GateBlock): # 名前付きブロックは中身に展開する (フラット化で構造は失われる。 # JSONシリアライズ等のフラットなスキーマ向け)。 inner = flatten(Circuit(n_qubits, list(op.ops))) ops.extend(inner.ops) elif isinstance(op, (g.OneQubitGate, g.Reset)): ops.extend([ op.create(t, op.params, None) for t in op.target_iter(n_qubits) ]) elif isinstance(op, g.TwoQubitGate): ops.extend([ op.create(t, op.params, None) for t in op.control_target_iter(n_qubits) ]) elif isinstance(op, g.Measurement): if op.key is None: ops.extend([ op.create(t, op.params, None) for t in op.target_iter(n_qubits) ]) else: options: typing.Dict[str, Any] = {'key': op.key} if op.duplicated is not None: options['duplicated'] = op.duplicated ops.append( op.create( tuple(t for t in op.target_iter(n_qubits)), op.params, options ) ) elif isinstance(op, g.Barrier): # スライス指定を明示的な量子ビット列に展開して1つのbarrierとして保持 ops.append(op.create(tuple(op.target_iter(n_qubits)), op.params, None)) elif isinstance(op, g.Gate): # 3量子ビット以上のゲート (ccx/ccz/cswap 等)。これらの targets は # スライス不可の明示的なタプルなので、そのまま新しい回路へ移せばよい。 ops.append(op.create(tuple(op.targets), op.params, None)) else: raise ValueError(f"Cannot process operation {op.lowername}.") return Circuit(n_qubits, ops)