Skip to content

Commit 27c520b

Browse files
authored
default to plotting a single classical line for all bits (#26)
1 parent 90013ad commit 27c520b

File tree

5 files changed

+68
-19
lines changed

5 files changed

+68
-19
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
version:
17-
- '1.6'
18-
- '1.9'
17+
- '1.11'
1918
- '1'
2019
os:
2120
- ubuntu-latest

.github/workflows/downgrade.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
version: ['1.9']
18+
version: ['1.11']
1919
steps:
2020
- uses: actions/checkout@v4
2121
- uses: julia-actions/setup-julia@v1

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Quantikz"
22
uuid = "b0d11df0-eea3-4d79-b4a5-421488cbf74b"
33
authors = ["Stefan Krastanov <[email protected]>"]
4-
version = "1.3.1"
4+
version = "1.4.0"
55

66
[deps]
77
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
@@ -15,5 +15,5 @@ tectonic_jll = "d7dd28d6-a5e6-559c-9131-7eb760cdacc5"
1515
FileIO = "1.6"
1616
Ghostscript_jll = "9.53"
1717
ImageMagick = "1.1"
18-
julia = "1.6"
18+
julia = "1.11"
1919
tectonic_jll = "0.11"

src/Quantikz.jl

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ A module for drawing quantum circuits through the Quantikz latex package.
44
module Quantikz
55

66
using Base.Filesystem
7+
using Base.ScopedValues: @with, ScopedValue
78
using Pkg.Artifacts
89

910
using FileIO
@@ -25,11 +26,15 @@ export MultiControl, CNOT, CPHASE, SWAP, H, P, Id, U,
2526
string2image,
2627
circuit2image,
2728
displaycircuit,
28-
savecircuit
29+
savecircuit,
30+
@with, ScopedValue
2931

3032
const quantikzname = "tikzlibraryquantikz.code.tex"
3133
const quantikzfile = joinpath(artifact"quantikz", "quantikz", quantikzname)
3234

35+
const classicalbitslayout = ScopedValue(:compressed)
36+
classicalbitslayout_error() = error("`classicalbitslayout` config variable has to be either `:expanded` or `:complressed`. Instead it is `$(classicalbitslayout[])`")
37+
3338
# This is necessary because typeof(ibegin:iend) <: AbstractRange is false
3439
const ArrayOrRange = Union{A,B,C} where {A<:AbstractVector, B<:EndpointRanges.EndpointUnitRange, C<:EndpointRanges.EndpointStepRange}
3540

@@ -237,10 +242,19 @@ Measurement(is::ArrayOrRange, b::Integer) = Measurement("\\;\\;", is, b)
237242
affectedqubits(m::Measurement) = m.targets
238243
function update_table!(qtable,step,meas::Measurement)
239244
table = qubitsview(qtable)
245+
layoutbit = if isnothing(meas.bit)
246+
nothing
247+
elseif classicalbitslayout[] == :expanded
248+
meas.bit
249+
elseif classicalbitslayout[] == :compressed
250+
1
251+
else
252+
classicalbitslayout_error()
253+
end
240254
if length(meas.targets) == 1
241255
table[meas.targets[1],step] = "\\meterD{$(meas.str)}"
242-
if !isnothing(meas.bit)
243-
bitsview(qtable)[meas.bit,step] = "\\cwbend{$(-(qtable.qubits-meas.targets[1])-qtable.ancillaries-meas.bit)}"
256+
if !isnothing(layoutbit)
257+
bitsview(qtable)[layoutbit,step] = "\\cwbend{$(-(qtable.qubits-meas.targets[1])-qtable.ancillaries-layoutbit)}"
244258
end
245259
else
246260
step = step+1
@@ -250,8 +264,8 @@ function update_table!(qtable,step,meas::Measurement)
250264
ancillaryview(qtable)[1,step-1] = "\\lstick{}"
251265
ancillaryview(qtable)[1,step] = "\\ctrl{$(M-qtable.qubits-1)}"
252266
ancillaryview(qtable)[1,step+1] = "\\meterD{}"
253-
if !isnothing(meas.bit)
254-
bitsview(qtable)[meas.bit,step+1] = "\\cwbend{$(1-qtable.ancillaries-meas.bit)}"
267+
if !isnothing(layoutbit)
268+
bitsview(qtable)[layoutbit,step+1] = "\\cwbend{$(1-qtable.ancillaries-layoutbit)}"
255269
end
256270
end
257271
qtable
@@ -311,16 +325,23 @@ affectedbits(g::ClassicalDecision) = g.bits
311325
function update_table!(qtable,step,g::ClassicalDecision)
312326
qvtable = qubitsview(qtable)
313327
bvtable = bitsview(qtable)
314-
bits = explicit_targets(bvtable, g.bits)
315-
startpoint = minimum(bits)
328+
actualbits = explicit_targets(bvtable, g.bits)
329+
layoutbits = if classicalbitslayout[] == :expanded
330+
actualbits
331+
elseif classicalbitslayout[] == :compressed
332+
[1]
333+
else
334+
classicalbitslayout_error()
335+
end
336+
startpoint = minimum(layoutbits)
316337
if !isa(g.targets,AbstractVector) || length(g.targets)>0
317338
m, M = explicit_extrema(qvtable, g.targets)
318339
draw_rectangle!(qvtable,step,g.targets,g.str)
319340
bvtable[startpoint,step] = "\\cwbend{$(-(qtable.qubits-M)-qtable.ancillaries-startpoint)}"
320341
else
321342
bvtable[startpoint,step] = "\\cwbend{0}"
322343
end
323-
for b in sort(bits)[2:end]
344+
for b in sort(layoutbits)[2:end]
324345
bvtable[b,step] = "\\cwbend{$(startpoint-b)}"
325346
startpoint = b
326347
end
@@ -391,13 +412,23 @@ function circuit2table_expanded(circuit, qubits)
391412
qubitsview(table)[affectedqubits(op),current_step:end] .= "\\qw"
392413
qubitsview(table)[deleteoutputs(op),current_step:end] .= ""
393414
end
394-
return table
415+
layoutbits = if classicalbitslayout[] == :expanded
416+
table.bits
417+
elseif classicalbitslayout[] == :compressed
418+
1
419+
else
420+
classicalbitslayout_error()
421+
end
422+
cutoff = table.qubits+table.ancillaries+layoutbits
423+
return QuantikzTable(table.table[begin:cutoff,:], table.qubits, table.ancillaries, layoutbits)
395424
end
396425

426+
"""Turn implicit endpoints to explicit integer indices and take the extrema"""
397427
function explicit_extrema(table,r)
398428
t = explicit_targets(table,r)
399429
isempty(t) ? t : extrema(t)
400430
end
431+
"""Turn implicit endpoints to explicit integer indices"""
401432
function explicit_targets(table,targets)
402433
targets = (1:size(table,1))[targets]
403434
end
@@ -412,6 +443,7 @@ function circuit2table_compressed(circuit, qubits)
412443
filled_up_to = fill(1+PADDING,qubits)
413444
afilled_up_to = fill(1+PADDING,table.ancillaries)
414445
bfilled_up_to = fill(1+PADDING,table.bits)
446+
maxbit = 0
415447
for op in circuit
416448
qubits = extrema2range(explicit_extrema(qvtable, affectedqubits(op)))
417449
if circuitwidthbits(op)!=0 || neededancillaries(op)!=0
@@ -422,20 +454,29 @@ function circuit2table_compressed(circuit, qubits)
422454
end
423455
end
424456
bits = extrema2range(explicit_extrema(bvtable, affectedbits(op)))
457+
layoutbits = if isempty(bits) || classicalbitslayout[] == :expanded
458+
bits
459+
elseif classicalbitslayout[] == :compressed
460+
[1]
461+
else
462+
classicalbitslayout_error()
463+
end
464+
maxbit = max(maxbit, layoutbits...)
425465
ancillaries = neededancillaries(op)
426466
steps = nsteps(op)
427467
current_step = maximum([filled_up_to[qubits]...,afilled_up_to[1:ancillaries]...,bfilled_up_to[bits]...])
428468
filled_up_to[qubits] .= current_step+steps
429469
afilled_up_to[1:ancillaries] .= current_step+steps
430470
if circuitwidthbits(op)!=0
431471
filled_up_to[qubits.stop:end] .= current_step+steps
432-
bfilled_up_to[bits] .= current_step+steps
472+
bfilled_up_to[layoutbits] .= current_step+steps
433473
end
434474
qvtable[affectedqubits(op),current_step:end] .= "\\qw"
435475
qvtable[deleteoutputs(op),current_step:end] .= ""
436476
update_table!(table,current_step,op)
437477
end
438-
return QuantikzTable(table.table[:,1:maximum(filled_up_to)-1+PADDING],table.qubits,table.ancillaries,table.bits)
478+
cutoff = table.qubits+table.ancillaries+maxbit
479+
return QuantikzTable(table.table[begin:cutoff,1:maximum(filled_up_to)-1+PADDING],table.qubits,table.ancillaries,maxbit)
439480
end
440481

441482
function circuit2table(circuit, qubits; mode=:compressed, kw...)

test/runtests.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
using Quantikz, Test
1+
using Test
2+
using Quantikz
23
using Quantikz.VendoredEndpointRanges
34
const EndpointRanges = VendoredEndpointRanges
45

5-
function stringtests()
6+
function classical_expanded_stringtests()
67
@testset "Misc string conversions" begin
78
circuit = [
89
CNOT(1,2),CPHASE(2,3),
@@ -173,5 +174,13 @@ function filetests()
173174
end
174175
end
175176

176-
stringtests()
177+
function classical_compressed_stringtests()
178+
@testset "Misc string conversions" begin
179+
circuit = [CNOT(1,2), Measurement(1,1), Measurement(1,2), ClassicalDecision([1,2,4],[1,2,4]), ClassicalDecision(1,1), ClassicalDecision(2,2), Measurement([1,2],3)]
180+
@test circuit2string(circuit, mode=:expanded) == "\\begin{quantikz}[transparent, row sep={0.8cm,between origins}]\n\\qw & \\ctrl{0} & \\meterD{} & \\meterD{} & \\gate[4,disable auto height]{\\;\\;} & \\gate[1]{\\;\\;} & \\qw & \\qw & \\gate[2,disable auto height]{\\;\\;} & \\qw & \\qw\\\\\n\\qw & \\targ{}\\vqw{-1} & \\qw & \\qw & \\qw & \\qw & \\gate[1]{\\;\\;} & \\qw & \\qw & \\qw & \\qw\\\\\n\\qw & \\qw & \\qw & \\qw & \\linethrough & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw\\\\\n\\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw\\\\\n & & & & & & & \\lstick{} & \\ctrl{-3} & \\meterD{} & \\\\\n\\cw & \\cw & \\cwbend{-5} & \\cwbend{-5} & \\cwbend{-2} & \\cwbend{-5} & \\cwbend{-4} & \\cw & \\cw & \\cwbend{-1} & \\cw\n\\end{quantikz}"
181+
end
182+
end
183+
184+
@with Quantikz.classicalbitslayout=>:expanded classical_expanded_stringtests()
185+
classical_compressed_stringtests()
177186
filetests()

0 commit comments

Comments
 (0)