4

So, if i have an Directed Acyclic Graph where the cost of each edge either 0 or more than 0, if its more than 0 it will have a negative-weight (So you can by it for 5$ and it will shorten your way by -20 for example).

I know that we can easily find a shortest/cheapest way in a DAG, but what if we have limited money?

So imagine the next situation:

dag

We have 8 money.The algorithm would find the shortest path which is -10+-3= -13, but it would cost 12 but we only have 8 money, so its not an option. The ideal path would be -10+0 which only costs 7 money. Is there an algorithm which i can use to solve this problem?

uraimo
  • 19,081
  • 8
  • 48
  • 55
Ryper
  • 338
  • 3
  • 15

3 Answers3

5

This problem is NP-Hard, with a reduction from Knapsack-Problem.

Short intuitive "proof": The idea is, create a vertex for each item - you can either "take it" or "not take it" by choosing the vertex with the cost or the "free" vertex.

Sketch:

enter image description here

In the above you can see, from the Knapsack Problem, create a graph, for each item, you can choose to take it - and pay the cost and gain the "value", or ignore it.

More formally:

Given an instance of knapsack with weights=w1,w2,w3,...cn and cost=c1,c2,..,cn, with some maximal weight W, create a graph G=(V,E) with

V= { V_i,U_i,W_i | i=0,...n }
E= { (W_i,V_i+1,U_i+1 | i=0,...,n-1} U {(V_i,W_i+1), (U_i,W_i+1) | i=0,...,n-1 }

value(W_i,V_i+1) = c_i+1
money(W_i,V_i+1) = w_i+1
value(W_i,U_i+1) = 0
money(W_i,U_i+1) = 0
money(V_i,W_i+1) = cost(V_i,W_i+1) = money(U_i,W_i+1) = cost(U_i,W_i+1) = 0

The solution to this problem that uses at most W money, will be also the solution for knapsack with maximal capacity of W.


A possible pseudo polynomial solution could be (using Dynamic Programming technique):

D(start,0) = 0
D(v,x) = infinity     x < 0
D(v,x) = min { D(u,x-money(u,v)) + value(u,v) | for each edge (u,v) } U {infinity}

In the above D(v,x) is the minimal distance needed to travel from the start node to v, paying exactly x money.

Note that it can be done because it's a DAG, so you can calculate the values from first to last according to the graph's topological sort.

When done, you need to search all values of x from 0 to MAXIMAL_AMOUNT_OF_MONEY_ALLOWED to find the minimal value of D(target,x), and that's the answer.
Finding the actual cost is done by retracing back your steps, as done in other Dynamic Programming solutions.

The above run time is O(|V|*MAX_MONEY + |E|)

Community
  • 1
  • 1
amit
  • 175,853
  • 27
  • 231
  • 333
  • 1
    Looks good, but I couldn't understand the sentence fragment "- and path the cost, or ignore it, and take the "value" from it, with the cost you are willing to pay for it." Also it would help to mention that D(v, x) is the minimum distance you need to travel to get from the start to v if you initially have $x in your pocket. Finally I think it needs to be `D(u,x-money(u,v)) + value(u,v)` in the recurrence since the values (weights) are apparently negative. – j_random_hacker Jul 07 '15 at 12:27
  • @j_random_hacker Thanks for the feedback, editted. Feel free to clarify a bit more if you see it needed (since I need to take my son to physiotherapy and will be back only in a few hours). – amit Jul 07 '15 at 12:31
  • yes i'm pretty sure that i need to use a variation of the Knapsack-Problem, but i think your solution is way more complitcate to this problem, and i don't see where it would solve the next problem: So imagane a graph with 5 vertex, i only storing the edges beetwen the i and the i+1 vertex. http://i57.tinypic.com/30w1itk.jpg Here is the matrix, the rules are simple we can only choose one edge from A vertex to B , so we can only choose one edge from a coloumn. So what would the algorithm do if we had a weight limit( = Money) of 13 next comment: – Ryper Jul 07 '15 at 17:36
  • ([row][column]) (i am simplified the things with this matrix i think) 1) it would choose [0][1], [1][1], [3][1], [0][0] thats a total weight of 10 and the value would be 17, but we choosen more edges from one column which is not acceptable 2) it would choose [0][0],[2][1] what would be 11 weight, and the value would be 12, it is the correct But how would the algorithm know that it can only choose one from one column, i cant imagine this, any ideas? – Ryper Jul 07 '15 at 17:45
  • @Ryper This solution is pretty much a straight forward modification of knapsack to this problem. If you do agree it's a knapsack there is no simpler (efficient) solution that that. The algorithm never chooses more than one edge leading to each vertex, it chooses at most a single edge (or none if there is no feasible solution), that's what the min{..} is guaranteeing - chosing only a single edge. – amit Jul 07 '15 at 17:48
  • @amit what do you mean in choosing the "create a graph for each item"?? i think i understand know how knapsack works, i only need that – Ryper Jul 07 '15 at 19:20
  • @Ryper It's "Create a vertex for each item", typo. But note that this is NOT what you are looking for. The first part of the answer is explaining why the problem is NP-Hard, showing you can transform knapsack to your problem. You are looking for the second part of the answer, where the recursive formula is `D(v,x)` - this is how you solve your problem in pseudo-polynomial time. – amit Jul 07 '15 at 20:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82647/discussion-between-ryper-and-amit). – Ryper Jul 07 '15 at 20:53
