DevelopersHiQ / Language
HiQ Objects
Classes and interfaces with exactly one main block. Every object is resolved at compile time: objects flatten to named qubits and variables, every call inlines and dispatch is static.
- .qcos3
- qcos-l3/0
- Classes, interfaces and one main block
- Lowers to HiQ Script
A HiQ Objects program is classes, interfaces and exactly one main block. There is no program line. Comments start with // or #. Every object is resolved at compile time: objects flatten to named qubits and variables, every call inlines, and dispatch is static.
class Bell { public qubit a public qubit b public bit ma public bit mb public def prepare() { h a cx a, b } public def read() { measure a -> ma measure b -> mb }}main { Bell pair pair.prepare() pair.read()}Classes and interfaces
| Form | Meaning |
|---|---|
interface Oracle { def mark(target: qubit) } | Method signatures |
class Name(params) extends Base(args) implements A, B { ... } | A class. All the clauses are optional |
abstract class Name { abstract def f() } | Cannot be instantiated |
qubit x, qubit x[n], bit c, uint8 n = 3, int8 n | Fields |
Class y(args), Class ys[n](args) | Object fields and arrays of objects |
public, override, abstract before def | Method modifiers, in any order |
def init() { ... } | Runs once, after the object is built |
Fields and methods are visible to the class and its heirs unless public. A local object is declared the same way inside main or a method.
Parameters
int and float parameters are compile-time values. qubit, bit, uintN, intN, their arrays, classes and interfaces bind by reference. A classical expression binds by value into a new variable.
Statements
| Form | Meaning |
|---|---|
h a, rz(pi / 2) a, cx a, b | A gate |
measure q -> c, reset q | Measure and reset |
x = y + 1 | Assignment |
qubit t, uint8 n = 0 | A local declaration. A local qubit lives until the end of its scope |
if c { } else { }, match x { 0 => { } _ => { } }, while c budget 8 { } | Control flow |
for i in 0..n step 1 { } | Always unrolled, stop excluded |
within { } do { }, inverse { } | Compute and uncompute, and inversion of a gate block |
obj.method(args), self.method(args), super.method(args) | Calls |
There are no return values: values travel through fields and arguments. There is no controlled block. Recursion is refused (l3.recursion, l3.recursive_class). A class or interface cannot take a gate's name.
Idioms
Polymorphism through an interface:
interface Oracle { def mark(target: qubit) }class Flip implements Oracle { public def mark(target: qubit) { x target }}class Runner(oracle: Oracle) { public qubit t public bit r public def run() { oracle.mark(t) measure t -> r }}main { Flip flip Runner runner(flip) runner.run()}An array of objects, a parameterised rotation, and feedback:
class Cell(angle: float) { public qubit q public bit m public def spin() { ry(angle) q } public def read() { measure q -> m }}class Chain(n: int) { public Cell cells[n](pi / 4) public def run() { for i in 0..n { cells[i].spin() } cells[0].read() if cells[0].m { x cells[1].q } }}main { Chain chain(2) chain.run()}Refused, with the code
class Empty { public qubit q}class Bad { public qubit q public def go() { foo q }}main { Bad b b.go()}Examples in this layer
- Grover with oracle objectsAny class that implements Oracle can be searched for.examples/l3/grover_oracles.qcos3
- Register QFTThe Fourier transform as a class over a register.examples/l3/register_qft.qcos3
- Repetition codeA bit-flip code as a class, and a subclass that adds an error.examples/l3/repetition_code.qcos3