code: def sinkhorn(w1, w2, M, reg, k):
      
      K = np.exp(-M / reg)
      ui = np.ones((M.shape[0],))
      vi = np.ones((M.shape[1],))
      for i in range(k):
          vi = w2 / (np.dot(K.T, ui))
          ui = w1 / (np.dot(K, vi))
      G = ui.reshape((M.shape[0], 1)) * K * vi.reshape((1, M.shape[1]))
      return G
docs: Sinkhorn algorithm with fixed number of iteration (autograd)