|
| 1 | +# mOLSQ: Multilevel Quantum Layout Synthesis |
| 2 | + |
| 3 | +## Build and Installation Instructions |
| 4 | + |
| 5 | +``` |
| 6 | +# Clone mOLSQ repository |
| 7 | +git clone [email protected]:WanHsuanLin/mOLSQ.git |
| 8 | +cd mOLSQ |
| 9 | +
|
| 10 | +# Build |
| 11 | +cmake . -Bbuild |
| 12 | +cd build |
| 13 | +make |
| 14 | +``` |
| 15 | + |
| 16 | +- Required Dependencies: |
| 17 | + - GMP: Please install GMP. You may need to compile it with `-fPIC` depending on your system. |
| 18 | + - Bitwuzla (https://github.com/bitwuzla/bitwuzla/tree/4eda0536800576cb2531ab9ce13292da8f21f0eb): Please install Bitwuzla. |
| 19 | + - pblib (https://github.com/master-keying/pblib): Please intall pblib in the `include/`. You may need to compile it with `-fPIC` depending on your system. |
| 20 | + |
| 21 | +## Create a device from the Input Coupling Graph |
| 22 | + |
| 23 | +To perform QLS, we need to know the connections between the qubits, which is information about the physical device. |
| 24 | +We are going to use the `createDevice` function. |
| 25 | + |
| 26 | +``` |
| 27 | +from olsqPy import Device |
| 28 | +from src.pyolsq.apiPy import createDevice |
| 29 | +device = createDevice(name="dev", nqubits=5, connection=[(0, 1), (1, 2), (1, 3), (3, 4)]) |
| 30 | +device.printDevice() |
| 31 | +``` |
| 32 | + |
| 33 | +We use a minimalist class `qcdevice` to store the properties of the device that we need, which can be constructed with these arguments. |
| 34 | +(The last three are only for fidelity optimization.) |
| 35 | +- `name` |
| 36 | +- `nqubits`: the number of physical qubits |
| 37 | +- `connection`: a list of physical qubit pairs corresponding to edges in the coupling graph |
| 38 | +- `swap_duration`: number of cycles a SWAP gate takes. |
| 39 | + Usually it is either one, or three meaning three CX gates. |
| 40 | +- `fmeas`: a list of measurement fidelity |
| 41 | +- `fsingle`: a list of single-qubit gate fidelity |
| 42 | +- `ftwo`: a list of two-qubit gate fidelity, indices aligned with `connection` |
| 43 | + |
| 44 | +If `name` starts with `"default_"`, a hard-coded device stored in `olsq/devices/` would be loaded. |
| 45 | +Other arguments can still be specified, in which case the original device properties would be replaced by the input. |
| 46 | +``` |
| 47 | +# use a hard-coded device in olsq/devices/ called ourense |
| 48 | +# which actually has the same properties as the device we constructed above |
| 49 | +lsqc_solver.setdevice( qcdevice("default_ourense") ) |
| 50 | +``` |
| 51 | + |
| 52 | +## Create a Circuit from the Input Program |
| 53 | + |
| 54 | +Apart from the device, we need the quantum program/circuit to execute, which can be constructed with the `createCircuit` function. |
| 55 | + |
| 56 | +mOLSQ has an intermediate representation (IR) of quantum programs. (For details, refer to [a later part](#olsq-ir) of this tutorial.) |
| 57 | +In general, there are four ways to set the program: |
| 58 | +1. Use OLSQ IR |
| 59 | +2. Use a string in QASM format |
| 60 | +``` |
| 61 | +from olsqPy import Circuit |
| 62 | +from src.pyolsq.apiPy import createCircuit |
| 63 | +circuit_name = "toffoli" |
| 64 | +circuit_str = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[3];\nh q[2];\n" \ |
| 65 | + "cx q[1], q[2];\ntdg q[2];\ncx q[0], q[2];\nt q[2];\n" \ |
| 66 | + "cx q[1], q[2];\ntdg q[2];\ncx q[0], q[2];\nt q[1];\nt q[2];\n" \ |
| 67 | + "cx q[0], q[1];\nh q[2];\nt q[0];\ntdg q[1];\ncx q[0], q[1];\n" |
| 68 | +
|
| 69 | +# input the quantum program as a QASM string |
| 70 | +lsqc_solver.setprogram(circuit_str) |
| 71 | +circuit = createCircuit(circuit_name, circuit_str, is_qasm = true) |
| 72 | +circuit.printCircuit() |
| 73 | +``` |
| 74 | + |
| 75 | + |
| 76 | +## Initialization and solve |
| 77 | + |
| 78 | +``` |
| 79 | +from olsqPy import Device, Circuit, mOLSQ |
| 80 | +
|
| 81 | +# initialize your circuit |
| 82 | +# initialize your device |
| 83 | +
|
| 84 | +lsqc_solver = mOLSQ(circuit, device) |
| 85 | +lsqc_solver.enableAllCommute() # for circuits whose gates are all commutable |
| 86 | +# lsqc_solver.disAllCommute() # for circuits whose gates are not commutable (default) |
| 87 | +
|
| 88 | +lsqc_solver.run() |
| 89 | +``` |
| 90 | + |
| 91 | +There are two argument in the constructor of mOLSQ: `Circuit` and `Device`. |
| 92 | +The former one stands for the input circuit, and the later one stands for the input device. |
| 93 | +Idealy, the `run` method will return three solutions, `${circuit_name}_stage_0.qasm`, `${circuit_name}_stage_1.qasm`, and `${circuit_name}_stage_2.qasm`, from FastQLS (hueristic QLS algorithm), the first multilevel V cycle, and the second multilevel V cycle, respectively. |
| 94 | + |
| 95 | +## OLSQ IR |
| 96 | + |
| 97 | +OLSQ IR contains three things: |
| 98 | +1. `count_program_qubit`: the number of qubits in the program. |
| 99 | +2. `gates`: a list of tuples representing qubit(s) acted on by a gate, each tuple has one index if it is a single-qubit gate, two indices if it is a two-qubit gate. |
| 100 | +3. `gate_spec`: list of type/name of each gate, which is not important to OLSQ, and only needed when generating output. |
| 101 | + |
| 102 | +``` |
| 103 | +# For the following circuit |
| 104 | +# q_0: ───────────────────■─── |
| 105 | +# │ |
| 106 | +# q_1: ───────■───────────┼─── |
| 107 | +# ┌───┐┌─┴─┐┌─────┐┌─┴─┐ |
| 108 | +# q_2: ┤ H ├┤ X ├┤ TDG ├┤ X ├─ |
| 109 | +# └───┘└───┘└─────┘└───┘ |
| 110 | +
|
| 111 | +# count_program_qubit = 3 |
| 112 | +# gates = ((2,), (1,2), (2,), (0,1)) |
| 113 | +# gate_spec = ("h", "cx", "tdg", "cx") |
| 114 | +``` |
| 115 | + |
| 116 | +## Example: run_mlqls.py |
| 117 | + |
| 118 | +run_mlqls.py is an example program to use mOLSQ2 to perform layout synthesis. The output will be stored in under `result/` |
| 119 | +``` |
| 120 | +# compile an qaoa circuit on a 5-by-5 grid quantum device |
| 121 | +python3 run_mlqls.py --dt grid --d 4 -qf benchmark/qaoa/qaoa_16_0.qasm |
| 122 | +# The output files (Final IR output file and the intermediate qasm file) of running the command are in example/. |
| 123 | +
|
| 124 | +# compile an qaoa circuit on sycamore quantum device |
| 125 | +python3 run_mlqls.py --dt sycamore --qf benchmark/qaoa/qaoa_16_0.qasm |
| 126 | +``` |
| 127 | +- `--dt $(str)`: Type of the quantum device: ourense, sycamore, rochester, tokyo, aspen-4, eagle, or grid. When using a grid architecure, add `--d $(int)` to specify the grid length. |
| 128 | +- `--d $(int)`: Grid length of the grid architecture |
| 129 | +- `--qf $(str)`: Input QASM file name |
0 commit comments