Skip to content

Commit 274c67f

Browse files
support visualization on cond measure
1 parent bfe834a commit 274c67f

File tree

5 files changed

+53
-12
lines changed

5 files changed

+53
-12
lines changed

tensorcircuit/basecircuit.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ def cond_measurement(self, index: int) -> Tensor:
10921092
:rtype: Tensor
10931093
"""
10941094
return self.general_kraus( # type: ignore
1095-
[np.array([[1.0, 0], [0, 0]]), np.array([[0, 0], [0, 1]])], index # type: ignore
1095+
[np.array([[1.0, 0], [0, 0]]), np.array([[0, 0], [0, 1]])], index, name="measure" # type: ignore
10961096
)
10971097

10981098
cond_measure = cond_measurement

tensorcircuit/circuit.py

+22-5
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ def unitary_kraus2(
317317
*index: int,
318318
prob: Optional[Sequence[float]] = None,
319319
status: Optional[float] = None,
320+
name: Optional[str] = None,
320321
) -> Tensor:
321322
# general impl from Monte Carlo trajectory depolarizing above
322323
# still jittable
@@ -326,7 +327,12 @@ def index2gate2(r: Tensor, kraus: Sequence[Tensor]) -> Tensor:
326327
return backend.switch(r, [lambda _=k: _ for k in kraus])
327328

328329
return self._unitary_kraus_template(
329-
kraus, *index, prob=prob, status=status, get_gate_from_index=index2gate2
330+
kraus,
331+
*index,
332+
prob=prob,
333+
status=status,
334+
get_gate_from_index=index2gate2,
335+
name=name,
330336
)
331337

332338
def unitary_kraus(
@@ -335,6 +341,7 @@ def unitary_kraus(
335341
*index: int,
336342
prob: Optional[Sequence[float]] = None,
337343
status: Optional[float] = None,
344+
name: Optional[str] = None,
338345
) -> Tensor:
339346
"""
340347
Apply unitary gates in ``kraus`` randomly based on corresponding ``prob``.
@@ -360,7 +367,12 @@ def index2gate(r: Tensor, kraus: Sequence[Tensor]) -> Tensor:
360367
return reduce(add, [r[i] * kraus[i] for i in range(l)])
361368

362369
return self._unitary_kraus_template(
363-
kraus, *index, prob=prob, status=status, get_gate_from_index=index2gate
370+
kraus,
371+
*index,
372+
prob=prob,
373+
status=status,
374+
get_gate_from_index=index2gate,
375+
name=name,
364376
)
365377

