Put the canonicalizers where a caller will look for them, and settle the -ize spelling (#746) - #940
Merged
Merged
Conversation
Both existed only as Transformation objects, reachable by someone who already knew the transformation layer existed. Entity.Canonicalise() and Entity.CanonicaliseAsRationalFunction() put them beside Simplify, Expand and Factorize, which is where a caller looks. Wiring them into the pipeline is a different question and the answer is that there is nothing to wire. Simplify already runs CanonicalOrder before its rules -- that is what makes a binary rule find sin(x)^2 + cos(x)^2 buried in a longer sum -- and Canonicalisation *is* InnerSimplification composed with the sort, so it cannot go inside InnerSimplified without containing itself. What was missing was reach, not application. The rational one returns null where the expression is not a rational function over Q, which is the library's own way of saying "no answer" and keeps the boundary in the signature: a form whose whole value is that equal trees mean equal expressions must not hand back a normalisation that resembles one. Neither is applied by anything, and a test pins that: InnerSimplified still leaves "y + x" alone and Simplify still leaves "1/x + 1/y" split. Turning either on by default moves every commutative operand order in every printed answer, and that is a release's decision rather than a method's. Measured: suite 7087 passed / 0 failed, 17 of them new. #746 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…746) The public surface is Factorize, Latexize, Stringize, Normalization, Factorization. Five members were not, so the same operation had two spellings depending on which one a caller reached for. Entity.Canonicalise -> Canonicalize Entity.CanonicaliseAsRationalFunction -> CanonicalizeAsRationalFunction Transformation.Canonicalisation -> Canonicalization Transformation.RationalCanonicalisation -> RationalCanonicalization Transformation.Rationalisation -> Rationalization RewriteRules.RationaliseDenominator -> RationalizeDenominator The first four have not shipped. The last two are in the v2.1.0 tag, so they get a BREAKING-CHANGES entry: the compiler names the missing member, which makes it a build error rather than a wrong answer, and the only silent part is the rule set's Name, which comes from nameof. Prose keeps British spelling. Factorize has always sat beside the word "factorisation" and still does; the convention is about identifiers, not about the documentation. Also renamed a private LongDivision.Canonicalise helper that predates this work, so that a grep for the British spelling now returns only prose. Measured: suite 7087 passed / 0 failed. Library, unit tests, benchmark project and the F# wrapper all build under -c Release; the two Windows-only sample projects fail on Linux as they did before. #746 Co-authored-by: Claude Opus 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.
Both canonicalisers existed only as
Transformationobjects, reachable by someone who already knew the transformation layer existed. This puts them besideSimplify,ExpandandFactorize.Wiring them into the pipeline turned out not to be a thing to do
Simplifyalready runsCanonicalOrderbefore its rules — that is what lets a binary rule findsin(x)^2 + cos(x)^2buried in a longer sum. AndCanonicalizationisInnerSimplificationcomposed with the sort, so it cannot go insideInnerSimplifiedwithout containing itself.What was missing was reach, not application.
The rational one refuses, and says so by answering nothing
nullwhere the expression is not a rational function over ℚ — the library's own way of saying "no answer", and it keeps the boundary in the signature. A form whose whole value is that equal trees mean equal expressions must not hand back a normalisation that merely resembles one.Cancelling still carries its condition:
x/xis1 provided not x = 0, and is not equal to the canonical form of1. There is a test saying exactly that.Nothing is applied by default
Pinned by a test:
InnerSimplifiedstill leavesy + xalone, andSimplifystill leaves1/x + 1/ysplit. Turning either on by default moves every commutative operand order in every printed answer — a release's decision, not a method's.And the spelling is settled, in the direction the surface already went
The second commit renames five members so that one operation has one spelling:
Entity.CanonicaliseCanonicalizeEntity.CanonicaliseAsRationalFunctionCanonicalizeAsRationalFunctionTransformation.CanonicalisationCanonicalizationTransformation.RationalCanonicalisationRationalCanonicalizationTransformation.RationalisationRationalizationRewriteRules.RationaliseDenominatorRationalizeDenominatorThe rest of the surface is
Factorize,Latexize,Stringize,Normalization,Factorization, so the odd ones out were the-isefive.The last two are in the
v2.1.0tag and so get aBREAKING-CHANGES.mdentry. It breaks a build rather than an answer — the compiler names the missing member. The one silent part is the rule set'sName, which comes fromnameof, so a caller matching the string"RationaliseDenominator"now sees"RationalizeDenominator".Prose keeps British spelling.
Factorizehas always sat beside the word "factorisation" and still does; the convention is about identifiers, not documentation. A privateLongDivision.Canonicalisehelper predating this work was renamed too, so a grep for the British spelling now returns only prose.Measured
Suite 7087 passed / 0 failed, 17 of them new, run after the rename.
docsamplesagainst a build of the first commit: 84 samples, 0 compile errors, 0 output mismatches, 57 outputs verified. Library, unit tests, benchmark project and the F# wrapper all build under-c Release; the two Windows-only sample projects fail on Linux exactly as they do on master.PublicApi.txtrecords every addition and rename, and the alphabetical ordering was re-checked becausesandzdo not sort alike.🤖 Generated with Claude Code