def sequence_sum(self, value): """Implements `sequence_sum` as defined in `api/intrinsics.py`.""" value = value_impl.to_value(value, None, self._context_stack) if value.type_signature.is_sequence(): element_type = value.type_signature.element else: py_typecheck.check_type(value.type_signature, computation_types.FederatedType) py_typecheck.check_type(value.type_signature.member, computation_types.SequenceType) element_type = value.type_signature.member.element type_analysis.check_is_sum_compatible(element_type) if value.type_signature.is_sequence(): value = value_impl.ValueImpl.get_comp(value) comp = building_block_factory.create_sequence_sum(value) comp = self._bind_comp_as_reference(comp) return value_impl.ValueImpl(comp, self._context_stack) elif value.type_signature.is_federated(): intrinsic_type = computation_types.FunctionType( value.type_signature.member, value.type_signature.member.element) intrinsic = building_blocks.Intrinsic(intrinsic_defs.SEQUENCE_SUM.uri, intrinsic_type) intrinsic_impl = value_impl.ValueImpl(intrinsic, self._context_stack) if value.type_signature.placement in [ placement_literals.SERVER, placement_literals.CLIENTS ]: return self.federated_map(intrinsic_impl, value) else: raise TypeError('Unsupported placement {}.'.format( value.type_signature.placement)) else: raise TypeError( 'Cannot apply `tff.sequence_sum()` to a value of type {}.'.format( value.type_signature))
def federated_sum(self, value): """Implements `federated_sum` as defined in `api/intrinsics.py`.""" value = value_impl.to_value(value, None, self._context_stack) value = value_utils.ensure_federated_value(value, placements.CLIENTS, 'value to be summed') type_analysis.check_is_sum_compatible(value.type_signature) value = value_impl.ValueImpl.get_comp(value) comp = building_block_factory.create_federated_sum(value) return value_impl.ValueImpl(comp, self._context_stack)
def sequence_sum(value): """Computes a sum of elements in a sequence. Args: value: A value of a TFF type that is either a sequence, or a federated sequence. Returns: The sum of elements in the sequence. If the argument `value` is of a federated type, the result is also of a federated type, with the sum computed locally and independently at each location (see also a discussion on `sequence_map` and `sequence_reduce`). Raises: TypeError: If the arguments are of wrong or unsupported types. """ value = value_impl.to_value(value, None) if value.type_signature.is_sequence(): element_type = value.type_signature.element else: py_typecheck.check_type(value.type_signature, computation_types.FederatedType) py_typecheck.check_type(value.type_signature.member, computation_types.SequenceType) element_type = value.type_signature.member.element type_analysis.check_is_sum_compatible(element_type) if value.type_signature.is_sequence(): comp = building_block_factory.create_sequence_sum(value.comp) comp = _bind_comp_as_reference(comp) return value_impl.Value(comp) elif value.type_signature.is_federated(): intrinsic_type = computation_types.FunctionType( value.type_signature.member, value.type_signature.member.element) intrinsic = building_blocks.Intrinsic(intrinsic_defs.SEQUENCE_SUM.uri, intrinsic_type) intrinsic_impl = value_impl.Value(intrinsic) return federated_map(intrinsic_impl, value) else: raise TypeError( 'Cannot apply `tff.sequence_sum()` to a value of type {}.'.format( value.type_signature))
def federated_sum(value): """Computes a sum at `tff.SERVER` of a `value` placed on the `tff.CLIENTS`. To sum integer values with stronger privacy properties, consider using `tff.federated_secure_sum_bitwidth`. Args: value: A value of a TFF federated type placed at the `tff.CLIENTS`. Returns: A representation of the sum of the member constituents of `value` placed on the `tff.SERVER`. Raises: TypeError: If the argument is not a federated TFF value placed at `tff.CLIENTS`. """ value = value_impl.to_value(value, None) value = value_utils.ensure_federated_value(value, placements.CLIENTS, 'value to be summed') type_analysis.check_is_sum_compatible(value.type_signature) comp = building_block_factory.create_federated_sum(value.comp) comp = _bind_comp_as_reference(comp) return value_impl.Value(comp)
def test_negative_examples(self, type_spec): with self.assertRaises(type_analysis.SumIncompatibleError): type_analysis.check_is_sum_compatible(type_spec)
def test_positive_examples(self, type_spec): type_analysis.check_is_sum_compatible(type_spec)