{ "cells": [ { "cell_type": "markdown", "id": "f840ed81", "metadata": {}, "source": [ "[PyZX](pyzx.readthedocs.io/) is an implementation of the ZX-calculus. It stands apart from the other quantum programming environments presented in these tutorials in that it is not intended to be used to actually program a quantum computer. Rather, it is to be used as an interface to programmatically manipulate the rules of the ZX-calculus. As the name suggests, it is written in, and provided as a package for, the Python programming language. There are other implementations of the ZX-calculus, such as in [Rust](https://github.com/Quantomatic/quizx) or [Julia](https://juliapackages.com/p/zxcalculus), but neither are as feature-complete as PyZX. In particular, although the Rust implementation is considerably faster, it lacks many of the features of PyZX. In particular, PyZX includes tools for visualizing and manipulating ZX-diagrams which can be conveniently used inside a Jupyter notebook.\n", "\n", "The ZX-calculus and its applications to quantum computation are the subject of ongoing research, and currently PyZX only implements a rather limited subset of rewrite rules of the ZX-calculus. These rewrite rules have been found to be useful in applications, mostly for the optimisation and compilation of quantum circuits." ] }, { "cell_type": "markdown", "id": "090b271a", "metadata": {}, "source": [ "# Tutorial\n", "\n", "PyZX is made available as a PyPi package, which can then be installed via `pip install pyzx` and imported as usual:" ] }, { "cell_type": "code", "execution_count": 3, "id": "539f71f3", "metadata": {}, "outputs": [], "source": [ "import pyzx as zx\n", "\n", "from fractions import Fraction # Used to described rational angles" ] }, { "cell_type": "markdown", "id": "a5d9feb3", "metadata": {}, "source": [ "## Circuits & ZX-Diagrams" ] }, { "cell_type": "markdown", "id": "748ff9ac", "metadata": {}, "source": [ "Quantum circuits are represented in PyZX using the `Circuit` class, whose underlying data consist in a list of gates taken from those defined in PyZX. For instance:" ] }, { "cell_type": "code", "execution_count": 4, "id": "c31aa1f1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Circuit(3 qubits, 0 bits, 3 gates)\n", "CNOT(0,2)\n", "ZPhase(2,phase=3/4)\n", "CNOT(0,2)\n" ] } ], "source": [ "circ = zx.Circuit(3) # The initialisation argument describes the number of qubits in the circuit \n", "\n", "circ.add_gate(\"CNOT\", 0, 2)\n", "circ.add_gate(\"ZPhase\", 2, phase=Fraction(3,4))\n", "circ.add_gate(\"CNOT\", 0, 2)\n", "\n", "print(circ)\n", "for gate in circ:\n", " print(gate)" ] }, { "cell_type": "markdown", "id": "86bfc540", "metadata": {}, "source": [ "The gates supported by PyZX are defined in the `pyzx.circuit.gates` submodule, and we refer you there for the auxiliary arguments that must be given for each gate type:" ] }, { "cell_type": "code", "execution_count": 5, "id": "b713673b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on module pyzx.circuit.gates in pyzx.circuit:\n", "\n", "NAME\n", " pyzx.circuit.gates\n", "\n", "DESCRIPTION\n", " This file contains the definition of commonly used\n", " quantum gates for use in the Circuit class.\n", "\n", "CLASSES\n", " builtins.object\n", " Gate\n", " CCZ\n", " Tofolli\n", " CHAD\n", " CNOT\n", " CRZ\n", " CZ\n", " CX\n", " SWAP\n", " DiscardBit\n", " FSim\n", " HAD\n", " InitAncilla\n", " Measurement\n", " ParityPhase\n", " PostSelect\n", " XPhase\n", " NOT\n", " ZPhase\n", " S\n", " T\n", " Z\n", " typing.Generic(builtins.object)\n", " TargetMapper\n", " \n", " class CCZ(Gate)\n", " | CCZ(ctrl1: int, ctrl2: int, target: int)\n", " | \n", " | Method resolution order:\n", " | CCZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, ctrl1: int, ctrl2: int, target: int)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | reposition(self, mask, bit_mask=None)\n", " | \n", " | tcount(self)\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __hash__ = None\n", " | \n", " | name = 'CCZ'\n", " | \n", " | qasm_name = 'ccz'\n", " | \n", " | qc_name = 'Z'\n", " | \n", " | quippername = 'Z'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class CHAD(Gate)\n", " | CHAD(control: int, target: int) -> None\n", " | \n", " | Method resolution order:\n", " | CHAD\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, control: int, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'CHAD'\n", " | \n", " | qasm_name = 'ch'\n", " | \n", " | quippername = 'undefined'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class CNOT(Gate)\n", " | CNOT(control: int, target: int) -> None\n", " | \n", " | Method resolution order:\n", " | CNOT\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, control: int, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'CNOT'\n", " | \n", " | qasm_name = 'cx'\n", " | \n", " | qc_name = 'Tof'\n", " | \n", " | quippername = 'not'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class CRZ(Gate)\n", " | CRZ(control: int, target: int, phase: Union[fractions.Fraction, int]) -> None\n", " | \n", " | Method resolution order:\n", " | CRZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, control: int, target: int, phase: Union[fractions.Fraction, int]) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | name = 'CRZ'\n", " | \n", " | printphase = True\n", " | \n", " | qasm_name = 'crz'\n", " | \n", " | quippername = 'undefined'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class CX(CZ)\n", " | CX(control: int, target: int) -> None\n", " | \n", " | Method resolution order:\n", " | CX\n", " | CZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'CX'\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " | \n", " | quippername = 'X'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from CZ:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, control: int, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from CZ:\n", " | \n", " | __hash__ = None\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class CZ(Gate)\n", " | CZ(control: int, target: int) -> None\n", " | \n", " | Method resolution order:\n", " | CZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, control: int, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __hash__ = None\n", " | \n", " | name = 'CZ'\n", " | \n", " | qasm_name = 'cz'\n", " | \n", " | qc_name = 'Z'\n", " | \n", " | quippername = 'Z'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class DiscardBit(Gate)\n", " | DiscardBit(target)\n", " | \n", " | Method resolution order:\n", " | DiscardBit\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | reposition(self, _mask, bit_mask=None)\n", " | \n", " | to_graph(self, g, _q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'DiscardBit'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class FSim(Gate)\n", " | FSim(theta: Union[fractions.Fraction, int], phi: Union[fractions.Fraction, int], control: int, target: int)\n", " | \n", " | Method resolution order:\n", " | FSim\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, theta: Union[fractions.Fraction, int], phi: Union[fractions.Fraction, int], control: int, target: int)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | reposition(self, mask, bit_mask=None)\n", " | \n", " | tcount(self)\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | __hash__ = None\n", " | \n", " | name = 'FSim'\n", " | \n", " | printphase = True\n", " | \n", " | qsim_name = 'fs'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | index = 0\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class Gate(builtins.object)\n", " | Base class for representing quantum gates.\n", " | \n", " | Methods defined here:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_graph(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], q_mapper: pyzx.circuit.gates.TargetMapper[~VT], c_mapper: pyzx.circuit.gates.TargetMapper[~VT]) -> None\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | name = 'BaseGate'\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class HAD(Gate)\n", " | HAD(target: int) -> None\n", " | \n", " | Method resolution order:\n", " | HAD\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'HAD'\n", " | \n", " | qasm_name = 'h'\n", " | \n", " | qc_name = 'H'\n", " | \n", " | quippername = 'H'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class InitAncilla(Gate)\n", " | InitAncilla(label)\n", " | \n", " | Method resolution order:\n", " | InitAncilla\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, label)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'InitAncilla'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_graph(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], q_mapper: pyzx.circuit.gates.TargetMapper[~VT], c_mapper: pyzx.circuit.gates.TargetMapper[~VT]) -> None\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class Measurement(Gate)\n", " | Measurement(target: int, result_bit: Optional[int]) -> None\n", " | \n", " | Method resolution order:\n", " | Measurement\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, target: int, result_bit: Optional[int]) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | reposition(self, mask, bit_mask=None)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'result_bit': typing.Optional[int], 'target': str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | index = 0\n", " | \n", " | name = 'BaseGate'\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class NOT(XPhase)\n", " | NOT(target: int) -> None\n", " | \n", " | Method resolution order:\n", " | NOT\n", " | XPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'NOT'\n", " | \n", " | printphase = False\n", " | \n", " | qasm_name = 'x'\n", " | \n", " | qc_name = 'X'\n", " | \n", " | quippername = 'not'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from XPhase:\n", " | \n", " | split_phases(self) -> List[pyzx.circuit.gates.Gate]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from XPhase:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class ParityPhase(Gate)\n", " | ParityPhase(phase: Union[fractions.Fraction, int], *targets: int)\n", " | \n", " | Method resolution order:\n", " | ParityPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, phase: Union[fractions.Fraction, int], *targets: int)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | reposition(self, mask, bit_mask=None)\n", " | \n", " | tcount(self)\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | __hash__ = None\n", " | \n", " | name = 'ParityPhase'\n", " | \n", " | printphase = True\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | index = 0\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class PostSelect(Gate)\n", " | PostSelect(label)\n", " | \n", " | Method resolution order:\n", " | PostSelect\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, label)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_graph(self, g, labels, qs, _cs, rs, _crs)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'PostSelect'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class S(ZPhase)\n", " | S(target: int, adjoint: bool = False) -> None\n", " | \n", " | Method resolution order:\n", " | S\n", " | ZPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int, adjoint: bool = False) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'S'\n", " | \n", " | printphase = False\n", " | \n", " | qasm_name = 's'\n", " | \n", " | qasm_name_adjoint = 'sdg'\n", " | \n", " | qc_name = 'S'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from ZPhase:\n", " | \n", " | split_phases(self) -> List[ForwardRef('ZPhase')]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from ZPhase:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " \n", " class SWAP(CZ)\n", " | SWAP(control: int, target: int) -> None\n", " | \n", " | Method resolution order:\n", " | SWAP\n", " | CZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'SWAP'\n", " | \n", " | qasm_name = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " | \n", " | quippername = 'undefined'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from CZ:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __init__(self, control: int, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from CZ:\n", " | \n", " | __hash__ = None\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | tcount(self) -> int\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | to_quipper(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class T(ZPhase)\n", " | T(target: int, adjoint: bool = False) -> None\n", " | \n", " | Method resolution order:\n", " | T\n", " | ZPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int, adjoint: bool = False) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'T'\n", " | \n", " | printphase = False\n", " | \n", " | qasm_name = 't'\n", " | \n", " | qasm_name_adjoint = 'tdg'\n", " | \n", " | qc_name = 'T'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from ZPhase:\n", " | \n", " | split_phases(self) -> List[ForwardRef('ZPhase')]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from ZPhase:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " \n", " class TargetMapper(typing.Generic)\n", " | This class is used to map the target parameters of a gate to rows, qubits, and vertices\n", " | when converting them into a graph. Used by :func:`~pyzx.circuit.gates.Gate.to_graph`.\n", " | \n", " | Method resolution order:\n", " | TargetMapper\n", " | typing.Generic\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | add_label(self, l: int) -> None\n", " | Adds a tracked label.\n", " | \n", " | :raises: ValueError if the label is already tracked.\n", " | \n", " | advance_next_row(self, l: int) -> None\n", " | Advances the next free row in the label's qubit by one.\n", " | \n", " | labels(self) -> Set[int]\n", " | Returns the mapped labels.\n", " | \n", " | max_row(self) -> int\n", " | Returns the highest 'next row' number.\n", " | \n", " | next_row(self, l: int) -> int\n", " | Returns the next free row in the label's qubit.\n", " | \n", " | prev_vertex(self, l: int) -> ~VT\n", " | Returns the previous vertex in the label's qubit.\n", " | \n", " | remove_label(self, l: int) -> None\n", " | Removes a tracked label.\n", " | \n", " | :raises: ValueError if the label is not tracked.\n", " | \n", " | set_all_rows(self, n: int) -> None\n", " | Set the value of all 'next rows'.\n", " | \n", " | set_next_row(self, l: int, row: int) -> None\n", " | Sets the next free row in the label's qubit.\n", " | \n", " | set_prev_vertex(self, l: int, v: ~VT) -> None\n", " | Sets the previous vertex in the label's qubit.\n", " | \n", " | set_qubit(self, l: int, q: int) -> None\n", " | Sets the qubit id for a label.\n", " | \n", " | shift_all_rows(self, n: int) -> None\n", " | Shifts all 'next rows' by n.\n", " | \n", " | to_qubit(self, l: int) -> int\n", " | Maps a label to the qubit id in the graph.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'_prev_vs': typing.Dict[int, ~VT], '_qubits': typin...\n", " | \n", " | __orig_bases__ = (typing.Generic[~VT],)\n", " | \n", " | __parameters__ = (~VT,)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Class methods inherited from typing.Generic:\n", " | \n", " | __class_getitem__(params) from builtins.type\n", " | \n", " | __init_subclass__(*args, **kwargs) from builtins.type\n", " | This method is called when a class is subclassed.\n", " | \n", " | The default implementation does nothing. It may be\n", " | overridden to extend subclasses.\n", " \n", " class Tofolli(CCZ)\n", " | Tofolli(ctrl1: int, ctrl2: int, target: int)\n", " | \n", " | Method resolution order:\n", " | Tofolli\n", " | CCZ\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | to_basic_gates(self)\n", " | \n", " | to_graph(self, g, q_mapper, c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __hash__ = None\n", " | \n", " | name = 'Tof'\n", " | \n", " | qasm_name = 'ccx'\n", " | \n", " | qc_name = 'Tof'\n", " | \n", " | quippername = 'not'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from CCZ:\n", " | \n", " | __init__(self, ctrl1: int, ctrl2: int, target: int)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | reposition(self, mask, bit_mask=None)\n", " | \n", " | tcount(self)\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __annotations__ = {'name': typing.ClassVar[str], 'qasm_name': typing.C...\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class XPhase(Gate)\n", " | XPhase(target: int, phase: Union[fractions.Fraction, int] = 0) -> None\n", " | \n", " | Method resolution order:\n", " | XPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int, phase: Union[fractions.Fraction, int] = 0) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | split_phases(self) -> List[pyzx.circuit.gates.Gate]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | name = 'XPhase'\n", " | \n", " | printphase = True\n", " | \n", " | qasm_name = 'rx'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", " \n", " class Z(ZPhase)\n", " | Z(target: int) -> None\n", " | \n", " | Method resolution order:\n", " | Z\n", " | ZPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | name = 'Z'\n", " | \n", " | printphase = False\n", " | \n", " | qasm_name = 'z'\n", " | \n", " | qc_name = 'Z'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from ZPhase:\n", " | \n", " | split_phases(self) -> List[ForwardRef('ZPhase')]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from ZPhase:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " \n", " class ZPhase(Gate)\n", " | ZPhase(target: int, phase: Union[fractions.Fraction, int]) -> None\n", " | \n", " | Method resolution order:\n", " | ZPhase\n", " | Gate\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, target: int, phase: Union[fractions.Fraction, int]) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | split_phases(self) -> List[ForwardRef('ZPhase')]\n", " | \n", " | tcount(self)\n", " | \n", " | to_emoji(self, strings: List[List[str]]) -> None\n", " | \n", " | to_graph(self, g, q_mapper, _c_mapper)\n", " | Add the converted gate to the graph.\n", " | \n", " | :param g: The graph to add the gate to.\n", " | :param q_mapper: A mapper for qubit labels.\n", " | :param c_mapper: A mapper for bit labels.\n", " | \n", " | to_quipper(self)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __annotations__ = {'printphase': typing.ClassVar[bool]}\n", " | \n", " | name = 'ZPhase'\n", " | \n", " | printphase = True\n", " | \n", " | qasm_name = 'rz'\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from Gate:\n", " | \n", " | __add__(self, other)\n", " | \n", " | __eq__(self, other: object) -> bool\n", " | Return self==value.\n", " | \n", " | __matmul__(self, other)\n", " | \n", " | __repr__(self) -> str\n", " | Return repr(self).\n", " | \n", " | __str__(self) -> str\n", " | Return str(self).\n", " | \n", " | copy(self: ~Tvar) -> ~Tvar\n", " | \n", " | graph_add_node(self, g: pyzx.graph.base.BaseGraph[~VT, ~ET], mapper: pyzx.circuit.gates.TargetMapper[~VT], t: Literal[0, 1, 2, 3], l: int, r: int, phase: Union[fractions.Fraction, int] = 0, etype: Literal[1, 2] = 1, ground: bool = False) -> ~VT\n", " | \n", " | reposition(self: ~Tvar, mask: List[int], bit_mask: Optional[List[int]] = None) -> ~Tvar\n", " | \n", " | to_adjoint(self: ~Tvar) -> ~Tvar\n", " | \n", " | to_basic_gates(self) -> List[ForwardRef('Gate')]\n", " | \n", " | to_qasm(self) -> str\n", " | \n", " | to_qc(self) -> str\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from Gate:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from Gate:\n", " | \n", " | __hash__ = None\n", " | \n", " | index = 0\n", " | \n", " | qasm_name_adjoint = 'undefined'\n", " | \n", " | qc_name = 'undefined'\n", "\n", "DATA\n", " ClassVar = typing.ClassVar\n", " Special type construct to mark class variables.\n", " \n", " An annotation wrapped in ClassVar indicates that a given\n", " attribute is intended to be used as a class variable and\n", " should not be set on instances of that class. Usage::\n", " \n", " class Starship:\n", " stats: ClassVar[Dict[str, int]] = {} # class variable\n", " damage: int = 10 # instance variable\n", " \n", " ClassVar accepts only types and cannot be further subscribed.\n", " \n", " Note that ClassVar is not a class itself, and should not\n", " be used with isinstance() or issubclass().\n", " \n", " Dict = typing.Dict\n", " A generic version of dict.\n", " \n", " ET = ~ET\n", " FractionLike = typing.Union[fractions.Fraction, int]\n", " List = typing.List\n", " A generic version of list.\n", " \n", " Optional = typing.Optional\n", " Optional type.\n", " \n", " Optional[X] is equivalent to Union[X, None].\n", " \n", " Set = typing.Set\n", " A generic version of set.\n", " \n", " Tvar = ~Tvar\n", " Type = typing.Type\n", " A special construct usable to annotate class objects.\n", " \n", " For example, suppose we have the following classes::\n", " \n", " class User: ... # Abstract base for User classes\n", " class BasicUser(User): ...\n", " class ProUser(User): ...\n", " class TeamUser(User): ...\n", " \n", " And a function that takes a class argument that's a subclass of\n", " User and returns an instance of the corresponding class::\n", " \n", " U = TypeVar('U', bound=User)\n", " def new_user(user_class: Type[U]) -> U:\n", " user = user_class()\n", " # (Here we could write the user object to a database)\n", " return user\n", " \n", " joe = new_user(BasicUser)\n", " \n", " At this point the type checker knows that joe has type BasicUser.\n", " \n", " VT = ~VT\n", " __annotations__ = {'gate_types': typing.Dict[str, typing.Type[pyzx.cir...\n", " gate_types = {'CCZ': , 'CHAD': , 'ccx': \n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "zx.draw(diagram, labels=True)" ] }, { "cell_type": "markdown", "id": "fff49bfb", "metadata": {}, "source": [ "However, this isn't really the \"standard\" way to instantiate a ZX-diagram. It's much more common to obtain one from a quantum circuit of interest, and PyZX of course provides a method to do so. To convert our circuit to a diagram, we write:" ] }, { "cell_type": "code", "execution_count": 14, "id": "e2972e98", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "circ_diagram = circ.to_graph()\n", "zx.draw(circ_diagram)" ] }, { "cell_type": "markdown", "id": "659930e3", "metadata": {}, "source": [ "An interactive visualisation can be obtained using the PyZX graph editor. The editor can be used to manipulate vertices of the diagram, apply rewrite rules or even arbitrary edits to the diagram. Click \"Save snapshot\" to save the result back into `circ_diagram`:" ] }, { "cell_type": "code", "execution_count": 15, "id": "ae3b1134", "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", "\t\t\t" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "666118c8548145a9998b46f97e34ec63", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ZXEditorWidget(graph_buttons='{\"spider\": {\"active\": false, \"text\": \"fuse spiders\", \"tooltip\": \"Fuses connected…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d0c19ed7d38f482ebb66112348cbf102", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "666118c8548145a9998b46f97e34ec63", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ZXEditorWidget(graph_buttons='{\"spider\": {\"active\": false, \"text\": \"fuse spiders\", \"tooltip\": \"Fuses connected…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "zx.editor.edit(circ_diagram)" ] }, { "cell_type": "markdown", "id": "4e5adc68", "metadata": {}, "source": [ "Within the PyZX editor, you will note that we can also apply some of the ZX-calculus rewrite rules to our diagram. Let's next see how we can do this programmatically." ] }, { "cell_type": "markdown", "id": "9ef38b05", "metadata": {}, "source": [ "## Applying rewrites" ] }, { "cell_type": "markdown", "id": "4fb23841", "metadata": {}, "source": [ "The syntax for applying a result is a little complex. Rewrites are applied by calling the `zx.simplify.simp` function, which takes 4 non-optional arguments:\n", "\n", "- the diagram `diagram` to apply the rewrites to;\n", "- a string `name`, which simply describes a name to display;\n", "- a function `match`, which finds *non-intersecting* matches in `diagram` of the LHS of the rewrite rule to apply;\n", "- a function `rewrite`, which rewrites each match to the RHS of the rule.\n", "\n", "The rewrite rules that were available in the editor all have `match` and `rewrite` functions which are described in the `pyzx.rules` submodule. These each come in a version that finds a single match, and a version that tries to find as many *non-overlapping* matches in the diagram as possible, dubbed \"parallel\" versions.\n", "\n", "Let's apply the spider fusion rule to the following simple diagram:" ] }, { "cell_type": "code", "execution_count": 16, "id": "909728ca", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "circ4 = zx.Circuit(1) # The initialisation argument describes the number of qubits in the circuit \n", "\n", "circ4.add_gate(\"ZPhase\", 0, Fraction(1/2))\n", "circ4.add_gate(\"ZPhase\", 0, Fraction(1/2))\n", "\n", "circ_diagram4 = circ4.to_graph()\n", "zx.draw(circ_diagram4)" ] }, { "cell_type": "code", "execution_count": 17, "id": "0c29f1f9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "spider: 1. 1 iterations\n" ] }, { "data": { "text/html": [ "
\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "zx.simplify.simp(circ_diagram4, \"spider\", zx.simplify.match_spider, zx.simplify.spider)\n", "zx.draw(circ_diagram4)" ] }, { "cell_type": "markdown", "id": "6c11ef24", "metadata": {}, "source": [ "Now, if you peruse the content of `pyzx.simplify` (for instance with `help(zx.simplify)`), you will notice that the set of rewrites defined is very incomplete, and also includes some rather unfamiliar rewrites. This is partly because only rewrites which have proved useful in practice have been implemented, and partly because of the issue of circuit extraction. " ] }, { "cell_type": "markdown", "id": "a1212576", "metadata": {}, "source": [ "## Extracting circuits from diagrams" ] }, { "cell_type": "markdown", "id": "e68447ee", "metadata": {}, "source": [ "It is easy to turn a quantum circuit into a ZX-diagram and apply rewrite rules. However, once these rewrites have been applied it can be very complicated to extract a quantum circuit from the resulting diagram, short of reversing all of the rewrites and returning to the original circuit. In fact, it was [recently proved](https://arxiv.org/abs/2202.09194) that extracting circuits from an arbitrary ZX-diagram (one not necessarily obtained from a circuit in the first place) can be #P-hard, even under the promise that such a circuit exists. \n", "\n", "In order to avoid this difficulty, one carefully applies rewrites to a diagram which are known to preserve some global property of the diagram which guarantees extractability. For example, \"causal flow\" is a graph-theoretic property originally defined for reasoning about measurement-based quantum computations (MBQC). When adapted to a ZX-diagram, it guarantees that the ZX-diagram can be interpreted as such an MBQC for which a circuit extraction is known. The problem of finding rewrite rules which guarantee extractability is still very much the topic of ongoing research, and goes beyond the remit of these notes.\n", "\n", "Some such rewrite strategies are assembled into simplification strategies for quantum circuits, also defined in `pyzx.simplify`. The main ones are `clifford_simp` and `full_reduce`. Let's apply `clifford_simp` to simplify one of our circuits:" ] }, { "cell_type": "code", "execution_count": 18, "id": "cac179ec", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "zx.clifford_simp(circ_diagram)\n", "zx.draw(circ_diagram)" ] }, { "cell_type": "markdown", "id": "79c87604", "metadata": {}, "source": [ "This is clearly not a circuit, but we can extract a PyZX `Circuit` using:" ] }, { "cell_type": "code", "execution_count": 19, "id": "7afef4ce", "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'float' object cannot be interpreted as an integer", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "Input \u001b[0;32mIn [19]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m simplified_circuit \u001b[38;5;241m=\u001b[39m zx\u001b[38;5;241m.\u001b[39mextract_circuit(circ_diagram)\n\u001b[1;32m 2\u001b[0m zx\u001b[38;5;241m.\u001b[39mdraw(simplified_circuit)\n", "File \u001b[0;32m/nix/store/8pcypyimqnwbgrdncvp54s9icg90gj38-python3-3.9.13-env/lib/python3.9/site-packages/pyzx/extract.py:635\u001b[0m, in \u001b[0;36mextract_circuit\u001b[0;34m(g, optimize_czs, optimize_cnots, up_to_perm, quiet)\u001b[0m\n\u001b[1;32m 631\u001b[0m q: Union[\u001b[38;5;28mfloat\u001b[39m, \u001b[38;5;28mint\u001b[39m]\n\u001b[1;32m 633\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m 634\u001b[0m \u001b[38;5;66;03m# preprocessing\u001b[39;00m\n\u001b[0;32m--> 635\u001b[0m czs_saved \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[43mclean_frontier\u001b[49m\u001b[43m(\u001b[49m\u001b[43mg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfrontier\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mqubit_map\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moptimize_czs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 637\u001b[0m \u001b[38;5;66;03m# Now we can proceed with the actual extraction\u001b[39;00m\n\u001b[1;32m 638\u001b[0m \u001b[38;5;66;03m# First make sure that frontier is connected in correct way to inputs\u001b[39;00m\n\u001b[1;32m 639\u001b[0m neighbor_set \u001b[38;5;241m=\u001b[39m neighbors_of_frontier(g, frontier)\n", "File \u001b[0;32m/nix/store/8pcypyimqnwbgrdncvp54s9icg90gj38-python3-3.9.13-env/lib/python3.9/site-packages/pyzx/extract.py:509\u001b[0m, in \u001b[0;36mclean_frontier\u001b[0;34m(g, c, frontier, qubit_map, optimize_czs)\u001b[0m\n\u001b[1;32m 507\u001b[0m g\u001b[38;5;241m.\u001b[39mset_phase(v, \u001b[38;5;241m0\u001b[39m)\n\u001b[1;32m 508\u001b[0m \u001b[38;5;66;03m# And now on to CZ gates\u001b[39;00m\n\u001b[0;32m--> 509\u001b[0m cz_mat \u001b[38;5;241m=\u001b[39m Mat2([[\u001b[38;5;241m0\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(g\u001b[38;5;241m.\u001b[39mqubit_count())] \u001b[38;5;28;01mfor\u001b[39;00m j \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28;43mrange\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mqubit_count\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m])\n\u001b[1;32m 510\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m v \u001b[38;5;129;01min\u001b[39;00m frontier:\n\u001b[1;32m 511\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m w \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mlist\u001b[39m(g\u001b[38;5;241m.\u001b[39mneighbors(v)):\n", "\u001b[0;31mTypeError\u001b[0m: 'float' object cannot be interpreted as an integer" ] } ], "source": [ "simplified_circuit = zx.extract_circuit(circ_diagram)\n", "zx.draw(simplified_circuit)" ] }, { "cell_type": "markdown", "id": "35d4ebb9", "metadata": {}, "source": [ "# Deutsch-Jozsa algorithm" ] }, { "cell_type": "markdown", "id": "4a19e289", "metadata": {}, "source": [ "Let's import the (unitary part of) the Deutsch-Jozsa quantum circuit we gave in the OpenQASM and Qiskit tutorials:" ] }, { "cell_type": "code", "execution_count": null, "id": "83f17700", "metadata": {}, "outputs": [], "source": [ "dj_circ = zx.Circuit.from_qasm(\"\"\"\n", "OPENQASM 2.0;\n", "include \"qelib1.inc\";\n", "qreg q[4];\n", "creg c[3];\n", "h q[0];\n", "h q[1];\n", "h q[2];\n", "x q[3];\n", "h q[3];\n", "x q[0];\n", "x q[2];\n", "barrier q[0],q[1],q[2],q[3];\n", "cx q[0],q[3];\n", "cx q[1],q[3];\n", "cx q[2],q[3];\n", "barrier q[0],q[1],q[2],q[3];\n", "x q[0];\n", "x q[2];\n", "h q[0];\n", "h q[1];\n", "h q[2];\n", "barrier q[0],q[1],q[2],q[3];\n", "measure q[0] -> c[0];\n", "measure q[1] -> c[1];\n", "measure q[2] -> c[2];\n", "\"\"\").to_graph()\n", "\n", "zx.draw(dj_circ)" ] }, { "cell_type": "markdown", "id": "2efb890f", "metadata": {}, "source": [ "As announced, `from_qasm` ignores the the classical parts when importing the circuit. We can then appy an optimisation routine:" ] }, { "cell_type": "code", "execution_count": null, "id": "7f2be364", "metadata": {}, "outputs": [], "source": [ "zx.clifford_simp(dj_circ)\n", "zx.draw(dj_circ)" ] }, { "cell_type": "markdown", "id": "db470696", "metadata": {}, "source": [ "Then extract a circuit back out:" ] }, { "cell_type": "code", "execution_count": null, "id": "0fc8d380", "metadata": {}, "outputs": [], "source": [ "zx.draw(zx.extract_circuit(dj_circ))" ] }, { "cell_type": "markdown", "id": "10766ecf", "metadata": {}, "source": [ "Now, it might not be apparent from such a small circuit, but the optimisation ideas underlying `clifford_simp` have proven very effective when the circuits get much larger. It's also worth pointing that this example might be somewhat unnatural: we are optimising not just the circuit for implementing Deutsch-Jozsa, but also the circuit that implements the oracle for the input function `f`." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.13" } }, "nbformat": 4, "nbformat_minor": 5 }