blob: 5419d5247b12a19af195586a2000d40c78eda219 [file] [log] [blame] [edit]
// 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 layout_test
import (
"path/filepath"
"testing"
"gonum.org/v1/gonum/graph"
"gonum.org/v1/gonum/graph/simple"
"gonum.org/v1/gonum/spatial/r2"
"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
. "gonum.org/v1/gonum/graph/layout"
)
var (
// tag is modified in isomap_noasm_test.go to "_noasm" when any
// build tag prevents use of the assembly numerical kernels.
tag string
// arch is modified in isomap_arm64_test.go to "_arm64" on arm64
// and "_386" on 386 to allow differences in numerical precision
// to be allowed for.
arch string
)
func TestIsomapR2(t *testing.T) {
isomapR2Tests := []struct {
name string
g graph.Graph
}{
{
name: "line_isomap",
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(1)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
{
name: "square_isomap",
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(1)},
{F: simple.Node(0), T: simple.Node(2)},
{F: simple.Node(1), T: simple.Node(3)},
{F: simple.Node(2), T: simple.Node(3)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
{
name: "tetrahedron_isomap",
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(1)},
{F: simple.Node(0), T: simple.Node(2)},
{F: simple.Node(0), T: simple.Node(3)},
{F: simple.Node(1), T: simple.Node(2)},
{F: simple.Node(1), T: simple.Node(3)},
{F: simple.Node(2), T: simple.Node(3)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
{
name: "sheet_isomap",
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(1)},
{F: simple.Node(0), T: simple.Node(3)},
{F: simple.Node(1), T: simple.Node(2)},
{F: simple.Node(1), T: simple.Node(4)},
{F: simple.Node(2), T: simple.Node(5)},
{F: simple.Node(3), T: simple.Node(4)},
{F: simple.Node(3), T: simple.Node(6)},
{F: simple.Node(4), T: simple.Node(5)},
{F: simple.Node(4), T: simple.Node(7)},
{F: simple.Node(5), T: simple.Node(8)},
{F: simple.Node(6), T: simple.Node(7)},
{F: simple.Node(7), T: simple.Node(8)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
{
name: "tube_isomap",
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(1)},
{F: simple.Node(0), T: simple.Node(2)},
{F: simple.Node(0), T: simple.Node(3)},
{F: simple.Node(1), T: simple.Node(2)},
{F: simple.Node(1), T: simple.Node(4)},
{F: simple.Node(2), T: simple.Node(5)},
{F: simple.Node(3), T: simple.Node(4)},
{F: simple.Node(3), T: simple.Node(5)},
{F: simple.Node(3), T: simple.Node(6)},
{F: simple.Node(4), T: simple.Node(5)},
{F: simple.Node(4), T: simple.Node(7)},
{F: simple.Node(5), T: simple.Node(8)},
{F: simple.Node(6), T: simple.Node(7)},
{F: simple.Node(6), T: simple.Node(8)},
{F: simple.Node(7), T: simple.Node(8)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
{
name: "wp_page_isomap", // https://en.wikipedia.org/wiki/PageRank#/media/File:PageRanks-Example.jpg
g: func() graph.Graph {
edges := []simple.Edge{
{F: simple.Node(0), T: simple.Node(3)},
{F: simple.Node(1), T: simple.Node(2)},
{F: simple.Node(1), T: simple.Node(3)},
{F: simple.Node(1), T: simple.Node(4)},
{F: simple.Node(1), T: simple.Node(5)},
{F: simple.Node(1), T: simple.Node(6)},
{F: simple.Node(1), T: simple.Node(7)},
{F: simple.Node(1), T: simple.Node(8)},
{F: simple.Node(3), T: simple.Node(4)},
{F: simple.Node(4), T: simple.Node(5)},
{F: simple.Node(4), T: simple.Node(6)},
{F: simple.Node(4), T: simple.Node(7)},
{F: simple.Node(4), T: simple.Node(8)},
{F: simple.Node(4), T: simple.Node(9)},
{F: simple.Node(4), T: simple.Node(10)},
}
g := simple.NewUndirectedGraph()
for _, e := range edges {
g.SetEdge(e)
}
return orderedGraph{g}
}(),
},
}
for _, test := range isomapR2Tests {
o := NewOptimizerR2(test.g, IsomapR2{}.Update)
var n int
for o.Update() {
n++
}
p := plot.New()
p.Add(render{o})
p.HideAxes()
path := filepath.Join("testdata", test.name+tag+arch+".png")
err := p.Save(10*vg.Centimeter, 10*vg.Centimeter, path)
if err != nil {
t.Errorf("unexpected error: %v", err)
continue
}
ok := checkRenderedLayout(t, path)
if !ok {
got := make(map[int64]r2.Vec)
nodes := test.g.Nodes()
for nodes.Next() {
id := nodes.Node().ID()
got[id] = o.Coord2(id)
}
t.Logf("got node positions: %#v", got)
}
}
}