tensorcircuit-nightly 1.3.0.dev20250728__py3-none-any.whl → 1.4.0.dev20251103__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tensorcircuit-nightly might be problematic. Click here for more details.
- tensorcircuit/__init__.py +5 -1
- tensorcircuit/abstractcircuit.py +4 -0
- tensorcircuit/analogcircuit.py +413 -0
- tensorcircuit/applications/layers.py +1 -1
- tensorcircuit/applications/van.py +1 -1
- tensorcircuit/backends/abstract_backend.py +312 -5
- tensorcircuit/backends/cupy_backend.py +3 -1
- tensorcircuit/backends/jax_backend.py +92 -3
- tensorcircuit/backends/jax_ops.py +108 -0
- tensorcircuit/backends/numpy_backend.py +49 -3
- tensorcircuit/backends/pytorch_backend.py +92 -3
- tensorcircuit/backends/tensorflow_backend.py +102 -3
- tensorcircuit/basecircuit.py +123 -82
- tensorcircuit/circuit.py +67 -57
- tensorcircuit/cloud/local.py +1 -1
- tensorcircuit/cloud/quafu_provider.py +1 -1
- tensorcircuit/cloud/tencent.py +1 -1
- tensorcircuit/compiler/simple_compiler.py +2 -2
- tensorcircuit/cons.py +1 -0
- tensorcircuit/densitymatrix.py +16 -11
- tensorcircuit/experimental.py +7 -152
- tensorcircuit/fgs.py +5 -6
- tensorcircuit/gates.py +66 -22
- tensorcircuit/keras.py +3 -3
- tensorcircuit/mpscircuit.py +109 -61
- tensorcircuit/quantum.py +697 -133
- tensorcircuit/quditcircuit.py +733 -0
- tensorcircuit/quditgates.py +618 -0
- tensorcircuit/results/counts.py +45 -31
- tensorcircuit/shadows.py +1 -1
- tensorcircuit/simplify.py +3 -1
- tensorcircuit/stabilizercircuit.py +4 -2
- tensorcircuit/templates/blocks.py +2 -2
- tensorcircuit/templates/hamiltonians.py +29 -8
- tensorcircuit/templates/lattice.py +676 -335
- tensorcircuit/timeevol.py +896 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/METADATA +50 -25
- tensorcircuit_nightly-1.4.0.dev20251103.dist-info/RECORD +96 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/top_level.txt +0 -1
- tensorcircuit_nightly-1.3.0.dev20250728.dist-info/RECORD +0 -122
- tests/__init__.py +0 -0
- tests/conftest.py +0 -67
- tests/test_backends.py +0 -1035
- tests/test_calibrating.py +0 -149
- tests/test_channels.py +0 -409
- tests/test_circuit.py +0 -1713
- tests/test_cloud.py +0 -219
- tests/test_compiler.py +0 -147
- tests/test_dmcircuit.py +0 -555
- tests/test_ensemble.py +0 -72
- tests/test_fgs.py +0 -318
- tests/test_gates.py +0 -156
- tests/test_hamiltonians.py +0 -159
- tests/test_interfaces.py +0 -557
- tests/test_keras.py +0 -160
- tests/test_lattice.py +0 -1666
- tests/test_miscs.py +0 -334
- tests/test_mpscircuit.py +0 -341
- tests/test_noisemodel.py +0 -156
- tests/test_qaoa.py +0 -86
- tests/test_qem.py +0 -152
- tests/test_quantum.py +0 -549
- tests/test_quantum_attr.py +0 -42
- tests/test_results.py +0 -379
- tests/test_shadows.py +0 -160
- tests/test_simplify.py +0 -46
- tests/test_stabilizer.py +0 -226
- tests/test_templates.py +0 -218
- tests/test_torchnn.py +0 -99
- tests/test_van.py +0 -102
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/WHEEL +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/licenses/LICENSE +0 -0
tensorcircuit/basecircuit.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Quantum circuit: common methods for all circuit classes as MixIn
|
|
3
|
+
|
|
4
|
+
Note:
|
|
5
|
+
- Supports qubit (d = 2) and qudit (d >= 2) systems.
|
|
6
|
+
- For string-encoded samples/counts when d <= 36, digits use base-d characters 0-9A-Z (A = 10, ..., Z = 35).
|
|
3
7
|
"""
|
|
4
8
|
|
|
5
9
|
# pylint: disable=invalid-name
|
|
@@ -19,8 +23,10 @@ from .quantum import (
|
|
|
19
23
|
correlation_from_counts,
|
|
20
24
|
measurement_counts,
|
|
21
25
|
sample_int2bin,
|
|
22
|
-
sample_bin2int,
|
|
23
26
|
sample2all,
|
|
27
|
+
_infer_num_sites,
|
|
28
|
+
_decode_basis_label,
|
|
29
|
+
onehot_d_tensor,
|
|
24
30
|
)
|
|
25
31
|
from .abstractcircuit import AbstractCircuit
|
|
26
32
|
from .cons import npdtype, backend, dtypestr, contractor, rdtypestr
|
|
@@ -41,8 +47,9 @@ class BaseCircuit(AbstractCircuit):
|
|
|
41
47
|
is_mps = False
|
|
42
48
|
|
|
43
49
|
@staticmethod
|
|
44
|
-
def all_zero_nodes(n: int,
|
|
45
|
-
|
|
50
|
+
def all_zero_nodes(n: int, prefix: str = "qb-", dim: int = 2) -> List[tn.Node]:
|
|
51
|
+
prefix = "qd-" if dim > 2 else prefix
|
|
52
|
+
l = [0.0 for _ in range(dim)]
|
|
46
53
|
l[0] = 1.0
|
|
47
54
|
nodes = [
|
|
48
55
|
tn.Node(
|
|
@@ -289,7 +296,7 @@ class BaseCircuit(AbstractCircuit):
|
|
|
289
296
|
for op, index in ops:
|
|
290
297
|
if not isinstance(op, tn.Node):
|
|
291
298
|
# op is only a matrix
|
|
292
|
-
op = backend.
|
|
299
|
+
op = backend.reshaped(op, d=self._d)
|
|
293
300
|
op = backend.cast(op, dtype=dtypestr)
|
|
294
301
|
op = gates.Gate(op)
|
|
295
302
|
else:
|
|
@@ -355,12 +362,12 @@ class BaseCircuit(AbstractCircuit):
|
|
|
355
362
|
|
|
356
363
|
def perfect_sampling(self, status: Optional[Tensor] = None) -> Tuple[str, float]:
|
|
357
364
|
"""
|
|
358
|
-
Sampling
|
|
365
|
+
Sampling base-d strings (0-9A-Z when d <= 36) from the circuit output based on quantum amplitudes.
|
|
359
366
|
Reference: arXiv:1201.3974.
|
|
360
367
|
|
|
361
368
|
:param status: external randomness, with shape [nqubits], defaults to None
|
|
362
369
|
:type status: Optional[Tensor]
|
|
363
|
-
:return: Sampled
|
|
370
|
+
:return: Sampled base-d string and the corresponding theoretical probability.
|
|
364
371
|
:rtype: Tuple[str, float]
|
|
365
372
|
"""
|
|
366
373
|
return self.measure_jit(*range(self._nqubits), with_prob=True, status=status)
|
|
@@ -369,10 +376,10 @@ class BaseCircuit(AbstractCircuit):
|
|
|
369
376
|
self, *index: int, with_prob: bool = False, status: Optional[Tensor] = None
|
|
370
377
|
) -> Tuple[Tensor, Tensor]:
|
|
371
378
|
"""
|
|
372
|
-
Take measurement
|
|
379
|
+
Take measurement on the given site indices (computational basis).
|
|
373
380
|
This method is jittable is and about 100 times faster than unjit version!
|
|
374
381
|
|
|
375
|
-
:param index: Measure on which
|
|
382
|
+
:param index: Measure on which site (wire) index.
|
|
376
383
|
:type index: int
|
|
377
384
|
:param with_prob: If true, theoretical probability is also returned.
|
|
378
385
|
:type with_prob: bool, optional
|
|
@@ -383,9 +390,8 @@ class BaseCircuit(AbstractCircuit):
|
|
|
383
390
|
"""
|
|
384
391
|
# finally jit compatible ! and much faster than unjit version ! (100x)
|
|
385
392
|
sample: List[Tensor] = []
|
|
386
|
-
|
|
387
|
-
p =
|
|
388
|
-
p = backend.cast(p, dtype=rdtypestr)
|
|
393
|
+
one_r = backend.cast(backend.convert_to_tensor(1.0), rdtypestr)
|
|
394
|
+
p = one_r
|
|
389
395
|
for k, j in enumerate(index):
|
|
390
396
|
if self.is_dm is False:
|
|
391
397
|
nodes1, edge1 = self._copy()
|
|
@@ -400,40 +406,71 @@ class BaseCircuit(AbstractCircuit):
|
|
|
400
406
|
if i != j:
|
|
401
407
|
e ^ edge2[i]
|
|
402
408
|
for i in range(k):
|
|
403
|
-
|
|
404
|
-
i
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
newnodes
|
|
414
|
-
|
|
415
|
-
|
|
409
|
+
if self._d == 2:
|
|
410
|
+
m = (1 - sample[i]) * gates.array_to_tensor(
|
|
411
|
+
np.array([1, 0])
|
|
412
|
+
) + sample[i] * gates.array_to_tensor(np.array([0, 1]))
|
|
413
|
+
else:
|
|
414
|
+
m = onehot_d_tensor(sample[i], d=self._d)
|
|
415
|
+
g1 = Gate(m)
|
|
416
|
+
g1.id = id(g1)
|
|
417
|
+
g1.is_dagger = False
|
|
418
|
+
g1.flag = "measurement"
|
|
419
|
+
newnodes.append(g1)
|
|
420
|
+
g1.get_edge(0) ^ edge1[index[i]]
|
|
421
|
+
g2 = Gate(m)
|
|
422
|
+
g2.id = id(g2)
|
|
423
|
+
g2.is_dagger = True
|
|
424
|
+
g2.flag = "measurement"
|
|
425
|
+
newnodes.append(g2)
|
|
426
|
+
g2.get_edge(0) ^ edge2[index[i]]
|
|
427
|
+
|
|
416
428
|
rho = (
|
|
417
429
|
1
|
|
418
430
|
/ backend.cast(p, dtypestr)
|
|
419
431
|
* contractor(newnodes, output_edge_order=[edge1[j], edge2[j]]).tensor
|
|
420
432
|
)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
433
|
+
if self._d == 2:
|
|
434
|
+
pu = backend.real(rho[0, 0])
|
|
435
|
+
if status is None:
|
|
436
|
+
r = backend.implicit_randu()[0]
|
|
437
|
+
else:
|
|
438
|
+
r = status[k]
|
|
439
|
+
r = backend.real(backend.cast(r, dtypestr))
|
|
440
|
+
eps = 0.31415926 * 1e-12
|
|
441
|
+
sign = (
|
|
442
|
+
backend.sign(r - pu + eps) / 2 + 0.5
|
|
443
|
+
) # in case status is exactly 0.5
|
|
444
|
+
sign = backend.convert_to_tensor(sign)
|
|
445
|
+
sign = backend.cast(sign, dtype=rdtypestr)
|
|
446
|
+
sign_complex = backend.cast(sign, dtypestr)
|
|
447
|
+
sample.append(sign_complex)
|
|
448
|
+
p = p * (pu * (-1) ** sign + sign)
|
|
424
449
|
else:
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
450
|
+
pu = backend.clip(
|
|
451
|
+
backend.real(backend.diagonal(rho)),
|
|
452
|
+
backend.convert_to_tensor(0.0),
|
|
453
|
+
backend.convert_to_tensor(1.0),
|
|
454
|
+
)
|
|
455
|
+
pu = pu / backend.sum(pu)
|
|
456
|
+
if status is None:
|
|
457
|
+
ind = backend.implicit_randc(
|
|
458
|
+
a=backend.arange(self._d),
|
|
459
|
+
shape=1,
|
|
460
|
+
p=backend.cast(pu, rdtypestr),
|
|
461
|
+
)
|
|
462
|
+
else:
|
|
463
|
+
one_r = backend.cast(backend.convert_to_tensor(1.0), rdtypestr)
|
|
464
|
+
st = backend.cast(status[k : k + 1], rdtypestr)
|
|
465
|
+
ind = backend.probability_sample(
|
|
466
|
+
shots=1,
|
|
467
|
+
p=backend.cast(pu, rdtypestr),
|
|
468
|
+
status=one_r - st,
|
|
469
|
+
)
|
|
470
|
+
k_out = backend.cast(ind[0], "int32")
|
|
471
|
+
sample.append(backend.cast(k_out, rdtypestr))
|
|
472
|
+
p = p * backend.cast(pu[k_out], rdtypestr)
|
|
473
|
+
sample = backend.real(backend.stack(sample))
|
|
437
474
|
if with_prob:
|
|
438
475
|
return sample, p
|
|
439
476
|
else:
|
|
@@ -453,25 +490,22 @@ class BaseCircuit(AbstractCircuit):
|
|
|
453
490
|
:return: The tensornetwork nodes for the amplitude of the circuit.
|
|
454
491
|
:rtype: List[Gate]
|
|
455
492
|
"""
|
|
493
|
+
|
|
456
494
|
no, d_edges = self._copy()
|
|
457
495
|
ms = []
|
|
458
496
|
if self.is_dm:
|
|
459
497
|
msconj = []
|
|
460
498
|
if isinstance(l, str):
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
endn = np.array([1, 0], dtype=npdtype)
|
|
466
|
-
ms.append(tn.Node(endn))
|
|
499
|
+
symbols = _decode_basis_label(l, n=self._nqubits, dim=self._d)
|
|
500
|
+
for k in symbols:
|
|
501
|
+
n = onehot_d_tensor(k, d=self._d)
|
|
502
|
+
ms.append(tn.Node(n))
|
|
467
503
|
if self.is_dm:
|
|
468
|
-
msconj.append(tn.Node(
|
|
469
|
-
else:
|
|
504
|
+
msconj.append(tn.Node(n))
|
|
505
|
+
else:
|
|
470
506
|
l = backend.cast(l, dtype=dtypestr)
|
|
471
507
|
for i in range(self._nqubits):
|
|
472
|
-
endn = l[i]
|
|
473
|
-
1 - l[i]
|
|
474
|
-
) * gates.array_to_tensor(np.array([1, 0]))
|
|
508
|
+
endn = onehot_d_tensor(l[i], d=self._d)
|
|
475
509
|
ms.append(tn.Node(endn))
|
|
476
510
|
if self.is_dm:
|
|
477
511
|
msconj.append(tn.Node(endn))
|
|
@@ -522,17 +556,18 @@ class BaseCircuit(AbstractCircuit):
|
|
|
522
556
|
|
|
523
557
|
def probability(self) -> Tensor:
|
|
524
558
|
"""
|
|
525
|
-
get the
|
|
559
|
+
get the d^n length probability vector over computational basis
|
|
526
560
|
|
|
527
|
-
:return: probability vector
|
|
561
|
+
:return: probability vector of shape [dim**n]
|
|
528
562
|
:rtype: Tensor
|
|
529
563
|
"""
|
|
530
564
|
s = self.state() # type: ignore
|
|
531
565
|
if self.is_dm is False:
|
|
532
|
-
|
|
533
|
-
|
|
566
|
+
amp = backend.reshape(s, [-1])
|
|
567
|
+
p = backend.real(backend.abs(amp) ** 2)
|
|
534
568
|
else:
|
|
535
|
-
|
|
569
|
+
diag = backend.diagonal(s)
|
|
570
|
+
p = backend.real(backend.reshape(diag, [-1]))
|
|
536
571
|
return p
|
|
537
572
|
|
|
538
573
|
@partial(arg_alias, alias_dict={"format": ["format_"]})
|
|
@@ -546,7 +581,7 @@ class BaseCircuit(AbstractCircuit):
|
|
|
546
581
|
status: Optional[Tensor] = None,
|
|
547
582
|
jittable: bool = True,
|
|
548
583
|
) -> Any:
|
|
549
|
-
"""
|
|
584
|
+
r"""
|
|
550
585
|
batched sampling from state or circuit tensor network directly
|
|
551
586
|
|
|
552
587
|
:param batch: number of samples, defaults to None
|
|
@@ -569,6 +604,7 @@ class BaseCircuit(AbstractCircuit):
|
|
|
569
604
|
"count_tuple": # (np.array([0]), np.array([2]))
|
|
570
605
|
|
|
571
606
|
"count_dict_bin": # {"00": 2, "01": 0, "10": 0, "11": 0}
|
|
607
|
+
for cases d\in [11, 36], use 0-9A-Z digits (e.g., 'A' -> 10, ..., 'Z' -> 35);
|
|
572
608
|
|
|
573
609
|
"count_dict_int": # {0: 2, 1: 0, 2: 0, 3: 0}
|
|
574
610
|
|
|
@@ -576,7 +612,8 @@ class BaseCircuit(AbstractCircuit):
|
|
|
576
612
|
:param random_generator: random generator, defaults to None
|
|
577
613
|
:type random_generator: Optional[Any], optional
|
|
578
614
|
:param status: external randomness given by tensor uniformly from [0, 1],
|
|
579
|
-
if set, can overwrite random_generator
|
|
615
|
+
if set, can overwrite random_generator, shape [batch] for `allow_state=True`
|
|
616
|
+
and shape [batch, nqubits] for `allow_state=False` using perfect sampling implementation
|
|
580
617
|
:type status: Optional[Tensor]
|
|
581
618
|
:param jittable: when converting to count, whether keep the full size. if false, may be conflict
|
|
582
619
|
external jit, if true, may fail for large scale system with actual limited count results
|
|
@@ -597,25 +634,29 @@ class BaseCircuit(AbstractCircuit):
|
|
|
597
634
|
return r
|
|
598
635
|
r = [r] # type: ignore
|
|
599
636
|
else:
|
|
637
|
+
r = [] # type: ignore
|
|
638
|
+
if status is not None:
|
|
639
|
+
assert backend.shape_tuple(status)[0] == batch
|
|
640
|
+
for seed in status:
|
|
641
|
+
r.append(self.perfect_sampling(seed)) # type: ignore
|
|
600
642
|
|
|
601
|
-
|
|
602
|
-
def perfect_sampling(key: Any) -> Any:
|
|
603
|
-
backend.set_random_state(key)
|
|
604
|
-
return self.perfect_sampling()
|
|
643
|
+
else:
|
|
605
644
|
|
|
606
|
-
|
|
645
|
+
@backend.jit
|
|
646
|
+
def perfect_sampling(key: Any) -> Any:
|
|
647
|
+
backend.set_random_state(key)
|
|
648
|
+
return self.perfect_sampling()
|
|
607
649
|
|
|
608
|
-
|
|
650
|
+
subkey = random_generator
|
|
651
|
+
for _ in range(batch):
|
|
652
|
+
key, subkey = backend.random_split(subkey)
|
|
653
|
+
r.append(perfect_sampling(key)) # type: ignore
|
|
609
654
|
|
|
610
|
-
subkey = random_generator
|
|
611
|
-
for _ in range(batch):
|
|
612
|
-
key, subkey = backend.random_split(subkey)
|
|
613
|
-
r.append(perfect_sampling(key)) # type: ignore
|
|
614
655
|
if format is None:
|
|
615
656
|
return r
|
|
616
657
|
r = backend.stack([ri[0] for ri in r]) # type: ignore
|
|
617
|
-
|
|
618
|
-
ch = sample_bin2int(r, self._nqubits)
|
|
658
|
+
ch = backend.cast(r, "int32")
|
|
659
|
+
# ch = sample_bin2int(r, self._nqubits, dim=self._d)
|
|
619
660
|
else: # allow_state
|
|
620
661
|
if batch is None:
|
|
621
662
|
nbatch = 1
|
|
@@ -640,7 +681,7 @@ class BaseCircuit(AbstractCircuit):
|
|
|
640
681
|
# 2,
|
|
641
682
|
# )
|
|
642
683
|
if format is None: # for backward compatibility
|
|
643
|
-
confg = sample_int2bin(ch, self._nqubits)
|
|
684
|
+
confg = sample_int2bin(ch, self._nqubits, dim=self._d)
|
|
644
685
|
prob = backend.gather1d(p, ch)
|
|
645
686
|
r = list(zip(confg, prob)) # type: ignore
|
|
646
687
|
if batch is None:
|
|
@@ -648,7 +689,9 @@ class BaseCircuit(AbstractCircuit):
|
|
|
648
689
|
return r
|
|
649
690
|
if self._nqubits > 35:
|
|
650
691
|
jittable = False
|
|
651
|
-
return sample2all(
|
|
692
|
+
return sample2all(
|
|
693
|
+
sample=ch, n=self._nqubits, format=format, jittable=jittable, dim=self._d
|
|
694
|
+
)
|
|
652
695
|
|
|
653
696
|
def sample_expectation_ps(
|
|
654
697
|
self,
|
|
@@ -848,9 +891,9 @@ class BaseCircuit(AbstractCircuit):
|
|
|
848
891
|
"""
|
|
849
892
|
inputs = backend.reshape(inputs, [-1])
|
|
850
893
|
N = inputs.shape[0]
|
|
851
|
-
n =
|
|
894
|
+
n = _infer_num_sites(N, self._d)
|
|
852
895
|
assert n == self._nqubits
|
|
853
|
-
inputs = backend.reshape(inputs, [
|
|
896
|
+
inputs = backend.reshape(inputs, [self._d for _ in range(n)])
|
|
854
897
|
if self.inputs is not None:
|
|
855
898
|
self._nodes[0].tensor = inputs
|
|
856
899
|
if self.is_dm:
|
|
@@ -881,9 +924,9 @@ class BaseCircuit(AbstractCircuit):
|
|
|
881
924
|
|
|
882
925
|
|
|
883
926
|
|
|
884
|
-
:param index: the
|
|
927
|
+
:param index: the site index for the Z-basis measurement
|
|
885
928
|
:type index: int
|
|
886
|
-
:return: 0 or 1 for
|
|
929
|
+
:return: 0 or 1 for Z-basis measurement outcome
|
|
887
930
|
:rtype: Tensor
|
|
888
931
|
"""
|
|
889
932
|
return self.general_kraus( # type: ignore
|
|
@@ -962,8 +1005,8 @@ class BaseCircuit(AbstractCircuit):
|
|
|
962
1005
|
|
|
963
1006
|
def projected_subsystem(self, traceout: Tensor, left: Tuple[int, ...]) -> Tensor:
|
|
964
1007
|
"""
|
|
965
|
-
remaining wavefunction or density matrix on
|
|
966
|
-
fixed
|
|
1008
|
+
remaining wavefunction or density matrix on sites in ``left``, with other sites
|
|
1009
|
+
fixed to given digits (0..d-1) as indicated by ``traceout``
|
|
967
1010
|
|
|
968
1011
|
:param traceout: can be jitted
|
|
969
1012
|
:type traceout: Tensor
|
|
@@ -972,15 +1015,14 @@ class BaseCircuit(AbstractCircuit):
|
|
|
972
1015
|
:return: _description_
|
|
973
1016
|
:rtype: Tensor
|
|
974
1017
|
"""
|
|
975
|
-
|
|
1018
|
+
|
|
976
1019
|
traceout = backend.cast(traceout, dtypestr)
|
|
977
1020
|
nodes, front = self._copy()
|
|
978
1021
|
L = self._nqubits
|
|
979
1022
|
edges = []
|
|
980
1023
|
for i in range(len(traceout)):
|
|
981
1024
|
if i not in left:
|
|
982
|
-
|
|
983
|
-
n = gates.Gate((1 - b) * end0 + b * end1)
|
|
1025
|
+
n = Gate(onehot_d_tensor(traceout[i], d=self._d))
|
|
984
1026
|
nodes.append(n)
|
|
985
1027
|
front[i] ^ n[0]
|
|
986
1028
|
else:
|
|
@@ -989,8 +1031,7 @@ class BaseCircuit(AbstractCircuit):
|
|
|
989
1031
|
if self.is_dm:
|
|
990
1032
|
for i in range(len(traceout)):
|
|
991
1033
|
if i not in left:
|
|
992
|
-
|
|
993
|
-
n = gates.Gate((1 - b) * end0 + b * end1)
|
|
1034
|
+
n = Gate(onehot_d_tensor(traceout[i], d=self._d))
|
|
994
1035
|
nodes.append(n)
|
|
995
1036
|
front[i + L] ^ n[0]
|
|
996
1037
|
else:
|