diff --git a/gap/digraph.gd b/gap/digraph.gd index 46cb83d79..758606213 100644 --- a/gap/digraph.gd +++ b/gap/digraph.gd @@ -152,3 +152,5 @@ DeclareOperation("RandomLattice", [IsFunction, IsPosInt]); # in the not-too-distant future! DeclareOperation("RandomMultiDigraph", [IsPosInt]); DeclareOperation("RandomMultiDigraph", [IsPosInt, IsPosInt]); + +DeclareOperation("RemoveDigraphEdgeWeight", [IsDigraph, IsPosInt, IsPosInt]); \ No newline at end of file diff --git a/gap/digraph.gi b/gap/digraph.gi index 893d363bc..7108e68b6 100644 --- a/gap/digraph.gi +++ b/gap/digraph.gi @@ -167,11 +167,20 @@ InstallMethod(DigraphMutableCopy, "for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], function(D) local copy; + copy := ConvertToMutableDigraphNC(OutNeighboursMutableCopy(D)); SetDigraphVertexLabels(copy, StructuralCopy(DigraphVertexLabels(D))); + if HaveEdgeLabelsBeenAssigned(D) then SetDigraphEdgeLabelsNC(copy, StructuralCopy(DigraphEdgeLabelsNC(D))); fi; + + if IsImmutableDigraph(D) and HasEdgeWeights(D) then + copy!.edgeweights := EdgeWeightsMutableCopy(D); + elif IsMutableDigraph(D) and IsBound(D!.edgeweights) then + copy!.edgeweights := StructuralCopy(D!.edgeweights); + fi; + return copy; end); @@ -179,11 +188,20 @@ InstallMethod(DigraphImmutableCopy, "for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], function(D) local copy; + copy := ConvertToImmutableDigraphNC(OutNeighboursMutableCopy(D)); SetDigraphVertexLabels(copy, StructuralCopy(DigraphVertexLabels(D))); + if HaveEdgeLabelsBeenAssigned(D) then SetDigraphEdgeLabelsNC(copy, StructuralCopy(DigraphEdgeLabelsNC(D))); fi; + + if IsImmutableDigraph(D) and HasEdgeWeights(D) then + SetEdgeWeights(copy, StructuralCopy(EdgeWeights(D))); + elif IsMutableDigraph(D) and IsBound(D!.edgeweights) then + SetEdgeWeights(copy, StructuralCopy(D!.edgeweights)); + fi; + return copy; end); @@ -1837,3 +1855,32 @@ n -> RandomLatticeCons(IsImmutableDigraph, n)); InstallMethod(RandomLattice, "for a func and a pos int", [IsFunction, IsPosInt], RandomLatticeCons); + +InstallMethod(RemoveDigraphEdgeWeight, "for a mutable digraph, pos int, pos int", +[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt], +function(D, v, pos) + if IsBound(D!.edgeweights) and v <= Length(D!.edgeweights) and pos <= Length(D!.edgeweights[v]) then + Remove(D!.edgeweights[v], pos); + fi; +end); + +InstallMethod(RemoveDigraphEdgeWeight, "for an immutable digraph, pos int, pos int", +[IsImmutableDigraph, IsPosInt, IsPosInt], +function(D, v, pos) + local newD, w; + newD := DigraphMutableCopy(D); + + if HasEdgeWeights(D) then + if v <= Length(newD!.edgeweights) + and pos <= Length(newD!.edgeweights[v]) then + Remove(newD!.edgeweights[v], pos); + fi; + fi; + + MakeImmutable(newD); + if HasEdgeWeights(D) then + SetEdgeWeights(newD, StructuralCopy(newD!.edgeweights)); + fi; + + return newD; +end); diff --git a/gap/oper.gi b/gap/oper.gi index 85b327d40..556b89359 100644 --- a/gap/oper.gi +++ b/gap/oper.gi @@ -103,45 +103,61 @@ function(D, m, labels) return DigraphAddVertices(D, labels); end); -InstallMethod(DigraphRemoveVertex, -"for a mutable digraph by out-neighbours and positive integer", +InstallMethod(DigraphRemoveVertex, "for a mutable digraph by out-neighbours and positive integer", [IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPosInt], function(D, u) local pos, w, v; + if u > DigraphNrVertices(D) then return D; fi; + RemoveDigraphVertexLabel(D, u); if IsBound(D!.edgelabels) then Remove(D!.edgelabels, u); fi; + Remove(D!.OutNeighbours, u); + if IsBound(D!.edgeweights) then + Remove(D!.edgeweights, u); + fi; + for v in DigraphVertices(D) do pos := 1; while pos <= Length(D!.OutNeighbours[v]) do w := D!.OutNeighbours[v][pos]; + if w = u then Remove(D!.OutNeighbours[v], pos); RemoveDigraphEdgeLabel(D, v, pos); + RemoveDigraphEdgeWeight(D, v, pos); + elif w > u then - D!.OutNeighbours[v][pos] := w - 1; - pos := pos + 1; + D!.OutNeighbours[v][pos] := w - 1; + pos := pos + 1; + else - pos := pos + 1; + pos := pos + 1; fi; od; od; return D; end); -InstallMethod(DigraphRemoveVertex, -"for an immutable digraph and positive integer", +InstallMethod(DigraphRemoveVertex, "for an immutable digraph and positive integer", [IsImmutableDigraph, IsPosInt], function(D, u) - if u > DigraphNrVertices(D) then - return D; + local newD; + + newD := DigraphMutableCopy(D); + DigraphRemoveVertex(newD, u); + MakeImmutable(newD); + + if HasEdgeWeights(D) then + SetEdgeWeights(newD, StructuralCopy(newD!.edgeweights)); fi; - return MakeImmutable(DigraphRemoveVertex(DigraphMutableCopy(D), u)); + + return newD; end); InstallMethod(DigraphRemoveVertices, "for a mutable digraph and a list", @@ -223,8 +239,7 @@ InstallMethod(DigraphAddEdges, "for an immutable digraph and a list", [IsImmutableDigraph, IsList], {D, edges} -> MakeImmutable(DigraphAddEdges(DigraphMutableCopy(D), edges))); -InstallMethod(DigraphRemoveEdge, -"for a mutable digraph by out-neighbours and two positive integers", +InstallMethod(DigraphRemoveEdge, "for a mutable digraph by out-neighbours and two positive integers", [IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt], function(D, src, ran) local pos; @@ -238,19 +253,33 @@ function(D, src, ran) ErrorNoReturn("the 3rd argument must be a vertex of the ", "digraph that is the 1st argument,"); fi; + pos := Position(D!.OutNeighbours[src], ran); + if pos <> fail then Remove(D!.OutNeighbours[src], pos); RemoveDigraphEdgeLabel(D, src, pos); + RemoveDigraphEdgeWeight(D, src, pos); fi; + return D; end); -InstallMethod(DigraphRemoveEdge, -"for a immutable digraph and two positive integers", +InstallMethod(DigraphRemoveEdge, "for a immutable digraph and two positive integers", [IsImmutableDigraph, IsPosInt, IsPosInt], -{D, src, ran} --> MakeImmutable(DigraphRemoveEdge(DigraphMutableCopy(D), src, ran))); +function(D, src, ran) + local newD; + + newD := DigraphMutableCopy(D); + DigraphRemoveEdge(newD, src, ran); + MakeImmutable(newD); + + if HasEdgeWeights(D) then + SetEdgeWeights(newD, StructuralCopy(newD!.edgeweights)); + fi; + + return newD; +end); InstallMethod(DigraphRemoveEdge, "for a mutable digraph and a list", [IsMutableDigraph, IsList], diff --git a/tst/standard/digraph.tst b/tst/standard/digraph.tst index 25f8dcc53..311c80a32 100644 --- a/tst/standard/digraph.tst +++ b/tst/standard/digraph.tst @@ -13,7 +13,7 @@ #@local adjacencies, b, bin, c, c1, c2, d, di, digraph, divides, elms, eq #@local eq_distr, eq_new, error, f, failed, failed_names, failed_values, foo, g #@local gr, gr1, gr2, gr3, gr4, gr5, graph, graph1, graph2, grnc, group, h -#@local hom13, hom21, hom23, hom31, hom41, hom42, hom52, hom53, i, im, inn +#@local hom13, hom21, hom23, hom31, hom41, hom42, hom52, hom53, i, im, im2, inn #@local isGraph, iso, iso_distr, iso_new, j, k, list, m, main, mat, n, name #@local name2, names, new, order, p, prop, properties, r, r1, r2, record, rel1 #@local rel2, rel3, representatives, s, schreierVector, sgn, temp, test, v, x @@ -565,6 +565,63 @@ gap> OutNeighbours(D); gap> AsDigraph(AsPartialPerm((2, 5, 3)), 2); fail +# Tests for DigraphMutableCopy, DigraphImmutableCopy, RemoveDigraphEdgeWeight (mutable & immutable). +gap> d := EdgeWeightedDigraph([[2,3],[3],[],[]], [[5,10],[15],[],[]]); + +gap> HasEdgeWeights(d); +true +gap> EdgeWeights(d); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] +gap> m := DigraphMutableCopy(d); + +gap> IsMutableDigraph(m); +true +gap> OutNeighbours(m) = OutNeighbours(d); +true +gap> DigraphVertexLabels(m) = DigraphVertexLabels(d); +true +gap> HasEdgeWeights(m); +false +gap> IsBound(m!.edgeweights); +true +gap> m!.edgeweights = [[5,10],[15],[],[]]; +true +gap> m!.edgeweights[1][1] := 999; +999 +gap> EdgeWeights(d)[1][1]; +5 +gap> im := DigraphImmutableCopy(d); + +gap> IsImmutableDigraph(im); +true +gap> OutNeighbours(im) = OutNeighbours(d); +true +gap> HasEdgeWeights(im); +true +gap> EdgeWeights(im); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] +gap> EdgeWeights(im)[1][1] := 777; +Error, List Assignment: must be a mutable list +gap> EdgeWeights(d); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] +gap> m := DigraphMutableCopy(d); + +gap> RemoveDigraphEdgeWeight(m, 1, 2); +gap> m!.edgeweights; +[ [ 5 ], [ 15 ], [ ], [ ] ] +gap> EdgeWeights(d); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] +gap> im2 := DigraphImmutableCopy(d); + +gap> im2 := RemoveDigraphEdgeWeight(im2, 1, 2); + +gap> EdgeWeights(im2); +[ [ 5 ], [ 15 ], [ ], [ ] ] +gap> HasEdgeWeights(im2); +true +gap> EdgeWeights(d); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] + # RandomDigraph gap> IsImmutableDigraph(RandomDigraph(100, 0.2)); true diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst index f4637c9a1..743b7e8e5 100644 --- a/tst/standard/oper.tst +++ b/tst/standard/oper.tst @@ -13,7 +13,7 @@ #@local G, G1, L, TestPartialOrderDigraph #@local TestPartialOrderDigraph2, TestUnion, a, adj, b, comps, copy, d, e #@local edges, edges2, func, g, gr, gr1, gr2, gr3, gr4, gri, grrt, grt, h, i -#@local i1, i2, id, idom, in1, in2, in3, iter, j1, j2, m, m1, m2, mat, n, nbs +#@local i1, i2, id, idom, in1, in2, in3, iter, j1, j2, m, m1, m2, m3, m4, im3, im4, mat, n, nbs #@local out, out1, out2, out3, p1, p2, path, preorder, qr, r, res, rtclosure, t #@local tclosure, u1, u2, x gap> START_TEST("Digraphs package: standard/oper.tst"); @@ -3299,6 +3299,46 @@ gap> DigraphEdges(D); gap> DigraphVertexLabels(D); [ 1, 2, 3, 6, [ 4, 5 ] ] +# Tests for DigraphRemoveVertex, DigraphRemoveVertex (immutable), DigraphRemoveEdge, DigraphRemoveEdge (immutable). +gap> d := EdgeWeightedDigraph([[2,3],[3],[],[]], [[5,10],[15],[],[]]); + +gap> m2 := DigraphMutableCopy(d); + +gap> DigraphRemoveEdge(m2, 1, 3); + +gap> OutNeighbours(m2); +[ [ 2 ], [ 3 ], [ ], [ ] ] +gap> m2!.edgeweights; +[ [ 5 ], [ 15 ], [ ], [ ] ] +gap> im3 := DigraphRemoveEdge(d, 1, 3); + +gap> IsImmutableDigraph(im3); +true +gap> OutNeighbours(im3); +[ [ 2 ], [ 3 ], [ ], [ ] ] +gap> EdgeWeights(im3); +[ [ 5 ], [ 15 ], [ ], [ ] ] +gap> m4 := DigraphMutableCopy(d); + +gap> DigraphRemoveVertex(m4, 1); + +gap> OutNeighbours(m4); +[ [ 2 ], [ ], [ ] ] +gap> m4!.edgeweights; +[ [ 15 ], [ ], [ ] ] +gap> im4 := DigraphRemoveVertex(d, 1); + +gap> IsImmutableDigraph(im4); +true +gap> OutNeighbours(im4); +[ [ 2 ], [ ], [ ] ] +gap> EdgeWeights(im4); +[ [ 15 ], [ ], [ ] ] +gap> OutNeighbours(d); +[ [ 2, 3 ], [ 3 ], [ ], [ ] ] +gap> EdgeWeights(d); +[ [ 5, 10 ], [ 15 ], [ ], [ ] ] + # gap> DIGRAPHS_StopTest(); gap> STOP_TEST("Digraphs package: standard/oper.tst", 0);