Skip to content

Commit

Permalink
Rework circuit (#6)
Browse files Browse the repository at this point in the history
Complete rework of the quantum-circuit() implementation.

This includes

- Layout algorithm (determine cell sizes, spacing etc.).
- Wire code. Importantly, wires are not drawn through gates anymore! Also, wires are now filled to the end. setwire() has been - improved to enable partial stroke changements (e.g., only thickness or paint).
- more modular code
- Added better error messages
  • Loading branch information
Mc-Zen authored Apr 26, 2024
1 parent df8f60f commit a2b6700
Show file tree
Hide file tree
Showing 61 changed files with 837 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Setup typst
uses: yusancky/setup-typst@v2
with:
version: 'v0.10.0'
version: 'v0.11.0'

- name: Run test suite
run: typst-test run
1 change: 1 addition & 0 deletions examples/fault-tolerant-measurement.typ
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#quantum-circuit(
row-spacing: 6pt,
fill-wires: false,
lstick($|0〉$), 10pt, group(3, 2, label: (content: "Prepare")), $H$, ctrl(2), 3pt,
group(4, 2, label: (content: "Verify")), 3,
group(7, 3, label: (content: [Controlled-$M$])),
Expand Down
1 change: 1 addition & 0 deletions examples/fault-tolerant-toffoli1.typ
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "../src/quill.typ": *

#quantum-circuit(
fill-wires: false,
lstick($|0〉$), $H$, ctrl(3), 5, $X$, ctrl(2), rstick($|x〉$), [\ ],
lstick($|0〉$), $H$, 1, ctrl(3), 3, $X$, 1, ctrl(0), rstick($|y〉$), [\ ],
lstick($|0〉$), 3, targ(), 1, $Z$, 2, targ(), rstick($|z plus.circle x y〉$), [\ ],
Expand Down
1 change: 1 addition & 0 deletions examples/fault-tolerant-toffoli2.typ
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#let group = gategroup.with(stroke: (dash: "dotted", thickness: .5pt))

#quantum-circuit(
fill-wires: false,
group(3, 3, padding: (left: 1.5em)), lstick($|0〉$), $H$, ctrl(2), ctrl(3), 3,
group(2, 1),ctrl(1), 1, group(3, 1), ctrl(2), $X$, 1, rstick($|x〉$), [\ ],
lstick($|0〉$), $H$, ctrl(0), 1, ctrl(3), 2, $Z$, $X$, 2, group(2, 1),
Expand Down
4 changes: 2 additions & 2 deletions examples/phase-estimation.typ
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#import "../src/quill.typ": *

#quantum-circuit(
setwire(0), lstick(align(center)[First register\ $t$ qubits], n: 4), lstick($|0〉$),
setwire(0), lstick(align(center)[First register\ $t$ qubits], n: 4, pad: 10.5pt), lstick($|0〉$),
setwire(1), $H$, 4, midstick($ dots $), ctrl(4), rstick($|0〉$), [\ ], 10pt,
setwire(0), phantom(width: 13pt), lstick($|0〉$), setwire(1), $H$, 2, ctrl(3), 1,
midstick($ dots $), 1, rstick($|0〉$), [\ ],
setwire(0), 1, lstick($|0〉$), setwire(1), $H$, 1, ctrl(2), 2,
midstick($ dots $), 1, rstick($|0〉$), [\ ],
setwire(0), 1, lstick($|0〉$), setwire(1), $H$, ctrl(1), 3, midstick($ dots $), 1,
rstick($|0〉$), [\ ],
setwire(0), lstick([Second register], n: 1, brace: "{"), lstick($|u〉$),
setwire(0), lstick([Second register], n: 1, brace: "{", pad: 10.5pt), lstick($|u〉$),
setwire(4, wire-distance: 1.3pt), 1, $ U^2^0 $, $ U^2^1 $, $ U^2^2 $,
1, midstick($ dots $), $ U^2^(t-1) $, rstick($|u〉$)
)
82 changes: 66 additions & 16 deletions src/decorations.typ
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

// align: "left" (for rstick) or "right" (for lstick)
// brace: auto, none, "{", "}", "|", "[", ...
#let lrstick(content, n, align, brace, label) = gate(
#let lrstick(content, n, align, brace, label, pad: 0pt, x: auto, y: auto) = gate(
content,
x: x,
y: y,
draw-function: draw-functions.draw-lrstick,
size-hint: layout.lrstick-size-hint,
box: false,
Expand All @@ -20,6 +22,7 @@
data: (
brace: brace,
align: align,
pad: pad
),
label: label
)
Expand All @@ -34,33 +37,57 @@
/// is shown only if `n > 1`. A brace is always shown when
/// explicitly given, e.g., `"}"`, `"["` or `"|"`. No brace is shown for
/// `brace: none`
/// - pad (length): Adds a padding between the label and the connected wire to the right.
/// - label (array, string, content, dictionary): One or more labels to add to the gate.
/// See @@gate(). .
#let lstick(content, n: 1, brace: auto, label: none) = lrstick(content, n, right, brace, label)
/// See @@gate().
#let lstick(
content,
n: 1,
brace: auto,
pad: 0pt,
label: none,
x: auto,
y: auto
) = lrstick(content, n, right, brace, label, pad: pad, x: x, y: y)


/// Basic command for labelling a wire at the end.
/// - content (content): Label to display, e.g., `$|0〉$`.
/// - n (content): How many wires the `rstick` should span.
/// - pad (length): Adds a padding between the label and the connected wire to the left.
/// - brace (auto, none, string): If `brace` is `auto`, then a default `}` brace
/// is shown only if `n > 1`. A brace is always shown when
/// explicitly given, e.g., `"}"`, `"["` or `"|"`. No brace is shown for
/// `brace: none`.
/// - label (array, string, content, dictionary): One or more labels to add to the gate.
/// See @@gate().
#let rstick(content, n: 1, brace: auto, label: none) = lrstick(content, n, left, brace, label)
#let rstick(
content,
n: 1,
brace: auto,
pad: 0pt,
label: none,
x: auto,
y: auto
) = lrstick(content, n, left, brace, label, pad: pad, x: x, y: y)

