diff --git a/doc/weights.xml b/doc/weights.xml
index 6816f17c7..1f98ee26d 100644
--- a/doc/weights.xml
+++ b/doc/weights.xml
@@ -69,4 +69,56 @@ gap> EdgeWeights(g);
]]>
-<#/GAPDoc>
\ No newline at end of file
+<#/GAPDoc>
+
+<#GAPDoc Label="EdgeWeightedDigraphTotalWeight">
+
+
+ An integer, float or rational.
+
+ If digraph is a digraph with edge weights, then this attribute
+ returns the sum of the weights of its edges.
+
+ &MUTABLE_RECOMPUTED_ATTR;
+
+ See .
+ D := EdgeWeightedDigraph([[2], [1], [1, 2]],
+> [[12], [5], [6, 9]]);
+
+gap> EdgeWeightedDigraphTotalWeight(D);
+32]]>
+
+
+<#/GAPDoc>
+
+<#GAPDoc Label="EdgeWeightedDigraphMinimumSpanningTree">
+
+
+ A digraph.
+
+ If digraph is a connected digraph with edge weights, then this
+ attribute returns a digraph which is a minimum spanning tree of
+ digraph.
+
+ A spanning tree of a digraph is a subdigraph with the same
+ vertices but a subset of its edges that form an undirected tree. It is
+ minimum if it has the smallest possible total weight for a
+ spanning tree of that digraph.
+
+ &MUTABLE_RECOMPUTED_ATTR;
+
+ See ,
+ and
+ .
+ D := EdgeWeightedDigraph([[2], [1], [1, 2]],
+> [[12], [5], [6, 9]]);
+
+gap> T := EdgeWeightedDigraphMinimumSpanningTree(D);
+
+gap> EdgeWeights(T);
+[ [ ], [ 5 ], [ 6 ] ]]]>
+
+
+<#/GAPDoc>
diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml
index 8adb9eb49..0baeaf83c 100644
--- a/doc/z-chap5.xml
+++ b/doc/z-chap5.xml
@@ -27,6 +27,8 @@
Edge Weights
<#Include Label="EdgeWeights">
<#Include Label="EdgeWeightedDigraph">
+ <#Include Label="EdgeWeightedDigraphTotalWeight">
+ <#Include Label="EdgeWeightedDigraphMinimumSpanningTree">
Orders
diff --git a/gap/weights.gd b/gap/weights.gd
index 33fed4801..b15f5dd71 100644
--- a/gap/weights.gd
+++ b/gap/weights.gd
@@ -12,6 +12,11 @@
DeclareAttribute("EdgeWeights", IsDigraph);
DeclareGlobalFunction("EdgeWeightedDigraph");
DeclareProperty("IsNegativeEdgeWeightedDigraph", IsDigraph and HasEdgeWeights);
+DeclareAttribute("EdgeWeightedDigraphTotalWeight", IsDigraph and HasEdgeWeights);
# 2. Edge Weight Copies
-DeclareOperation("EdgeWeightsMutableCopy", [IsDigraph and HasEdgeWeights]);
\ No newline at end of file
+DeclareOperation("EdgeWeightsMutableCopy", [IsDigraph and HasEdgeWeights]);
+
+# 3. Minimum Spanning Trees
+DeclareAttribute("EdgeWeightedDigraphMinimumSpanningTree",
+ IsDigraph and HasEdgeWeights);
diff --git a/gap/weights.gi b/gap/weights.gi
index 9ddd888c2..777c55d10 100644
--- a/gap/weights.gi
+++ b/gap/weights.gi
@@ -67,7 +67,7 @@ function(digraph, weights)
return digraph;
end);
-InstallMethod(IsNegativeEdgeWeightedDigraph, "for an edge weighted digraph",
+InstallMethod(IsNegativeEdgeWeightedDigraph, "for a digraph with edge weights",
[IsDigraph and HasEdgeWeights],
function(digraph)
local weights, u, w;
@@ -84,10 +84,91 @@ function(digraph)
return false;
end);
+InstallMethod(EdgeWeightedDigraphTotalWeight,
+"for a digraph with edge weights",
+[IsDigraph and HasEdgeWeights],
+D -> Sum(EdgeWeights(D), Sum));
+
#############################################################################
# 2. Copies of edge weights
#############################################################################
InstallMethod(EdgeWeightsMutableCopy, "for a digraph with edge weights",
[IsDigraph and HasEdgeWeights],
-D -> List(EdgeWeights(D), ShallowCopy));
\ No newline at end of file
+D -> List(EdgeWeights(D), ShallowCopy));
+
+#############################################################################
+# 3. Minimum Spanning Trees
+#############################################################################
+
+InstallMethod(EdgeWeightedDigraphMinimumSpanningTree,
+"for a digraph with edge weights",
+[IsDigraph and HasEdgeWeights],
+function(digraph)
+ local weights, numberOfVertices, edgeList, u, outNeighbours, idx, v, w, mst,
+ mstWeights, partition, i, nrEdges, total, node, x, y, out;
+
+ # check graph is connected
+ if not IsConnectedDigraph(digraph) then
+ ErrorNoReturn("the argument must be a connected digraph,");
+ fi;
+
+ weights := EdgeWeights(digraph);
+
+ # create a list of edges containing u-v
+ # w: the weight of the edge
+ # u: the start vertex
+ # v: the finishing vertex of that edge
+ numberOfVertices := DigraphNrVertices(digraph);
+ edgeList := [];
+ for u in DigraphVertices(digraph) do
+ outNeighbours := OutNeighboursOfVertex(digraph, u);
+ for idx in [1 .. Size(outNeighbours)] do
+ v := outNeighbours[idx]; # the out neighbour
+ w := weights[u][idx]; # the weight to the out neighbour
+ Add(edgeList, [w, u, v]);
+ od;
+ od;
+
+ # sort edge weights by their weight
+ StableSortBy(edgeList, x -> x[1]);
+
+ mst := EmptyPlist(numberOfVertices);
+ mstWeights := EmptyPlist(numberOfVertices);
+
+ partition := PartitionDS(IsPartitionDS, numberOfVertices);
+
+ for v in [1 .. numberOfVertices] do
+ Add(mst, []);
+ Add(mstWeights, []);
+ od;
+
+ i := 1;
+ nrEdges := 0;
+ total := 0;
+ while nrEdges < numberOfVertices - 1 do
+ node := edgeList[i];
+
+ w := node[1];
+ u := node[2];
+ v := node[3];
+
+ i := i + 1;
+
+ x := Representative(partition, u);
+ y := Representative(partition, v);
+
+ # if cycle doesn't exist
+ if x <> y then
+ Add(mst[u], v);
+ Add(mstWeights[u], w);
+ nrEdges := nrEdges + 1;
+ total := total + w;
+ Unite(partition, x, y);
+ fi;
+ od;
+
+ out := EdgeWeightedDigraph(mst, mstWeights);
+ SetEdgeWeightedDigraphTotalWeight(out, total);
+ return out;
+end);
diff --git a/tst/standard/weights.tst b/tst/standard/weights.tst
index dd3c94828..6acc69b38 100644
--- a/tst/standard/weights.tst
+++ b/tst/standard/weights.tst
@@ -18,9 +18,11 @@ gap> DIGRAPHS_StartTest();
gap> d := EdgeWeightedDigraph([[2], []], [[5], []]);
-# create with Digraph
+# create edge weighted digraph
gap> d := EdgeWeightedDigraph(Digraph([[2], []]), [[5], []]);
+gap> EdgeWeightedDigraphTotalWeight(d);
+5
# weight not valid
gap> d := EdgeWeightedDigraph([[2], []], [["a"], []]);
@@ -85,6 +87,56 @@ gap> d := EdgeWeightedDigraph([[2], [1]], [[-5], [10]]);
gap> IsNegativeEdgeWeightedDigraph(d);
true
+# not connnected digraph
+gap> d := EdgeWeightedDigraph([[1], [2]], [[5], [10]]);
+
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+Error, the argument must be a connected digraph,
+
+# digraph with one node
+gap> d := EdgeWeightedDigraph([[]], [[]]);
+
+gap> tree := EdgeWeightedDigraphMinimumSpanningTree(d);
+
+gap> EdgeWeightedDigraphTotalWeight(tree);
+0
+
+# digraph with loop
+gap> d := EdgeWeightedDigraph([[1]], [[5]]);
+
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+
+
+# digraph with cycle
+gap> d := EdgeWeightedDigraph([[2], [3], [1]], [[5], [10], [15]]);
+
+gap> tree := EdgeWeightedDigraphMinimumSpanningTree(d);
+
+gap> EdgeWeightedDigraphTotalWeight(tree);
+15
+
+# digraph with negative edge
+gap> d := EdgeWeightedDigraph([[2], []], [[-5], []]);
+
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+
+
+# digraph with negative cycle
+gap> d := EdgeWeightedDigraph([[2], [3], [1]], [[-5], [-10], [-15]]);
+
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+
+
+# digraph with parallel edges
+gap> d := EdgeWeightedDigraph([[2, 2, 2], [1]], [[10, 5, 15], [7]]);
+
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+
+
+# DIGRAPHS_UnbindVariables
+gap> Unbind(d);
+gap> Unbind(tree);
+
#
gap> DIGRAPHS_StopTest();
gap> STOP_TEST("Digraphs package: standard/weights.tst", 0);
\ No newline at end of file
diff --git a/tst/testinstall.tst b/tst/testinstall.tst
index 6cdc58701..e165c78c2 100644
--- a/tst/testinstall.tst
+++ b/tst/testinstall.tst
@@ -411,10 +411,16 @@ gap> String(D);
"DigraphFromDigraph6String(\"&CECG\")"
gap> String(CycleDigraph(4));
"CycleDigraph(4)"
+
+# Edge-weighted digraphs
gap> d := EdgeWeightedDigraph([[2], [1]], [[5], [10]]);
gap> EdgeWeights(d);
[ [ 5 ], [ 10 ] ]
+gap> EdgeWeightedDigraphTotalWeight(d);
+15
+gap> EdgeWeightedDigraphMinimumSpanningTree(d);
+
# Issue 617: bug in DigraphRemoveEdge, wasn't removing edge labels
gap> D := DigraphByEdges(IsMutableDigraph, [[1, 2], [2, 3], [3, 4], [4, 1], [1, 1]]);;