code: def federated_training(model_owner, data_owners):
      # share model owner's model weights to data owners
      update_weights = model_owner.share_weights()
      for data_owner in data_owners:
          data_owner.update_model(*update_weights)
      # collect encrypted gradients from data owners
      model_grads = zip(
          *(data_owner.compute_gradient() for data_owner in data_owners)
      )
      # compute mean of gradients (without decrypting)
      with tf.name_scope("secure_aggregation"):
          aggregated_model_grads = [
              tfe.add_n(grads) / len(grads) for grads in model_grads
          ]
      # send the encrypted aggregated gradients
      # to the model owner for it to decrypt and update
      model_owner.update_model(*aggregated_model_grads)
  
imports: import argparse
  import sys
  import tensorflow
  import tf_encrypted
  from tf_encrypted.keras.datasets import *
  from tf_encrypted.protocol import ABY3
  from tf_encrypted.protocol import Pond
  from tf_encrypted.protocol import SecureNN
label_desc: Use image node_id 1 for calling a global function with example usage: federated_training(model_owner, data_owners) without return types