>     Map Preprocessing
>     =================
>


Differential Heuristics for A\*
-------------------------------

While researching further, I came upon some hints of a concept called 
"differential heuristics".
I tried to search further for this:

* 
https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html#approximate-heuristics
* Slide 44: 
https://www.slideshare.net/StavrosVassos/interactive-objects-pathfindingpart3
* http://research.microsoft.com/pubs/154937/soda05.pdf <- this seems to be the 
original paper
* https://www.aaai.org/ocs/index.php/SOCS/SOCS11/paper/viewFile/4020/4340

In summary, differential heuristics involve an A\* `h(n)` function built from 
precomputed distances from multiple landmarks.
The primary advantage of differential heuristics is that they make A\* search 
fewer nodes than e.g. Manhattan distance.

Ideally, `h(n)` is the `distance(n, t)` where `t` is the destination.
With differential heuristics, `h(n)` is then the maximum of `abs(distance(n, l) 
- distance(t, l))` among all landmarks `l`, where `t` is the destination.
`distance(_, l)` for all landmarks is precomputed.

Now of course in LN we cannot use heuristics like Manhattan distance anyway.
But we can definitely use precomputed distances.

I proposed a `getroutequick` which uses precomputed distances from the source 
in order to guide an algorithm towards the source.
This is based on the observation that our source tends to be always a single 
location, our own node.

However, we may still want to acquire a route that does not arise from our own 
node.
For example, consider a variant of `permuteroute` that, if it cannot heal from 
the pivot to some postfix node within 3 hops, falls back to performing A\* from 
the pivot to the final destination.
Presumably, the pivot is nearer to the destination and we are more likely to 
quickly reach the destination from the pivot rather than the actual payment 
source.

Another example of creating a route not from our own node is generalized 
rebalancing.
Rebalancing transfers funds from one of our local channels to another of our 
local channels.
We can derive this path by finding a route from the counterparty of the source 
channel to the counterparty of the destination channel, exclude our own node 
from consideration in pathfinding.
Then we just append the destination channel and prepend the source channel.
(Admittedly a friend-of-friend limited subgraph like proposed by Rene will work 
almost as well and would still be much faster, but this can be a fallback in 
case we cannot find a rebalancing route when scanning the friend-of-friend.)

Suppose we treat our own node as the single landmark in a differential 
heuristic system.
When finding a route, the payee is actually the source and the payer (our own 
node) is the destination.
The distance from the destination (the payer, our own node) to the landmark 
(again, our own node) --- i.e. `distance(t, l)` --- is 0, so the 
`abs(distance(n, l) - distance(t, l))` becomes `abs(distance(n, l) - 0)` 
becomes `distance(n, l)`.
So differential heuristics is actually a generalization of the preprocessing I 
proposed earlier that enables us to use A\*, but only for routes arising from 
our own node.

Thus, we can use this same preprocessed stored cost data of 
total-distance-from-our-own-node, not only to implement a `getroutequick` that 
works only for routes where our own node is one end of the route, but also for 
a `getroutequick` that can arise from any node.
The speed benefit is much much greater for routes where we are one end of the 
route, but we still get the benefit of using A\* if neither end of the 
requested route is not our own node.

As we would still want to store the preprocessed 
total-distance-from-our-own-node anyway to implement a `getroutequick` that 
uses A\* on an almost-exact heuristic, it means that we can implement a 
`getroutequick` from any node without increasing our memory usage, and with a 
relatively small tweak to the code.
Specifically, we need to look up `distance(t, l)` where `t` is the start of the 
route, and to compute the heuristic, subtract this from `distance(n, l)` and 
get the absolute value.
If the start of the route is our own node (which is the landmark `l`) then that 
distance is 0 and we automatically fall back to the A\* variant that uses an 
almost-exact heuristic to reach our own node.

Further landmarks beyond our own node can be selected (preferably distant from 
our own node) to improve the speed of searching in the case where we need to 
find from an arbitrary node, at the cost of increasing the memory space needed.

_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to