# tff.tensorflow.computation

<br />

Decorates/wraps Python functions and defuns as TFF TensorFlow computations.

    tff.tensorflow.computation(
        *args, **kwargs
    )

### Used in the notebooks

| Used in the tutorials |
|---|
| - [Implementing Custom Aggregations](https://www.tensorflow.org/federated/tutorials/custom_aggregators) - [Sending Different Data To Particular Clients With federated_language.federated_select](https://www.tensorflow.org/federated/tutorials/federated_select) - [Random noise generation in TFF](https://www.tensorflow.org/federated/tutorials/random_noise_generation) - [Custom Federated Algorithms, Part 1: Introduction to the Federated Core](https://www.tensorflow.org/federated/tutorials/custom_federated_algorithms_1) - [Building Your Own Federated Learning Algorithm](https://www.tensorflow.org/federated/tutorials/building_your_own_federated_learning_algorithm) |

This symbol can be used as either a decorator or a wrapper applied to a
function given to it as an argument. The supported patterns and examples of
usage are as follows:

1. Convert an existing function inline into a TFF computation. This is the
   simplest mode of usage, and how one can embed existing non-TFF code for
   use with the TFF framework. In this mode, one invokes
   [`tff.tensorflow.computation`](https://www.tensorflow.org/federated/api_docs/python/tff/tensorflow/computation) with a pair of arguments, the first being a
   function/defun that contains the logic, and the second being the TFF type
   of the parameter:

       foo = tff.tensorflow.computation(lambda x: x > 10, tf.int32)

   After executing the above code snippet, `foo` becomes an instance of the
   abstract base class `Computation`. Like all computations, it has the
   `type_signature` property:

       str(foo.type_signature) == '(int32 -> bool)'

   The function passed as a parameter doesn't have to be a lambda, it can
   also be an existing Python function or a defun. Here's how to construct
   a computation from the standard TensorFlow operator [`tf.add`](https://www.tensorflow.org/api_docs/python/tf/math/add):

       foo = tff.tensorflow.computation(tf.add, (tf.int32, tf.int32))

   The resulting type signature is as expected:

       str(foo.type_signature) == '(<int32,int32> -> int32)'

   If one intends to create a computation that doesn't accept any arguments,
   the type argument is simply omitted. The function must be a no-argument
   function as well:

       foo = tff.tensorflow.computation(lambda: tf.constant(10))

2. Decorate a Python function or a TensorFlow defun with a TFF type to wrap
   it as a TFF computation. The only difference between this mode of usage
   and the one mentioned above is that instead of passing the function/defun
   as an argument, [`tff.tensorflow.computation`](https://www.tensorflow.org/federated/api_docs/python/tff/tensorflow/computation) along with the optional type specifier
   is written above the function/defun's body.

   Here's an example of a computation that accepts a parameter:

       @tff.tensorflow.computation(tf.int32)
       def foo(x):
         return x > 10

   One can think of this mode of usage as merely a syntactic sugar for the
   example already given earlier:

       foo = tff.tensorflow.computation(lambda x: x > 10, tf.int32)

   Here's an example of a no-parameter computation:

       @tff.tensorflow.computation
       def foo():
         return tf.constant(10)

   Again, this is merely syntactic sugar for the example given earlier:

       foo = tff.tensorflow.computation(lambda: tf.constant(10))

   If the Python function has multiple decorators,
   [`tff.tensorflow.computation`](https://www.tensorflow.org/federated/api_docs/python/tff/tensorflow/computation) should be the outermost one (the one that
   appears first in the sequence).
3. Create a polymorphic callable to be instantiated based on arguments,
   similarly to TensorFlow defuns that have been defined without an input
   signature.

   This mode of usage is symmetric to those above. One simply omits the type
   specifier, and applies [`tff.tensorflow.computation`](https://www.tensorflow.org/federated/api_docs/python/tff/tensorflow/computation) as a decorator or
   wrapper to a function/defun that does expect parameters.

   Here's an example of wrapping a lambda as a polymorphic callable:

       foo = tff.tensorflow.computation(lambda x, y: x > y)

   The resulting `foo` can be used in the same ways as if it were had the
   type been declared; the corresponding computation is simply created on
   demand, in the same way as how polymorphic TensorFlow defuns create and
   cache concrete function definitions for each combination of argument
   types.

       ...foo(1, 2)...
       ...foo(0.5, 0.3)...

   Here's an example of creating a polymorphic callable via decorator:

       @tff.tensorflow.computation
       def foo(x, y):
         return x > y

   The syntax is symmetric to all examples already shown.

<br />

<br />

<br />

| ## Args ||
|---|---|
| `*args` | Either a function/defun, or TFF type spec, or both (function first), or neither, as documented in the 3 patterns and examples of usage above. |

<br />

<br />

<br />

<br />

| ## Returns ||
|---|---|
| If invoked with a function as an argument, returns an instance of a TFF computation constructed based on this function. If called without one, as in the typical decorator style of usage, returns a callable that expects to be called with the function definition supplied as a parameter; see the patterns and examples of usage above. ||

<br />