print('PySyft Tensorflow')

https://blog.openmined.org/introducing-pysyft-tensorflow

import tensorflow as tf
import syft

hook = syft.TensorFlowHook(tf)

# Sending a tensor to remote worker

alice = syft.VirtualWorker(hook, "alice")

x = tf.constant([1., 2., 3., 4.])
x_ptr = x.send(alice)

print(x_ptr)
# ==> (Wrapper)>[PointerTensor | me:random_id1 -> alice:random_id2]

# Do arithmetic and manipulation operations directly on these tensors
y_ptr = x_ptr + x_ptr
y = tf.reshape(y_ptr, shape=[2, 2])
id = tf.constant([[1., 0.], [0., 1.]]).send(alice)
z = tf.matmul(y, id).get()

print(z)
# ==> tf.Tensor([[2. 4.]
# [6. 8.]], shape=(2, 2), dtype=float32)

# Only new aspects of PySyft with TF are the new tools
# that Tensorflow bringsm like `tf.Variable`
x = tf.expand_dims(id[0], 0)

# Initialize the weight
w_init = tf.initializers.glorot_normal()
w = tf.Variable(w_init(shape=(2, 1), dtype=tf.float32)).send(alice)
z = tf.matmul(x, w)

# Manual differentiation & update
dzdx = tf.transpose(x)
w.assign_sub(dzdx)

print("Updated: ", w.get())

🌅