def test_scope_extern_wrapping_with_non_repeating_subcircuits(): def wrap(*ops): return cirq.CircuitOperation(cirq.FrozenCircuit(*ops)) def wrap_frozen(*ops): return cirq.FrozenCircuit(wrap(*ops)) q = cirq.LineQubit(0) inner = wrap_frozen(wrap(cirq.measure(q, key='a')), wrap(cirq.X(q).with_classical_controls('b'))) middle = wrap_frozen( wrap(cirq.measure(q, key=cirq.MeasurementKey('b'))), wrap(cirq.CircuitOperation(inner, repetitions=2)), ) outer_subcircuit = cirq.CircuitOperation(middle, repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['0:b', '0:b', '1:b', '1:b'] assert not cirq.control_keys(outer_subcircuit) assert not cirq.control_keys(circuit) cirq.testing.assert_has_diagram( circuit, """ 0: ─────M───M('0:0:a')───X───M('0:1:a')───X───M───M('1:0:a')───X───M('1:1:a')───X─── ║ ║ ║ ║ ║ ║ 0:b: ═══@════════════════^════════════════^═══╬════════════════╬════════════════╬═══ ║ ║ ║ 1:b: ═════════════════════════════════════════@════════════════^════════════════^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_control_key(): class Named: def _control_keys_(self): return frozenset([cirq.MeasurementKey('key')]) class NoImpl: def _control_keys_(self): return NotImplemented assert cirq.control_keys(Named()) == {cirq.MeasurementKey('key')} assert not cirq.control_keys(NoImpl()) assert not cirq.control_keys(5)
def test_parameterized_repeat_side_effects_when_not_using_rep_ids(): q = cirq.LineQubit(0) op = cirq.CircuitOperation( cirq.FrozenCircuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key='m')), repetitions=sympy.Symbol('a'), use_repetition_ids=False, ) assert cirq.control_keys(op) == {cirq.MeasurementKey('c')} assert cirq.parameter_names(op.with_params({'a': 1})) == {'a'} assert set(map(str, cirq.measurement_key_objs(op))) == {'m'} assert cirq.measurement_key_names(op) == {'m'} assert cirq.measurement_key_names( cirq.with_measurement_key_mapping(op, {'m': 'm2'})) == {'m2'} with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): op.mapped_circuit() with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.decompose(op) with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.with_repetition_ids(['x', 'y']) with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.repeat(repetition_ids=['x', 'y'])
def test_condition_stacking(): q0 = cirq.LineQubit(0) op = cirq.X(q0).with_classical_controls('a').with_tags( 't').with_classical_controls('b') assert set(map(str, cirq.control_keys(op))) == {'a', 'b'} assert set(map(str, op.classical_controls)) == {'a', 'b'} assert not op.tags
def test_control_key_enumerable_deprecated(): class Deprecated: def _control_keys_(self): return [cirq.MeasurementKey('key')] with cirq.testing.assert_deprecated('frozenset', deadline='v0.16'): assert cirq.control_keys(Deprecated()) == {cirq.MeasurementKey('key')}
def test_condition_removal(): q0 = cirq.LineQubit(0) op = (cirq.X(q0).with_tags('t1').with_classical_controls('a').with_tags( 't2').with_classical_controls('b')) op = op.without_classical_controls() assert not cirq.control_keys(op) assert not op.classical_controls assert not op.tags
def test_scope_extern_mismatch(): q = cirq.LineQubit(0) inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('b'), ) middle = cirq.Circuit( cirq.measure(q, key=cirq.MeasurementKey('b', ('0', ))), cirq.CircuitOperation(inner.freeze(), repetitions=2), ) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['b', 'b', 'b', 'b'] assert cirq.control_keys(outer_subcircuit) == {cirq.MeasurementKey('b')} assert cirq.control_keys(circuit) == {cirq.MeasurementKey('b')} cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M('a')───X─── ] ] [ 0: ───M('0:b')───[ ║ ]──────────── ] 0: ───[ [ b: ════════════^═══ ](loops=2) ]──────────── [ ║ ] [ b: ══════════════╩══════════════════════════════════ ](loops=2) ║ b: ═══╩═══════════════════════════════════════════════════════════════════ """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───M('0:0:b')───M('0:0:a')───X───M('0:1:a')───X───M('1:0:b')───M('1:0:a')───X───M('1:1:a')───X─── ║ ║ ║ ║ b: ═════════════════════════════^════════════════^═════════════════════════════^════════════════^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_scope_local(): q = cirq.LineQubit(0) inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('a'), ) middle = cirq.Circuit(cirq.CircuitOperation(inner.freeze(), repetitions=2)) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['0:0:a', '0:1:a', '1:0:a', '1:1:a'] assert not cirq.control_keys(outer_subcircuit) assert not cirq.control_keys(circuit) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M───X─── ] ] 0: ───[ 0: ───[ ║ ║ ]──────────── ]──────────── [ [ a: ═══@═══^═══ ](loops=2) ](loops=2) """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───────M───X───M───X───M───X───M───X─── ║ ║ ║ ║ ║ ║ ║ ║ 0:0:a: ═══@═══^═══╬═══╬═══╬═══╬═══╬═══╬═══ ║ ║ ║ ║ ║ ║ 0:1:a: ═══════════@═══^═══╬═══╬═══╬═══╬═══ ║ ║ ║ ║ 1:0:a: ═══════════════════@═══^═══╬═══╬═══ ║ ║ 1:1:a: ═══════════════════════════@═══^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_scope_flatten_both(): q = cirq.LineQubit(0) inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('a'), ) middle = cirq.Circuit( cirq.CircuitOperation(inner.freeze(), repetitions=2, use_repetition_ids=False)) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2, use_repetition_ids=False) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['a', 'a', 'a', 'a'] assert not cirq.control_keys(outer_subcircuit) assert not cirq.control_keys(circuit) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M───X─── ] ] 0: ───[ 0: ───[ ║ ║ ]──────────────────────── ]──────────────────────── [ [ a: ═══@═══^═══ ](loops=2, no_rep_ids) ](loops=2, no_rep_ids) """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───M───X───M───X───M───X───M───X─── ║ ║ ║ ║ ║ ║ ║ ║ a: ═══@═══^═══@═══^═══@═══^═══@═══^═══ """, use_unicode_characters=True, )
def test_repeat_until_sympy(sim): q1, q2 = cirq.LineQubit.range(2) circuitop = cirq.CircuitOperation( cirq.FrozenCircuit(cirq.X(q2), cirq.measure(q2, key='b')), use_repetition_ids=False, repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('a'), sympy.Symbol('b'))), ) c = cirq.Circuit(cirq.measure(q1, key='a'), circuitop) # Validate commutation assert len(c) == 2 assert cirq.control_keys(circuitop) == {cirq.MeasurementKey('a')} measurements = sim.run(c).records['b'][0] assert len(measurements) == 2 assert measurements[0] == (1,) assert measurements[1] == (0,)
def test_control_keys_caching(): q0, q1, q2, q3 = cirq.LineQubit.range(4) m = cirq.Moment(cirq.X(q0).with_classical_controls('foo')) assert m._control_keys is None keys = cirq.control_keys(m) assert m._control_keys == keys # Make sure it gets updated when adding an operation. m = m.with_operation(cirq.X(q1).with_classical_controls('bar')) assert m._control_keys == { cirq.MeasurementKey(name='bar'), cirq.MeasurementKey(name='foo') } # Or multiple operations. m = m.with_operations( cirq.X(q2).with_classical_controls('doh'), cirq.X(q3).with_classical_controls('baz')) assert m._control_keys == { cirq.MeasurementKey(name='bar'), cirq.MeasurementKey(name='foo'), cirq.MeasurementKey(name='doh'), cirq.MeasurementKey(name='baz'), }
def test_parameterized_repeat_side_effects(): q = cirq.LineQubit(0) op = cirq.CircuitOperation( cirq.FrozenCircuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key='m')), repetitions=sympy.Symbol('a'), ) # Control keys can be calculated because they only "lift" if there's a matching # measurement, in which case they're not returned here. assert cirq.control_keys(op) == {cirq.MeasurementKey('c')} # "local" params do not bind to the repetition param. assert cirq.parameter_names(op.with_params({'a': 1})) == {'a'} # Check errors that require unrolling the circuit. with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.measurement_key_objs(op) with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.measurement_key_names(op) with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): op.mapped_circuit() with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.decompose(op) # Not compatible with repetition ids with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.with_repetition_ids(['x', 'y']) with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.repeat(repetition_ids=['x', 'y']) # TODO(daxfohl): This should work, but likely requires a new protocol that returns *just* the # name of the measurement keys. (measurement_key_names returns the full serialized string). with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.with_measurement_key_mapping(op, {'m': 'm2'}) # Everything should work once resolved op = cirq.resolve_parameters(op, {'a': 2}) assert set(map(str, cirq.measurement_key_objs(op))) == {'0:m', '1:m'} assert op.mapped_circuit() == cirq.Circuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('0:m')), cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('1:m')), ) assert cirq.decompose(op) == cirq.decompose( cirq.Circuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('0:m')), cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('1:m')), ))
def test_sympy_scope(): q = cirq.LineQubit(0) a, b, c, d = sympy.symbols('a b c d') inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls(a & b).with_classical_controls(c | d), ) middle = cirq.Circuit( cirq.measure(q, key='b'), cirq.measure(q, key=cirq.MeasurementKey('c', ('0', ))), cirq.CircuitOperation(inner.freeze(), repetitions=2), ) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_controls = [ str(k) for op in circuit.all_operations() for k in cirq.control_keys(op) ] assert set(internal_controls) == { '0:0:a', '0:1:a', '1:0:a', '1:1:a', '0:b', '1:b', 'c', 'd' } assert cirq.control_keys(outer_subcircuit) == {'c', 'd'} assert cirq.control_keys(circuit) == {'c', 'd'} assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit)) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M───X(conditions=[c | d, a & b])─── ] ] [ [ ║ ║ ] ] [ [ a: ═══@═══^══════════════════════════════ ] ] [ [ ║ ] ] [ 0: ───M───M('0:c')───[ b: ═══════^══════════════════════════════ ]──────────── ] [ ║ [ ║ ] ] [ ║ [ c: ═══════^══════════════════════════════ ] ] 0: ───[ ║ [ ║ ] ]──────────── [ ║ [ d: ═══════^══════════════════════════════ ](loops=2) ] [ ║ ║ ] [ b: ═══@══════════════╬════════════════════════════════════════════════════════ ] [ ║ ] [ c: ══════════════════╬════════════════════════════════════════════════════════ ] [ ║ ] [ d: ══════════════════╩════════════════════════════════════════════════════════ ](loops=2) ║ c: ═══╬═════════════════════════════════════════════════════════════════════════════════════════════ ║ d: ═══╩═════════════════════════════════════════════════════════════════════════════════════════════ """, use_unicode_characters=True, ) # pylint: disable=line-too-long cirq.testing.assert_has_diagram( circuit, """ 0: ───────M───M('0:0:c')───M───X(conditions=[c | d, 0:0:a & 0:b])───M───X(conditions=[c | d, 0:1:a & 0:b])───M───M('1:0:c')───M───X(conditions=[c | d, 1:0:a & 1:b])───M───X(conditions=[c | d, 1:1:a & 1:b])─── ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ 0:0:a: ═══╬════════════════@═══^════════════════════════════════════╬═══╬════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ ║ ║ 0:1:a: ═══╬════════════════════╬════════════════════════════════════@═══^════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ ║ 0:b: ═════@════════════════════^════════════════════════════════════════^════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ 1:0:a: ════════════════════════╬════════════════════════════════════════╬════════════════════════════════════╬════════════════@═══^════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ 1:1:a: ════════════════════════╬════════════════════════════════════════╬════════════════════════════════════╬════════════════════╬════════════════════════════════════@═══^════════════════════════════════════ ║ ║ ║ ║ ║ 1:b: ══════════════════════════╬════════════════════════════════════════╬════════════════════════════════════@════════════════════^════════════════════════════════════════^════════════════════════════════════ ║ ║ ║ ║ c: ════════════════════════════^════════════════════════════════════════^═════════════════════════════════════════════════════════^════════════════════════════════════════^════════════════════════════════════ ║ ║ ║ ║ d: ════════════════════════════^════════════════════════════════════════^═════════════════════════════════════════════════════════^════════════════════════════════════════^════════════════════════════════════ """, use_unicode_characters=True, )
def test_sympy_path_prefix(): q = cirq.LineQubit(0) op = cirq.X(q).with_classical_controls(sympy.Symbol('b')) prefixed = cirq.with_key_path_prefix(op, ('0', )) assert cirq.control_keys(prefixed) == {'0:b'}