/// Create a midstick, i.e., a mid-circuit text.
/// - content (content): Label to display, e.g., `$|0〉$`.
/// - label (array, string, content, dictionary): One or more labels to add to the gate.
#let midstick(content, fill: none, label: none) = gate(content, draw-function: draw-functions.draw-unboxed-gate, label: label, fill: fill)
#let midstick(
content,
fill: none,
label: none,
x: auto,
y: auto
) = gate(content, draw-function: draw-functions.draw-unboxed-gate, label: label, fill: fill, x: x, y: y)



/// Creates a symbol similar to `\qwbundle` on `quantikz`. Annotates a wire to
/// be a bundle of quantum or classical wires.
/// - label (integer, content):
#let nwire(label) = gate([#label], draw-function: draw-functions.draw-nwire, box: false)
/// - label (int, content):
#let nwire(label, x: auto, y: auto) = gate([#label], draw-function: draw-functions.draw-nwire, box: false, x: x, y: y)



Expand All @@ -69,11 +96,11 @@
///
/// The wire style is reset for each row.
///
/// - wire-count (integer): Number of wires to display.
/// - stroke (none, stroke): When given, the stroke is applied to the wire.
/// - wire-count (int): Number of wires to display.
/// - stroke (auto, none, stroke): When given, the stroke is applied to the wire.
/// Otherwise the current stroke is kept.
/// - wire-distance (length): Distance between wires.
#let setwire(wire-count, stroke: none, wire-distance: 1pt) = (
#let setwire(wire-count, stroke: auto, wire-distance: auto) = (
qc-instr: "setwire",
wire-count: wire-count,
stroke: stroke,
Expand All @@ -83,8 +110,11 @@
/// Highlight a group of circuit elements by drawing a rectangular box around
/// them.
///
/// - wires (integer): Number of wires to include.
/// - steps (integer): Number of columns to include.
/// - wires (int): Number of wires to include.
/// - steps (int): Number of columns to include.
/// - x (auto, int): The starting column of the gategroup.
/// - y (auto, int): The starting wire of the gategroup.
/// - z (string): The gategroup can be placed `"below"` or `"above"` the circuit.
/// - padding (length, dictionary): Padding of rectangle. May be one length
/// for all sides or a dictionary with the keys `left`, `right`, `top`,
/// `bottom` and `default`. Not all keys need to be specified. The value
Expand All @@ -98,6 +128,9 @@
#let gategroup(
wires,
steps,
x: auto,
y: auto,
z: "below",
padding: 0pt,
stroke: .7pt,
fill: none,
Expand All @@ -107,24 +140,36 @@
qc-instr: "gategroup",
wires: wires,
steps: steps,
x: x,
y: y,
z: z,
padding: process-args.process-padding-arg(padding),
style: (fill: fill, stroke: stroke, radius: radius),
labels: process-args.process-label-arg(label, default-pos: top)
)

/// Slice the circuit vertically, showing a separation line between columns.
///
/// - n (integer): Number of wires to slice.
/// - n (int): Number of wires to slice.
/// - x (auto, int): The starting column of the slice.
/// - y (auto, int): The starting wire of the slice.
/// - z (string): The slice can be placed `"below"` or `"above"` the circuit.
/// - stroke (stroke): Line style for the slice.
/// - label (array, string, content, dictionary): One or more labels to add to the
/// slice. See @@gate().
#let slice(
n: 0,
x: auto,
y: auto,
z: "below",
stroke: (paint: red, thickness: .7pt, dash: "dashed"),
label: none
) = (
qc-instr: "slice",
wires: n,
x: x,
y: y,
z: z,
style: (stroke: stroke),
labels: process-args.process-label-arg(label, default-pos: top)
)
Expand All @@ -135,19 +180,24 @@
/// This function is passed the coordinates of the specified cell rows
/// and columns.
///
/// - columns (integer, array): Column indices for which to obtain coordinates.
/// - rows (integer, array): Row indices for which to obtain coordinates.
/// - columns (int, array): Column indices for which to obtain coordinates.
/// - rows (int, array): Row indices for which to obtain coordinates.
/// - callback (function): Function to call with the obtained coordinates. The
/// signature should be with signature `(col-coords, row-coords) => {}`.
/// This function is expected to display the content to draw in absolute
/// coordinates within the circuit.
/// - z (string): The annotation can be placed `"below"` or `"above"` the circuit.
#let annotate(
columns,
rows,
callback
callback,
z: "below",
) = (
qc-instr: "annotate",
rows: rows,
x: none,
y: none,
z: z,
columns: columns,
callback: callback
)
Expand Down
6 changes: 3 additions & 3 deletions src/draw-functions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
}

let brace-size = measure(brace, draw-params.styles)
let width = size.width + brace-size.width
let width = size.width + brace-size.width + gate.data.pad
let height = size.height
let brace-offset-y
let content-offset-y = 0pt
Expand All @@ -243,8 +243,8 @@
brace-offset-y = -.25em
}

let brace-pos-x = if isleftstick { size.width } else { 0pt }
let content-pos-x = if isleftstick { 0pt } else { brace-size.width }
let brace-pos-x = if isleftstick { size.width } else { gate.data.pad }
let content-pos-x = if isleftstick { 0pt } else { width - size.width}

box(
width: width,
Expand Down
Loading

0 comments on commit a2b6700

Please sign in to comment.