Metadata-Version: 2.1
Name: olsq
Version: 0.0.1
Summary: Optimal Layout Synthesis for Quantum Computing (OLSQ) for mapping and scheduling quantum circuits
Home-page: https://github.com/tbcdebug/OLSQ
Author: Daniel Bochen Tan
Author-email: bctan@cs.ucla.edu
License: BSD
Project-URL: Bug Tracker, https://github.com/tbcdebug/OLSQ/issues
Description: [![iccad](https://img.shields.io/badge/Published-ICCAD'20-brightgreen.svg?style=for-the-badge)](https://ieeexplore.ieee.org/document/9256696)
        [![arXiv](https://img.shields.io/badge/arXiv-2007.15671-brightgreen.svg?style=for-the-badge)](https://arxiv.org/abs/2007.15671)
        [![Unitary Fund](https://img.shields.io/badge/Supported%20By-UNITARY%20FUND-brightgreen.svg?style=for-the-badge)](http://unitary.fund)
        
        # OLSQ: Optimal Layout Synthesis for Quantum Computing
        
        ## Installation
        
        ```
        pip install -i https://test.pypi.org/simple/ --no-deps olsq==0.1.dev9
        ```
        Please make sure that you have the `networkx` version `>=2.5` and `z3-solver` version `>=4.8.9.0` in your Python environment.
        
        ## Brief Tutorial
        
        The code blocks in this section consist an example usage of OLSQ.
        We also add an interface to [Cirq](https://github.com/quantumlib/Cirq), check out the next section as well.
        
        ### Initialization
        
        ```
        from olsq import OLSQ
        
        
        lsqc_solver = OLSQ("depth", "normal")
        ```
        
        There are two argument in the constructor of OLSQ: `objective_name` and `mode`.
        - `objective_name` can be `depth`, `swap`, or `fidelity`.
        - `mode` can be `normal`, or `transition`.
        The latter stands for TB-OLSQ in the paper.
        
        ### Setting the Input Program
        
        ```
        circuit = "OPENQASM 2.0;\n include \"qelib1.inc\";\n qreg q[3];\n h q[2];\n cx q[1], q[2];\n tdg q[2];\n " \
                  "cx q[0], q[2];\n t q[2];\n cx q[1], q[2];\n tdg q[2];\n cx q[0], q[2];\n t q[1];\n t q[2];\n " \
                  "cx q[0], q[1];\n h q[2];\n t q[0];\n tdg q[1];\n cx q[0], q[1];\n"
        lsqc_solver.setprogram(circuit)
        ```
        
        The example circuit above is a Toffoli gate
        ```
        """
                                                               ┌───┐      
        q_0: ───────────────────■─────────────────────■────■───┤ T ├───■──
                                │             ┌───┐   │  ┌─┴─┐┌┴───┴┐┌─┴─┐
        q_1: ───────■───────────┼─────────■───┤ T ├───┼──┤ X ├┤ TDG ├┤ X ├
             ┌───┐┌─┴─┐┌─────┐┌─┴─┐┌───┐┌─┴─┐┌┴───┴┐┌─┴─┐├───┤└┬───┬┘└───┘
        q_2: ┤ H ├┤ X ├┤ TDG ├┤ X ├┤ T ├┤ X ├┤ TDG ├┤ X ├┤ T ├─┤ H ├──────
             └───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘└───┘ └───┘      
        """
        ```
        
        ### Setting the input device
        
        ```
        from olsq.device import qcdevice
        
        
        lsqc_solver.setdevice(qcdevice("dev", 5, [(0, 1), (1, 2), (1, 3), (3, 4)], 3))
        ```
        
        We only use a few properties of the QC device, so we use a minimalist class `qcdevice` to store these values.
        To construct a `qcdevice`, The below arguments are required.
        (The last three are only for fidelity optimization.)
        1. `name`
        2. `nqubits`: the number of physical qubits
        3. `connection`: a list of physical qubit pairs corresponding to edges in the coupling graph
        4. `swap_duration`: number of cycles a SWAP gate takes.
           Usually it is either one, or three meaning three CX gates.
        5. `fmeas`: a list of measurement fidelity
        6. `fsingle`: a list of single-qubit gate fidelity
        7. `ftwo`: a list of two-qubit gate fidelity, indices aligned with `connection`
        
        ### Solving and Output
        
        ```
        result = lsqc_solver.solve()
        print(result)
        ```
        
        The `solve` method can also takes two optional arguemnts
        - `output_mode` can be `"IR"` or `"QASM"`. The former means our own IR.
        
        - `output_file_name`
        
        The result of the above example is as below.
        ```
        """
                                                         ┌───┐     ┌───┐┌───┐ ┌───┐      ┌─┐      
        q_0: ───────────────────■─────────────────────■──┤ X ├──■──┤ X ├┤ T ├─┤ H ├──────┤M├──────
             ┌───┐┌───┐┌─────┐┌─┴─┐┌───┐┌───┐┌─────┐┌─┴─┐└─┬─┘┌─┴─┐└─┬─┘└───┘ ├───┤      └╥┘┌─┐   
        q_1: ┤ H ├┤ X ├┤ TDG ├┤ X ├┤ T ├┤ X ├┤ TDG ├┤ X ├──■──┤ X ├──■────■───┤ T ├───■───╫─┤M├───
             └───┘└─┬─┘└─────┘└───┘└───┘└─┬─┘└┬───┬┘└───┘     └───┘     ┌─┴─┐┌┴───┴┐┌─┴─┐ ║ └╥┘┌─┐
        q_2: ───────■─────────────────────■───┤ T ├─────────────────────┤ X ├┤ TDG ├┤ X ├─╫──╫─┤M├
                                              └───┘                     └───┘└─────┘└───┘ ║  ║ └╥┘
        q_3: ─────────────────────────────────────────────────────────────────────────────╫──╫──╫─
                                                                                          ║  ║  ║
        q_4: ─────────────────────────────────────────────────────────────────────────────╫──╫──╫─
                                                                                          ║  ║  ║
        c: 5/═════════════════════════════════════════════════════════════════════════════╩══╩══╩═
                                                                                          2  0  1
        """
        ```
        
        ## Cirq Interface
        
        Given `circuit` and `device_graph` as in [this line](https://github.com/quantumlib/Cirq/blob/8f9d8597364b8bd0d29833cbbd014ebf1c62f3db/cirq/contrib/quantum_volume/quantum_volume.py#L215).
        ```
        from olsq.olsq_cirq import OLSQ_cirq
        
        
        # use OLSQ to route the circuit
        lsqc_solver = OLSQ_cirq("depth", "normal")
        
        # simply pass the circuit
        lsqc_solver.setprogram(circuit)
        
        # construct a device from a device graph
        lsqc_solver.setdevicegraph(device_graph)
        
        # mapping is the final mapping from physical to logical
        routed_circuit, mapping = lsqc_solver.solve()
        ```
        ## Qiskit Interface
        
        There are two arguments for the `setprogram` method of `OLSQ_qiskit`: if the second is `"qasm"`, then you can input a QASM string representing the quantum program as the first argument; if the second is `"qiskit"`, then you can input a `QuantumCircuit` object in Qiskit as the first argument.
        
        You can pass a `backend` from `IBMQ` to OLSQ using the `setdevice` method with the second argument set to `"ibm"`.
        
        The `solve` method returns an `QuantumCircuit` object and the final mapping from physical to logical qubits.
        
        ```
        from qiskit import IBMQ
        from olsq.olsq_qiskit import OLSQ_qiskit
        
        lsqc_solver = OLSQ_qiskit("depth", "normal")
        
        lsqc_solver.setprogram(circuit, "qasm") # circuit is some QASM string
        
        provider = IBMQ.load_account()
        backend = provider.backends()[1] # change to your backend of choice
        
        lsqc_solver.setdevicegraph(backend, "ibm")
        
        routed_circuit, mapping = lsqc_solver.solve()
        ```
        
        ## BibTeX Citation
        ```
        @InProceedings{iccad20-tan-cong-optimal-layout-synthesis,
          author          = {Tan, Bochen and Cong, Jason},
          booktitle       = {Proceedings of the 39th International Conference on Computer-Aided Design},
          title           = {Optimal Layout Synthesis for Quantum Computing},
          year            = {2020},
          address         = {New York, NY, USA},
          publisher       = {Association for Computing Machinery},
          series          = {ICCAD '20},
          archiveprefix   = {arXiv},
          eprint          = {2007.15671},
          primaryclass    = {quant-ph},
          articleno       = {137},
          doi             = {10.1145/3400302.3415620},
          isbn            = {9781450380263},
          keywords        = {quantum computing, scheduling, allocation, mapping, placement, layout synthesis},
          location        = {Virtual Event, USA},
          numpages        = {9},
          url             = {https://doi.org/10.1145/3400302.3415620},
        }
        ```
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
