Esta documentación está disponible en inglés. La documentación en español comienza en la versión 1.2.

Author diagrams

Let a part take its height from its wires

fit=wires lines a gate's rails or a block's pins up with the terminals wired to them, so straight wires stay straight.

Stop bending wires to meet a fixed pitch

A block with several terminals on a side has a fixed pitch. A CNOT's rails are 18 units apart; an IC spreads its pins evenly over its body. Our qubits and buses rarely sit 18 units apart, so every wire bent to meet the part — in to the gate, and out again.

fit=wires turns that round. On a part declared with it, each terminal takes the height of the terminal it is wired to, the part is centred between them, and a block's body grows to hold them. The wires arrive straight.

prepare:Q0 "|0\rangle" at (80, 100) #blue
prepare:Q1 "|0\rangle" at (80, 210) #blue
prepare:Q2 "|0\rangle" at (80, 320) #blue
hadamard:HQ "H" at (230, 100) #cyan
cnot:CA "CNOT" at (420, 150) #purple [fit=wires]
cnot:CB "CNOT" at (600, 260) #purple [fit=wires]
measure:MA "M" at (800, 100) #emerald
measure:MB "M" at (800, 210) #emerald
measure:MC "M" at (800, 320) #emerald

Q0.out -> HQ.in #blue [ortho]
HQ.out -> CA.in1 #cyan [ortho]
Q1.out -> CA.in2 #blue [ortho]
CA.out1 -> MA.in #purple [ortho]
CA.out2 -> CB.in1 #purple [ortho]
Q2.out -> CB.in2 #blue [ortho]
CB.out1 -> MB.in #purple [ortho]
CB.out2 -> MC.in #purple [ortho]
compiled by @schemd/core → shown in the rail

Nothing else changes. A document that never writes fit=wires compiles to exactly the bytes it did in 1.0.

Rails on gates, pins on blocks

Two families take the option:

Part What follows its wires
cnot, cz, cphase, toffoli, controlled, swap, barrier, delay one rail per qubit, from its input's wire — or its output's when the input is unwired
ic and digital blocks (mux, register, counter, flipflop, …) the left and right terminals, each side in its declared order; top and bottom stay in place

A quantum gate's rails may come in any order, so a CNOT whose control sits below its target needs nothing special; its two vertical terminals still face away from each other. A block's pins keep the order we declared them in, top to bottom, and its body never shrinks below its usual height.

prepare:R0 "|0\rangle" at (80, 110) #blue
prepare:R1 "|0\rangle" at (80, 220) #blue
prepare:R2 "|1\rangle" at (80, 330) #blue
hadamard:HA "H" at (240, 110) #cyan
hadamard:HB "H" at (240, 220) #cyan
hadamard:HC "H" at (240, 330) #cyan
ic:UF "U_f" at (500, 220) #purple [left="x0,x1,y" right="x0o,x1o,yo" fit=wires]
measure:MX0 "M" at (800, 110) #emerald
measure:MX1 "M" at (800, 220) #emerald

R0.out -> HA.in #blue [ortho]
R1.out -> HB.in #blue [ortho]
R2.out -> HC.in #blue [ortho]
HA.out -> UF.x0 #cyan [ortho]
HB.out -> UF.x1 #cyan [ortho]
HC.out -> UF.y #cyan [ortho]
UF.x0o -> MX0.in #purple [ortho]
UF.x1o -> MX1.in #purple [ortho]
compiled by @schemd/core → shown in the rail

The unwired yo pin is spaced from its wired neighbours at the block's usual pitch. A part with nothing wired to the terminals that fit keeps its usual shape, so adding fit=wires to a part we have not wired yet is harmless.

Settled left to right, never by source order

Fitting is arithmetic, not search, and its rules are short:

  • Fitted parts settle left to right, then top to bottom, then by id. Each one reads only parts already settled, so a chain of gates fits from its first gate onwards — the second CNOT in the GHZ circuit reads the first one's fitted rail.
  • A terminal wired to several parts follows the nearest, then the higher, then the first by name.
  • The part's centre is derived. It sits halfway between its outermost wired terminals, so the y we wrote matters only while nothing is wired.
  • Placement runs first. A part placed relative to a fitted one is measured from its unfitted shape, so leave room for it to grow, or place its neighbours with at (x, y).

Reordering the lines of a document never changes its drawing.

prepare:QT "|0\rangle" at (90, 110) #blue
prepare:QC "|1\rangle" at (90, 240) #blue
cnot:CU "CNOT" at (420, 175) #purple [fit=wires]
port:OT "target" at (740, 110) #emerald
port:OC "control" at (740, 240) #emerald

QC.out -> CU.in1 #blue [ortho]
QT.out -> CU.in2 #blue [ortho]
CU.out1 -> OC.in #purple [ortho]
CU.out2 -> OT.in #purple [ortho]
compiled by @schemd/core → shown in the rail

The compiled part records where its terminals landed: rails on a fitted gate and rows on a fitted block, as offsets from its centre. Full-mode markup carries data-fit="wires", and parseSchematicSvg reads it back as [fit=wires].

An impossible fit says what would work

Two terminals must arrive at least 16 units apart, and a block's must arrive in the order its pins are declared. When they do not, the diagnostic names the terminal and the height that would work:

We wrote It says
Two pins fed 10 units apart U1 cannot line up q with its wire: it arrives 10 units below p's, and pins need at least 16. Move the wire on q to y >= 216, or remove fit=wires.
Pins fed in the wrong order U1 cannot line up i1 with its wire: it arrives at y=100, above i0's at y=200, but i1 sits below i0 on U1's left side. Swap the wires, reorder the pins, or remove fit=wires.
fit=wires with orientation fit=wires lines terminals up with their wires vertically; remove orientation or fit.
fit=wires on a part with one terminal a side Option fit is not supported for measure; it lines up the rails of a gate that spans several qubits.

Fitting is for parts that span several wires. For a part with one terminal a side, line up the terminal itself: an alignment written at PORT places the part so its own terminal, not its centre, sits level with the reference. More on that in placement.

port:SIG "SIG" at (90, 170) #blue
resistor:RIN "10 k\Omega" right-of SIG by 110 #amber
xnor:GX "XNOR" right-of RIN by 110 aligned-y with RIN.out at in2 #purple [inputs=2]
port:OUTX "Y" right-of GX by 110 #emerald

SIG.out -> RIN.in #blue [ortho]
RIN.out -> GX.in2 #amber [ortho]
GX.out1 -> OUTX.in #purple [ortho]
compiled by @schemd/core → shown in the rail