diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..73551256f --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,28 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '42 0 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Stale issue message' + stale-pr-message: 'Stale pull request message' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' + days-before-close: -1 diff --git a/doc/attr.xml b/doc/attr.xml index 09b27850e..a432c5757 100644 --- a/doc/attr.xml +++ b/doc/attr.xml @@ -2429,3 +2429,40 @@ gap> Length(M); <#/GAPDoc> + +<#GAPDoc Label="NonUpperSemimodularPair"> + + + + A pair of vertices or fail. + + NonUpperSemimodularPair returns a pair of vertices in the digraph + D that witnesses the fact that D does not represent an upper + semimodular lattice, if such a pair exists.

+ + If the digraph D does not satisfy , then an error is given. Otherwise if the + digraph D does satisfy , then either a non-upper semimodular pair of + vertices is returned, or fail is returned if no such pair exists + (meaning that D is an upper semimodular lattice.

+ + NonLowerSemimodularPair behaves in the analogous way to + NonUpperSemimodularPair with respect to lower semimodularity.

+ + See and for the definition of upper + semimodularity of a lattice. + + D := DigraphFromDigraph6String( +> "&M~~sc`lYUZO__KIBboC_@h?U_?_GL?A_?c"); + +gap> NonLowerSemimodularPair(D); +[ 10, 9 ] +gap> NonUpperSemimodularPair(D); +fail +]]> + + +<#/GAPDoc> diff --git a/doc/digraph.xml b/doc/digraph.xml index ea43bb730..9f1e0159f 100644 --- a/doc/digraph.xml +++ b/doc/digraph.xml @@ -421,33 +421,52 @@ gap> D := DigraphByInNeighbours(IsMutableDigraph, <#GAPDoc Label="AsDigraph"> - + A digraph, or fail. - If f is a transformation or permutation, - and n is a non-negative integer - such that the restriction of f to [1..n] defines - a function of [1..n], then AsDigraph - returns the functional digraph with n vertices defined by - f. See . -

- - Specifically, the digraph returned by AsDigraph has n edges: - for each vertex v in [1..n], there is a unique edge - with source v; this edge has range v^f. -

- If the optional second argument n is not supplied, then - the degree of the transformation f, - or the largest moved point of the permutation f, - as applicable, is used by default. If the restriction of - f to [1..n] does not define a function of - [1..n], then AsDigraph(f, n) - returns fail. + If f is a binary relation represented as one of the following in + &GAP;: + + + a transformation + + + satisfying ; + + + a permutation + + + satisfying ; + + + a partial perm + + + satisfying ; + + + a binary relation + + + satisfying ; + + + and n is a non-negative integer, then AsDigraph attempts + to construct a digraph with n vertices whose edges are determined + by f.

+ + The digraph returned by AsDigraph has for each vertex + v in [1 .. n], an edge with source v and range + v ^ f. If v ^ f is greater than n for any + v, then fail is returned.

- See also . + If the optional second argument n is not supplied, then the degree + of the transformation f, the largest moved point of the permutation + f, the maximum of the degree and the codegree of the partial perm + f, or as applicable, is used by default.

&STANDARD_FILT_TEXT; diff --git a/doc/prop.xml b/doc/prop.xml index e8b720471..ee75b409b 100644 --- a/doc/prop.xml +++ b/doc/prop.xml @@ -1459,3 +1459,39 @@ true <#/GAPDoc> + +<#GAPDoc Label="IsUpperSemimodularDigraph"> + + + + true or false. + + IsUpperSemimodularDigraph returns true if the digraph + D represents an upper semimodular lattice and false if it + does not. Similarly, IsLowerSemimodularDigraph returns true + if D represents a lower semimodular lattice and false if + it does not.

+ + In a lattice we say that a vertex a covers a vertex b + if a is greater than b, and there are no further vertices + between a and b. A lattice is upper semimodular if + whenever the meet of a and b is covered by a, the join + of a and b covers b. Lower semimodularity is + defined analogously.

