Skip to content

Implement IsJoinIrreducible and IsMeetIrreducible#910

Open
ThatOtherAndrew wants to merge 8 commits intodigraphs:mainfrom
ThatOtherAndrew:pr/joinmeetirreducible
Open

Implement IsJoinIrreducible and IsMeetIrreducible#910
ThatOtherAndrew wants to merge 8 commits intodigraphs:mainfrom
ThatOtherAndrew:pr/joinmeetirreducible

Conversation

@ThatOtherAndrew
Copy link
Copy Markdown

Adds two new operations to section 10 (Operations for vertices) of oper.gi/oper.gd:

  • IsJoinIrreducible(D, v) — returns true if vertex v is not the join of any two distinct smaller nodes in D
  • IsMeetIrreducible(D, v) — returns true if vertex v is not the meet of any two distinct larger nodes in D

Both were originally implemented by building the full O(N²) join/meet table, but then optimised to use DigraphReflexiveTransitiveReduction, a function producing a Hasse diagram which allows for a computational shortcut (see SageMath docs below):

https://doc.sagemath.org/html/en/reference/combinat/sage/combinat/posets/hasse_diagram.html#sage.combinat.posets.hasse_diagram.HasseDiagram.find_nontrivial_congruence

Tests are merged into tst/standard/oper.tst, covering N5, a chain, B2, M3, and error handling (two test case sets written by myself and the rest with LLM assistance because I do not think my mathematical knowledge of the underlying concepts is strong enough to come up with reasonably comprehensive/diverse test cases).


Closes #400

@ThatOtherAndrew
Copy link
Copy Markdown
Author

Requesting a review from @james-d-mitchell please - how does this look? Is the PR description sufficiently detailed and mathematically accurate?

Copy link
Copy Markdown
Member

@james-d-mitchell james-d-mitchell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! If you also resolve #714, then this PR (or the code if merged first) should be updated to check for that rather than IsPartialOrderDigraph. Otherwise, this looks good to me!

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.36%. Comparing base (1f56fb0) to head (8ae6cba).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #910   +/-   ##
=======================================
  Coverage   97.35%   97.36%           
=======================================
  Files          50       50           
  Lines       21045    21069   +24     
  Branches      639      639           
=======================================
+ Hits        20489    20513   +24     
  Misses        491      491           
  Partials       65       65           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

If I understand correctly, InDegrees is faster than InDegreeOfVertexNC here due to caching behaviour where the in degrees of the digraph are computed once then looked up from cache, as opposed to the other function which has to recompute for each input vertex.

Co-authored-by: James Mitchell <james-d-mitchell@users.noreply.github.com>
@ThatOtherAndrew ThatOtherAndrew marked this pull request as ready for review April 1, 2026 15:44
Copilot AI review requested due to automatic review settings April 1, 2026 15:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds vertex-level operations to determine join-/meet-irreducibility on order-structured digraphs, and extends the standard operations test suite to cover these new APIs (motivated by #400).

Changes:

  • Declares new operations IsJoinIrreducible and IsMeetIrreducible in the operations interface.
  • Implements both operations in gap/oper.gi using the reflexive transitive reduction (Hasse diagram) as a shortcut.
  • Adds test coverage in tst/standard/oper.tst for several small lattices and input validation.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
gap/oper.gd Declares the two new public operations.
gap/oper.gi Implements irreducibility checks via Hasse-diagram degree counts.
tst/standard/oper.tst Adds tests for N5, chains, B2, M3, plus error handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2727 to +2736
local hasse;
if not IsPartialOrderDigraph(D) then
ErrorNoReturn("the 1st argument <D> must satisfy IsPartialOrderDigraph,");
elif not v in DigraphVertices(D) then
ErrorNoReturn("the 2nd argument <v> must be a vertex of the ",
"1st argument <D>,");
fi;
hasse := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D));
# join-irreducible iff at most one lower cover in the Hasse diagram
return InDegrees(hasse)[v] <= 1;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsJoinIrreducible is implemented as “at most one lower cover in the Hasse diagram”. This implication only holds in (finite) join-semilattices/lattices; for a general partial order it can be wrong (e.g. two incomparable minimal upper bounds means joins may not exist, yet a vertex can have multiple lower covers while still not being the join of any two smaller vertices). Consider either tightening the precondition to IsJoinSemilatticeDigraph/IsLatticeDigraph (and error accordingly), or implementing the join-based definition via PartialOrderDigraphJoinOfVertices so the result matches the operation’s stated meaning for arbitrary partial orders.

