Coq 是否有从假设中提取含义的策略(反转除外)?

Coq 是否有从假设中提取含义的策略(反转除外)?,coq,Coq,假设我有以下目标: 在人眼看来,很明显,H最终为真的唯一方法是n为7或21。我想用“既然H需要n是7或21,那么目标必须是真的”来证明这一点 我的第一个猜测是使用“反转H”,但这只增加了另一个相同形式的假设。考虑到假设H的形状,我担心这里最好的策略是使用暴力:即使匹配以简洁的形状打印,它的计算就像是由22个嵌套模式匹配组成,如 H : match n with | 0 => false | S n1 => match n1 with | 0

假设我有以下目标:

在人眼看来,很明显,H最终为真的唯一方法是n为7或21。我想用“既然H需要n是7或21,那么目标必须是真的”来证明这一点


我的第一个猜测是使用“反转H”,但这只增加了另一个相同形式的假设。

考虑到假设H的形状,我担心这里最好的策略是使用暴力:即使匹配以简洁的形状打印,它的计算就像是由22个嵌套模式匹配组成,如

H : match n with
    | 0 => false
    | S n1 => 
      match n1 with
      | 0 => false
      | S n2 => ... (* The case for 7 is somewhere there *)
     
        match n21 with
        | 0 => true
        | S _ => false
      end
     ...
   end
end

因此,您可以重复对
n
进行案例分析,放弃所有获得假设
true=false
的琐碎情况。 以下是一种方法:

Goal forall (n:nat), match n with | 7 | 21 => true | _ => false end = true -> n = 7 \/ n = 21.
Proof.
  intros n.
  repeat (destruct n as [|n] ; try discriminate). (* applies 22 times and then stops progressing *)
  all: auto. (* solves the last two goals by reflexivity *)
Qed.
如果您不喜欢repeat子句,也可以尝试使用依赖模式匹配来解决此问题:

Proof.
  intros n.
  refine (match n as k return match k with | 7 | 21 => true | _ => false end = true -> k = 7 \/ k = 21 with
          | 7 => _
          | 21 => _
          | _ => _ end).
  (* 22 goals left *)
  all: try discriminate. (* solves the 20 absurd goals *)
  all: auto. (* solves the last two goals by reflexivity *)
Qed.
然而,我不能建议遵循这条路径:即使证明脚本是“小”的,它们实际上扩展到与最大整数的大小相同的模式匹配(因此证明的大小至少与所匹配的最大常量的大小成线性关系,这在第二个证明脚本中可以清楚地看到)


解决这个问题的一个更好的方法是用
H:Nat.eqb n 7 | | Nat.eqb n 21=true修改给你这个假设H的源定义,并使用关于等式的引理(可能还有反射,请参阅以获取关于该主题的参考)。

考虑到假设H的形状,恐怕这里最好的策略是使用暴力:即使匹配以简洁的形状打印出来,它的计算也好像是由22个嵌套模式匹配组成,如

H : match n with
    | 0 => false
    | S n1 => 
      match n1 with
      | 0 => false
      | S n2 => ... (* The case for 7 is somewhere there *)
     
        match n21 with
        | 0 => true
        | S _ => false
      end
     ...
   end
end

因此,您可以重复对
n
进行案例分析,放弃所有获得假设
true=false
的琐碎情况。 以下是一种方法:

Goal forall (n:nat), match n with | 7 | 21 => true | _ => false end = true -> n = 7 \/ n = 21.
Proof.
  intros n.
  repeat (destruct n as [|n] ; try discriminate). (* applies 22 times and then stops progressing *)
  all: auto. (* solves the last two goals by reflexivity *)
Qed.
如果您不喜欢repeat子句,也可以尝试使用依赖模式匹配来解决此问题:

Proof.
  intros n.
  refine (match n as k return match k with | 7 | 21 => true | _ => false end = true -> k = 7 \/ k = 21 with
          | 7 => _
          | 21 => _
          | _ => _ end).
  (* 22 goals left *)
  all: try discriminate. (* solves the 20 absurd goals *)
  all: auto. (* solves the last two goals by reflexivity *)
Qed.
然而,我不能建议遵循这条路径:即使证明脚本是“小”的,它们实际上扩展到与最大整数的大小相同的模式匹配(因此证明的大小至少与所匹配的最大常量的大小成线性关系,这在第二个证明脚本中可以清楚地看到)


解决这个问题的一个更好的方法是,用
H:Nat.eqb n 7 | | | Nat.eqb n 21=true修改给出这个假设H的源定义,并使用关于等式的引理(可能还有反射,请参阅以获取该主题的参考)。

这非常有用。非常感谢你!这非常有帮助。非常感谢你!