def erx(a, b):
    """
    http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/EdgeRecombinationCrossoverOperator.aspx

    Algorithm Pseudo Code:

    1. X = the first node from a random parent.

    2. While the CHILD chromo isn't full, Loop:
        - Append X to CHILD
        - Remove X from Neighbor Lists

        if X's neighbor list is empty:
           - Xp = random node not already in CHILD
        else
           - Determine neighbor of X that has fewest neighbors
           - If there is a tie, randomly choose 1
           - Xp = chosen node
        X = Xp
     """

    assert len(a) == len(b)

    # calculate the edge matrix considering both permutation
    H = calc_adjency_matrix(a)
    H = calc_adjency_matrix(b, H=H)

    # randomly select the first node
    _next = np.random.choice(list(H.keys()))

    y = []
    while True:

        # append to the child
        y.append(_next)

        # break if the child was successfully created.
        if len(y) == len(a):
            break

        # get the neighbors to consider and remove them from the lists
        neighbors = list(H[_next])
        remove_from_adj_list(H, _next)

        # if the current node does not have any neighbors
        if len(neighbors) == 0:
            _next = np.random.choice(list(H.keys()))

        # otherwise search in the neighbors for a node with the fewest neighbors
        else:
            # search for the one with minimum neighbors
            n_neighbors = [len(H[e]) for e in neighbors]
            min_n_neighbors = min(n_neighbors)
            _next = [neighbors[k] for k in range(len(neighbors)) if n_neighbors[k] == min_n_neighbors]

            # break the tie if they might have the same number of neighbors
            _next = np.random.choice(_next)

    return y

    http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/EdgeRecombinationCrossoverOperator.aspx

    Algorithm Pseudo Code:

    1. X = the first node from a random parent.

    2. While the CHILD chromo isn't full, Loop:
        - Append X to CHILD
        - Remove X from Neighbor Lists

        if X's neighbor list is empty:
           - Xp = random node not already in CHILD
        else
           - Determine neighbor of X that has fewest neighbors
           - If there is a tie, randomly choose 1
           - Xp = chosen node
        X = Xp
     
pymoo/operators/crossover/erx.py