def defer_measurements(
    circuit: cirq.AbstractCircuit, *, context: cirq.TransformerContext | None = None
) -> cirq.Circuit:
    """Implements the Deferred Measurement Principle.

    Uses the Deferred Measurement Principle to move all measurements to the
    end of the circuit. All non-terminal measurements are changed to
    conditional quantum gates onto ancilla qubits, and classically controlled
    operations are transformed to quantum controls from those ancilla qubits.
    Finally, measurements of all ancilla qubits are appended to the end of the
    circuit.

    Optimizing deferred measurements is an area of active research, and future
    iterations may contain optimizations that reduce the number of ancilla
    qubits, so one should not depend on the exact shape of the output from this
    function. Only the logical equivalence is guaranteed to remain unchanged.
    Moment and subcircuit structure is not preserved.

    Args:
        circuit: The circuit to transform. It will not be modified.
        context: `cirq.TransformerContext` storing common configurable options
            for transformers.
    Returns:
        A circuit with equivalent logic, but all measurements at the end of the
        circuit.
    Raises:
        NotImplementedError: When attempting to defer a measurement with a
            confusion map. (https://github.com/quantumlib/Cirq/issues/5482)
    """

    circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)
    terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}
    measurement_qubits: dict[cirq.MeasurementKey, list[tuple[cirq.Qid, ...]]] = defaultdict(list)

    def defer(op: cirq.Operation, _) -> cirq.OP_TREE:
        if op in terminal_measurements:
            return op
        gate = op.gate
        if isinstance(gate, ops.MeasurementGate):
            key = value.MeasurementKey.parse_serialized(gate.key)
            targets = [_MeasurementQid(key, q, len(measurement_qubits[key])) for q in op.qubits]
            measurement_qubits[key].append(tuple(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()
            ]
            xs = [ops.X(targets[i]) for i, b in enumerate(gate.full_invert_mask()) if b]
            return cxs + confusions + xs
        elif protocols.is_measurement(op):
            return [defer(op, None) for op in protocols.decompose_once(op)]
        elif op.classical_controls:
            # Convert to a quantum control

            # First create a sorted set of the indexed keys for this control.
            keys = sorted(
                set(
                    indexed_key
                    for condition in op.classical_controls
                    for indexed_key in (
                        [(condition.key, condition.index)]
                        if isinstance(condition, value.KeyCondition)
                        else [(k, -1) for k in condition.keys]
                    )
                )
            )
            for key, index in keys:
                if key not in measurement_qubits:
                    raise ValueError(f'Deferred measurement for key={key} not found.')
                if index >= len(measurement_qubits[key]) or index < -len(measurement_qubits[key]):
                    raise ValueError(f'Invalid index for {key}')

            # Try every possible datastore state (exponential in the number of keys) against the
            # condition, and the ones that work are the control values for the new op.
            compatible_datastores = [
                store
                for store in _all_possible_datastore_states(keys, measurement_qubits)
                if all(c.resolve(store) for c in op.classical_controls)
            ]

            # Rearrange these into the format expected by SumOfProducts
            products = [
                [val for k, i in keys for val in store.records[k][i]]
                for store in compatible_datastores
            ]
            control_values = ops.SumOfProducts(products)
            qs = [q for k, i in keys for q in measurement_qubits[k][i]]
            return op.without_classical_controls().controlled_by(*qs, control_values=control_values)
        return op

    circuit = transformer_primitives.map_operations_and_unroll(
        circuit=circuit,
        map_func=defer,
        tags_to_ignore=context.tags_to_ignore if context else (),
        raise_if_add_qubits=False,
    ).unfreeze()
    for k, qubits_list in measurement_qubits.items():
        for qubits in qubits_list:
            circuit.append(ops.measure(*qubits, key=k))
    return circuit
Implements the Deferred Measurement Principle.

    Uses the Deferred Measurement Principle to move all measurements to the
    end of the circuit. All non-terminal measurements are changed to
    conditional quantum gates onto ancilla qubits, and classically controlled
    operations are transformed to quantum controls from those ancilla qubits.
    Finally, measurements of all ancilla qubits are appended to the end of the
    circuit.

    Optimizing deferred measurements is an area of active research, and future
    iterations may contain optimizations that reduce the number of ancilla
    qubits, so one should not depend on the exact shape of the output from this
    function. Only the logical equivalence is guaranteed to remain unchanged.
    Moment and subcircuit structure is not preserved.

    Args:
        circuit: The circuit to transform. It will not be modified.
        context: `cirq.TransformerContext` storing common configurable options
            for transformers.
    Returns:
        A circuit with equivalent logic, but all measurements at the end of the
        circuit.
    Raises:
        NotImplementedError: When attempting to defer a measurement with a
            confusion map. (https://github.com/quantumlib/Cirq/issues/5482)
    
cirq-core/cirq/transformers/measurement_transformers.py