+ + See also , , + and . + + &MUTABLE_RECOMPUTED_PROP; + + D := DigraphFromDigraph6String( +> "&M~~sc`lYUZO__KIBboC_@h?U_?_GL?A_?c"); + +gap> IsUpperSemimodularDigraph(D); +true +gap> IsLowerSemimodularDigraph(D); +false]]> + + +<#/GAPDoc> diff --git a/doc/z-chap4.xml b/doc/z-chap4.xml index 00224832d..1524d671c 100644 --- a/doc/z-chap4.xml +++ b/doc/z-chap4.xml @@ -35,10 +35,14 @@ <#Include Label="InDegreeOfVertex"> <#Include Label="InNeighboursOfVertex"> <#Include Label="DigraphLoops"> - <#Include Label="PartialOrderDigraphMeetOfVertices"> <#Include Label="DegreeMatrix"> <#Include Label="LaplacianMatrix"> + +

Orders + <#Include Label="PartialOrderDigraphMeetOfVertices"> + <#Include Label="NonUpperSemimodularPair"> +
Reachability and connectivity <#Include Label="DigraphDiameter"> diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml index 906c65d76..f571974c2 100644 --- a/doc/z-chap5.xml +++ b/doc/z-chap5.xml @@ -22,9 +22,13 @@ <#Include Label="IsSymmetricDigraph"> <#Include Label="IsTournament"> <#Include Label="IsTransitiveDigraph"> +
+ +
Orders <#Include Label="IsPreorderDigraph"> <#Include Label="IsPartialOrderDigraph"> <#Include Label="IsMeetSemilatticeDigraph"> + <#Include Label="IsUpperSemimodularDigraph">
Regularity diff --git a/gap/attr.gd b/gap/attr.gd index 5336d5b75..b67221290 100644 --- a/gap/attr.gd +++ b/gap/attr.gd @@ -121,3 +121,9 @@ DeclareAttribute("DigraphMaximumMatching", IsDigraph); DeclareAttribute("Bridges", IsDigraph); DeclareAttributeThatReturnsDigraph("StrongOrientation", IsDigraph); + +DeclareAttribute("NonUpperSemimodularPair", IsDigraph); +DeclareAttribute("NonLowerSemimodularPair", IsDigraph); + +DeclareProperty("IsUpperSemimodularDigraph", IsDigraph); +DeclareProperty("IsLowerSemimodularDigraph", IsDigraph); diff --git a/gap/attr.gi b/gap/attr.gi index 7cc679762..ca51e0aac 100644 --- a/gap/attr.gi +++ b/gap/attr.gi @@ -2657,3 +2657,73 @@ function(D) M := List(DigraphLoops(D), x -> [x, x]); return Union(M, DIGRAPHS_MateToMatching(D, mateD)); end); + +# The following function is a transliteration from python to GAP of +# the function find_nonsemimodular_pair +# in sage/src/sage/combinat/posets/hasse_diagram.py + +BindGlobal("DIGRAPHS_NonSemimodularPair", +function(nbs) + local n, covers, covers_len, a, covers_a, b, e, a_i, b_i; + n := Length(nbs); + + for e in [1 .. n] do + covers := nbs[e]; + covers_len := Length(covers); + if covers_len < 2 then + continue; + fi; + for a_i in [1 .. covers_len] do + a := covers[a_i]; + covers_a := nbs[a]; + for b_i in [1 .. a_i] do + b := covers[b_i]; + if not ForAny(nbs[b], j -> j in covers_a) then + return [a, b]; + fi; + od; + od; + od; + + return fail; +end); + +InstallMethod(NonUpperSemimodularPair, "for a digraph", +[IsDigraphByOutNeighboursRep], +function(D) + if not IsLatticeDigraph(D) then + ErrorNoReturn("the argument (a digraph) is not a lattice"); + fi; + D := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D)); + return DIGRAPHS_NonSemimodularPair(OutNeighbours(D)); +end); + +InstallMethod(NonLowerSemimodularPair, "for a digraph", +[IsDigraphByOutNeighboursRep], +function(D) + if not IsLatticeDigraph(D) then + ErrorNoReturn("the argument (a digraph) is not a lattice"); + fi; + D := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D)); + return DIGRAPHS_NonSemimodularPair(InNeighbours(D)); +end); + +InstallMethod(IsUpperSemimodularDigraph, "for a digraph", +[IsDigraphByOutNeighboursRep], +function(D) + if not IsLatticeDigraph(D) then + return false; + fi; + D := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D)); + return DIGRAPHS_NonSemimodularPair(OutNeighbours(D)) = fail; +end); + +InstallMethod(IsLowerSemimodularDigraph, "for a digraph", +[IsDigraphByOutNeighboursRep], +function(D) + if not IsLatticeDigraph(D) then + return false; + fi; + D := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D)); + return DIGRAPHS_NonSemimodularPair(InNeighbours(D)) = fail; +end); diff --git a/gap/digraph.gd b/gap/digraph.gd index d93389b46..0f722b5a3 100644 --- a/gap/digraph.gd +++ b/gap/digraph.gd @@ -106,18 +106,24 @@ DeclareSynonym("DigraphByInNeighbors", DigraphByInNeighbours); DeclareConstructor("AsDigraphCons", [IsDigraph, IsBinaryRelation]); DeclareConstructor("AsDigraphCons", [IsDigraph, IsTransformation]); DeclareConstructor("AsDigraphCons", [IsDigraph, IsTransformation, IsInt]); +DeclareConstructor("AsDigraphCons", [IsDigraph, IsPartialPerm]); +DeclareConstructor("AsDigraphCons", [IsDigraph, IsPartialPerm, IsInt]); DeclareOperation("AsDigraph", [IsFunction, IsBinaryRelation]); DeclareOperation("AsDigraph", [IsFunction, IsTransformation]); DeclareOperation("AsDigraph", [IsFunction, IsTransformation, IsInt]); DeclareOperation("AsDigraph", [IsFunction, IsPerm]); DeclareOperation("AsDigraph", [IsFunction, IsPerm, IsInt]); +DeclareOperation("AsDigraph", [IsFunction, IsPartialPerm]); +DeclareOperation("AsDigraph", [IsFunction, IsPartialPerm, IsInt]); DeclareOperation("AsDigraph", [IsBinaryRelation]); DeclareOperation("AsDigraph", [IsTransformation]); DeclareOperation("AsDigraph", [IsTransformation, IsInt]); DeclareOperation("AsDigraph", [IsPerm]); DeclareOperation("AsDigraph", [IsPerm, IsInt]); +DeclareOperation("AsDigraph", [IsPartialPerm]); +DeclareOperation("AsDigraph", [IsPartialPerm, IsInt]); DeclareOperation("AsBinaryRelation", [IsDigraph]); DeclareOperation("AsSemigroup", [IsFunction, IsDigraph]); diff --git a/gap/digraph.gi b/gap/digraph.gi index e400ff2e9..c0ef7a829 100644 --- a/gap/digraph.gi +++ b/gap/digraph.gi @@ -1062,6 +1062,58 @@ InstallMethod(AsDigraph, "for a function and a perm", InstallMethod(AsDigraph, "for a perm", [IsPerm], p -> AsDigraph(AsTransformation(p))); +InstallMethod(AsDigraphCons, +"for IsMutableDigraph, a partial perm, and an integer", +[IsMutableDigraph, IsPartialPerm, IsInt], +function(filt, f, n) + local list, x, i; + if n < 0 then + ErrorNoReturn("the 2nd argument should be a non-negative integer,"); + fi; + + list := EmptyPlist(n); + for i in [1 .. n] do + x := i ^ f; + if x > n then + return fail; + elif x <> 0 then + list[i] := [x]; + else + list[i] := []; + fi; + od; + return DigraphNC(IsMutableDigraph, list); +end); + +InstallMethod(AsDigraphCons, +"for IsImmutableDigraph, a partial perm, and an integer", +[IsImmutableDigraph, IsPartialPerm, IsInt], +function(filt, f, n) + local D; + D := AsDigraph(IsMutableDigraph, f, n); + if D <> fail then + D := MakeImmutable(D); + SetIsMultiDigraph(D, false); + fi; + return D; +end); + +InstallMethod(AsDigraph, "for a function, a partial perm, and an integer", +[IsFunction, IsPartialPerm, IsInt], AsDigraphCons); + +InstallMethod(AsDigraph, "for a partial perm and an integer", +[IsPartialPerm, IsInt], +{t, n} -> AsDigraphCons(IsImmutableDigraph, t, n)); + +InstallMethod(AsDigraph, "for a function and a partial perm", +[IsFunction, IsPartialPerm], +{func, t} -> AsDigraphCons(func, t, Maximum(DegreeOfPartialPerm(t), + CodegreeOfPartialPerm(t)))); + +InstallMethod(AsDigraph, "for a partial perm", [IsPartialPerm], +t -> AsDigraphCons(IsImmutableDigraph, t, Maximum(DegreeOfPartialPerm(t), + CodegreeOfPartialPerm(t)))); + InstallMethod(AsBinaryRelation, "for a digraph", [IsDigraphByOutNeighboursRep], function(D) local rel; diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst index 9f2d76de9..5c0558caf 100644 --- a/tst/standard/attr.tst +++ b/tst/standard/attr.tst @@ -2792,6 +2792,36 @@ gap> D := DigraphRemoveEdge(D, 1, 3); gap> D := DigraphRemoveEdge(D, 1, 3); +# Semimodular lattices +gap> D := DigraphFromDigraph6String("&C[o?"); + +gap> IsUpperSemimodularDigraph(D); +false +gap> IsLowerSemimodularDigraph(D); +false +gap> NonUpperSemimodularPair(D); +Error, the argument (a digraph) is not a lattice +gap> NonLowerSemimodularPair(D); +Error, the argument (a digraph) is not a lattice +gap> D := DigraphFromDigraph6String("&K~~]mKaC_EgLb?_?~?g?m?a?b"); + +gap> IsUpperSemimodularDigraph(D); +true +gap> NonUpperSemimodularPair(D); +fail +gap> IsLowerSemimodularDigraph(D); +true +gap> NonLowerSemimodularPair(D); +fail +gap> D := DigraphFromDigraph6String("&M~~sc`lYUZO__KIBboC_@h?U_?_GL?A_?c"); + +gap> IsUpperSemimodularDigraph(D); +true +gap> IsLowerSemimodularDigraph(D); +false +gap> NonLowerSemimodularPair(D); +[ 10, 9 ] + # DIGRAPHS_UnbindVariables gap> Unbind(adj); gap> Unbind(adj1); diff --git a/tst/standard/digraph.tst b/tst/standard/digraph.tst index 3ad78e781..d8cbffcb6 100644 --- a/tst/standard/digraph.tst +++ b/tst/standard/digraph.tst @@ -479,7 +479,8 @@ fail gap> f := ();; gap> D := AsDigraph(f); -gap> D = EmptyDigraph(0);; +gap> D = EmptyDigraph(0); +true gap> AsDigraph(f, 10); gap> g := (1, 3, 7)(2, 6, 5, 8);; @@ -511,6 +512,41 @@ gap> D := AsDigraph(IsMutableDigraph, h, 6); gap> OutNeighbours(D); [ [ 1 ], [ 5 ], [ 2 ], [ 4 ], [ 3 ], [ 6 ] ] +# AsDigraph for a partial perm +gap> f := PartialPerm([]);; +gap> D := AsDigraph(f); + +gap> D = EmptyDigraph(0); +true +gap> AsDigraph(f, 10); + +gap> x := AsPartialPerm((1, 3, 7)(2, 6, 5, 8)); +(1,3,7)(2,6,5,8)(4) +gap> D := AsDigraph(x); + +gap> AsDigraph(x, -1); +Error, the 2nd argument should be a non-negative integer, +gap> AsDigraph(x, 0); + +gap> D := AsDigraph(g, 10); + +gap> AsDigraph(g, 7); +fail +gap> x := AsPartialPerm((2, 5, 3), 5); +(1)(2,5,3)(4) +gap> D := AsDigraph(IsMutableDigraph, x); + +gap> AsDigraph(IsImmutableDigraph, x, 5); + +gap> D = AsDigraph(IsImmutableDigraph, x, 5); +true +gap> D := AsDigraph(IsMutableDigraph, x, 6); + +gap> OutNeighbours(D); +[ [ 1 ], [ 5 ], [ 2 ], [ 4 ], [ 3 ], [ ] ] +gap> AsDigraph(AsPartialPerm((2, 5, 3)), 2); +fail + # RandomDigraph gap> IsImmutableDigraph(RandomDigraph(100, 0.2)); true