Triangle max sum using depth first search - algorithm

I have the classic problem with a triangle and need to get the max path. I am allowed to move from (i,j) to (i,j-1), (i, j+1), (i+1,j)
Example input:
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
and the maximum path is the sum of (1) + (2 + 3) + (4 + 3 + 2 + 1) + (2 + 3 + 4 + 5 + 6 + 7). I am not allowed to move on a node twice
I know how to solve this using DP but this problem has been shown to us at the Artificial Intelligence class and the solution it needs is using DFS/GBFS
How is it possible to solve this problem using DFS? Only recursive came to my mind but it's not near close to DFS.
I am representing the input as a graph, so for the following
1
2 3 4
5 6 7 8 9
I have the following graph
1 -> {3}, 3 -> {2, 4, 7}, 4 -> {3, 8} etc
I was thinking of doing a recursive function, MaxSum(node) and start from node 1 and do something like that
return Max(MaxSum(neighbour_1), MaxSum(neighbour_2), ..., MaxSum(neighbour_n)) + node
where each neighbour_i is unvisited neighbour
But where does the DFS part come in?
Also, how could I solve this problem using GBFS?
I am not interested in code or something, only algorithmic explanations

But where does the DFS part come in?
The graph you have is acyclic and the problem you are trying to solve is longest path problem (after transforming the node weights to edge weights). The general solution requires you to use DFS to find a topological order but in your case you know an easy topogical order, the one just like in your example:
1
2 3 4
5 6 7 8 9
You use this order for second part - the DP solution. So in a way, you are skipping the DFS part.
You could explicitly run DFS for the first path and it could give a different topological order (depending on how you traverse the edges) but it's just a waste of effort.
Also for the second part, instead of performing the DP you could use BFS level by level to update the neighbors of the elements in the current level. But again it doesn't make much sense since using DP would give you the same results and would even be cheaper.

Related

Issue with min cost path

I was solving min cost path problem through dynamic approach but suddenly I realised that greedy approach is also working.
I applied greedy like this :
choose the min of bottom, right and diagonal cost and move in the min cost path.
1 2 3
4 8 2
1 5 3
where numbers are cost which will be added to the required cost if we include that point.
path from 1 to 3 is 12 through greedy is 8.
If my approach doesn't follow all examples, the what is that example?
How about a map such as:
1 1 1
2 10 10
1 1 1
Your greedy approach will end up taking 1+1+1+10+1, instead of 1+2+1+1
Greedy algorithms can be 'beaten' by giving them a long meandering path with several small steps:
2 2 e
2 ∞ 0
s 3 0
In this case, going from s to e will require either
The greedy solution: See that 2 is smaller and slog through several three 2's for a total cost of 6
A dynamic solution: See that after the three there is an easy path for a total cost of 3.
Also, I'd take a look at how your two algorithms define length. The optimal path is actually 1 -> 4 -> 2 -> 3 which has a cost of 10. If your dynamic solution isn't returning that, it may indicate that something else is going on.

Is there better way than a Dijkstra algorithm for finding fastest path that do not exceed specified cost

I'm having a problem with finding fastest path that do not exceed specified cost.
There's similar question to this one, however there's a big difference between them.
Here, the only records that can appear in the data are the ones, that lead from a lower point to a higher point (eg. 1 -> 3 might appear but 3 -> 1 might not) (see below). Without knowing that, I'd use Dijkstra. That additional information, might let it do in a time faster than Dijkstras algorithm.
What do you think about it?
Let's say I've got specified maximum cost, and 4 records.
// specified cost
10
// end point
5
//(start point) (finish point) (time) (cost)
2 5 50 5
3 5 20 9
1 2 30 5
1 3 30 7
// all the records lead from a lower to a higher point no.
I have to decide, whether It's possible to get from point (1) to (5) (its impossible when theres no path that costs <= than we've got or when theres no connection between 1-5) and if so, what would be the fastest way to get in there.
The output for such data would be:
80 // fastest time
3 1 // number of points that (1 -> 2) -> (2 -> 5)
Keep in mind, that if there's a record saying you can move 1->2
1 2 30 5
It doesnt allow you to move 2<-1.
For each node at depth n, the minimum cost of path to it is n/2 * (minimal first edge at the path + minimal edge connecting to the node) - sum of arithmetic series. If this computation exceeds the required maximum, no need to check the nodes that follow. Cut these nodes off and apply Dijkstra on the rest.

