Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ classifiers = [
dynamic = ["version"]
dependencies = [
"anywidget>=0.9.18",
"cirq>=1.3.0",
"ply>=3.11",
"qiskit>=2.1.2",
"stim>=1.15.0",
"stimcirq>=1.15.0",
"traitlets>=5.14.3",
]

Expand Down
66 changes: 66 additions & 0 deletions src/crumpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
import pathlib

import anywidget
import cirq
import qiskit
import qiskit.qasm3
import stim
import stimcirq
import traitlets
from cirq.contrib.qasm_import import circuit_from_qasm

__version__ = "0.0.0"

Expand Down Expand Up @@ -42,3 +48,63 @@ class CircuitWidget(anywidget.AnyWidget):
)
indentCircuitLines = traitlets.Bool(True).tag(sync=True)
curveConnectors = traitlets.Bool(True).tag(sync=True)

@staticmethod
def from_cirq(cirq_circuit: cirq.Circuit):
"""Create a `CircuitWidget` from a `cirq.Circuit`.

`cirq_circuit` will be transpiled to a `stim.Circuit` before use with `CircuitWidget`.
`cirq_circuit` must be transpilable to a `stim.Circuit`.

Parameters
----------
cirq_circuit : cirq.Circuit
cirq circuit to visualize

Raises
------
TypeError
If `cirq_circuit` is unable to be converted to a `stim.Circuit`
"""
try:
stim_circuit = stimcirq.cirq_circuit_to_stim_circuit(cirq_circuit)
return CircuitWidget(stim=str(stim_circuit))
except TypeError as ex:
msg = "Unable to translate cirq circuit to stim."
raise TypeError(msg) from ex

@staticmethod
def from_qiskit(qiskit_circuit: qiskit.QuantumCircuit):
"""Create a `CircuitWidget` from a `qiskit.QuantumCircuit`.

`qiskit_circuit` will be transpiled to a `stim.Circuit` before use with `CircuitWidget`.
`qiskit_circuit` must be transpilable to a `stim.Circuit`.

Parameters
----------
qiskit_circuit : qiskit.QuantumCircuit
qiskit circuit to visualize

Raises
------
TypeError
If `qiskit_circuit` is unable to be converted to a `stim.Circuit`
"""
try:
qasm_circuit = qiskit.qasm3.dumps(qiskit_circuit)
cirq_circuit = circuit_from_qasm(qasm_circuit)
return CircuitWidget.from_cirq(cirq_circuit)
except TypeError as ex:
msg = "Unable to translate qiskit circuit to stim."
raise TypeError(msg) from ex

@staticmethod
def from_stim(stim_circuit: stim.Circuit):
"""Create a `CircuitWidget` from a `stim.Circuit`.

Parameters
----------
stim_circuit : stim.Circuit
stim circuit to visualize
"""
return CircuitWidget(stim=str(stim_circuit))
62 changes: 62 additions & 0 deletions tests/test_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

from __future__ import annotations

import cirq
import ipywidgets
import pytest
import qiskit
import stim
import traitlets

from crumpy import CircuitWidget
Expand Down Expand Up @@ -58,3 +61,62 @@ def sliderToCircuit(slider_val):
new_stim = "Y 0;"
circuit.stim = new_stim
assert circuit.stim == new_stim


class Test_CircuitImporting:
def test_from_cirq_valid(self):
"""CircuitWidget.from_cirq should create a CircuitWidget with the correct circuit when given a valid (stim-transpilable) cirq circuit."""

q0 = cirq.LineQubit(0)
q1 = cirq.LineQubit(1)
cirq_circuit = cirq.Circuit(cirq.H(q0), cirq.CNOT(q0, q1))

widg = CircuitWidget.from_cirq(cirq_circuit)

assert "H 0" in widg.stim
assert "CNOT 0 1" in widg.stim or "CX 0 1" in widg.stim

def test_from_cirq_invalid(self):
"""CircuitWidget.from_cirq should raise an error when given an invalid (non-stim-transpilable) cirq circuit."""

q0 = cirq.LineQubit(0)
q1 = cirq.LineQubit(1)
cirq_circuit = cirq.Circuit(cirq.H(q0), cirq.CNOT(q0, q1), cirq.rx(2).on(q0))
with pytest.raises(TypeError):
CircuitWidget.from_cirq(cirq_circuit)

def test_from_qiskit_valid(self):
"""CircuitWidget.from_qiskit should create a CircuitWidget with the correct circuit when given a valid (stim-transpilable) qiskit circuit."""

qc = qiskit.QuantumCircuit(2)
qc.z(0)
qc.cx(1, 0)

widg = CircuitWidget.from_qiskit(qc)

assert "Z 0" in widg.stim
assert "CNOT 1 0" in widg.stim or "CX 1 0" in widg.stim

def test_from_qiskit_invalid(self):
"""CircuitWidget.from_qiskit should raise an error when given an invalid (non-stim-transpilable) qiskit circuit."""

qc = qiskit.QuantumCircuit(2)
qc.z(0)
qc.cx(1, 0)
qc.ry(1.234, 0)

with pytest.raises(TypeError):
CircuitWidget.from_qiskit(qc)

def test_from_stim(self):
"""CircuitWidget.from_stim should create a CircuitWidget with the given stim circuit."""

stim_circuit = stim.Circuit("""
X 1
CY 0 1
""")

widg = CircuitWidget.from_stim(stim_circuit)

assert "X 1" in widg.stim
assert "CY 0 1" in widg.stim # also covers alternate name ZCY
Loading
Loading