Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gap/digraph.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
47 changes: 47 additions & 0 deletions gap/digraph.gi
Original file line number Diff line number Diff line change
Expand Up @@ -167,23 +167,41 @@ 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);

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);

Expand Down Expand Up @@ -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],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[IsImmutableDigraph, IsPosInt, IsPosInt],
[IsImmutableDigraph and HasEdgeWeights, IsPosInt, IsPosInt],

function(D, v, pos)
local newD, w;
newD := DigraphMutableCopy(D);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
newD := DigraphMutableCopy(D);
newD := DigraphImmutableCopy(D);


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
weights := EdgeWeightsMutableCopy(D);

if HasEdgeWeights(D) then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SetEdgeWeights(newD, StructuralCopy(newD!.edgeweights));
SetEdgeWeights(newD, weights));

fi;

return newD;
end);
61 changes: 45 additions & 16 deletions gap/oper.gi
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand All @@ -238,19 +253,33 @@ function(D, src, ran)
ErrorNoReturn("the 3rd argument <ran> must be a vertex of the ",
"digraph <D> 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],
Expand Down
59 changes: 58 additions & 1 deletion tst/standard/digraph.tst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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],[],[]]);
<immutable digraph with 4 vertices, 3 edges>
gap> HasEdgeWeights(d);
true
gap> EdgeWeights(d);
[ [ 5, 10 ], [ 15 ], [ ], [ ] ]
gap> m := DigraphMutableCopy(d);
<mutable digraph with 4 vertices, 3 edges>
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);
<immutable digraph with 4 vertices, 3 edges>
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: <list> must be a mutable list
gap> EdgeWeights(d);
[ [ 5, 10 ], [ 15 ], [ ], [ ] ]
gap> m := DigraphMutableCopy(d);
<mutable digraph with 4 vertices, 3 edges>
gap> RemoveDigraphEdgeWeight(m, 1, 2);
gap> m!.edgeweights;
[ [ 5 ], [ 15 ], [ ], [ ] ]
gap> EdgeWeights(d);
[ [ 5, 10 ], [ 15 ], [ ], [ ] ]
gap> im2 := DigraphImmutableCopy(d);
<immutable digraph with 4 vertices, 3 edges>
gap> im2 := RemoveDigraphEdgeWeight(im2, 1, 2);
<immutable digraph with 4 vertices, 3 edges>
gap> EdgeWeights(im2);
[ [ 5 ], [ 15 ], [ ], [ ] ]
gap> HasEdgeWeights(im2);
true
gap> EdgeWeights(d);
[ [ 5, 10 ], [ 15 ], [ ], [ ] ]

# RandomDigraph
gap> IsImmutableDigraph(RandomDigraph(100, 0.2));
true
Expand Down
42 changes: 41 additions & 1 deletion tst/standard/oper.tst
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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],[],[]]);
<immutable digraph with 4 vertices, 3 edges>
gap> m2 := DigraphMutableCopy(d);
<mutable digraph with 4 vertices, 3 edges>
gap> DigraphRemoveEdge(m2, 1, 3);
<mutable digraph with 4 vertices, 2 edges>
gap> OutNeighbours(m2);
[ [ 2 ], [ 3 ], [ ], [ ] ]
gap> m2!.edgeweights;
[ [ 5 ], [ 15 ], [ ], [ ] ]
Comment on lines +3311 to +3312
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a design decision here!

Either:

  • mutable digraphs cannot hold EdgeWeights (because they can't hold attributes); or
  • mutable digraphs can store edge weights internally using !.edgeweights as a workaround.

The second approach has been taken in this PR, and we should review whether it's a good idea when we finally merge.

gap> im3 := DigraphRemoveEdge(d, 1, 3);
<immutable digraph with 4 vertices, 2 edges>
gap> IsImmutableDigraph(im3);
true
gap> OutNeighbours(im3);
[ [ 2 ], [ 3 ], [ ], [ ] ]
gap> EdgeWeights(im3);
[ [ 5 ], [ 15 ], [ ], [ ] ]
gap> m4 := DigraphMutableCopy(d);
<mutable digraph with 4 vertices, 3 edges>
gap> DigraphRemoveVertex(m4, 1);
<mutable digraph with 3 vertices, 1 edge>
gap> OutNeighbours(m4);
[ [ 2 ], [ ], [ ] ]
gap> m4!.edgeweights;
[ [ 15 ], [ ], [ ] ]
gap> im4 := DigraphRemoveVertex(d, 1);
<immutable digraph with 3 vertices, 1 edge>
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);
Loading