Finding the maximum sum from a matrix

There is a matrix with m rows and n columns. The task is to find the maximum sum choosing a single element from each row and column. I came up with a solution, which finds the maximum from the whole matrix and then sets that row and column as zero adds it to the sum and proceeds with finding the next max. This repeats m times.
But the problem with this approach was if there is repetitive elements. I'll try to explain it with an example. Here is the matrix..
3 6 5 3
9 4 9 2
8 1 4 3
4 7 2 5
Now, if I follow the above method.. sum will be 9 + 7 + 5 + 3 whereas it should be 9 + 8 + 7 + 3. How to solve this problem.. I'm stuck
Update: The columns are cost of seats which can be assigned to a person and the rows are number of persons. We want to assign them in such a way, so that we get the max cost.
Isn't this just http://en.wikipedia.org/wiki/Assignment_problem, typically solved by http://en.wikipedia.org/wiki/Hungarian_algorithm? Obviously, you want a maximum rather than a minimum, but surely you can achieve that by maximising for costs that are -(the real cost) or, if you are worried about -ve costs, (Max cost in matrix) - (real cost).
Your algorithm is wrong - consider a slight change in the matrix, where the second 9 is 8:
3 6 5 3
9 4 8 2
8 1 4 3
4 7 2 5
Then your algorithm has no problem in finding 9, 7, 5, 3 (no duplicates), but the correct answer is still 8, 8, 7, 3.
You can brute force it, by trying all combinations. One good way to put that into code is to use a recursive function, that solves the problem for any matrix:
In it you would iterate through say the first row and call the function for the submatrix obtained by deleting the correspondent row and column. Then you would pick the highest sum.
That, of course, will be too slow for large matrixes. The complexity is O(N!).

Finding good heuristic for A* search

I'm trying to find the optimal solution for a little puzzle game called Twiddle (an applet with the game can be found here). The game has a 3x3 matrix with the number from 1 to 9. The goal is to bring the numbers in the correct order using the minimum amount of moves. In each move you can rotate a 2x2 square either clockwise or counterclockwise.
I.e. if you have this state
6 3 9
8 7 5
1 2 4
and you rotate the upper left 2x2 square clockwise you get
8 6 9
7 3 5
1 2 4
I'm using a A* search to find the optimal solution. My f() is simply the number of rotations needed. My heuristic function already leads to the optimal solution (if I modify it, see the notice a t the end) but I don't think it's the best one you can find. My current heuristic takes each corner, looks at the number at the corner and calculates the manhatten distance to the position this number will have in the solved state (which gives me the number of rotation needed to bring the number to this postion) and sums all these values. I.e. You take the above example:
6 3 9
8 7 5
1 2 4
and this end state
1 2 3
4 5 6
7 8 9
then the heuristic does the following
6 is currently at index 0 and should by at index 5: 3 rotations needed
9 is currently at index 2 and should by at index 8: 2 rotations needed
1 is currently at index 6 and should by at index 0: 2 rotations needed
4 is currently at index 8 and should by at index 3: 3 rotations needed
h = 3 + 2 + 2 + 3 = 10
Additionally, if h is 0, but the state is not completely ordered, than h = 1.
But there is the problem, that you rotate 4 elements at once. So there a rare cases where you can do two (ore more) of theses estimated rotations in one move. This means theses heuristic overestimates the distance to the solution.
My current workaround is, to simply excluded one of the corners from the calculation which solves this problem at least for my test-cases. I've done no research if really solves the problem or if this heuristic still overestimates in some edge-cases.
So my question is: What is the best heuristic you can come up with?
(Disclaimer: This is for a university project, so this is a bit of homework. But I'm free to use any resource if can come up with, so it's okay to ask you guys. Also I will credit Stackoverflow for helping me ;) )
Simplicity is often most effective. Consider the nine digits (in the rows-first order) as forming a single integer. The solution is represented by the smallest possible integer i(g) = 123456789. Hence I suggest the following heuristic h(s) = i(s) - i(g). For your example, h(s) = 639875124 - 123456789.
You can get an admissible (i.e., not overestimating) heuristic from your approach by taking all numbers into account, and dividing by 4 and rounding up to the next integer.
To improve the heuristic, you could look at pairs of numbers. If e.g. in the top left the numbers 1 and 2 are swapped, you need at least 3 rotations to fix them both up, which is a better value than 1+1 from considering them separately. In the end, you still need to divide by 4. You can pair up numbers arbitrarily, or even try all pairs and find the best division into pairs.
All elements should be taken into account when calculating distance, not just corner elements. Imagine that all corner elements 1, 3, 7, 9 are at their home, but all other are not.
It could be argued that those elements that are neighbors in the final state should tend to become closer during each step, so neighboring distance can also be part of heuristic, but probably with weaker influence than distance of elements to their final state.

Adding waypoints to A* graph search

I have the ability to calculate the best route between a start and end point using A*. Right now, I am including waypoints between my start and end points by applying A* to the pairs in all permutations of my points.
Example:
I want to get from point 1 to point 4. Additionally, I want to pass through points 2 and 3.
I calculate the permutations of (1, 2, 3, 4):
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1
Then, for each permutation, I calculate the A* route from the first to the second, then append it to the route from the second to the third, then the third to the fourth.
When I have this calculated for each permutation, I sort the routes by distance and return the shortest.
Obviously, this works but involves a lot of calculation and totally collapses when I have 6 waypoints (permutations of 8 items is 40320 :-))
Is there a better way to do this?
First of all, you should store all intermediate calculations. Once you calculated the route from 1 to 2, you should never recalculate it again, just look up in a table.
Second, if your graph is undirected, a route from 2 to 1 has exactly the same distance as a route from 1 to 2, so you should not recalculate it either.
And finally, in any case you will have an algorithm that is exponential to the number of points you need to pass. This is very similar to the traveling salesman problem, and it will be exactly this problem if you include all available points. The problem is NP-complete, i.e. it has complexity, exponential to the number of waypoints.
So if you have a lot of points that you must pass, exponential collapse is inevitable.
As a previous answer mentioned, this problem is the NP-complete Traveling Salesperson Problem.
There is a better method than the one you use. The state-of-the-art TSP solver is due to Georgia Tech's Concorde solver. If you can't simply use their freely available program in your own or use their API, I can describe the basic techniques they use.
To solve the TSP, they start with a greedy heuristic called the Lin-Kernighan heuristic to generate an upper bound. Then they use branch-and-cut on a mixed integer programming formulation of the TSP. This means they write a series of linear and integer constraints which, when solved, gives you the optimal path of the TSP. Their inner loop calls a linear programming solver such as Qsopt or Cplex to get a lower bound.
As I mentioned, this is the state-of-the-art so if you're looking for a better way to solve the TSP than what you're doing, here is the best. They can handle over 10,000 cities in a few seconds, especially on the symmmetric, planar TSP (which I suspect is the variant you're working on).
If the number of waypoints you need to eventually handle is small, say on the order of 10 to 15, then you may be able to do a branch-and-bound search using the minimum spanning tree heuristic. This is a textbook exercise in many introductory AI courses. More waypoints than that you will probably outlive the actual running time of the algorithm, and you will have to use Concorde instead.

Resources