Пример #1
0
 def test_raises_with_conflicting_names(self):
     t1 = computation_types.NamedTupleType(
         [computation_types.AbstractType('T1')] * 2)
     t2 = computation_types.NamedTupleType([('a', tf.int32),
                                            ('b', tf.int32)])
     with self.assertRaises(TypeError):
         type_analysis.is_concrete_instance_of(t2, t1)
Пример #2
0
 def test_succeeds_under_tuple(self):
     t1 = computation_types.NamedTupleType(
         [computation_types.AbstractType('T1')] * 2)
     t2 = computation_types.NamedTupleType([
         computation_types.TensorType(tf.int32),
         computation_types.TensorType(tf.int32)
     ])
     self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
Пример #3
0
 def test_abstract_federated_types_succeeds(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.CLIENTS, all_equal=True)
   self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
Пример #4
0
 def test_abstract_fails_on_different_federated_placements(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))
Пример #5
0
 def test_fails_under_tuple_conflicting_concrete_types(self):
     t1 = computation_types.NamedTupleType(
         [computation_types.AbstractType('T1')] * 2)
     t2 = computation_types.NamedTupleType([
         computation_types.TensorType(tf.int32),
         computation_types.TensorType(tf.float32)
     ])
     self.assertFalse(type_analysis.is_concrete_instance_of(t2, t1))
Пример #6
0
 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)
Пример #7
0
 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))
Пример #8
0
    async def create_value(self, value, type_spec=None):
        """A coroutine that creates embedded value from `value` of type `type_spec`.

    See the `FederatingExecutorValue` for detailed information about the
    `value`s and `type_spec`s that can be embedded using `create_value`.

    Args:
      value: An object that represents the value to embed within the executor.
      type_spec: An optional `tff.Type` of the value represented by this object,
        or something convertible to it.

    Returns:
      An instance of `FederatingExecutorValue` that represents the embedded
      value.

    Raises:
      TypeError: If the `value` and `type_spec` do not match.
      ValueError: If `value` is not a kind recognized by the
        `FederatingExecutor`.
    """
        type_spec = computation_types.to_type(type_spec)
        if isinstance(type_spec, computation_types.FederatedType):
            self._check_executor_compatible_with_placement(type_spec.placement)
        elif (isinstance(type_spec, computation_types.FunctionType) and
              isinstance(type_spec.result, computation_types.FederatedType)):
            self._check_executor_compatible_with_placement(
                type_spec.result.placement)
        if isinstance(value, intrinsic_defs.IntrinsicDef):
            if not type_analysis.is_concrete_instance_of(
                    type_spec, value.type_signature):
                raise TypeError(
                    'Incompatible type {} used with intrinsic {}.'.format(
                        type_spec, value.uri))
            return FederatingExecutorValue(value, type_spec)
        elif isinstance(value, placement_literals.PlacementLiteral):
            if type_spec is None:
                type_spec = computation_types.PlacementType()
            else:
                py_typecheck.check_type(type_spec,
                                        computation_types.PlacementType)
            return FederatingExecutorValue(value, type_spec)
        elif isinstance(value, computation_impl.ComputationImpl):
            return await self.create_value(
                computation_impl.ComputationImpl.get_proto(value),
                type_utils.reconcile_value_with_type_spec(value, type_spec))
        elif isinstance(value, pb.Computation):
            deserialized_type = type_serialization.deserialize_type(value.type)
            if type_spec is None:
                type_spec = deserialized_type
            else:
                type_analysis.check_assignable_from(type_spec,
                                                    deserialized_type)
            which_computation = value.WhichOneof('computation')
            if which_computation in ['lambda', 'tensorflow']:
                return FederatingExecutorValue(value, type_spec)
            elif which_computation == 'intrinsic':
                intrinsic_def = intrinsic_defs.uri_to_intrinsic_def(
                    value.intrinsic.uri)
                if intrinsic_def is None:
                    raise ValueError(
                        'Encountered an unrecognized intrinsic "{}".'.format(
                            value.intrinsic.uri))
                return await self.create_value(intrinsic_def, type_spec)
            else:
                raise ValueError(
                    'Unsupported computation building block of type "{}".'.
                    format(which_computation))
        elif isinstance(type_spec, computation_types.FederatedType):
            self._check_value_compatible_with_placement(
                value, type_spec.placement, type_spec.all_equal)
            children = self._target_executors[type_spec.placement]
            if type_spec.all_equal:
                value = [value for _ in children]
            results = await asyncio.gather(*[
                c.create_value(v, type_spec.member)
                for v, c in zip(value, children)
            ])
            return FederatingExecutorValue(results, type_spec)
        else:
            child = self._target_executors[None][0]
            return FederatingExecutorValue(
                await child.create_value(value, type_spec), type_spec)
