From 6ea22f2da1aa476e8cf11d670aaf62f80875ac83 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Mon, 24 Aug 2026 23:30:47 +0000 Subject: [PATCH] Two rule sets run on the matcher rather than on their switch #746 tier 1 records pattern matching as data (#248) as delivered and then says what is wrong with that: the engine exists and **nothing runs on it** -- every type in `Core/Transformations/Matching` is internal, five sets are expressed as data, and 0 of the 30 registered sets used the matcher at run time. The reason was a number. Swapping `DivisionPreparing` for its data form had been measured at about 5% of `Simplify`, and 5% for one of thirty sets is not affordable. #1050 changed that number by settling a pattern's determinism once instead of on every attempt. Re-measured against `Simplify` itself -- both arms in one process, plus a third arm that is the switch again as a control, because comparing two runs on this machine measures the machine: switch median 539 ms data median 536 ms -0.6% control median 533 ms -1.1% <- the switch against itself The change is smaller than this machine's disagreement with itself. Allocation is 38,181,736 B against 38,196,896 B, +0.04%. So `DivisionPreparing` and `CollapseMultipleFractions` now execute as data. They are the two whose data form is proven to agree with the switch it mirrors over generated expressions, with a minimum firing count so agreement cannot be vacuous -- which is the precondition for running one in place of the other. The switch stays, and is not dead code. `RewriteRule` carries a `PatternSource` and a `SourceLine` that `RuleRegistryGenerator` reads off a switch's arms, and it cannot yet read a rule written as data, so the addressable rules of these two sets still come from `Patterns` and describe arms the agreement test holds the matcher to. Teaching the generator to read `MatchedRules` is what would let the switch go, and is #825. Measured, not assumed: suite 8553/0, and rulecheck, canoncheck, casbench and simpsweep are byte-identical to master's committed reports -- rulecheck reporting 0 value changes across 1005 applications of 30 sets, which is the harness that attributes a change to a named set. Part of #746 tier 1 (#248). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Bjumi5K7fg8yx6UK1mZTQd --- .../Core/Transformations/RewriteRules.cs | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/Sources/AngouriMath/Core/Transformations/RewriteRules.cs b/Sources/AngouriMath/Core/Transformations/RewriteRules.cs index 2396956b3..4f10610f4 100644 --- a/Sources/AngouriMath/Core/Transformations/RewriteRules.cs +++ b/Sources/AngouriMath/Core/Transformations/RewriteRules.cs @@ -117,12 +117,17 @@ public static class RewriteRules /// /// Gets a quotient into the shape the division rules expect before they run. /// + /// + /// Run by the matcher rather than by the switch — + /// . See the note on + /// for what that costs and what still describes it. + /// public static RewriteRuleSet DivisionPreparing { get; } = new( nameof(DivisionPreparing), "Lifts numeric factors out of a quotient so that the division rules can see it.", TransformationRelation.Equivalence, Soundness.SoundUnderAssumptions, - Patterns.DivisionPreparingRules, + Matching.MatchedRules.DivisionPreparing.ApplyHere, Patterns.DivisionPreparingRulesArms); /// @@ -204,12 +209,41 @@ public static class RewriteRules /// /// Brings a quotient of quotients down to a single one. /// + /// + /// + /// Run by the matcher rather than by the switch — + /// . This and + /// are the two sets whose data form is proven to agree + /// with the switch it mirrors over generated expressions + /// (MatchedRulesAgreeWithTheSwitchTest), which is the precondition for running one + /// instead of the other. + /// + /// + /// What it costs. Measured against Simplify itself, both arms in + /// one process with a third arm that is the switch again as a control: the data form + /// is −0.6% where the control differs from its own source by −1.1%, so the change is + /// smaller than this machine's disagreement with itself, and allocation is +0.04%. That + /// number used to be +5% for alone, and what closed it was + /// settling a pattern's determinism once rather than on every attempt + /// (#1050). + /// + /// + /// The switch is still what describes them. carries + /// a and a , + /// which RuleRegistryGenerator reads off the arms of a switch; it has no way + /// yet to read a rule written as data. So the addressable rules of these two sets still come + /// from Patterns, and the arms they describe are the ones the agreement test holds + /// the matcher to rather than dead code. Teaching the generator to read + /// is what would let the switch go, and is + /// #825. + /// + /// public static RewriteRuleSet CollapseMultipleFractions { get; } = new( nameof(CollapseMultipleFractions), "Collapses nested quotients into a single numerator over a single denominator.", TransformationRelation.Equivalence, Soundness.SoundUnderAssumptions, - Patterns.CollapseMultipleFractions, + Matching.MatchedRules.CollapseMultipleFractions.ApplyHere, Patterns.CollapseMultipleFractionsArms); ///