跳转至

QCDA

QuICT.qcda.QCDA

QCDA(process: List = None)

Bases: object

Customize the process of synthesis, optimization and mapping

In this class, we meant to provide the users with a direct path to design the process by which they could transform a unitary matrix to a quantum circuit and/or optimize a quantum circuit.

Initialize a QCDA process

A QCDA process is defined by a list of synthesis, optimization and mapping. Experienced users could customize the process for certain purposes.

Parameters:

  • process (list, default: None ) –

    A customized list of Synthesis, Optimization and Mapping

Source code in QuICT/qcda/qcda.py
def __init__(self, process: List = None):
    """Initialize a QCDA process

    A QCDA process is defined by a list of synthesis, optimization and mapping.
    Experienced users could customize the process for certain purposes.

    Args:
        process (list, optional): A customized list of Synthesis, Optimization and Mapping
    """
    self.process = []
    if process is not None:
        self.process = process

add_default_optimization

add_default_optimization(level: str = 'light', keep_phase: bool = False)

Generate the default optimization process

The default optimization process contains the CommutativeOptimization.

Parameters:

  • level (str, default: 'light' ) –

    Optimizing level. Support light, heavy level.

  • keep_phase (bool, default: False ) –

    whether to keep the global phase as a GPhase gate in the output

Source code in QuICT/qcda/qcda.py
def add_default_optimization(self, level: str = "light", keep_phase: bool = False):
    """Generate the default optimization process

    The default optimization process contains the CommutativeOptimization.

    Args:
        level (str, optional): Optimizing level. Support `light`, `heavy` level.
        keep_phase (bool, optional): whether to keep the global phase as a GPhase gate in the output
    """

    self.add_method(CommutativeOptimization(keep_phase=keep_phase))
    self.add_method(CliffordRzOptimization(level=level, keep_phase=keep_phase))

add_gate_transform

add_gate_transform(target_instruction: InstructionSet = None, keep_phase: bool = False)

Add GateTransform for some target InstructionSet

GateTransform would transform the gates in the original Circuit/CompositeGate to a certain InstructionSet.

Parameters:

  • target_instruction (InstructionSet, default: None ) –

    The target InstructionSet

  • keep_phase (bool, default: False ) –

    whether to keep the global phase as a GPhase gate in the output

Source code in QuICT/qcda/qcda.py
def add_gate_transform(self, target_instruction: InstructionSet = None, keep_phase: bool = False):
    """Add GateTransform for some target InstructionSet

    GateTransform would transform the gates in the original Circuit/CompositeGate to a certain InstructionSet.

    Args:
        target_instruction (InstructionSet): The target InstructionSet
        keep_phase (bool): whether to keep the global phase as a GPhase gate in the output
    """
    assert target_instruction is not None, ValueError("No InstructionSet provided for Synthesis")
    self.add_method(GateTransform(target_instruction, keep_phase=keep_phase))

add_mapping

add_mapping(layout: Layout = None, method: str = 'sabre')

Generate the default mapping process

The default mapping process contains the Mapping

Parameters:

  • layout (Layout, default: None ) –

    Topology of the target physical device

  • method (str, default: 'sabre' ) –

    used mapping method in ['sabre', 'vf2']

Source code in QuICT/qcda/qcda.py
def add_mapping(self, layout: Layout = None, method: str = "sabre"):
    """Generate the default mapping process

    The default mapping process contains the Mapping

    Args:
        layout (Layout): Topology of the target physical device
        method (str, optional): used mapping method in ['sabre', 'vf2']
    """
    assert layout is not None, ValueError("No Layout provided for Mapping")
    assert method in ["sabre", "vf2"], ValueError("Invalid mapping method")
    mapping_dict = {
        "sabre": SABREMapping(layout),
        "vf2": VF2Mapping(layout),
    }
    self.add_method(mapping_dict[method])

add_method

add_method(method=None)

Adding a specific method to the process

Parameters:

  • method

    Some QCDA method

Source code in QuICT/qcda/qcda.py
def add_method(self, method=None):
    """Adding a specific method to the process

    Args:
        method: Some QCDA method
    """
    self.process.append(method)

auto_compile

auto_compile(circuit: Circuit, quantum_machine_info: VirtualQuantumMachine, keep_phase=False) -> Tuple[Circuit, List[int], List[int]]

Auto-Compile the circuit with the given quantum machine info. Normally follow the steps:

  1. Optimization
  2. Mapping
  3. Local KAK Decomposition
  4. Gate Transform
  5. Optimization

Parameters:

  • circuit (CompositeGate / Circuit) –

    the target CompositeGate or Circuit

  • quantum_machine_info (VirtualQuantumMachine) –

    the information about target quantum machine.

  • keep_phase (bool, default: False ) –

    whether to keep the global phase as a GPhase gate in the output

Return

compiled_circuit (CompositeGate/Circuit): The compiled CompositeGate or Circuit. logic2phy (List[int]): The mapping of logical qubits to physical qubits. phy2logic (List[int]): The mapping of physical qubits to logical qubits at the end of circuit.

Source code in QuICT/qcda/qcda.py
def auto_compile(
    self, circuit: Circuit, quantum_machine_info: VirtualQuantumMachine, keep_phase=False
) -> Tuple[Circuit, List[int], List[int]]:
    """Auto-Compile the circuit with the given quantum machine info. Normally follow the steps:

    1. Optimization
    2. Mapping
    3. Local KAK Decomposition
    4. Gate Transform
    5. Optimization

    Args:
        circuit (CompositeGate/Circuit): the target CompositeGate or Circuit
        quantum_machine_info (VirtualQuantumMachine): the information about target quantum machine.
        keep_phase (bool): whether to keep the global phase as a GPhase gate in the output

    Return:
        compiled_circuit (CompositeGate/Circuit): The compiled CompositeGate or Circuit.
        logic2phy (List[int]): The mapping of logical qubits to physical qubits.
        phy2logic (List[int]): The mapping of physical qubits to logical qubits at the end of circuit.
    """
    qm_iset = quantum_machine_info.instruction_set
    qm_layout = quantum_machine_info.layout
    qm_process = []
    # Step 1: optimization algorithm for common circuit
    circuit.decomposition()
    circuit.flatten()
    if circuit.count_gate_by_gatetype(GateType.cx) == circuit.size():
        qm_process.append(CnotWithoutAncilla())
    else:
        gate_types = circuit.get_all_gatetype()
        qm_process.append(self._choice_opt_algorithm(gate_types))

    # Step 2: Mapping if layout is not all-connected
    if qm_layout is not None:
        mapping = SABREMapping(qm_layout, initial_iterations=10, swap_iterations=10)
        qm_process.append(mapping)

    if qm_iset is not None:
        # Step 3: Local KAK Decomposition
        if qm_iset.two_qubit_gate in [GateType.rxx, GateType.ryy, GateType.rzz]:
            qm_process.append(LocalKAKDecomposition(target="rot", keep_phase=keep_phase))
        else:
            qm_process.append(LocalKAKDecomposition(target="cx", keep_phase=keep_phase))

        # Step 4: Gate Transform by the given instruction set
        qm_process.append(GateTransform(qm_iset, keep_phase=keep_phase))

    # Step 5: Start the auto QCDA process:
    logger.info("QCDA Now processing GateDecomposition.")
    for process in qm_process:
        logger.info(f"QCDA Now processing {process.__class__.__name__}.")
        circuit = process.execute(circuit)

    # Step 6: Depending on the special instruction set gate, choice best optimization algorithm.
    if qm_iset is not None or qm_layout is not None:
        post_opt_process = self._choice_opt_algorithm(circuit.get_all_gatetype(), keep_phase=keep_phase)
        logger.info(f"QCDA Now processing {post_opt_process.__class__.__name__}.")
        circuit = post_opt_process.execute(circuit)

    logic2phy = mapping.logic2phy if qm_layout is not None else None
    phy2logic = mapping.phy2logic if qm_layout is not None else None

    return circuit, logic2phy, phy2logic

compile

compile(circuit: Union[Circuit, CompositeGate]) -> Union[Circuit, CompositeGate]

Compile the circuit with the given process

Parameters:

Returns:

  • Union[Circuit, CompositeGate]

    Union[Circuit, CompositeGate]: the resulting CompositeGate or Circuit

Source code in QuICT/qcda/qcda.py
def compile(self, circuit: Union[Circuit, CompositeGate]) -> Union[Circuit, CompositeGate]:
    """Compile the circuit with the given process

    Args:
        circuit (Union[Circuit, CompositeGate]): the target CompositeGate or Circuit

    Returns:
        Union[Circuit, CompositeGate]: the resulting CompositeGate or Circuit
    """
    logger.info("QCDA Now processing GateDecomposition.")
    circuit.decomposition()
    circuit.flatten()
    for process in self.process:
        logger.info(f"QCDA Now processing {process.__class__.__name__}.")
        circuit = process.execute(circuit)

    return circuit