// Copyright ©2019 The Gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package dot_test import ( "fmt" "log" "math" "strconv" "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/encoding" "gonum.org/v1/gonum/graph/encoding/dot" "gonum.org/v1/gonum/graph/simple" ) // dotGraph provides a shim for interaction between the DOT // unmarshaler and a simple.WeightedUndirectedGraph. type dotGraph struct { *simple.WeightedUndirectedGraph } func newDotGraph() *dotGraph { return &dotGraph{WeightedUndirectedGraph: simple.NewWeightedUndirectedGraph(0, 0)} } // NewEdge returns a DOT-aware edge. func (g *dotGraph) NewEdge(from, to graph.Node) graph.Edge { e := g.WeightedUndirectedGraph.NewWeightedEdge(from, to, math.NaN()).(simple.WeightedEdge) return &weightedEdge{WeightedEdge: e} } // NewNode returns a DOT-aware node. func (g *dotGraph) NewNode() graph.Node { return &node{Node: g.WeightedUndirectedGraph.NewNode()} } // SetEdge is a shim to allow the DOT unmarshaler to // add weighted edges to a graph. func (g *dotGraph) SetEdge(e graph.Edge) { g.WeightedUndirectedGraph.SetWeightedEdge(e.(*weightedEdge)) } // weightedEdge is a DOT-aware weighted edge. type weightedEdge struct { simple.WeightedEdge } // SetAttribute sets the weight of the receiver. func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error { if attr.Key != "weight" { return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key) } var err error e.W, err = strconv.ParseFloat(attr.Value, 64) return err } // node is a DOT-aware node. type node struct { graph.Node dotID string } // SetDOTID sets the DOT ID of the node. func (n *node) SetDOTID(id string) { n.dotID = id } func (n *node) String() string { return n.dotID } const ug = ` graph { a b c a--b ["weight"=0.5] a--c ["weight"=1] } ` func ExampleUnmarshal_weighted() { dst := newDotGraph() err := dot.Unmarshal([]byte(ug), dst) if err != nil { log.Fatal(err) } for _, e := range graph.EdgesOf(dst.Edges()) { fmt.Printf("%+v\n", e.(*weightedEdge).WeightedEdge) } // Unordered output: // {F:a T:b W:0.5} // {F:a T:c W:1} }