366378
def _unitary_kraus_template(
@@ -372,6 +384,7 @@ def _unitary_kraus_template(
372384
get_gate_from_index: Optional[
373385
Callable[[Tensor, Sequence[Tensor]], Tensor]
374386
] = None,
387+
name: Optional[str] = None,
375388
) -> Tensor: # DRY
376389
sites = len(index)
377390
kraus = [k.tensor if isinstance(k, tn.Node) else k for k in kraus]
@@ -406,7 +419,7 @@ def step_function(x: Tensor) -> Tensor:
406419
raise ValueError("no `get_gate_from_index` implementation is provided")
407420
g = get_gate_from_index(r, kraus)
408421
g = backend.reshape(g, [2 for _ in range(sites * 2)])
409-
self.any(*index, unitary=g) # type: ignore
422+
self.any(*index, unitary=g, name=name) # type: ignore
410423
return r
411424

412425
def _general_kraus_tf(
@@ -482,6 +495,7 @@ def _general_kraus_2(
482495
kraus: Sequence[Gate],
483496
*index: int,
484497
status: Optional[float] = None,
498+
name: Optional[str] = None,
485499
) -> Tensor:
486500
# the graph building time is frustratingly slow, several minutes
487501
# though running time is in terms of ms
@@ -528,13 +542,16 @@ def calculate_kraus_p(i: int) -> Tensor:
528542
for w, k in zip(prob, kraus_tensor)
529543
]
530544

531-
return self.unitary_kraus2(new_kraus, *index, prob=prob, status=status)
545+
return self.unitary_kraus2(
546+
new_kraus, *index, prob=prob, status=status, name=name
547+
)
532548

533549
def general_kraus(
534550
self,
535551
kraus: Sequence[Gate],
536552
*index: int,
537553
status: Optional[float] = None,
554+
name: Optional[str] = None,
538555
) -> Tensor:
539556
"""
540557
Monte Carlo trajectory simulation of general Kraus channel whose Kraus operators cannot be
@@ -553,7 +570,7 @@ def general_kraus(
553570
when the random number will be generated automatically
554571
:type status: Optional[float], optional
555572
"""
556-
return self._general_kraus_2(kraus, *index, status=status)
573+
return self._general_kraus_2(kraus, *index, status=status, name=name)
557574

558575
apply_general_kraus = general_kraus
559576

tensorcircuit/densitymatrix.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def check_kraus(kraus: Sequence[Gate]) -> bool: # TODO(@refraction-ray)
175175
return True
176176

177177
def apply_general_kraus(
178-
self, kraus: Sequence[Gate], index: Sequence[Tuple[int, ...]]
178+
self, kraus: Sequence[Gate], index: Sequence[Tuple[int, ...]], **kws: Any
179179
) -> None:
180180
# note the API difference for index arg between DM and DM2
181181
self.check_kraus(kraus)
@@ -302,7 +302,7 @@ def to_circuit(self, circuit_params: Optional[Dict[str, Any]] = None) -> Circuit
302302

303303

304304
class DMCircuit2(DMCircuit):
305-
def apply_general_kraus(self, kraus: Sequence[Gate], *index: int) -> None: # type: ignore
305+
def apply_general_kraus(self, kraus: Sequence[Gate], *index: int, **kws: Any) -> None: # type: ignore
306306
# incompatible API for now
307307
kraus = [
308308
k

tensorcircuit/translation.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,27 @@
33
"""
44

55
from typing import Any, Dict, List, Optional
6-
import warnings
7-
6+
import logging
87
import numpy as np
98

9+
logger = logging.getLogger(__name__)
10+
11+
1012
try:
1113
from qiskit import QuantumCircuit
1214
import qiskit.quantum_info as qi
15+
from qiskit.extensions.exceptions import ExtensionError
1316
except ImportError:
14-
warnings.warn("Please first ``pip install qiskit`` to enable related functionality")
17+
logger.warning(
18+
"Please first ``pip install qiskit`` to enable related functionality"
19+
)
1520

1621
from . import gates
1722
from .circuit import Circuit
1823
from .densitymatrix import DMCircuit2
1924
from .cons import backend
2025

26+
2127
Tensor = Any
2228

2329

@@ -150,7 +156,16 @@ def qir2qiskit(qir: List[Dict[str, Any]], n: int) -> Any:
150156
[2 ** len(index), 2 ** len(index)],
151157
)
152158
)
153-
qiskit_circ.unitary(qop, index[::-1], label=qis_name)
159+
try:
160+
qiskit_circ.unitary(qop, index[::-1], label=qis_name)
161+
except ExtensionError:
162+
logger.warning(
163+
"omit non unitary gate in tensorcircuit when transforming to qiskit"
164+
)
165+
qiskit_circ.unitary(
166+
np.eye(2 ** len(index)), index[::-1], label=qis_name
167+
)
168+
154169
return qiskit_circ
155170

156171

tests/test_circuit.py

+9
Original file line numberDiff line numberDiff line change
@@ -1073,3 +1073,12 @@ def amp(s):
10731073
np.testing.assert_allclose(
10741074
amp(tc.array_to_tensor([0, 0, 0], dtype="float32")), 1 / np.sqrt(2), atol=1e-5
10751075
)
1076+
1077+
1078+
def test_draw_cond_measure():
1079+
c = tc.Circuit(2)
1080+
c.H(0)
1081+
c.cond_measure(0)
1082+
c.cnot(0, 1)
1083+
print("")
1084+
print(c.draw())

0 commit comments

Comments
 (0)