DevelopersHiQ / Use it
Examples
Every example program in the language repository, with full source. Each one passes the checker and states its expected result in its first comment. Copy one into a file and check it with softqcos lang check.
- 24 programs
- Apache-2.0 once the repository opens
HiQ Assembly
For exact control of every gate, measurement and branch.
Bell pair
Two qubits whose measurements always agree.
// Bell pair: the two measurements always agree.program bellqubits a, bbits m0, m1h acx a, bmeasure a -> m0measure b -> m1GHZ state
Four qubits that read 0000 or 1111.
// GHZ state on four qubits: all bits read 0000 or 1111.program ghzqubits q[4]bits m[4]h q[0]cx q[0], q[1]cx q[1], q[2]cx q[2], q[3]repeat i in 0..4 { measure q[i] -> m[i]}Teleportation
Move a state with two measurements and real-time corrections.
// Teleportation: the state ry(pi / 3)|0> moves from msg to bob,// using two measurements and real-time corrections.program teleportqubits msg, alice, bobbits m0, m1, outry(pi / 3) msg// Shared Bell pair between alice and bob.h alicecx alice, bob// Bell measurement on msg and alice.cx msg, aliceh msgmeasure msg -> m0measure alice -> m1// Corrections decided at run time.if m1 { x bob}if m0 { z bob}measure bob -> outSuperdense coding
Two classical bits carried by one qubit of an entangled pair.
// Superdense coding: two classical bits travel on one qubit.// Alice applies z to set b0 and x to set b1; here she sends b0 = 0, b1 = 1.program superdensequbits alice, bobbits b0, b1h alicecx alice, bob// Encode b1 = 1 with x. A z here would also set b0.x alicecx alice, bobh alicemeasure alice -> b0measure bob -> b1Deutsch-Jozsa
Constant or balanced, in one query.
// Deutsch-Jozsa with a balanced oracle f(x) = x0 xor x1 xor x2.// A constant oracle reads 000; this one never does.program deutsch_jozsaqubits x[3], ybits m[3]x yh yrepeat i in 0..3 { h x[i]}// Oracle: y ^= f(x).repeat i in 0..3 { cx x[i], y}repeat i in 0..3 { h x[i] measure x[i] -> m[i]}Bernstein-Vazirani
Read a hidden string in one query.
// Bernstein-Vazirani: recover the hidden string s = 101 in one query.program bernstein_vaziraniqubits x[3], ybits m[3]x yh yrepeat i in 0..3 { h x[i]}// Oracle for s = 101: y ^= x0 xor x2.cx x[0], ycx x[2], yrepeat i in 0..3 { h x[i] measure x[i] -> m[i]}Grover search
Find the marked state 11 in one iteration.
// Grover search on two qubits for the marked state 11.// One iteration finds it with certainty.program groverqubits a, bbits ma, mbroutine diffusion(p, q) { within { h p h q x p x q } do { cz p, q }}h ah b// Oracle: phase flip on 11.cz a, bcall diffusion(a, b)measure a -> mameasure b -> mbPhase estimation
Read the phase of an eigenstate into a register.
// Phase estimation of the T gate (phase 1/8) with three counting qubits.// The counting register reads 001 (read backwards: 0.001 in binary = 1/8).program phase_estimationqubits c[3], targetbits m[3]x targetrepeat i in 0..3 { h c[i]}// Controlled T^(2^k): c[0] applies T once, c[1] twice, c[2] four times.cp(pi / 4) c[0], targetcp(pi / 2) c[1], targetcp(pi) c[2], target// Inverse QFT on the counting register.swap c[0], c[2]h c[0]cp(-pi / 2) c[1], c[0]h c[1]cp(-pi / 4) c[2], c[0]cp(-pi / 2) c[2], c[1]h c[2]repeat i in 0..3 { measure c[i] -> m[i]}Repeat until success
Try again until a measurement reads 1, within a budget of 16.
// Repeat until success: try again until the ancilla reads 1, at most 16 times,// counting the attempts, then act on the count.program repeat_until_successqubits a, ancbits muint8 attemptswhile !m budget 16 { h anc measure anc -> m reset anc attempts = attempts + 1}match attempts { 1 => { x a } 2, 3 => { z a } _ => { h a }}Fourier transform
The quantum Fourier transform on three qubits, applied to 101.
// Quantum Fourier transform on three qubits, applied to the basis state 101.program qftqubits q[3]bits m[3]routine qft3(a, b, c) { h a cp(pi / 2) b, a cp(pi / 4) c, a h b cp(pi / 2) c, b h c swap a, c}x q[0]x q[2]call qft3(q[0], q[1], q[2])repeat i in 0..3 { measure q[i] -> m[i]}Parity with one ancilla
Each check allocates, measures and releases one reused qubit.
// Parity checks with one reused ancilla: each check allocates a fresh// qubit, measures it and releases it with a reset, so the peak is the data// qubits plus one, not plus two.program parity_ancillaqubits d[3]bits syndrome[2]x d[1]alloc anccx d[0], anccx d[1], ancmeasure anc -> syndrome[0]release anc resetalloc anccx d[1], anccx d[2], ancmeasure anc -> syndrome[1]release anc resetHiQ Script
For experiments that measure, decide and try again.
Fourier transform
The quantum Fourier transform with constants and loops.
# Quantum Fourier transform on N qubits, for any N of 2 or more.# The controlled phase between qubits i and j is pi / 2^(j - i).program qftconst N = 4const HALF = N >> 1qubit q[N]bit m[N]x q[0]for i = 0 to N - 2 h q[i] for j = i + 1 to N - 1 cp(pi / (1 << (j - i))) q[j], q[i] nextnexth q[N - 1]for i = 0 to HALF - 1 swap q[i], q[N - 1 - i]nextfor i = 0 to N - 1 measure q[i] into m[i]nextRepetition code
Encode, inject an error, read the syndrome and correct it.
# Three-qubit bit-flip code: encode, inject one error, measure the two# parities with a reused ancilla, and correct from the syndrome.program repetition_codequbit d[3]bit s[2], out[3]uint8 syndrome = 0# Encode |1> as |111>.x d[0]cx d[0], d[1]cx d[0], d[2]# The error: a flip on the middle qubit.x d[1]for i = 0 to 1 alloc anc cx d[i], anc cx d[i + 1], anc measure anc into s[i] free anc resetnextif s[0] then let syndrome = syndrome + 1endif s[1] then let syndrome = syndrome + 2endselect syndrome case 1: x d[0] case 3: x d[1] case 2: x d[2]endfor i = 0 to 2 measure d[i] into out[i]nextParallel preparation
Tasks on disjoint qubits, checked so the order cannot matter.
# Two independent preparations written as tasks. The checker proves they# share no qubit and no variable, so the reported depth overlaps them.program parallel_preparationqubit a[2], b[2]bit ma[2], mb[2]parallel task bell_a h a[0] cx a[0], a[1] end task bell_b h b[0] cx b[0], b[1] endendfor i = 0 to 1 measure a[i] into ma[i] measure b[i] into mb[i]nextGHZ state
GHZ on N qubits. Change N and nothing else.
# GHZ state on N qubits. Change N and nothing else.program ghzconst N = 5qubit q[N]bit m[N]h q[0]for i = 0 to N - 2 cx q[i], q[i + 1]nextfor i = 0 to N - 1 measure q[i] into m[i]nextBernstein-Vazirani
The hidden string 1011 read in one query, with a loop over N bits.
# Bernstein-Vazirani on N bits: the oracle adds every bit of x where the# hidden string s has a 1. Here s = 1011, read as q[0] q[1] q[2] q[3].program bernstein_vaziraniconst N = 4qubit x[N], ybit m[N]x yh yfor i = 0 to N - 1 h x[i]nextcx x[0], ycx x[2], ycx x[3], yfor i = 0 to N - 1 h x[i] measure x[i] into m[i]nextGrover search
Three qubits, marked state 111, two iterations.
# Grover search on three qubits for the marked state 111.# Two iterations find it with probability about 0.95.program groverconst N = 3const ROUNDS = 2qubit q[N]bit m[N]sub diffusion(a, b, c) compute h a h b h c x a x b x c do ccz a, b, c endendfor i = 0 to N - 1 h q[i]nextfor r = 1 to ROUNDS ccz q[0], q[1], q[2] call diffusion(q[0], q[1], q[2])nextfor i = 0 to N - 1 measure q[i] into m[i]nextRepeat until success
Run the body, then try again until a measurement reads 1, at most eight times.
# Repeat until success in L2: run the body, then try again until the# measurement reads 1, at most eight times in total.program repeat_until_successqubit a, ancbit muint8 tries = 0repeat h anc measure anc into m reset anc let tries = tries + 1until m limit 8if m and tries <= 2 then x aendHiQ Objects
For algorithm libraries and reusable building blocks.
Grover with oracle objects
Any class that implements Oracle can be searched for.
// Grover search with the oracle passed as an object. Any class that// implements Oracle can be searched for; dispatch is resolved at compile time.interface Oracle { def mark(a: qubit, b: qubit) }// Marks 11.class MarkEleven implements Oracle { public def mark(a: qubit, b: qubit) { cz a, b }}// Marks 01 (a = 0, b = 1).class MarkZeroOne implements Oracle { public def mark(a: qubit, b: qubit) { within { x a } do { cz a, b } }}class Search(oracle: Oracle) { public qubit a public qubit b public bit ma public bit mb def diffuse() { within { h a h b x a x b } do { cz a, b } } public def run() { h a h b oracle.mark(a, b) diffuse() measure a -> ma measure b -> mb }}main { MarkZeroOne target Search search(target) search.run()}Register QFT
The Fourier transform as a class over a register.
// A quantum register class with a Fourier transform and its inverse,// sized at compile time. Applying qft then iqft returns the input.class Register(n: int) { public qubit q[n] public bit m[n] public def load_one(k: int) { x q[k] } public def qft() { for i in 0..n { h q[i] for j in i + 1..n { cp(pi / (1 << (j - i))) q[j], q[i] } } } public def iqft() { inverse { self.qft() } } public def read() { for i in 0..n { measure q[i] -> m[i] } }}main { Register r(3) r.load_one(1) r.qft() r.iqft() r.read()}Repetition code
A bit-flip code as a class, and a subclass that adds an error.
// A three-qubit bit-flip code as a class hierarchy: a base code that// encodes and decodes, and a subclass that adds a deliberate error.class BitFlipCode { public qubit d[3] public bit s0 public bit s1 public bit out[3] public def encode() { cx d[0], d[1] cx d[0], d[2] } def error() { } public def correct() { qubit anc cx d[0], anc cx d[1], anc measure anc -> s0 reset anc cx d[1], anc cx d[2], anc measure anc -> s1 reset anc if s0 { if s1 { x d[1] } else { x d[0] } } else { if s1 { x d[2] } } } public def run() { x d[0] encode() error() correct() for i in 0..3 { measure d[i] -> out[i] } }}class NoisyChannel extends BitFlipCode { override def error() { x d[2] }}main { NoisyChannel channel channel.run()}HiQ Pulse
For control engineers who shape the signal itself.
Rabi
A drive pulse built from a gaussian and a constant waveform.
# A Rabi point: one Gaussian drive pulse on qubit 0, then a readout.# Sweep amp across programs to trace the Rabi oscillation.pulse rabidt 0.5 nsbits 1port d0 drive qubits 0port m0 measure qubits 0frame drive on d0 freq 5.1 GHzframe read on m0 freq 7.2 GHzwaveform pi_half gaussian duration 40 ns amp 0.25 sigma 10 nswaveform tone constant duration 1 us amp 0.1play pi_half on drivebarrierplay tone on readcapture read 1 us -> 0Ramsey
Two half-pi pulses around a free evolution delay.
# Ramsey: two half-pi pulses separated by a free evolution delay,# with a virtual phase advance on the second pulse.pulse ramseydt 1 nsbits 1port d0 drive qubits 0port m0 measure qubits 0frame drive on d0 freq 5.1 GHzframe read on m0 freq 7.2 GHzwaveform half gaussian duration 32 ns amp 0.25 sigma 8 nsplay half on drivedelay 200 ns on driveshift_phase drive pi/2play half on drivebarriercapture read 2 us -> 0Echo
A refocusing pulse between two delays.
# Hahn echo: half-pi, wait, pi, wait, half-pi. The pi pulse is a# Blackman window at twice the amplitude.pulse echodt 1 nsbits 1port d0 drive qubits 0port m0 measure qubits 0frame drive on d0 freq 5.1 GHzframe read on m0 freq 7.2 GHzwaveform half blackman duration 40 ns amp 0.2waveform full blackman duration 40 ns amp 0.4play half on drivedelay 500 ns on driveplay full on drivedelay 500 ns on driveplay half on drivebarriercapture read 2 us -> 0