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
31 changes: 30 additions & 1 deletion doc/digraph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ gap> D := AsDigraph(b);
<Description>
Each of these operations returns a new copy of <A>digraph</A>,
of the appropriate mutability, retaining none of the attributes or
properties of <A>digraph</A>. <P/>
properties of <A>digraph</A>, with the exception that edge weights are preserved. <P/>

<C>DigraphCopy</C> is a synonym for <C>DigraphCopySameMutability</C>.
<Example><![CDATA[
Expand Down Expand Up @@ -585,6 +585,35 @@ true]]></Example>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphImmutableCopyNoWeights">
<ManSection>
<Oper Name="DigraphImmutableCopyNoWeights" Arg="digraph"/>
<Returns>An immutable digraph.</Returns>
<Description>
This operation returns an immutable copy of <A>digraph</A> that is
identical to <Ref Oper="DigraphImmutableCopy"/>, except that any edge
weights that <A>digraph</A> may have are not copied to the returned
digraph. <P/>

This can be useful when modifying the structure of a digraph with
<Ref Oper="DigraphRemoveVertex"/> or <Ref Oper="DigraphRemoveEdge"/>,
where the weights need to be updated to match the new structure,
rather than simply copied. <P/>

<Example><![CDATA[
gap> D := EdgeWeightedDigraph([[2, 3], [3], []], [[2, 5], [3], []]);
<immutable digraph with 3 vertices, 3 edges>
gap> HasEdgeWeights(D);
true
gap> D2 := DigraphImmutableCopyNoWeights(D);
<immutable digraph with 3 vertices, 3 edges>
gap> HasEdgeWeights(D2);
false
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="AsBinaryRelation">
<ManSection>
<Oper Name="AsBinaryRelation" Arg="digraph"/>
Expand Down
6 changes: 6 additions & 0 deletions doc/oper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ true
digraph are <C>[1..n-1]</C>, but the original labels can be
accessed via <Ref Oper="DigraphVertexLabels"/>. <P/>

If <A>digraph</A> has edge weights, then the returned digraph will also have edge weights with the weights updated
to reflect the removal of the vertex and its associated edges. <P/>

If <A>digraph</A> belongs to <Ref Filt="IsMutableDigraph"/>, then the
vertex is removed directly from <A>digraph</A>. If <A>digraph</A> belongs
to <Ref Filt="IsImmutableDigraph"/>, an immutable copy of <A>digraph</A>
Expand Down Expand Up @@ -702,6 +705,9 @@ true
constructed from <A>digraph</A> by removing the edge specified by
<A>edge</A> or <A>[src, ran]</A>. <P/>

If <A>digraph</A> has edge weights then the returned digraph will also have edge weights with the weight for the
removed edge no longer present. <P/>

If <A>digraph</A> belongs to <Ref
Filt="IsMutableDigraph"/>, then the edge is removed directly from
<A>digraph</A>. If <A>digraph</A> belongs to <Ref
Expand Down
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("DigraphImmutableCopyNoWeights", [IsDigraph]);
23 changes: 21 additions & 2 deletions gap/digraph.gi
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,34 @@ function(D)
return copy;
end);

InstallMethod(DigraphImmutableCopy, "for a digraph by out-neighbours",
InstallMethod(DigraphImmutableCopy,
"for a digraph by out-neighbours",
[IsDigraphByOutNeighboursRep],
function(D)
local copy, weights;
copy := DigraphImmutableCopyNoWeights(D);

if HasEdgeWeights(D) then
weights := EdgeWeightsMutableCopy(D);
SetEdgeWeights(copy, weights);
fi;

return copy;
end);

InstallMethod(DigraphImmutableCopyNoWeights,
"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;

return copy;
end);

Expand Down Expand Up @@ -1839,4 +1858,4 @@ InstallMethod(RandomLattice, "for a pos int", [IsPosInt],
n -> RandomLatticeCons(IsImmutableDigraph, n));

InstallMethod(RandomLattice, "for a func and a pos int", [IsFunction, IsPosInt],
RandomLatticeCons);
RandomLatticeCons);
46 changes: 42 additions & 4 deletions gap/oper.gi
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,28 @@ InstallMethod(DigraphRemoveVertex,
"for an immutable digraph and positive integer",
[IsImmutableDigraph, IsPosInt],
function(D, u)
local newD, weights;

if u > DigraphNrVertices(D) then
return D;
fi;
return MakeImmutable(DigraphRemoveVertex(DigraphMutableCopy(D), u));

newD := DigraphImmutableCopyNoWeights(D);
newD := DigraphMutableCopy(newD);
DigraphRemoveVertex(newD, u);
MakeImmutable(newD);

if HasEdgeWeights(D) then
weights := EdgeWeightsMutableCopy(D);

if u <= Length(weights) then
Remove(weights, u);
fi;

SetEdgeWeights(newD, weights);
fi;

return newD;
end);

InstallMethod(DigraphRemoveVertices, "for a mutable digraph and a list",
Expand Down Expand Up @@ -247,10 +265,30 @@ function(D, src, ran)
end);

InstallMethod(DigraphRemoveEdge,
"for a immutable digraph and two positive integers",
"for an immutable digraph and two positive integers",
[IsImmutableDigraph, IsPosInt, IsPosInt],
{D, src, ran}
-> MakeImmutable(DigraphRemoveEdge(DigraphMutableCopy(D), src, ran)));
function(D, src, ran)
local newD, weights, pos, outs;

newD := DigraphImmutableCopyNoWeights(D);
newD := DigraphMutableCopy(newD);
DigraphRemoveEdge(newD, src, ran);
MakeImmutable(newD);

if HasEdgeWeights(D) then
weights := EdgeWeightsMutableCopy(D);
outs := OutNeighbours(D)[src];
pos := Position(outs, ran);

if pos <> fail and pos <= Length(weights[src]) then
Remove(weights[src], pos);
fi;

SetEdgeWeights(newD, weights);
fi;

return newD;
end);

