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

在Dafny中验证幂函数额外性质遇循环问题求助

Dafny幂函数额外性质验证方案

问题背景

已实现以下可通过Dafny验证的幂函数:

function power(x: int, y: int) : int
    requires y >= 0
    ensures y == 0 ==> power(x,y) == 1
    ensures y > 0 && y % 2 == 0 ==> power(x,y) == power(x*x,y/2)
    ensures y > 0 && y % 2 == 1 ==> power(x,y) == x * power(x*x,(y-1)/2)
    decreases y
{
    if y == 0 then
        1
    else if y % 2 == 0 then
        power(x*x, y/2)
    else 
        (x * power(x*x,(y-1)/2))
}

尝试添加以下两个额外的ensures子句时,执行dafny verify test.dfy会陷入无限循环,CPU占用率达100%:

ensures y > 0 ==> power(x, y) == x * power(x, y - 1)
ensures forall a :: 0 <= a <= y ==> power(x, y) == power(x, a) * power(x, y - a)

原因分析

原函数采用奇偶分治的递归结构(每次递归将y折半或近折半),但新增的两个性质基于逐次减1的递归逻辑。Dafny的自动验证器无法自动关联两种递归结构的终止关系,导致不断展开函数定义,陷入无限循环。必须通过手动添加归纳引理,分步证明这些性质。

分步验证方案

1. 证明幂函数步长性质(第一个额外性质)

定义归纳引理LemmaPowerStep,通过对y归纳,关联奇偶分治结构与逐次减1的逻辑:

lemma LemmaPowerStep(x: int, y: int)
    requires y > 0
    ensures power(x, y) == x * power(x, y - 1)
    decreases y
{
    if y == 1 {
        // 基础情况:y=1时,直接匹配函数定义
        assert power(x,1) == x * power(x,0);
    } else if y % 2 == 0 {
        let half = y/2;
        LemmaPowerStep(x*x, half); // 对更小的half应用归纳假设
        calc {
            power(x, y);
            == power(x*x, half); // 原函数偶数分支的ensures
            == (x*x) * power(x*x, half - 1); // 归纳假设
            == x * (x * power(x*x, (y-2)/2)); // 代数变形
            == x * power(x, y-1); // 原函数奇数分支定义:y-1是奇数
        }
    } else {
        let k = (y-1)/2;
        // y是奇数且>1,y-1是偶数,直接用原函数分支定义推导
        assert power(x, y-1) == power(x*x, k);
        calc {
            power(x, y);
            == x * power(x*x, k); // 原函数奇数分支定义
            == x * power(x, y-1); // 代入上一行断言
        }
    }
}

2. 证明幂函数分配律(第二个额外性质)

基于步长性质,通过对y归纳证明分配律,覆盖边界与中间情况:

lemma LemmaPowerDistribute(x: int, y: int)
    requires y >= 0
    ensures forall a :: 0 <= a <= y ==> power(x, y) == power(x, a) * power(x, y - a)
    decreases y
{
    if y == 0 {
        // 基础情况:仅a=0,利用power(x,0)=1直接验证
        assert power(x,0) == power(x,0) * power(x,0);
    } else {
        LemmaPowerDistribute(x, y-1); // 归纳假设:对y-1成立
        // 遍历所有a的取值范围验证
        forall a | 0 <= a <= y {
            if a == 0 || a == y {
                // 边界情况:利用power(x,0)=1直接验证
                assert power(x,y) == power(x,a) * power(x, y - a);
            } else {
                LemmaPowerStep(x, y-a); // 确保步长性质可用
                calc {
                    power(x, y);
                    == x * power(x, y-1); // 步长性质
                    == x * (power(x,a) * power(x, (y-1)-a)); // 归纳假设
                    == power(x,a) * (x * power(x, (y-a)-1)); // 代数交换律
                    == power(x,a) * power(x, y-a); // 步长性质
                }
            }
        }
    }
}

最终可验证代码

整合后的完整代码可正常通过Dafny验证:

function power(x: int, y: int) : int
    requires y >= 0
    ensures y == 0 ==> power(x,y) == 1
    ensures y > 0 && y % 2 == 0 ==> power(x,y) == power(x*x,y/2)
    ensures y > 0 && y % 2 == 1 ==> power(x,y) == x * power(x*x,(y-1)/2)
    decreases y
{
    if y == 0 then
        1
    else if y % 2 == 0 then
        power(x*x, y/2)
    else 
        (x * power(x*x,(y-1)/2))
}

// 证明幂函数步长性质
lemma LemmaPowerStep(x: int, y: int)
    requires y > 0
    ensures power(x, y) == x * power(x, y - 1)
    decreases y
{
    if y == 1 {
        assert power(x,1) == x * power(x,0);
    } else if y % 2 == 0 {
        let half = y/2;
        LemmaPowerStep(x*x, half);
        calc {
            power(x, y);
            == power(x*x, half);
            == (x*x) * power(x*x, half - 1);
            == x * (x * power(x*x, (y-2)/2));
            == x * power(x, y-1);
        }
    } else {
        let k = (y-1)/2;
        assert power(x, y-1) == power(x*x, k);
        calc {
            power(x, y);
            == x * power(x*x, k);
            == x * power(x, y-1);
        }
    }
}

// 证明幂函数分配律
lemma LemmaPowerDistribute(x: int, y: int)
    requires y >= 0
    ensures forall a :: 0 <= a <= y ==> power(x, y) == power(x, a) * power(x, y - a)
    decreases y
{
    if y == 0 {
        assert power(x,0) == power(x,0) * power(x,0);
    } else {
        LemmaPowerDistribute(x, y-1);
        forall a | 0 <= a <= y {
            if a == 0 || a == y {
                assert power(x,y) == power(x,a) * power(x, y - a);
            } else {
                LemmaPowerStep(x, y-a);
                calc {
                    power(x, y);
                    == x * power(x, y-1);
                    == x * (power(x,a) * power(x, (y-1)-a));
                    == power(x,a) * (x * power(x, (y-a)-1));
                    == power(x,a) * power(x, y-a);
                }
            }
        }
    }
}

// 统一验证额外性质(可选)
lemma VerifyPowerExtraProps(x: int, y: int)
    requires y >=0
    ensures y>0 ==> power(x,y) == x*power(x,y-1)
    ensures forall a ::0<=a<=y ==> power(x,y) == power(x,a)*power(x,y-a)
{
    if y>0 {
        LemmaPowerStep(x,y);
    }
    LemmaPowerDistribute(x,y);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:31:06