def makeringlatticeCIJ(n, k, seed=None):
    '''
    This function generates a directed lattice network with toroidal
    boundary counditions (i.e. with ring-like "wrapping around").

    Parameters
    ----------
    N : int
        number of vertices
    K : int
        number of edges
    seed : hashable, optional
        If None (default), use the np.random's global random state to generate random numbers.
        Otherwise, use a new np.random.RandomState instance seeded with the given value.

    Returns
    -------
    CIJ : NxN np.ndarray
        connection matrix

    Notes
    -----
    The lattice is made by placing connections as close as possible
    to the main diagonal, with wrapping around. No connections are made
    on the main diagonal. In/Outdegree is kept approx. constant at K/N.
    '''
    rng = get_rng(seed)
    # initialize
    CIJ = np.zeros((n, n))
    CIJ1 = np.ones((n, n))
    kk = 0
    count = 0
    seq = range(1, n)
    seq2 = range(n - 1, 0, -1)

    # fill in
    while kk < k:
        count += 1
        dCIJ = np.triu(CIJ1, seq[count]) - np.triu(CIJ1, seq[count] + 1)
        dCIJ2 = np.triu(CIJ1, seq2[count]) - np.triu(CIJ1, seq2[count] + 1)
        dCIJ = dCIJ + dCIJ.T + dCIJ2 + dCIJ2.T
        CIJ += dCIJ
        kk = int(np.sum(CIJ))

    # remove excess connections
    overby = kk - k
    if overby:
        i, j = np.where(dCIJ)
        rp = rng.permutation(np.size(i))
        for ii in range(overby):
            CIJ[i[rp[ii]], j[rp[ii]]] = 0

    return CIJ
This function generates a directed lattice network with toroidal
    boundary counditions (i.e. with ring-like "wrapping around").

    Parameters
    ----------
    N : int
        number of vertices
    K : int
        number of edges
    seed : hashable, optional
        If None (default), use the np.random's global random state to generate random numbers.
        Otherwise, use a new np.random.RandomState instance seeded with the given value.

    Returns
    -------
    CIJ : NxN np.ndarray
        connection matrix

    Notes
    -----
    The lattice is made by placing connections as close as possible
    to the main diagonal, with wrapping around. No connections are made
    on the main diagonal. In/Outdegree is kept approx. constant at K/N.