I would like to try an accelerated approach to learning nim with a little help from a coach / pair-programming partner.
As I'm the author of the python project "Graph-theory" I know the python code well.
The objective of working with a coach is to rebuild the library in nim and make it an official nim package.
The main hurdle I would like to bypass is associated with navigating the small but important differences between python and nim in order to avoid wrong starts, followed by getting the right approach to packaging and distributing the package to common platforms (linux, windows, macos).
For the convenience of being in the same time-zone I can say that I'm Edinburgh, GB and welcome any proposals (including fee's) to dr.bjorn.madsen AT gmail.com
It's never wrong to ask for help, right?
I was very happy to see 5 super kind responses within a few hours.
I will contact each of them to find what schedule works best for both of us and would like to thank everyone for all the hearts on this posts. I'm so impressed with the passion within this group.
Thank you!
I am really looking forward to a graph library similar to networkx or yours in Nim. I have written this simple code that reads a graph from a file and can write to a file.
I have used a hash table to get node labels and a list to get the nodes number from a label. I have not handled weights and the label actually must be a string (even though I used a type alias).
You can also find examples of fuzzing a graph theory library in the talk of dr. chaos's library author at: https://youtu.be/6gsgg1zpTTQ?t=411 It directly uses generics to store data at each node.
#[
Reading graphs from files and writing into files
Based on jill-jênn Vie et christoph Dürr work
https://github.com/jilljenn/tryalgo/blob/master/tryalgo/graph.py
]#
import std/[tables, strutils, sugar]
# for creating a graph using vertex names
type
Node* = int
Label* = string
# Graph with Adjacency list representation
Graph* = ref object of RootObj
neighbors*: seq[seq[Node]] # Adjacency list
name2node*: Table[Label, Node] # Labels table
node2name*: seq[Label] # Reverse Table
# weight: seq[seq[Tuple[node: Node, weight: int]]]
func len*(g: Graph): int = len(g.node2name)
func getItem*(g: Graph, v: Node): seq[Node] = g.neighbors[v]
func degree*(g: Graph, node: Label): int = len(g.neighbors[g.name2node[node]])
func addNode*(g: Graph, name: Label) =
doAssert name notin g.name2node
g.name2node[name] = Node(len(g.name2node))
add(g.node2name, name)
g.neighbors.add(@[])
# g.weight.add(@[])
proc addArc*(g: Graph, nameU, nameV: Label, weightUV: int = 0) =
var
u = g.name2node[nameU]
v = g.name2node[nameV]
if v notin g.neighbors[u]:
g.neighbors[u].add(v)
# g.weight[u].add(Tuple[node: v, weight: weightUV])
proc addEdge*(g: Graph, nameU, nameV: Label, weightUV: int = 0) =
g.add_arc(nameU, nameV, weightUV)
g.add_arc(nameV, nameU, weightUV)
template outputGraph*(name: string, nameOfGraph: untyped): untyped =
echo name
echo `nameOfGraph`.neighbors
echo `nameOfGraph`.node2name
echo `nameOfGraph`.name2node
proc readGraph(filename: string, directed=false): Graph =
# Read a graph from a text file
#[
:param filename: plain text file. All numbers are separated by space.
Starts with a line containing n (#vertices) and m (#edges).
Then m lines follow, for each edge.
Vertices are numbered from 0 to n-1.
Line for unweighted edge u,v contains two integers u, v.
]#
let file = open(filename)
defer:
file.close()
var g: Graph
new g
var line: string = ""
while true:
line = file.readline() # ignore leading comments
if line[0] != '#':
break
let tempSeq = collect(for i in line.split(','): i.strip(trailing=false).parseInt())
let (nbNodes, nbEdges) = (temp_seq[0], temp_seq[1])
# echo nbNodes, ", ", nbEdges
for node in 0 ..< nb_edges:
line = file.readline()
let tempSeq = collect(for i in line.split(','): i.strip(trailing=false))
let (node1, node2) = (temp_seq[0], temp_seq[1])
for node in [node1, node2]:
if node notin g.name2node:
g.addNode(node)
if directed:
g.addArc(node1, node2)
else:
g.addEdge(node1, node2)
doAssert g.neighbors.len == nbNodes
g
proc writeGraph(graph: Graph, filename: string, directed=false) =
# Read a graph from a text file
#[
:param filename: plain text file. All numbers are separated by space.
Starts with a line containing n (#vertices) and m (#edges).
Then m lines follow, for each edge.
Vertices are numbered from 0 to n-1.
Line for unweighted edge u,v contains two integers u, v.
]#
let file = open(filename, fmWrite)
defer:
file.close()
let
nbNode = graph.neighbors.len
# Compute the number of edges
var nbEdge = 0
for sequenceNeighbors in graph.neighbors:
nbEdge.inc(sequenceNeighbors.len)
if not directed:
nbEdge = nbEdge div 2
file.write($nbNode & ", " & $nbEdge & "\n")
for node in 0 ..< nbNode:
let nodeLabel = graph.node2name[node]
for node2 in graph.neighbors[node]:
# To avoid repetition of same nodes
if node <= node2:
file.write(nodeLabel & ", " & graph.node2name[node2] & "\n")
when isMainModule:
var g: Graph
g = readGraph("graphExample.txt")
g.writeGraph("graphExample2.txt")
for idx in 0 ..< g.len:
echo g.getItem(idx)
This is far from perfect code, but I hope this can help to kickstart your project.I will contact each of them to find what schedule works best for both of us and would like to thank everyone for all the hearts on this posts. I'm so impressed with the passion within this group.
How cool would it be if we organized this as a community? you ask for a nim mentor/coach/... and we provide!
A coach is exactly what I have been hoping for ever since I restarted my programming hobby with nim (previously pascal). Have 3 awesome projects in mind, but currently working on a simple cli torrent client (and associated lib), which nim ecosystem is missing, and also a good scope for learning: sockets, async, network protocol parsing, many algorithms and such. Although I am not very skilled, I am rather motivated to learn "proper" programming.
Discord has been of great help, but sometimes I wish I could discuss the particulars of my project in greater detail, nim server's attention span is rather limited for this purpose. In exchange for some tutoring and spoon feeding/code review, nim community will hopefully benefit from (at least) 2 interesting libraries published to nimble directory. And a happy coder.
You can hit me up on discord (preferably) voidwalker#1983 or matrix @voidwalker09:matrix.org or e-mail sgmihai at "don't be evil" company