def sequence_map(self, fn, arg): """Implements `sequence_map` as defined in `api/intrinsics.py`.""" fn = value_impl.to_value(fn, None, self._context_stack) py_typecheck.check_type(fn.type_signature, computation_types.FunctionType) arg = value_impl.to_value(arg, None, self._context_stack) if isinstance(arg.type_signature, computation_types.SequenceType): fn = value_impl.ValueImpl.get_comp(fn) arg = value_impl.ValueImpl.get_comp(arg) return value_impl.ValueImpl( building_block_factory.create_sequence_map(fn, arg), self._context_stack) elif isinstance(arg.type_signature, computation_types.FederatedType): parameter_type = computation_types.SequenceType( fn.type_signature.parameter) result_type = computation_types.SequenceType(fn.type_signature.result) intrinsic_type = computation_types.FunctionType( (fn.type_signature, parameter_type), result_type) intrinsic = building_blocks.Intrinsic(intrinsic_defs.SEQUENCE_MAP.uri, intrinsic_type) intrinsic_impl = value_impl.ValueImpl(intrinsic, self._context_stack) local_fn = value_utils.get_curried(intrinsic_impl)(fn) if arg.type_signature.placement in [ placements.SERVER, placements.CLIENTS ]: return self.federated_map(local_fn, arg) else: raise TypeError('Unsupported placement {}.'.format( arg.type_signature.placement)) else: raise TypeError( 'Cannot apply `tff.sequence_map()` to a value of type {}.'.format( arg.type_signature))
def sequence_map(fn, arg): """Maps a TFF sequence `value` pointwise using a given function `fn`. This function supports two modes of usage: * When applied to a non-federated sequence, it maps individual elements of the sequence pointwise. If the supplied `fn` is of type `T->U` and the sequence `arg` is of type `T*` (a sequence of `T`-typed elements), the result is a sequence of type `U*` (a sequence of `U`-typed elements), with each element of the input sequence individually mapped by `fn`. In this mode of usage, `sequence_map` behaves like a compuatation with type signature `<T->U,T*> -> U*`. * When applied to a federated sequence, `sequence_map` behaves as if it were individually applied to each member constituent. In this mode of usage, one can think of `sequence_map` as a specialized variant of `federated_map` that is designed to work with sequences and allows one to specify a `fn` that operates at the level of individual elements. Indeed, under the hood, when `sequence_map` is invoked on a federated type, it injects `federated_map`, thus emitting expressions like `federated_map(a -> sequence_map(fn, x), arg)`. Args: fn: A mapping function to apply pointwise to elements of `arg`. arg: A value of a TFF type that is either a sequence, or a federated sequence. Returns: A sequence with the result of applying `fn` pointwise to each element of `arg`, or if `arg` was federated, a federated sequence with the result of invoking `sequence_map` on member sequences locally and independently at each location. Raises: TypeError: If the arguments are not of the appropriate types. """ fn = value_impl.to_value(fn, None) py_typecheck.check_type(fn.type_signature, computation_types.FunctionType) arg = value_impl.to_value(arg, None) if arg.type_signature.is_sequence(): comp = building_block_factory.create_sequence_map(fn.comp, arg.comp) comp = _bind_comp_as_reference(comp) return value_impl.Value(comp) elif arg.type_signature.is_federated(): parameter_type = computation_types.SequenceType( fn.type_signature.parameter) result_type = computation_types.SequenceType(fn.type_signature.result) intrinsic_type = computation_types.FunctionType( (fn.type_signature, parameter_type), result_type) intrinsic = building_blocks.Intrinsic(intrinsic_defs.SEQUENCE_MAP.uri, intrinsic_type) intrinsic_impl = value_impl.Value(intrinsic) local_fn = value_utils.get_curried(intrinsic_impl)(fn) return federated_map(local_fn, arg) else: raise TypeError( 'Cannot apply `tff.sequence_map()` to a value of type {}.'.format( arg.type_signature))
def create_whimsy_called_sequence_map(parameter_name, parameter_type=tf.int32): r"""Returns a whimsy called sequence map. Call / \ sequence_map data Args: parameter_name: The name of the parameter. parameter_type: The type of the parameter. """ fn = create_identity_function(parameter_name, parameter_type) arg_type = computation_types.SequenceType(parameter_type) arg = building_blocks.Data('data', arg_type) return building_block_factory.create_sequence_map(fn, arg)