docs: def reconstruct_acd(edm, X0, W=None, print_out=False, tol=1e-10, sweeps=10):
      """ Reconstruct point set using alternating coordinate descent.
  
      :param X0: Nxd matrix of starting points.
      :param tol: Stopping criterion: if the stepsize in all coordinate directions 
                  is less than tol for 2 consecutive sweeps, we stop. 
      :param sweep: Maximum number of sweeps. One sweep goes through all coordintaes and points once. 
      """
  
      def get_unique_delta(delta, i, coord, print_out=False):
          delta_unique = delta.copy()
          ftest = []
          for de in delta_unique:
              X_ktest = X_k.copy()
              X_ktest[i, coord] += de
              ftest.append(f(X_ktest, edm, W))
          # choose delta_unique with lowest cost.
          if print_out:
              print(ftest)
              print(delta_unique)
          delta_unique = delta_unique[ftest == min(ftest)]
          if print_out:
              print(delta_unique)
          if len(delta_unique) > 1:
              # if multiple delta_uniques give the same cost, choose the biggest step.
              delta_unique = max(delta_unique)
          return delta_unique
  
      def sweep():
          for i in range(N):
              loop_point(i)
  
      def loop_coordinate(coord, i):
          delta = get_step_size(i, coord, X_k, edm, W)
          if len(delta) > 1:
              delta_unique = get_unique_delta(delta, i, coord)
          elif len(delta) == 1:
              delta_unique = delta[0]
          else:
              print('Warning: did not find delta!', delta)
              delta_unique = 0.0
          try:
              X_k[i, coord] += delta_unique
          except:
              get_unique_delta(delta, i, coord, print_out=True)
              raise
  
          cost_this = f(X_k, edm, W)
          costs.append(cost_this)
  
          if delta_unique <= tol:
              coordinates_converged[i, coord] += 1
          else:
              if print_out:
                  print('======= coordinate {} of {} not yet converged'.format(coord, i))
              coordinates_converged[i, coord] = 0
  
      def loop_point(i):
          coord_counter = 0
          while not (coordinates_converged[i] >= 2).all():
              if print_out:
                  print('==== point {}'.format(i))
              coord_counter += 1
              for coord in range(d):
                  if print_out:
                      print('======= coord {}'.format(coord))
                  loop_coordinate(coord, i)
              if coord_counter > coord_n_it:
                  break
      from .distributed_mds import get_step_size, f
  
      N, d = X0.shape
      if W is None:
          W = np.ones((N, N)) - np.eye(N)
  
      X_k = X0.copy()
  
      costs = []
      coordinates_converged = np.zeros(X_k.shape)
      coord_n_it = 3
      for sweep_counter in range(sweeps):
          if print_out:
              print('= sweep', sweep_counter)
          sweep()
          if (coordinates_converged >= 2).all():
              if (print_out):
                  print('acd: all coordinates converged after {} sweeps.'.format(
                      sweep_counter))
              return X_k, costs
      if (print_out):
          print('acd: did not converge after {} sweeps'.format(sweep_counter + 1))
      return X_k, costs