I was thinking recently about a possible solution to find, in polynomial time, whether an undirected graph has a Hamiltonian path or not.
The main concept used as part of this implementation is based on an observation that I noticed while trying to find (i.e. on paper) a Hamiltonian path for several undirected graphs.
The steps could be defined as follows:
Read the adjacency matrix of the graph.
While the adjacency matrix is being read, a map (i.e. dictionary-based structure) will be created for all the nodes. Also, the starting node of the path will be selected while the adjacency matrix
is being read. These operations can be described as follows:
2.1. The map will store all the nodes from the graph, as a key - value structure.
Each entry in the map will be represented as: (key: node index, value: node class)
The node class will contain the following details about the node: node index, number of incident edges to it, and a flag to indicate if the current node has already been visited or not.
By taking into consideration that each entry in the map will contain just the value
corresponding to that node, it can be stated that any read access from the map for a given node
index will be constant (i.e. O(1)).
2.2. As part of reading the adjacency matrix and building the map at step 2.1., the starting node will also be retained. The starting node of the path will be represented by the node which has the minimum number of edges incident to it.
If multiple nodes exist in the graph with this property, then the node with the lowest index
number will be selected. In this context, we can assume that each node will have an index
associated to it, starting from zero: 0, 1, 2, etc.
The starting node identified at step 2.2. will be marked as visited.
The next operations will be followed for the remaining nodes. The loop will end either when the number of visited nodes is equal to the number of nodes from the graph, or when there hasn't been found an unvisited adjacent node for the current node.
Therefore, the next steps will be followed as part of this loop:
4.1. The first operation will be to find the next node to visit.
The next node to be visited will have to respect the following constraints:
4.2. If a next node hasn't been found, then the algorithm will end and indicate that no
Hamiltonian paths were found.
4.3. If a next node has been found, then this will represent the current node. It will be marked
as visited, and the number of visited nodes will be incremented.
If the number of visited nodes is equal to the number of nodes from the graph, then a Hamiltonian path has been found. Either way, a message will be displayed based on the outcome of the algorithm.
The implementation / tests are available on GitHub: https://github.com/george-cionca/hamiltonian-path
My main questions are:
As I understand it, your algorithm is a heuristic greedy algorithm. That is, the path starts at the vertex with the lowest degree, and the path continues toward the unvisited vertex with the lowest degree (or the one with the fewest edges to unvisited nodes).
This fails if the vertex with the lowest degree is not the correct vertex.
Consider, for example, a graph with a single vertex v1 that connects, through two edges, two large complete graphs. We then have vertex v1 that connects to, say, v2 and v7, and we have vertices {v2, v3, v4, v5, v6} and {v7, v8, v9, v10, v11}, with both sets fully connected.
A Hamiltonian path certainly exists, as we can cover one cluster, move to the other and clear that one. However, your algorithm will start at v1 and be unable to find the path.
It will not have escaped your notice that the hamiltonian path problem is NP-complete. As you present a polynomial-time algorithm to solve the problem, correctness would mean you would have proven P=NP. This is highly unlikely. When it seems like you have proven something famously unsolved and widely believed to be false, I recommend somewhat lowering your expectations, and looking for a mistake you might have made as opposed to looking for verification that the algorithm works. In this case, you might have looked at the implicit assumptions of the algorithm (such as the lowest degree vertex being a valid starting point) and tried to think of a counterexample for this intuition.