14
14
from typing import TYPE_CHECKING
15
15
from warnings import warn
16
16
17
+ from pecos .qeclib .steane .decoders .lookup import (
18
+ FlagLookupQASMActiveCorrectionZ ,
19
+ )
17
20
from pecos .qeclib .steane .gates_sq import paulis , sqrt_paulis
18
21
from pecos .qeclib .steane .gates_sq .hadamards import H
19
22
from pecos .qeclib .steane .gates_tq import transversal_tq
@@ -162,9 +165,7 @@ def prep_t_plus_state(
162
165
d = self .d ,
163
166
a = self .a ,
164
167
out = self .scratch ,
165
- reject = self .scratch [
166
- 2
167
- ], # the first two bits of self.scratch are used by "out"
168
+ reject = self .scratch [2 ], # the first two bits are used by "out"
168
169
flag_x = self .flag_x ,
169
170
flag_z = self .flag_z ,
170
171
flags = self .flags ,
@@ -268,6 +269,7 @@ def tdg(self, aux: Steane, reject: Bit | None = None, rus_limit: int | None = No
268
269
)
269
270
270
271
# Begin Experimental: ------------------------------------
272
+
271
273
def nonft_t_tel (self , aux : Steane ):
272
274
"""Warning:
273
275
This is experimental.
@@ -283,7 +285,7 @@ def nonft_t_tel(self, aux: Steane):
283
285
aux .cx (self ),
284
286
self .mz (self .t_meas ),
285
287
If (self .t_meas == 1 ).Then (aux .x (), aux .sz ()),
286
- Permute ( self .d , aux . d ),
288
+ self .permute ( aux ),
287
289
)
288
290
289
291
def t_tel (
@@ -306,7 +308,7 @@ def t_tel(
306
308
aux .cx (self ),
307
309
self .mz (self .t_meas ),
308
310
If (self .t_meas == 1 ).Then (aux .x (), aux .sz ()), # SZ/S correction.
309
- Permute ( self .d , aux . d ),
311
+ self .permute ( aux ),
310
312
)
311
313
312
314
def nonft_tdg_tel (self , aux : Steane ):
@@ -324,7 +326,7 @@ def nonft_tdg_tel(self, aux: Steane):
324
326
aux .cx (self ),
325
327
self .mz (self .tdg_meas ),
326
328
If (self .tdg_meas == 1 ).Then (aux .x (), aux .szdg ()),
327
- Permute ( self .d , aux . d ),
329
+ self .permute ( aux ),
328
330
)
329
331
330
332
def tdg_tel (
@@ -347,8 +349,84 @@ def tdg_tel(
347
349
aux .cx (self ),
348
350
self .mz (self .tdg_meas ),
349
351
If (self .t_meas == 1 ).Then (aux .x (), aux .szdg ()), # SZdg/Sdg correction.
350
- Permute (self .d , aux .d ),
352
+ self .permute (aux ),
353
+ )
354
+
355
+ def t_cor (
356
+ self ,
357
+ aux : Steane ,
358
+ reject : Bit | None = None ,
359
+ flag : Bit | None = None ,
360
+ rus_limit : int | None = None ,
361
+ ):
362
+ """T gate via teleportation using fault-tolerant initialization of the T|+> state.
363
+
364
+ Applies active corrections of errors diagnozed by the measurement for gate teleportation.
365
+ """
366
+ warn ("Using experimental feature: t_cor" , stacklevel = 2 )
367
+ block = Block (
368
+ # gate teleportation without logical correction
369
+ aux .prep_t_plus_state (reject = reject , rus_limit = rus_limit ),
370
+ self .cx (aux ),
371
+ aux .mz (self .t_meas ),
372
+ # active error correction
373
+ self .syn_z .set (aux .syn_meas ),
374
+ self .last_raw_syn_z .set (0 ),
375
+ self .pf_x .set (0 ),
376
+ FlagLookupQASMActiveCorrectionZ (
377
+ self .d ,
378
+ self .syn_z ,
379
+ self .syn_z ,
380
+ self .last_raw_syn_z ,
381
+ self .pf_x ,
382
+ self .syn_z ,
383
+ self .syn_z ,
384
+ self .scratch ,
385
+ ),
386
+ # logical correction
387
+ If (self .t_meas == 1 ).Then (self .sz ()),
351
388
)
389
+ if flag is not None :
390
+ block .extend (If (self .syn_z != 0 ).Then (flag .set (1 )))
391
+ return block
392
+
393
+ def tdg_cor (
394
+ self ,
395
+ aux : Steane ,
396
+ reject : Bit | None = None ,
397
+ flag : Bit | None = None ,
398
+ rus_limit : int | None = None ,
399
+ ):
400
+ """Tdg gate via teleportation using fault-tolerant initialization of the Tdg|+> state.
401
+
402
+ Applies active corrections of errors diagnozed by the measurement for gate teleportation.
403
+ """
404
+ warn ("Using experimental feature: t_cor" , stacklevel = 2 )
405
+ block = Block (
406
+ # gate teleportation without logical correction
407
+ aux .prep_tdg_plus_state (reject = reject , rus_limit = rus_limit ),
408
+ self .cx (aux ),
409
+ aux .mz (self .tdg_meas ),
410
+ # active error correction
411
+ self .syn_z .set (aux .syn_meas ),
412
+ self .last_raw_syn_z .set (0 ),
413
+ self .pf_x .set (0 ),
414
+ FlagLookupQASMActiveCorrectionZ (
415
+ self .d ,
416
+ self .syn_z ,
417
+ self .syn_z ,
418
+ self .last_raw_syn_z ,
419
+ self .pf_x ,
420
+ self .syn_z ,
421
+ self .syn_z ,
422
+ self .scratch ,
423
+ ),
424
+ # logical correction
425
+ If (self .tdg_meas == 1 ).Then (self .szdg ()),
426
+ )
427
+ if flag is not None :
428
+ block .extend (If (self .syn_z != 0 ).Then (flag .set (1 )))
429
+ return block
352
430
353
431
# End Experimental: ------------------------------------
354
432
@@ -370,19 +448,17 @@ def cz(self, target: Steane):
370
448
371
449
def m (self , meas_basis : str , log : Bit | None = None ):
372
450
"""Destructively measure the logical qubit in some Pauli basis."""
373
- block = Block (
374
- MeasDecode (
375
- q = self .d ,
376
- meas_basis = meas_basis ,
377
- meas = self .raw_meas ,
378
- log_raw = self .log_raw ,
379
- log = self .log ,
380
- syn_meas = self .syn_meas ,
381
- pf_x = self .pf_x ,
382
- pf_z = self .pf_z ,
383
- last_raw_syn_x = self .last_raw_syn_x ,
384
- last_raw_syn_z = self .last_raw_syn_z ,
385
- ),
451
+ block = MeasDecode (
452
+ q = self .d ,
453
+ meas_basis = meas_basis ,
454
+ meas = self .raw_meas ,
455
+ log_raw = self .log_raw ,
456
+ log = self .log ,
457
+ syn_meas = self .syn_meas ,
458
+ pf_x = self .pf_x ,
459
+ pf_z = self .pf_z ,
460
+ last_raw_syn_x = self .last_raw_syn_x ,
461
+ last_raw_syn_z = self .last_raw_syn_z ,
386
462
)
387
463
if log is not None :
388
464
block .extend (log .set (self .log ))
@@ -400,7 +476,7 @@ def mz(self, log: Bit | None = None):
400
476
"""Logical destructive measurement of the logical Z operator."""
401
477
return self .m ("Z" , log = log )
402
478
403
- def qec (self , flag_bit : Bit | None = None ):
479
+ def qec (self , flag : Bit | None = None ):
404
480
block = ParallelFlagQECActiveCorrection (
405
481
q = self .d ,
406
482
a = self .a ,
@@ -416,6 +492,21 @@ def qec(self, flag_bit: Bit | None = None):
416
492
pf_z = self .pf_z ,
417
493
scratch = self .scratch ,
418
494
)
419
- if flag_bit is not None :
420
- block .extend (If (self .flags != 0 ).Then (flag_bit .set (1 )))
495
+ if flag is not None :
496
+ block .extend (If (self .flags != 0 ).Then (flag .set (1 )))
497
+ return block
498
+
499
+ def permute (self , other : Steane ):
500
+ """Permute this code block (including both quantum and classical registers) with another."""
501
+ block = Block (
502
+ Permute (self .d , other .d ),
503
+ Permute (self .a , other .a ),
504
+ )
505
+ for var_a , var_b in zip (self .vars , other .vars ):
506
+ if isinstance (var_a , CReg ):
507
+ block .extend (
508
+ var_a .set (var_a ^ var_b ),
509
+ var_b .set (var_b ^ var_a ),
510
+ var_a .set (var_a ^ var_b ),
511
+ )
421
512
return block
0 commit comments