Download dense_evolution/utils/drawing.py from Tatopenn/dense-Evolution: direct link, hf CLI and curl.
- Browser
- Download file 3.76 kB
-
https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/utils/drawing.py
- Command line
-
hf download hf://Tatopenn/dense-Evolution/dense_evolution/utils/drawing.py
-
curl -L -o drawing.py https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/utils/drawing.py
3.76 kB
| """ | |
| Plain-text circuit diagrams -- the fast way to sanity-check what a | |
| gate-tuple list actually builds without running it, the same job | |
| Qiskit's `circuit.draw()` or Cirq's text diagrams do. | |
| Uses plain ASCII ('-', '|', '*') rather than Unicode box-drawing | |
| characters deliberately: a diagram meant to be printed to a terminal or | |
| written to a log file needs to survive whatever console encoding the | |
| caller happens to have (this was tested against, and would otherwise | |
| crash on, a default Windows cp1252 console). | |
| """ | |
| __all__ = ['draw_circuit'] | |
| _LABELS = { | |
| 'h': 'H', 'x': 'X', 'y': 'Y', 'z': 'Z', 's': 'S', 'sdg': 'Sdg', | |
| 't': 'T', 'tdg': 'Tdg', 'sx': 'Sx', 'id': 'I', | |
| 'rx': 'Rx', 'ry': 'Ry', 'rz': 'Rz', 'p': 'P', 'u1': 'P', 'phase': 'P', | |
| } | |
| _TWO_QUBIT_TARGET_SYMBOL = {'cx': 'X', 'cz': 'Z', 'cy': 'Y', 'cp': 'P', 'crz': 'Rz'} | |
| def draw_circuit(circuit, n_qubits): | |
| """ | |
| Render a circuit (in the gate-tuple form run_circuit accepts) as a | |
| plain-text diagram, one gate per column, one line per qubit. | |
| Parameters | |
| ---------- | |
| circuit : list[tuple] | |
| Gate ops, as passed to `DenseSVSimulator.run_circuit`. Supports | |
| every gate this package's transpiler recognizes: single-qubit | |
| static and parametric gates, cx/cz/cy/cp/crz, swap, and ccx. | |
| n_qubits : int | |
| Number of qubit rows to draw, must be >= 1 (should cover every | |
| qubit index referenced in `circuit`). | |
| Returns | |
| ------- | |
| str | |
| Multi-line diagram, one row per qubit (``q0: --H----*--``, ...). | |
| Print it, or split on '\\n' to inspect individual rows. | |
| Examples | |
| -------- | |
| >>> import dense_evolution as de | |
| >>> print(de.draw_circuit([('h', 0), ('cx', 0, 1)], n_qubits=2)) | |
| q0: --H----*-- | |
| q1: -------X-- | |
| """ | |
| if n_qubits < 1: | |
| raise ValueError(f"draw_circuit needs at least 1 qubit, got {n_qubits}") | |
| prefixes = [f"q{q}: " for q in range(n_qubits)] | |
| prefix_width = max(len(p) for p in prefixes) | |
| rows = [p.ljust(prefix_width) for p in prefixes] | |
| for op in circuit: | |
| name = op[0] | |
| col = {} # qubit -> symbol to draw in this column (None = plain wire) | |
| if name == 'swap': | |
| a, b = op[1], op[2] | |
| lo, hi = min(a, b), max(a, b) | |
| for q in range(n_qubits): | |
| col[q] = 'x' if q in (a, b) else ('|' if lo < q < hi else None) | |
| elif name == 'ccx': | |
| c1, c2, tgt = op[1], op[2], op[3] | |
| lo, hi = min(c1, c2, tgt), max(c1, c2, tgt) | |
| for q in range(n_qubits): | |
| if q in (c1, c2): | |
| col[q] = '*' | |
| elif q == tgt: | |
| col[q] = 'X' | |
| else: | |
| col[q] = '|' if lo < q < hi else None | |
| elif name in _TWO_QUBIT_TARGET_SYMBOL: | |
| ctrl, tgt = op[1], op[2] | |
| lo, hi = min(ctrl, tgt), max(ctrl, tgt) | |
| for q in range(n_qubits): | |
| if q == ctrl: | |
| col[q] = '*' | |
| elif q == tgt: | |
| col[q] = _TWO_QUBIT_TARGET_SYMBOL[name] | |
| else: | |
| col[q] = '|' if lo < q < hi else None | |
| else: | |
| q = op[1] | |
| col[q] = _LABELS.get(name, name.upper()) | |
| label_width = max((len(v) for v in col.values() if v is not None), default=1) | |
| seg_width = label_width + 4 # 2 filler chars on each side | |
| for q in range(n_qubits): | |
| content = col.get(q) | |
| if content is None: | |
| rows[q] += '-' * seg_width | |
| else: | |
| rows[q] += '--' + content.center(label_width) + '--' | |
| return '\n'.join(rows) | |