Skip to content

Commit

Permalink
Merge branch 'fixbasicseq.rb'
Browse files Browse the repository at this point in the history
 - Updates to working BasicSequences and notebooks, and up to date documentation
 - Addresses issues #55, #38
 - Also addresses #35, #32, #31
 - Also #26, #25, #21
  • Loading branch information
ahelsing committed Oct 11, 2019
2 parents 88f4d4d + 6d251cb commit 923e2a2
Show file tree
Hide file tree
Showing 46 changed files with 2,876 additions and 2,003 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
.ipynb_checkpoints
*.txt~
*.ipynb~
*.md~
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# NOTE: When editing this, be sure to update setup.py

language: python
python:
- "3.6"
- "3.5"
# - "3.7" (fails due to watchdog; skip for now)

install:
# Setup anaconda. See http://conda.pydata.org/docs/travis.html
Expand Down
106 changes: 79 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,46 @@ programs directly specify gates at the physical layer, but with many of the
niceties of a high-level programming language provided by the python host
language.

Documentation on the QGL2 compiler and language, including current known limitations, is in [doc].

## Examples

QGL2 directly parses the Python syntax to give natural looking binding of qubit
measurement results to variables and control flow statements.
For usage examples, see the sample Jupyter notebooks in the [sample notebooks directory](/notebooks).

```python
# single qubit reset
from qgl2.qgl2 import qgl2decl, QRegister
from qgl2.qgl1 import Id, X, MEAS
For code samples, see the [Basic Sequences](/src/python/qgl2/basic_sequences).

For an example of compiling a QGL2 program from the command-line, see [doc/README.txt].

QGL2 directly parses the Python syntax to give natural looking qubit sequences and control flow.
measurement results to variables and control flow statements. For example:

```python
@qgl2decl
def reset():
q = QRegister(1)
m = MEAS(q)
if m:
X(q)
else:
Id(q)
```
def RabiAmp(qubit: qreg, amps, phase=0):
"""Variable amplitude Rabi nutation experiment."""
for amp in amps:
init(qubit)
Utheta(qubit, amp=amp, phase=phase)
MEAS(qubit)

Once a function is decorated with `@qgl2decl` it can act as the `main` for
compiling a QGL2 program. If the `reset` function is placed in Python module
then it can be compiled with:
compiling a QGL2 program. If the `RabiAmp` function is placed in a Python module
then it can be compiled with something like:

```python
from pyqgl2.main import compile_function
result = compile_function(filename, "reset")
from pyqgl2.qreg import QRegister
import numpy as np
q = QRegister(1)
qgl1Function = compile_function(filename, "RabiAmp", (q, np.linspace(0, 1, 1), 0))
```

The result is a function, whose execution generates a QGL sequence.
```python
# Run the compiled function. Note that the generated function takes no arguments itself
seq = qgl1Function()
```
That sequence can then be examined or compiled to hardware, as described in the [QGL documentation](https://github.com/BBN-Q/QGL).

QGL2 uses type annotations in function calls to mark quantum and classical
values. Encapsulating subroutines makes it possible to write tidy compact code
Expand Down Expand Up @@ -70,8 +82,8 @@ def qft(qs: qreg):
MEAS(qs)
```

By embedding in Python powerful metaprogramming of sequences is possible. For
example process tomography on a two qubit sequence comes a function.
By embedding in Python, powerful metaprogramming of sequences is possible. For
example process tomography on a two qubit sequence becomes a function.

