Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle confusion matrices in deferred measurements #5851

Merged
merged 27 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Merge branch 'master' into deferred-kraus2
  • Loading branch information
daxfohl authored Oct 11, 2022
commit 0f84860ab5fb4b92ec8935a686f30a92219257f6
1 change: 1 addition & 0 deletions cirq-core/cirq/ops/gate_operation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ def all_subclasses(cls):
# Private gates.
cirq.transformers.analytical_decompositions.two_qubit_to_fsim._BGate,
cirq.transformers.measurement_transformers._ConfusionChannel,
cirq.transformers.measurement_transformers._ModAdd,
cirq.transformers.routing.visualize_routed_circuit._SwapPrintGate,
cirq.ops.raw_types._InverseCompositeGate,
cirq.circuits.qasm_output.QasmTwoQubitGate,
Expand Down
38 changes: 37 additions & 1 deletion cirq-core/cirq/transformers/measurement_transformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,14 @@ def defer(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
key = value.MeasurementKey.parse_serialized(gate.key)
targets = [_MeasurementQid(key, q) for q in op.qubits]
measurement_qubits[key] = targets
cxs = [ops.CX(q, target) for q, target in zip(op.qubits, targets)]
cxs = [_mod_add(q, target) for q, target in zip(op.qubits, targets)]
confusions = [
_ConfusionChannel(m, [op.qubits[i].dimension for i in indexes]).on(
*[targets[i] for i in indexes]
)
for indexes, m in gate.confusion_map.items()
]
cxs = [_mod_add(q, target) for q, target in zip(op.qubits, targets)]
xs = [ops.X(targets[i]) for i, b in enumerate(gate.full_invert_mask()) if b]
return cxs + confusions + xs
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
elif protocols.is_measurement(op):
Expand Down Expand Up @@ -347,3 +348,38 @@ def _qid_shape_(self) -> Tuple[int, ...]:

def _kraus_(self) -> Tuple[np.ndarray, ...]:
viathor marked this conversation as resolved.
Show resolved Hide resolved
return self._kraus


@value.value_equality
class _ModAdd(ops.ArithmeticGate):
"""Adds two qudits of the same dimension.

Operates on two qudits by modular addition:

|a,b> -> |a,a+b mod d>"""

def __init__(self, dimension: int):
self._dimension = dimension

def registers(self) -> Tuple[Tuple[int], Tuple[int]]:
return (self._dimension,), (self._dimension,)

def with_registers(self, *new_registers) -> '_ModAdd':
raise NotImplementedError()

def apply(self, *register_values: int) -> Tuple[int, int]:
return register_values[0], sum(register_values)

def _value_equality_values_(self) -> int:
return self._dimension


def _mod_add(source: 'cirq.Qid', target: 'cirq.Qid') -> 'cirq.Operation':
assert source.dimension == target.dimension
if source.dimension == 2:
# Use a CX gate in 2D case for simplicity.
return ops.CX(source, target)
# We can use a ModAdd gate in the qudit case, since the ancilla qudit corresponding to the
# measurement is always zero, so "adding" the measured qudit to it sets the ancilla qudit to
# the same state, which is the quantum equivalent to a measurement onto a creg.
return _ModAdd(source.dimension).on(source, target)\
You are viewing a condensed version of this merge commit. You can view the full changes here.