-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Behaviour of DigraphRemoveEdge/DigraphRemoveEdges is inconsistent #260 #723
base: main
Are you sure you want to change the base?
Changes from 5 commits
2492f10
6e704ab
cc2feb9
b7f59d1
a15fbe5
07bfb34
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -166,7 +166,13 @@ end); | |
|
||
InstallMethod(DigraphRemoveVertices, "for an immutable digraph and a list", | ||
[IsImmutableDigraph, IsList], | ||
{D, list} -> MakeImmutable(DigraphRemoveVertices(DigraphMutableCopy(D), list))); | ||
function(D, list) | ||
if ForAll(list, IsPosInt) and | ||
not (ForAny(list, x -> x <= DigraphNrVertices(D))) then | ||
return D; | ||
fi; | ||
return MakeImmutable(DigraphRemoveVertices(DigraphMutableCopy(D), list)); | ||
end); | ||
|
||
############################################################################# | ||
# 2. Adding and removing edges | ||
|
@@ -223,11 +229,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", | ||
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt], | ||
function(D, src, ran) | ||
local pos; | ||
DIGRAPHS_CheckDigraphRemoveEdge := function(D, src, ran) | ||
if IsMultiDigraph(D) then | ||
ErrorNoReturn("the 1st argument <D> must be a digraph with no multiple ", | ||
"edges,"); | ||
|
@@ -238,6 +240,14 @@ function(D, src, ran) | |
ErrorNoReturn("the 3rd argument <ran> must be a vertex of the ", | ||
"digraph <D> that is the 1st argument,"); | ||
fi; | ||
end; | ||
|
||
InstallMethod(DigraphRemoveEdge, | ||
"for a mutable digraph by out-neighbours and two positive integers", | ||
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt], | ||
function(D, src, ran) | ||
local pos; | ||
DIGRAPHS_CheckDigraphRemoveEdge(D, src, ran); | ||
pos := Position(D!.OutNeighbours[src], ran); | ||
if pos <> fail then | ||
Remove(D!.OutNeighbours[src], pos); | ||
|
@@ -249,8 +259,19 @@ end); | |
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 pos, DMutable; | ||
DMutable := DigraphMutableCopy(D); | ||
DIGRAPHS_CheckDigraphRemoveEdge(DMutable, src, ran); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we create a copy and then check it is valid. Why not check the original graph before copying, so that extra work is not done? |
||
pos := Position(D!.OutNeighbours[src], ran); | ||
if pos <> fail then | ||
Remove(DMutable!.OutNeighbours[src], pos); | ||
RemoveDigraphEdgeLabel(DMutable, src, pos); | ||
return MakeImmutable(DMutable); | ||
else | ||
return D; | ||
fi; | ||
end); | ||
|
||
InstallMethod(DigraphRemoveEdge, "for a mutable digraph and a list", | ||
[IsMutableDigraph, IsList], | ||
|
@@ -264,7 +285,13 @@ end); | |
InstallMethod(DigraphRemoveEdge, | ||
"for a immutable digraph and a list", | ||
[IsImmutableDigraph, IsList], | ||
{D, edge} -> MakeImmutable(DigraphRemoveEdge(DigraphMutableCopy(D), edge))); | ||
function(D, edge) | ||
if Length(edge) <> 2 then | ||
ErrorNoReturn("the 2nd argument <edge> must be a list of length 2,"); | ||
else | ||
return DigraphRemoveEdge(D, edge[1], edge[2]); | ||
fi; | ||
end); | ||
|
||
InstallMethod(DigraphRemoveEdges, "for a digraph and a list", | ||
[IsMutableDigraph, IsList], | ||
|
@@ -275,7 +302,32 @@ end); | |
|
||
InstallMethod(DigraphRemoveEdges, "for an immutable digraph and a list", | ||
[IsImmutableDigraph, IsList], | ||
{D, edges} -> MakeImmutable(DigraphRemoveEdges(DigraphMutableCopy(D), edges))); | ||
function(D, edges) | ||
local DMutableRemoved; | ||
DMutableRemoved := DigraphRemoveEdges(DigraphMutableCopy(D), edges); | ||
|
||
# If any edges have been removed | ||
if DigraphNrEdges(D) <> DigraphNrEdges(DMutableRemoved) then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, could we somehow check this before copying, to avoid the extra work if it's not necessary? I think you could check all the inputs with |
||
return MakeImmutable(DMutableRemoved); | ||
else | ||
return D; | ||
fi; | ||
end); | ||
|
||
DIGRAPHS_DigraphReverseEdgeDoOper := function(D, u, v, pos) | ||
Remove(D!.OutNeighbours[u], pos); | ||
Add(D!.OutNeighbours[v], u); | ||
if Length(Positions(D!.OutNeighbours[v], u)) > 1 then | ||
# output is a multidigraph | ||
ClearDigraphEdgeLabels(D); | ||
elif IsBound(D!.edgelabels) | ||
and IsBound(D!.edgelabels[u]) | ||
and IsBound(D!.edgelabels[u][pos]) then | ||
SetDigraphEdgeLabel(D, v, u, D!.edgelabels[u][pos]); | ||
RemoveDigraphEdgeLabel(D, u, pos); | ||
fi; | ||
return D; | ||
end; | ||
|
||
InstallMethod(DigraphReverseEdge, | ||
"for a mutable digraph by out-neighbours and two positive integers", | ||
|
@@ -293,24 +345,28 @@ function(D, u, v) | |
elif u = v then | ||
return D; | ||
fi; | ||
Remove(D!.OutNeighbours[u], pos); | ||
Add(D!.OutNeighbours[v], u); | ||
if Length(Positions(D!.OutNeighbours[v], u)) > 1 then | ||
# output is a multidigraph | ||
ClearDigraphEdgeLabels(D); | ||
elif IsBound(D!.edgelabels) | ||
and IsBound(D!.edgelabels[u]) | ||
and IsBound(D!.edgelabels[u][pos]) then | ||
SetDigraphEdgeLabel(D, v, u, D!.edgelabels[u][pos]); | ||
RemoveDigraphEdgeLabel(D, u, pos); | ||
fi; | ||
return D; | ||
return DIGRAPHS_DigraphReverseEdgeDoOper(D, u, v, pos); | ||
end); | ||
|
||
InstallMethod(DigraphReverseEdge, | ||
"for an immutable digraph, positive integer, and positive integer", | ||
[IsImmutableDigraph, IsPosInt, IsPosInt], | ||
{D, u, v} -> MakeImmutable(DigraphReverseEdge(DigraphMutableCopy(D), u, v))); | ||
function(D, u, v) | ||
local pos; | ||
if IsMultiDigraph(D) then | ||
ErrorNoReturn("the 1st argument <D> must be a digraph with no ", | ||
"multiple edges,"); | ||
fi; | ||
pos := Position(D!.OutNeighbours[u], v); | ||
if pos = fail then | ||
ErrorNoReturn("there is no edge from ", u, " to ", v, | ||
" in the digraph <D> that is the 1st argument,"); | ||
elif u = v then | ||
return D; | ||
fi; | ||
return MakeImmutable(DIGRAPHS_DigraphReverseEdgeDoOper( | ||
DigraphMutableCopy(D), u, v, pos)); | ||
end); | ||
|
||
InstallMethod(DigraphReverseEdge, "for a mutable digraph and list", | ||
[IsMutableDigraph, IsList], | ||
|
@@ -323,7 +379,13 @@ end); | |
|
||
InstallMethod(DigraphReverseEdge, "for an immutable digraph and a list", | ||
[IsImmutableDigraph, IsList], | ||
{D, e} -> MakeImmutable(DigraphReverseEdge(DigraphMutableCopy(D), e))); | ||
function(D, e) | ||
if Length(e) <> 2 then | ||
ErrorNoReturn("the 2nd argument <e> must be a list of length 2,"); | ||
else | ||
return DigraphReverseEdge(D, e[1], e[2]); | ||
fi; | ||
end); | ||
|
||
InstallMethod(DigraphReverseEdges, "for a mutable digraph and a list", | ||
[IsMutableDigraph, IsList], | ||
|
@@ -334,7 +396,23 @@ end); | |
|
||
InstallMethod(DigraphReverseEdges, "for an immutable digraph and a list", | ||
[IsImmutableDigraph, IsList], | ||
{D, E} -> MakeImmutable(DigraphReverseEdges(DigraphMutableCopy(D), E))); | ||
function(D, E) | ||
local changed, DMutable, edge; | ||
changed := false; | ||
DMutable := DigraphMutableCopy(D); | ||
for edge in E do | ||
DigraphReverseEdge(DMutable, edge); | ||
if edge[1] <> edge[2] then # The edge could be reversed | ||
changed := true; | ||
fi; | ||
od; | ||
|
||
if changed = true then | ||
return MakeImmutable(DMutable); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, could we figure out whether the condition is true without creating a copy first? |
||
else | ||
return D; | ||
fi; | ||
end); | ||
|
||
InstallMethod(DigraphClosure, | ||
"for a mutable digraph by out-neighbours and a positive integer", | ||
|
@@ -1218,8 +1296,14 @@ end); | |
InstallMethod(QuotientDigraph, | ||
"for an immutable digraph and a homogeneous list", | ||
[IsImmutableDigraph, IsHomogeneousList], | ||
{D, partition} -> | ||
MakeImmutable(QuotientDigraph(DigraphMutableCopy(D), partition))); | ||
function(D, partition) | ||
if DigraphNrVertices(D) = 0 and IsEmpty(partition) then | ||
return D; | ||
else | ||
return MakeImmutable(QuotientDigraph(DigraphMutableCopy(D), partition)); | ||
|
||
fi; | ||
end); | ||
|
||
############################################################################# | ||
# 6. In and out degrees, neighbours, and edges of vertices | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the list has negative integers, then presumably the input digraph should still not be copied?
Instead of testing
IsPosInt
and then checking<=
, would we be better to checkForAny(list, x -> not x in DigraphVertices(D)
? Then it's a single clean statement that catches everything.