@@ -4,6 +4,7 @@ A module for drawing quantum circuits through the Quantikz latex package.
4
4
module Quantikz
5
5
6
6
using Base. Filesystem
7
+ using Base. ScopedValues: @with , ScopedValue
7
8
using Pkg. Artifacts
8
9
9
10
using FileIO
@@ -25,11 +26,15 @@ export MultiControl, CNOT, CPHASE, SWAP, H, P, Id, U,
25
26
string2image,
26
27
circuit2image,
27
28
displaycircuit,
28
- savecircuit
29
+ savecircuit,
30
+ @with , ScopedValue
29
31
30
32
const quantikzname = " tikzlibraryquantikz.code.tex"
31
33
const quantikzfile = joinpath (artifact " quantikz" , " quantikz" , quantikzname)
32
34
35
+ const classicalbitslayout = ScopedValue (:compressed )
36
+ classicalbitslayout_error () = error (" `classicalbitslayout` config variable has to be either `:expanded` or `:complressed`. Instead it is `$(classicalbitslayout[]) `" )
37
+
33
38
# This is necessary because typeof(ibegin:iend) <: AbstractRange is false
34
39
const ArrayOrRange = Union{A,B,C} where {A<: AbstractVector , B<: EndpointRanges.EndpointUnitRange , C<: EndpointRanges.EndpointStepRange }
35
40
@@ -237,10 +242,19 @@ Measurement(is::ArrayOrRange, b::Integer) = Measurement("\\;\\;", is, b)
237
242
affectedqubits (m:: Measurement ) = m. targets
238
243
function update_table! (qtable,step,meas:: Measurement )
239
244
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
240
254
if length (meas. targets) == 1
241
255
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 ) }"
244
258
end
245
259
else
246
260
step = step+ 1
@@ -250,8 +264,8 @@ function update_table!(qtable,step,meas::Measurement)
250
264
ancillaryview (qtable)[1 ,step- 1 ] = " \\ lstick{}"
251
265
ancillaryview (qtable)[1 ,step] = " \\ ctrl{$(M- qtable. qubits- 1 ) }"
252
266
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 ) }"
255
269
end
256
270
end
257
271
qtable
@@ -311,16 +325,23 @@ affectedbits(g::ClassicalDecision) = g.bits
311
325
function update_table! (qtable,step,g:: ClassicalDecision )
312
326
qvtable = qubitsview (qtable)
313
327
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)
316
337
if ! isa (g. targets,AbstractVector) || length (g. targets)> 0
317
338
m, M = explicit_extrema (qvtable, g. targets)
318
339
draw_rectangle! (qvtable,step,g. targets,g. str)
319
340
bvtable[startpoint,step] = " \\ cwbend{$(- (qtable. qubits- M)- qtable. ancillaries- startpoint) }"
320
341
else
321
342
bvtable[startpoint,step] = " \\ cwbend{0}"
322
343
end
323
- for b in sort (bits )[2 : end ]
344
+ for b in sort (layoutbits )[2 : end ]
324
345
bvtable[b,step] = " \\ cwbend{$(startpoint- b) }"
325
346
startpoint = b
326
347
end
@@ -391,13 +412,23 @@ function circuit2table_expanded(circuit, qubits)
391
412
qubitsview (table)[affectedqubits (op),current_step: end ] .= " \\ qw"
392
413
qubitsview (table)[deleteoutputs (op),current_step: end ] .= " "
393
414
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)
395
424
end
396
425
426
+ """ Turn implicit endpoints to explicit integer indices and take the extrema"""
397
427
function explicit_extrema (table,r)
398
428
t = explicit_targets (table,r)
399
429
isempty (t) ? t : extrema (t)
400
430
end
431
+ """ Turn implicit endpoints to explicit integer indices"""
401
432
function explicit_targets (table,targets)
402
433
targets = (1 : size (table,1 ))[targets]
403
434
end
@@ -412,6 +443,7 @@ function circuit2table_compressed(circuit, qubits)
412
443
filled_up_to = fill (1 + PADDING,qubits)
413
444
afilled_up_to = fill (1 + PADDING,table. ancillaries)
414
445
bfilled_up_to = fill (1 + PADDING,table. bits)
446
+ maxbit = 0
415
447
for op in circuit
416
448
qubits = extrema2range (explicit_extrema (qvtable, affectedqubits (op)))
417
449
if circuitwidthbits (op)!= 0 || neededancillaries (op)!= 0
@@ -422,20 +454,29 @@ function circuit2table_compressed(circuit, qubits)
422
454
end
423
455
end
424
456
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... )
425
465
ancillaries = neededancillaries (op)
426
466
steps = nsteps (op)
427
467
current_step = maximum ([filled_up_to[qubits]. .. ,afilled_up_to[1 : ancillaries]. .. ,bfilled_up_to[bits]. .. ])
428
468
filled_up_to[qubits] .= current_step+ steps
429
469
afilled_up_to[1 : ancillaries] .= current_step+ steps
430
470
if circuitwidthbits (op)!= 0
431
471
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
433
473
end
434
474
qvtable[affectedqubits (op),current_step: end ] .= " \\ qw"
435
475
qvtable[deleteoutputs (op),current_step: end ] .= " "
436
476
update_table! (table,current_step,op)
437
477
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)
439
480
end
440
481
441
482
function circuit2table (circuit, qubits; mode= :compressed , kw... )
0 commit comments