Skip to content

Stop REAL_RAT_REDUCE_CONV diverging on rational literals - #2036

Merged
mn200 merged 2 commits into
HOL-Theorem-Prover:developfrom
lukaszcz:real-rat-reduce-termination
Aug 11, 2026
Merged

Stop REAL_RAT_REDUCE_CONV diverging on rational literals#2036
mn200 merged 2 commits into
HOL-Theorem-Prover:developfrom
lukaszcz:real-rat-reduce-termination

Conversation

@lukaszcz

Copy link
Copy Markdown
Contributor

The bug

REAL_RAT_DIV_CONV rewrites x / y to x * inv y and back, so on a
literal already in lowest terms it returns |- &1 / &3 = &1 / &3
success, no change. computeLib re-evaluates whatever a registered
conversion hands back, so CBV_CONV went round that term forever:
REAL_RAT_REDUCE_CONV did not terminate on any term containing a
non-integral rational literal.

The fix

real_rat_compset already guarded one entry — REAL_RAT_NEG_CONV
with CHANGED_CONV. Several of the others are no-ops on an
already-reduced argument in the same way, so the guard belongs on every
entry rather than on whichever operator's no-op was noticed first. The
compset now adds all of them through a single add_reduce_conv that
applies it.

A registered conversion can report no progress in two ways: return a
reflexive theorem, or raise UNCHANGED (as ALL_CONV, hence
TRY_CONV, does). Both are fatal — the first loops, the second escapes
CBV_CONV entirely, because reduce_cst catches only HOL_ERR when
deciding to move on to the next rule. Conv.CHANGED_CONV covers both,
so it needs no QCHANGED_CONV around it; QCHANGED_CONV in its place
would be a regression, since it catches only the raise and lets the
diverging mode through. A comment at the site records this so the
question is not reopened.

Tests

src/real/selftest.sml gains a test that the conversion terminates on
&1 / &3 * x, plus a companion pinning that &1 / &3 + &1 / &6 still
reduces to &1 / &2 — so the termination guard cannot be satisfied by
simply disabling reduction.

Scope

This is the instance half of #2034. The underlying computeLib
mechanism — reduce_cst counting a reflexive result as progress — and
the add_conv documentation that never stated the contract are
deliberately left alone here.

REAL_RAT_DIV_CONV rewrites x / y to x * inv y and back, so on a literal
already in lowest terms it returns |- &1 / &3 = &1 / &3: success, no
change.  computeLib re-evaluates whatever a registered conversion hands
back, so CBV_CONV went round that term forever, and
REAL_RAT_REDUCE_CONV did not terminate on any term containing a
non-integral rational literal.

The compset already guarded one entry, REAL_RAT_NEG_CONV, with
CHANGED_CONV.  The guard belongs on every entry rather than on
whichever operator's no-op was noticed first, so real_rat_compset now
adds them through one function that applies it.

A registered conversion can report no progress in two ways: return a
reflexive theorem, or raise UNCHANGED (as ALL_CONV, hence TRY_CONV,
does).  Both are fatal -- the first loops, the second escapes CBV_CONV
entirely, because reduce_cst catches only HOL_ERR when deciding to move
on to the next rule.  Conv.CHANGED_CONV covers both, so it needs no
QCHANGED_CONV around it, and QCHANGED_CONV in its place would be a
regression: that one catches only the raise and lets the diverging mode
through.  A comment at the site records this so the question is not
reopened.

Found via a normaliser that runs REAL_RAT_REDUCE_CONV after
REAL_POLY_CONV: the latter turns x / 3 into 1 / 3 * x, so any real goal
containing a division by a non-unit literal hung outright.  SOSLib
composes the same two conversions in that order, at
src/real/SOSLib.sml:2133.

src/real/selftest.sml gains a test that the conversion terminates on
&1 / &3 * x, and a companion pinning that &1 / &3 + &1 / &6 still
reduces to &1 / &2, so the guard cannot be satisfied by disabling
reduction.

This is the instance half of HOL-Theorem-Prover#2034.  The
underlying computeLib mechanism -- reduce_cst counting a reflexive
result as progress -- and the add_conv documentation that never stated
the contract are deliberately left alone here.
@lukaszcz
lukaszcz force-pushed the real-rat-reduce-termination branch from 4dbc756 to 7f856fb Compare August 10, 2026 09:36
@mn200

mn200 commented Aug 10, 2026

Copy link
Copy Markdown
Member

Both new selftests should use convtest; only one does at the moment.

@lukaszcz

Copy link
Copy Markdown
Contributor Author

Both new selftests should use convtest; only one does at the moment.

Fixed

@mn200

mn200 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Thanks!

@mn200
mn200 merged commit 40f97f1 into HOL-Theorem-Prover:develop Aug 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants