List 定义一个;arg max";类似于有限集上的函数,证明了它的一些性质,避免了通过列表绕道

List 定义一个;arg max";类似于有限集上的函数,证明了它的一些性质,避免了通过列表绕道,list,function,set,fold,isabelle,List,Function,Set,Fold,Isabelle,我正在使用向量作为函数的自定义实现,其域是自然数的有限“索引集”,并且其图像是某种类型,可以在其上定义最大值,通常是实数。例如,我可以有一个二维向量v,其中v1=2.7和v3=4.2 在这些向量上,我想定义一个类似“arg max”的操作符,它告诉我最大分量的索引,3,在上面的v示例中。我之所以说“该”索引,是因为类似“arg max”的操作符将另外接受一个应用于具有值的组件的断开连接函数。(背景是。) 我知道有限集上的Max是使用fold1定义的(我还不知道它是如何工作的)。我尝试了这一点,这

我正在使用向量作为函数的自定义实现,其域是自然数的有限“索引集”,并且其图像是某种类型,可以在其上定义最大值,通常是
实数
。例如,我可以有一个二维向量
v
,其中
v1=2.7
v3=4.2

在这些向量上,我想定义一个类似“arg max”的操作符,它告诉我最大分量的索引,
3
,在上面的
v
示例中。我之所以说“该”索引,是因为类似“arg max”的操作符将另外接受一个应用于具有值的组件的断开连接函数。(背景是。)

我知道有限集上的
Max
是使用
fold1
定义的(我还不知道它是如何工作的)。我尝试了这一点,这一点本身就被接受了,但对于我想做的其他事情,这一点并不奏效:

fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = fold1
  (λ x y . if (v x > v y) then x      (* component values differ *)
   else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
   else y) N"
请注意,此外,我想证明我的“arg max”类算子的某些性质,这可能需要归纳。我知道有限集合上的归纳有一条规则。好的,但我也希望能够以这样一种方式定义我的操作符,即它可以被计算(例如,当尝试使用具体的有限集时),但是

value "arg_max_tb {1::nat} (op >) (nth [27::real, 42])"
使用预期返回值
1
时,会出现以下错误:

Wellsortedness error
(in code equation arg_max_tb ?n ?t ?v \equiv
                  fold1 (\lambda x y. if ord_real_inst.less_real (?v y) (?v x) then ...) ?n):
Type nat not of sort enum
 No type arity nat :: enum
因此,我求助于将有限集转换为列表。在列表中,我已经能够定义运算符,并通过使用
list\u nonempty\u import
进行归纳来证明其某些属性(如果感兴趣,可以共享代码)

基于工作列表的定义如下所示:

fun arg_max_l_tb :: "(nat list) ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_l_tb [] t v = 0"
      (* in practice we will only call the function
         with lists of at least one element *)
    | "arg_max_l_tb [x] t v = x"
    | "arg_max_l_tb (x # xs) t v =
      (let y = arg_max_l_tb xs t v in
        if (v x > v y) then x              (* component values differ *)
        else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
        else y)"

fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = arg_max_l_tb (sorted_list_of_set N) t v"
我没有成功地在有限集的构造函数上直接定义函数。以下操作不起作用:

fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ participant"
where "arg_max_tb {} t b = 0"
    | "arg_max_tb {x} t b = x"
    | "arg_max_tb (insert x S) t b =
      (let y = arg_max_tb S t b in
        if (b x > b y) then x
        else if (b x = b y ∧ t x y) then x
        else y)"
它给了我错误信息

Malformed definition:
Non-constructor pattern not allowed in sequential mode.
⋀t b. arg_max_tb {} t b = 0
这可能是因为列表构造函数被定义为
数据类型
,而有限集仅被定义为
归纳
模式吗


无论如何,你知道在有限集上定义这个函数的方法吗?无论是直接写下来,还是通过某种类似折叠的效用函数?

对有限集进行折叠要求结果独立于访问集合元素的顺序,因为集合是无序的。因此,大多数关于折叠的引理都假定折叠操作是左可换的,即,对于所有的
a
b
x
,折叠操作都是左可换的

在第一个定义中提供给
fold1
的函数不满足此条件,因为断开连接函数是一个任意谓词。例如,以打领带功能
%v'为例。正确
。因此,如果你想坚持这个定义,你必须首先找到关于打破僵局的充分条件,并将这个假设贯穿于你所有的引理中

基于元素排序列表的工作解决方案避免了这种可交换性问题。上一个关于模式匹配的建议在
{}
{x}
插入x S
上不起作用,原因有二。首先,
fun
只能在数据类型构造函数上进行模式匹配,因此必须改用
函数
;这解释了错误消息。但是,你还必须证明方程没有重叠,因此你会再次遇到同样的交换性问题。此外,您将无法证明终止,因为
S
可能是无限的

代码生成的良好分类错误来自
fold1
的设置
fold1 f A
定义为
x。折叠集合f A x
其中
fold1Set f A x
保持iff
x
是按元素的某些顺序对
f
进行折叠的结果。为了检查所有结果是否相同,生成的代码会简单地测试
x
的所有可能值
fold1Set f A x
是否成立。如果它确实只找到一个这样的值,那么它将返回该值。否则,它将引发一个异常。在您的例子中,
x
是一个索引,即
nat
类型,其中包含无限多个值。因此,不可能进行详尽的测试。从技术上讲,这意味着
nat
不是类型类
enum
的实例


通常情况下,您会根据
fold1
为您定义的所有内容导出专门的代码方程式。请参阅有关程序优化的代码生成器教程。

这个问题实际上由多个问题组成

有限集上函数的定义 折叠/折叠1 通常的递归组合符是
有限集.fold
(或
fold1
)。但是,为了能够证明任何
折叠f z S
,结果必须独立于
f
应用于
S
元素的顺序

如果
f
是关联的和可交换的,您可以使用
Finite\u Set.ab\u semigroup\u mult.fold1\u insert
Finite\u Set.fold1\u singleton
来获取
fold1 f S
的simp规则,并且您应该能够使用
Finite\u ne\u inclut
作为您的归纳规则

请注意,您提供给fold1的函数(我称之为
f
)只有在
t
为线性顺序时才是可交换的:

fun arg_max_tb :: "index_set ⇒ tie_breaker ⇒ (real vector) ⇒ nat"
where "arg_max_tb N t v = fold1
  (λ x y . if (v x > v y) then x      (* component values differ *)
   else if (v x = v y ∧ t x y) then x (* tie-breaking needed *)
   else y) N"
fold1上的现有引理没有涵盖这一点,因此您需要证明有限集.ab_半群\u mult.fold1\u insert的广义变体,或者插入一个额外的分界符,例如

   else if (v x = v y ∧ ~t x y ∧ ~t y x ∧ x < y) then x
else如果(vx=vy∧ ~t×y∧ ~t y x∧ x
如果
t
是一个线性顺序,则可以从simp规则中删除此额外的连接断路器。请注意,此添加