def test_joined_generator(self): generator1 = TwoRotsGenerator() generator2 = OneRotGenerator() grad = op_tree_generator_grad( OpTreeGenerator.join(generator1, generator2), rad ) grad_lco = LinearCombinationOfOperations({ _generator((q0, q1)): _coeff for _generator, _coeff in grad.items() }) for _generator, _coeff in grad.items(): print(_generator.diagram(), _coeff) exact_grad_lco = LinearCombinationOfOperations({ (X(q0), rx(rad).on(q0), rz(rad).on(q1), ry(c * rad).on(q0)): -0.5j, (rx(rad).on(q0), Z(q1), rz(rad).on(q1), ry(c * rad).on(q0)): -0.5j, (rx(rad).on(q0), rz(rad).on(q1), Y(q0), ry(c * rad).on(q0)): -0.5j * c, }) param_resolver = { rad: np.random.rand() * 4 * np.pi, c: np.random.rand() } grad_lco = cirq.resolve_parameters(grad_lco, param_resolver) exact_grad_lco = cirq.resolve_parameters(exact_grad_lco, param_resolver) test_lco_identical_with_simulator( grad_lco, exact_grad_lco, self )
def test_tf_gradient_correctness_with_symbols(self, n_qubits, batch_size, inner_dim_size): """Tests that tf.gradient of inner_product works with symbols.""" symbol_names = ['alpha', 'beta', 'gamma'] n_params = len(symbol_names) qubits = cirq.GridQubit.rect(1, n_qubits) circuit_batch, resolver_batch = \ util.random_symbol_circuit_resolver_batch( qubits, symbol_names, batch_size) other_batch = [0 for i in range(batch_size)] for i in range(len(other_batch)): other_batch[i] = copy.deepcopy(circuit_batch) for j in range(len(other_batch[i])): other_batch[i][j] = cirq.resolve_parameters( circuit_batch[i], resolver_batch[i]) symbol_values_array = np.array( [[resolver[symbol] for symbol in symbol_names] for resolver in resolver_batch]) programs = util.convert_to_tensor(circuit_batch) other_programs = util.convert_to_tensor(other_batch) symbol_names_tensor = tf.convert_to_tensor(symbol_names, dtype=tf.dtypes.string) symbol_values = tf.convert_to_tensor(symbol_values_array) with tf.GradientTape() as tape: tape.watch(symbol_values) ip = fidelity_op.fidelity(programs, symbol_names_tensor, symbol_values, other_programs) out = tape.gradient(ip, symbol_values) out_arr = np.zeros((batch_size, n_params), dtype=np.complex64) # dx came from _GRAD_EPS of core/src/adj_util.cc dx = 5e-3 for i in range(batch_size): for k, name in enumerate(symbol_names): if name in resolver_batch[i].param_dict: new_resolver = copy.deepcopy(resolver_batch[i]) new_resolver.param_dict[name] += dx final_circuit_p = cirq.resolve_parameters( circuit_batch[i], new_resolver) new_resolver = copy.deepcopy(resolver_batch[i]) new_resolver.param_dict[name] -= dx final_circuit_m = cirq.resolve_parameters( circuit_batch[i], new_resolver) final_wf_p = cirq.final_state_vector(final_circuit_p) final_wf_m = cirq.final_state_vector(final_circuit_m) # Performs central finite difference. for j in range(inner_dim_size): internal_wf = cirq.final_state_vector(other_batch[i][j]) fid_p = cirq.fidelity(final_wf_p, internal_wf) fid_m = cirq.fidelity(final_wf_m, internal_wf) grad_fid = 0.5 * (fid_p - fid_m) / dx out_arr[i][k] += grad_fid self.assertAllClose(out, out_arr, atol=1e-3) self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)
def test_resolve_parameters(): assert cirq.resolve_parameters(CExpZinGate(cirq.Symbol('a')), cirq.ParamResolver({'a': 0.5 })) == CExpZinGate(0.5) assert cirq.resolve_parameters(CExpZinGate(0.25), cirq.ParamResolver({})) == CExpZinGate(0.25)
def test_resolve_parameters(): class NoMethod: pass class ReturnsNotImplemented: def _is_parameterized_(self): return NotImplemented def _resolve_parameters_(self, resolver): return NotImplemented class SimpleParameterSwitch: def __init__(self, var): self.parameter = var def _is_parameterized_(self) -> bool: return self.parameter == 0 def _resolve_parameters_(self, resolver: ParamResolver): self.parameter = resolver.value_of(self.parameter) return self assert not cirq.is_parameterized(NoMethod()) assert not cirq.is_parameterized(ReturnsNotImplemented()) assert not cirq.is_parameterized(SimpleParameterSwitch('a')) assert cirq.is_parameterized(SimpleParameterSwitch(0)) ni = ReturnsNotImplemented() r = cirq.ParamResolver({'a': 0}) no = NoMethod() assert cirq.resolve_parameters(no, r) == no assert cirq.resolve_parameters(ni, r) == ni assert cirq.resolve_parameters(SimpleParameterSwitch(0), r).parameter == 0 assert cirq.resolve_parameters(SimpleParameterSwitch('a'), r).parameter == 0
def test_fsim_gate_with_symbols(): theta, phi = sympy.symbols(['theta', 'phi']) op = cirq.FSimGate(theta=theta, phi=phi).on(*cirq.LineQubit.range(2)) c_new_sqrt_iswap = cirq.Circuit(cirq.parameterized_2q_op_to_sqrt_iswap_operations(op)) c_new_sqrt_iswap_inv = cirq.Circuit( cirq.parameterized_2q_op_to_sqrt_iswap_operations(op, use_sqrt_iswap_inv=True) ) for theta_val in np.linspace(0, 2 * np.pi, 4): for phi_val in np.linspace(0, 2 * np.pi, 6): cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(cirq.resolve_parameters(op, {'theta': theta_val, 'phi': phi_val})), cirq.unitary( cirq.resolve_parameters(c_new_sqrt_iswap, {'theta': theta_val, 'phi': phi_val}) ), atol=1e-6, ) cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(cirq.resolve_parameters(op, {'theta': theta_val, 'phi': phi_val})), cirq.unitary( cirq.resolve_parameters( c_new_sqrt_iswap_inv, {'theta': theta_val, 'phi': phi_val} ) ), atol=1e-6, )
def test_phased_fsim_resolve(): f = cirq.PhasedFSimGate(sympy.Symbol('a'), sympy.Symbol('b'), sympy.Symbol('c'), sympy.Symbol('d'), sympy.Symbol('e')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'a': 1}) assert f == cirq.PhasedFSimGate(1, sympy.Symbol('b'), sympy.Symbol('c'), sympy.Symbol('d'), sympy.Symbol('e')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'b': 2}) assert f == cirq.PhasedFSimGate(1, 2, sympy.Symbol('c'), sympy.Symbol('d'), sympy.Symbol('e')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'c': 3}) assert f == cirq.PhasedFSimGate(1, 2, 3, sympy.Symbol('d'), sympy.Symbol('e')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'d': 4}) assert f == cirq.PhasedFSimGate(1, 2, 3, 4, sympy.Symbol('e')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'e': 5}) assert f == cirq.PhasedFSimGate(1, 2, 3, 4, 5) assert not cirq.is_parameterized(f)
def test_with_params(): a = cirq.LineQubit(0) z_exp = sympy.Symbol('z_exp') x_exp = sympy.Symbol('x_exp') delta = sympy.Symbol('delta') theta = sympy.Symbol('theta') circuit = cirq.FrozenCircuit(cirq.Z(a) ** z_exp, cirq.X(a) ** x_exp, cirq.Z(a) ** delta) op_base = cirq.CircuitOperation(circuit) param_dict = { z_exp: 2, x_exp: theta, sympy.Symbol('k'): sympy.Symbol('phi'), } op_with_params = op_base.with_params(param_dict) assert op_with_params.base_operation() == op_base assert op_with_params.param_resolver == cirq.ParamResolver( { z_exp: 2, x_exp: theta, # As 'k' is irrelevant to the circuit, it does not appear here. } ) assert cirq.parameter_names(op_with_params) == {'theta', 'delta'} assert ( cirq.resolve_parameters(op_base, cirq.ParamResolver(param_dict), recursive=False) == op_with_params ) # Recursive parameter resolution is rejected. with pytest.raises(ValueError, match='Use "recursive=False"'): _ = cirq.resolve_parameters(op_base, cirq.ParamResolver(param_dict))
def test_two_qubit_gates_with_symbols(gate: cirq.Gate, use_sqrt_iswap_inv: bool): # Note that even though these gates are not natively supported by # `cirq.parameterized_2q_op_to_sqrt_iswap_operations`, the transformation succeeds because # `cirq.optimize_for_target_gateset` also relies on `cirq.decompose` as a fallback. c_orig = cirq.Circuit(gate(*cirq.LineQubit.range(2))) c_new = cirq.optimize_for_target_gateset( c_orig, gateset=cirq.SqrtIswapTargetGateset( use_sqrt_iswap_inv=use_sqrt_iswap_inv, additional_gates=[cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate], ), ignore_failures=False, ) # Check that `c_new` only contains sqrt iswap as the 2q entangling gate. sqrt_iswap_gate = cirq.SQRT_ISWAP_INV if use_sqrt_iswap_inv else cirq.SQRT_ISWAP for op in c_new.all_operations(): if cirq.num_qubits(op) == 2: assert op.gate == sqrt_iswap_gate # Check if unitaries are the same for val in np.linspace(0, 2 * np.pi, 10): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( cirq.resolve_parameters(c_orig, {'t': val}), cirq.resolve_parameters(c_new, {'t': val}), atol=1e-6, )
def test_protocols(): t = sympy.Symbol('t') cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('Y')) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('Z')) cirq.testing.assert_implements_consistent_protocols( 1j * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( 2 * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( t * cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('XYIZ', coefficient=t + 2)) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.MutableDensePauliString('XYIZ', coefficient=-1)) # Unitarity and shape. assert cirq.has_unitary(1j * cirq.DensePauliString('X')) assert not cirq.has_unitary(2j * cirq.DensePauliString('X')) assert not cirq.has_unitary(cirq.DensePauliString('X') * t) p = -cirq.DensePauliString('XYIZ') assert cirq.num_qubits(p) == len(p) == 4 # Parameterization. x = cirq.DensePauliString('X') assert not cirq.is_parameterized(x) assert not cirq.is_parameterized(x * 2) assert cirq.is_parameterized(x * t) assert cirq.resolve_parameters(x * t, {'t': 2}) == x * 2 assert cirq.resolve_parameters(x * 3, {'t': 2}) == x * 3
def test_recursive_params(): q = cirq.LineQubit(0) a, a2, b, b2 = sympy.symbols('a a2 b b2') circuitop = cirq.CircuitOperation( cirq.FrozenCircuit(cirq.X(q) ** a, cirq.Z(q) ** b), # Not recursive, a and b are swapped. param_resolver=cirq.ParamResolver({a: b, b: a}), ) # Recursive, so a->a2->0 and b->b2->1. outer_params = {a: a2, a2: 0, b: b2, b2: 1} resolved = cirq.resolve_parameters(circuitop, outer_params) # Combined, a->b->b2->1, and b->a->a2->0. assert resolved.param_resolver.param_dict == {a: 1, b: 0} # Non-recursive, so a->a2 and b->b2. resolved = cirq.resolve_parameters(circuitop, outer_params, recursive=False) # Combined, a->b->b2, and b->a->a2. assert resolved.param_resolver.param_dict == {a: b2, b: a2} with pytest.raises(RecursionError): cirq.resolve_parameters(circuitop, {a: a2, a2: a}) # Non-recursive, so a->b and b->a. resolved = cirq.resolve_parameters(circuitop, {a: b, b: a}, recursive=False) # Combined, a->b->a, and b->a->b. assert resolved.param_resolver.param_dict == {} # First example should behave like an X when simulated result = cirq.Simulator().simulate(cirq.Circuit(circuitop), param_resolver=outer_params) assert np.allclose(result.state_vector(copy=False), [0, 1])
def test_two_qubit_gates_with_symbols(gate: cirq.Gate, expected_length: int): """Tests that the gates with symbols decompose without error into a circuit that has an equivalent unitary form. """ q0 = cirq.GridQubit(5, 3) q1 = cirq.GridQubit(5, 4) original_circuit = cirq.Circuit(gate(q0, q1)) converted_circuit = original_circuit.copy() with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cgoc.ConvertToSqrtIswapGates().optimize_circuit(converted_circuit) converted_circuit_iswap_inv = cirq.optimize_for_target_gateset( original_circuit, gateset=cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True)) converted_circuit_iswap = cirq.optimize_for_target_gateset( original_circuit, gateset=cirq.SqrtIswapTargetGateset()) assert len(converted_circuit) <= expected_length assert (len(converted_circuit_iswap) <= expected_length or len(converted_circuit_iswap_inv) <= expected_length) # Check if unitaries are the same for val in np.linspace(0, 2 * np.pi, 6): resolved_original = cirq.resolve_parameters(original_circuit, {'t': val}) assert _unitaries_allclose( resolved_original, cirq.resolve_parameters(converted_circuit, {'t': val})) assert _unitaries_allclose( resolved_original, cirq.resolve_parameters(converted_circuit_iswap, {'t': val})) assert _unitaries_allclose( resolved_original, cirq.resolve_parameters(converted_circuit_iswap_inv, {'t': val}))
def test_skips_empty_resolution(): class Tester: def _resolve_parameters_(self, param_resolver): return 5 t = Tester() assert cirq.resolve_parameters(t, {}) is t assert cirq.resolve_parameters(t, {'x': 2}) == 5
def _resolve_parameters_(self, resolver): resolved_weights = cirq.resolve_parameters(self.weights, resolver) resolved_exponent = cirq.resolve_parameters(self._exponent, resolver) resolved_global_shift = cirq.resolve_parameters(self._global_shift, resolver) return type(self)(resolved_weights, exponent=resolved_exponent, global_shift=resolved_global_shift)
def test_exporting_and_binding_parametrized_circuit_results_in_equivalent_circuit( self, zquantum_circuit, cirq_circuit): converted = export_to_cirq(zquantum_circuit) converted_bound = cirq.resolve_parameters(converted, EXAMPLE_PARAM_VALUES) ref_bound = cirq.resolve_parameters(cirq_circuit, EXAMPLE_PARAM_VALUES) assert converted_bound == ref_bound, ( f"Converted circuit:\n{converted_bound}\n isn't equal to\n{ref_bound}" )
def test_correctness_with_symbols(self, n_qubits, batch_size, inner_dim_size): """Tests that inner_product works with symbols.""" symbol_names = ['alpha', 'beta', 'gamma'] n_params = len(symbol_names) qubits = cirq.GridQubit.rect(1, n_qubits) circuit_batch, resolver_batch = \ util.random_symbol_circuit_resolver_batch( qubits, symbol_names, batch_size) other_batch = [ util.random_circuit_resolver_batch(qubits, inner_dim_size)[0] for i in range(batch_size) ] symbol_values_array = np.array( [[resolver[symbol] for symbol in symbol_names] for resolver in resolver_batch]) programs = util.convert_to_tensor(circuit_batch) other_programs = util.convert_to_tensor(other_batch) symbol_names_tensor = tf.convert_to_tensor(symbol_names, dtype=tf.dtypes.string) symbol_values = tf.convert_to_tensor(symbol_values_array) prev_grad = tf.cast(tf.random.normal((batch_size, inner_dim_size)), tf.complex64) out = inner_product_op._inner_product_grad(programs, symbol_names_tensor, symbol_values, other_programs, prev_grad) out_arr = np.zeros((batch_size, n_params), dtype=np.complex64) # dx came from _GRAD_EPS of core/src/adj_util.cc dx = 5e-3 for i, resolver in enumerate(resolver_batch): for k, name in enumerate(symbol_names): if name in resolver.param_dict: new_resolver = copy.deepcopy(resolver) new_resolver.param_dict[name] += dx final_circuit_p = cirq.resolve_parameters( circuit_batch[i], new_resolver) new_resolver = copy.deepcopy(resolver) new_resolver.param_dict[name] -= dx final_circuit_m = cirq.resolve_parameters( circuit_batch[i], new_resolver) final_wf_p = cirq.final_state_vector(final_circuit_p) final_wf_m = cirq.final_state_vector(final_circuit_m) # Performs central finite difference. final_wf_grad = 0.5 * (final_wf_p - final_wf_m) / dx for j, other in enumerate(other_batch[i]): internal_wf = cirq.final_state_vector(other) out_arr[i][k] += (prev_grad[i][j] * np.vdot(final_wf_grad, internal_wf)) self.assertAllClose(out, np.conj(out_arr), atol=1e-3)
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, compare_unitaries: bool = True, eject_parameterized: bool = False, *, with_context: bool = False, ): context = cirq.TransformerContext(tags_to_ignore=("nocompile",)) if with_context else None circuit = cirq.eject_phased_paulis( before, eject_parameterized=eject_parameterized, context=context ) # They should have equivalent effects. if compare_unitaries: if cirq.is_parameterized(circuit): for a in (0, 0.1, 0.5, -1.0, np.pi, np.pi / 2): params = {'x': a, 'y': a / 2, 'z': -2 * a} ( cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( cirq.resolve_parameters(circuit, params), cirq.resolve_parameters(expected, params), 1e-8, ) ) else: ( cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( circuit, expected, 1e-8 ) ) # And match the expected circuit. assert circuit == expected, ( "Circuit wasn't optimized as expected.\n" "INPUT:\n" "{}\n" "\n" "EXPECTED OUTPUT:\n" "{}\n" "\n" "ACTUAL OUTPUT:\n" "{}\n" "\n" "EXPECTED OUTPUT (detailed):\n" "{!r}\n" "\n" "ACTUAL OUTPUT (detailed):\n" "{!r}" ).format(before, expected, circuit, expected, circuit) # And it should be idempotent. circuit = cirq.eject_phased_paulis( circuit, eject_parameterized=eject_parameterized, context=context ) assert circuit == expected
def test_parameterizable(): a = sympy.Symbol('a') cz = cirq.ControlledGate(cirq.Y) cza = cirq.ControlledGate(cirq.YPowGate(exponent=a)) scza = cirq.ControlledGate(cirq.YPowGate(exponent=a), [q]) assert cirq.is_parameterized(cza) assert cirq.is_parameterized(scza) assert not cirq.is_parameterized(cz) assert cirq.resolve_parameters(cza, cirq.ParamResolver({'a': 1})) == cz assert cirq.resolve_parameters(scza, cirq.ParamResolver({'a': 1})) == cz
def test_parameterized(): t = sympy.Symbol('t') assert not cirq.is_parameterized(Duration()) assert not cirq.is_parameterized(Duration(nanos=500)) assert cirq.is_parameterized(Duration(nanos=500 * t)) assert cirq.resolve_parameters(Duration(), {'t': 2}) == Duration() assert cirq.resolve_parameters(Duration(nanos=500), {'t': 2}) == Duration(nanos=500) assert cirq.resolve_parameters(Duration(nanos=500 * t), {'t': 2}) == Duration(nanos=1000)
def test_phase_gradient_symbolic(): a = cirq.PhaseGradientGate(num_qubits=2, exponent=0.5) b = cirq.PhaseGradientGate(num_qubits=2, exponent=sympy.Symbol('t')) assert not cirq.is_parameterized(a) assert cirq.is_parameterized(b) assert cirq.has_unitary(a) assert not cirq.has_unitary(b) assert cirq.resolve_parameters(a, {'t': 0.25}) is a assert cirq.resolve_parameters(b, {'t': 0.5}) == a assert cirq.resolve_parameters(b, {'t': 0.25}) == cirq.PhaseGradientGate( num_qubits=2, exponent=0.25)
def test_fsim_resolve(): f = cirq.FSimGate(sympy.Symbol('a'), sympy.Symbol('b')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'a': 2}) assert f == cirq.FSimGate(2, sympy.Symbol('b')) assert cirq.is_parameterized(f) f = cirq.resolve_parameters(f, {'b': 1}) assert f == cirq.FSimGate(2, 1) assert not cirq.is_parameterized(f)
def test_moment_preservation(self): """Test Moment-structure preservation.""" t = sympy.Symbol('t') r = sympy.Symbol('r') qubits = cirq.GridQubit.rect(1, 6) circuit_batch = [ cirq.Circuit( cirq.Moment([cirq.H(q) for q in qubits]), cirq.Moment([ cirq.X(qubits[4]), cirq.PhasedXPowGate(phase_exponent=np.random.random() * t).on(qubits[5]), cirq.ISwapPowGate(exponent=np.random.random() * t).on( qubits[0], qubits[1]), cirq.FSimGate(theta=np.random.random() * t, phi=np.random.random() * r).on( qubits[2], qubits[3]) ]), cirq.Moment([cirq.H(q) for q in qubits])) ] inputs = util.convert_to_tensor(circuit_batch) outputs = tfq_ps_util_ops.tfq_ps_decompose(inputs) decomposed_programs = util.from_tensor(outputs) # Now all programs don't have ISWAP & PhasedXPowGate because ISWAP has # 3 eigenvalues and PhasedXPowGate doesn't have _eigen_components. # Check if two programs are identical. rand_resolver = {'t': np.random.random(), 'r': np.random.random()} self.assertAllClose(cirq.unitary( cirq.resolve_parameters(circuit_batch[0], rand_resolver)), cirq.unitary( cirq.resolve_parameters(decomposed_programs[0], rand_resolver)), atol=1e-5) # Check if the Moments are conserved. max_decomposed_length = 3 n_non_decomposed_moments = 2 self.assertEqual(len(decomposed_programs[0]), n_non_decomposed_moments + max_decomposed_length) # Total length of Moments = 5 # The non-decomposed moments should be the same. self.assertEqual(decomposed_programs[0][0], circuit_batch[0][0]) self.assertEqual(decomposed_programs[0][-1], circuit_batch[0][-1]) # Check paralellized decompose gates in Moment[1]~[3]. # The target ops are replaced by the first decomposition gates. It means # the first Moment has exactly the same number of gate ops. self.assertEqual(len(decomposed_programs[0][1]), len(circuit_batch[0][1])) # From the second Moments, the Moments only have decomposition gates. # In this example, two ISwapPowGate & one PhasedXPowGate are located. # Since PhasedXPowGate, ISwapPowGate, FSimGate has 3, 2, 3 result gates # Moment[2] have 3 gate ops and Moment[3] have 2 gate ops. self.assertEqual(len(decomposed_programs[0][2]), 3) self.assertEqual(len(decomposed_programs[0][3]), 2)
def test_decompose_parameterized_operation(): op = cirq.ISWAP(*cirq.LineQubit.range(2)) theta = sympy.Symbol("theta") circuit = cirq.Circuit(op**theta) decomposed_circuit = cirq.optimize_for_target_gateset( circuit, gateset=ionq_target_gateset, ignore_failures=False) for theta_val in [-0.25, 1.0, 0.5]: cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( cirq.resolve_parameters(circuit, {theta: theta_val}), cirq.resolve_parameters(decomposed_circuit, {theta: theta_val}), atol=1e-6, ) assert ionq_target_gateset.validate(decomposed_circuit)
def _resolve_parameters_(self, resolver, recursive: bool = True): resolved_weights = cirq.resolve_parameters(self.weights, resolver, recursive=recursive) resolved_exponent = cirq.resolve_parameters(self._exponent, resolver, recursive=recursive) resolved_global_shift = cirq.resolve_parameters(self._global_shift, resolver, recursive=recursive) return type(self)(resolved_weights, exponent=resolved_exponent, global_shift=resolved_global_shift)
def assert_optimizes( before: cirq.Circuit, expected: cirq.Circuit, compare_unitaries: bool = True, eject_parameterized: bool = False, ): with cirq.testing.assert_deprecated("Use cirq.eject_phased_paulis", deadline='v1.0'): opt = cirq.EjectPhasedPaulis(eject_parameterized=eject_parameterized) circuit = before.copy() expected = cirq.drop_empty_moments(expected) opt.optimize_circuit(circuit) # They should have equivalent effects. if compare_unitaries: if cirq.is_parameterized(circuit): for a in (0, 0.1, 0.5, -1.0, np.pi, np.pi / 2): params: cirq.ParamDictType = {'x': a, 'y': a / 2, 'z': -2 * a} (cirq.testing. assert_circuits_with_terminal_measurements_are_equivalent( cirq.resolve_parameters(circuit, params), cirq.resolve_parameters(expected, params), 1e-8, )) else: (cirq.testing. assert_circuits_with_terminal_measurements_are_equivalent( circuit, expected, 1e-8)) # And match the expected circuit. assert circuit == expected, ("Circuit wasn't optimized as expected.\n" "INPUT:\n" "{}\n" "\n" "EXPECTED OUTPUT:\n" "{}\n" "\n" "ACTUAL OUTPUT:\n" "{}\n" "\n" "EXPECTED OUTPUT (detailed):\n" "{!r}\n" "\n" "ACTUAL OUTPUT (detailed):\n" "{!r}").format(before, expected, circuit, expected, circuit) # And it should be idempotent. opt.optimize_circuit(circuit) assert circuit == expected
def test_multi_circuit_batch(self): """Test that a batch of circuits works.""" a_symbol = sympy.Symbol('alpha') some_values = np.array([[0.5], [3.5]]) circuit = cirq.Circuit(cirq.H(cirq.GridQubit(0, 0))**a_symbol) results = unitary.Unitary()(util.convert_to_tensor([circuit, circuit]), symbol_names=[a_symbol], symbol_values=some_values) u_1 = cirq.unitary( cirq.resolve_parameters(circuit, {a_symbol: some_values[0][0]})) u_2 = cirq.unitary( cirq.resolve_parameters(circuit, {a_symbol: some_values[1][0]})) self.assertAllClose(results, [u_1, u_2])
def test_single_circuit_batch_inputs(self): """Test that a single circuit with multiple parameters works.""" a_symbol = sympy.Symbol('alpha') some_values = np.array([[0.5], [3.5]]) circuit = cirq.Circuit(cirq.H(cirq.GridQubit(0, 0))**a_symbol) results = unitary.Unitary()(circuit, symbol_names=[a_symbol], symbol_values=some_values) u_1 = cirq.unitary( cirq.resolve_parameters(circuit, {a_symbol: some_values[0][0]})) u_2 = cirq.unitary( cirq.resolve_parameters(circuit, {a_symbol: some_values[1][0]})) self.assertAllClose(results, [u_1, u_2])
def test_parameterized_decompose(): angles = sympy.symbols('x0, x1, x2, x3') parameterized_op = cirq.TwoQubitDiagonalGate(angles).on( *cirq.LineQubit.range(2)) decomposed_circuit = cirq.Circuit(cirq.decompose(parameterized_op)) for resolver in (cirq.Linspace('x0', -2, 2, 3) * cirq.Linspace('x1', -2, 2, 3) * cirq.Linspace('x2', -2, 2, 3) * cirq.Linspace('x3', -2, 2, 3)): np.testing.assert_allclose( cirq.unitary(cirq.resolve_parameters(parameterized_op, resolver)), cirq.unitary(cirq.resolve_parameters(decomposed_circuit, resolver)), )
def test_resolve(): diagonal_angles = [2, 3, 5, 7] diagonal_gate = cirq.TwoQubitDiagonalGate( diagonal_angles[:2] + [sympy.Symbol('a'), sympy.Symbol('b')]) assert cirq.is_parameterized(diagonal_gate) diagonal_gate = cirq.resolve_parameters(diagonal_gate, {'a': 5}) assert diagonal_gate == cirq.TwoQubitDiagonalGate(diagonal_angles[:3] + [sympy.Symbol('b')]) assert cirq.is_parameterized(diagonal_gate) diagonal_gate = cirq.resolve_parameters(diagonal_gate, {'b': 7}) assert diagonal_gate == cirq.TwoQubitDiagonalGate(diagonal_angles) assert not cirq.is_parameterized(diagonal_gate)
def test_resolve(): diagonal_angles = [2, 3, 5, 7, 11, 13, 17, 19] diagonal_gate = cirq.ThreeQubitDiagonalGate( diagonal_angles[:6] + [sympy.Symbol('a'), sympy.Symbol('b')]) assert cirq.is_parameterized(diagonal_gate) diagonal_gate = cirq.resolve_parameters(diagonal_gate, {'a': 17}) assert diagonal_gate == cirq.ThreeQubitDiagonalGate(diagonal_angles[:7] + [sympy.Symbol('b')]) assert cirq.is_parameterized(diagonal_gate) diagonal_gate = cirq.resolve_parameters(diagonal_gate, {'b': 19}) assert diagonal_gate == cirq.ThreeQubitDiagonalGate(diagonal_angles) assert not cirq.is_parameterized(diagonal_gate)
def test_resolve_parameters_consistency_basic(self): """Compare tfq op to cirq resolving.""" qubits = cirq.GridQubit.rect(1, 4) circuit = cirq.Circuit() symbols = [] for n, q in enumerate(qubits): new_bit = sympy.Symbol("bit_{}".format(n)) circuit += cirq.X(q)**new_bit symbols.append(new_bit) symbol_names = [str(s) for s in symbols] bitstring_list = [[0, 0, 0, 0], [0, 1, 0, 1], [1, 0, 1, 1]] circuit_list = [] resolver_list = [] for bitstring in bitstring_list: resolve_dict = {} for s, b in zip(symbols, bitstring): resolve_dict[s] = b resolver_list.append(cirq.ParamResolver(resolve_dict)) circuit_list.append(circuit) test_resolved_circuits = util.from_tensor( tfq_utility_ops.resolve_parameters( util.convert_to_tensor(circuit_list), symbol_names, np.asarray(bitstring_list))) expected_resolved_circuits = [] for circuit, resolver in zip(circuit_list, resolver_list): expected_resolved_circuits.append( cirq.resolve_parameters(circuit, resolver)) for exp_c, test_c in zip(expected_resolved_circuits, test_resolved_circuits): self.assertAllEqual(exp_c, test_c)