I understand the travelling salesman problem. Suppose if I want to visit only selected cities and come back to start, how to do that?
Lets say my cost matrix is,
A B C D
A 0 1 2 1
B 1 0 1 2
C 2 1 0 1
D 1 2 1 0
If I want to visit all the cities and come back to A. My shortest path would be A->B->C->D and min distance would be 4.
Suppose lets say if I want to visit only B and D. How can I find the min distance?
This is modified travelling salesman problem? Can someone help me with doing brute force algo for this case?
You can run first Floyd-Warshall to compute the shortest paths between all pairs of nodes. See wikipedia article.
Once you have the condensed cost matrix you can eliminate all cities that you are not interested in. From there it's the standard traveling salesman.
Since traveling salesman is NP complete it doesn't matter for complexity that you run Floyd-Warshall before it.
If you want the complete directions (including detours through uninteresting cities to make the paths shorter you'll have to go back to the Floyd-Warshall and reconstruct the paths.
I don't have my code handy, but here's some suggestions and pseudocode to get you going:
I would solve this by storing a vector as well as your above distance matrix in memory. Something like:
struct Location{
bool visited;
bool mustVisit;
}
Vector<Location> locationVec;
Populate the vector with the locations in your problem, marking whether or not they have to be visited, and always setting visited to false. Then comes the fun part! You need to create permutations of the locationVec. I would do this recursively, something like:
void addLocation(int & curLength, int & maxLength, int & curDistance, Vector<Location> &locationVec, Location* lastVisited)
if(curLenth == maxLength){
//check if currentDistance is less than the previously generated best difference, if so
//replace it
lastVisited->visited=0;
return;
}
//Add the next location
for (int& i : locationVec){
//Check if the location has been visited, and if it must be visited.
//If so: mark as visited, point lastVisited to it, and break
//Also add from lastVisited to the new location to your curDistance
curLength++;
}
addLocation(curLength, maxLength, curDistance, locationVec, lastVisited);
return;
}
That should get you started. Remember to subtract from currentDist when you change visited from visited = 1 to visited = 0, because you're essentially "unvisiting" the city. You may need to keep track of lastlastvisited as well, depending on your exact implementation.
If you need to speed it up (and you probably will, traveling Salesman is very slow), look into Branch and Bound: http://en.wikipedia.org/wiki/Branch_and_bound
Related
I have the following task, but I have no idea how to do it?
Calculate (lexicographically) the shortest path from V1-node to the other nodes by means of Dijkstra. Please write the current Heaps and corresponding Pred-fields as well. Start with new Heap and pred-field before the ExtractMin-Call.
I got this result via Dijkstra, but how should I add it to the min-heap (tree)?
I found exactly this task in an old exam I use for learning algorithms. I wasn't sure how to solve it so I searched several books for any explanation on how the minheap works along with Dijkstra and didn't find any. Finally I figured it out. So I hope this helps to understand how to solve this problem.
Step 1: Draw the heap lexicographically: V1 -> root, and then the
other nodes from left to right. V1 has the value 0, all other nodes
inf.
Step 2: ExtractMin(): swap root (which has the lowest value)
with the very last node and cut it off.
Step 3: Relaxation: Update new values for the nodes, if value decreases. "What is the new value from start to X when
I walk via the node, I just extracted, respecting its predecessors? Is it less than the old value, then update."
Step 4: Update the predecessor field if there is a better path.
Step 5: Call Heapify(): Resort the heap, so that
the node with the lowest value becomes root.
Repeat Step 2 to 5 until there are no nodes left.
Let (x,p1,p2,...pn) denote that there is a directed edge from x to p1 (but not from p1 to x), a directed edge from x to p2, etc... and a directed edge from x to pn.
Suppose we have:
(a,b,c)
(b,d,c)
(c,d,e)
(f,e,h)
(g,f,h,i)
(i,j)
For simplicity, let's assume that the distances between all connected nodes are 1. Now there is no connection from a to g or vice versa, but we can have two people leave from a and g respectively and meet at a common point. We want to find the shortest sum of two paths that meet at a node such that one path begins at a and the other begins at g. A simple drawing of this directed graph will reveal that the answer are these two paths:
a->c->e
g->f->e
with a total distance of 4. How to write an algorithm that accepts a directed graph (as in the above) and two nodes (e.g. a and g in this case) and output this answer, which I suppose could be in the form std::make_pair({a,c,e}, {g,f,e})? I tried to adapt Dijkstra's Algorithm to do so but with no luck. I welcomes all ideas.
Edit: Above was a simplified version of the real problem. Here is the real problem, which I was reluctant to describe because an example graph would be too difficult to read. So I will describe it without an example graph.
Two points A and B are selected in a directed graph similar to the one above but larger. There is no connection from one point to the other, and neither is there a common point reachable from both A and B. However, we do know that there exist points (how many is not given) N1, N2, ... Nk such that there is a common point reachable from both A and N1, a common point reachable from both N1 and N2, ..., and a common point reachable from both Nk and B. We want to find these k+1 paths such that the total sum of these paths is minimum. That's the real problem.
You didn't adapt Dijkstra correctly. And you don't have to find dist(a,x) and dist(g,x) for every node x in every case.
In Dijkstra's algorithm, every node is considered Visited or Unvisited, and the search proceeds until the destination is Visited (or no further searching is possible).
In the variant, every node is Unvisited, Visited-By-A, Visited-By-B, or Visited-By-Both. When a node becomes Visited-By-Both, the sum of the paths to it is a limit on the search; the code will keep track of the smallest sum yet found, and terminate the search when the shortest path still being explored is longer than this sum.
I believe this search is O(V logV) in the worst case.
EDIT: The "real" problem.
We have A and B, and we are searching for {N}, {x} that minimizes
(|A, x1| + |N1, x1|) + (|N1, x2| + |N2, x2|) + (|N2, x3| + |N3, x3|)+ ... + (|Nk, xk| + |Nk, B|)
where |x,y| is the length of the shortest path from x to y.
Now consider a new graph, made by adding reverse edges to G: for every edge x->y in G, we add y->x (with the same weight, but all weights are 1 for our purposes) BUT we do not add backward edges leading to A. Then we REMOVE forward edges from B. Now find the shortest path on this new graph from A to B.
This path begins with a forward edge from A, ends with a backward edge to B, and is the shortest such path. Along the path, there must be nodes which the path enters on a forward edge and leaves along a backward edge; we label these xi. And likewise, there must be nodes which the path enters on a backward edge and leaves along a forward edge; we label these Ni. (There must be at least one N, because x1 cannot be xk, because we assume that there is no point forward-reachable from both A and B.)
If we break the path into all-forward and all-backward legs, we get
A-->x1, x1<--N1, N1-->x2, x2<--N2, N2-->x3, ..., xk<--Nk, Nk-->B
The length of this path is
|A,x1| + |N1, x1| + |N1,x2| + |N2,x2| + |N2,x3| + ... + |Nk,xk| + |Nk,B|, which is minimal for this choice of A,B.
Therefore these are the paths we're looking for (and they can be found by a simple O(V) transformation of the graph and a Dijkstra search (O(VlogV))).
In my C++ course we have been working on graphs for a while, and there's a certain question that I've been stuck on for quite some time. The teacher gave us a program that created a graph of integers and then was able to find the shortest path between two integers in the graph. Our job was to adapt this to work for strings (specifically, find the shortest path only jumping to words that have 1 different letter than the previous word e.g bears -> beard).
Here is a sample of what I would expect my program to do:
Given the list [board, beard, bears, brand, boars, bland, blank]
it would create an edge matrix that resembled this:
board | beard boars
beard | board bears
bears | beard boars
brand | bland
boars | board bears
bland | brand blank
blank | bland
And then if asked to find the distance between board & bears it would output:
board->beard->bears
The way I adapted my program is that it creates a graph of a struct named 'node' which contains a number and a word. I use the number to compare the order within one vector to other variables, and the word to create the path. My adapted program successfully creates the graph from data in a text file and connects all words that have a 1 letter difference, however, when I run my function to find the shortest distance it bypasses my edges and simply print out that the start word and end word are a distance of 1 apart.
I will post my full, compile-able program below and explain what I know about the problem.
Here is a link to two pastebin links (I do not have a high enough reputation yet to post more than two links so I must combine them) The first is my full program, I have adapted it to use a set of words that I know are a word distance of 1 apart rather than a text file.
http://pastebin.com/W7HRZG2v
This second link is a download of the code my teacher gave (in case you wish to see a working version of the program)
I've narrowed the problem down to how I'm filling the vector "parents". Somehow it isn't generating properly and is creating an issue when the program tries to retrieve a path from it.
Here is a link to a photo (reputation not high enough to post images yet) comparing what the parents vector looks like in my teacher's "healthy" program (find distance between 2 & 5) to the parents vector in my program:
http://puu.sh/95zQI/26e9b83b9a.png
Notice how in my teacher's, 2 and 4, both integers used in the path, are present in the parents vector and called on to create it.
Notice how in mine the only word present in the parents vector is the beginning word, and hence it is the only word available to call on. However when comparing the way my teacher filled parents with the way I do, there are no differences I can see, aside from the fact that my parents is a string so I am entering a word instead of a number:
(my adapted version is on the left, teacher's is on the right)
if (distanceNodes[edgeNum] > distanceNodes[currNum] + 1) | if (distanceNodes[edge] > distanceNodes[curr] + 1)
{ | {
distanceNodes[edgeNum] = distanceNodes[currNum] + 1; | distanceNodes[edge] = distanceNodes[curr] + 1;
parents[edgeNum] = curr->word; | parents[edge] = curr;
} | }
If someone more proficient in graph application could look at this and assist me I would be extremely grateful. I've been stuck on this problem for over a week and the only tip my teacher will give me is that I should compare my program to his line by line; I did that and I still can't find the problem, I'm about ready to give up.
If you can help me, thank you very much,
Tristan
Here:
node * one = createNewNode(1, "board");
...
node * three = createNewNode(3, "bears");
...
insertEdge(&g, one, three);
The program correctly finds the edge you put there.
More generally, you must learn to step through your code and see what's happening.
And don't use global variables if you can help it.
EDIT:
I had some free time, so here's another problem:
int currNum = start->num;
while (! inTree[currNum])
{
...
parents[edgeNum] = curr->word;
...
}
You iterate by number, but you look things up by a pointer which you never update.
I'm sure there are other problems. The bottom line is that you're not checking things. For some reason, testing, which real coders do all the time, is never taught in programming courses.
Let me start off with saying that I have very basic knowledge of nodes and graphs.
My goal is to make a solver for a maze which is stored as an array. I know exactly how to implement the algorithm for solving (I'm actually implementing a couple of them) but what my problem is, is that I am very confused on how to implement the nodes that the solver will use in each empty cell.
Here is an example array:
char maze[5][9] =
"#########",
"# # #",
"# ## ## #",
"# # #",
"#########"
My solver starts at the top left and the solution (exit) is at the bottom right.
I've read up on how nodes work and how graphs are implemented, so here is how I think I need to make this:
Starting point will become a node
Each node will have as property the column and the row number
Each node will also have as property the visited state
Visited state can be visited, visited and leads to dead end, not visited
Every time a node gets visited, every directly adjacent, empty and not visited cell becomes the visited node's child
Every visited node gets put on top of the solutionPath stack (and marked on the map as '*')
Every node that led to a dead end is removed from the stack (and marked on the map as '~')
Example of finished maze:
"#########",
"#*~#****#",
"#*##*##*#",
"#****~#*#",
"#########"
Basically my question is, am I doing something really stupid here with my way of thinking (since I am really inexperienced with nodes) and if it is could you please explain to me why? Also if possible provide me other websites to check which implement examples of graphs on real world applications so I can get a better grasp of it.
The answer really depends on what you find most important in the problem. If you're searching for efficiency and speed - you're adding way too many nodes. There's no need for so many.
The efficient method
Your solver only needs nodes at the start and end of the path, and at every possible corner on the map. Like this:
"#########",
"#oo#o o#",
"# ## ## #",
"#o oo#o#",
"#########"
There's no real need to test the other places on the map - you'll either HAVE TO walk thru them, or won't have need to even bother testing.
If it helps you - I got a template digraph class that I designed for simple graph representation. It's not very well written, but it's perfect for showing the possible solution.
#include <set>
#include <map>
template <class _nodeType, class _edgeType>
class digraph
{
public:
set<_nodeType> _nodes;
map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
I use this class to find a path in a tower defence game using the Dijkstra's algorithm. The representation should be sufficient for any other algorithm tho.
Nodes can be of any given type - you'll probably end up using pair<unsigned int, unsigned int>. The _edges connect two _nodes by their position in the set.
The easy to code method
On the other hand - if you're looking for an easy to implement method - you just need to treat every free space in the array as a possible node. And if that's what you're looking for - there's no need for designing a graph, because the array represents the problem in a perfect way.
You don't need dedicated classes to solve it this way.
bool myMap[9][5]; //the array containing the map info. 0 = impassable, 1 = passable
vector<pair<int,int>> route; //the way you need to go
pair<int,int> start = pair<int,int>(1,1); //The route starts at (1,1)
pair<int,int> end = pair<int,int>(7,3); //The road ends at (7,3)
route = findWay(myMap,start,end); //Finding the way with the algorithm you code
Where findWay has a prototype of vector<pair<int,int>> findWay(int[][] map, pair<int,int> begin, pair<int,int> end), and implements the algorithm you desire. Inside the function you'll probably need another two dimensional array of type bool, that indicates which places were tested.
When the algorithm finds a route, you usually have to read it in reverse, but I guess it depends on the algorithm.
In your particular example, myMap would contain:
bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,1,1,0,
0,1,0,0,1,0,0,1,0,
0,1,1,1,1,1,0,1,0,
0,0,0,0,0,0,0,0,0};
And findWay would return a vector containing (1,1),(1,2),(1,3),(2,3),(3,3),(4,3),(4,2),(4,1),(5,1),(6,1),(7,1),(7,2),(7,3)
I'm a real speed freak if it gets to algorithms, and in the plugins I made for a game.
The speed is.. a bit.. not satisfying. Especially while driving around with a car and you do not follow your path, the path has to be recalculated.. and it takes some time, So the in-game GPS is stacking up many "wrong way" signals (and stacking up the signals means more calculations afterward, for each wrong way move) because I want a fast, live-gps system which updates constantly.
I changed the old algorithm (some simple dijkstra implementation) to boost::dijkstra's to calculate a path from node A to node B
(total node list is around ~15k nodes with ~40k connections, for curious people here is the map: http://gz.pxf24.pl/downloads/prv2.jpg (12 MB), edges in the red lines are the nodes),
but it didn't really increase in speed. (At least not noticeably, maybe 50 ms).
The information that is stored in the Node array is:
The ID of the Node,
The position of the node,
All the connections to the node (and which way it is connected to the other nodes, TO, FROM, or BOTH)
Distance to the connected nodes.
I'm curious if anybody knows some faster alternatives in C/C++?
Any suggestions (+ code examples?) are appreciated!
If anyone is interested in the project, here it is (source+binaries):
https://gpb.googlecode.com/files/RouteConnector_177.zip
In this video you can see what the gps-system is like:
http://www.youtu.be/xsIhArstyU8
as you can see the red route is updating slowly (well, for us - gamers - it is slow).
( ByTheWay: the gaps between the red lines have been fixed a long time ago :p )
Since this is a GPS, it must have a fixed destination. Instead of computing the path from your current node to the destination each time you change the current node, you can instead find the shortest paths from your destination to all the nodes: just run Dijkstra once starting from the destination. This will take about as long as an update takes right now.
Then, in each node, keep prev = the node previous to this on the shortest path to this node (from your destination). You update this as you compute the shortest paths. Or you can use a prev[] array outside of the nodes - basically whatever method you are using to reconstruct the path now should still work.
When moving your car, your path is given by currentNode.prev -> currentNode.prev.prev -> ....
This will solve the update lag and keep your path optimal, but you'll still have a slight lag when entering your destination.
You should consider this approach even if you plan on using A* or other heuristics that do not always give the optimal answer, at least if you still get lag with those approaches.
For example, if you have this graph:
1 - 2 cost 3
1 - 3 cost 4
2 - 4 cost 1
3 - 4 cost 2
3 - 5 cost 5
The prev array would look like this (computed when you compute the distances d[]):
1 2 3 4 5
prev = 1 1 1 2 3
Meaning:
shortest path FROM TO
1 2 = prev[2], 2 = 1, 3
1 3 = prev[3], 3 = 1, 3
1 4 = prev[ prev[4] ], prev[4], 4 = 1, 2, 4 (fill in right to left)
1 5 = prev[ prev[5] ], prev[5], 5 = 1, 3, 5
etc.
To make the start instant, you can cheat in the following way.
Have a fairly small set of "major thoroughfare nodes". For each node define its "neighborhood" (all nodes within a certain distance). Store the shortest routes from every major thoroughfare node to every other one. Store the shortest routes to/from each node to its major thoroughfares.
If the two nodes are in the same neighborhood you can calculate the best answer on the fly. Else consider only routes of the form, "here to major thoroughfare node near me to major thoroughfare near it to it". Since you've already precalculated those, and have a limited number of combinations, you should very quickly be able to calculate a route on the fly.
Then the challenge becomes picking a set of major thoroughfare nodes. It should be a fairly small set of nodes that most good routes should go through - so pick a node every so often along major streets. A list of a couple of hundred should be more than good enough for your map.