Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pathfinding #192

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft

pathfinding #192

wants to merge 12 commits into from

Conversation

Vib-UX
Copy link
Contributor

@Vib-UX Vib-UX commented Aug 21, 2021

fixes #190

@Vib-UX Vib-UX changed the title Work in Progress pathfinding Aug 21, 2021
@codecov-commenter
Copy link

codecov-commenter commented Aug 21, 2021

Codecov Report

Merging #192 (698cb5a) into main (eacb603) will decrease coverage by 0.90%.
The diff coverage is 45.05%.

❗ Current head 698cb5a differs from pull request most recent head 96146da. Consider uploading reports for the commit 96146da to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##             main     #192      +/-   ##
==========================================
- Coverage   93.37%   92.47%   -0.91%     
==========================================
  Files         182      183       +1     
  Lines        4757     4848      +91     
  Branches      561      581      +20     
==========================================
+ Hits         4442     4483      +41     
- Misses        174      214      +40     
- Partials      141      151      +10     
Impacted Files Coverage Δ
packages/graph/lib/PriorityQueue.ts 34.00% <34.00%> (ø)
packages/graph/lib/graph.ts 73.01% <58.53%> (-26.99%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update eacb603...96146da. Read the comment docs.

Copy link
Member

@bmancini55 bmancini55 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

K its coming along nicely. Some nits surrounding coding style that we can go over. The biggest issues I see are:

  1. The construction of the adjacency list is only from node1 -> node2. The graph is a symmetric directed graph meaning each channel is two edges: node1->node2 and node2->node1.

  2. This would be facilitated by using the Node's channels property, which is a Map. If it helps you can create a secondary property on Node that returns a tuple containing the [Channel,ChannelSettings] for the Node's channel setting which would aid in point 1.

  3. Finding the min distance should ideally use a heap, but we can get to optimizations later.

@@ -7,6 +8,8 @@ import { Node } from "./node";
* Graph represents a
*/
export class Graph {
public nodes_list: string[] = [];
Copy link
Member

@bmancini55 bmancini55 Sep 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably don't need nodes_list. Can easily iterate over a Map type:

const map = new Map();
map.set(1, 'a');
map.set(2, 'b');
map.set(3, 'c');

// iterate over key-values since Map is an iterator
for(const [key, val] of map) {
   console.log(key, val);
}

// iterate over keys as an iterator
for(const key of map.keys()) {
   console.log(key);
}

// iterate over vals as an iterator
for(const val of map.values()) {
   console.log(val);
}

Lastly you can covert any iterator into an Array with Array.from:

console.log(Array.from(map));
console.log(Array.from(map.keys()));
console.log(Array.from(map.values()));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing will work with maps (;

@@ -7,6 +8,8 @@ import { Node } from "./node";
* Graph represents a
*/
export class Graph {
public nodes_list: string[] = [];
public adjacencyList = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for adjacency list. The Node type includes a Channels Map that contains all of the Channels the Node is a member of.

const str_id = dest.nodeId.toString("hex");

// Distances will store the base_fee required to traverse from the src
let distances = {},
Copy link
Member

@bmancini55 bmancini55 Sep 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Language nit: use maps over objects. Even though JS/TS allows object mutation, memory management is most effective when types remain static. As such the Set/Map types are better suited for that type of stuff.

@Vib-UX
Copy link
Contributor Author

Vib-UX commented Sep 9, 2021

K its coming along nicely. Some nits surrounding coding style that we can go over. The biggest issues I see are:

  1. The construction of the adjacency list is only from node1 -> node2. The graph is a symmetric directed graph meaning each channel is two edges: node1->node2 and node2->node1.
  2. This would be facilitated by using the Node's channels property, which is a Map. If it helps you can create a secondary property on Node that returns a tuple containing the [Channel,ChannelSettings] for the Node's channel setting which would aid in point 1.
  3. Finding the min distance should ideally use a heap, but we can get to optimizations later.

Yes, I made a mistake it should behave like an undirected graph. Nice Catch 😓

@bmancini55
Copy link
Member

Yes, I made a mistake it should behave like an undirected graph. Nice Catch sweat

Conceptually yes, channels are similar to undirected/symmetric directed graph. So both directions or every node pair where a channel exists are theoretically possible and need to be considered. For routing purposes that symmetry may break when:

  1. A channel only has settings on one side (meaning it only received a channel_update from one of the nodes)
  2. A node may disable it's side of the channel in the update message
  3. The min/max settings may prevent an HTLC from being routeable.

@bmancini55
Copy link
Member

Also just for edification, node1/node2 in the channel are just the lexicographical ordering of the identifiers. When I first starting learning this stuff I thought node1 was the opener or had some larger meaning. But it's just the node with the lower ordered nodeId.

@Vib-UX
Copy link
Contributor Author

Vib-UX commented Sep 9, 2021

Also just for edification, node1/node2 in the channel are just the lexicographical ordering of the identifiers. When I first starting learning this stuff I thought node1 was the opener or had some larger meaning. But it's just the node with the lower ordered nodeId.

That's really insightful 💡 , I actually thought that node1 is probably the one who opened the channel.

@Vib-UX
Copy link
Contributor Author

Vib-UX commented Sep 10, 2021

K its coming along nicely. Some nits surrounding coding style that we can go over. The biggest issues I see are:

  1. The construction of the adjacency list is only from node1 -> node2. The graph is a symmetric directed graph meaning each channel is two edges: node1->node2 and node2->node1.
  2. This would be facilitated by using the Node's channels property, which is a Map. If it helps you can create a secondary property on Node that returns a tuple containing the [Channel,ChannelSettings] for the Node's channel setting which would aid in point 1.
  3. Finding the min distance should ideally use a heap, but we can get to optimizations later.

For Heap optimization, I found this package related to priority queues we can import that and workaround with it or should I build it from scratch?

@bmancini55
Copy link
Member

For Heap optimization, I found this package related to priority queues we can import that and workaround with it or should I build it from scratch?

* https://www.npmjs.com/package/priorityqueuejs

Scratch, we try to avoid external packages where possible.

We'll most likely put it in the Core package but feel free to add it to this project first so we don't have to deal with deps issues while prototyping.

@Vib-UX
Copy link
Contributor Author

Vib-UX commented Sep 10, 2021

For Heap optimization, I found this package related to priority queues we can import that and workaround with it or should I build it from scratch?

* https://www.npmjs.com/package/priorityqueuejs

Scratch, we try to avoid external packages where possible.

We'll most likely put it in the Core package but feel free to add it to this project first so we don't have to deal with deps issues while prototyping.

Sure 🤝

@Vib-UX Vib-UX requested a review from bmancini55 September 11, 2021 13:48
// from dest --> src and return route from src --> dest

// Convert it to corresponding node_id
const str_id = dest.nodeId.toString("hex");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider calling this variable dest_str_id or dest_id

Copy link
Member

@bmancini55 bmancini55 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

min-heap looks good with a couple minors. If you want to split that into a separate PR and add tests we can merge it in.

I still need to review dijkstras using the heap.

this._queue.push(value);
let pos = this._queue.length - 1;

while (pos !== 0 && this._compare(this._queue[this._parentOf(pos)], this._queue[pos])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

micro optimization but cache the call to _parentOf since we call it 3 times. will require refactor to a do/while loop.

}

private _compare(item1: T, item2: T) {
if (this._comparator) {
Copy link
Member

@bmancini55 bmancini55 Sep 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make the _comparator compulsory in the constructor, then we dont' need this check and can drop this whole function.

this._queue = [];
}

public contains(value: T, comparator?: (item: T) => boolean) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this operation? If not then lets drop it since its extra code

@Vib-UX
Copy link
Contributor Author

Vib-UX commented Sep 18, 2021

min-heap looks good with a couple minors. If you want to split that into a separate PR and add tests we can merge it in.

I still need to review dijkstras using the heap.

separate PR would make it look neat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

graph: path finding
4 participants