diff --git a/doc/oper.xml b/doc/oper.xml index daa733164..cf9221328 100644 --- a/doc/oper.xml +++ b/doc/oper.xml @@ -2133,9 +2133,38 @@ true <#/GAPDoc> +<#GAPDoc Label="IsKParadoxicalTournament"> + + + true or false. + + A tournament D is k-paradoxical if for every set + S of k vertices there is a vertex outside S which + is an in-neighbour of every vertex in S, i.e. there is one player + who beats all the players of S. This is a generalisation of + . +

+ If D has no vertices, then the answer is false. If D + has at least one vertex and k is 0 then the answer is + true. +

+ If k is negative or D is not a tournament (see + ), then an error is raised. + D := Digraph([[2, 3, 5], [3, 4, 6], [4, 5, 7], [5, 6, 1], +> [6, 7, 2], [7, 1, 3], [1, 2, 4]]);; +gap> IsKParadoxicalTournament(D, 2); +true +gap> IsKParadoxicalTournament(D, 3); +false]]> + + +<#/GAPDoc> + <#GAPDoc Label="DigraphDijkstra"> - + Two lists. diff --git a/doc/prop.xml b/doc/prop.xml index 8a7b39790..5c293f4a3 100644 --- a/doc/prop.xml +++ b/doc/prop.xml @@ -451,6 +451,35 @@ false <#/GAPDoc> +<#GAPDoc Label="IsParadoxicalTournament"> + + + true or false. + + A tournament D is paradoxical if every vertex has at least + one in-neighbour, i.e. each player loses at least one game. This is the + same as being 1-paradoxical; see + . +

+ If D has no vertices, then the answer is false. +

+ If D is not a tournament (see ), then an + error is raised. +

