Repository navigation
Conversation
A 1x1 tiling whose class is closed under rotation (the cyclic shift that moves the
first entry to the end), which is when its basis is rotationally stable, has n times
as many permutations of length n as its min cut, {p : 1 + p in the class}, or its
max cut, {p : p + 1 in the class}, has of length n - 1: exactly one rotation of each
permutation starts with its minimum, and exactly one ends with its maximum. A class
closed under the cyclic shift of the values (its inverse basis is rotationally
stable) has the same two cuts. RotationalCutFactory adds the rule to each cut, the
max cut only when it is a different class, with RotationalCutConstructor:
F(x) = 1 + x (x C(x))' for the whole class, and x (x C(x))' for its nonempty part.
TileScopePack.make_rotational adds the factory to a pack.
It moves the rotationally stable strategy of Permuta's pull request #207, which was
closed in favor of a strategy in Tilings, into a strategy here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uts and hints TileScopePack.add_rotational_cuts (was make_rotational) adds the rotational cut strategies to any pack, whose name gets the suffix _rotational_cuts, and tilescope spec's new flag -r/--rotational-cuts does the same on the command line. tilings.hints gathers hints: properties of a class that make it likely that a change to a pack helps the search, where Permuta's enumeration strategies settle a count outright. The first is a class closed under rotation: the hint names its cuts and suggests the rotational cuts. tilescope spec logs the hints that the pack it runs does not follow. The packs' JSON tests cover the new modifier. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code that builds its own argparse.Namespace for build_pack, as some callers did before the flag existed, broke on the new attribute (an AttributeError, found on a test run on a cluster). build_pack now reads it with getattr, and a test calls it with such a namespace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tests As a reviewer asked: pattern, patterns, obstruction, value, shift, length, child_object, objects and jsonable in place of patt, patts, ob, val, k, n, obj, objs and d, and size, gridded_perm, equation, parent_function and cut_function in the tests. The parameters the strategy's base classes name (n, idx, obj, objs, d) keep their names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he CLI The review's round 1, and Henning's directions for the hint. - RotationalCutRule: the rule of a cut is a NonBijectiveRule, as FusionRule is. Its forward map sends the n rotations of 1 + p (or of p + 1) to p, and it tells them apart by their index among the rotations its backward map yields, so a bijection through a cut is one to one. - The hint names the class to search for instead: the cut, cut again while it is closed under rotation, with n (n - 1) ... times the count of the last cut, and F = 1 + x (x G)' once for each cut. It still mentions the rotational cuts for the pack. A Hint now names the strategies that follow it, and the CLI asks it whether the pack has them (Hint.followed_by), rather than undoing argparse's naming of a flag. hints is now hints_for. - tilescope spec says when it cannot compute the generating function of the specification it found, as for a cut, whose equation has a derivative, or for catalytic variables, rather than ending with an error. - is_rotationally_stable minimizes the basis first, so it answers for the class. rotation_of is now rotation_kind, through one helper with the strategy. Permuta's shift_up, remove and inverse_set are used. max_cut_differs decides whether the max cut is another class, for the factory and the hint alike. - A rotation is defined as the cyclic shift, not Perm.rotate's quarter turn, in the module, the README and the CHANGELOG. The README's example is a class whose cut is used, with the class the hint names. The CHANGELOG lists the public names. - Tests, the review's among them: a bijection through a cut, the strategy's and the constructor's flags and predicates, a basis that is not minimal, Av(12, 21) and a class closed under both rotations, the chain of cuts down to Av(12), an equation for a cut that is not a geometric series, the hint's class and chain, and tilescope spec's hint logging and its message with no generating function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
comb_spec_searcher's auto_search checks for a specification at times that depend on the clock, so with the rotational cuts it can find one with or without a cut. On a loaded machine, PyPy 3.11 found Av(123, 231, 312)'s without one, and the bijection test failed on its premise. - test_a_bijection_through_a_cut_is_one_to_one puts its specification together from the cut's rule and a specification of the cut, so the cut is always in it. It still fails on a plain Rule and on either order method. - test_spec_tells_of_the_hint_unless_the_pack_follows_it, with the flag, takes either message about the generating function: there is none to show when the specification has a cut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the rotational cut, a strategy for permutation classes closed under rotation, and hints, which tell a TileScope user when a simpler class is worth searching for instead. Permuta#207 proposed this as an enumeration strategy in Permuta; it was closed because it belongs in Tilings as strategies, and this moves it here.
The idea
A rotation here is the cyclic shift that moves a permutation's first entry to its end (
Perm.shift_left), not the quarter turn ofPerm.rotate. The n rotations of a permutation of length n are distinct, and exactly one of them starts with its minimum. So a class closed under rotation has n times as many permutations of length n as its min cut, the permutations p for which the class has 1 followed by p raised by one, has of length n − 1. Exactly one rotation ends with the maximum too, so the max cut (p followed by a new maximum) counts the class the same way, and it can be a different class. A class closed under the same shift of its values has the same two cuts.What it adds
RotationalCutFactoryandRotationalCutStrategy(tilings/strategies/rotation.py): for a 1x1 tiling without assumptions whose class is closed under rotation, of its positions or of its values (the whole class, or its nonempty permutations), the rule to the min cut, and to the max cut when that is a different class. In a search, a cut that is closed under rotation again is cut again. The rule counts, generates and samples objects, soRule.sanity_checkchecks all three.RotationalCutRule, aNonBijectiveRuleasFusionRuleis: its forward map sends the n rotations to one object of the cut, and tells them apart by their index among the rotations, so a bijection between specifications through a cut is one to one.TileScopePack.add_rotational_cutsand thetilescope specflag-r/--rotational-cuts.tilings.hints:hints_for(basis)returns the hints (Hint) for a class. The first is for a class closed under rotation: it names the class to search for instead, the cut, cut again while it is closed under rotation, and how its counts and generating function give the class's.tilescope speclogs the hints that its pack does not follow.tilescope specno longer ends with an error when it cannot compute the generating function of the specification it found; it says so. That happens for every specification with a rotational cut, as comb_spec_searcher'sget_genfcannot solve an equation with a derivative, and also fordevelop's specifications with catalytic variables (as with--fusionon Av(123)).is_rotationally_stable,rotation_kind,min_cut,max_cutandmax_cut_differs, and README and CHANGELOG entries.Why a rule, not a verification
The cut is searched for like any other class, and the rule has an equation, generates objects and samples. A verification strategy would instead promise that a nested search enumerates the class. As comb_spec_searcher cannot compute a generating function through the rule, the hint points to the cut instead, whose generating function gives the class's.
Who will use it
TileScope users with a class closed under rotation: the hint tells them which simpler class to run, and the strategy cuts such classes wherever a search meets them. Henning's TileScope runs use it.
Tests
In
tests/strategies/test_rotation.py,tests/test_hints.py, and the encoding and pack tests:tilescope spec's hint logging, its flag, and its message when it cannot compute a generating function;add_rotational_cuts, through JSON;point_placements().add_rotational_cuts()on [1234] = Av(1234, 2341, 3412, 4123), which finds a specification with a rotational cut in about a second, with counts 1, 1, 2, 6, 20, 65, 198, 560, 1480. Its generating function, derived from the cut's (Av(123, 3412)), is (1 - 8x + 27x^2 - 48x^3 + 49x^4 - 27x^5 + 6x^6 - 4x^7)/((1 - 2x)^2 (1 - x)^5).How it was checked
Before submission, by an automated reviewer, against
developof all three libraries:developand on this branch, which run equally fast.AI assistance: written with Claude Code (Opus 5.5) as the TileScope agent, and reviewed before submission by Claude Code (Opus 5.5) as an automated reviewer; Henning Ulfarsson checked and opened it.