Пример #9
0
 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))
Пример #10
0
 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))
Пример #11
0
 def test_raises_different_structures(self):
     with self.assertRaises(TypeError):
         type_analysis.is_concrete_instance_of(
             computation_types.to_type(tf.int32),
             computation_types.to_type([tf.int32]))
Пример #12
0
 def test_raises_with_int_second_argument(self):
     with self.assertRaises(TypeError):
         type_analysis.is_concrete_instance_of(
             computation_types.to_type(tf.int32), 1)
Пример #13
0
 def test_raises_with_int_first_argument(self):
   with self.assertRaises(TypeError):
     type_analysis.is_concrete_instance_of(
         1, computation_types.TensorType(tf.int32))
Пример #14
0
 async def create_value(self, value, type_spec=None):
     type_spec = computation_types.to_type(type_spec)
     if isinstance(value, intrinsic_defs.IntrinsicDef):
         if not type_analysis.is_concrete_instance_of(
                 type_spec, value.type_signature):  # pytype: disable=attribute-error
             raise TypeError(
                 'Incompatible type {} used with intrinsic {}.'.format(
                     type_spec, value.uri))
         return CompositeValue(value, type_spec)
     elif isinstance(value, pb.Computation):
         which_computation = value.WhichOneof('computation')
         if which_computation in ['lambda', 'tensorflow']:
             return CompositeValue(value, type_spec)
         elif which_computation == 'intrinsic':
             intrinsic_def = intrinsic_defs.uri_to_intrinsic_def(
                 value.intrinsic.uri)
             if intrinsic_def is None:
                 raise ValueError(
                     'Encountered an unrecognized intrinsic "{}".'.format(
                         value.intrinsic.uri))
             return await self.create_value(intrinsic_def, type_spec)
         else:
             raise NotImplementedError(
                 'Unimplemented computation type {}.'.format(
                     which_computation))
     elif isinstance(type_spec, computation_types.FederatedType):
         if type_spec.placement == placement_literals.SERVER:
             if not type_spec.all_equal:
                 raise ValueError(
                     'Expected an all equal value at the `SERVER` placement, '
                     'found {}.'.format(type_spec))
             results = await self._parent_executor.create_value(
                 value, type_spec.member)
             return CompositeValue(results, type_spec)
         elif type_spec.placement == placement_literals.CLIENTS:
             if type_spec.all_equal:
                 results = await asyncio.gather(*[
                     c.create_value(value, type_spec)
                     for c in self._child_executors
                 ])
                 return CompositeValue(results, type_spec)
             else:
                 py_typecheck.check_type(value, list)
                 cardinalities = await self._get_cardinalities()
                 total_clients = sum(cardinalities)
                 py_typecheck.check_len(value, total_clients)
                 results = []
                 offset = 0
                 for child, num_clients in zip(self._child_executors,
                                               cardinalities):
                     new_offset = offset + num_clients
                     result = child.create_value(value[offset:new_offset],
                                                 type_spec)
                     results.append(result)
                     offset = new_offset
                 return CompositeValue(await asyncio.gather(*results),
                                       type_spec)
         else:
             raise ValueError('Unexpected placement {}.'.format(
                 type_spec.placement))
     else:
         return CompositeValue(
             await self._parent_executor.create_value(value, type_spec),
             type_spec)