+ + &MUTABLE_RECOMPUTED_PROP; + + D := Digraph([[2], [3], [1]]);; +gap> IsParadoxicalTournament(D); +true +gap> D := Digraph([[2, 3], [3], []]);; +gap> IsParadoxicalTournament(D); +false]]> + + +<#/GAPDoc> + <#GAPDoc Label="IsChainDigraph"> diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml index 059e10eea..dcfdebb06 100644 --- a/doc/z-chap4.xml +++ b/doc/z-chap4.xml @@ -18,6 +18,7 @@ <#Include Label="DigraphOutEdges"> <#Include Label="IsDigraphEdge"> <#Include Label="IsMatching"> + <#Include Label="IsKParadoxicalTournament"> <#Include Label="DigraphMaximalMatching"> <#Include Label="DigraphMaximumMatching"> diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml index 491deb4c8..f1da97657 100644 --- a/doc/z-chap5.xml +++ b/doc/z-chap5.xml @@ -21,6 +21,7 @@ <#Include Label="IsReflexiveDigraph"> <#Include Label="IsSymmetricDigraph"> <#Include Label="IsTournament"> + <#Include Label="IsParadoxicalTournament"> <#Include Label="IsTransitiveDigraph"> diff --git a/gap/oper.gd b/gap/oper.gd index 4766b3496..da757c6cc 100644 --- a/gap/oper.gd +++ b/gap/oper.gd @@ -117,6 +117,7 @@ DeclareOperation("IsPerfectMatching", [IsDigraph, IsHomogeneousList]); DeclareOperation("IsDigraphPath", [IsDigraph, IsHomogeneousList, IsHomogeneousList]); DeclareOperation("IsDigraphPath", [IsDigraph, IsList]); +DeclareOperation("IsKParadoxicalTournament", [IsDigraph, IsInt]); # 9. Connectivity . . . DeclareOperation("DigraphIsKing", [IsDigraph, IsPosInt, IsPosInt]); diff --git a/gap/oper.gi b/gap/oper.gi index bdc462bee..4a072885a 100644 --- a/gap/oper.gi +++ b/gap/oper.gi @@ -1596,6 +1596,60 @@ function(D, edges) return true; end); +InstallMethod(IsKParadoxicalTournament, "for a tournament and an integer", +[IsDigraph, IsInt], +function(D, k) + local n, inn_blist, backtrack; + + if not IsTournament(D) then + ErrorNoReturn("the 1st argument must be a tournament,"); + fi; + + if k < 0 then + ErrorNoReturn("the 2nd argument must be non-negative,"); + fi; + + n := DigraphNrVertices(D); + + if n = 0 then + return false; + fi; + + if k = 0 then + return true; + fi; + + if k = 1 then + return IsParadoxicalTournament(D); + fi; + + # this minimum number of vertices needed for k-paradox is given by + # Szekeres, E.; Szekeres, G. (1965), "On a problem of Schütte and Erdős" + if n < (k + 2) * (2 ^ (k - 1)) - 1 then + return false; + fi; + + inn_blist := List(InNeighbours(D), inn -> BlistList([1 .. n], inn)); + + backtrack := function(prev, depth, common) + local vertex, ncommon; + for vertex in [prev + 1 .. n - k + depth + 1] do + ncommon := IntersectionBlist(common, inn_blist[vertex]); + if SizeBlist(ncommon) = 0 then + return false; + fi; + if depth + 1 < k then + if not backtrack(vertex, depth + 1, ncommon) then + return false; + fi; + fi; + od; + return true; + end; + + return backtrack(0, 0, BlistList([1 .. n], [1 .. n])); +end); + ############################################################################# # 9. Connectivity ############################################################################# diff --git a/gap/prop.gd b/gap/prop.gd index 808d67dc7..c015a03e9 100644 --- a/gap/prop.gd +++ b/gap/prop.gd @@ -26,6 +26,7 @@ DeclareProperty("IsCompleteBipartiteDigraph", IsDigraph); DeclareProperty("IsCompleteMultipartiteDigraph", IsDigraph); DeclareProperty("IsCompleteDigraph", IsDigraph); DeclareProperty("IsTournament", IsDigraph); +DeclareProperty("IsParadoxicalTournament", IsDigraph); DeclareProperty("IsChainDigraph", IsDigraph); DeclareProperty("IsCycleDigraph", IsDigraph); DeclareProperty("IsDigraphCore", IsDigraph); diff --git a/gap/prop.gi b/gap/prop.gi index 0c564ef17..84bdde087 100644 --- a/gap/prop.gi +++ b/gap/prop.gi @@ -339,6 +339,20 @@ function(D) return IsAntisymmetricDigraph(D); end); +InstallMethod(IsParadoxicalTournament, "for a tournament", +[IsDigraph], +function(D) + if not IsTournament(D) then + ErrorNoReturn("the argument must be a tournament,"); + fi; + + if DigraphNrVertices(D) = 0 then + return false; + else + return not ForAny(InNeighbours(D), IsEmpty); + fi; +end); + InstallMethod(IsEmptyDigraph, "for a digraph with known number of edges", [IsDigraph and HasDigraphNrEdges], D -> DigraphNrEdges(D) = 0); diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst index 585f10a99..afb3b31b0 100644 --- a/tst/standard/oper.tst +++ b/tst/standard/oper.tst @@ -41,6 +41,36 @@ gap> gr := Digraph([[], [3, 4], [1, 4], [1]]); gap> DigraphIsKing(gr, 2, 2); Error, the 1st argument must be a tournament, +# IsKParadoxicalTournament: for a tournament and a non-negative integer +gap> gr := Digraph([[2], [1]]);; +gap> IsKParadoxicalTournament(gr, 1); +Error, the 1st argument must be a tournament, +gap> gr := EmptyDigraph(0);; +gap> IsKParadoxicalTournament(gr, 0); +false +gap> IsKParadoxicalTournament(gr, 1); +false +gap> gr := Digraph([[]]);; +gap> IsKParadoxicalTournament(gr, 0); +true +gap> IsKParadoxicalTournament(gr, -1); +Error, the 2nd argument must be non-negative, +gap> gr := Digraph([[2], [3], [1]]);; +gap> IsKParadoxicalTournament(gr, 1); +true +gap> gr := Digraph([[2, 4, 7], [4, 5, 7], [1, 2, 4, 6, 7], +> [], [1, 3, 4, 6, 7], [1, 2, 4, 7], [4]]);; +gap> IsKParadoxicalTournament(gr, 2); +false +gap> gr := p -> Digraph( +> List([0 .. p - 1], +> x -> List(Set(List([1 .. (p - 1) / 2], i -> i ^ 2 mod p)), +> s -> (x + s) mod p + 1)));; +gap> IsKParadoxicalTournament(gr(19), 3); +true +gap> IsKParadoxicalTournament(gr(19), 4); +false + # DigraphRemoveLoops gap> gr := DigraphFromDigraph6String("&EhxPC?@"); diff --git a/tst/standard/prop.tst b/tst/standard/prop.tst index 623ff6713..5384a77cb 100644 --- a/tst/standard/prop.tst +++ b/tst/standard/prop.tst @@ -416,6 +416,24 @@ gap> gr := Digraph([[2], [1], [1]]); gap> IsTournament(gr); false +# IsParadoxical +gap> gr := Digraph([[2], [1]]);; +gap> IsParadoxicalTournament(gr); +Error, the argument must be a tournament, +gap> gr := EmptyDigraph(0);; +gap> IsParadoxicalTournament(gr); +false +gap> gr := Digraph([[2, 3], [3], []]);; +gap> IsTournament(gr); +true +gap> IsParadoxicalTournament(gr); +false +gap> gr := Digraph([[2], [3], [1]]);; +gap> IsTournament(gr); +true +gap> IsParadoxicalTournament(gr); +true + # IsStronglyConnectedDigraph gap> gr := Digraph([]);