Пример #1
0
func TestCrunch(t *testing.T) {
	dg := concrete.NewDenseGraph(5, true)
	dg.Crunch()
	if len(dg.NodeList()) != 5 || len(dg.DirectedEdgeList()) != 5*5 {
		t.Errorf("Crunch did something")
	}
}
Пример #2
0
func TestDenseLists(t *testing.T) {
	dg := concrete.NewDenseGraph(15, true)
	nodes := nodeSorter(dg.NodeList())

	if len(nodes) != 15 {
		t.Fatalf("Wrong number of nodes")
	}

	sort.Sort(nodes)

	for i, node := range dg.NodeList() {
		if i != node.ID() {
			t.Errorf("Node list doesn't return properly id'd nodes")
		}
	}

	edges := dg.DirectedEdgeList()
	if len(edges) != 15*15 {
		t.Errorf("Improper number of edges for passable dense graph")
	}

	dg.RemoveEdge(concrete.Edge{concrete.Node(12), concrete.Node(11)}, true)
	edges = dg.DirectedEdgeList()
	if len(edges) != (15*15)-1 {
		t.Errorf("Removing edge didn't affect edge listing properly")
	}
}
Пример #3
0
func TestFWOneEdge(t *testing.T) {
	dg := concrete.NewDenseGraph(2, true)
	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.Node(0), concrete.Node(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1) > 1e-6 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW %v", path)
	}

	paths, cost, err := aPaths(concrete.Node(0), concrete.Node(1))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-1) > 1e-6 {
		t.Errorf("FW got wrong cost %f", cost)
	}

	if len(paths) != 1 {
		t.Errorf("Didn't get right paths in FW %v", paths)
	}

	path = paths[0]
	if len(path) != 2 || path[0].ID() != 0 && path[1].ID() != 1 {
		t.Errorf("Wrong path in FW allpaths %v", path)
	}
}
Пример #4
0
func TestFWTwoPaths(t *testing.T) {
	dg := concrete.NewDenseGraph(5, false)
	// Adds two paths from 0->2 of equal length
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(2)}, 2, true)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(1)}, 1, true)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(1), concrete.Node(2)}, 1, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)
	path, cost, err := sPath(concrete.Node(0), concrete.Node(2))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2) > .00001 {
		t.Errorf("Path has incorrect cost, %f", cost)
	}

	if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
		t.Logf("Got correct path: %v", path)
	} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
		t.Logf("Got correct path %v", path)
	} else {
		t.Errorf("Got wrong path %v", path)
	}

	paths, cost, err := aPaths(concrete.Node(0), concrete.Node(2))

	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-2) > .00001 {
		t.Errorf("All paths function gets incorrect cost, %f", cost)
	}

	if len(paths) != 2 {
		t.Fatalf("Didn't get all shortest paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 2 {
			t.Logf("Got correct path for all paths: %v", path)
		} else if len(path) == 3 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 {
			t.Logf("Got correct path for all paths %v", path)
		} else {
			t.Errorf("Got wrong path for all paths %v", path)
		}
	}
}
Пример #5
0
func TestBasicDensePassable(t *testing.T) {
	dg := concrete.NewDenseGraph(5, true)
	if dg == nil {
		t.Fatal("Directed graph could not be made")
	}

	for i := 0; i < 5; i++ {
		if !dg.NodeExists(concrete.Node(i)) {
			t.Errorf("Node that should exist doesn't: %d", i)
		}

		if degree := dg.Degree(concrete.Node(i)); degree != 10 {
			t.Errorf("Node in impassable graph has a neighbor. Node: %d Degree: %d", i, degree)
		}
	}

	for i := 5; i < 10; i++ {
		if dg.NodeExists(concrete.Node(i)) {
			t.Errorf("Node exists that shouldn't: %d", i)
		}
	}
}
Пример #6
0
func TestDenseAddRemove(t *testing.T) {
	dg := concrete.NewDenseGraph(10, false)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(2)}, 1, false)

	if neighbors := dg.Neighbors(concrete.Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 ||
		dg.EdgeBetween(concrete.Node(0), concrete.Node(2)) == nil {
		t.Errorf("Couldn't add neighbor")
	}

	if neighbors := dg.Successors(concrete.Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 ||
		dg.EdgeTo(concrete.Node(0), concrete.Node(2)) == nil {
		t.Errorf("Adding edge didn't create successor")
	}

	if neighbors := dg.Predecessors(concrete.Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 ||
		dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Adding undirected edge didn't create predecessor")
	}

	if neighbors := dg.Neighbors(concrete.Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 ||
		dg.EdgeBetween(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Adding an undirected neighbor didn't add it reciprocally")
	}

	if neighbors := dg.Successors(concrete.Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 ||
		dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Adding undirected edge didn't create proper successor")
	}

	if neighbors := dg.Predecessors(concrete.Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 ||
		dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Adding edge didn't create proper predecessor")
	}

	dg.RemoveEdge(concrete.Edge{concrete.Node(0), concrete.Node(2)}, true)

	if neighbors := dg.Neighbors(concrete.Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 ||
		dg.EdgeBetween(concrete.Node(0), concrete.Node(2)) == nil {
		t.Errorf("Removing a directed edge changed result of neighbors when neighbors is undirected; neighbors: %v", neighbors)
	}

	if neighbors := dg.Successors(concrete.Node(0)); len(neighbors) != 0 || dg.EdgeTo(concrete.Node(0), concrete.Node(2)) != nil {
		t.Errorf("Removing edge didn't properly remove successor")
	}

	if neighbors := dg.Predecessors(concrete.Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 ||
		dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Removing directed edge improperly removed predecessor")
	}

	if neighbors := dg.Neighbors(concrete.Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 ||
		dg.EdgeBetween(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Removing a directed edge removed reciprocal edge, neighbors: %v", neighbors)
	}

	if neighbors := dg.Successors(concrete.Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 ||
		dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Errorf("Removing edge improperly removed successor")
	}

	if neighbors := dg.Predecessors(concrete.Node(2)); len(neighbors) != 0 || dg.EdgeTo(concrete.Node(0), concrete.Node(2)) != nil {
		t.Errorf("Removing directed edge wrongly kept predecessor")
	}

	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(2)}, 2, true)
	// I figure we've torture tested Neighbors/Successors/Predecessors at this point
	// so we'll just use the bool functions now
	if dg.EdgeTo(concrete.Node(0), concrete.Node(2)) == nil {
		t.Error("Adding directed edge didn't change successor back")
	} else if dg.EdgeTo(concrete.Node(2), concrete.Node(0)) == nil {
		t.Error("Adding directed edge strangely removed reverse successor")
	} else if c1, c2 := dg.Cost(concrete.Edge{concrete.Node(2), concrete.Node(0)}), dg.Cost(concrete.Edge{concrete.Node(0), concrete.Node(2)}); math.Abs(c1-c2) < .000001 {
		t.Error("Adding directed edge affected cost in undirected manner")
	}

	dg.RemoveEdge(concrete.Edge{concrete.Node(2), concrete.Node(0)}, false)
	if dg.EdgeTo(concrete.Node(0), concrete.Node(2)) != nil || dg.EdgeTo(concrete.Node(2), concrete.Node(0)) != nil {
		t.Error("Removing undirected edge did no work properly")
	}
}
Пример #7
0
// Tests with multiple right paths, but also one dead-end path
// and one path that reaches the goal, but not optimally
func TestFWConfoundingPath(t *testing.T) {
	dg := concrete.NewDenseGraph(6, false)

	// Add a path from 0->5 of cost 4
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(1)}, 1, true)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(1), concrete.Node(2)}, 1, true)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(2), concrete.Node(3)}, 1, true)
	dg.SetEdgeCost(concrete.Edge{concrete.Node(3), concrete.Node(5)}, 1, true)

	// Add direct edge to goal of cost 4
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(5)}, 4, true)

	// Add edge to a node that's still optimal
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(2)}, 2, true)

	// Add edge to 3 that's overpriced
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(3)}, 4, true)

	// Add very cheap edge to 4 which is a dead end
	dg.SetEdgeCost(concrete.Edge{concrete.Node(0), concrete.Node(4)}, 0.25, true)

	aPaths, sPath := search.FloydWarshall(dg, nil)

	path, cost, err := sPath(concrete.Node(0), concrete.Node(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4) > 1e-6 {
		t.Errorf("Incorrect cost %f", cost)
	}

	if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
		t.Logf("Correct path found for single path %v", path)
	} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
		t.Logf("Correct path found for single path %v", path)
	} else if len(path) == 4 && path[0].ID() == 0 && path[1].ID() == 2 && path[2].ID() == 3 && path[3].ID() == 5 {
		t.Logf("Correct path found for single path %v", path)
	} else {
		t.Errorf("Wrong path found for single path %v", path)
	}

	paths, cost, err := aPaths(concrete.Node(0), concrete.Node(5))
	if err != nil {
		t.Fatal(err)
	}

	if math.Abs(cost-4) > 1e-6 {
		t.Errorf("Incorrect cost %f", cost)
	}

	if len(paths) != 3 {
		t.Errorf("Wrong paths gotten for all paths %v", paths)
	}

	for _, path := range paths {
		if len(path) == 5 && path[0].ID() == 0 && path[1].ID() == 1 && path[2].ID() == 2 && path[3].ID() == 3 && path[4].ID() == 5 {
			t.Logf("Correct path found for multi path %v", path)
		} else if len(path) == 2 && path[0].ID() == 0 && path[1].ID() == 5 {
			t.Logf("Correct path found for multi path %v", path)
		} else if len(path) == 4 && path[0].ID() == 0 && path[1].ID() == 2 && path[2].ID() == 3 && path[3].ID() == 5 {
			t.Logf("Correct path found for multi path %v", path)
		} else {
			t.Errorf("Wrong path found for multi path %v", path)
		}
	}

	path, _, err = sPath(concrete.Node(4), concrete.Node(5))
	if err != nil {
		t.Log("Success!", err)
	} else {
		t.Errorf("Path was found by FW single path where one shouldn't be %v", path)
	}

	paths, _, err = aPaths(concrete.Node(4), concrete.Node(5))
	if err != nil {
		t.Log("Success!", err)
	} else {
		t.Errorf("Path was found by FW multi-path where one shouldn't be %v", paths)
	}
}