GithubHelp home page GithubHelp logo

quil-lang / quil Goto Github PK

View Code? Open in Web Editor NEW
103.0 18.0 16.0 409 KB

Specification of Quil: A Practical Quantum Instruction Set Architecture

Home Page: https://quil-lang.github.io/

License: Apache License 2.0

ANTLR 1.88% TeX 72.45% Common Lisp 4.45% CSS 0.28% Assembly 20.54% Emacs Lisp 0.40%
forest quil quantum-computing quantum-programming

quil's Introduction

Quil: A Portable Quantum Instruction Language

DOI

This repository contains the reference specification for the Quil language in addition to some useful extras outlined below.

The current version of the spec can be browsed here.

Repository layout:

  • /examples: examples of Quil
  • /grammars: example grammars used by parser generators
  • /paper: the source and rendered files for the Quil reference paper, by Smith et al
  • /rfcs: proposals for adding features or changing Quil
  • /spec: the Quil language specification

Known Usages

The following is a list of known usages of the Quil language. Open a pull request to add your own to this list.

Language bindings:

  • PyQuil: A library for easily generating Quil programs to be executed using the Rigetti Forest SDK

Compilers:

  • quilc: The Rigetti optimizing Quil compiler

Simulators:

  • qvm: The Rigetti high-performance quantum virtual machine

quil's People

Contributors

appleby avatar braised-babbage avatar ecpeterson avatar erichulburd avatar jmbr avatar kalzoo avatar macrologist avatar notmgsk avatar spin1half avatar stevenheidel avatar stylewarning avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quil's Issues

CI job for spec grammar validation

