docs: def lattice(prng, n_features, alpha, random_sign=False, low=0.3, high=0.7):
      """Returns the adjacency matrix for a lattice network.
  
      The resulting network is a Toeplitz matrix with random values summing
      between -1 and 1 and zeros along the diagonal.
  
      The range of the values can be controlled via the parameters low and high.
      If random_sign is false, all entries will be negative, otherwise their sign
      will be modulated at random with probability 1/2.
  
      Each row has maximum edges of np.ceil(alpha * n_features).
  
      Parameters
      -----------
      n_features : int
  
      alpha : float (0, 1)
          The complexity / sparsity factor.
  
      random sign : bool (default=False)
          Randomly modulate each entry by 1 or -1 with probability of 1/2.
  
      low : float (0, 1) (default=0.3)
          Lower bound for np.random.RandomState.uniform before normalization.
  
      high : float (0, 1) > low (default=0.7)
          Upper bound for np.random.RandomState.uniform before normalization.
      """
      degree = int(1 + np.round(alpha * n_features / 2.))
  
      if random_sign:
          sign_row = -1.0 * np.ones(degree) + 2 * (
              prng.uniform(low=0, high=1, size=degree) > .5
          )
      else:
          sign_row = -1.0 * np.ones(degree)
  
      # in the *very unlikely* event that we draw a bad row that sums to zero
      # (which is only possible when random_sign=True), we try again up to
      # MAX_ATTEMPTS=5 times.  If we are still unable to draw a good set of
      # values something is probably wrong and we raise.
      MAX_ATTEMPTS = 5
      attempt = 0
      row = np.zeros((n_features,))
      while np.sum(row) == 0 and attempt < MAX_ATTEMPTS:
          row = np.zeros((n_features,))
          row[1 : 1 + degree] = sign_row * prng.uniform(low=low, high=high, size=degree)
          attempt += 1
  
      if np.sum(row) == 0:
          raise Exception("InvalidLattice", "Rows sum to 0.")
          return
  
      # sum-normalize and keep signs
      row /= np.abs(np.sum(row))
  
      return sp.linalg.toeplitz(c=row, r=row)