Re: Distinct for indices, is it good library Api?

2019-12-25 Thread b3liever
In the end, I think, it makes no sense to write an 1:1 port of petgraph, I will 
do a library that is usable at least by a noob (me). I think its best not to 
export `EdgeIndex` and keep edges private, if the weight must be updated, 
updateEdge is available, findEdge though will be private. Removing nodes and 
edges invalidates the last indices, so I won't implement it.


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread b3liever
Now I get it thanks, I've seen a couple of ways to model an adjacency list, but 
I think this must be the most efficient. Actually it models a doubly linked 
list with indices, there is no need for a seq, it has no limitations. You can 
see how the example at the end represented in memory, take a look at the 
commented output.


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread b3liever
Nice idea, thanks! I also tried converters (like the original library does) but 
it failed to compile. will submit a bug report


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread mashingan
> What do you mean?

If I understand correctly, you defined the Node with information of incoming / 
outgoing Edge


type
  Node*[N] = object ## The graph's node type.
  weight*: N ## Associated node data.
  next: array[2, EdgeIndex] ## Next edge in outgoing and incoming edge 
lists.


Run

This way, you only have 1 Edge for each, 1 for incoming and 1 for outgoing. 
Unless your graph specifically only as a one line flow, a node should be able 
to have several nodes incoming and outgoing but you only defined it as an array 
of two Edge member. If it's seq, you can add it later based on new graph 
connection or any info.

Simply changing the definition into seq should somehow solve the limitation of 
current definition. But since it's in development phase, you would recognize it 
the more you develop it, that's why I mentioned "will be unused". CMIIW


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread dawkot
Why not overload procs like fromEdges to accept pairs of integers?


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread b3liever
> The array of two nodes index for incoming/outgoing will be unused the more 
> you add APIs to your graph.

What do you mean by this? 


Re: Distinct for indices, is it good library Api?

2019-12-25 Thread mashingan
IMO, It's not worthy to make it distinct, moreover, you should use generic 
instead of int for nodes label.

Unrelated to the question, you should keep the Node definition is literally as 
a node, and keep Edge definition is the connection from Node1 and Node2. The 
array of two nodes index for incoming/outgoing will be unused the more you add 
APIs to your graph.


Distinct for indices, is it good library Api?

2019-12-25 Thread b3liever
Hi and merry Christmas,

I was trying to port [petagraph](https://github.com/petgraph/petgraph) rust 
library to nim and although I made some 
[progress](https://gist.github.com/b3liever/de2d4e2267b13832f7d52f10ba3140fe) I 
am struggling with some fundamental decisions.

for example, when adding a node in the graph, it returns the index:


var graph: Graph[string, float]
let nodeA = graph.addNode("a")
let nodeB = graph.addNode("b")
let nodeC = graph.addNode("c")
let nodeD = graph.addNode("d")
let nodeE = graph.addNode("e")
let nodeF = graph.addNode("f")
let nodeG = graph.addNode("g")
let nodeH = graph.addNode("h")

# Also returns the edge index when adding an edge, not sure if its useful
let edge1 = graph.addEdge(nodeA, nodeB, 1.0)

Run

These indices are `distinct` types like so:


type
  IndexType = int
  NodeIndex = distinct IndexType
  EdgeIndex = distinct IndexType

Run

That allows to have array element access syntax for nodes and edges:


proc `[]`*[N, E](self: Graph[N, E], a: NodeIndex): N =
  ## Access the weight for node `a`.
  self.nodes[int(a)].weight

proc `[]`*[N, E](self: Graph[N, E], e: EdgeIndex): E =
  ## Access the weight for edge `e`.
  self.edges[int(e)].weight

# works like so:
echo graph[edge1] # 1.0
echo graph[nodeA] # "a"

Run

And this was the only benefit I think there is with `distinct` indices, 
consider this code:


import graph, sequtils
let graph2 = fromEdges[int, int](mapLiterals(@[
   (0, 1), (0, 2), (0, 3),
   (1, 2), (1, 3),
   (2, 3)], NodeIndex))

Run

becomes tiresome to write, since everything needs to converted to the correct 
`IndexType` subtype. Also the internal code is littered with 
`self.nodes[int(nix)]`. My question is does it worth it, or should I just use 
int everywhere?