Longest/shortest path algorithms

test

Algorithms to facilitate longest (and shortest) path algorithms. Path cost is calculated by either summing or multiplying edge weights.

Floyd-Warshall

Floyd-Warshall algorithm has the ability to calculate longest path (ie. most profitable trade) calculations, albeit at the expensive cost of $O(n^3)$.

For multiplication based weights, we make use of the fact that product maximisation is equivalent to maximisation of log of weights, as per: $x*y = 2^{log2(x) + log2(y)}$.

For longest paths, weights have been multiplied by $-1$ and hence reused in shortest path algorithm.

NOTE: Floyd-Warshall can detect negative path cycles (ie. infinite arbitrage opportunities), which cause the latest price update to be ignored. Potential TBD - remove offending edge to remove negative cycles...

Sample usage of Floyd-Warshall calculator. All prices are in $10^{12}$, including self references, eg. cost of BNB -> BNB = $10^{12}$

```rust use bestpath::prelude::*; use bestpath::prelude::floyd_warshall::calculator::FloydWarshallCalculator;

let ingraph = &[ ( ProviderPair { pair: Pair { source: "BNB".toowned(), target: "USDT".toowned() }, provider: "CRYPTOCOMPARE".toowned() }, 364190000000000u128 ), ( ProviderPair { pair: Pair { source: "USDT".toowned(), target: "ETH".toowned() }, provider: "COINGECKO".toowned() }, 2745000000u128 ), ]; let resout = FloydWarshallCalculator::calcbestpaths(ingraph); let asnodes = resout.unwrap().intoiter().collect::ref = resout.asref().unwrap(); // multi-hop path path asserteq!( &PricePath { totalcost: 999701550000u128, steps: vec![ PathStep { pair: Pair { source: "BNB".toowned(), target: "USDT".toowned() }, provider: "CRYPTOCOMPARE".toowned(), cost: 364190000000000u128 }, PathStep { pair: Pair { source: "USDT".toowned(), target: "ETH".toowned() }, provider: "COINGECKO".toowned(), cost: 2745000000u128 } ] }, resref.get(&Pair { source: "BNB".toowned(), target: "ETH".toowned() }).unwrap() ); // 1 hop path, based on input ProviderPair asserteq!( &PricePath { totalcost: 364190000000000u128, steps: vec![ PathStep { pair: Pair { source: "BNB".toowned(), target: "USDT".toowned() }, provider: "CRYPTOCOMPARE".toowned(), cost: 364190000000000u128 } ] }, resref.get(&Pair { source: "BNB".toowned(), target: "USDT".toowned() }).unwrap() ); // path to self, note cost is still in scale 10^12 asserteq!( &PricePath { totalcost: 1000000000000u128, steps: vec![] }, resref.get(&Pair { source: "BNB".toowned(), target: "BNB".to_owned() }).unwrap() ); ```

Utility within a pallet

Best-path serves as a best trade finding mechanism for best-path-pallet.