0

Use flood algorithm. Rules:
In each visited node update an array of paths and their prices.
Release the array when the visited node is no more needed.
Always remove paths with price > money.
Start flood in the source node.
End flood in the target node when all incoming edges are flooded.
Follow flood using outgoing edges when all incoming edges are flooded.
At the end take the path with highest price in the target node.

Pavel Gatnar
  • 3,987
  • 2
  • 19
  • 29
0

Since your question is not about path-finding in general and only about finding a path within a certain cost, I will assume you have some algorithm for finding the shortest path already and will speak in general about how to modify it.

The simplest way would be to just ignore the paths which increase the cost beyond the amount you want to spend. In your path-finding algorithm, when you are adding an edge to a path, abandon that path if the sum cost is now too high. If it is reasonable to just skip it or mark it invalid some way in your code, do it, otherwise you could treat the sum weight for the path as infinity, then it will handle itself.

Assuming you have some function for checking the next edge along the path (and if you don't, or not in this format, then just adapt it to what you do have)...

// accepts the edge you are checking, max cost, and the sum weight and cost so far to this point
// returns float array {sum cost, sum weight), or infinity if cost is exceeded
void checkNextStep(Edge* edge, float maxCost, float* sumWeight, float* sumCost)
{
    if(*sumCost + edge->cost > maxCost)
    {
        *sumWeight = INFINITY;
        *sumCost += edge->cost;
    }
    *sumWeight += edge->weight;
    *sumCost += edge->cost;
}

Now that path will automatically be rejected if the cost goes above your threshold, because infinity will likely not be the shortest path.

If you end up getting a shortest path with weight infinity, then that means you do not have enough money to get to your target node at all, by any path. So you can use that as a check that you can't get there at all with your money system.

Loduwijk
  • 1,950
  • 1
  • 16
  • 28
  • This approach is sub-optimal (won't get you the best solution). You cannot modify shortest path to get an optimal answer to this problem, at least not simply, and assuming P!=NP – amit Jul 07 '15 at 17:17
  • This approach gives the question asker the solution that was asked for, which does mean you will get the best solution. The asker's definition of best solution was to return the shortest path that did not exceed a cost threshold. You cannot just say "You cannot..." without backing it up. What I provided will work, unless I am overlooking something. If there is an error in it, then please explain where the error is. From where I'm sitting, I'm seeing a perfectly good answer (possibly the best; that's arguable depending on how you like your answers formatted) that is being overlooked. – Loduwijk Jul 07 '15 at 21:01
  • I did back it up. I proved this problem is NP-Hard in my answer. That means there is no known polynomial solution to it, and most believe there is none. – amit Jul 07 '15 at 21:10
  • Here's another proof for you: Asker stated that the shortest path can be found (assumes pre-existing code, or at least available algorithm). Asker stated that there is a secondary cost (money), and paths which exceed a threshold for the secondary cost should be rejected (no optimization necessary here, just reject certain paths). I supplied a recommendation for altering the asker's code (which may or may not exist; that part was not specified that I recall), and as far as I can tell _it works_. QED. – Loduwijk Jul 07 '15 at 21:43
  • I just realized something. When you say "sub-optimal" and "best solution," do you mean that my suggestion will not return the answer that the asker wants, or do you mean that it does not provide the best solution in that it is not the best algorithm solution to use to find the answer that the asker wants? The statement could be taken either way, and they are different, so I might not be talking about the same thing as you. – Loduwijk Jul 07 '15 at 21:55
  • I mean it might return a path longer than the shortest one that can be achieved with a given budget. Do you know what NP-Hard problems are? (It's ok if you don't but you should read about them before dismissing an argument that involves them) – amit Jul 07 '15 at 21:57
  • The "proof" in your comment does not work, because his "shortest path" is working on a set of edges without restriction. Adding the restriction is making the whole shortst-path algorithm wrong. The problem is, you might have 10$, and you now see a shortcut that costs 9$. With your approach, you might take it - but that will disable all shortcuts in the future that costs 2$ each, so if each shortcut is giving you the same value (let's say -1), you'd prefer taking 5*2$ shortcuts rather than 1*9$. But the greedy approach will take the 9$ shortcut. – amit Jul 07 '15 at 22:06
  • I remember going over it in college, so I know the basic idea yes. As for your last comment, the way I am reading the asker's question, I do not see that as a requirement. If you want to make such optimizations, then that's good. I do not think that was part of the question as stated, but I suppose you could read it that way. I read "I have the shortest path, but want it ignored if above cost," not "I want the best path with money considered." However, I do not deny the point you are making, so it's moot, I'm wasting our time and bowing out now. – Loduwijk Jul 07 '15 at 22:19