Skip to content

A rational coefficient beside a variable never reaches a fixed point at the safe ceiling #1200

Description

@Rafael-SOWNet

At the safe ceiling (RulesUpTo(Rearranges)), seven of the 3,630 shapes in the growth corpus never
report a fixed point, and they are one family: a rational coefficient beside a variable.

Measured (build 98a9420c, after #1198)

WorkBudget { Steps = 200_000, Time = 30 s }, one input per graph:

input fixed point e-nodes after 30 s e-nodes after 2 s extracted
2 * x * 1/2 no 158 — x
x * 1/2 * 2 no 135 — x
(2 - 0) * x * 1/2 no 159 182 x
x / x * -x no 583 464 -x
x / x * x * 1/2 no 249 282 x / 2
x / x * x ^ (-2) no 317 291 x ^ (-2)
1 / (1/2) * x * 1/2 no 159 181 x
x ^ 2 / x no 145 109 x
2 ^ (-1) / sqrt(1/2) no, step ceiling 1,565 1,072 sqrt(1/2)

So this is a stall, not a runaway: the graph barely grows with fifteen times the budget, and
every extraction is right. ConstantFoldTest.ACoefficientBesideAVariableStallsRatherThanRunsAway
pins it in both directions — an entry that starts saturating is to be deleted, and one that grows
past a thousand e-nodes has stopped being a stall.

What it is

The spellings of a coefficient beside a variable — 1/2 * x, x / 2, x * 2 ^ (-1),
2 ^ (-1) * x — are exchanged by Rearranges rules (a-reciprocal-rational-factor-is-a-division,
a-reciprocal-power-is-a-quotient, the quotient and product regrouping rules of Common), and a
fresh spelling keeps appearing at the edge of what has been rewritten, so a pass never comes back
empty. Before #1198 the same rules ran away on constant-only input (2 - 0 + 0 * 2, 54 cases),
because with nothing folding a number the spellings were unbounded; folding rationals on
insertion bounded the family without closing it. RunawayBreadthTest had called these rules
"confluent on plain arithmetic" from three inputs; it now says what was measured.

What would close it, not decided

Either a normal form for a rational coefficient inside the graph — c * x with c a literal,
folded on insertion the way a rational over rationals now is — or an orientation among the
spelling rules so that only one direction fires under saturation. The first is a mechanism; the
second is what the growth ceiling already does for expanding rules and would need a marker for
"rearranges, but one way". Neither is worth doing until something calls the graph on this shape;
Transformation.CanonicalizationOverGraph is offered, not applied.

Found while measuring #746 tier 2 item 4 (PR #1198). Related: the budget overshoot on these
same inputs, filed separately.

Activity

  1. Rafael-SOWNet commented on Sep 7, 2026

    @Rafael-SOWNet
    MemberAuthor

    The budget overshoot on these same inputs is #1199.

  2. Rafael-SOWNet commented on Sep 7, 2026

    @Rafael-SOWNet
    MemberAuthor

    A correction, measured once extraction stopped being the cost (the fix for #1199 makes a whole-graph extraction a fixed point from the leaves up; the old top-down walk took 1.9 s on a 253-node graph, which is what made these look bounded). Same inputs, 200,000 steps / 30 s, safe ceiling:

    input fixed point e-nodes wall
    x ^ 2 / x no 11,755 30.0 s
    x / x * -x no 12,563 30.0 s
    x / x * x * 1/2 no 10,773 30.0 s
    2 ^ (-1) / sqrt(1/2) no, step ceiling 1,565 3.7 s
    x * 1/2 * 2 no, step ceiling 1,022 1.0 s
    2 * x * 1/2, (2 - 0) * x * 1/2, 1 / (1/2) * x * 1/2 no, step ceiling 558–559 0.2–0.8 s

    So this is two families, not one stall: the three with an x / x or x ^ 2 / x are genuine runaways at about 400 e-nodes a second, and the coefficient-only ones plateau at some 560 e-nodes and stop because the steps run out. "Bounded at 135–583 e-nodes after thirty seconds" above was the slow extraction, not the graph. Every one still extracts the right answer, and the budget is now honoured to the millisecond, so what bounds them is the budget and nothing intrinsic. ConstantFoldTest is corrected to say the same.

  3. Rafael-SOWNet commented on Sep 7, 2026

    @Rafael-SOWNet
    MemberAuthor

    The practical cost of this is gone with #1206, without pretending the rules are confluent. The two public transformations that extract an answer — Transformation.EqualitySaturation (cheapest member) and Transformation.CanonicalizationOverGraph (least member) — now stop once the extraction has survived two passes unchanged, which on these inputs comes on the third pass where the graph's own fixed point never does. Measured through both, before and after, on the corpus gate's forty problems and the nine inputs above: every answer identical, and the run of all of them 13,495 ms → 320 ms — x / x * -x 1,869 → 10 ms, x ^ 2 / x 2,010 → 3 ms, 2 ^ (-1) / sqrt(1/2) 998 → 2 ms. Saturation.ProvesEqual keeps saturating (it needs a union, not an extraction) and the bare Saturation.Run still runs away on this family, which ConstantFoldTest still pins.

    So this stays open as the question about the rules — a normal form for a coefficient's spellings inside the graph, or an orientation among the regrouping rules — but nothing a caller reaches waits on it any more.

  4. added this to the 2.6.0 milestone on Sep 18, 2026
  5. added theissue type on Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions