跳转至

CircuitBased

QuICT.core.utils.CircuitBased

CircuitBased(name: str, qubits: int = 0, precision: str = 'double')

Bases: object

Based Class for Circuit and Composite Gate.

Parameters:

  • name (str) –

    The name of current Quantum Circuit

Source code in QuICT/core/utils/circuit_based.py
def __init__(self, name: str, qubits: int = 0, precision: str = "double"):
    """
    Args:
        name (str): The name of current Quantum Circuit
    """
    self.name = name
    self.precision = precision

    self._gates = CircuitGates()    # List[Union[BasicGate, CompositeGate]]
    self._qubits = qubits
    self._pointer = None

fast_gates property

fast_gates

Return the list of tuple(gate, qubit_indexes, size) in the current circuit.

gates property

gates

Return the list of BasicGate/CompositeGate/Operator in the current circuit.

Warning: this is slowly due to the copy of gates, you can use self.fast_gates to get list of tuple(gate, qubit_indexes, size) for further using.

assigned_value

assigned_value()

Whether all symbols in the Circuit/CompositeGate are assigned values.

Returns:

  • bool

    If True, all symbols in the Circuit/CompositeGate are assigned values.

Source code in QuICT/core/utils/circuit_based.py
def assigned_value(self):
    """ Whether all symbols in the Circuit/CompositeGate are assigned values.

    Returns:
        bool: If True, all symbols in the Circuit/CompositeGate are assigned values.
    """
    for gate in self.fast_gates:
        if not gate.assigned_value:
            return False
    return True

count_1qubit_gate

count_1qubit_gate() -> int

The number of the one qubit gates in the Circuit/CompositeGate

Returns:

  • int ( int ) –

    the number of the one qubit gates

Source code in QuICT/core/utils/circuit_based.py
def count_1qubit_gate(self) -> int:
    """ The number of the one qubit gates in the Circuit/CompositeGate

    Returns:
        int: the number of the one qubit gates
    """
    return self._gates.siq_gates_count

count_2qubit_gate

count_2qubit_gate() -> int

The number of the two qubit gates in the Circuit/CompositeGate

Returns:

  • int ( int ) –

    the number of the two qubit gates

Source code in QuICT/core/utils/circuit_based.py
def count_2qubit_gate(self) -> int:
    """ The number of the two qubit gates in the Circuit/CompositeGate

    Returns:
        int: the number of the two qubit gates
    """
    return self._gates.biq_gates_count

count_gate_by_gatetype

count_gate_by_gatetype(gate_type: GateType) -> int

The number of the target Quantum Gate in the Circuit/CompositeGate

Parameters:

  • gateType(GateType)

    the type of gates to be count

Returns:

  • int ( int ) –

    the number of the gates

Source code in QuICT/core/utils/circuit_based.py
def count_gate_by_gatetype(self, gate_type: GateType) -> int:
    """ The number of the target Quantum Gate in the Circuit/CompositeGate

    Args:
        gateType(GateType): the type of gates to be count

    Returns:
        int: the number of the gates
    """
    return self._gates.gates_count_by_type(gate_type)

count_training_gate

count_training_gate()

The number of the trainable gates in the Circuit/CompositeGate

Returns:

  • int

    the number of the trainable gates

Source code in QuICT/core/utils/circuit_based.py
def count_training_gate(self):
    """ The number of the trainable gates in the Circuit/CompositeGate

    Returns:
        int: the number of the trainable gates
    """
    return self._gates.training_gates_count

count_variables

count_variables()

The number of the variables in the Circuit/CompositeGate.

Returns:

  • int

    The number of variables.

Source code in QuICT/core/utils/circuit_based.py
def count_variables(self):
    """ The number of the variables in the Circuit/CompositeGate.

    Returns:
        int: The number of variables.
    """
    return self._gates.variables_count

decomposition

decomposition()

Decomposition the CompositeGate and BasicGate in current Circuit.

Source code in QuICT/core/utils/circuit_based.py
def decomposition(self):
    """ Decomposition the CompositeGate and BasicGate in current Circuit. """
    self._gates.decomposition(no_copy=True, self_change=True)

decomposition_gates

decomposition_gates(no_copy: bool = False) -> list

Decomposition the CompositeGate or BasicGate which has build_gate function.

Returns:

  • list ( list ) –

    The list of BasicGate

Source code in QuICT/core/utils/circuit_based.py
def decomposition_gates(self, no_copy: bool = False) -> list:
    """ Decomposition the CompositeGate or BasicGate which has build_gate function.

    Returns:
        list: The list of BasicGate
    """
    return self._gates.decomposition(no_copy)

draw

draw(method: str = 'matp_auto', filename: str = None, flatten: bool = False, hidden_empty_qubits: bool = True)

Draw the figure of circuit.

Parameters:

  • method(str)

    the method to draw the circuit matp_inline: Show the figure interactively but do not save it to file. matp_file: Save the figure to file but do not show it interactively. matp_auto: Automatically select inline or file mode according to matplotlib backend. matp_silent: Return the drawn figure without saving or showing. command : command

  • filename(str)

    the output filename without file extensions, default to None. If filename is None, it will using matlibplot.show() except matlibplot.backend is agg, it will output jpg file named circuit's name.

  • flatten(bool)

    Whether draw the Circuit with CompositeGate or Decomposite it.

  • hidden_empty_qubits(bool)

    Whether hidden the empty qubits in the circuit's graph.

Returns:

  • If method is 'matp_silent', a matplotlib Figure is returned. Note that that figure is created in matplotlib

  • Object Oriented interface, which means it must be display with IPython.display.

Examples:

>>> from IPython.display import display
>>> circ = Circuit(5)
>>> circ.random_append()
>>> silent_fig = circ.draw(method="matp_silent")
>>> display(silent_fig)
>>> from IPython.display import display
>>> compositegate = CompositeGate()
>>> cx_gate=CX & [1,3]
>>> u2_gate= U2(1, 0)
>>> H| compositegate(1)
>>> cx_gate | compositegate
>>> u2_gate | compositegate(1)
>>> silent_fig = compositegate.draw(method="matp_silent")
>>> display(silent_fig)
Source code in QuICT/core/utils/circuit_based.py
def draw(
    self,
    method: str = 'matp_auto',
    filename: str = None,
    flatten: bool = False,
    hidden_empty_qubits: bool = True
):
    """Draw the figure of circuit.

    Args:
        method(str): the method to draw the circuit
            matp_inline: Show the figure interactively but do not save it to file.
            matp_file: Save the figure to file but do not show it interactively.
            matp_auto: Automatically select inline or file mode according to matplotlib backend.
            matp_silent: Return the drawn figure without saving or showing.
            command : command
        filename(str): the output filename without file extensions, default to None.
            If filename is None, it will using matlibplot.show() except matlibplot.backend
            is agg, it will output jpg file named circuit's name.
        flatten(bool): Whether draw the Circuit with CompositeGate or Decomposite it.
        hidden_empty_qubits(bool): Whether hidden the empty qubits in the circuit's graph.

    Returns:
        If method is 'matp_silent', a matplotlib Figure is returned. Note that that figure is created in matplotlib
        Object Oriented interface, which means it must be display with IPython.display.

    Examples:
        >>> from IPython.display import display
        >>> circ = Circuit(5)
        >>> circ.random_append()
        >>> silent_fig = circ.draw(method="matp_silent")
        >>> display(silent_fig)

        >>> from IPython.display import display
        >>> compositegate = CompositeGate()
        >>> cx_gate=CX & [1,3]
        >>> u2_gate= U2(1, 0)
        >>> H| compositegate(1)
        >>> cx_gate | compositegate
        >>> u2_gate | compositegate(1)
        >>> silent_fig = compositegate.draw(method="matp_silent")
        >>> display(silent_fig)
    """
    from QuICT.tools.drawer import PhotoDrawer, TextDrawing
    import matplotlib

    if method.startswith('matp'):
        if filename is not None:
            if '.' not in filename:
                filename += '.jpg'

        photo_drawer = PhotoDrawer()
        if method == 'matp_auto':
            save_file = matplotlib.get_backend() == 'agg'
            show_inline = matplotlib.get_backend() != 'agg'
        elif method == 'matp_file':
            save_file = True
            show_inline = False
        elif method == 'matp_inline':
            save_file = False
            show_inline = True
        elif method == 'matp_silent':
            save_file = False
            show_inline = False
        else:
            raise ValueError(
                "Circuit.draw.matp_method", "[matp_auto, matp_file, matp_inline, matp_silent]", method
            )

        silent = (not show_inline) and (not save_file)
        photo_drawer.run(
            circuit=self, filename=filename, save_file=save_file,
            flatten=flatten, hidden_empty_qubits=hidden_empty_qubits
        )

        if show_inline:
            from IPython.display import display
            display(photo_drawer.figure)
        elif silent:
            return photo_drawer.figure

    elif method == 'command':
        gates = self.flatten_gates() if flatten else self.gates
        qregs = self.qubits if not hidden_empty_qubits else self._gates.qubits
        text_drawer = TextDrawing(qregs, gates, hidden_empty_qubits=hidden_empty_qubits)
        if filename is None:
            print(text_drawer.single_string())
            return
        elif '.' not in filename:
            filename += '.txt'

        text_drawer.dump(filename)
    else:
        raise ValueError(
            "Circuit.draw.method", "[matp_auto, matp_file, matp_inline, matp_silent, command]", method
        )

flatten

flatten()

Flat all CompositeGate in current Circuit.

Source code in QuICT/core/utils/circuit_based.py
def flatten(self):
    """ Flat all CompositeGate in current Circuit. """
    self._gates.flatten(no_copy=True, self_change=True)

flatten_gates

flatten_gates(no_copy: bool = False) -> list

Get the list of Quantum Gates, flat all the CompositeGate in Circuit.

Source code in QuICT/core/utils/circuit_based.py
def flatten_gates(self, no_copy: bool = False) -> list:
    """ Get the list of Quantum Gates, flat all the CompositeGate in Circuit. """
    return self._gates.flatten(no_copy)

free_symbols

free_symbols()

The symbols in the Circuit/CompositeGate.

Returns:

  • list

    The symbols list.

Source code in QuICT/core/utils/circuit_based.py
def free_symbols(self):
    """ The symbols in the Circuit/CompositeGate.

    Returns:
        list: The symbols list.
    """
    return self._gates.free_symbols

gate_combination

gate_combination(eliminate_single: bool = False)

Combination all consecutive single-qubit gate / bi-qubits gate in the circuit. It will flat all CompositeGate here.

Source code in QuICT/core/utils/circuit_based.py
def gate_combination(self, eliminate_single: bool = False):
    """ Combination all consecutive single-qubit gate / bi-qubits gate in the circuit.
    It will flat all CompositeGate here.
    """
    return self._gates.combination(eliminate_single)

gate_length

gate_length() -> int

The number of CompositeGate and BasicGate in Circuit.

Source code in QuICT/core/utils/circuit_based.py
def gate_length(self) -> int:
    """ The number of CompositeGate and BasicGate in Circuit. """
    return self._gates.length

get_all_gatetype

get_all_gatetype() -> list

Return all gate's type in current circuit.

Source code in QuICT/core/utils/circuit_based.py
def get_all_gatetype(self) -> list:
    """ Return all gate's type in current circuit. """
    return self._gates.gatetype_list

get_gates_by_depth

get_gates_by_depth(depth: int) -> list

Get the list of Quantum Gates in target qubits and depth.

Parameters:

  • depth (int) –

    The target depth.

Source code in QuICT/core/utils/circuit_based.py
def get_gates_by_depth(self, depth: int) -> list:
    """ Get the list of Quantum Gates in target qubits and depth.

    Args:
        depth (int): The target depth.
    """
    target_qubits = self._gates.qubits
    if depth == -1:
        return self._gates.find_last_layer_gates(target_qubits, all_contains=True)

    return self._gates.get_target_gates(target_qubits, depth, no_copy=False)

init_pargs

init_pargs(symbols: list, values: Union[list, ndarray])

Initialize the trainable parameters of the Circuit/CompositeGate.

Parameters:

  • symbols (list) –

    The symbols that needs to be assigned values.

  • values (Union[list, ndarray]) –

    The values to be assigned.

Source code in QuICT/core/utils/circuit_based.py
def init_pargs(self, symbols: list, values: Union[list, np.ndarray]):
    """ Initialize the trainable parameters of the Circuit/CompositeGate.

    Args:
        symbols (list): The symbols that needs to be assigned values.
        values (Union[list, np.ndarray]): The values to be assigned.
    """
    if not isinstance(symbols, list):
        symbols = [symbols]
    if not isinstance(values, (list, np.ndarray)):
        values = [values]
    assert set(symbols).issubset(set(self.free_symbols())), "The symbols must belong to free symbols."
    self._gates.init_pargs(symbols, values)

insert

insert(gate, index: int)

insert a Quantum Gate into current Circuit with given index.

Parameters:

  • gate (Union[BasicGate, CompositeGate]) –

    The quantum gate want to insert.

  • index (int) –

    The index of gate list.

Source code in QuICT/core/utils/circuit_based.py
def insert(self, gate, index: int):
    """ insert a Quantum Gate into current Circuit with given index.

    Args:
        gate (Union[BasicGate, CompositeGate]): The quantum gate want to insert.
        index (int): The index of gate list.
    """
    if type(gate).__name__ == "CompositeGate" and gate.size() == 0:
        return

    assert isinstance(index, int) and index >= 0

    self._gates.insert(gate.copy(), index)

insert_by_position

insert_by_position(gate, qubits: list = None, depth: int = -1)

Insert a Quantum Gate into current Circuit with given qubits and depth, it will cause the gate list to be flatten due to the insert gate into CompositeGate.

Parameters:

  • gate (Union[BasicGate, CompositeGate]) –

    The quantum gate want to insert

  • qubits (list[int], default: None ) –

    The target qubit indexes.

  • depth (int, default: -1 ) –

    The index of insert position.

Source code in QuICT/core/utils/circuit_based.py
def insert_by_position(self, gate, qubits: list = None, depth: int = -1):
    """ Insert a Quantum Gate into current Circuit with given qubits and depth, it will
    cause the gate list to be flatten due to the insert gate into CompositeGate.

    Args:
        gate (Union[BasicGate, CompositeGate]): The quantum gate want to insert
        qubits (list[int]): The target qubit indexes.
        depth (int): The index of insert position.
    """
    if type(gate).__name__ == "CompositeGate" and gate.size() == 0:
        return

    if qubits is None:
        qubits = gate.qubits if type(gate).__name__ == "CompositeGate" else gate.cargs + gate.targs
        gate = gate.copy()
    else:
        gate = gate.copy() & qubits

    if len(qubits) == 0:
        raise ValueError("Gate need qubit indexes to insert into Composite Gate.")

    self._qubit_indexes_validation(qubits)
    self._gates.insert(gate, depth)

pop

pop(index: int = -1)

Pop the BasicGate/Operator/CompositeGate from current Quantum Circuit.

Parameters:

  • index (int, default: -1 ) –

    The target gate's index. Defaults to 0.

Source code in QuICT/core/utils/circuit_based.py
def pop(self, index: int = -1):
    """ Pop the BasicGate/Operator/CompositeGate from current Quantum Circuit.

    Args:
        index (int, optional): The target gate's index. Defaults to 0.
    """
    return self._gates.pop(index)

pop_by_position

pop_by_position(qubits: list, depth: int)

Pop the BasicGate/Operator/CompositeGate from current Quantum Circuit with given qubits and depth.

Parameters:

  • qubits (list) –

    The indexes of qubits.

  • depth (int) –

    The target depth.

Source code in QuICT/core/utils/circuit_based.py
def pop_by_position(self, qubits: list, depth: int):
    """ Pop the BasicGate/Operator/CompositeGate from current Quantum Circuit with
    given qubits and depth.

    Args:
        qubits (list): The indexes of qubits.
        depth (int): The target depth.
    """
    return self._gates.pop_by_position(qubits, depth)

qasm

qasm(output_file: str = None)

The qasm of current CompositeGate/Circuit. The Operator will be ignore.

Parameters:

  • output_file (str, default: None ) –

    The output qasm file's name or path

Returns:

  • str

    The string of Circuit/CompositeGate's qasm.

Source code in QuICT/core/utils/circuit_based.py
def qasm(self, output_file: str = None):
    """ The qasm of current CompositeGate/Circuit. The Operator will be ignore.

    Args:
        output_file (str): The output qasm file's name or path

    Returns:
        str: The string of Circuit/CompositeGate's qasm.
    """
    # Header
    qreg = self.width() if type(self).__name__ == "Circuit" else max(self.qubits) + 1
    creg = min(self.count_gate_by_gatetype(GateType.measure), qreg)
    if creg == 0:
        creg = qreg

    qasm_string = 'OPENQASM 2.0;\ninclude "qelib1.inc";\n'
    qasm_string += f"qreg q[{qreg}];\n"
    qasm_string += f"creg c[{creg}];\n"

    # Body [gates]
    cbits = 0
    for gate in self.flatten_gates(no_copy=True):
        targs = gate.cargs + gate.targs
        if gate.qasm_name == "measure":
            qasm_string += f"measure q[{targs[0]}] -> c[{cbits}];\n"
            cbits += 1
            cbits = cbits % creg
        elif gate.qasm_name == "unitary":
            str_args = [f"q[{arg}]" for arg in targs]
            qasm_string += f"{gate.name} " + ', '.join(str_args) + ";\n"
        else:
            qasm_string += gate.qasm(targs)

    if output_file is not None:
        with open(output_file, "w+") as of:
            of.write(qasm_string)

    return qasm_string

qcis

qcis(output_file: str = None)

generate the qcis of current CompositeGate/Circuit. WARNING: Only support the instruction set of QCIS.

Parameters:

  • output_file (str, default: None ) –

    The output qcis file's name or path

Returns:

  • str

    The string of Circuit/CompositeGate's qcis.

Source code in QuICT/core/utils/circuit_based.py
def qcis(self, output_file: str = None):
    """ generate the qcis of current CompositeGate/Circuit.
    WARNING: Only support the instruction set of QCIS.

    Args:
        output_file (str): The output qcis file's name or path

    Returns:
        str: The string of Circuit/CompositeGate's qcis.
    """
    qcis_string = ""
    # Body [gates]
    for gate in self.flatten_gates(no_copy=True):
        targs = gate.cargs + gate.targs
        if gate.qasm_name == "measure":
            qcis_string += f"M Q{targs[0]}\n"
        elif gate.qasm_name == "rx":
            if np.isclose(gate.parg, np.pi / 2):
                qcis_string += f"X2P Q{targs[0]}\n"
            elif np.isclose(gate.parg, -np.pi / 2):
                qcis_string += f"X2M Q{targs[0]}\n"
            else:
                qcis_string += f"RX Q{targs[0]} {gate.parg}\n"
        elif gate.qasm_name == "ry":
            if np.isclose(gate.parg, np.pi / 2):
                qcis_string += f"Y2P Q{targs[0]}\n"
            elif np.isclose(gate.parg, -np.pi / 2):
                qcis_string += f"Y2M Q{targs[0]}\n"
            else:
                qcis_string += f"RY Q{targs[0]} {gate.parg}\n"
        elif gate.qasm_name == "sdg":
            qcis_string += f"SD Q{targs[0]}\n"
        elif gate.qasm_name == "tdg":
            qcis_string += f"TD Q{targs[0]}\n"
        else:
            gate_qcis = gate.qasm_name.upper()
            qubit_string = ' '.join([f"Q{qarg}" for qarg in targs])
            if gate.params == 0:
                qcis_string += f"{gate_qcis} {qubit_string}\n"
            else:
                param_string = ' '.join([str(parg) for parg in gate.pargs])
                qcis_string += f"{gate_qcis} {qubit_string} {param_string}\n"

    qcis_string = qcis_string[:-1]
    if output_file is not None:
        with open(output_file, "w+") as of:
            of.write(qcis_string)

    return qcis_string

size

size() -> int

the number of BasicGate/Operator in the Circuit.

Returns:

  • int ( int ) –

    the number of gates in circuit

Source code in QuICT/core/utils/circuit_based.py
def size(self) -> int:
    """ the number of BasicGate/Operator in the Circuit.

    Returns:
        int: the number of gates in circuit
    """
    return self._gates.size

symbol_pargs

symbol_pargs()

Returns the symbols in the Circuit/CompositeGate and their corresponding values.

Returns:

  • dict

    Symbols with corresponding values.

Source code in QuICT/core/utils/circuit_based.py
def symbol_pargs(self):
    """ Returns the symbols in the Circuit/CompositeGate and their corresponding values.

    Returns:
        dict: Symbols with corresponding values.
    """
    return self._gates.symbol_pargs