/** Creates the neighbour relationships between neurons. */
  private void createLinks() {
    // "linkEnd" will store the identifiers of the "neighbours".
    final List<Long> linkEnd = new ArrayList<Long>();
    final int iLast = numberOfRows - 1;
    final int jLast = numberOfColumns - 1;
    for (int i = 0; i < numberOfRows; i++) {
      for (int j = 0; j < numberOfColumns; j++) {
        linkEnd.clear();

        switch (neighbourhood) {
          case MOORE:
            // Add links to "diagonal" neighbours.
            if (i > 0) {
              if (j > 0) {
                linkEnd.add(identifiers[i - 1][j - 1]);
              }
              if (j < jLast) {
                linkEnd.add(identifiers[i - 1][j + 1]);
              }
            }
            if (i < iLast) {
              if (j > 0) {
                linkEnd.add(identifiers[i + 1][j - 1]);
              }
              if (j < jLast) {
                linkEnd.add(identifiers[i + 1][j + 1]);
              }
            }
            if (wrapRows) {
              if (i == 0) {
                if (j > 0) {
                  linkEnd.add(identifiers[iLast][j - 1]);
                }
                if (j < jLast) {
                  linkEnd.add(identifiers[iLast][j + 1]);
                }
              } else if (i == iLast) {
                if (j > 0) {
                  linkEnd.add(identifiers[0][j - 1]);
                }
                if (j < jLast) {
                  linkEnd.add(identifiers[0][j + 1]);
                }
              }
            }
            if (wrapColumns) {
              if (j == 0) {
                if (i > 0) {
                  linkEnd.add(identifiers[i - 1][jLast]);
                }
                if (i < iLast) {
                  linkEnd.add(identifiers[i + 1][jLast]);
                }
              } else if (j == jLast) {
                if (i > 0) {
                  linkEnd.add(identifiers[i - 1][0]);
                }
                if (i < iLast) {
                  linkEnd.add(identifiers[i + 1][0]);
                }
              }
            }
            if (wrapRows && wrapColumns) {
              if (i == 0 && j == 0) {
                linkEnd.add(identifiers[iLast][jLast]);
              } else if (i == 0 && j == jLast) {
                linkEnd.add(identifiers[iLast][0]);
              } else if (i == iLast && j == 0) {
                linkEnd.add(identifiers[0][jLast]);
              } else if (i == iLast && j == jLast) {
                linkEnd.add(identifiers[0][0]);
              }
            }

            // Case falls through since the "Moore" neighbourhood
            // also contains the neurons that belong to the "Von
            // Neumann" neighbourhood.

            // fallthru (CheckStyle)
          case VON_NEUMANN:
            // Links to preceding and following "row".
            if (i > 0) {
              linkEnd.add(identifiers[i - 1][j]);
            }
            if (i < iLast) {
              linkEnd.add(identifiers[i + 1][j]);
            }
            if (wrapRows) {
              if (i == 0) {
                linkEnd.add(identifiers[iLast][j]);
              } else if (i == iLast) {
                linkEnd.add(identifiers[0][j]);
              }
            }

            // Links to preceding and following "column".
            if (j > 0) {
              linkEnd.add(identifiers[i][j - 1]);
            }
            if (j < jLast) {
              linkEnd.add(identifiers[i][j + 1]);
            }
            if (wrapColumns) {
              if (j == 0) {
                linkEnd.add(identifiers[i][jLast]);
              } else if (j == jLast) {
                linkEnd.add(identifiers[i][0]);
              }
            }
            break;

          default:
            throw new MathInternalError(); // Cannot happen.
        }

        final Neuron aNeuron = network.getNeuron(identifiers[i][j]);
        for (long b : linkEnd) {
          final Neuron bNeuron = network.getNeuron(b);
          // Link to all neighbours.
          // The reverse links will be added as the loop proceeds.
          network.addLink(aNeuron, bNeuron);
        }
      }
    }
  }