Example #1
0
func TestBiggerAStar(t *testing.T) {
	tg := concrete.NewTileGraph(3, 3, true)

	path, cost, _ := search.AStar(concrete.Node(0), concrete.Node(8), tg, nil, nil)

	if math.Abs(cost-4) > 1e-5 || !search.IsPath(path, tg) {
		t.Error("Non-optimal or impossible path found for 3x3 grid")
	}

	tg = concrete.NewTileGraph(1000, 1000, true)
	path, cost, _ = search.AStar(concrete.Node(0), concrete.Node(999*1000+999), tg, nil, nil)
	if !search.IsPath(path, tg) || cost != 1998 {
		t.Error("Non-optimal or impossible path found for 100x100 grid; cost:", cost, "path:\n"+tg.PathString(path))
	}
}
Example #2
0
func TestObstructedAStar(t *testing.T) {
	tg := concrete.NewTileGraph(10, 10, true)

	// Creates a partial "wall" down the middle row with a gap down the left side
	tg.SetPassability(4, 1, false)
	tg.SetPassability(4, 2, false)
	tg.SetPassability(4, 3, false)
	tg.SetPassability(4, 4, false)
	tg.SetPassability(4, 5, false)
	tg.SetPassability(4, 6, false)
	tg.SetPassability(4, 7, false)
	tg.SetPassability(4, 8, false)
	tg.SetPassability(4, 9, false)

	rows, cols := tg.Dimensions()
	path, cost1, expanded := search.AStar(concrete.Node(5), tg.CoordsToNode(rows-1, cols-1), tg, nil, nil)

	if !search.IsPath(path, tg) {
		t.Error("Path doesn't exist in obstructed graph")
	}

	ManhattanHeuristic := func(n1, n2 graph.Node) float64 {
		id1, id2 := n1.ID(), n2.ID()
		r1, c1 := tg.IDToCoords(id1)
		r2, c2 := tg.IDToCoords(id2)

		return math.Abs(float64(r1)-float64(r2)) + math.Abs(float64(c1)-float64(c2))
	}

	path, cost2, expanded2 := search.AStar(concrete.Node(5), tg.CoordsToNode(rows-1, cols-1), tg, nil, ManhattanHeuristic)
	if !search.IsPath(path, tg) {
		t.Error("Path doesn't exist when using heuristic on obstructed graph")
	}

	if math.Abs(cost1-cost2) > 1e-5 {
		t.Error("Cost when using admissible heuristic isn't approximately equal to cost without it")
	}

	if expanded2 > expanded {
		t.Error("Using admissible, consistent heuristic expanded more nodes than null heuristic (possible, but unlikely -- suggests an error somewhere)")
	}

}
Example #3
0
func TestIsPath(t *testing.T) {
	dg := concrete.NewDirectedGraph()
	if !search.IsPath(nil, dg) {
		t.Error("IsPath returns false on nil path")
	}
	p := []graph.Node{concrete.Node(0)}
	if search.IsPath(p, dg) {
		t.Error("IsPath returns true on nonexistant node")
	}
	dg.AddNode(p[0])
	if !search.IsPath(p, dg) {
		t.Error("IsPath returns false on single-length path with existing node")
	}
	p = append(p, concrete.Node(1))
	dg.AddNode(p[1])
	if search.IsPath(p, dg) {
		t.Error("IsPath returns true on bad path of length 2")
	}
	dg.AddDirectedEdge(concrete.Edge{p[0], p[1]}, 1)
	if !search.IsPath(p, dg) {
		t.Error("IsPath returns false on correct path of length 2")
	}
	p[0], p[1] = p[1], p[0]
	if search.IsPath(p, dg) {
		t.Error("IsPath erroneously returns true for a reverse path")
	}
	p = []graph.Node{p[1], p[0], concrete.Node(2)}
	dg.AddDirectedEdge(concrete.Edge{p[1], p[2]}, 1)
	if !search.IsPath(p, dg) {
		t.Error("IsPath does not find a correct path for path > 2 nodes")
	}
	ug := concrete.NewGraph()
	ug.AddUndirectedEdge(concrete.Edge{p[1], p[0]}, 1)
	ug.AddUndirectedEdge(concrete.Edge{p[1], p[2]}, 1)
	if !search.IsPath(p, ug) {
		t.Error("IsPath does not correctly account for undirected behavior")
	}
}
Example #4
0
func main() {
	// graph G {
	G := NewGraphNode(0)
	// e
	e := NewGraphNode(1)

	// subgraph clusterA {
	clusterA := NewGraphNode(2)

	// a -- b
	a := NewGraphNode(3)
	b := NewGraphNode(4)
	a.AddNeighbor(b)
	b.AddNeighbor(a)
	clusterA.AddRoot(a)
	clusterA.AddRoot(b)

	// subgraph clusterC {
	clusterC := NewGraphNode(5)
	// C -- D
	C := NewGraphNode(6)
	D := NewGraphNode(7)
	C.AddNeighbor(D)
	D.AddNeighbor(C)

	clusterC.AddRoot(C)
	clusterC.AddRoot(D)
	// }
	clusterA.AddRoot(clusterC)
	// }

	// subgraph clusterB {
	clusterB := NewGraphNode(8)

	// d -- f
	d := NewGraphNode(9)
	f := NewGraphNode(10)
	d.AddNeighbor(f)
	f.AddNeighbor(d)
	clusterB.AddRoot(d)
	clusterB.AddRoot(f)
	// }

	// d -- D
	d.AddNeighbor(D)
	D.AddNeighbor(d)

	// e -- clusterB
	e.AddNeighbor(clusterB)
	clusterB.AddNeighbor(e)

	// clusterC -- clusterB
	clusterC.AddNeighbor(clusterB)
	clusterB.AddNeighbor(clusterC)

	G.AddRoot(e)
	G.AddRoot(clusterA)
	G.AddRoot(clusterB)
	// }

	path := []graph.Node{C, D, d, f}
	if !search.IsPath(path, G) {
		fmt.Println("Not working!")
	} else {
		fmt.Println("Working!")
	}
}