Skip to content

fix(gcd): cont 单项情形 sign 不一致 (#17) — 对齐 Maple/SymPy/FLINT 约定#18

Merged
lihaokun merged 1 commit into
masterfrom
fix/cont-single-term-sign-issue-17
May 13, 2026
Merged

fix(gcd): cont 单项情形 sign 不一致 (#17) — 对齐 Maple/SymPy/FLINT 约定#18
lihaokun merged 1 commit into
masterfrom
fix/cont-single-term-sign-issue-17

Conversation

@lihaokun

Copy link
Copy Markdown
Owner

Summary

修复 issue #17:CLPoly cont() 对单项与多项多项式返回不一致的 sign:

  • 单项cont(-x) = -1(返 leading coef 带符号)
  • 多项cont(-x+1) = 1(gcd 折正)

Maple / SymPy / FLINT 统一约定 content always non-negative。这也是 issue #14 (squarefreebasis unit leak) 的根因之一(PR #16 仅在 sqf 层兜底修了表象)。

Changes

3 处修复(详细见 docs/fixes/2026-05-12-cont-single-term-sign.md,含半形式化正确性证明):

  1. clpoly/polynomial_gcd.hh:1067 (univariate ZZ cont 特化版):init ZZ c = 0,gcd(0, c_i) 走 GMP mpz_gcd 取绝对值,自动归正
  2. clpoly/upolynomial.hh:220 (template Tc cont 版本):同样模式
  3. clpoly/polynomial_gcd.hh:631+ (多变量 cont):return 前加 4 行 sign normalize,cover single-group 路径

Before / After

                  Before              After (matches Maple/SymPy/FLINT)
cont(x)         = 1     ✓             1     ✓
cont(-x)        = -1    ✗             1     ✓
cont(-2x)       = -2    ✗             2     ✓
cont(-x+1)      = 1     ✓             1     ✓
cont(-2x+2)     = 2     ✓             2     ✓
cont(常数 -6)   = -6    ✗             6     ✓
cont(-2xy mv)   = -2y   ✗             2y    ✓
cont(0 empty)   = 1     ✓             1     ✓

Test plan

Semi-Formal Correctness Proof

docs/fixes/2026-05-12-cont-single-term-sign.md §3:

  • Spec 数学定义
  • Lemma 1(loop invariant,归纳证明)
  • Main Theorem(实现 = Spec,分 case)
  • 等价性 Claim(修后多项情形与原实现等价)
  • 边缘情形枚举表

Lean side

Lean Model.lean 端有自己的 MvPolyZZ.contImpl / SparsePolyZZ.contImpl(在 feature/formal-proofs 分支),同样问题。本 PR 后会在 feature/formal-proofs 分支独立同步修(不在本 PR 范围)。

Closes #17

🤖 Generated with Claude Code

Bug: cont() 对单项与多项多项式返回不一致的 sign:
  cont(-x)   = -1   ← 单项 c 直接返 leading coef(带符号)
  cont(-x+1) = 1    ← 多项 c = gcd(c0, c1, ...) GMP 折正

而 Maple/SymPy/FLINT 通用约定是 "content always non-negative"。

issue #14 (squarefreebasis unit leak) 的根因之一也是这个;PR #16 在
squarefreefactorize 加 sign-normalize 兜底修了表象,但 cont 根因未修。

修复(3 处):

1. clpoly/polynomial_gcd.hh:1067 (univariate ZZ cont 特化版)
   - 改 init `ZZ c = 0`(让 gcd(0, c_i) = |c_i|,GMP mpz_gcd 取绝对值)
   - 用 range-for 迭代统一处理
   - 末尾 c == 0 兜底返 1(零多项式约定)

2. clpoly/upolynomial.hh:220 (template Tc cont 版本)
   - 同样模式 — 与 ZZ 特化版行为一致
   - 顺带规避原代码 L225 `(ptr++).second` 的 `.` typo(该 template 未被
     实例化,typo 未触发;新代码用 range-for 自然规避)

3. clpoly/polynomial_gcd.hh:631+ (多变量 cont)
   - return 前加 4 行 sign normalize(如 front coef < 0,全部取反)
   - cover single-group 路径(`cont = std::move(tmp)` 不归正的)
   - 对 multi-group(polynomial_GCD 已归正)路径是 no-op

正确性半形式化证明:见 docs/fixes/2026-05-12-cont-single-term-sign.md
(Spec + Lemma 1 loop invariant + Main Theorem + 等价性 Claim + 边缘情形枚举)

测试:
- 新增 test/test_cont_sign_consistency.cc (16 用例 / 16 PASS)
  * §1 Univariate cont (7 case): x, -x, -2x, -x+1, -2x+2, -6 const, 0 empty
  * §2 Multivariate cont lex (3 case): -x, -2xy, -x+1
  * §3 Invariant: cont(F) 非负 (6 case)
- 全量回归 27 test files / 0 failed(含 issue #14 squarefreebasis_bugfix)

参考实现对照(实测 SymPy + 文献 Maple/FLINT):
  cont(-x) = 1, cont(-2x) = 2, etc.(全正)

Closes #17

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lihaokun lihaokun force-pushed the fix/cont-single-term-sign-issue-17 branch from a2abe5a to 7498683 Compare May 13, 2026 04:20
@lihaokun lihaokun merged commit 86119b0 into master May 13, 2026
2 checks passed
@lihaokun lihaokun deleted the fix/cont-single-term-sign-issue-17 branch May 13, 2026 08:45
lihaokun added a commit that referenced this pull request May 13, 2026
…修 __upoly_primitive 潜伏 bug

PR #18 把 C++ cont 统一为非负(Maple/SymPy/FLINT 约定),本 commit
同步 Lean 端:

- Model.lean:1158 MvPolyZZ.contImpl 删 sign-match
- Model.lean:1268 SparsePolyZZ.contImpl 删 sign-match
- Model.lean:1626 MvPolyZZ.contInt 删 sign-match
- #eval 期望值更新 + 4 个新回归 case

附带修复 Corpus.lean:5044 __upoly_primitive_upoly_ir 的 sign 反转
潜伏 bug — caller 显式翻 sign 保 pp 首项 > 0,但被 contImpl 内部
sign-match 抵消导致 pp 首项实际为负。本 fix 解开抵消。

empty case 保留返 0(Lean 内部 sentinel for contMv empty-detection),
是 ABI 选择不是 spec 偏离。

lake build 3071 jobs 全过。

详见:
- docs/fixes/2026-05-13-lean-cont-sign-sync.md
- docs/devlog/2026-05-13-lean-cont-sign-sync.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lihaokun added a commit that referenced this pull request May 14, 2026
加 4 个 joint case 到 test_squarefreebasis_bugfix.cc,验证 PR #16
(sqf sign-normalize) + PR #18 (cont 始终非负) 联合通过 squarefreebasis
调用链时仍精确成立:

- sqf(-2xy+3x) 乘积重建:cont=2y-3 (PR #18 修后非负) ✓
- squarefreebasis({-2xy+3x, ...}) basis 无 unit ✓
- sqf(-6(xy-1)(xy+2)) 含非平凡 sign + mv const cont ✓

全套 27/27 测试通过。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

cont() 单项 vs 多项情形 sign 不一致(违反 Maple/SymPy/FLINT 约定)

1 participant