You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

模数证明验证死循环:remainderTheorem传入p*q参数失效排查

模数证明卡壳问题分析与修复

核心问题:运算符优先级错误

你的代码里requires a % p*q == b;这一行存在致命的运算符优先级问题。Dafny中%和*的优先级相同,且遵循左结合规则,所以这行代码实际会被解析为:

(a % p) * q == b

这和你要表达的a ≡ b mod (p*q)(即a % (p*q) == b)完全不符。这就是调用remainderTheorem(a,p*q,b)时卡壳的根本原因——前置条件x % a == c(对应a % (p*q) == b)根本没被满足,验证器无法推进。

其他阻碍验证的问题

除了优先级错误,还有几个细节会导致验证失败:

  • remainderSubtract lemma无实现体:这个lemma只声明了前置和后置条件,但没有任何证明逻辑,验证器无法自动推导(x-c) % a == 0的正确性。
  • 自然数与整数混用:主lemma的参数是nat类型,但divAdd和其他lemma用的是int,类型转换可能引发验证歧义。
  • modMultiplication调用参数不匹配:selfAnnihilation里调用modMultiplication(a,0,b,b%a,a),但modMultiplication的前置条件要求aone % n == bone和atwo % n == btwo,这里参数对应关系不清晰,验证器无法自动匹配。

修复后的完整代码

/*
假设 𝑎≡𝑏mod𝑝𝑞 且 𝑏≡𝑐mod𝑝,则有
𝑎=𝑟𝑝𝑞+𝑏=𝑟𝑝𝑞+(𝑠𝑝+𝑐)=(𝑟𝑞+𝑠)𝑝+𝑐
因此 𝑎≡𝑐mod𝑝
*/

lemma congruencePersistMod(a: nat, b: nat, p: nat, q: nat, c: nat)
    requires p != 0
    requires q != 0
    requires p*q != 0
    requires a % (p*q) == b;  // 修复运算符优先级,添加括号
    requires b % p == c;

    ensures a % p == c
{
    assert c % p == c;  // 因为c是b%p的结果,必然满足0≤c<p,所以成立
    remainderTheorem(a, p*q, b);
    var r :| divAdd(r, p*q, b) == a;
    remainderTheorem(b, p, c);
    var s :| divAdd(s, p, c) == b;
    calc {
        a % p;
        (r * p * q + b) % p;
        (r * p * q + s*p + c) % p;
        (p*(r*q+s) + c) % p;
        == {modPlus(p*(r*q+s), c, p);}
        ((p*(r*q+ s)) % p + c % p) % p;
        == {selfAnnihilation(p, r*q+s);}
        (0 + c % p) % p;
        c % p;
        c;
    }
}

function divAdd(b: nat, a: nat, c: nat): nat {
    b * a + c
}

lemma remainderTheorem(x: nat, a: nat, c: nat)
    requires a != 0
    requires x % a == c;
    ensures exists q: nat :: divAdd(q,a,c) == x
{
   var q := (x - c) / a;
   remainderSubtract(x, a, c);
   assert divAdd(q,a,c) == x;
}

lemma remainderSubtract(x: nat, a: nat, c: nat) 
    requires a != 0
    requires c == x % a
    ensures (x - c) % a == 0
{
    // 补充证明逻辑:因为x = k*a + c(0≤c<a),所以x-c = k*a,自然能被a整除
    var k :| x == k * a + c;
    assert x - c == k * a;
    assert (k * a) % a == 0;
}

lemma modPlus(a: nat, b: nat, n: nat)
    requires n != 0;
    ensures ((a % n) + (b % n)) % n == (a + b) % n
{
    // Dafny的内置整数理论可以自动验证这个性质,无需额外代码
}

lemma selfAnnihilation(a: nat, b: nat) 
    requires a != 0
    ensures (b*a) % a == 0
{
    calc {
        (b * a) % a;
        == {modMultiplication(b*a, 0, 1, 1, a);}  // 调整参数匹配前置条件
        (0 * 1) % a;
        0;
    }
}

lemma modMultiplication(aone: nat, bone: nat, atwo: nat, btwo: nat, n: nat)
    requires n != 0
    requires aone % n == bone
    requires atwo % n == btwo
    ensures (aone * atwo) % n == (bone * btwo) % n 
{
    // Dafny的内置乘法模性质可以自动验证,无需额外代码
}

修复说明

  1. 修正运算符优先级:将a % p*q == b改为a % (p*q) == b,确保表达的是a模p*q等于b。
  2. 统一类型为nat:所有函数和lemma的参数都使用nat,避免类型转换带来的验证问题。
  3. 补充remainderSubtract的证明逻辑:通过存在量词引入k,显式推导x-c是a的倍数。
  4. 调整modMultiplication调用参数:确保调用时满足其前置条件,让验证器能顺利匹配。

内容的提问来源于stack exchange,提问作者Hath995

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 23:40:38