Skip to content

Commit

Permalink
elaborate on pragma functionality in RST docs (rigetti#409)
Browse files Browse the repository at this point in the history
* elaborate on pragma functionality in RST docs

* clarification pursuant to PR feedback
  • Loading branch information
ecpeterson authored and mpharrigan committed Apr 23, 2018
1 parent 9e3e8e5 commit 9d9448f
Showing 1 changed file with 103 additions and 11 deletions.
114 changes: 103 additions & 11 deletions docs/source/compiler.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,123 @@ connection object is used instead. The compiled program can be accessed after a
submitted to the QPU by using the ``.compiled_quil()`` accessor method on the resulting ``Job``
object instance.


Region-specific compiler features through PRAGMA
------------------------------------------------

The Quil compiler can also be communicated with through ``PRAGMA`` commands embedded in the Quil
program.

+ It can be circumvented in user-specified regions. The start of such a region is denoted by
``PRAGMA PRESERVE_BLOCK``, and the end is denoted by ``PRAGMA END_PRESERVE_BLOCK``.
The Quil compiler promises not to modify any instructions contained in such a region.
+ It can sometimes arrange gate sequences more cleverly if the user gives it hints about
sequences of gates that commute. A region containing commuting sequences is bookended by
``PRAGMA COMMUTING_BLOCKS`` and ``PRAGMA END_COMMUTING_BLOCKS``; within such a region, a
given commuting sequence is bookended by ``PRAGMA BLOCK`` and ``PRAGMA END_BLOCK``.
The following snippet demonstrates this hinting syntax:

Preserved regions
~~~~~~~~~~~~~~~~~

The compiler can be circumvented in user-specified regions. The start of such a region is denoted by
``PRAGMA PRESERVE_BLOCK``, and the end is denoted by ``PRAGMA END_PRESERVE_BLOCK``. The Quil
compiler promises not to modify any instructions contained in such a region.

The following is an example of a program that prepares a Bell state on qubits 0 and 1, then performs
a time delay to invite noisy system interaction before measuring the qubits. The time delay region
is marked by ``PRAGMA PRESERVE_BLOCK`` and ``PRAGMA END_PRESERVE_BLOCK``; without these delimiters,
the compiler will remove the identity gates that serve to provide the time delay. However, the
regions outside of the ``PRAGMA`` region will still be compiled, converting the Bell state preparation
to the native gate set.

.. code:: python
# prepare a Bell state
H 0
CNOT 0 1
# wait a while
PRAGMA PRESERVE_BLOCK
I 0
I 1
I 0
I 1
# ...
I 0
I 1
PRAGMA END_PRESERVE_BLOCK
# and read out the results
MEASURE 0 [0]
MEASURE 1 [1]
Parallelizable regions
~~~~~~~~~~~~~~~~~~~~~~

The compiler can sometimes arrange gate sequences more cleverly if the user gives it hints about
sequences of gates that commute. A region containing commuting sequences is bookended by
``PRAGMA COMMUTING_BLOCKS`` and ``PRAGMA END_COMMUTING_BLOCKS``; within such a region, a given
commuting sequence is bookended by ``PRAGMA BLOCK`` and ``PRAGMA END_BLOCK``.

The following snippet demonstrates this hinting syntax in a context typical of VQE-type algorithms:
after a first stage of performing some state preparation on individual qubits, there is a second
stage of "mixing operations" that both re-use qubit resources and mutually commute, followed by a
final rotation and measurement. The following program is naturally laid out on a ring with vertices
(read either clockwise or counterclockwise) as 0, 1, 2, 3. After scheduling the first round of
preparation gates, the compiler will use the hinting to schedule the first and third blocks (which
utilize qubit pairs 0-1 and 2-3) before the second and fourth blocks (which utilize qubit pairs 1-2
and 0-3), resulting in a reduction in circuit depth by one half. Without hinting, the compiler will
instead execute the blocks in their written order.

.. code:: python
# Stage one
H 0
H 1
H 2
H 3
# Stage two
PRAGMA COMMUTING_BLOCKS
PRAGMA BLOCK
CZ 0 1
CNOT 0 1
RZ(0.4) 1
CNOT 0 1
PRAGMA END_BLOCK
PRAGMA BLOCK
CNOT 1 2
RZ(0.6) 2
CNOT 1 2
PRAGMA END_BLOCK
PRAGMA BLOCK
CZ 1 2
CNOT 2 3
RZ(0.8) 3
CNOT 2 3
PRAGMA END_BLOCK
PRAGMA BLOCK
CZ 0 2
CNOT 0 3
RZ(0.9) 3
CNOT 0 3
PRAGMA END_BLOCK
PRAGMA END_COMMUTING_BLOCKS
# Stage three
H 0
H 1
H 2
H 3
MEASURE 0 [0]
MEASURE 1 [1]
MEASURE 2 [2]
MEASURE 3 [3]
Rewirings
~~~~~~~~~

When a Quil program contains multi-qubit instructions that do not name qubit-qubit links present on a
target device, the compiler will rearrange the qubits so that execution becomes possible. In order to
help the user understand what rearrangement may have been done, the compiler emits two forms of
``PRAGMA``: ``PRAGMA EXPECTED_REWIRING`` and ``PRAGMA CURRENT_REWIRING``. From the perspective of the
user, both ``PRAGMA`` instructions serve the same purpose: ``PRAGMA ..._REWIRING "#(n0 n1 ... nk)"``
indicates that the logical qubit labeled ``j`` in the program has been assigned to lie on the physical
qubit labeled ``nj`` on the device. This is strictly for human-readability: user-supplied instructions
of the form ``PRAGMA ..._REWIRING`` are discarded and have no effect.

.. WARNING::

The compiler **will not** rearrange qubits in programs which already map perfectly onto the
target device, leaving it entirely up to the user to select high-fidelity configurations of
qubits.


Common Error Messages
Expand Down

0 comments on commit 9d9448f

Please sign in to comment.