I am new to golang and I am writing some graph routing algorithms. My graph representation looks like so
type Vertex [2]float64
type Edges map[Vertex]BagOfVertices
type BagOfVertices map[*Vertex]bool
I want to be able to represent edges from a particular Vertex, as a set of references to other Vertices. I am very memory constrained. To avoid memory costs of allocating lots of duplicate Vertex objects, I want to use pointers to vertex objects.
I have 1,335,262 nodes and 4,895,070 edges and about 800MB of RAM.
Here is my attempt at doing that
func (e *Edges) GetOrCreateVertex(vertex Vertex) *Vertex {
edges := *e
if _, ok := edges[vertex]; ok {
fmt.Println("Found val")
return &vertex
}
edges[vertex] = make(BagOfVertices)
fmt.Println("Create val")
return &vertex
}
func TestEdges(t *testing.T) {
var edges Edges = make(map[Vertex]BagOfVertices)
// Create edge from vertex 0 to vertex 1
v0 := edges.GetOrCreateVertex(Vertex{0, 0})
v1 := edges.GetOrCreateVertex(Vertex{1, 1})
edges[*v0][v1] = true
// Check edge exist from vertex 0 to vertex 1
v0 = edges.GetOrCreateVertex(Vertex{0, 0})
v1 = edges.GetOrCreateVertex(Vertex{1, 1})
if _, ok := edges[*v0][v1]; !ok {
t.Errorf("Edge from %v to %v does not exist", v0, v1)
}
}
Clearly the pointer returned by GetOrCreateVertex points to the value which was just created rather than the key of Edges. How can I get GetOrCreateVertex to return the pointer to the key in the Edges map?
My work around was to create
My workaround is to have a second map to store the pointers to the vertices.
type Vertex [2]float64
type GraphType struct {
vertices Vertices
edges Edges
}
type Vertices map[Vertex]*Vertex
type Edges map[*Vertex]BagOfVertices
type BagOfVertices map[*Vertex]bool
func (graph *GraphType) Init() {
graph.vertices = make(Vertices)
graph.edges = make(Edges)
}
func (graph *GraphType) GetOrCreateVertex(vertex Vertex) *Vertex {
if val, ok := graph.vertices[vertex]; ok {
fmt.Println("Found val")
return val
}
graph.vertices[vertex] = &vertex
graph.edges[&vertex] = make(BagOfVertices)
fmt.Println("Create val")
return &vertex
}
func TestEdges(t *testing.T) {
var graph GraphType
graph.Init()
// Create vertex 0 and vertex 1
graph.GetOrCreateVertex(Vertex{0, 0})
graph.GetOrCreateVertex(Vertex{1, 1})
// Create edge from vertex 0 to vertex 1
v0 := graph.GetOrCreateVertex(Vertex{0, 0})
v1 := graph.GetOrCreateVertex(Vertex{1, 1})
graph.edges[v0][v1] = true
// Check edge exist from vertex 0 to vertex 1
v0 = graph.GetOrCreateVertex(Vertex{0, 0})
v1 = graph.GetOrCreateVertex(Vertex{1, 1})
if _, ok := graph.edges[v0][v1]; !ok {
t.Errorf("Edge from %v to %v does not exist", v0, v1)
}
}