Graphs – Shortest Path Algorithms – Summary

Are following statements valid?

  1. Shortest Path in an undirected graph can be found using BFS. Is DFS an option here? If DFS is not an option, why.

  2. Dijkstra’s SPT works if there are no negative weights in a Digraph. This is because Dijkstra’s is a greedy algorithm. Once a vertex is removed from Indexed Priority Queue, it is not added back,even though a negative edge gives shortest path to that vertex later on. Dijkstra works even if cycles exist in digraph

  3. If a digraph doesn’t contain cycles, then Topological Sort Order SPT will give shortest path from a single vertex to all other vertices. In this approach negative weights in digraph will not affect the correctness of algorithm. This is because topological sort makes sure all the vertices are in the correct order despite having negative weights on some edges (but not all)

  4. If a digraph doesn’t contain negative edge cycle, but has cycles and some negative weight edges then Bellman Ford is correct algorithm to use to solve Shortest Path problem.

  5. What is a fundamental algorithm to solve shortest path problem in digraphs? BFS? I think DFS can work too, with a minor tweak to reset seen flag for a given vertex.

Approximation algorithm to visit all nodes in an undirected, weighted, complete graph, with shortest sum of edge weights

I’m looking for an algorithm that gives a smallest sum of ‘travel time’ within the following constraints:

  • a complete, connected, weighted graph,
  • vertices are defined in 3d euclidean space,
  • relatively low number of vertices (less than 500),
  • no limits on how many times a node may be visited,
  • a fixed starting vertex,
  • no requirement for which vertex to end at.

I’ve looked at minimum spanning tree algorithms, but those could create sub-optimal result, because they optimize for lowest summed edge weight.

I’m suspecting this may be a variant of the travelling salesman problem and thus NP-hard. For our use case however, a good approximation will be good enough.

find shortest path in the matrix for multiple objects

I have the implementation of A* search algorithm that allows to find the shortest path from start to goal.

The implementation looks like this

