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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Hence, occasionally changes will be backwards incompatible (although they will a
- `extract_circuit` raises `ValueError` for graphs containing ground vertices or mismatched input/output counts, instead of a `KeyError` crash (by @dlyongemallo).
- Missed copying `_grounds` in `clone()`, incorrectly checking destination `is_ground` instead of source in `tensor()` (by @dlyongemallo).
Comment thread
dlyongemallo marked this conversation as resolved.

### Removed
- `Measurement.to_graph_ground`; measurements now always use the symbolic boolean representation (by @dlyongemallo).

### Changed
- Migrated project configuration from `setup.py` to `pyproject.toml`. Make the `galois` package an optional dependency, as it is only used in `pyzx.web`. (by @dlyongemallo)
- Dropped support for Python 3.9 (end of life). Added support for Python 3.13. (by @dlyongemallo)
Expand Down
33 changes: 2 additions & 31 deletions pyzx/circuit/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -1561,32 +1561,6 @@ def reposition(self, mask, bit_mask = None):
g.result_bit = bit_mask[self.result_bit]
return g

def to_graph_ground(self, g, q_mapper, c_mapper):
"""Represent the measurement as a node with a ground symbol."""
# Discard previous bit value
if self.result_bit is not None:
DiscardBit(self.result_bit).to_graph(g, q_mapper, c_mapper)
# Qubit measurement
r = q_mapper.next_row(self.target)
if self.result_bit is not None:
r = max(r, c_mapper.next_row(self.result_bit))
v = self.graph_add_node(g,
q_mapper,
VertexType.Z,
self.target,
r,
ground=True)
q_mapper.set_next_row(self.target, r+1)
# Classical result
if self.result_bit is not None:
u = self.graph_add_node(g,
c_mapper,
VertexType.X,
self.result_bit,
r)
g.add_edge((v,u), EdgeType.SIMPLE)
c_mapper.set_next_row(self.result_bit, r+1)

def to_graph_symbolic_boolean(self, g, q_mapper):
"""Represent the measurement as a node with symbolic boolean phases."""
r = q_mapper.next_row(self.target)
Expand All @@ -1605,11 +1579,8 @@ def to_graph_symbolic_boolean(self, g, q_mapper):
phase=phase)
q_mapper.set_next_row(self.target, r+1)

def to_graph(self, g, q_mapper, c_mapper, ground=False):
if ground:
self.to_graph_ground(g, q_mapper, c_mapper)
else:
self.to_graph_symbolic_boolean(g, q_mapper)
def to_graph(self, g, q_mapper, _c_mapper):
self.to_graph_symbolic_boolean(g, q_mapper)

gate_types: Dict[str,Type[Gate]] = {
"XPhase": XPhase,
Expand Down
50 changes: 0 additions & 50 deletions tests/test_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,56 +1288,6 @@ def test_classical_bits_output_positions(self):
output_qubits = sorted(g.qubit(v) for v in g.outputs())
self.assertEqual(output_qubits, [0, 1, 2, 3])

def test_measurement_ground_mode_with_result_bit(self):
"""Measurement with result_bit in ground mode should use c_mapper."""
from pyzx.circuit.gates import Measurement
from pyzx.circuit.graphparser import circuit_to_graph
c = Circuit(1, bit_amount=1)
c.gates = [Measurement(0, result_bit=0)]
g = circuit_to_graph(c)
# 1 quantum input + 1 classical input = 2 inputs.
self.assertEqual(len(g.inputs()), 2)
# Measurement consumes the qubit (no quantum output), but
# the classical bit still gets an output boundary.
self.assertEqual(len(g.outputs()), 1)

def test_measurement_ground_mode_graph_structure(self):
"""Ground-mode measurement should create correct graph structure."""
from pyzx.circuit.gates import Measurement
from pyzx.circuit.graphparser import circuit_to_graph
from pyzx.utils import VertexType
c = Circuit(1, bit_amount=1)
m = Measurement(0, result_bit=0)
c.gates = [m]
g = circuit_to_graph(c)
# Count vertex types.
types = [g.type(v) for v in g.vertices()]
n_boundary = types.count(VertexType.BOUNDARY)
# 1 quantum input + 1 classical input + 1 classical output = 3.
self.assertEqual(n_boundary, 3)

def test_measurement_ground_mode_direct(self):
"""Directly test to_graph_ground with c_mapper labels."""
from pyzx.circuit.gates import Measurement, TargetMapper
from pyzx.utils import VertexType
from pyzx.graph import Graph
g = Graph()
q_mapper = TargetMapper()
c_mapper = TargetMapper()
# Set up one quantum wire and one classical wire.
q_in = g.add_vertex(VertexType.BOUNDARY, 0, 0)
c_in = g.add_vertex(VertexType.BOUNDARY, 1, 0)
q_mapper.add_label(0, 1)
q_mapper.set_prev_vertex(0, q_in)
c_mapper.add_label(0, 1)
c_mapper.set_qubit(0, 1)
c_mapper.set_prev_vertex(0, c_in)
# Call to_graph_ground directly.
m = Measurement(0, result_bit=0)
m.to_graph_ground(g, q_mapper, c_mapper)
# Should not crash, and the graph should have vertices.
self.assertGreater(len(list(g.vertices())), 2)

def test_hththt_t_injection_feedforward(self):
"""HTHTHT... circuit with T gates implemented via injection.

Expand Down
Loading