Add DOT attributes to multi.DirectedGraph Lines

38 views
Skip to first unread message

miller

unread,
Jul 23, 2024, 11:18:01 AM7/23/24
to gonum-dev
I'm trying to un-marhsal DOT input into a multi.DirectedGraph. Notice that the `dir` attribute determines the direction of the edge. If the value of `dir` is `both`, then I need to add a line (from, to) and (to, from). 

I'm trying to use `dot.UnmarshalMulti()` to un-marshal and I'm able to wrap the multi.DirectedGraph such that I can print out the attributes of edges when un-marshalling but not able to set any of the attributes on the line, `attrs` is always empty. This is my second project with Go and first post in this forum so any help is appreciated.

type dotMultiGraph struct {
*multi.DirectedGraph
}

func newDotMultiGraph() *dotMultiGraph {
return &dotMultiGraph{DirectedGraph: multi.NewDirectedGraph()}
}

func (g *dotMultiGraph) AddEdge(from, to graph.Node) graph.Line {
e := &dotLine{Line: g.DirectedGraph.NewLine(from, to), attrs: make(map[string]string)}
return e
}

func (g *dotMultiGraph) NewLine(from, to graph.Node) graph.Line {
line := g.DirectedGraph.NewLine(from, to)
dotLine := &dotLine{Line: line, attrs: make(map[string]string)}
return dotLine
}

func (g *dotMultiGraph) SetLine(e graph.Line) {
fmt.Printf("yoo: %+v\n", e.(*dotLine)) // this is where I think I would check if dir == both
g.DirectedGraph.SetLine(e.(*dotLine))
}

type dotLine struct {
graph.Line
attrs map[string]string
}

func (e *dotLine) SetAttribute(attr encoding.Attribute) error {
fmt.Printf("attr: %s\n", attr)
e.attrs[attr.Key] = attr.Value
return nil
}

func TestParsingGraphs(t *testing.T) {
ug := `
digraph "graph" {
graph [fontsize=12]
node [fontsize=12]
edge [fontsize=12]
rankdir=TB;
"N0" -> "N1" [uuid = "<Node1, Node0>", color = "#000000", fontcolor = "#000000", style = "solid", label = "edges", dir = "forward"]
"N0" -> "N2" [uuid = "<Node1, Node2>", color = "#000000", fontcolor = "#000000", style = "solid", label = "edges", dir = "both"]
"N2" -> "N1" [uuid = "<Node2, Node0>", color = "#000000", fontcolor = "#000000", style = "solid", label = "edges", dir = "forward"]
"N0" [uuid="Node1", label="Node1", color="#ffd700", fontcolor = "#000000", shape = "box", style = "filled, solid"]
"N1" [uuid="Node0", label="Node0", color="#ffd700", fontcolor = "#000000", shape = "box", style = "filled, solid"]
"N2" [uuid="Node2", label="Node2\n($cyclic_n)", color="#ffd700", fontcolor = "#000000", shape = "box", style = "filled, solid"]
}
`

// g := multi.NewDirectedGraph()
// multi.DirectedGraph
g := newDotMultiGraph()

err := dot.UnmarshalMulti([]byte(ug), g)
if err != nil {
log.Fatalf("failed to unmarshal DOT data: %v", err)
}

// cycles := topo.DirectedCyclesIn(g)

// if len(cycles) == 0 {
// t.Logf("Analysis result: %s\n", ug) // todo: handle command not found
// t.Logf("Cycles: %s", cycles)

// // Print out the nodes and edges
// t.Log("Nodes:")
// for nodes := g.Nodes(); nodes.Next(); {
// node := nodes.Node()
// t.Logf("Node ID: %v\n", node.ID())
// }

t.Log("Edges:")
for edges := g.Edges(); edges.Next(); {
edge := edges.Edge()
// t.Log(edge)

fmt.Printf("%+v\n", g.Lines(edge.From().ID(), edge.To().ID()).Line())
t.Logf("Edge from %v to %v\n", edge.From().ID(), edge.To().ID())
}

data, err := dot.Marshal(g, "Example Graph", "", "\t")
if err != nil {
log.Fatalf("error marshalling graph to DOT: %v", err)
}
t.Log(string(data))
// t.Errorf("Expected cycles to be > 0, found none")
// }
}

Dan Kortschak

unread,
Jul 26, 2024, 6:48:30 AM7/26/24
to gonu...@googlegroups.com
On Mon, 2024-07-22 at 20:07 -0700, miller wrote:
> I'm trying to un-marhsal DOT input into a multi.DirectedGraph. Notice
> that the `dir` attribute determines the direction of the edge. If the
> value of `dir` is `both`, then I need to add a line (from, to) and
> (to, from). 
>
> I'm trying to use `dot.UnmarshalMulti()` to un-marshal and I'm able
> to wrap the multi.DirectedGraph such that I can print out the
> attributes of edges when un-marshalling but not able to set any of
> the attributes on the line, `attrs` is always empty. This is my
> second project with Go and first post in this forum so any help is
> appreciated.

This does what you want, https://go.dev/play/p/5W8BOzSXmp7. It's not
nice, but you are reaching outside the intended usage of DOT. The
attributes are set after the edge is added to the graph.

Please post plain text.

Dan

miller

unread,
Jul 26, 2024, 8:42:48 PM7/26/24
to gonum-dev
Thank you sir. In case someone finds it helpful, here[1] is a slightly modified version of the code you sent that I'm using.

Reply all
Reply to author
Forward
0 new messages