Chapter 7. Move and Neighborhood Selection

7.1. Move and Neighborhood Introduction

7.1.1. What is a Move?

A Move is a change (or set of changes) from a solution A to a solution B. For example, the move below changes queen C from row 0 to row 2:

singleMoveNQueens04

The new solution is called a neighbor of the original solution, because it can be reached in a single Move. Although a single move can change multiple queens, the neighbors of a solution should always be a very small subset of all possible solutions. For example, on that original solution, these are all possible changeMoves:

possibleMovesNQueens04

If we ignore the 4 changeMoves that have no impact and are therefore not doable, we can see that number of moves is n * (n - 1) = 12. This is far less than the number of possible solutions, which is nn = 256. As the problem scales out, the number of possible moves increases far less than the number of possible solutions.

Yet, in 4 changeMoves or less we can reach any solution. For example we can reach a very different solution in 3 changeMoves:

sequentialMovesNQueens04
Note

There are many other types of moves besides changeMoves. Many move types are included out-of-the-box, but you can also implement custom moves.

A Move can affect multiple entities or even create/delete entities. But it must not change the problem facts.

All optimization algorithms use Moves to transition from one solution to a neighbor solution. Therefore, all the optimization algorithms are confronted with Move selection: the craft of creating and iterating moves efficiently and the art of finding the most promising subset of random moves to evaluate first.

7.1.2. What is a MoveSelector?

A MoveSelector's main function is to create an Iterator<Move> when needed. An optimization algorithm will iterate through a subset of those moves.

Here’s an example how to configure a changeMoveSelector for the optimization algorithm Local Search:

  <localSearch>
    <changeMoveSelector/>
    ...
  </localSearch>

Out of the box, this works and all properties of the changeMoveSelector are defaulted sensibly (unless that fails fast due to ambiguity). On the other hand, the configuration can be customized significantly for specific use cases. For example: you might want to configure a filter to discard pointless moves.

7.1.3. Subselecting of Entities, Values and Other Moves

To create a Move, a MoveSelector needs to select 1 or more planning entities and/or planning values to move. Just like MoveSelectors, EntitySelectors and ValueSelectors need to support a similar feature set (such as scalable just-in-time selection). Therefore, they all implement a common interface Selector and they are configured similarly.

A MoveSelector is often composed of EntitySelectors, ValueSelectors or even other MoveSelectors, which can be configured individually if desired:

    <unionMoveSelector>
      <changeMoveSelector>
        <entitySelector>
          ...
        </entitySelector>
        <valueSelector>
          ...
        </valueSelector>
        ...
      </changeMoveSelector>
      <swapMoveSelector>
        ...
      </swapMoveSelector>
    </unionMoveSelector>

Together, this structure forms a Selector tree:

selectorTree

The root of this tree is a MoveSelector which is injected into the optimization algorithm implementation to be (partially) iterated in every step.