Repository navigation
Prune affix template partials whose required slots cannot find their material, in order and at the word edges - #575
johnml1135 wants to merge 8 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #575 +/- ##
==========================================
+ Coverage 75.33% 75.55% +0.22%
==========================================
Files 454 455 +1
Lines 38509 38915 +406
Branches 5335 5424 +89
==========================================
+ Hits 29010 29404 +394
Misses 8364 8364
- Partials 1135 1147 +12 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
07d7dca to
d957913
Compare
This comment has been minimized.
This comment has been minimized.
|
On the design question: the overlap is intended, and keeping both checks is the cheaper choice.
A shared builder would save only compile-time data, roughly one frozen feature-structure clone per anchored allomorph. Its per-word cost is unification either way. The repeated edge search (most of the look-ahead's unifications on Sena) fits #598, which already tracks repeated shape scans. I have not measured it, so I'm not claiming a saving there. |
…erial An analysis template partial now stops as soon as a required slot can no longer find the segments its affix inserts, instead of paying for every optional slot before the required one. The test is used only while every slot walked since is a pure copy-and-insert rule, so parses do not change. A count-only shadow mode and a null-by-default check observer let a harness verify soundness and cost on real grammars. Closes #561 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lking a template The required-slot look-ahead now needs each rule's inserted segments to match distinct segments in the order the rule inserts them, a slot that inserts only before or after its copied parts to find that material within the reach of the outer slots' own edge material, and the material of a required ordered slot to lie after the prefix and before the suffix of the required slots that unapply first. Slots that can reorder, repeat or remove from the middle switch the order and edge tests off for the slots behind them. Closes #567 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hed parts are unbounded runs, which restore no segments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y rules conservatively - Morpher.PruneRequiredSlots turns the prune off (default on); set it before parsing. - Tracing runs the slot rules without pruning, so failure reasons stay. - An allomorph with an untyped constraint is impure and unprunable, so a grammar that compiled before cannot throw. - A boundary-only insertion no longer counts as an infix. - Drop the redundant HasSegmentConstraint guard. - Tests for the optional-node rule, the suffix-side window, empty and deleted unbounded runs, and ordered copies.
Centralize opaque required-slot summary updates.
Since master's 98d902a a final template is not unapplied after a non-template rule unless the grammar has partial rules. The test's deletion rule leaves the word NonTemplate, so the unpruned parse was empty and the pruning on/off comparison had nothing to compare. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eference from a test comment Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d957913 to
a6e0ade
Compare
|
Verdict: approve. F11 and F12 are fixed in a6e0ade, and the branch is rebased onto master at 0cbf85f. No new findings. Most important: nothing open. Your answer on the edge-prefilter overlap settles last round's design question: the prefilter's edge constraints are sound only for the next slot, and dropping the duplicate next-slot check costs rule attempts. Counts: 0 Critical, 0 Important, 0 new Low. Ran: Not verified: the strict comment hygiene scan ( Public API: Findings: F1 addressed, F2 addressed, F3 addressed, F4 accepted (#598), F5 accepted (#598, unverified), F6 addressed, F7 addressed, F8 addressed, F9 addressed, F10 addressed, F11 addressed, F12 addressed. Reviewed at a6e0ade |
|
In general, I'd like to move away from turning optimizations off when tracing, so that tracing doesn't become slow and so that bugs in the optimization code are easier to identify. I propose that RequiredSlotCannotUnapply trace failures with something like FailureReason.UnreachableRequiredSlot along with the name of the slot. This will require a change to FieldWorks. I think that the user can figure out the failure from the slot name and the failure description. |
…ailureReason.UnreachableRequiredSlot with the slot Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Thanks, done in d3c5c06: the look-ahead stays on while tracing, and the tracing guard is gone.
FieldWorks change needed: |
|
No new findings. Reviewed at d3c5c06 |
|
FieldWorks follow-up for this PR: sillsdev/FieldWorks#1247 (draft), tracked as LT-22899. It updates FieldWorks' two FieldWorks will not compile against a SIL.Machine release that contains this PR until that PR merges. It stays a draft until such a release exists. At that point it bumps |
… template, and ignore slot and clitic partial rules in reachability An analysis dropped because it still owes a partial rule now leaves a TemplateAnalysisOutput trace node with FailureReason.OwedPartialCannotUnapply, the owing final template as source and the grammar's partial rules as FailureObject, as UnreachableRequiredSlot does in #575 (EndUnapplyTemplate gains the failureObj parameter, Trace gains FailureObject). Final-template state and the look-ahead are enabled only when the grammar has a final template that can be pruned. Reachability seeds only from non-template, non-clitic partial rules, the ones synthesis marks partial, so a grammar whose only partial rules sit in slots or are clitics prunes like one without partial rules. New grammars cx10 to cx12 and tests for the trace, the tracking flag and the work bound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Correction to the retired-instruction table in my earlier reply: two Amharic cells were wrong. The conclusion stands. I re-ran the Windows hardware-counter trial with a tighter instrument. It now uses 5 repeats, a 95% Welch interval with a 0.5% minimum effect, buffered output and stricter per-process attribution. I also re-measured the original builds with it, to separate instrument changes from newer PanGloss code. What was wrong: Amharic is not within noise in either row. The old 2-repeat figures were instrument noise.
What holds. Figures are the change with the mechanism turned off, on current code; + means the mechanism saves work.
¹ One word parses differently between the builds on current code, so it is left out of these two cells. The Mbugwe and Aweti figures are smaller because newer PanGloss code parses faster; the original builds still reproduce the earlier +7.1% and +20.2%. Sena's original builds read +3.3% under the new instrument. Removing the overlap still never saves instructions. With Amharic corrected, it measurably costs on Aweti and Amharic, and probably on Swahili. |
Start here:
src/SIL.Machine.Morphology.HermitCrab/RequiredSlotMaterial.cs-- the class remarks (Presence, Order) give the soundness argument for dropping a partial; the rest is wiring.Status: open, review required; head d3c5c06. CI was still running when this was written. #576 and #579 are folded into this branch (both show as merged); #580 (draft) is parked on top and #577 (draft) is parked.
HermitCrab's affix-template walk now drops a partial as soon as a required slot can no longer find the segments its affix inserts. Parses are unchanged; doomed partials stop paying for every optional slot between them and the required one. The slot's literals must appear in the order the rule inserts them and, for prefix-only or suffix-only slots, near the word edge; slots whose unmatched parts are unbounded runs keep being tested. Pruning is on by default;
Morpher.PruneRequiredSlots = falseturns it off (set it before parsing), and tracing prunes too: each prune is traced asFailureReason.UnreachableRequiredSlotwith the slot (Trace.FailureObject).The question a reviewer arrives with is "does it lose a parse?". Tests assert identical parses with pruning off and on for each hard case, and a shadow pass found 0 violations (carried over, see Evidence). A slot is tested only while every slot walked since is pure, ordered where order is used, and typed; untyped constraints and boundary-only inserts are handled conservatively. The question worth your time is the cost side: the look-ahead has its own unification cost, so whether it pays on real grammars.
Where to look
Apply_ImpureSlotBetween_DoesNotPruneForTheInnerRequiredSlot(purity gate),AnalysisAffixTemplateOrderTests(order and edge windowSlotWalk.Lo/Hi),AnalysisAffixTemplateFusionTests(unbounded runs).RequiredSlotMaterial.RestoredSegmentsagainstAnalysisMorphologicalTransform.Untruncate: an unbounded run must restore nothing, or the purity test is unsound.Apply_Parallel_ReturnsTheSameParsesAsSequential,Apply_TracingPrunedPartial_TracesTheUnreachableRequiredSlot.Apply_PublicPruningSwitch_ControlsRuleAttempts,Compile_UntypedConstraints_DisablesTheSummaryConservatively,Apply_BoundaryOnlyInfix_DoesNotMakeReachUnbounded.Not here: the performance follow-ups (repeated shape scans, narrowing, keeping shadow mode) are tracked in #598; #580 is parked; the stack was not re-measured on top of #569, which may reduce its value.
Verification at 91ee3da: HermitCrab tests 199/199 pass (Release);
dotnet csharpierand comment hygiene clean; the HermitCrab project builds with 0 warnings. The fulllocal_check.shdid not complete (cmake is missing for SentencePiece). The measurements below were not re-run at this head.Next: review
RequiredSlotMaterial.cs, and say whether the cost side justifies merging before #569 is measured.Reading this a year from now -- start here
This branch is four commits on master c245476: 0bf9e64 (the required-slot prune, issue #561), 28cbee1 (was PR #576: slot literals in order and at reachable edges, issue #567), faa2499 (was PR #579: keep testing behind slots whose unmatched parts are unbounded runs) and 91ee3da (review fixes). #576 and #579 were separate stacked PRs and were folded in so the look-ahead is reviewed once. All of it runs under the internal
RequiredSlotLookaheadMode(Off,Shadow,On);Morpher.PruneRequiredSlotsis the public on/off view of it. The unification and census counters that produced the numbers below are not in this PR; they live on the research branchesresearch/hc-rsl-census@6ad11702andresearch/hc-ordered-census@4bb687f0.Decisions, and why
RequiredSlotCheckObserver(null by default) are kept for the soundness tests; whether to keep them is part of HermitCrab analysis: measure the required-slot look-ahead's repeated scans, narrowing and shadow diagnostics in steps #598.Untruncatewrites nothing for it, so a slot whose unmatched parts are unbounded runs stays pure. Bounded runs, bare restored segments, alternations with an optional branch andModifyFromInputstay impure.UnreachableRequiredSlotwith the slot, which needs a FieldWorks change (EndUnapplyTemplategains afailureObjparameter); an allomorph with an untyped constraint is impure and unprunable; boundary-only inserts do not make the edge reach unbounded.Paths not taken
Evidence (carried over, not re-run at 91ee3da)
All figures are from the bodies of #575, #576 and #579 before the fold, measured on those PRs' own heads (before the review-fix commit; the #579 figures also before #522 removed the analysis memo). They are not from 91ee3da.
Deferred, and what would unblock it
🤖 Generated with Claude Code
This change is