def test_abstract_can_be_concretized_abstract_fails_on_different_federated_all_equal_bits( self): t1 = computation_types.FederatedType( [computation_types.AbstractType('T1')] * 2, placement_literals.CLIENTS, all_equal=True) t2 = computation_types.FederatedType([tf.int32] * 2, placement_literals.SERVER, all_equal=True) self.assertFalse(type_analysis.is_concrete_instance_of(t2, t1))
def test_succeeds_under_tuple(self): t1 = self.func_with_param( computation_types.StructType( [computation_types.AbstractType('T1')] * 2)) t2 = self.func_with_param( computation_types.StructType([ computation_types.TensorType(tf.int32), computation_types.TensorType(tf.int32) ])) type_analysis.check_concrete_instance_of(t2, t1)
def test_executor_call_unsupported_intrinsic(self): dummy_intrinsic = intrinsic_defs.IntrinsicDef( 'DUMMY_INTRINSIC', 'dummy_intrinsic', computation_types.AbstractType('T')) comp = pb.Computation(intrinsic=pb.Intrinsic(uri='dummy_intrinsic'), type=type_serialization.serialize_type(tf.int32)) with self.assertRaises(NotImplementedError): _run_test_comp(comp, num_clients=3)
def test_abstract_federated_types_succeeds(self): t1 = self.func_with_param( computation_types.FederatedType( [computation_types.AbstractType('T1')] * 2, placement_literals.CLIENTS, all_equal=True)) t2 = self.func_with_param( computation_types.FederatedType( [tf.int32] * 2, placement_literals.CLIENTS, all_equal=True)) type_analysis.check_concrete_instance_of(t2, t1)
def _federated_select(client_keys, max_key, server_val, select_fn, secure): """Internal helper for `federated_select` and `federated_secure_select`.""" client_keys = value_impl.to_value(client_keys, None) _check_select_keys_type(client_keys.type_signature, secure) max_key = value_impl.to_value(max_key, None) expected_max_key_type = computation_types.at_server(tf.int32) if not expected_max_key_type.is_assignable_from(max_key.type_signature): _select_parameter_mismatch( max_key.type_signature, 'a 32-bit unsigned integer placed at server', 'max_key', secure, expected_type=expected_max_key_type) server_val = value_impl.to_value(server_val, None) expected_server_val_type = computation_types.at_server( computation_types.AbstractType('T')) if (not server_val.type_signature.is_federated() or not server_val.type_signature.placement.is_server()): _select_parameter_mismatch(server_val.type_signature, 'a value placed at server', 'server_val', secure, expected_type=expected_server_val_type) select_fn_param_type = computation_types.to_type( [server_val.type_signature.member, tf.int32]) select_fn = value_impl.to_value(select_fn, None, parameter_type_hint=select_fn_param_type) expected_select_fn_type = computation_types.FunctionType( select_fn_param_type, computation_types.AbstractType('U')) if (not select_fn.type_signature.is_function() or not select_fn.type_signature.parameter.is_assignable_from( select_fn_param_type)): _select_parameter_mismatch(select_fn.type_signature, 'a function from state and key to result', 'select_fn', secure, expected_type=expected_select_fn_type) comp = building_block_factory.create_federated_select( client_keys.comp, max_key.comp, server_val.comp, select_fn.comp, secure) comp = _bind_comp_as_reference(comp) return value_impl.Value(comp)
def test_transforms_abstract_type(self): orig_type = computation_types.AbstractType('T') expected_type = computation_types.to_type(tf.float32) result_type, mutated = type_transformations.transform_type_postorder( orig_type, _convert_abstract_type_to_tensor) noop_type, not_mutated = type_transformations.transform_type_postorder( orig_type, _convert_placement_type_to_tensor) self.assertEqual(result_type, expected_type) self.assertEqual(noop_type, orig_type) self.assertTrue(mutated) self.assertFalse(not_mutated)
def test_fails_under_tuple_conflicting_concrete_types(self): t1 = self.func_with_param( computation_types.StructType( [computation_types.AbstractType('T1')] * 2)) t2 = self.func_with_param( computation_types.StructType([ computation_types.TensorType(tf.int32), computation_types.TensorType(tf.float32) ])) with self.assertRaises(type_analysis.MismatchedConcreteTypesError): type_analysis.check_concrete_instance_of(t2, t1)
def test_tf_wrapper_fails_bad_types(self): function = computation_types.FunctionType( None, computation_types.TensorType(tf.int32)) federated = computation_types.FederatedType(tf.int32, placement_literals.CLIENTS) tuple_on_function = computation_types.NamedTupleType( [federated, function]) with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type {int32}@CLIENTS' ): @computation_wrapper_instances.tensorflow_wrapper(federated) def _(x): del x # pylint: disable=anomalous-backslash-in-string with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type \( -> int32\)' ): @computation_wrapper_instances.tensorflow_wrapper(function) def _(x): del x with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type placement'): @computation_wrapper_instances.tensorflow_wrapper( computation_types.PlacementType()) def _(x): del x with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type T'): @computation_wrapper_instances.tensorflow_wrapper( computation_types.AbstractType('T')) def _(x): del x with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type <{int32}@CLIENTS,\( ' '-> int32\)>'): @computation_wrapper_instances.tensorflow_wrapper( tuple_on_function) def _(x): del x
def test_raises_not_implemented_error_with_unimplemented_intrinsic(self): executor = create_test_executor() dummy_intrinsic = intrinsic_defs.IntrinsicDef( 'DUMMY_INTRINSIC', 'dummy_intrinsic', computation_types.AbstractType('T')) comp = pb.Computation(intrinsic=pb.Intrinsic(uri='dummy_intrinsic'), type=type_serialization.serialize_type(tf.int32)) comp = self.run_sync(executor.create_value(comp)) with self.assertRaises(NotImplementedError): self.run_sync(executor.create_call(comp))
def test_abstract_can_be_concretized_fails_on_different_placements(self): t1 = self.func_with_param( computation_types.FederatedType( [computation_types.AbstractType('T1')] * 2, placement_literals.CLIENTS, all_equal=True)) t2 = self.func_with_param( computation_types.FederatedType( [tf.int32] * 2, placement_literals.SERVER, all_equal=True)) with self.assertRaises(type_analysis.MismatchedStructureError): type_analysis.check_concrete_instance_of(t2, t1)
def test_abstract_parameters_contravariant(self): struct = lambda name: computation_types.StructType([(name, tf.int32)]) unnamed = struct(None) concrete = computation_types.FunctionType( computation_types.StructType( [unnamed, computation_types.FunctionType(struct('bar'), unnamed)]), struct('foo')) abstract = computation_types.AbstractType('A') generic = computation_types.FunctionType( computation_types.StructType( [abstract, computation_types.FunctionType(abstract, abstract)]), abstract) type_analysis.check_concrete_instance_of(concrete, generic)
def test_executor_call_unsupported_intrinsic(self): dummy_intrinsic = intrinsic_defs.IntrinsicDef( 'DUMMY_INTRINSIC', 'dummy_intrinsic', computation_types.AbstractType('T')) comp = pb.Computation(type=type_serialization.serialize_type(tf.int32), intrinsic=pb.Intrinsic(uri='dummy_intrinsic')) loop = asyncio.get_event_loop() executor = composing_executor.ComposingExecutor( _create_bottom_stack(), [_create_worker_stack() for _ in range(3)]) with self.assertRaises(NotImplementedError): v1 = loop.run_until_complete(executor.create_value(comp, tf.int32)) loop.run_until_complete(executor.create_call(v1, None))
def test_raises_not_implemented_error_with_unimplemented_intrinsic(self): executor = create_test_executor() # `whimsy_intrinsic` definition is needed to allow lookup. whimsy_intrinsic = intrinsic_defs.IntrinsicDef( 'WHIMSY_INTRINSIC', 'whimsy_intrinsic', computation_types.AbstractType('T')) type_signature = computation_types.TensorType(tf.int32) comp = pb.Computation( intrinsic=pb.Intrinsic(uri='whimsy_intrinsic'), type=type_serialization.serialize_type(type_signature)) del whimsy_intrinsic comp = self.run_sync(executor.create_value(comp)) with self.assertRaises(NotImplementedError): self.run_sync(executor.create_call(comp))
class VisitPreorderTest(parameterized.TestCase): # pyformat: disable @parameterized.named_parameters([ ('abstract_type', computation_types.AbstractType('T'), 1), ('nested_federated_type', computation_types.FederatedType( computation_types.FederatedType( computation_types.FederatedType( tf.int32, placement_literals.CLIENTS), placement_literals.CLIENTS), placement_literals.CLIENTS), 4), ('nested_function_type', computation_types.FunctionType( computation_types.FunctionType( computation_types.FunctionType(tf.int32, tf.int32), tf.int32), tf.int32), 7), ('nested_sequence_type', computation_types.SequenceType( computation_types.SequenceType( computation_types.SequenceType(tf.int32))), 4), ('named_tuple_type', computation_types.NamedTupleType([ tf.int32, tf.bool, computation_types.SequenceType(tf.int32)]), 5), ('placement_type', computation_types.PlacementType(), 1), ]) # pyformat: enable def test_preorder_call_count(self, type_signature, expected_count): class Counter(object): k = 0 def _count_hits(given_type, arg): del given_type # Unused. Counter.k += 1 return arg type_transformations.visit_preorder(type_signature, _count_hits, None) actual_count = Counter.k self.assertEqual(actual_count, expected_count)
def test_well_formed_check_succeeds_good_types(self): federated = computation_types.FederatedType(tf.int32, placements.CLIENTS) self.assertTrue(type_utils.check_well_formed(federated)) tensor = computation_types.TensorType(tf.int32) self.assertTrue(type_utils.check_well_formed(tensor)) namedtuple = computation_types.NamedTupleType( [tf.int32, computation_types.NamedTupleType([tf.int32, tf.int32])]) self.assertTrue(type_utils.check_well_formed(namedtuple)) sequence = computation_types.SequenceType(tf.int32) self.assertTrue(type_utils.check_well_formed(sequence)) fn = computation_types.FunctionType(tf.int32, tf.int32) self.assertTrue(type_utils.check_well_formed(fn)) abstract = computation_types.AbstractType('T') self.assertTrue(type_utils.check_well_formed(abstract)) placement = computation_types.PlacementType() self.assertTrue(type_utils.check_well_formed(placement))
def test_executor_call_unsupported_intrinsic(self): dummy_intrinsic = intrinsic_defs.IntrinsicDef( 'DUMMY_INTRINSIC', 'dummy_intrinsic', computation_types.AbstractType('T')) type_signature = computation_types.TensorType(tf.int32) comp = pb.Computation( type=type_serialization.serialize_type(type_signature), intrinsic=pb.Intrinsic(uri='dummy_intrinsic')) loop = asyncio.get_event_loop() factory = federated_composing_strategy.FederatedComposingStrategy.factory( _create_bottom_stack(), [_create_worker_stack()]) executor = federating_executor.FederatingExecutor( factory, _create_bottom_stack()) v1 = loop.run_until_complete(executor.create_value(comp)) with self.assertRaises(NotImplementedError): loop.run_until_complete(executor.create_call(v1))
def test_fails_with_bad_types(self): function = computation_types.FunctionType( None, computation_types.TensorType(tf.int32)) federated = computation_types.FederatedType(tf.int32, placement_literals.CLIENTS) tuple_on_function = computation_types.StructType([federated, function]) def foo(x): # pylint: disable=unused-variable del x # Unused. with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type {int32}@CLIENTS' ): computation_wrapper_instances.tensorflow_wrapper(foo, federated) # pylint: disable=anomalous-backslash-in-string with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type \( -> int32\)' ): computation_wrapper_instances.tensorflow_wrapper(foo, function) with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type placement'): computation_wrapper_instances.tensorflow_wrapper( foo, computation_types.PlacementType()) with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type T'): computation_wrapper_instances.tensorflow_wrapper( foo, computation_types.AbstractType('T')) with self.assertRaisesRegex( TypeError, r'you have attempted to create one with the type <{int32}@CLIENTS,\( ' '-> int32\)>'): computation_wrapper_instances.tensorflow_wrapper( foo, tuple_on_function)
class IsStructureOfIntegersTest(parameterized.TestCase): @parameterized.named_parameters( ('int', tf.int32), ('ints', ([tf.int32, tf.int32], )), ('federated_int_at_clients', computation_types.FederatedType(tf.int32, placements.CLIENTS)), ) def test_returns_true(self, type_spec): self.assertTrue(type_utils.is_structure_of_integers(type_spec)) @parameterized.named_parameters( ('bool', tf.bool), ('string', tf.string), ('int_and_bool', ([tf.int32, tf.bool], )), ('sequence_of_ints', computation_types.SequenceType(tf.int32)), ('placement', computation_types.PlacementType()), ('function', computation_types.FunctionType(tf.int32, tf.int32)), ('abstract', computation_types.AbstractType('T')), ) def test_returns_false(self, type_spec): self.assertFalse(type_utils.is_structure_of_integers(type_spec))
def test_preorder_call_count(self): class Counter(object): k = 0 def _count_hits(given_type, arg): del given_type Counter.k += 1 return arg sequence = computation_types.SequenceType( computation_types.SequenceType( computation_types.SequenceType(tf.int32))) type_utils.preorder_call(sequence, _count_hits, None) self.assertEqual(Counter.k, 4) federated = computation_types.FederatedType( computation_types.FederatedType( computation_types.FederatedType(tf.int32, placements.CLIENTS), placements.CLIENTS), placements.CLIENTS) type_utils.preorder_call(federated, _count_hits, None) self.assertEqual(Counter.k, 8) fn = computation_types.FunctionType( computation_types.FunctionType(tf.int32, tf.int32), tf.int32) type_utils.preorder_call(fn, _count_hits, None) self.assertEqual(Counter.k, 13) abstract = computation_types.AbstractType('T') type_utils.preorder_call(abstract, _count_hits, None) self.assertEqual(Counter.k, 14) placement = computation_types.PlacementType() type_utils.preorder_call(placement, _count_hits, None) self.assertEqual(Counter.k, 15) namedtuple = computation_types.NamedTupleType([ tf.int32, tf.bool, computation_types.FederatedType(tf.int32, placements.CLIENTS) ]) type_utils.preorder_call(namedtuple, _count_hits, None) self.assertEqual(Counter.k, 20) nested_namedtuple = computation_types.NamedTupleType([namedtuple]) type_utils.preorder_call(nested_namedtuple, _count_hits, None) self.assertEqual(Counter.k, 26)
class IsSumCompatibleTest(parameterized.TestCase): @parameterized.named_parameters([ ('tensor_type', computation_types.TensorType(tf.int32)), ('tuple_type_int', computation_types.StructType([tf.int32, tf.int32],)), ('tuple_type_float', computation_types.StructType([tf.complex128, tf.float32, tf.float64])), ('federated_type', computation_types.FederatedType(tf.int32, placement_literals.CLIENTS)), ]) def test_positive_examples(self, type_spec): self.assertTrue(type_analysis.is_sum_compatible(type_spec)) @parameterized.named_parameters([ ('tensor_type_bool', computation_types.TensorType(tf.bool)), ('tensor_type_string', computation_types.TensorType(tf.string)), ('tuple_type', computation_types.StructType([tf.int32, tf.bool])), ('sequence_type', computation_types.SequenceType(tf.int32)), ('placement_type', computation_types.PlacementType()), ('function_type', computation_types.FunctionType(tf.int32, tf.int32)), ('abstract_type', computation_types.AbstractType('T')), ]) def test_negative_examples(self, type_spec): self.assertFalse(type_analysis.is_sum_compatible(type_spec))
def test_to_representation_for_type_with_abstract_type(self): with self.assertRaises(TypeError): reference_executor.to_representation_for_type( 10, computation_types.AbstractType('T'))
# intrinsics defined above, as follows. # # @federated_computation # def federated_aggregate(x, zero, accumulate, merge, report): # a = generic_partial_reduce(x, zero, accumulate, INTERMEDIATE_AGGREGATORS) # b = generic_reduce(a, zero, merge, SERVER) # c = generic_map(report, b) # return c # # Actual implementations might vary. # # Type signature: <{T}@CLIENTS,U,(<U,T>->U),(<U,U>->U),(U->R)> -> R@SERVER FEDERATED_AGGREGATE = IntrinsicDef( 'FEDERATED_AGGREGATE', 'federated_aggregate', computation_types.FunctionType(parameter=[ type_constructors.at_clients(computation_types.AbstractType('T')), computation_types.AbstractType('U'), type_constructors.reduction_op(computation_types.AbstractType('U'), computation_types.AbstractType('T')), type_constructors.binary_op(computation_types.AbstractType('U')), computation_types.FunctionType(computation_types.AbstractType('U'), computation_types.AbstractType('R')) ], result=type_constructors.at_server( computation_types.AbstractType('R')))) # Applies a given function to a value on the server. # # Type signature: <(T->U),T@SERVER> -> U@SERVER FEDERATED_APPLY = IntrinsicDef( 'FEDERATED_APPLY', 'federated_apply',
class CheckWellFormedTest(parameterized.TestCase): # pyformat: disable @parameterized.named_parameters([ ('abstract_type', computation_types.AbstractType('T')), ('federated_type', computation_types.FederatedType(tf.int32, placement_literals.CLIENTS)), ('function_type', computation_types.FunctionType(tf.int32, tf.int32)), ('named_tuple_type', computation_types.NamedTupleType([tf.int32] * 3)), ('placement_type', computation_types.PlacementType()), ('sequence_type', computation_types.SequenceType(tf.int32)), ('tensor_type', computation_types.TensorType(tf.int32)), ]) # pyformat: enable def test_does_not_raise_type_error(self, type_signature): try: type_analysis.check_well_formed(type_signature) except TypeError: self.fail('Raised TypeError unexpectedly.') @parameterized.named_parameters([ ('federated_function_type', computation_types.FederatedType( computation_types.FunctionType(tf.int32, tf.int32), placement_literals.CLIENTS)), ('federated_federated_type', computation_types.FederatedType( computation_types.FederatedType(tf.int32, placement_literals.CLIENTS), placement_literals.CLIENTS)), ('sequence_sequence_type', computation_types.SequenceType( computation_types.SequenceType([tf.int32]))), ('sequence_federated_type', computation_types.SequenceType( computation_types.FederatedType(tf.int32, placement_literals.CLIENTS))), ('tuple_federated_function_type', computation_types.NamedTupleType([ computation_types.FederatedType( computation_types.FunctionType(tf.int32, tf.int32), placement_literals.CLIENTS) ])), ('tuple_federated_federated_type', computation_types.NamedTupleType([ computation_types.FederatedType( computation_types.FederatedType(tf.int32, placement_literals.CLIENTS), placement_literals.CLIENTS) ])), ('federated_tuple_function_type', computation_types.FederatedType( computation_types.NamedTupleType( [computation_types.FunctionType(tf.int32, tf.int32)]), placement_literals.CLIENTS)), ]) # pyformat: enable def test_raises_type_error(self, type_signature): with self.assertRaises(TypeError): type_analysis.check_well_formed(type_signature)
def test_fails_conflicting_binding_in_parameter_and_result(self): t1 = computation_types.FunctionType( *[computation_types.AbstractType('T')] * 2) t2 = computation_types.FunctionType(tf.int32, tf.float32) self.assertFalse(type_analysis.is_concrete_instance_of(t2, t1))
def test_succeeds_function_different_parameter_and_return_types(self): t1 = computation_types.FunctionType( computation_types.AbstractType('T'), computation_types.AbstractType('U')) t2 = computation_types.FunctionType(tf.int32, tf.float32) self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
def test_succeeds_single_function_type(self): t1 = computation_types.FunctionType( *[computation_types.AbstractType('T')] * 2) t2 = computation_types.FunctionType(tf.int32, tf.int32) self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
def test_fails_conflicting_concrete_types_under_sequence(self): t1 = computation_types.SequenceType( [computation_types.AbstractType('T')] * 2) t2 = computation_types.SequenceType([tf.int32, tf.float32]) self.assertFalse(type_analysis.is_concrete_instance_of(t2, t1))
def test_succeeds_abstract_type_under_sequence_type(self): t1 = computation_types.SequenceType( computation_types.AbstractType('T')) t2 = computation_types.SequenceType(tf.int32) self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
def test_raises_with_different_lengths(self): t1 = computation_types.NamedTupleType( [computation_types.AbstractType('T1')] * 2) t2 = computation_types.NamedTupleType([tf.int32]) with self.assertRaises(TypeError): type_analysis.is_concrete_instance_of(t2, t1)
def test_with_single_abstract_type_and_tuple_type(self): t1 = computation_types.AbstractType('T1') t2 = computation_types.NamedTupleType([tf.int32]) self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))