in tensorflow_quantum/core/serialize/serializer.py [0:0]
def serialize_circuit(circuit_inp):
"""Returns a `cirq.Program` proto representing the `cirq.Circuit`.
Note that the circuit must use gates valid in the tfq_gate_set.
Currently we only support scalar multiplication of symbols and
no other more complex arithmetic expressions. This means
we can support things like X**(3*alpha), and Rx(alpha). Because
we use the `cirq.Program` proto, we only support `cirq.GridQubit`
and `cirq.LineQubit` instances during serialization of circuits.
Note: once serialized terminal measurements are removed.
Args:
circuit_inp: A `cirq.Circuit`.
Returns:
A `tfq.proto.Program` proto.
"""
circuit = copy.deepcopy(circuit_inp)
if not isinstance(circuit, cirq.Circuit):
raise TypeError("serialize requires cirq.Circuit objects."
" Given: " + str(type(circuit)))
# This code is intentionally written to avoid using cirq functions
# as this get analyzed by tensorflow-autograph.
# Gives a map from moment index to measure qubits in moment
measured_moments = dict()
# Tracks qubits that have been measured already.
all_measured_qubits = set()
for i, moment in enumerate(circuit.moments):
measured_qubits = set()
for op in moment:
for qubit in op.qubits:
if not isinstance(qubit, (cirq.GridQubit, cirq.LineQubit)):
raise ValueError(
"Attempted to serialize circuit that don't use "
"only cirq.GridQubits or cirq.LineQubits.")
if isinstance(op.gate, cirq.MeasurementGate):
for qubit in op.qubits:
if qubit in all_measured_qubits:
raise ValueError("Serialization of circuit failed. "
"Circuits with non-terminal "
"measurement operations are not "
"supported.")
measured_qubits.add(qubit)
all_measured_qubits.add(qubit)
if len(measured_qubits) > 0:
measured_moments[i] = measured_qubits
# Remove terminal measurements.
for moment_ind in measured_moments:
old_moment = circuit[moment_ind]
measured_qubits = measured_moments[moment_ind]
new_moment = cirq.Moment(
filter(lambda x: not any(y in measured_qubits for y in x.qubits),
old_moment.operations))
circuit[moment_ind] = new_moment
# Demote cirq.controlled_operations (controlled gates) to their sub_gate
# types with _tfq_control_qubits and _tfq_control_values fields so that
# the gates can still get picked up by the serializer. There would be no way
# to discern controlledgates from one another otherwise. This
# "momentary demotion" occurs with the help of the DelayedAssignmentGate.
for i, moment in enumerate(circuit):
controlled_ops = [
op for op in moment if isinstance(op, cirq.ControlledOperation)
]
new_ops = dict()
for op in controlled_ops:
tfq_compatible = op.sub_operation
tfq_compatible._tfq_control_qubits = op.controls
tfq_compatible._tfq_control_values = op.control_values
new_ops[op.qubits] = tfq_compatible
circuit[i] = cirq.Moment(
new_ops[op.qubits] if op.qubits in new_ops else op for op in moment)
return SERIALIZER.serialize(circuit)