Пример #15
0
  async def create_value(
      self,
      value: Any,
      type_spec: Any = None) -> executor_value_base.ExecutorValue:
    """Creates an embedded value from the given `value` and `type_spec`.

    The kinds of supported `value`s are:

    * An instance of `intrinsic_defs.IntrinsicDef`.

    * An instance of `placement_literals.PlacementLiteral`.

    * An instance of `pb.Computation` if of one of the following kinds:
      intrinsic, lambda, and tensorflow.

    * A Python `list` if `type_spec` is a federated type.

      Note: The `value` must be a list even if it is of an `all_equal` type or
      if there is only a single participant associated with the given placement.

    * A Python value if `type_spec` is a non-functional, non-federated type.

    Args:
      value: An object to embed in the executor, one of the supported types
        defined by above.
      type_spec: An optional type convertible to instance of `tff.Type` via
        `tff.to_type`, the type of `value`.

    Returns:
      An instance of `executor_value_base.ExecutorValue` representing a value
      embedded in the `FederatingExecutor` using a particular
      `FederatingStrategy`.

    Raises:
      TypeError: If the `value` and `type_spec` do not match.
      ValueError: If `value` is not a kind supported by the
        `FederatingExecutor`.
    """
    type_spec = computation_types.to_type(type_spec)
    if isinstance(value, intrinsic_defs.IntrinsicDef):
      if not type_analysis.is_concrete_instance_of(type_spec,
                                                   value.type_signature):
        raise TypeError('Incompatible type {} used with intrinsic {}.'.format(
            type_spec, value.uri))
      return self._strategy.ingest_value(value, type_spec)
    elif isinstance(value, placement_literals.PlacementLiteral):
      if type_spec is None:
        type_spec = computation_types.PlacementType()
      type_spec.check_placement()
      return self._strategy.ingest_value(value, type_spec)
    elif isinstance(value, computation_impl.ComputationImpl):
      return await self.create_value(
          computation_impl.ComputationImpl.get_proto(value),
          type_utils.reconcile_value_with_type_spec(value, type_spec))
    elif isinstance(value, pb.Computation):
      deserialized_type = type_serialization.deserialize_type(value.type)
      if type_spec is None:
        type_spec = deserialized_type
      else:
        type_spec.check_assignable_from(deserialized_type)
      which_computation = value.WhichOneof('computation')
      if which_computation in ['lambda', 'tensorflow']:
        return self._strategy.ingest_value(value, type_spec)
      elif which_computation == 'intrinsic':
        intrinsic_def = intrinsic_defs.uri_to_intrinsic_def(value.intrinsic.uri)
        if intrinsic_def is None:
          raise ValueError('Encountered an unrecognized intrinsic "{}".'.format(
              value.intrinsic.uri))
        return await self.create_value(intrinsic_def, type_spec)
      else:
        raise ValueError(
            'Unsupported computation building block of type "{}".'.format(
                which_computation))
    elif type_spec is not None and type_spec.is_federated():
      return await self._strategy.compute_federated_value(value, type_spec)
    else:
      result = await self._unplaced_executor.create_value(value, type_spec)
      return self._strategy.ingest_value(result, type_spec)
Пример #16
0
 def test_raises_with_abstract_type_as_first_arg(self):
     t1 = computation_types.AbstractType('T1')
     t2 = computation_types.TensorType(tf.int32)
     with self.assertRaises(TypeError):
         type_analysis.is_concrete_instance_of(t1, t2)
Пример #17
0
 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))
Пример #18
0
 def test_with_single_abstract_type_and_tensor_type(self):
     t1 = computation_types.AbstractType('T1')
     t2 = computation_types.TensorType(tf.int32)
     self.assertTrue(type_analysis.is_concrete_instance_of(t2, t1))
Пример #19
0
 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))
Пример #20
0
 def test_raises_with_abstract_type_in_second_argument(self):
     t1 = computation_types.AbstractType('T1')
     t2 = computation_types.AbstractType('T2')
     with self.assertRaises(TypeError):
         type_analysis.is_concrete_instance_of(t2, t1)
