Source code for bqskit.passes.util.conversion

"""This module implements the BlockConversionPass."""
from __future__ import annotations

import logging

from bqskit.compiler.basepass import BasePass
from bqskit.compiler.passdata import PassData
from bqskit.ir.circuit import Circuit
from bqskit.ir.gates.circuitgate import CircuitGate
from bqskit.ir.gates.constant.unitary import ConstantUnitaryGate
from bqskit.ir.gates.parameterized.unitary import VariableUnitaryGate
from bqskit.ir.point import CircuitPoint

_logger = logging.getLogger(__name__)


[docs] class BlockConversionPass(BasePass): """ Converts blocks of one type to another type. Blocks are either described by a constant or variable unitary gate or as a circuit gate. Often during the flow of compilatin we will need to convert them from one form to another for a future pass. """
[docs] def __init__( self, convert_target: str, convert_variable: bool = True, convert_constant: bool = True, convert_circuitgates: bool = True, ): """ Construct a BlockConversionPass. Args: convert_target (str): Either `variable` or `constant`. Blocks will be converted to the form described here. If this is `variable` all gates will be converted to `VariableUnitaryGate` s. If this is `constant` blocks will be converted to `ConstantUnitaryGate` s. Blocks cannot be converted to circuit gates, that can be caried out by synthesis. convert_variable (bool): If this is true, this will replace VariableUnitaryGate's in the circuit with one's specified in convert_target. convert_constant (bool): If this is true, this will replace ConstantUnitaryGate's in the circuit with one's specified in convert_target. convert_circuitgates (bool): If this is true, this will replace CircuitGate's in the circuit with one's specified in convert_target. The subcircuit information captured in the circuit gate will be lost. """ self.convert_variable = convert_variable self.convert_constant = convert_constant self.convert_circuitgates = convert_circuitgates if convert_target == 'variable': self.convert_target = 'variable' self.convert_variable = False elif convert_target == 'constant': self.convert_target = 'constant' self.convert_constant = False else: raise ValueError('Unexpected input for conversion target.')
[docs] async def run(self, circuit: Circuit, data: PassData) -> None: """Perform the pass's operation, see :class:`BasePass` for more.""" # Variable -> Constant if self.convert_variable and self.convert_target == 'constant': _logger.debug('Converting variable gates to constant gates.') for cycle, op in circuit.operations_with_cycles(): if isinstance(op.gate, VariableUnitaryGate): cgate = ConstantUnitaryGate(op.get_unitary(), op.radixes) point = CircuitPoint(cycle, op.location[0]) circuit.replace_gate(point, cgate, op.location) # CircuitGates -> Constant if self.convert_circuitgates and self.convert_target == 'constant': _logger.debug('Converting circuit gates to constant gates.') for cycle, op in circuit.operations_with_cycles(): if isinstance(op.gate, CircuitGate): cgate = ConstantUnitaryGate(op.get_unitary(), op.radixes) point = CircuitPoint(cycle, op.location[0]) circuit.replace_gate(point, cgate, op.location) # Constant -> Variable if self.convert_constant and self.convert_target == 'variable': _logger.debug('Converting constant gates to variable gates.') for cycle, op in circuit.operations_with_cycles(): if isinstance(op.gate, ConstantUnitaryGate): params = VariableUnitaryGate.get_params(op.get_unitary()) vgate = VariableUnitaryGate(op.num_qudits, op.radixes) point = CircuitPoint(cycle, op.location[0]) circuit.replace_gate(point, vgate, op.location, params) # CircuitGates -> Variable if self.convert_constant and self.convert_target == 'variable': _logger.debug('Converting circuit gates to variable gates.') for cycle, op in circuit.operations_with_cycles(): if isinstance(op.gate, CircuitGate): params = VariableUnitaryGate.get_params(op.get_unitary()) vgate = VariableUnitaryGate(op.num_qudits, op.radixes) point = CircuitPoint(cycle, op.location[0]) circuit.replace_gate(point, vgate, op.location, params)