如何禁止简化策略展开算术表达式?

时间:2015-02-10 12:53:50

标签: coq

simpl策略展开2 + a到#34;匹配树和#34;等表达式。这看起来并不简单。例如:

Goal forall i:Z, ((fun x => x + i) 3 = i + 3).
simpl.

导致:

forall i : Z,
match i with
| 0 => 3
| Z.pos y' =>
    Z.pos
      match y' with
      | q~1 =>
          match q with
          | q0~1 => (Pos.succ q0)~1
          | q0~0 => (Pos.succ q0)~0
          | 1 => 3
          end~0
      | q~0 =>
          match q with
          | q0~1 => (Pos.succ q0)~0
          | q0~0 => q0~1
          | 1 => 2
          end~1
      | 1 => 4
      end
| Z.neg y' => Z.pos_sub 3 y'
end = i + 3

如何通过simpl策略避免此类并发症?

这个特定的目标可以通过omega解决,但如果它更复杂一点,omega就会失败,我不得不求助于:replace (2 + a) with (a + 2); simpl; replace (a + 2) with (2 + a)

2 个答案:

答案 0 :(得分:8)

您可以使用TransparentOpaque命令控制定义展开。在您的示例中,您应该能够说出类似

的内容
Opaque Z.add.
simpl.
Transparent Z.add.

或者,Arguments command可用于指示simpl策略,以避免在某些情况下简化术语。 E.g。

Arguments Z.add _ _ : simpl nomatch.
在你的情况下,

为我做了诀窍。这个特殊变体的作用是避免在这样做之后(在你的例子中看到的)大的,丑陋的match出现在头部位置时简化一个术语。但是,还有其他变种。

最后,为了完整起见,Ssreflect库提供了很好的基础设施,可以使某些定义在本地不透明。所以你可以说像

rewrite (lock Z.add) /= -lock.

意为“锁定Z.add,以便它不会简化,然后简化表达式的剩余部分(/=开关),然后再次解锁定义(-lock)”

答案 1 :(得分:4)

您可以调整简化策略的行为方式,以减少匹配。

Require Import Coq.ZArith.ZArith.

Goal forall i:Z, ((fun x => (x + i)%Z) 3%Z = (i + 3)%Z).
Arguments Z.add x y : simpl nomatch.
simpl.

详细了解here

否则,您可以使用other tactics来选择减少的方法。例如cbn beta