精益Mergesort使用日益完善的关系

时间:2018-12-30 11:44:06

标签: algorithm mergesort lean

我正在尝试在精益中创建mergesort定义,并创建了以下代码:

{% extends "admin/change_list.html" %}
{% load staticfiles %}
{% block content %}
<div align="right">
    <form id="generate-form" method="POST">
        {% csrf_token %}
        <select>
            <option value="">-- section name --</option>
            {% for section in sections %}
            <option value="{{ section.short_name }}">{{ section.name }}</option>
            {% endfor %}
        </select>
        <input type="text" name="from_date" class="vTextField" placeholder="from">
        <input type="text" name="to_date" class="vTextField" placeholder="to">&nbsp;
        <input type="submit" value="Generate" class="default" id="gen-schedules"
        style="margin:0; height: 30px; padding-top: 5px;">
    <form>
</div>
{{ block.super }}
{% endblock %}

具有合并定义

def mergesort (a: ℕ): list ℕ → list ℕ     
    | [] := []    
    | [a] := [a]  
    | (x::xs) :=  merge (mergesort (fhalf xs)) (mergesort (sndhalf xs))

以及半/ sndhalf定义:

def merge : list ℕ → list ℕ → list ℕ    
    | xs [] := xs    
    | [] ys := ys
    | (x :: xs) (y :: ys) := if x < y then x :: (merge xs ( y :: ys)) 
                                      else y :: (merge (x :: xs) ys)

但是,我收到以下错误消息:

  

无法证明递归应用程序在减少,有充分的依据   关系

 def fhalf {α: Type} (xs: list α): list α := 
    list.take (list.length xs/2) xs

def sndhalf {α: Type} (xs: list α): list α :=
    list.drop (list.length xs/2) xs
     

可能的解决方案:

     
      
  • 在定义末尾使用@has_well_founded.r (list ℕ) (@has_well_founded_of_has_sizeof (list ℕ) (@list.has_sizeof ℕ nat.has_sizeof)) 关键字来指定用于建立良好关系并减少证明的策略。

  •   
  • 默认的递减策略使用“假设”策略,因此可以使用“ have”表达式提供提示(即本地证明)。嵌套异常包含递减策略的失败状态。

  •   

有人可以帮助我证明合并排序正在减少吗?

1 个答案:

答案 0 :(得分:4)

首先,请注意mergesort的定义存在多个问题。第一,参数a是不必要的,永远不会使用。 (第二行中匹配的a是新鲜的。)二,在x::xs情况下,您完全忘记了x。要查看函数的实际作用,可以像在meta中一样添加关键字meta def mergesort。这将禁用终止检查,因此您可以#eval mergesort 2 [1, 3, 2]并看到没有得到想要的东西。在您撰写本文时,我将继续回答。

有一个默认的有根据的关系,证明它的默认方法是在本地上下文中查找证明。通过查看定义中的错误消息,您可以看到Lean期望得到的证明:它需要list.sizeof (fhalf xs) < x + (1 + list.sizeof xs)list.sizeof (sndhalf xs) < x + (1 + list.sizeof xs)的证明。因此,通过添加行

def mergesort (a : ℕ): list ℕ → list ℕ     
| [] := []    
| [a] := [a]  
| (x::xs) := 
  have list.sizeof (fhalf xs) < x + (1 + list.sizeof xs), from sorry,
  have list.sizeof (sndhalf xs) < x + (1 + list.sizeof xs), from sorry,
  merge (mergesort (fhalf xs)) (mergesort (sndhalf xs))

此策略将成功。您需要填写这些sorry

使用linarith中可用的mathlib策略(通过import tactic.linarith),您可以跳过一些算法:

def mergesort (a : ℕ): list ℕ → list ℕ     
| [] := []    
| [a] := [a]  
| (x::xs) := 
  have list.sizeof (fhalf xs) ≤ list.sizeof xs, from sorry,
  have list.sizeof (sndhalf xs) ≤ list.sizeof xs, from sorry,
  have list.sizeof (fhalf xs) < x + (1 + list.sizeof xs), by linarith,
  have list.sizeof (sndhalf xs) < x + (1 + list.sizeof xs), by linarith,
  merge (mergesort (fhalf xs)) (mergesort (sndhalf xs))

因此,用证明替换那些sorry,您很高兴。您可能想证明类似

lemma sizeof_take_le {α} [h : has_sizeof α] : ∀ n (xs : list α), 
  list.sizeof (list.take n xs) ≤ list.sizeof xs 

更正mergesort的定义后,详细信息将有所更改。

另一种方法是更改​​建立良好的关系和决策策略,就像mathlib定义中所做的那样:https://github.com/leanprover/mathlib/blob/master/data/list/sort.lean#L174 不幸的是,执行此操作的界面相当底层,我不知道它是否记录在何处。

要在不使用using_well_founded的情况下更改关系,可以添加一个使用list.length而不是list.sizeof的本地实例:

def new_list_sizeof : has_sizeof (list ℕ) := ⟨list.length⟩
local attribute [instance, priority 100000] new_list_sizeof

由此产生的目标比使用sizeof的目标更容易证明。

相关问题