```python
@qgl2decl
Expand All @@ -91,24 +103,64 @@ def tomo(f, q1: qreg, q2: qreg):


## Installation
### Current instructions
<!-- Be sure to keep this in sync with .travis.yml and setup.py -->
* Most any OS should be OK. Instructions tested on Ubuntu 18.04
* Install `git` and `buildessentials` packages
* `git-lfs` is now required: See https://git-lfs.github.com/
* Download it & unpack and run `install.sh`
* Install python 3.6; easiest done using [Anaconda](https://www.anaconda.com/distribution/#download-section)
* See below for sample installation given an Anaconda install
* You will need python 3 compatible atom (either atom 1.0.0-dev or ecpy channel atom 0.4)
* Install QGL: (https://github.com/BBN-Q/QGL)
* Install QGL dependencies: `cd QGL; pip install -e .`
* From within the QGL git clone, set up git lfs: `<QGL>$ git lfs install`
* Add QGL to your `.bashrc`: `export PYTHONPATH=$QHOME/QGL:$QHOME/pyqgl2/src/python`
* Then: `pip install meta` and `pip install watchdog`
* Optional: `pip install pep8` and `pip install pylint`
* For typical usage, you also need Auspex (https://github.com/BBN-Q/Auspex)
* See install instructions at https://auspex.readthedocs.io/en/latest/
* Download or clone, then `cd auspex; pip install -e .`
* Put `Auspex/src` on your `PYTHONPATH` as in above
* Install `bbndb` as well (if not installed by QGL): `git clone git@github.com:BBN-Q/bbndb.git`
* Put the bbndb directory on your PYTHONPATH
* `pip install -e .`
* ?Optional: Get the BBN Adapt module as well
* `git@github.com:BBN-Q/Adapt.git`
* Put `Adapt/src` on your `PYTHONPATH` as in above
* Create a measurement file, typically eg `QHOME/test_measure.yml`, containing:
```
config:
AWGDir: /tmp/awg
KernelDir: /tmp/kern
LogDir: /tmp/alog
```
* Set an environment variable to point to it in your `.bashrc`: `export BBN_MEAS_FILE=$QHOME/test_measure.yml`
* Optional: Install `coveralls` (i.e. for CI)
* Download `pyqgl2` source from git (https://github.com/BBN-Q/pyqgl2)
* Test: `cd pyqgl2; python -m unittest discover`. Should see 80+ tests run without errors (warnings are OK).

### Dependencies
<!-- Be sure to keep this in sync with .travis.yml and setup.py -->
* Working [https://github.com/BBN-Q/QGL] installation (including `networkx`, `numpy`, `scipy`, `bqplot`, `sqlalchemy`)
* Python 3.6
* watchdog and meta
* PYTHONPATH includes `<QGL2 install directory>/src/python`

* Working QGL installation (including networkx, bokeh, numpy, scipy)
* Python 3.5 or 3.6
* PYTHONPATH includes <QGL2 install directory>/src/python

Expanding on that:
Requires python3 anaconda, python 3 compatible atom (either atom 1.0.0-dev or
ecpy channel atom 0.4), and latest QGL repo. The quickest way to get started is:

### Sample install using Anaconda
```bash
<install anaconda python3>
conda install future
conda install -c ecpy atom watchdog
pip install meta
git clone --recurse-submodules git@github.com:BBN-Q/QGL
cd QGL
pip install -e .
git lfs install
cd ..
git clone https://github.com/BBN-Q/auspex.git
cd auspex
pip install -e .
cd ..
git clone git@qiplab.bbn.com:buq-lab/pyqgl2.git
```
Expand Down
53 changes: 23 additions & 30 deletions doc/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,34 @@ restrictions / limitations / ways it is not full python, see
restrictions.txt

To run a QGL2 program:
See sample Jupyter notebooks in <qgl2>/notebooks. Start with
"QGL2 RabiAmp.ipynb" or "QGL2 RabiSingleShot.ipynb".
See sample Jupyter notebooks in <qgl2>/notebooks.

The QGL2 main is in `pyqgl2.main`

Run that with -h to get commandline help.
The QGL2 main is in `pyqgl2.main`. Run that with -h to get commandline
help. See sample uses in [src/pythong/qgl2/basic_sequences].

Sample commandline:

```
<qgl2>/src/python $ python pyqgl2/main.py qgl2/basic_sequences/RabiMin.py -m doRabiAmp
Using ChannelLibrary from config
Compiled 1 sequences.
['<QGL>/QGL/awg/qgl2main/test/test-APS1.h5', '<QGL>/QGL/awg/qgl2main/test/test-APS2.h5']
$ python src/python/pyqgl2/main.py -C src/python/qgl2/basic_sequences/Rabi.py -m SingleShotNoArg
AWG_DIR environment variable not defined. Unless otherwise specified, using temporary directory for AWG sequence file outputs.
Will create and use APS2ish 3 qubit test channel library
Creating engine...


COMPILING [src/python/qgl2/basic_sequences/Rabi.py] main SingleShotNoArg
...
Generated sequences:

