In practice, instead of modifying the search algorithm, we want to modify the graph (so we don’t have to re-invent the wheel).

This means that when we have a graph-traversal problem such as searching for a cheapest path, we want to build in the constraints into our graph by layering it. The edges between layers then represent state transitions.

Idea

Let’s look at an example. We are looking at a direct graph with non-negative edge-weights. Instead of a normal traversal, we are also allowed to cheat, up to times. Cheating means setting the weight of an edge to .

The idea is to create different layers in our graph, each representing having cheated times where . Each layer is connected normally, with non-modified edge-weights. There is also an edge of weight from every vertex to it’s successor in the next layer .

To cheat, you can use a downwards edge that links a graph with cheats to one with cheats. Because there are no upwards edges, you cannot “un-cheat”.

To find the shortest path, we can apply Dijkstra’s to this graph. We then take the minimum over the distances to all for . We could also link all edges together with cost instead of looping over the target vertices.

Formalising

To define the vertices:

  1. Use a direct product between the set of vertices and our cheats: .
  2. Use super- or subscript:

This new vertex set has size .

To define the edges: We can either use our set notation from before to create edges from: .

Or we define and by : And our edges from one layer to the next with cost : The first set of edges represents normal edge-traversal in , the second set represents cheating, and the final set ensures that there is always a path from to in if there is a path from to in .