Source code for mimiqcircuits.decomposition.basis.flattened

#
# Copyright © 2022-2024 University of Strasbourg. All Rights Reserved.
# Copyright © 2023-2025 QPerfect. All Rights Reserved.
#
# 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.
#
"""Flattened decomposition basis."""

from __future__ import annotations

from typing import TYPE_CHECKING, Sequence

from mimiqcircuits.decomposition.abstract import DecompositionBasis, DecompositionError

if TYPE_CHECKING:
    from mimiqcircuits import Circuit, Operation


# Terminality per operation type, for the types where the type alone decides
# it. Filled on first use and shared by all instances.
_TERMINAL_BY_TYPE: dict[type, bool] = {}


[docs] class FlattenedBasis(DecompositionBasis): """Flatten container operations while leaving all other operations untouched."""
[docs] def isterminal(self, op: Operation) -> bool: """Containers are non-terminal; all other operations are terminal.""" t = type(op) known = _TERMINAL_BY_TYPE.get(t) if known is not None: return known import mimiqcircuits as mc # An inverse is decided by what it wraps, so it is never cached. if isinstance(op, mc.Inverse): return not isinstance(op.op, (mc.GateCall, mc.Block)) # A conditional container is flattened into conditional instructions; # it is decided by its body, so it is never cached either. if isinstance(op, mc.IfStatement): return self.isterminal(op.get_operation()) known = not isinstance(op, (mc.GateCall, mc.Block)) _TERMINAL_BY_TYPE[t] = known return known
[docs] def decompose( self, op: Operation, qubits: Sequence[int], bits: Sequence[int], zvars: Sequence[int], ) -> Circuit: """Decompose one container expansion step using FlattenContainers.""" import mimiqcircuits as mc from mimiqcircuits.decomposition.rules import FlattenContainers from mimiqcircuits.operations.ifstatement import _decompose_ifstatement if isinstance(op, mc.IfStatement): return _decompose_ifstatement(self, op, qubits, bits, zvars) rule = FlattenContainers() if rule.matches(op): return rule.decompose_step(op, qubits, bits, zvars) raise DecompositionError( f"Operation {op.name} matches FlattenedBasis but cannot be decomposed." )
__all__ = ["FlattenedBasis"]