diff --git a/QuadTree.Tests/QuadTree.Tests.fsproj b/QuadTree.Tests/QuadTree.Tests.fsproj index 4de3d64..bc76cf2 100644 --- a/QuadTree.Tests/QuadTree.Tests.fsproj +++ b/QuadTree.Tests/QuadTree.Tests.fsproj @@ -13,7 +13,7 @@ - + diff --git a/QuadTree.Tests/Tests.BFS.fs b/QuadTree.Tests/Tests.BFS.fs index df5d0f3..49bc80b 100644 --- a/QuadTree.Tests/Tests.BFS.fs +++ b/QuadTree.Tests/Tests.BFS.fs @@ -7,16 +7,20 @@ open Matrix open Vector open Common -(* -1,N,N,N -, -N,1,1,N -3,N,2,3 -N,N,N,2 -N,N,3,N -=> -0,1,1,2 -*) +let singleStart (n: uint64) (s: uint64) = + Vector.CoordinateList(n * 1UL, [ s * 1UL, 1UL ]) + |> Vector.fromCoordinateList + +let vec (n: uint64) pairs = + Vector.CoordinateList( + n * 1UL, + pairs |> List.map (fun (i: uint64, v: uint64) -> i * 1UL, v) + ) + |> Vector.fromCoordinateList + +let unsafes (n: uint64) (v: Vector.SparseVector<_>) = + List.init (int n) (fun i -> Vector.unsafeGet v (uint64 i * 1UL)) + [] let ``Simple level bfs.`` () = let graph = @@ -69,3 +73,1386 @@ let ``Simple level bfs.`` () = let actual = Graph.BFS.bfs_level graph startVertices Assert.Equal(expected, actual) + +[] +let ``Simple parent bfs.`` () = + let graph = + let tree = + Matrix.qtree.Node( + Matrix.qtree.Node( + Matrix.qtree.Leaf(UserValue(None)), + Matrix.qtree.Leaf(UserValue(Some(1))), + Matrix.qtree.Leaf(UserValue(Some(3))), + Matrix.qtree.Leaf(UserValue(None)) + ), + Matrix.qtree.Node( + Matrix.qtree.Leaf(UserValue(Some(1))), + Matrix.qtree.Leaf(UserValue(None)), + Matrix.qtree.Leaf(UserValue(Some(2))), + Matrix.qtree.Leaf(UserValue(Some(3))) + ), + Matrix.qtree.Leaf(UserValue(None)), + Matrix.qtree.Node( + Matrix.qtree.Leaf(UserValue(None)), + Matrix.qtree.Leaf(UserValue(Some(2))), + Matrix.qtree.Leaf(UserValue(Some(3))), + Matrix.qtree.Leaf(UserValue(None)) + ) + ) + + let store = Matrix.Storage(4UL, tree) + SparseMatrix(4UL, 4UL, 9UL, store) + + let startVertices = + let tree = + Vector.btree.Node( + Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(1UL))), Vector.btree.Leaf(UserValue(None))), + Vector.btree.Leaf(UserValue(None)) + ) + + let store = Vector.Storage(4UL, tree) + SparseVector(4UL, 1UL, store) + + let expected = + let tree = + Vector.btree.Node( + Vector.btree.Leaf(UserValue(Some(0UL))), + Vector.btree.Node(Vector.btree.Leaf(UserValue(Some(0UL))), Vector.btree.Leaf(UserValue(Some(1UL)))) + ) + + let store = Vector.Storage(4UL, tree) + Ok(SparseVector(4UL, 4UL, store)) + + let actual = Graph.BFS.bfs_parent graph startVertices + + Assert.Equal(expected, actual) + +// ============== 3-node line ============== + +let private line3graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 3UL, + 3UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 1UL + 2UL, 1UL, 1UL ] + ) + ) + +[] +let ``Level bfs 3 node line start 0`` () = + let n = uint64 line3graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level line3graph start + let expected = [ Some 0UL; Some 1UL; Some 2UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs 3 node line start 0`` () = + let n = uint64 line3graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent line3graph start + let expected = [ Some 0UL; Some 0UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Level bfs 3 node line start 1`` () = + let n = uint64 line3graph.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_level line3graph start + let expected = [ Some 1UL; Some 0UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs 3 node line start 1`` () = + let n = uint64 line3graph.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_parent line3graph start + let expected = [ Some 1UL; Some 1UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +// ============== 5-node star (center 0) ============== + +let private star5graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 5UL, + 5UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 0UL, 2UL, 1UL + 2UL, 0UL, 1UL + 0UL, 3UL, 1UL + 3UL, 0UL, 1UL + 0UL, 4UL, 1UL + 4UL, 0UL, 1UL ] + ) + ) + +[] +let ``Level bfs 5 node star start center`` () = + let n = uint64 star5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level star5graph start + let expected = [ Some 0UL; Some 1UL; Some 1UL; Some 1UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node star start center`` () = + let n = uint64 star5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent star5graph start + let expected = [ Some 0UL; Some 0UL; Some 0UL; Some 0UL; Some 0UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Level bfs 5 node star start leaf`` () = + let n = uint64 star5graph.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_level star5graph start + let expected = [ Some 1UL; Some 0UL; Some 2UL; Some 2UL; Some 2UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node star start leaf`` () = + let n = uint64 star5graph.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_parent star5graph start + let expected = [ Some 1UL; Some 1UL; Some 0UL; Some 0UL; Some 0UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +// ============== Two components ============== + +let private twoCompGraph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 6UL, + 6UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 1UL + 2UL, 1UL, 1UL + 0UL, 2UL, 1UL + 2UL, 0UL, 1UL + + 3UL, 4UL, 1UL + 4UL, 3UL, 1UL + 4UL, 5UL, 1UL + 5UL, 4UL, 1UL + 3UL, 5UL, 1UL + 5UL, 3UL, 1UL ] + ) + ) + +[] +let ``Level bfs two components start 0`` () = + let n = uint64 twoCompGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level twoCompGraph start + let expected = [ Some 0UL; Some 1UL; Some 1UL; None; None; None ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs two components start 0`` () = + let n = uint64 twoCompGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent twoCompGraph start + let expected = [ Some 0UL; Some 0UL; Some 0UL; None; None; None ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +// ============== Square (4-cycle) ============== + +let private squareGraph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 4UL, + 4UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + 3UL, 0UL, 2UL + 0UL, 3UL, 2UL ] + ) + ) + +[] +let ``Level bfs square start 0`` () = + let n = uint64 squareGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level squareGraph start + let expected = [ Some 0UL; Some 1UL; Some 2UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs square start 0`` () = + let n = uint64 squareGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent squareGraph start + let expected = [ Some 0UL; Some 0UL; Some 1UL; Some 0UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +// ============== 6-cycle ============== + +let private cycle6graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 6UL, + 6UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 3UL + 3UL, 2UL, 3UL + 3UL, 4UL, 4UL + 4UL, 3UL, 4UL + 4UL, 5UL, 5UL + 5UL, 4UL, 5UL + 5UL, 0UL, 6UL + 0UL, 5UL, 6UL ] + ) + ) + +[] +let ``Level bfs 6 cycle start 0`` () = + let n = uint64 cycle6graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level cycle6graph start + let expected = [ Some 0UL; Some 1UL; Some 2UL; Some 3UL; Some 2UL; Some 1UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +[] +let ``Parent bfs 6 cycle start 0`` () = + let n = uint64 cycle6graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent cycle6graph start + let expected = [ Some 0UL; Some 0UL; Some 1UL; Some 2UL; Some 5UL; Some 0UL ] + Assert.Equal(Ok expected, Result.map (unsafes n) result) + +// ============== 2 nodes ============== + +let private graph2 = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 2UL, + 2UL, + [ 0UL, 1UL, 5UL; 1UL, 0UL, 5UL ] + ) + ) + +[] +let ``Level bfs 2 nodes start 0`` () = + let n = uint64 graph2.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level graph2 start + Assert.Equal(Ok [ Some 0UL; Some 1UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 2 nodes start 0`` () = + let n = uint64 graph2.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent graph2 start + Assert.Equal(Ok [ Some 0UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 2 nodes start 1`` () = + let n = uint64 graph2.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_level graph2 start + Assert.Equal(Ok [ Some 1UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 2 nodes start 1`` () = + let n = uint64 graph2.ncols + let start = singleStart n 1UL + let result = Graph.BFS.bfs_parent graph2 start + Assert.Equal(Ok [ Some 1UL; Some 1UL ], Result.map (unsafes n) result) + +// ============== 4-node line ============== + +let private line4graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 4UL, + 4UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 3UL + 3UL, 2UL, 3UL ] + ) + ) + +[] +let ``Level bfs 4 node line start 0`` () = + let n = uint64 line4graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level line4graph start + Assert.Equal(Ok [ Some 0UL; Some 1UL; Some 2UL; Some 3UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 4 node line start 0`` () = + let n = uint64 line4graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent line4graph start + Assert.Equal(Ok [ Some 0UL; Some 0UL; Some 1UL; Some 2UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 4 node line start 3`` () = + let n = uint64 line4graph.ncols + let start = singleStart n 3UL + let result = Graph.BFS.bfs_level line4graph start + Assert.Equal(Ok [ Some 3UL; Some 2UL; Some 1UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 4 node line start 3`` () = + let n = uint64 line4graph.ncols + let start = singleStart n 3UL + let result = Graph.BFS.bfs_parent line4graph start + Assert.Equal(Ok [ Some 1UL; Some 2UL; Some 3UL; Some 3UL ], Result.map (unsafes n) result) + +// ============== 5-node line ============== + +let private line5graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 5UL, + 5UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 3UL + 3UL, 2UL, 3UL + 3UL, 4UL, 4UL + 4UL, 3UL, 4UL ] + ) + ) + +[] +let ``Level bfs 5 node line start 0`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level line5graph start + Assert.Equal(Ok [ Some 0UL; Some 1UL; Some 2UL; Some 3UL; Some 4UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node line start 0`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent line5graph start + Assert.Equal(Ok [ Some 0UL; Some 0UL; Some 1UL; Some 2UL; Some 3UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 5 node line start 4`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_level line5graph start + Assert.Equal(Ok [ Some 4UL; Some 3UL; Some 2UL; Some 1UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node line start 4`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_parent line5graph start + Assert.Equal(Ok [ Some 1UL; Some 2UL; Some 3UL; Some 4UL; Some 4UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 5 node line start 2`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_level line5graph start + Assert.Equal(Ok [ Some 2UL; Some 1UL; Some 0UL; Some 1UL; Some 2UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node line start 2`` () = + let n = uint64 line5graph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_parent line5graph start + Assert.Equal(Ok [ Some 1UL; Some 2UL; Some 2UL; Some 2UL; Some 3UL ], Result.map (unsafes n) result) + +// ============== Simple triangle ============== + +let private triangleGraph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 3UL, + 3UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 0UL, 2UL, 1UL + 2UL, 0UL, 1UL + 1UL, 2UL, 1UL + 2UL, 1UL, 1UL ] + ) + ) + +[] +let ``Level bfs triangle start 0`` () = + let n = uint64 triangleGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level triangleGraph start + Assert.Equal(Ok [ Some 0UL; Some 1UL; Some 1UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs triangle start 0`` () = + let n = uint64 triangleGraph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent triangleGraph start + Assert.Equal(Ok [ Some 0UL; Some 0UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs triangle start 2`` () = + let n = uint64 triangleGraph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_level triangleGraph start + Assert.Equal(Ok [ Some 1UL; Some 1UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs triangle start 2`` () = + let n = uint64 triangleGraph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_parent triangleGraph start + Assert.Equal(Ok [ Some 2UL; Some 2UL; Some 2UL ], Result.map (unsafes n) result) + +// ============== 5-node complete graph ============== + +let private complete5graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 5UL, + 5UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 0UL, 2UL, 2UL + 2UL, 0UL, 2UL + 0UL, 3UL, 3UL + 3UL, 0UL, 3UL + 0UL, 4UL, 4UL + 4UL, 0UL, 4UL + 1UL, 2UL, 5UL + 2UL, 1UL, 5UL + 1UL, 3UL, 6UL + 3UL, 1UL, 6UL + 1UL, 4UL, 7UL + 4UL, 1UL, 7UL + 2UL, 3UL, 8UL + 3UL, 2UL, 8UL + 2UL, 4UL, 9UL + 4UL, 2UL, 9UL + 3UL, 4UL, 10UL + 4UL, 3UL, 10UL ] + ) + ) + +[] +let ``Level bfs 5 node complete start 0`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level complete5graph start + Assert.Equal(Ok [ Some 0UL; Some 1UL; Some 1UL; Some 1UL; Some 1UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node complete start 0`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent complete5graph start + Assert.Equal(Ok [ Some 0UL; Some 0UL; Some 0UL; Some 0UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 5 node complete start 4`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_level complete5graph start + Assert.Equal(Ok [ Some 1UL; Some 1UL; Some 1UL; Some 1UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node complete start 4`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_parent complete5graph start + Assert.Equal(Ok [ Some 4UL; Some 4UL; Some 4UL; Some 4UL; Some 4UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs 5 node complete start 2`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_level complete5graph start + Assert.Equal(Ok [ Some 1UL; Some 1UL; Some 0UL; Some 1UL; Some 1UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs 5 node complete start 2`` () = + let n = uint64 complete5graph.ncols + let start = singleStart n 2UL + let result = Graph.BFS.bfs_parent complete5graph start + Assert.Equal(Ok [ Some 2UL; Some 2UL; Some 2UL; Some 2UL; Some 2UL ], Result.map (unsafes n) result) + +// ============== K3,3 bipartite ============== + +let private k33graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 6UL, + 6UL, + [ 0UL, 3UL, 1UL + 3UL, 0UL, 1UL + 0UL, 4UL, 2UL + 4UL, 0UL, 2UL + 0UL, 5UL, 3UL + 5UL, 0UL, 3UL + 1UL, 3UL, 4UL + 3UL, 1UL, 4UL + 1UL, 4UL, 5UL + 4UL, 1UL, 5UL + 1UL, 5UL, 6UL + 5UL, 1UL, 6UL + 2UL, 3UL, 7UL + 3UL, 2UL, 7UL + 2UL, 4UL, 8UL + 4UL, 2UL, 8UL + 2UL, 5UL, 9UL + 5UL, 2UL, 9UL ] + ) + ) + +[] +let ``Level bfs K3 3 start 0`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level k33graph start + Assert.Equal(Ok [ Some 0UL; Some 2UL; Some 2UL; Some 1UL; Some 1UL; Some 1UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs K3 3 start 0`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent k33graph start + Assert.Equal(Ok [ Some 0UL; Some 3UL; Some 3UL; Some 0UL; Some 0UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs K3 3 start 5`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_level k33graph start + Assert.Equal(Ok [ Some 1UL; Some 1UL; Some 1UL; Some 2UL; Some 2UL; Some 0UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs K3 3 start 5`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_parent k33graph start + Assert.Equal(Ok [ Some 5UL; Some 5UL; Some 5UL; Some 0UL; Some 0UL; Some 5UL ], Result.map (unsafes n) result) + +[] +let ``Level bfs K3 3 start 3`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 3UL + let result = Graph.BFS.bfs_level k33graph start + Assert.Equal(Ok [ Some 1UL; Some 1UL; Some 1UL; Some 0UL; Some 2UL; Some 2UL ], Result.map (unsafes n) result) + +[] +let ``Parent bfs K3 3 start 3`` () = + let n = uint64 k33graph.ncols + let start = singleStart n 3UL + let result = Graph.BFS.bfs_parent k33graph start + Assert.Equal(Ok [ Some 3UL; Some 3UL; Some 3UL; Some 3UL; Some 0UL; Some 0UL ], Result.map (unsafes n) result) + +// ============== 8 nodes random weights ============== + +let private random8graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 8UL, + 8UL, + [ 0UL, 1UL, 7UL + 1UL, 0UL, 7UL + 0UL, 2UL, 5UL + 2UL, 0UL, 5UL + 0UL, 3UL, 9UL + 3UL, 0UL, 9UL + 1UL, 2UL, 3UL + 2UL, 1UL, 3UL + 1UL, 3UL, 4UL + 3UL, 1UL, 4UL + 2UL, 3UL, 2UL + 3UL, 2UL, 2UL + 4UL, 5UL, 1UL + 5UL, 4UL, 1UL + 4UL, 6UL, 6UL + 6UL, 4UL, 6UL + 4UL, 7UL, 8UL + 7UL, 4UL, 8UL + 5UL, 6UL, 3UL + 6UL, 5UL, 3UL + 5UL, 7UL, 5UL + 7UL, 5UL, 5UL + 6UL, 7UL, 2UL + 7UL, 6UL, 2UL + 3UL, 4UL, 10UL + 4UL, 3UL, 10UL ] + ) + ) + +[] +let ``Level bfs 8 node random start 0`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level random8graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 1UL + Some 1UL + Some 1UL + Some 2UL + Some 3UL + Some 3UL + Some 3UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node random start 0`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent random8graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 0UL + Some 0UL + Some 0UL + Some 3UL + Some 4UL + Some 4UL + Some 4UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 8 node random start 7`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 7UL + let result = Graph.BFS.bfs_level random8graph start + + Assert.Equal( + Ok + [ Some 3UL + Some 3UL + Some 3UL + Some 2UL + Some 1UL + Some 1UL + Some 1UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node random start 7`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 7UL + let result = Graph.BFS.bfs_parent random8graph start + + Assert.Equal( + Ok + [ Some 3UL + Some 3UL + Some 3UL + Some 4UL + Some 7UL + Some 7UL + Some 7UL + Some 7UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 8 node random start 4`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_level random8graph start + + Assert.Equal( + Ok + [ Some 2UL + Some 2UL + Some 2UL + Some 1UL + Some 0UL + Some 1UL + Some 1UL + Some 1UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node random start 4`` () = + let n = uint64 random8graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_parent random8graph start + + Assert.Equal( + Ok + [ Some 3UL + Some 3UL + Some 3UL + Some 4UL + Some 4UL + Some 4UL + Some 4UL + Some 4UL ], + Result.map (unsafes n) result + ) + +// ============== 8 nodes grid ============== + +let private grid8graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 8UL, + 8UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + 0UL, 4UL, 3UL + 4UL, 0UL, 3UL + 1UL, 5UL, 4UL + 5UL, 1UL, 4UL + 2UL, 6UL, 5UL + 6UL, 2UL, 5UL + 3UL, 7UL, 6UL + 7UL, 3UL, 6UL + 4UL, 5UL, 2UL + 5UL, 4UL, 2UL + 5UL, 6UL, 1UL + 6UL, 5UL, 1UL + 6UL, 7UL, 3UL + 7UL, 6UL, 3UL ] + ) + ) + +[] +let ``Level bfs 8 node grid start 0`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level grid8graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node grid start 0`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent grid8graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 0UL + Some 1UL + Some 2UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 8 node grid start 7`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 7UL + let result = Graph.BFS.bfs_level grid8graph start + + Assert.Equal( + Ok + [ Some 4UL + Some 3UL + Some 2UL + Some 1UL + Some 3UL + Some 2UL + Some 1UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node grid start 7`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 7UL + let result = Graph.BFS.bfs_parent grid8graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 7UL + Some 5UL + Some 6UL + Some 7UL + Some 7UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 8 node grid start 4`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_level grid8graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 8 node grid start 4`` () = + let n = uint64 grid8graph.ncols + let start = singleStart n 4UL + let result = Graph.BFS.bfs_parent grid8graph start + + Assert.Equal( + Ok + [ Some 4UL + Some 0UL + Some 1UL + Some 2UL + Some 4UL + Some 4UL + Some 5UL + Some 6UL ], + Result.map (unsafes n) result + ) + +// ============== 10 nodes random ============== + +let private random10graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 10UL, + 10UL, + [ 0UL, 1UL, 4UL + 1UL, 0UL, 4UL + 0UL, 5UL, 2UL + 5UL, 0UL, 2UL + 1UL, 2UL, 3UL + 2UL, 1UL, 3UL + 1UL, 6UL, 5UL + 6UL, 1UL, 5UL + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + 2UL, 7UL, 4UL + 7UL, 2UL, 4UL + 3UL, 4UL, 2UL + 4UL, 3UL, 2UL + 3UL, 8UL, 6UL + 8UL, 3UL, 6UL + 4UL, 9UL, 3UL + 9UL, 4UL, 3UL + 5UL, 6UL, 1UL + 6UL, 5UL, 1UL + 6UL, 7UL, 2UL + 7UL, 6UL, 2UL + 7UL, 8UL, 1UL + 8UL, 7UL, 1UL + 8UL, 9UL, 4UL + 9UL, 8UL, 4UL ] + ) + ) + +[] +let ``Level bfs 10 node random start 0`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level random10graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node random start 0`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent random10graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 10 node random start 9`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 9UL + let result = Graph.BFS.bfs_level random10graph start + + Assert.Equal( + Ok + [ Some 5UL + Some 4UL + Some 3UL + Some 2UL + Some 1UL + Some 4UL + Some 3UL + Some 2UL + Some 1UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node random start 9`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 9UL + let result = Graph.BFS.bfs_parent random10graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 9UL + Some 6UL + Some 7UL + Some 8UL + Some 9UL + Some 9UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 10 node random start 5`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_level random10graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node random start 5`` () = + let n = uint64 random10graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_parent random10graph start + + Assert.Equal( + Ok + [ Some 5UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 5UL + Some 5UL + Some 6UL + Some 7UL + Some 8UL ], + Result.map (unsafes n) result + ) + +// ============== 12 nodes big ============== + +let private big12graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 12UL, + 12UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 11UL, 1UL + 11UL, 1UL, 1UL + 0UL, 11UL, 1UL + 11UL, 0UL, 1UL + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + 3UL, 4UL, 1UL + 4UL, 3UL, 1UL + 2UL, 4UL, 1UL + 4UL, 2UL, 1UL + 5UL, 6UL, 1UL + 6UL, 5UL, 1UL + 6UL, 7UL, 1UL + 7UL, 6UL, 1UL + 5UL, 7UL, 1UL + 7UL, 5UL, 1UL + 8UL, 9UL, 1UL + 9UL, 8UL, 1UL + 9UL, 10UL, 1UL + 10UL, 9UL, 1UL + 8UL, 10UL, 1UL + 10UL, 8UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 11UL, 4UL, 2UL + 4UL, 11UL, 2UL + 10UL, 5UL, 2UL + 5UL, 10UL, 2UL + 8UL, 7UL, 2UL + 7UL, 8UL, 2UL + 10UL, 11UL, 3UL + 11UL, 10UL, 3UL + 5UL, 4UL, 3UL + 4UL, 5UL, 3UL ] + ) + ) + +[] +let ``Level bfs 12 node big start 0`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level big12graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 2UL + Some 3UL + Some 4UL + Some 4UL + Some 3UL + Some 3UL + Some 2UL + Some 1UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 12 node big start 0`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent big12graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 0UL + Some 1UL + Some 2UL + Some 11UL + Some 4UL + Some 5UL + Some 5UL + Some 10UL + Some 10UL + Some 11UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 12 node big start 11`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 11UL + let result = Graph.BFS.bfs_level big12graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 1UL + Some 2UL + Some 2UL + Some 1UL + Some 2UL + Some 3UL + Some 3UL + Some 2UL + Some 2UL + Some 1UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 12 node big start 11`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 11UL + let result = Graph.BFS.bfs_parent big12graph start + + Assert.Equal( + Ok + [ Some 11UL + Some 11UL + Some 1UL + Some 4UL + Some 11UL + Some 4UL + Some 5UL + Some 5UL + Some 10UL + Some 10UL + Some 11UL + Some 11UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 12 node big start 6`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 6UL + let result = Graph.BFS.bfs_level big12graph start + + Assert.Equal( + Ok + [ Some 4UL + Some 4UL + Some 3UL + Some 3UL + Some 2UL + Some 1UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 2UL + Some 3UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 12 node big start 6`` () = + let n = uint64 big12graph.ncols + let start = singleStart n 6UL + let result = Graph.BFS.bfs_parent big12graph start + + Assert.Equal( + Ok + [ Some 11UL + Some 2UL + Some 4UL + Some 4UL + Some 5UL + Some 6UL + Some 6UL + Some 6UL + Some 7UL + Some 8UL + Some 5UL + Some 4UL ], + Result.map (unsafes n) result + ) + +// ============== 10 nodes complex line ============== + +let private complexLine10graph = + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + 10UL, + 10UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + 3UL, 4UL, 3UL + 4UL, 3UL, 3UL + 4UL, 5UL, 1UL + 5UL, 4UL, 1UL + 5UL, 6UL, 1UL + 6UL, 5UL, 1UL + 6UL, 7UL, 2UL + 7UL, 6UL, 2UL + 7UL, 8UL, 1UL + 8UL, 7UL, 1UL + 8UL, 9UL, 1UL + 9UL, 8UL, 1UL ] + ) + ) + +[] +let ``Level bfs 10 node complex line start 0`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_level complexLine10graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL + Some 6UL + Some 7UL + Some 8UL + Some 9UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node complex line start 0`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 0UL + let result = Graph.BFS.bfs_parent complexLine10graph start + + Assert.Equal( + Ok + [ Some 0UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL + Some 6UL + Some 7UL + Some 8UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 10 node complex line start 9`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 9UL + let result = Graph.BFS.bfs_level complexLine10graph start + + Assert.Equal( + Ok + [ Some 9UL + Some 8UL + Some 7UL + Some 6UL + Some 5UL + Some 4UL + Some 3UL + Some 2UL + Some 1UL + Some 0UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node complex line start 9`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 9UL + let result = Graph.BFS.bfs_parent complexLine10graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL + Some 6UL + Some 7UL + Some 8UL + Some 9UL + Some 9UL ], + Result.map (unsafes n) result + ) + +[] +let ``Level bfs 10 node complex line start 5`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_level complexLine10graph start + + Assert.Equal( + Ok + [ Some 5UL + Some 4UL + Some 3UL + Some 2UL + Some 1UL + Some 0UL + Some 1UL + Some 2UL + Some 3UL + Some 4UL ], + Result.map (unsafes n) result + ) + +[] +let ``Parent bfs 10 node complex line start 5`` () = + let n = uint64 complexLine10graph.ncols + let start = singleStart n 5UL + let result = Graph.BFS.bfs_parent complexLine10graph start + + Assert.Equal( + Ok + [ Some 1UL + Some 2UL + Some 3UL + Some 4UL + Some 5UL + Some 5UL + Some 5UL + Some 6UL + Some 7UL + Some 8UL ], + Result.map (unsafes n) result + ) diff --git a/QuadTree.Tests/Tests.LinearAlgebra.fs b/QuadTree.Tests/Tests.LinearAlgebra.fs index 3bde7b3..c114e8d 100644 --- a/QuadTree.Tests/Tests.LinearAlgebra.fs +++ b/QuadTree.Tests/Tests.LinearAlgebra.fs @@ -346,6 +346,55 @@ let ``Simple vxmi_values. 4 * (4x3).`` () = Assert.Equal(expected, actual) +[] +let ``vxmi_values 3x3 line graph start 0. BFS semantics`` () = + // 3-node line graph (3x3 stored as 4x4): + // N 1 N D + // 1 N 1 D + // N 1 N D + // D D D D + let m = + let tree = + Matrix.qtree.Node( + Matrix.qtree.Node(leaf_n (), leaf_v 1UL, leaf_v 1UL, leaf_n ()), + Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_v 1UL, leaf_d ()), + Matrix.qtree.Node(leaf_n (), leaf_v 1UL, leaf_d (), leaf_d ()), + Matrix.qtree.Node(leaf_n (), leaf_d (), leaf_d (), leaf_d ()) + ) + + let store = Matrix.Storage(4UL, tree) + SparseMatrix(3UL, 3UL, 4UL, store) + + // frontier = start 0 mapped to level 0: + // [0, N, N, D] = Node(Node(0, N), Node(N, D)) + let f = + let tree = + Vector.btree.Node(Vector.btree.Node(vleaf_v 0UL, vleaf_n ()), Vector.btree.Node(vleaf_n (), vleaf_d ())) + + let store = Vector.Storage(4UL, tree) + SparseVector(3UL, 1UL, store) + + let op_add x y = + match (x, y) with + | Some(v), _ + | _, Some(v) -> Some(v) + | _ -> None + + let op_mult (_, vp) (_, _, _) = Some(vp + 1UL) + + let expected = + // result = [N, 1, N, D] = Node(Node(N, 1), Node(N, D)) + let tree = + Vector.btree.Node(Vector.btree.Node(vleaf_n (), vleaf_v 1UL), Vector.btree.Node(vleaf_n (), vleaf_d ())) + + let store = Vector.Storage(4UL, tree) + Ok(SparseVector(3UL, 1UL, store)) + + let actual = LinearAlgebra.vxmi_values op_add op_mult f m + + Assert.Equal(expected, actual) + + [] let ``Simple mxm`` () = // 222D diff --git a/QuadTree.Tests/Tests.Boruvka.fs b/QuadTree.Tests/Tests.MST.fs similarity index 76% rename from QuadTree.Tests/Tests.Boruvka.fs rename to QuadTree.Tests/Tests.MST.fs index 6f2e2a0..4d7052f 100644 --- a/QuadTree.Tests/Tests.Boruvka.fs +++ b/QuadTree.Tests/Tests.MST.fs @@ -1,11 +1,7 @@ module Graph.Boruvka.Tests -open System open Xunit - open Matrix -open Vector -open Common let checkResult name actual expected = match actual with @@ -20,11 +16,11 @@ let checkResult name actual expected = | _ -> None) Assert.Equal(expected, actual) - | x -> Assert.Fail(sprintf "Boruvka failed: %A" x) + | x -> Assert.Fail(sprintf $"MST {name} failed: {x}") -[] -let ``Boruvka MST 2 nodes.`` () = +// ============== Shared test data ============== +let private ``test 2 nodes`` () = let graph = let clist = Matrix.CoordinateList( @@ -35,22 +31,9 @@ let ``Boruvka MST 2 nodes.`` () = Matrix.fromCoordinateList clist - let expected = - let clist = - Matrix.CoordinateList( - 2UL, - 2UL, - [ 0UL, 1UL, 5UL; 1UL, 0UL, 5UL ] - ) - - Matrix.fromCoordinateList clist |> Ok - - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST 3 nodes line.`` () = + graph, Ok graph +let private ``test 3 nodes line`` () = let graph = let clist = Matrix.CoordinateList( @@ -64,26 +47,9 @@ let ``Boruvka MST 3 nodes line.`` () = Matrix.fromCoordinateList clist - let expected = - let clist = - Matrix.CoordinateList( - 3UL, - 3UL, - [ 0UL, 1UL, 1UL - 1UL, 0UL, 1UL - 1UL, 2UL, 2UL - 2UL, 1UL, 2UL ] - ) - - Matrix.fromCoordinateList clist |> Ok - - checkResult (Graph.Boruvka.mst graph) expected - - - -[] -let ``Boruvka MST 4 nodes line.`` () = + graph, Ok graph +let private ``test 4 nodes line`` () = let graph = let clist = Matrix.CoordinateList( @@ -99,27 +65,9 @@ let ``Boruvka MST 4 nodes line.`` () = Matrix.fromCoordinateList clist - let expected = - let clist = - Matrix.CoordinateList( - 4UL, - 4UL, - [ 0UL, 1UL, 1UL - 1UL, 0UL, 1UL - 1UL, 2UL, 2UL - 2UL, 1UL, 2UL - 2UL, 3UL, 3UL - 3UL, 2UL, 3UL ] - ) - - Matrix.fromCoordinateList clist |> Ok - - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST 5 nodes line.`` () = + graph, Ok graph +let private ``test 5 nodes line`` () = let graph = let clist = Matrix.CoordinateList( @@ -137,29 +85,9 @@ let ``Boruvka MST 5 nodes line.`` () = Matrix.fromCoordinateList clist - let expected = - let clist = - Matrix.CoordinateList( - 5UL, - 5UL, - [ 0UL, 1UL, 1UL - 1UL, 0UL, 1UL - 1UL, 2UL, 2UL - 2UL, 1UL, 2UL - 2UL, 3UL, 3UL - 3UL, 2UL, 3UL - 3UL, 4UL, 4UL - 4UL, 3UL, 4UL ] - ) - - Matrix.fromCoordinateList clist |> Ok - - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST 5 nodes star.`` () = + graph, Ok graph +let private ``test 5 nodes star`` () = let graph = let clist = Matrix.CoordinateList( @@ -177,29 +105,51 @@ let ``Boruvka MST 5 nodes star.`` () = Matrix.fromCoordinateList clist + graph, Ok graph + +let private ``test square`` () = + let graph = + let clist = + Matrix.CoordinateList( + 4UL, + 4UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + + 1UL, 2UL, 2UL + 2UL, 1UL, 2UL + + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + + 3UL, 0UL, 2UL + 0UL, 3UL, 2UL ] + ) + + Matrix.fromCoordinateList clist + let expected = let clist = Matrix.CoordinateList( - 5UL, - 5UL, - [ 0UL, 1UL, 5UL - 1UL, 0UL, 5UL - 0UL, 2UL, 4UL - 2UL, 0UL, 4UL - 0UL, 3UL, 3UL - 3UL, 0UL, 3UL - 0UL, 4UL, 2UL - 4UL, 0UL, 2UL ] + 4UL, + 4UL, + [ 0UL, 1UL, 1UL + 1UL, 0UL, 1UL + + 2UL, 3UL, 1UL + 3UL, 2UL, 1UL + + 3UL, 0UL, 2UL + 0UL, 3UL, 2UL ] ) Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected + graph, expected -[] -let ``Boruvka MST 5 nodes complete.`` () = +let private ``test 5 nodes complete`` () = let graph = let clist = Matrix.CoordinateList( @@ -246,12 +196,9 @@ let ``Boruvka MST 5 nodes complete.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST two components.`` () = + graph, expected +let private ``test two components`` () = let graph = let clist = Matrix.CoordinateList( @@ -293,12 +240,9 @@ let ``Boruvka MST two components.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST cycle graph 6 nodes.`` () = + graph, expected +let private ``test cycle graph 6 nodes`` () = let graph = let clist = Matrix.CoordinateList( @@ -339,11 +283,9 @@ let ``Boruvka MST cycle graph 6 nodes.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - -[] -let ``Boruvka MST complete bipartite K3,3.`` () = + graph, expected +let private ``test complete bipartite K3,3`` () = let graph = let clist = Matrix.CoordinateList( @@ -400,11 +342,9 @@ let ``Boruvka MST complete bipartite K3,3.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - -[] -let ``Boruvka MST random weights.`` () = + graph, expected +let private ``test random weights`` () = let graph = let clist = Matrix.CoordinateList( @@ -412,28 +352,40 @@ let ``Boruvka MST random weights.`` () = 8UL, [ 0UL, 1UL, 7UL 1UL, 0UL, 7UL + 0UL, 2UL, 5UL 2UL, 0UL, 5UL + 0UL, 3UL, 9UL 3UL, 0UL, 9UL + 1UL, 2UL, 3UL 2UL, 1UL, 3UL + 1UL, 3UL, 4UL 3UL, 1UL, 4UL + 2UL, 3UL, 2UL 3UL, 2UL, 2UL + 4UL, 5UL, 1UL 5UL, 4UL, 1UL + 4UL, 6UL, 6UL 6UL, 4UL, 6UL + 4UL, 7UL, 8UL 7UL, 4UL, 8UL + 5UL, 6UL, 3UL 6UL, 5UL, 3UL + 5UL, 7UL, 5UL 7UL, 5UL, 5UL + 6UL, 7UL, 2UL 7UL, 6UL, 2UL + // Connect two components 3UL, 4UL, 10UL 4UL, 3UL, 10UL ] @@ -448,29 +400,31 @@ let ``Boruvka MST random weights.`` () = 8UL, [ 0UL, 2UL, 5UL 2UL, 0UL, 5UL + 1UL, 2UL, 3UL 2UL, 1UL, 3UL + 2UL, 3UL, 2UL 3UL, 2UL, 2UL - 1UL, 3UL, 4UL - 3UL, 1UL, 4UL + + 4UL, 3UL, 10UL + 3UL, 4UL, 10UL + 4UL, 5UL, 1UL 5UL, 4UL, 1UL + 5UL, 6UL, 3UL 6UL, 5UL, 3UL + 6UL, 7UL, 2UL - 7UL, 6UL, 2UL - 3UL, 4UL, 10UL - 4UL, 3UL, 10UL ] + 7UL, 6UL, 2UL ] ) Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - -[] -let ``Boruvka MST 8 nodes grid.`` () = + graph, expected +let private ``test 8 nodes grid`` () = let graph = let clist = Matrix.CoordinateList( @@ -527,11 +481,9 @@ let ``Boruvka MST 8 nodes grid.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - -[] -let ``Boruvka MST 10 nodes random.`` () = + graph, expected +let private ``test 10 nodes random`` () = let graph = let clist = Matrix.CoordinateList( @@ -539,28 +491,40 @@ let ``Boruvka MST 10 nodes random.`` () = 10UL, [ 0UL, 1UL, 4UL 1UL, 0UL, 4UL + 0UL, 5UL, 2UL 5UL, 0UL, 2UL + 1UL, 2UL, 3UL 2UL, 1UL, 3UL + 1UL, 6UL, 5UL 6UL, 1UL, 5UL + 2UL, 3UL, 1UL 3UL, 2UL, 1UL + 2UL, 7UL, 4UL 7UL, 2UL, 4UL + 3UL, 4UL, 2UL 4UL, 3UL, 2UL + 3UL, 8UL, 6UL 8UL, 3UL, 6UL + 4UL, 9UL, 3UL 9UL, 4UL, 3UL + 5UL, 6UL, 1UL 6UL, 5UL, 1UL + 6UL, 7UL, 2UL 7UL, 6UL, 2UL + 7UL, 8UL, 1UL 8UL, 7UL, 1UL + 8UL, 9UL, 4UL 9UL, 8UL, 4UL ] ) @@ -574,40 +538,37 @@ let ``Boruvka MST 10 nodes random.`` () = 10UL, [ 0UL, 1UL, 4UL 1UL, 0UL, 4UL - 0UL, 5UL, 2UL - 5UL, 0UL, 2UL + 1UL, 2UL, 3UL 2UL, 1UL, 3UL - 1UL, 6UL, 5UL - 6UL, 1UL, 5UL - 2UL, 3UL, 1UL + 3UL, 2UL, 1UL - 2UL, 7UL, 4UL - 7UL, 2UL, 4UL + 2UL, 3UL, 1UL + 3UL, 4UL, 2UL 4UL, 3UL, 2UL - 3UL, 8UL, 6UL - 8UL, 3UL, 6UL - 4UL, 9UL, 3UL + 9UL, 4UL, 3UL - 5UL, 6UL, 1UL + 4UL, 9UL, 3UL + + 0UL, 5UL, 2UL + 5UL, 0UL, 2UL + 6UL, 5UL, 1UL - 6UL, 7UL, 2UL + 5UL, 6UL, 1UL + 7UL, 6UL, 2UL + 6UL, 7UL, 2UL + 7UL, 8UL, 1UL - 8UL, 7UL, 1UL - 8UL, 9UL, 4UL - 9UL, 8UL, 4UL ] + 8UL, 7UL, 1UL ] ) Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST simple triangle.`` () = + graph, expected +let private ``test simple triangle`` () = let graph = let clist = Matrix.CoordinateList( @@ -620,14 +581,11 @@ let ``Boruvka MST simple triangle.`` () = 2UL, 0UL, 1UL 1UL, 2UL, 1UL - 2UL, 1UL, 1UL - - ] + 2UL, 1UL, 1UL ] ) Matrix.fromCoordinateList clist - let expected = let clist = Matrix.CoordinateList( @@ -642,12 +600,9 @@ let ``Boruvka MST simple triangle.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST simple square.`` () = + graph, expected +let private ``test simple square`` () = let graph = let clist = Matrix.CoordinateList( @@ -663,14 +618,11 @@ let ``Boruvka MST simple square.`` () = 3UL, 2UL, 1UL 0UL, 3UL, 1UL - 3UL, 0UL, 1UL - - ] + 3UL, 0UL, 1UL ] ) Matrix.fromCoordinateList clist - let expected = let clist = Matrix.CoordinateList( @@ -688,14 +640,9 @@ let ``Boruvka MST simple square.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - - - -[] -let ``Boruvka MST simple square in two steps.`` () = + graph, expected +let private ``test simple square in two steps`` () = let graph = let clist = Matrix.CoordinateList( @@ -711,14 +658,11 @@ let ``Boruvka MST simple square in two steps.`` () = 3UL, 2UL, 2UL 0UL, 3UL, 1UL - 3UL, 0UL, 1UL - - ] + 3UL, 0UL, 1UL ] ) Matrix.fromCoordinateList clist - let expected = let clist = Matrix.CoordinateList( @@ -736,14 +680,9 @@ let ``Boruvka MST simple square in two steps.`` () = Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - - - -[] -let ``Boruvka MST.`` () = + graph, expected +let private ``test 7 nodes`` () = let graph = let clist = Matrix.CoordinateList( @@ -785,7 +724,6 @@ let ``Boruvka MST.`` () = Matrix.fromCoordinateList clist - let expected = let clist = Matrix.CoordinateList( @@ -807,19 +745,14 @@ let ``Boruvka MST.`` () = 5UL, 4UL, 6UL 6UL, 3UL, 8UL - 3UL, 6UL, 8UL - - ] + 3UL, 6UL, 8UL ] ) Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST big.`` () = + graph, expected +let private ``test big`` () = let graph = let clist = Matrix.CoordinateList( @@ -877,14 +810,11 @@ let ``Boruvka MST big.`` () = 11UL, 10UL, 3UL 5UL, 4UL, 3UL - 4UL, 5UL, 3UL - - ] + 4UL, 5UL, 3UL ] ) Matrix.fromCoordinateList clist - let expected = let clist = Matrix.CoordinateList( @@ -921,19 +851,14 @@ let ``Boruvka MST big.`` () = 10UL, 5UL, 2UL 4UL, 5UL, 3UL - 5UL, 4UL, 3UL - - ] + 5UL, 4UL, 3UL ] ) Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected - - -[] -let ``Boruvka MST complex line.`` () = + graph, expected +let private ``test complex line`` () = let graph = let clist = Matrix.CoordinateList( @@ -964,16 +889,15 @@ let ``Boruvka MST complex line.`` () = 8UL, 7UL, 1UL 8UL, 9UL, 1UL - 9UL, 8UL, 1UL - - - ] + 9UL, 8UL, 1UL ] ) Matrix.fromCoordinateList clist + graph, Ok graph - let expected = +let private ``test complex line 2`` () = + let graph = let clist = Matrix.CoordinateList( 10UL, @@ -987,110 +911,254 @@ let ``Boruvka MST complex line.`` () = 2UL, 3UL, 1UL 3UL, 2UL, 1UL - 3UL, 4UL, 3UL - 4UL, 3UL, 3UL + 3UL, 9UL, 3UL + 9UL, 3UL, 3UL - 4UL, 5UL, 1UL - 5UL, 4UL, 1UL + 9UL, 8UL, 1UL + 8UL, 9UL, 1UL - 5UL, 6UL, 1UL - 6UL, 5UL, 1UL + 8UL, 7UL, 1UL + 7UL, 8UL, 1UL 6UL, 7UL, 2UL 7UL, 6UL, 2UL - 7UL, 8UL, 1UL - 8UL, 7UL, 1UL + 5UL, 6UL, 1UL + 6UL, 5UL, 1UL - 8UL, 9UL, 1UL - 9UL, 8UL, 1UL + 5UL, 4UL, 1UL + 4UL, 5UL, 1UL ] + ) + Matrix.fromCoordinateList clist - ] - ) + graph, Ok graph - Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected +// ============== Tests ============== +[] +let ``Boruvka MST 2 nodes.`` () = + let graph, expected = ``test 2 nodes`` () + checkResult "Boruvka 2 nodes" (Graph.Boruvka.mst graph) expected [] -let ``Boruvka MST complex line 2.`` () = +let ``Maggs-Plotkin MST 2 nodes.`` () = + let graph, expected = ``test 2 nodes`` () + checkResult "Maggs-Plotkin 2 nodes" (Graph.Maggs_Plotkin_MST.mst graph) expected - let graph = - let clist = - Matrix.CoordinateList( - 10UL, - 10UL, - [ 0UL, 1UL, 1UL - 1UL, 0UL, 1UL - 1UL, 2UL, 2UL - 2UL, 1UL, 2UL +[] +let ``Boruvka MST 3 nodes line.`` () = + let graph, expected = ``test 3 nodes line`` () + checkResult "Boruvka 3 nodes line" (Graph.Boruvka.mst graph) expected - 2UL, 3UL, 1UL - 3UL, 2UL, 1UL +[] +let ``Maggs-Plotkin MST 3 nodes line.`` () = + let graph, expected = ``test 3 nodes line`` () + let result = Graph.Maggs_Plotkin_MST.mst graph + checkResult "Maggs-Plotkin 3 nodes line" result expected - 3UL, 9UL, 3UL - 9UL, 3UL, 3UL - 9UL, 8UL, 1UL - 8UL, 9UL, 1UL +[] +let ``Boruvka MST 4 nodes line.`` () = + let graph, expected = ``test 4 nodes line`` () + checkResult "Boruvka 4 nodes line" (Graph.Boruvka.mst graph) expected - 8UL, 7UL, 1UL - 7UL, 8UL, 1UL +[] +let ``Maggs-Plotkin MST 4 nodes line.`` () = + let graph, expected = ``test 4 nodes line`` () + checkResult "Maggs-Plotkin 4 nodes line" (Graph.Maggs_Plotkin_MST.mst graph) expected - 6UL, 7UL, 2UL - 7UL, 6UL, 2UL - 5UL, 6UL, 1UL - 6UL, 5UL, 1UL +[] +let ``Boruvka MST square.`` () = + let graph, expected = ``test square`` () + checkResult "Boruvka 4 nodes line" (Graph.Boruvka.mst graph) expected - 5UL, 4UL, 1UL - 4UL, 5UL, 1UL +[] +let ``Maggs-Plotkin MST square.`` () = + let graph, expected = ``test square`` () + let result = Graph.Maggs_Plotkin_MST.mst graph + checkResult "Maggs-Plotkin 4 nodes line" result expected - ] - ) +[] +let ``Boruvka MST 5 nodes line.`` () = + let graph, expected = ``test 5 nodes line`` () + checkResult "Boruvka 5 nodes line" (Graph.Boruvka.mst graph) expected - Matrix.fromCoordinateList clist +[] +let ``Maggs-Plotkin MST 5 nodes line.`` () = + let graph, expected = ``test 5 nodes line`` () + checkResult "Maggs-Plotkin 5 nodes line" (Graph.Maggs_Plotkin_MST.mst graph) expected - let expected = - let clist = - Matrix.CoordinateList( - 10UL, - 10UL, - [ 0UL, 1UL, 1UL - 1UL, 0UL, 1UL +[] +let ``Boruvka MST 5 nodes star.`` () = + let graph, expected = ``test 5 nodes star`` () + checkResult "Boruvka 5 nodes star" (Graph.Boruvka.mst graph) expected - 1UL, 2UL, 2UL - 2UL, 1UL, 2UL +[] +let ``Maggs-Plotkin MST 5 nodes star.`` () = + let graph, expected = ``test 5 nodes star`` () + checkResult "Maggs-Plotkin 5 nodes star" (Graph.Maggs_Plotkin_MST.mst graph) expected - 2UL, 3UL, 1UL - 3UL, 2UL, 1UL - 3UL, 9UL, 3UL - 9UL, 3UL, 3UL +[] +let ``Boruvka MST 5 nodes complete.`` () = + let graph, expected = ``test 5 nodes complete`` () + checkResult "Boruvka 5 nodes complete" (Graph.Boruvka.mst graph) expected - 9UL, 8UL, 1UL - 8UL, 9UL, 1UL +[] +let ``Maggs-Plotkin MST 5 nodes complete.`` () = + let graph, expected = ``test 5 nodes complete`` () + checkResult "Maggs-Plotkin 5 nodes complete" (Graph.Maggs_Plotkin_MST.mst graph) expected - 8UL, 7UL, 1UL - 7UL, 8UL, 1UL - 6UL, 7UL, 2UL - 7UL, 6UL, 2UL +[] +let ``Boruvka MST two components.`` () = + let graph, expected = ``test two components`` () + checkResult "Boruvka two components" (Graph.Boruvka.mst graph) expected - 5UL, 6UL, 1UL - 6UL, 5UL, 1UL +[] +let ``Maggs-Plotkin MST two components.`` () = + let graph, expected = ``test two components`` () + checkResult "Maggs-Plotkin two components" (Graph.Maggs_Plotkin_MST.mst graph) expected - 5UL, 4UL, 1UL - 4UL, 5UL, 1UL - ] - ) +[] +let ``Boruvka MST cycle graph 6 nodes.`` () = + let graph, expected = ``test cycle graph 6 nodes`` () + checkResult "Boruvka cycle graph 6 nodes" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST cycle graph 6 nodes.`` () = + let graph, expected = ``test cycle graph 6 nodes`` () + checkResult "Maggs-Plotkin cycle graph 6 nodes" (Graph.Maggs_Plotkin_MST.mst graph) expected - Matrix.fromCoordinateList clist |> Ok - checkResult (Graph.Boruvka.mst graph) expected +[] +let ``Boruvka MST complete bipartite K3,3.`` () = + let graph, expected = ``test complete bipartite K3,3`` () + checkResult "Boruvka complete bipartite K3,3" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST complete bipartite K3,3.`` () = + let graph, expected = ``test complete bipartite K3,3`` () + checkResult "Maggs-Plotkin complete bipartite K3,3" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST random weights.`` () = + let graph, expected = ``test random weights`` () + let result = (Graph.Boruvka.mst graph) + checkResult "Boruvka random weights" result expected + +[] +let ``Maggs-Plotkin MST random weights.`` () = + let graph, expected = ``test random weights`` () + let result = Graph.Maggs_Plotkin_MST.mst graph + checkResult "Maggs-Plotkin random weights" result expected + + +[] +let ``Boruvka MST 8 nodes grid.`` () = + let graph, expected = ``test 8 nodes grid`` () + checkResult "Boruvka 8 nodes grid" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST 8 nodes grid.`` () = + let graph, expected = ``test 8 nodes grid`` () + checkResult "Maggs-Plotkin 8 nodes grid" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST 10 nodes random.`` () = + let graph, expected = ``test 10 nodes random`` () + checkResult "Boruvka 10 nodes random" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST 10 nodes random.`` () = + let graph, expected = ``test 10 nodes random`` () + let result = Graph.Maggs_Plotkin_MST.mst graph + checkResult "Maggs-Plotkin 10 nodes random" result expected + + +[] +let ``Boruvka MST simple triangle.`` () = + let graph, expected = ``test simple triangle`` () + checkResult "Boruvka simple triangle" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST simple triangle.`` () = + let graph, expected = ``test simple triangle`` () + checkResult "Maggs-Plotkin simple triangle" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST simple square.`` () = + let graph, expected = ``test simple square`` () + checkResult "Boruvka simple square" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST simple square.`` () = + let graph, expected = ``test simple square`` () + checkResult "Maggs-Plotkin simple square" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST simple square in two steps.`` () = + let graph, expected = ``test simple square in two steps`` () + checkResult "Boruvka simple square in two steps" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST simple square in two steps.`` () = + let graph, expected = ``test simple square in two steps`` () + let result = Graph.Maggs_Plotkin_MST.mst graph + checkResult "Maggs-Plotkin simple square in two steps" result expected + + +[] +let ``Boruvka MST.`` () = + let graph, expected = ``test 7 nodes`` () + checkResult "Boruvka" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST.`` () = + let graph, expected = ``test 7 nodes`` () + checkResult "Maggs-Plotkin" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST big.`` () = + let graph, expected = ``test big`` () + let result = (Graph.Boruvka.mst graph) + checkResult "Boruvka big" result expected + +[] +let ``Maggs-Plotkin MST big.`` () = + let graph, expected = ``test big`` () + checkResult "Maggs-Plotkin big" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST complex line.`` () = + let graph, expected = ``test complex line`` () + checkResult "Boruvka complex line" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST complex line.`` () = + let graph, expected = ``test complex line`` () + checkResult "Maggs-Plotkin complex line" (Graph.Maggs_Plotkin_MST.mst graph) expected + + +[] +let ``Boruvka MST complex line 2.`` () = + let graph, expected = ``test complex line 2`` () + checkResult "Boruvka complex line 2" (Graph.Boruvka.mst graph) expected + +[] +let ``Maggs-Plotkin MST complex line 2.`` () = + let graph, expected = ``test complex line 2`` () + checkResult "Maggs-Plotkin complex line 2" (Graph.Maggs_Plotkin_MST.mst graph) expected diff --git a/QuadTree/BFS.fs b/QuadTree/BFS.fs index 0ba2fc5..4cda183 100644 --- a/QuadTree/BFS.fs +++ b/QuadTree/BFS.fs @@ -8,23 +8,20 @@ type Error = | FrontierCalculationProblem of Vector.Error | VisitedCalculationProblem of Vector.Error -let bfs_level graph startVertices = - let rec inner level (frontier: Vector.SparseVector<_>) (visited: Vector.SparseVector<_>) = +let bfs + (op_add: 'c option -> 'c option -> 'c option) + (op_mult: uint64 * 'c -> uint64 * uint64 * 'b -> Option<'c>) + (initVisited: uint64 -> Option<'c> -> Option<'c>) + (graph: Matrix.SparseMatrix<'b>) + (startVertices: Vector.SparseVector<'c>) + = + let initialVisited = Vector.mapi startVertices initVisited + + let rec inner (frontier: Vector.SparseVector<'c>) (visited: Vector.SparseVector<'c>) = if frontier.nvals > 0UL then resultM { let! new_frontier = - LinearAlgebra.vxm - (fun x y -> - match (x, y) with - | Some(v), _ - | _, Some(v) -> Some(v) - | _ -> None) - (fun x y -> - match (x, y) with - | Some(v), Some(_) -> Some(v) - | _ -> None) - frontier - graph + LinearAlgebra.vxmi_values op_add op_mult frontier graph |> Result.mapError NewFrontierCalculationProblem let! frontier = @@ -32,17 +29,44 @@ let bfs_level graph startVertices = |> Result.mapError FrontierCalculationProblem let! visited = - Vector.map2 visited new_frontier (fun x y -> - match (x, y) with - | Some(_), _ -> x - | None, Some(_) -> Some(level) - | _ -> None) + Vector.map2 visited frontier (fun oldVal newVal -> + match oldVal with + | Some _ -> oldVal + | None -> newVal) |> Result.mapError VisitedCalculationProblem - return! inner (level + 1UL) frontier visited + return! inner frontier visited } else Ok visited - let initialVisited = Vector.map startVertices (Option.map (fun x -> 0UL)) - inner 1UL startVertices initialVisited + inner startVertices initialVisited + +let bfs_level graph startVertices = + let op_add x y = + match (x, y) with + | Some(v), _ + | _, Some(v) -> Some(v) + | _ -> None + + let op_mult (_, vp) (_, _, _) = Some(vp + 1UL) + + let initVisited _ v = v |> Option.map (fun _ -> 0UL) + + let frontier0 = + Vector.mapi startVertices (fun _ v -> v |> Option.map (fun _ -> 0UL)) + + bfs op_add op_mult initVisited graph frontier0 + +let bfs_parent graph startVertices = + let op_add x y = + match (x, y) with + | Some(v), _ + | _, Some(v) -> Some(v) + | _ -> None + + let op_mult (vi, _) (_, _, _) = Some(uint64 vi) + + let initVisited i v = v |> Option.map (fun _ -> uint64 i) + + bfs op_add op_mult initVisited graph startVertices diff --git a/QuadTree/Boruvka.fs b/QuadTree/Boruvka.fs index c0ed119..b3bf95c 100644 --- a/QuadTree/Boruvka.fs +++ b/QuadTree/Boruvka.fs @@ -82,6 +82,31 @@ let mst (graph: Matrix.SparseMatrix<_>) = Vector.scatter (Vector.empty length) edges parent op_min |> Result.mapError CEdgesCalculationProblem + // Suppress mutual 2-cycles between components (LAGraph approach). + // When components p and q select each other, keep only the larger root's edge. + let! cedges_dst = + Vector.map2i cedges cedges (fun _ cv _ -> + match cv with + | Some(w, dst) -> Some(uint64 dst * 1UL) + | None -> None) + |> Result.mapError IndexInnerCalculationProblem + + let dst_comp = Vector.gather parent cedges_dst + let back_check = Vector.gather dst_comp dst_comp + + let! cedges = + Vector.map2i cedges back_check (fun i cv bc -> + match cv with + | Some(w, dst) -> + match bc with + | Some bc_val -> + match Vector.unsafeGet parent i, Vector.unsafeGet dst_comp i with + | Some p, Some cd when cd <> p && bc_val = p && p < cd -> None + | _ -> Some(w, dst) + | None -> Some(w, dst) + | None -> None) + |> Result.mapError IndexInnerCalculationProblem + // Propagate component's cheapest edge to all its vertices // Each vertex gets its component's edge let t = Vector.gather cedges parent diff --git a/QuadTree/LinearAlgebra.fs b/QuadTree/LinearAlgebra.fs index 7405e02..a57daca 100644 --- a/QuadTree/LinearAlgebra.fs +++ b/QuadTree/LinearAlgebra.fs @@ -36,9 +36,9 @@ let vxm op_add op_mult (vector: Vector.SparseVector<'a>) (matrix: Matrix.SparseM let v3 = Vector.SparseVector(data_length, nvals3, (Vector.Storage(new_size, t3))) let v4 = Vector.SparseVector(data_length, nvals4, (Vector.Storage(new_size, t4))) - let vAdd v1 (v2: Vector.SparseVector<_>) = - match v2.storage.data with - | Vector.Leaf(Dummy) -> Ok(v1) + let vAdd (v1: Vector.SparseVector<_>) (v2: Vector.SparseVector<_>) = + match v1.storage.data, v2.storage.data with + | _, Vector.Leaf(Dummy) -> Ok(v1) | _ -> Vector.map2 v1 v2 op_add let z1 = vAdd v1 v3 @@ -144,9 +144,9 @@ let vxmi_values let v3 = Vector.SparseVector(data_length, nvals3, (Vector.Storage(new_size, t3))) let v4 = Vector.SparseVector(data_length, nvals4, (Vector.Storage(new_size, t4))) - let vAdd v1 (v2: Vector.SparseVector<_>) = - match v2.storage.data with - | Vector.Leaf(Dummy) -> Ok(v1) + let vAdd (v1: Vector.SparseVector<_>) (v2: Vector.SparseVector<_>) = + match v1.storage.data, v2.storage.data with + | _, Vector.Leaf(Dummy) -> Ok(v1) | _ -> Vector.map2 v1 v2 op_add let z1 = vAdd v1 v3 @@ -183,14 +183,16 @@ let vxmi_values colIdx | Vector.btree.Leaf(UserValue(Some(_))), Matrix.qtree.Node(y1, y2, y3, y4) -> _do vector vector y1 y2 y3 y4 + | Vector.btree.Leaf(UserValue(None)), Matrix.qtree.Node(y1, y2, y3, y4) -> _do vector vector y1 y2 y3 y4 | Vector.btree.Node(x1, x2), Matrix.qtree.Leaf(UserValue(Some(_))) -> _do x1 x2 matrix matrix matrix matrix + | Vector.btree.Node(x1, x2), Matrix.qtree.Leaf(UserValue(None)) -> _do x1 x2 matrix matrix matrix matrix | Vector.btree.Node(x1, x2), Matrix.qtree.Node(y1, y2, y3, y4) -> _do x1 x2 y1 y2 y3 y4 - | Vector.btree.Leaf(UserValue(None)), _ - | _, Matrix.qtree.Leaf(UserValue(None)) -> Ok(Vector.btree.Leaf(UserValue(None)), 0UL) - | Vector.btree.Leaf(Dummy), _ | _, Matrix.qtree.Leaf(Dummy) -> Ok(Vector.btree.Leaf(Dummy), 0UL) + | Vector.btree.Leaf(UserValue(None)), _ + | _, Matrix.qtree.Leaf(UserValue(None)) -> Ok(Vector.btree.Leaf(UserValue(None)), 0UL) + if uint64 vector.length = uint64 matrix.nrows then let vector_storage = if uint64 vector.storage.size < uint64 matrix.storage.size then diff --git a/QuadTree/Maggs_Plotkin_MST.fs b/QuadTree/Maggs_Plotkin_MST.fs new file mode 100644 index 0000000..97f311c --- /dev/null +++ b/QuadTree/Maggs_Plotkin_MST.fs @@ -0,0 +1,79 @@ +module Graph.Maggs_Plotkin_MST + +open Common +open Result +open Matrix + + +type Error = + | DiagAdditionProblem of Matrix.Error + | MSTComputationProblem of Matrix.Error + | ClosureComputationProblem of LinearAlgebra.Error + +let mst (graph: Matrix.SparseMatrix<'a>) = + + let diag = + let zero = Unchecked.defaultof<'a> + + Matrix.fromCoordinateList ( + Matrix.CoordinateList( + graph.nrows, + graph.ncols, + [ for i in 0UL .. uint64 graph.nrows - 1UL -> (i * 1UL, i * 1UL, zero) ] + ) + ) + + let _max x y = + match (x, y) with + | Some x, Some y -> max x y |> Some + | _ -> None + + let _min x y = + match (x, y) with + | Some x, Some y -> min x y |> Some + | Some x, None + | None, Some x -> Some x + | _ -> None + + resultM { + let! graph = + Matrix.map2 graph diag (fun x y -> + match y with + | None -> x + | _ -> y) + |> Result.mapError DiagAdditionProblem + + let graph = + Matrix.mapi graph (fun i j v -> + Option.map (fun x -> x, min (uint64 i) (uint64 j), max (uint64 i) (uint64 j)) v) + + let! closure = + let rec compute (matrix: SparseMatrix<_>) = + let nnz = matrix.nvals + + resultM { + + let! step = LinearAlgebra.mxm _min _max matrix matrix + + if nnz = step.nvals && matrix.storage = step.storage then + return step + else + return! compute step + } + + compute graph |> Result.mapError ClosureComputationProblem + + let! mst = + Matrix.map2i graph closure (fun i j x y -> + if uint64 i = uint64 j then + None + elif x = y then + match x with + | Some(w, _, _) -> Some(w) + | _ -> None + else + None) + |> Result.mapError MSTComputationProblem + + return mst + } diff --git a/QuadTree/QuadTree.fsproj b/QuadTree/QuadTree.fsproj index 438678c..abfc6ec 100644 --- a/QuadTree/QuadTree.fsproj +++ b/QuadTree/QuadTree.fsproj @@ -14,6 +14,7 @@ + diff --git a/README.md b/README.md index 8084adb..bd6ec23 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,13 @@ Infrastructure for benchmarking the implemented algorithms is available in the [ ## Implemented Algorithms * Single-source level BFS +* Single-source parent BFS * Single-source shortest path (SSSP) * Triangles counting * Boruvka MSF +* Maggs-Plotkin MSF ## TODO -* [ ] Single-source parent BFS * [ ] Multiple-source level BFS * [ ] Multiple-source parent BFS * [ ] PageRank