public class AStarShortestPathContext {      private Vertex[][] matrix;     private int rows, columns;     private int cost;     private PriorityQueue<Vertex> openList;     private Set<Vertex> closedSet;      public AStarShortestPathContext(int rows, int columns, int cost) {         this.rows = rows;         this.columns = columns;         this.cost = cost;          openList = new PriorityQueue<>(Comparator.comparingInt(Vertex::getF));         closedSet = new HashSet<>();     }      public List<Vertex> find(Vertex startVertex, Vertex goalVertex, boolean[][] blocked) {         refreshContext();          Vertex start = new Vertex(startVertex);         Vertex goal = new Vertex(goalVertex);          ComputationUtils.updateEuristic(matrix, goal);          openList.add(start);         while (!openList.isEmpty()) {             Vertex current = openList.poll();             closedSet.add(current);             if (current.equals(goal)) {                 return path(current);             } else {                 neighbours(current, blocked);             }         }          return Collections.emptyList();     }      /** Temporary solution **/     public void refreshContext() {         // do I really need to do that every search?         this.matrix = new Vertex[rows][];         for (int i = 0; i < rows; i++) {             this.matrix[i] = new Vertex[columns];             for (int j = 0; j < columns; j++) {                 matrix[i][j] =  new Vertex(i, j);             }         }          openList.clear();         closedSet.clear();     }      private void neighbours(Vertex current, boolean[][] blocked) {         int row = current.getRow();         int column = current.getColumn();          int lower = row + 1;         if (lower < rows && !blocked[lower][column]) {             checkAdjacentVertex(current, lower, column);         }          int left = column - 1;         if (left >= 0 && !blocked[row][left]) {             checkAdjacentVertex(current, row, left);         }          int right = column + 1;         if (right < columns && !blocked[row][right]) {             checkAdjacentVertex(current, row, right);         }          int upper = row - 1;         if (upper >= 0 && !blocked[upper][column]) {             checkAdjacentVertex(current, upper, column);         }     }      private void checkAdjacentVertex(Vertex current, int row, int column) {         Vertex adjacent = matrix[row][column];         if (!closedSet.contains(adjacent)) {             int g = ComputationUtils.g(current, cost);             if (!openList.contains(adjacent)) {                 updateVertex(adjacent, current, g, ComputationUtils.f(adjacent));                 openList.add(adjacent);             } else {                 if (g < adjacent.getG()) {                     updateVertex(adjacent, current, g, ComputationUtils.f(adjacent));                      // as no update operation by default we need to remove and add node again                     openList.remove(adjacent);                     openList.add(adjacent);                 }             }         }     }      // considering that I need only the last vertex I may need to adjust it     private List<Vertex> path(Vertex reachedGoal) {         List<Vertex> path = new ArrayList<>();         path.add(reachedGoal);          Vertex parent;         while ((parent = reachedGoal.getParent()) != null) {             path.add(0, parent);             reachedGoal = parent;         }         return path;     }      private void updateVertex(Vertex v, Vertex parent, int g, int f) {         v.setParent(parent);         v.setG(g);         v.setF(f); // order is important as F depends on G     }  } 

It supposed to work for multiple bots (threads) over the same table. To achieve that I created concurrent context class that looks like this

public class AStarShortestPathConcurrentContext implements IObservable<ChangeStateEvent> {     private AStarShortestPathContext searchContext;     private boolean[][] blocked;     private List<IObserver<ChangeStateEvent>> observers;      public AStarShortestPathConcurrentContext(int rows, int columns, int cost) {         searchContext = new AStarShortestPathContext(rows, columns, cost);         blocked = DataUtils.generateEmptyBoolMatrix(rows, columns);         observers = new ArrayList<>();     }      public synchronized Vertex next(Vertex startVertex, Vertex goalVertex, String identifier) {         List<Vertex> path = searchContext.find(startVertex, goalVertex, blocked);         // start vertex is 0, next vertex is 1         Vertex next = path.get(1);         updateBlockedTable(startVertex, next);          // basically notify Swing JTable to update values in cells and force rendering         notifyObserver(ChangeStateEvent             .builder()             .identifier(identifier)             .newState(NPCWalkState                 .builder()                 .row(next.getRow())                 .column(next.getColumn())                 .build())             .previousState(NPCWalkState                 .builder()                 .row(startVertex.getRow())                 .column(startVertex.getColumn())                 .build())             .build());         return next;     }      private void updateBlockedTable(Vertex startVertex, Vertex next) {         int blocked_row = next.getRow();         int blocked_column = next.getColumn();          int released_row = startVertex.getRow();         int released_column = startVertex.getColumn();          blocked[blocked_row][blocked_column] = true;         blocked[released_row][released_column] = false;     }      @Override     public void addObserver(IObserver<ChangeStateEvent> observer) {         observers.add(observer);     }      @Override     public void notifyObserver(ChangeStateEvent data) {         observers             .parallelStream()             .forEach(observer -> observer.receiveNotification(data));     } } 

And that class is used in the threads.

public class WalkableNPCThread implements Runnable {     private int speed;     private String objectId;     private AStarShortestPathConcurrentContext searchContext;     private Vertex startVertex;     private Vertex goalVertex;      public WalkableNPCThread(WalkableNPC npc, AStarShortestPathConcurrentContext searchContext) {         this.speed = npc.getSpeed();         this.searchContext = searchContext;         this.objectId = npc.getIdentifier();     }      public void configureWalk(int initialRow, int initialColumn, int goalRow, int goalColumn) {         startVertex = new Vertex(initialRow, initialColumn);         goalVertex = new Vertex(goalRow, goalColumn);     }      @Override     public void run() {         while (!startVertex.equals(goalVertex)) {             ThreadUtils.delaySeconds(speed);             Vertex nextStep = searchContext.next(startVertex, goalVertex, objectId);             startVertex = new Vertex(nextStep);         }     } } 

The table is the same for all threads, so I instantiate AStarShortestPathConcurrentContext only once and pass it as a constructor parameter to each thread. It seems to work fine.

What is bothering me is that method

public synchronized Vertex next(Vertex startVertex, Vertex goalVertex, String identifier) {     List<Vertex> path = searchContext.find(startVertex, goalVertex, blocked);     // start vertex is 0, next vertex is 1     Vertex next = path.get(1);     updateBlockedTable(startVertex, next);      // basically notify Swing JTable to update values in cells and force rendering     notifyObserver(ChangeStateEvent         .builder()         .identifier(identifier)         .newState(NPCWalkState             .builder()             .row(next.getRow())             .column(next.getColumn())             .build())         .previousState(NPCWalkState             .builder()             .row(startVertex.getRow())             .column(startVertex.getColumn())             .build())         .build());     return next; } 

I syncronize it in order to prevent updates of blocked field by other threads and also to prevent the update the AStarShortestPathContext when doing the search (I refresh it for each thread before the search).

I am not sure if I really need to block the whole method next. Is there a way to achieve the same better?

I was thinking for using lock for the whole method instead of synchronized but still it would block the whole method.

Shortest way to form a string out of subsequence of a string

The task

is taken from LeetCode

From any string, we can form a subsequence of that string by deleting some number of characters (possibly no deletions).

Given two strings source and target, return the minimum number of subsequences of source such that their concatenation equals target. If the task is impossible, return -1.

Example 1:

Input: source = "abc", target = "abcbc" Output: 2 // Explanation: The target "abcbc" can be formed by "abc" and "bc", which are subsequences of source "abc". 

Example 2:

Input: source = "abc", target = "acdbc" Output: -1 // Explanation: The target string cannot be constructed from the subsequences of source string due to the character "d" in target // string. 

Example 3:

Input: source = "xyz", target = "xzyxz" Output: 3 // Explanation: The target string can be constructed as follows "xz" + "y" + "xz". 

Note:

Both the source and target strings consist of only lowercase English letters from “a”-“z”. The lengths of source and target string are between 1 and 1000.

My solution

has time and space complexity of O(n) (I think…)

/**  * @param {string} source  * @param {string} target  * @return {number}  */ var shortestWay = function(source, target) {     const map = new Map();     for (let i = 0; i < source.length; i++) {         if (map.get(source[i])) {             const arr = map.get(source[i]);             arr.push(i);             map.set(source[i], arr);                     } else {             map.set(source[i], [i]);         }     }     let occurrences = 0;     for (let i = 0; i < target.length; i++) {         const indexes = map.get(target[i]);         if (indexes === void 0) return -1;         occurrences++;         let max = 0;         indexes.forEach(index => {             let j = 0;             let ignore = 0;             while(source[index + j + ignore] !== void 0) {                 if(target[i + j] !== source[index + j + ignore]) {                     ignore++                 } else {                     max = Math.max(max, j++);                 }             }         });         i += max;     }     return occurrences; }; 

calculating a shortest path in a table structure that changes in real time

I have a table that looks like this

enter image description here

In table NPC – are AI like characters that move from one point to another. Player – a character that is controlled by the user.

In any moment the player character might move to any cell of the table. But NPC has a particular goal cell that they should reach while moving. For example, blue NPC needs to read blue cell.

enter image description here

Other NPC are also moving. My goal is to write an algorithm that would allow NPC to reach the cell using the shortest path. As far as I understand it is a typical shortest path problem.

My question is – is there some algorithm that particularly optimized to handle such workflows, or any algorithms will suffice – just with recalculating the path after each move?

Shortest pathway across a snakes and ladders board (Update)

Earlier I posted a fairly inefficient recursive solution to the problem of getting across a snakes and ladders board in the smallest number of moves.

I have created a much faster solution to this using Dijkstra’s algorithm and I believe it is correct.

Each square on the board is linked to any square that is between 1-6 larger than it with a weight of one (equivalent of rolling a 1-6 on a dice). All snakes and ladders link squares with a weight of 1. The aim was to have the smallest total cost for the pathway between 1 and 100 (0 and 99 here as I have used list indexes).

This is the first time I have implemented Dijkstra’s algorithm and the first time I have used namedtuples. I am not sure if using namedtuples was appropriate, but it made it clearer in my head.

I think I have massively over-complicated bits of code especially within the for loop under the condition if edge.start == next_item:. I seem to be using list comprehensions far too much and I know this makes the solution slower than it could be. Please could someone help me work out better ways to access the variables in my queue of named-tuples.

"""Calculate the shortest path across a snakes and ladders board using Dijkstra's shortest path""" from collections import namedtuple  Edge = namedtuple("Edge", ("start", "end", "cost")) Stack = namedtuple("Stack", ("start", "pathcost", "totalcost"))   class Graph:     """Class generates graph and calculates shortest path"""     def __init__(self, edges):         """Generate edges in graph"""         self.edges = [Edge(*edge) for edge in edges]      def dijkstra_path(self, start, end):         """Function that calculates the shortest path"""         if start >= end or start < 0 or end > 99:             return -1         queue = sorted(             (                 Stack(edge.end, edge.cost, edge.cost)                 for edge in self.edges                 if edge.start == start             ),             key=lambda x: x[2],         )         while queue:             next_item, _, current_total = queue.pop(0)             if next_item == end:                 return current_total             for edge in self.edges:                 if edge.start == next_item:                     if edge.end in [item.start for item in queue]:                         current_cost = [                             item.totalcost for item in queue if item.start == edge.end                         ][0]                         if not current_cost < edge.cost + current_total:                             queue = [item for item in queue if item.start != edge.end]                             queue.append(                                 Stack(edge.end, edge.cost, edge.cost + current_total)                             )                     else:                         queue.append(                             Stack(edge.end, edge.cost, edge.cost + current_total)                         )             queue = sorted(queue, key=lambda x: x[2])   def build_graph():     """Chess Board"""     list_board = [[i, i + j, 1] for i in range(100) for j in range(1, 7)]     # Ladders     list_board.append([1, 37, 1])     list_board.append([19, 59, 1])     list_board.append([28, 63, 1])     list_board.append([55, 99, 1])     # Snakes     list_board.append([91, 13, 1])     list_board.append([86, 11, 1])     list_board.append([53, 2, 1])     list_board.append([41, 13, 1])     return list_board  if __name__ == "__main__":     GRAPH = Graph(build_graph())     FROM = 0     TO = 100     NUMBER_STEPS = GRAPH.dijkstra_path(FROM, TO)     if not NUMBER_STEPS == -1:         print(f"Can complete game in a minimum of {NUMBER_STEPS} rolls")     else:         print("Error. Make sure the starting point is between 0 and 99 and less than the end point",               "which itself must be than or equal to 99")  

Transition matrix for shortest path walk

Consider a directed, weighted graph $ G$ . Let $ s$ and $ t$ be two distinct vertices of $ G$ and consider a walker that starts at $ s$ and traverses a random shortest path from $ s$ to $ t$ , chosen uniformly at random from all shortest paths from $ s$ to $ t$ .

Question: What is the transition matrix $ P$ that characterises this “random walk” (specifically, choosing a random shortest path) that starts at $ s$ and ends at $ t$ ?

Intuitively, it seems clear that $ P$ is given by \begin{equation} P_{ij} = \frac{\omega_{ij}}{\sum_k \omega_{ik}}\,, \end{equation} where $ \omega_{ij}$ is the number of shortest paths from $ s$ to $ t$ that traverse the directed edge $ (i,j)$ .

To see this, consider the $ k$ shortest paths from $ s$ to $ t$ . If we let $ k$ walkers walk each of the $ k$ shortest paths, their empirical transition matrix is given by $ P$ .

However, this is not a rigorous proof. Can someone provide a rigorous proof or fill in the missing step(s)?

Shortest path in a incomplete graph

I know the Dijkstra algorithm to solve the “single source shortest path” problem in a graph. And I’ve seen people discuss solutions in a dynamic graph where edge/vertices are subject to change. Retrieving the shortest path of a dynamic graph

My question is a little different.

Given the entry node $ S$ , while the entire graph $ G(V, E)$ is unknown at the beginning. There’s a function public List<Edge> get(Node node) to figure out the outgoing weighted edges at each node. Also, there’s another function public boolean isExit(Node node) tells you when to stop if the node is an exit node.

The question is a lot like the shortest path finding problem in a maze, where you’re at the entry, you only know the next moves of the current node and past nodes, you’d like to find the exits (multiple) in the shortest path. In this analogy, we care more about how to find the “exit” quickly, rather than finding the global optimal shortest path.

I’m wondering if the normal Dijkstra algorithm (Greedy + Relaxation) still applies in the case.

Because we don’t know the full graph, the shortest path to a node might haven’t been explored yet, and exist in the unknown part. (That’s my biggest concern).

I hope my explanations are clear enough, thank you very much!

Shortest possible good codes?

Good codes (those with positive rate $ r=k/n$ and positive relative distance $ \delta=d/n$ ) will achieve capacity on $ BSC$ (binary symmetric channel) if the codes have higher rates than capacity where positive relative distance is seen. However this requires very long codes to drive the error to reasonably low value.

To achieve an error rate of $ e$ if capacity is $ C$ then what is the shortest good code that is possible over $ BSC$ as a function of $ e$ ? I am just looking for an upper bound and a lower bound.