Suggested change
local hasse;
if not IsPartialOrderDigraph(D) then
ErrorNoReturn("the 1st argument <D> must satisfy IsPartialOrderDigraph,");
elif not v in DigraphVertices(D) then
ErrorNoReturn("the 2nd argument <v> must be a vertex of the ",
"1st argument <D>,");
fi;
hasse := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D));
# join-irreducible iff at most one lower cover in the Hasse diagram
return InDegrees(hasse)[v] <= 1;
local verts, i, j, x, y, join;
if not IsPartialOrderDigraph(D) then
ErrorNoReturn("the 1st argument <D> must satisfy IsPartialOrderDigraph,");
elif not v in DigraphVertices(D) then
ErrorNoReturn("the 2nd argument <v> must be a vertex of the ",
"1st argument <D>,");
fi;
# An element v is join-irreducible if it is not the join of
# two distinct strictly smaller elements. We check all unordered
# pairs of vertices (x, y) with x <> y and neither equal to v.
verts := DigraphVertices(D);
for i in [1 .. Length(verts) - 1] do
x := verts[i];
if x = v then
continue;
fi;
for j in [i + 1 .. Length(verts)] do
y := verts[j];
if y = v then
continue;
fi;
join := PartialOrderDigraphJoinOfVertices(D, x, y);
if join = v then
# v can be expressed as the join of two distinct smaller elements
return false;
fi;
od;
od;
# No such pair found; v is join-irreducible.
return true;

Copilot uses AI. Check for mistakes.
Comment on lines +2744 to +2752
if not IsPartialOrderDigraph(D) then
ErrorNoReturn("the 1st argument <D> must satisfy IsPartialOrderDigraph,");
elif not v in DigraphVertices(D) then
ErrorNoReturn("the 2nd argument <v> must be a vertex of the ",
"1st argument <D>,");
fi;
hasse := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D));
# meet-irreducible iff at most one upper cover in the Hasse diagram
return OutDegreeOfVertexNC(hasse, v) <= 1;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsMeetIrreducible relies on “at most one upper cover in the Hasse diagram”, which (like the join case) is only equivalent to “not a meet of two distinct larger elements” when meets exist appropriately (e.g. meet-semilattices/lattices). For arbitrary partial orders, vertices can have multiple upper covers while no such meet representation exists. Either restrict the accepted digraphs to IsMeetSemilatticeDigraph/IsLatticeDigraph, or compute using the actual meet operation to match the documented semantics.

Copilot uses AI. Check for mistakes.
fi;
hasse := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D));
# join-irreducible iff at most one lower cover in the Hasse diagram
return InDegrees(hasse)[v] <= 1;
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsJoinIrreducible uses InDegrees(hasse)[v], which computes indegrees for all vertices even though only one value is needed. Using InDegreeOfVertexNC(hasse, v) (mirroring the OutDegreeOfVertexNC usage below) avoids the extra O(|V|+|E|) work per call on large digraphs.

Suggested change
return InDegrees(hasse)[v] <= 1;
return InDegreeOfVertexNC(hasse, v) <= 1;

Copilot uses AI. Check for mistakes.
Comment on lines +2728 to +2735
if not IsPartialOrderDigraph(D) then
ErrorNoReturn("the 1st argument <D> must satisfy IsPartialOrderDigraph,");
elif not v in DigraphVertices(D) then
ErrorNoReturn("the 2nd argument <v> must be a vertex of the ",
"1st argument <D>,");
fi;
hasse := DigraphReflexiveTransitiveReduction(DigraphMutableCopyIfMutable(D));
# join-irreducible iff at most one lower cover in the Hasse diagram
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only explicit precondition checked is IsPartialOrderDigraph(D), but IsPartialOrderDigraph does not exclude multidigraphs. If D has multiple edges, DigraphReflexiveTransitiveReduction will throw a different error (“must be a digraph with no multiple edges”) from inside this method. Consider either rejecting multidigraphs up front with a clear error, or normalizing the copied digraph by removing multiple edges before computing the reduction.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement IsJoin/MeetIrreducible for vertices in lattice digraphs

3 participants