Пример #21
0
 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))
    async def create_value(self, value, type_spec=None):
        """A coroutine that creates embedded value from `value` of type `type_spec`.

    See the `FederatingExecutorValue` for detailed information about the
    `value`s and `type_spec`s that can be embedded using `create_value`.

    Args:
      value: An object that represents the value to embed within the executor.
      type_spec: An optional `tff.Type` of the value represented by this object,
        or something convertible to it.

    Returns:
      An instance of `FederatingExecutorValue` that represents the embedded
      value.

    Raises:
      TypeError: If the `value` and `type_spec` do not match.
      ValueError: If `value` is not a kind recognized by the
        `FederatingExecutor`.
    """
        type_spec = computation_types.to_type(type_spec)
        if isinstance(type_spec, computation_types.FederatedType):
            self._check_executor_compatible_with_placement(type_spec.placement)
        elif (isinstance(type_spec, computation_types.FunctionType) and
              isinstance(type_spec.result, computation_types.FederatedType)):
            self._check_executor_compatible_with_placement(
                type_spec.result.placement)
        if isinstance(value, intrinsic_defs.IntrinsicDef):
            if not type_analysis.is_concrete_instance_of(
                    type_spec, value.type_signature):
                raise TypeError(
                    'Incompatible type {} used with intrinsic {}.'.format(
                        type_spec, value.uri))
            return FederatingExecutorValue(value, type_spec)
        elif isinstance(value, placement_literals.PlacementLiteral):
            if type_spec is None:
                type_spec = computation_types.PlacementType()
            else:
                py_typecheck.check_type(type_spec,
                                        computation_types.PlacementType)
            return FederatingExecutorValue(value, type_spec)
        elif isinstance(value, computation_impl.ComputationImpl):
            return await self.create_value(
                computation_impl.ComputationImpl.get_proto(value),
                type_utils.reconcile_value_with_type_spec(value, type_spec))
        elif isinstance(value, pb.Computation):
            deserialized_type = type_serialization.deserialize_type(value.type)
            if type_spec is None:
                type_spec = deserialized_type
            else:
                type_analysis.check_assignable_from(type_spec,
                                                    deserialized_type)
            which_computation = value.WhichOneof('computation')
            if which_computation in ['lambda', 'tensorflow']:
                return FederatingExecutorValue(value, type_spec)
            elif which_computation == 'reference':
                raise ValueError(
                    'Encountered an unexpected unbound references "{}".'.
                    format(value.reference.name))
            elif which_computation == 'intrinsic':
                intr = intrinsic_defs.uri_to_intrinsic_def(value.intrinsic.uri)
                if intr is None:
                    raise ValueError(
                        'Encountered an unrecognized intrinsic "{}".'.format(
                            value.intrinsic.uri))
                py_typecheck.check_type(intr, intrinsic_defs.IntrinsicDef)
                return await self.create_value(intr, type_spec)
            elif which_computation == 'placement':
                return await self.create_value(
                    placement_literals.uri_to_placement_literal(
                        value.placement.uri), type_spec)
            elif which_computation == 'call':
                parts = [value.call.function]
                if value.call.argument.WhichOneof('computation'):
                    parts.append(value.call.argument)
                parts = await asyncio.gather(
                    *[self.create_value(x) for x in parts])
                return await self.create_call(
                    parts[0], parts[1] if len(parts) > 1 else None)
            elif which_computation == 'tuple':
                element_values = await asyncio.gather(
                    *[self.create_value(x.value) for x in value.tuple.element])
                return await self.create_tuple(
                    anonymous_tuple.AnonymousTuple(
                        (e.name if e.name else None, v)
                        for e, v in zip(value.tuple.element, element_values)))
            elif which_computation == 'selection':
                which_selection = value.selection.WhichOneof('selection')
                if which_selection == 'name':
                    name = value.selection.name
                    index = None
                elif which_selection != 'index':
                    raise ValueError(
                        'Unrecognized selection type: "{}".'.format(
                            which_selection))
                else:
                    index = value.selection.index
                    name = None
                return await self.create_selection(await self.create_value(
                    value.selection.source),
                                                   index=index,
                                                   name=name)
            else:
                raise ValueError(
                    'Unsupported computation building block of type "{}".'.
                    format(which_computation))
        else:
            py_typecheck.check_type(type_spec, computation_types.Type)
            if isinstance(type_spec, computation_types.FunctionType):
                raise ValueError(
                    'Encountered a value of a functional TFF type {} and Python type '
                    '{} that is not of one of the recognized representations.'.
                    format(type_spec, py_typecheck.type_string(type(value))))
            elif isinstance(type_spec, computation_types.FederatedType):
                children = self._target_executors.get(type_spec.placement)
                self._check_value_compatible_with_placement(
                    value, type_spec.placement, type_spec.all_equal)
                if type_spec.all_equal:
                    value = [value for _ in children]
                child_vals = await asyncio.gather(*[
                    c.create_value(v, type_spec.member)
                    for v, c in zip(value, children)
                ])
                return FederatingExecutorValue(child_vals, type_spec)
            else:
                child = self._target_executors.get(None)
                if not child or len(child) > 1:
                    raise ValueError(
                        'Executor is not configured for unplaced values.')
                else:
                    return FederatingExecutorValue(
                        await child[0].create_value(value, type_spec),
                        type_spec)