[WAIT((Qubit('q1'),)),
Id(q1),
MEAS(M-q1, shape_fun=<autodyne>),
WAIT((Qubit('q1'),)),
X(q1),
MEAS(M-q1, shape_fun=<autodyne>)]
```

When using pyqgl2.main as your main:
- Any Channel library defined in the usual QGL JSON files will be
used.
- The qubit named 'q1' will be used as the Qubit in your QGL2
program, which must use a single qubit variable named 'q'.
- If you have no Channel library, a default one will be created.

The QGL2 programs in `qgl2/basic_sequences/*Min.py` are tuned for
working with the latest QGL2 compiler. Note they all use a single
qubit variable named 'q' that is given a default value at the
start. This value will be replaced by the compiler if a different
value is given as the sole argument to the function.

Note that not all the QGL2 programs in the `basic_sequences/*Min.py` will
currently work. E.G.:
* RabiWidth has a problem importing some needed QGL functions
* Some pulses use calibration sequences, but the helper to produce
those does not yet work.


Note that the unit tests defined in `tests/test_QGL2_Sequences.py` do
not currently work.
- Supply `-C` to use a test channel library, or supply a Channel
Library name to load from a file (see QGL / Auspex documentation).
- QGL2 function should be rewritten to require no arguments. See the
sample in `Rabi.py` - `SingleShotNoArg`
10 changes: 3 additions & 7 deletions doc/compiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
3. *Inliner* - Iteratively (up to 20 times) try to inline things until the program stops changing. (Note that we don’t have a mechanism to ask for a piece of code NOT to be inlined.)
4. *EvalTransformer* - Evaluate each expression.
5. Replace bindings with their values from evaluation.
6. Group code into sets of qubits acted upon
1. MarkReferencedQbits
2. AddSequential
3. QbitGrouper2 - why two steps?
7. *Flattener* - Flatten out repeat, range, ifs... Qiter, Qfor, with concur
8. *SequenceCreator* - Inject barriers
9. *SequenceExtractor* - Produce QGL1 sequence function
6. *Flattener* - Flatten out repeat, range, ifs... Qiter, Qfor, etc
7. *SequenceExtractor* - Produce QGL1 sequence function

32 changes: 6 additions & 26 deletions doc/restrictions.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Some current limitations of the QGL2 language
- including ways it is not Python

Note that for the latest set of known issues or planned enhancements,
see [https://github.com/BBN-Q/pyqgl2/issues].

* In general, *args and **kwargs are not well handled - for type
checking arguments, etc
* QGL2 looks at variables named `QBIT_*` as canonical qbits. Another
variable that happens to have that name might cause problems. See
issue #77.
variable that happens to have that name might cause problems.
* qgl2decl method declarations cannot be nested
* Make all functions top level functions
* Methods with a return statement are not inlined
Expand All @@ -15,35 +17,13 @@ Some current limitations of the QGL2 language
from qgl2.basic_sequences.qgl2_plumbing import init
* QGL2 uses read-only qubits, so you can read their
parameters, but cannot edit them. Note also that the full QGL
ChannelLibrary is not generally available. See issue #76.
* QGL2 main function cannot take arguments, specifically Qubits. See
issue #62.
ChannelLibrary is not generally available. See issue #37.
* There is no current good way to do control flow based on measurement
results, particularly measurements from a different channel. This
will change. See issue #66.
* Do not use QGL1 control flow functions directly. Use python to set
up your control flow.
* Do not use QGL1 functions that return a list of pulses. Much better
(and may be soon required) to rewrite that as a QGL2 function. Issue #79.
will change. See issue #24.
* Do not use a QGL2 function where a pure python function will do;
using QGL2 is slower / less efficient.

Things to fix:

* 'label' argument to Qubit() must be a literal string - no variable
whose value is a string, no expression, etc. Issue #75.
* EG see `test_Sequences` which loops over qbit names. That won't work.
* A Qubit() creation is only recognized if it is in an assignment. EG
x = Qubit("alabel") works, but
return Qubit("alabel") does not. Issue #75.
* Various ways to read & use file contents (like `with open`)
fail. See issue #67, 68, 69.
* QGL2 performance must be improved.
* QGL2 does not currently use repeat blocks, in part to avoid repeat
blocks that contain a barrier. Issue #74
* Provide way to give arguments to `compile_function` as arguments to
the function being compiled. Issue #50.

Other to do items for QGL2:

* Need to do more error checking on arguments other than qbit
Expand Down
Loading

0 comments on commit 923e2a2

Please sign in to comment.