InstallMethod(DigraphRemoveEdge, "for a mutable digraph and a list",
[IsMutableDigraph, IsList],
Expand Down
34 changes: 33 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,38 @@ gap> OutNeighbours(D);
gap> AsDigraph(AsPartialPerm((2, 5, 3)), 2);
fail

# Tests for DigraphImmutableCopy
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> 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> im2 := DigraphImmutableCopy(d);
<immutable digraph with 4 vertices, 3 edges>
gap> im2 := DigraphRemoveEdge(im2, 1, 3);
<immutable digraph with 4 vertices, 2 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
28 changes: 27 additions & 1 deletion tst/standard/oper.tst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#@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 out, out1, out2, out3, p1, p2, path, preorder, qr, r, res, rtclosure, t
#@local tclosure, u1, u2, x
#@local tclosure, u1, u2, x, imE, imV
#@local p, q, idp, idt, M
gap> START_TEST("Digraphs package: standard/oper.tst");
gap> LoadPackage("digraphs", false);;
Expand Down Expand Up @@ -3324,6 +3324,32 @@ gap> DigraphEdges(D);
gap> DigraphVertexLabels(D);
[ 1, 2, 3, 6, [ 4, 5 ] ]

# Tests for DigraphRemoveVertex (immutable) and DigraphRemoveEdge (immutable).
gap> d := EdgeWeightedDigraph([[2, 3], [3], [], []], [[5, 10], [15], [], []]);
<immutable digraph with 4 vertices, 3 edges>
gap> imE := DigraphRemoveEdge(d, 1, 3);
<immutable digraph with 4 vertices, 2 edges>
gap> IsImmutableDigraph(imE);
true
gap> OutNeighbours(imE);
[ [ 2 ], [ 3 ], [ ], [ ] ]
gap> EdgeWeights(imE);
[ [ 5 ], [ 15 ], [ ], [ ] ]
gap> EdgeWeights(d);
[ [ 5, 10 ], [ 15 ], [ ], [ ] ]
gap> imV := DigraphRemoveVertex(d, 1);
<immutable digraph with 3 vertices, 1 edge>
gap> IsImmutableDigraph(imV);
true
gap> OutNeighbours(imV);
[ [ 2 ], [ ], [ ] ]
gap> EdgeWeights(imV);
[ [ 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