Currently, the Quil spec contains EBNF grammar as well as examples of valid and invalid program instructions. Examples are often the most intuitive way to get a quick understanding of the grammatical and syntactical rules a glance. Inaccurate documentation can lead to mistrust of the specification. Additionally, the strictness of a well defined and valid grammar provides a valuable source of truth for downstream parsers (see the many parser generators that support EBNF on Wikipedia's comparison of parser generators). We may want to consider a CI step that validates the grammar and examples.

While writing some of the examples in #69 I used https://mdkrajnak.github.io/ebnftest/ to validate both the proposed grammar as well as valid / invalid examples.

@stylewarning also suggested that examples could be validated by using the Quilc Lisp parser.

Improve Quilt RFC

Related to rigetti/pyquil#1257, which will by default serve as the reference implementation of Quilt.

Mismatches between RFC and implemented grammar:

  • OpModifier used in place of GateModifier: CalibrationDefinition :: DEFCAL OpModifier* Name ( Parameter+ ) Qubit+ : Instruction+
  • SetPhase :: SET-PHASE Frame Float should be SetPhase :: SET-PHASE Frame Expression to match grammar
  • The inline spec for DEFCAL MEASURE shows a Name: MeasureCalibrationDefinition :: DEFCAL Name Qubit? Parameter : Instruction+, but the example doesn't match that spec: DEFCAL MEASURE 0 %dest:, and the implemented grammar is defMeasCalibration : DEFCAL MEASURE qubitOrFormal ( name )? COLON ( NEWLINE TAB instr )* ; which disagrees with both (example shows a variable not name)

Doc Improvements & Bugfixes:

  • No DEFFRAME example
  • Raw-capture example uses CAPTURE keyword: CAPTURE 0 "out" 200e-6 iqs
  • Example for DEFCAL MEASURE missing MEASURE
  • Typo: There is also support for shifted the phase
  • Are all frame attributes optional in a DEFFRAME?
  • Frame attribute CENTER-FREQUENCY missing in spec but present in grammar
  • LT instruction in example not described in spec (here or in main spec): LT %dest iq[0] 0.5 # thresholding

Spec improvements:

  • DELAY grammar is the only item which requires left recursion, because the required expression could match as an identifier. Is that worth reconsideration?
  • DEFCIRCUIT includes CircuitGates within its instruction block, which is the version of Gate with variable qubits. DELAY and FENCE, though, just allow variable qubits in the base instruction instead of a distinct CircuitDelay or CalibrationDelay. Is it worth reconsideration of CircuitGate to collapse it with Gate for consistency?

Allow single-quoted strings for PRAGMA

In Quil-T we make use of PRAGMA FILTER-NODE which expects a json-like string object. For example

PRAGMA FILTER-NODE raw "{'key': 'value', ...}"

The problem is, however, single-quoted strings are not valid JSON, so the above would have to be written

PRAGMA FILTER-NODE raw "{\"key\": \"value\", ...}"

which is awkward and error-prone when writing by-hand.

If we supported using single quotes for the pragma freeform string then the above would become

PRAGMA FILTER-NODE raw '{"key": "value", ...}'

@stylewarning WDYT?

Spec is not clear about volatility of memory

In actually using Quil, it is assumed that memory is shared a classical processor, and thus can change at any time. Implementations must not presently assume memory is only modified by a Quil program.

Clarification: Standard function definitions

The Quil spec references the cis function in an example for DEFGATE:

The definition of CAN can be written as the following Quil matrix definition:

DEFGATE CAN(%alpha, %beta, %gamma):
    (cis((%alpha+%beta-%gamma)/2)+cis((%alpha-%beta+%gamma)/2))/2, 0, 0, (cis((%alpha-%beta+%gamma)/2)-cis((%alpha+%beta-%gamma)/2))/2
    0, (cis((%alpha+%beta+%gamma)/(-2))+cis((%beta+%gamma-%alpha)/2))/2, (cis((%alpha+%beta+%gamma)/(-2))-cis((%beta+%gamma-%alpha)/2))/2, 0
    0, (cis((%alpha+%beta+%gamma)/(-2))-cis((%beta+%gamma-%alpha)/2))/2, (cis((%alpha+%beta+%gamma)/(-2))+cis((%beta+%gamma-%alpha)/2))/2, 0
    (cis((%alpha-%beta+%gamma)/2)-cis((%alpha+%beta-%gamma)/2))/2, 0, 0, (cis((%alpha+%beta-%gamma)/2)+cis((%alpha-%beta+%gamma)/2))/2

If I understand correctly: cis, sin, cos, exp, and sqrt` are all standard functions that can be used in (at least) gate definitions, but they don't appear in the spec outside of the above example. It would be nice to document their existence, where they can be used, and if they are treated like other keywords.

[Quil-T] Allow zero-qubit-count frames

Currently, the Quil-T "RFC" and defacto spec calls for one or more qubits in a frame identifier:

FrameName :: String
Frame :: Qubit+ FrameName

There have been calls from certain power users, to include @bramathon and @caldwellshane, to open up this definition somewhat to allow for frames which do not map to qubits. This is important in making Quil-T more flexible for heterogenous execution architectures. We should consider this.

This may be as simple as downgrading the plurality of Qubit in Frame to Qubit* and validating that this does not open up ambiguous parsing behavior.

Introduce a modulo operator

Tracking a value modulo 2*pi is a relatively useful thing to do, perhaps Quil's expressions should be extended to include a modulo operator.

Since % is already used for variables this wouldn't be a good choice. Instead we could:

  • introduce a function mod(dividend, divisor), although this would be the first named function in quil with >1 arguments
  • introduce some other symbol (maybe \)

Add DEFGATE AS CIRCUIT

It Would Be Nice to define gates by some circuit decomposition. This is different than DEFCIRCUIT since those are simply for expansion and not meant to represent "Gates".

DEFGATE CZ p q AS CIRCUIT:
    H p
    CNOT p q
    H p

This is not a DEFCIRCUIT! This is the expression of a unitary operation (which is not expanded!) as a sequence of gates.

Concrete qubit indices shouldn't be allowed.

local oscillators are not mentioned

In proposal.md the following line appears

Sample rates, local oscillators, timing, doesn't this all seem pretty hardware specific??

(apparently it is not possible on github to link from here to a line number in a markdown file)
But the word oscillator does not otherwise appear in this repo. Maybe this is cruft referring to deleted material ?

Remove the old spec

Some folks come to this repo and find ./spec/Quil.md as the spec, which is actually fairly out-of-date with the real spec (under ./specgen or quil-lang.github.io).

It would be helpful if ./spec was removed, and the README pointed to quil-lang.github.io.

Incorrect NONBLOCKING Example?

Background

In the Quil-T proposal / de facto spec, there's these two following lines:

Re: blocking pulses:

The execution of a pulse operation on a frame blocks pulse operations on intersecting frames, i.e. frames with a qubit in common with the pulse frame.

Re: nonblocking pulses:

A pulse operation (PULSE, CAPTURE, and RAW-CAPTURE) with the NONBLOCKING modifier does not exclude pulse operations on other frames.

Then there's this example:

NONBLOCKING PULSE 0 "xy" flat(duration: 1.0, iq: 1.0)
PULSE 0 1 "ff" flat(duration: 1.0, iq: 1.0)

with the description

the two pulses could be emitted simultaneously. Nonetheless, a NONBLOCKING pulse does still exclude the usage of the pulse frame, so e.g. NONBLOCKING PULSE 0 "xy" ... ; PULSE 0 "xy" ... would require serial execution.

Problem

This is not inherently inconsistent, and can be implemented as-is. However, it adds complexity and possibly confusion for the program author, in that the behavior of the blocking PULSE is modified by the NONBLOCKING modifier on the earlier PULSE. I'll refer to these (from the cited example) as instruction [0] and [1]. I'd propose that the behavior of the blocking PULSE - that it is the only instruction executing on all common-qubit frames - should not be modified by other instructions in the program.

In this case, [0] uses only 0 "xy" but does not use or block any other frames. However, [1] still blocks 0 "xy" because it is not NONBLOCKING. In my opinion, that should mean that these two instructions cannot be scheduled concurrently.

The metaphor: [0] sits at the table, occupies a seat, but doesn't reserve any other seats. [1] sits at the table but wants to reserve a number of seats, and [0] is sitting in one of those seats. Just because [0] doesn't care doesn't mean that the two are compatible and can sit together at the table, and thus (escaping the metaphor) doesn't mean that the two should run concurrently.

Proposal

I can ship an MR to this effect depending on feedback, but I'd change the example to specifically include the concurrent pulse-and-capture pattern used in readout, and to retain this example but as a counterexample and clarify that the two would not be concurrent.

I'd also add the verbiage:

Within an instruction block, an instruction which uses a frame must start execution after all previous instructions which use or block that frame, and complete execution before all later instructions which use or block that frame.

Specify inline anonymous gates

It Would Be Nice if not every gate needed a name. The compiler + QVM have internal representations of nameless gates, and these should be exposed as a part of the language, perhaps.

DEFCAL definition is inconsistent with the examples

The spec's definition of DEFCAL is

⟨Calibration Definition⟩ ::= DEFCAL ⟨Modifier⟩*⟨Identifier⟩ ( ⟨Parameters⟩ ) ⟨Qubit⟩+ : ⟨Instruction⟩+

The spec then uses these as examples

DEFCAL RX(%theta) %qubit:

...

DEFCAL RZ(%theta) %qubit:
    SHIFT-PHASE %qubit "xy" %theta

In particular, both use the % prefix for the qubit name. However, the definition uses ⟨Qubit⟩ as the type, which restricts values to non-negative integers.

I think there are two problems here:

  • DEFCAL should take ⟨Formal Qubit⟩ which would allow identifiers (e.g. DEFCAL I q: ...)
  • The examples should remove the % prefix where applicable

Controlled Gate Modifier and global phases

Global phase is a typically benign side effect that may vary between two functionally identical quantum gates. Two states A B (or unitaries/gates) are said to be "equivalent up to a global phase" if A = cB where c is a number of the form e^(i*theta) for any real theta. Furthermore, the bloch sphere representation for the state of a single qubit is invariant to global phase, as a consequence, representing single qubit gates as "rotations about the bloch sphere" are also invariant to global phase.

For example:
The S gate is defined as a 90 degree rotation about the Z axis of the bloch sphere:

DEFGATE S:
    1, 0 
    0, i

The RZ gate can be defined by a pauli sum, but notice that the unitary for the RZ(pi/2) is only equivalent to the canonical S matrix up to a global phase (in this case, the phase is e^(i*pi/4) = (1 + i)/sqrt(2)):

Screen Shot 2022-04-12 at 4 04 38 PM

Quil defines the CONTROLLED gate modifier in the following manner:

Screen Shot 2022-04-12 at 4 07 34 PM

The key here is that a global phase mismatch for two unitaries (A, B) will result in a local phase mismatch if they are used in a "controlled" manner. More specifically CONTROLLED S and CONTROLLED RZ(pi/2) have observably different properties (are not equivalent up to a global phase) despite the fact that T and RZ(pi/2) do not have observably different properties (only a global phase mismatch).

There are some ideas floating around about how to deal with this, but there does not seem to be an obvious best solution.

Add if statements to Quil

Instead of this:

MEASURE 0 ro
JUMP-WHEN ro @DELAY
RX(pi) 0
JUMP @END
LABEL DELAY
DELAY(60e-9) 0
LABEL END

We could have this:

MEASURE 0 ro
IF ro:
    RX(pi) 0
ELSE:
    DELAY(60e-9) 0

Documentation/spec overhaul

  • Update spec to document any new additions
  • Up-to-date grammar (with tests) for spec
  • Pull RFCs into spec
  • Versioned spec
  • Website presenting up-to-date spec

Provide instruction-based semantics for parameter arithmetic

This refers to interpreting gate parameters as actual sequences of Quil instructions. For example,

RX(2*a) 0

is presently not very meaningful as a linear list of instructions. It could be interpreted as something like

temp = a
temp *= 2
RX(temp) 0

but Quil doesn't say.

Proposed DEFCAL semantics incompatible with current DEFGATE / DEFCIRCUIT semantics

For DEFGATE and DEFCIRCUIT, the order of definitions is irrelevant; if there are multiple top-level definitions the behavior at gate/circuit application is undefined. As discussed elsewhere, this is convenient for the parser, since it does not need to keep positions of definitions and can worry about name resolution after parsing raw quil.

The proposed DEFCAL semantics:

Calibrations can be parameterized and include concrete values, which are resolved in "Haskell-style", with later definitions being prioritized over earlier ones.

This is incompatible with the current machinery.

Here are a few options:

  • The behavior is undefined when there are multiple DEFCAL with the same name. personally, I think this is too strict.

  • We adopt the last-to-first convention, but behavior is only well-defined if all DEFCAL are in the same .quil file. This is workable but feels like a hack.

  • We adopt something like a most-specific-first convention, where calibration definitions are ordered by the number of constant params/args, ordered left-to-right, and the behavior is otherwise ill-specified.

To elaborate on the latter:
RX(pi/2) 0
could match (ordered by priority):

DEFCAL RX(pi/2) 0: 
    ...
DEFCAL RX(%theta) 0:
    ...
DEFCAL RX(pi/2) %theta:
    ...
DEFCAL RX(%theta) %qubit:
    ...

regardless of the position of these declarations in the source file.

Introduce DEFGATE by exponentiated Hamiltonian

There is an internal proposal for a construct DEFEXPI, which allows gate definition via an exponentiated Pauli sum. The proposed syntax for a definition of CPHASE, for instance, was:

DEFEXPI CPHASE(%alpha) p q:
    Z(-%alpha) p
    Z(-%alpha) q
    ZZ(%alpha) p q

The block header contains the name of the gate to be defined, a (real) parameter list, and qubit indices. Each line in the body of the block consists of a Pauli word (formed from I, X, Y, Z), a parameter indicating a scalar prefactor, and a list of qubits to each the letters from the Pauli word are applied. (If a qubit does not appear in the list, we implicitly apply I to that qubit.) The CPHASE example is then shorthand for

$$CPHASE(\alpha) = \exp(-i \alpha (ZZ - IZ - ZI)).$$

TODO items:

  • Since this proposal, we've introduced the construct DEFGATE ... AS ... into Quil, and so it would be preferable to drop the new top-level keyword DEFEXPI in favor of a new DEFGATE type, like EXPONENTIATED-HAMILTONIAN or PAULI-SUM or so.
  • In the original proposal, there was some lingering confusion as to how to represent constant terms in a Hamiltonian. From the perspective of the execution semantics of the quantum programming language, this is immaterial: a constant term contributes only global phase, and so can be safely elided. In the interest of user ergonomics, it's less clear that this elision should forced at the level of the language specification.

Consideration for expanding logicalBinaryOp definition

While working on a parser implementation in quil-rust, it struck me that the INT alternative of the right-hand operand in a logical binary operation could possibly be further specified & wanted to get some thoughts. For reference:

logicalBinaryOp     : ( AND | OR | IOR | XOR ) addr ( addr | INT ) ;
// ...
INT                 : [0-9]+ ;
  1. Is it reasonable to introduce a BIT definition which would reduce the range of values to 1 or 0? @kalzoo mentioned we can (maybe already do?) coerce an INT when needed so maybe this isn't necessary.
  2. Is there a case for parsing an expression in this position?

Documentation around DELAY feels unclear

The proposal says

A DELAY instruction is equivalent to a NONBLOCKING no-operation on all specified frames. For example, DELAY 0 "xy" 1.0 delays frame 0 "xy" by one second.

If the DELAY instruction presents a list of qubits with no frame names, all frames on exactly these qubits are delayed. Thus DELAY 0 1.0 delays all one qubit frames on qubit 0, but does not affect 0 1 "cz".

The pyquil docstring for DELAY says

def DELAY(*args) -> Union[DelayFrames, DelayQubits]:
    """
    Produce a DELAY instruction.

    Note: There are two variants of DELAY. One applies to specific frames on some
    qubit, e.g. `DELAY 0 "rf" "ff" 1.0` delays the `"rf"` and `"ff"` frames on 0.
    It is also possible to delay all frames on some qubits, e.g. `DELAY 0 1 2 1.0`.

    :param args: A list of delay targets, ending with a duration.
    :returns: A DelayFrames or DelayQubits instance.
    """

The proposal definition seems to not exclude the following which delays specific frames on a number of qubits: DELAY q1 q2 ... qN f1 f2 ... fM <delay>. The second definition however does exclude that.

Questions:

  • Is it correct that the example above should be an error.
  • If yes -- why? Seems like an odd use case to exclude, so I wonder if there is a reason that is not obvious to me?

DEFWAVEFORM grammar: spec != implementation

Normally, this might mean fixing the implementations to match the spec, but in this case it seems more reasonable to align the spec to what's used in practice.

Moved from rigetti/pyquil#1429:

This may be a bug in the spec, as the grammar implemented here in pyQuil is in live use, but:

Spec: https://github.com/quil-lang/quil/blob/master/rfcs/analog/spec_changes.md#defining-new-waveforms

Note the sample rate, which is missing from the grammar here (and in practice)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.