Skip to content

Commit dc7b0ba

Browse files
james-d-mitchellwilfwilson
authored andcommitted
oper: add IsDigraphPath
1 parent 124cc59 commit dc7b0ba

File tree

5 files changed

+131
-3
lines changed

5 files changed

+131
-3
lines changed

doc/oper.xml

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,9 @@ gap> VerticesReachableFrom(D, 5);
13821382

13831383
The method for <C>DigraphPath</C> has worst case complexity of <M>O(m +
13841384
n)</M> where <M>m</M> is the number of edges and <M>n</M> the number of
1385-
vertices in <A>digraph</A>.
1385+
vertices in <A>digraph</A>.<P/>
1386+
1387+
See also <Ref Oper="IsDigraphPath"/>.
13861388

13871389
<Example><![CDATA[
13881390
gap> D := Digraph([[2], [3], [2, 3]]);
@@ -2131,3 +2133,55 @@ gap> data;
21312133
</Description>
21322134
</ManSection>
21332135
<#/GAPDoc>
2136+
2137+
<#GAPDoc Label="IsDigraphPath">
2138+
<ManSection>
2139+
<Oper Name="IsDigraphPath" Arg="D, v, a"/>
2140+
<Oper Name="IsDigraphPath" Arg="D, list" Label="for a digraph and list"/>
2141+
<Returns><K>true</K> or <K>false</K>.</Returns>
2142+
<Description>
2143+
This function returns <K>true</K> if the arguments <A>v</A> and <A>a </A>
2144+
describe a path in the digraph <A>D</A>.
2145+
2146+
A directed path (or directed cycle) of non-zero length <C>n-1</C>,
2147+
<M>(v_1, e_1, v_2, e_2, ..., e_{n-1}, v_n)</M>,
2148+
is represented by a pair of lists <C>[<A>v</A>, <A>a</A>]</C> as follows:
2149+
2150+
<List>
2151+
<Item>
2152+
<A>v</A> is the list <M>[v_1, v_2, ..., v_n]</M>.
2153+
</Item>
2154+
<Item>
2155+
<A>a</A> is the list of positive integers <M>[a_1, a_2, ..., a_{n-1}]</M>
2156+
where for each each <M>i &lt; n</M>, <M>a_i</M> is the position of
2157+
<M>v_{i+1}</M> in
2158+
<C>OutNeighboursOfVertex(</C><A>D</A><C>,</C><M>v_i</M><C>)</C>
2159+
corresponding to the edge <M>e_i</M>. This can be useful if the
2160+
position of a vertex in a list of out-neighours is significant, for
2161+
example in orbit digraphs.
2162+
</Item>
2163+
</List>
2164+
2165+
If the arguments to <C>IsDigraphPath</C> are a digraph <A>D</A> and list
2166+
<A>list</A>, then this is equivalent to calling <C>IsDigraphPath(<A>D</A>,
2167+
<A>list</A>[1], <A>list</A>[2])</C>.
2168+
2169+
<Example><![CDATA[
2170+
gap> D := Digraph(IsMutableDigraph, Combinations([1 .. 5]), IsSubset);
2171+
<mutable digraph with 32 vertices, 243 edges>
2172+
gap> DigraphReflexiveTransitiveReduction(D);
2173+
<mutable digraph with 32 vertices, 80 edges>
2174+
gap> MakeImmutable(D);
2175+
<immutable digraph with 32 vertices, 80 edges>
2176+
gap> IsDigraphPath(D, [32, 31, 33], [1, 1]);
2177+
false
2178+
gap> IsDigraphPath(D, [1], []);
2179+
true
2180+
gap> IsDigraphPath(D, [6, 9, 16, 17], [3, 3, 2]);
2181+
true
2182+
gap> IsDigraphPath(D, DigraphPath(D, 6, 1));
2183+
true
2184+
]]></Example>
2185+
</Description>
2186+
</ManSection>
2187+
<#/GAPDoc>

doc/z-chap4.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<#Include Label="DigraphPeriod">
6464
<#Include Label="DigraphFloydWarshall">
6565
<#Include Label="IsReachable">
66+
<#Include Label="IsDigraphPath">
6667
<#Include Label="VerticesReachableFrom">
6768
<#Include Label="DigraphPath">
6869
<#Include Label="DigraphShortestPath">

gap/oper.gd

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ DeclareOperation("IsMatching", [IsDigraph, IsHomogeneousList]);
9292
DeclareOperation("IsMaximalMatching", [IsDigraph, IsHomogeneousList]);
9393
DeclareOperation("IsMaximumMatching", [IsDigraph, IsHomogeneousList]);
9494
DeclareOperation("IsPerfectMatching", [IsDigraph, IsHomogeneousList]);
95+
DeclareOperation("IsDigraphPath",
96+
[IsDigraph, IsHomogeneousList, IsHomogeneousList]);
97+
DeclareOperation("IsDigraphPath", [IsDigraph, IsList]);
9598

9699
# 9. Connectivity . . .
97100
DeclareOperation("DigraphFloydWarshall",
@@ -132,4 +135,4 @@ DeclareOperation("PartialOrderDigraphMeetOfVertices",
132135
# 11. DFS
133136
DeclareOperation("NewDFSRecord", [IsDigraph]);
134137
DeclareOperation("DFSDefault", [IsRecord, IsObject]);
135-
DeclareGlobalFunction("ExecuteDFS");
138+
DeclareGlobalFunction("ExecuteDFS");

gap/oper.gi

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,37 @@ function(D, u, v)
13331333
return out;
13341334
end);
13351335

1336+
InstallMethod(IsDigraphPath, "for a digraph and list",
1337+
[IsDigraph, IsList],
1338+
function(D, digraph_path_output)
1339+
if Length(digraph_path_output) <> 2 then
1340+
DError(["the 2nd argument (a list) must have length 2, ",
1341+
"but found length {}"],
1342+
Length(digraph_path_output));
1343+
fi;
1344+
return IsDigraphPath(D, digraph_path_output[1], digraph_path_output[2]);
1345+
end);
1346+
1347+
InstallMethod(IsDigraphPath, "for a digraph, homog. list, and homog. list",
1348+
[IsDigraph, IsHomogeneousList, IsHomogeneousList],
1349+
function(D, nodes, edges)
1350+
local a, i;
1351+
if Length(nodes) <> Length(edges) + 1 then
1352+
DError(["the 2nd and 3rd arguments (lists) are incompatible, ",
1353+
"expected 3rd argument of length {}, got {}"],
1354+
Length(nodes) - 1,
1355+
Length(edges));
1356+
fi;
1357+
a := OutNeighbours(D);
1358+
for i in [1 .. Length(edges)] do
1359+
if nodes[i] > Length(a) or edges[i] > Length(a[nodes[i]])
1360+
or a[nodes[i]][edges[i]] <> nodes[i + 1] then
1361+
return false;
1362+
fi;
1363+
od;
1364+
return true;
1365+
end);
1366+
13361367
InstallMethod(DigraphShortestPath,
13371368
"for a digraph by out-neighbours and two pos ints",
13381369
[IsDigraphByOutNeighboursRep, IsPosInt, IsPosInt],
@@ -2149,4 +2180,4 @@ function(record, data, start, PreOrderFunc, PostOrderFunc, AncestorFunc,
21492180
fi;
21502181
ExecuteDFS_C(record, data, start, PreOrderFunc, PostOrderFunc,
21512182
AncestorFunc, CrossFunc);
2152-
end);
2183+
end);

tst/standard/oper.tst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,6 +2697,45 @@ gap> ExecuteDFS(NewDFSRecord(D), [], 3, DFSDefault, DFSDefault, DFSDefault,
26972697
> DFSDefault);
26982698
Error, the third argument <start> must be a vertex in your graph,
26992699

2700+
# IsDigraphPath
2701+
gap> D := Digraph(IsMutableDigraph, Combinations([1 .. 5]), IsSubset);
2702+
<mutable digraph with 32 vertices, 243 edges>
2703+
gap> DigraphReflexiveTransitiveReduction(D);
2704+
<mutable digraph with 32 vertices, 80 edges>
2705+
gap> MakeImmutable(D);
2706+
<immutable digraph with 32 vertices, 80 edges>
2707+
gap> IsDigraphPath(D, [1, 2, 3], []);
2708+
Error, the 2nd and 3rd arguments (lists) are incompatible, expected 3rd argume\
2709+
nt of length 2, got 0
2710+
gap> IsDigraphPath(D, [1], []);
2711+
true
2712+
gap> IsDigraphPath(D, [1, 2], [5]);
2713+
false
2714+
gap> IsDigraphPath(D, [32, 31, 33], [1, 1]);
2715+
false
2716+
gap> IsDigraphPath(D, [32, 33, 31], [1, 1]);
2717+
false
2718+
gap> IsDigraphPath(D, [6, 9, 16, 17], [3, 3, 2]);
2719+
true
2720+
gap> IsDigraphPath(D, [33, 9, 16, 17], [3, 3, 2]);
2721+
false
2722+
gap> IsDigraphPath(D, [6, 9, 18, 1], [9, 10, 2]);
2723+
false
2724+
2725+
# IsDigraphPath
2726+
gap> D := Digraph(IsMutableDigraph, Combinations([1 .. 5]), IsSubset);
2727+
<mutable digraph with 32 vertices, 243 edges>
2728+
gap> DigraphReflexiveTransitiveReduction(D);
2729+
<mutable digraph with 32 vertices, 80 edges>
2730+
gap> MakeImmutable(D);
2731+
<immutable digraph with 32 vertices, 80 edges>
2732+
gap> IsDigraphPath(D, DigraphPath(D, 6, 1));
2733+
true
2734+
gap> ForAll(List(IteratorOfPaths(D, 6, 1)), x -> IsDigraphPath(D, x));
2735+
true
2736+
gap> IsDigraphPath(D, []);
2737+
Error, the 2nd argument (a list) must have length 2, but found length 0
2738+
27002739
#
27012740
gap> DIGRAPHS_StopTest();
27022741
gap> STOP_TEST("Digraphs package: standard/oper.tst", 0);

0 commit comments

Comments
 (0)