所以这是我一直在Software Foundations工作的练习之一,我必须证明多重是可交换的。这是我的解决方案:
Theorem brack_help : forall n m p: nat,
n + (m + p) = n + m + p.
Proof.
intros n m p.
induction n as [| n'].
Case "n = 0".
simpl.
reflexivity.
Case "n = S n'".
simpl.
rewrite -> IHn'.
reflexivity.
Qed.
Lemma plus_help: forall n m: nat,
S (n + m) = n + S m.
Proof.
intros n m.
induction n as [| n].
Case "n = 0".
simpl.
reflexivity.
Case "n = S n".
simpl.
rewrite -> IHn.
reflexivity.
Qed.
Theorem mult_0_r : forall n:nat,
n * 0 = 0.
Proof.
intros n.
induction n as [|n'].
Case "n = 0".
simpl.
reflexivity.
Case "n = S n'".
simpl.
rewrite -> IHn'.
reflexivity.
Qed.
Theorem plus_comm : forall n m : nat,
n + m = m + n.
Proof.
intros n m.
induction n as [| n].
Case "n = 0".
simpl.
rewrite <- plus_n_O.
reflexivity.
Case "n = S n".
simpl.
rewrite -> IHn.
rewrite -> plus_help.
reflexivity.
Qed.
Theorem plus_swap : forall n m p : nat,
n + (m + p) = m + (n + p).
Proof.
intros n m p.
rewrite -> brack_help.
assert (H: n + m = m + n).
Case "Proof of assertion".
rewrite -> plus_comm.
reflexivity.
rewrite -> H.
rewrite <- brack_help.
reflexivity.
Qed.
Lemma mult_help : forall m n : nat,
m + (m * n) = m * (S n).
Proof.
intros m n.
induction m as [| m'].
Case "m = 0".
simpl.
reflexivity.
Case "m = S m'".
simpl.
rewrite <- IHm'.
rewrite -> plus_swap.
reflexivity.
Qed.
Lemma mult_identity : forall m : nat,
m * 1 = m.
Proof.
intros m.
induction m as [| m'].
Case "m = 0".
simpl.
reflexivity.
Case "m = S m'".
simpl.
rewrite -> IHm'.
reflexivity.
Qed.
Lemma plus_0_r : forall m : nat,
m + 0 = m.
Proof.
intros m.
induction m as [| m'].
Case "m = 0".
simpl.
reflexivity.
Case "m = S m'".
simpl.
rewrite -> IHm'.
reflexivity.
Qed.
Theorem mult_comm_helper : forall m n : nat,
m * S n = m + m * n.
Proof.
intros m n.
simpl.
induction n as [| n'].
Case "n = 0".
assert (H: m * 0 = 0).
rewrite -> mult_0_r.
reflexivity.
rewrite -> H.
rewrite -> mult_identity.
assert (H2: m + 0 = m).
rewrite -> plus_0_r.
reflexivity.
rewrite -> H2.
reflexivity.
Case "n = S n'".
rewrite -> IHn'.
assert (H3: m + m * n' = m * S n').
rewrite -> mult_help.
reflexivity.
rewrite -> H3.
assert (H4: m + m * S n' = m * S (S n')).
rewrite -> mult_help.
reflexivity.
rewrite -> H4.
reflexivity.
Qed.
Theorem mult_comm : forall m n : nat,
m * n = n * m.
Proof.
intros m n.
induction n as [| n'].
Case "n = 0".
simpl.
rewrite -> mult_0_r.
reflexivity.
Case "n = S n'".
simpl.
rewrite <- IHn'.
rewrite -> mult_comm_helper.
reflexivity.
Qed.
现在我认为,这个证据非常笨重。没有使用任何库,有没有更简洁的方法来做到这一点? (请注意,对于使用Case策略,您需要一些预定义的代码。自包含的工作代码位于以下要点:https://gist.github.com/psibi/1c80d61ca574ae62c23e)。
答案 0 :(得分:13)
如果你想更简洁地写这个(并且没有使用战术,求解器等......),你可以依赖这样一个事实,即大多数你需要的引理都是以你的主要形式表达的。 目标定理。
例如:
luaL_loadstring()
来自n * 0 = 0
。 mult_comm
来自n + 0 = n
。plus_comm
来自S (n + m) = n + S m
(通过两次重写和缩减)。考虑到这些因素,仅plus_comm
和mult_comm
作为引理,plus_assoc
相对比较容易证明:
plus_comm
注意:懒惰的标准库方法是ring
策略:
Theorem plus_assoc : forall a b c, a + (b + c) = a + b + c.
Proof.
intros.
induction a.
(* Case Z *) reflexivity.
(* Case S a *) simpl. rewrite IHa. reflexivity.
Qed.
Theorem plus_comm : forall a b, a + b = b + a.
Proof.
induction a.
(* Case Z *)
induction b.
(* Case Z *) reflexivity.
(* Case S b *) simpl. rewrite <- IHb. reflexivity.
(* Case a = S a *)
induction b.
(* Case Z *)
simpl. rewrite (IHa 0). reflexivity.
(* Case S b *)
simpl. rewrite <- IHb.
simpl. rewrite (IHa (S b)).
simpl. rewrite (IHa b).
reflexivity.
Qed.
Theorem mul_comm : forall a b, a * b = b * a.
Proof.
induction a.
(* Case Z *)
induction b.
(* Case Z *) reflexivity.
(* Case S b *) simpl. rewrite <- IHb. reflexivity.
(* Case S a *)
induction b.
(* Case Z *)
simpl. rewrite (IHa 0). reflexivity.
(* Case S b *)
simpl. rewrite <- IHb.
rewrite (IHa (S b)).
simpl. rewrite (IHa b).
rewrite (plus_assoc b a (b * a)).
rewrite (plus_assoc a b (b * a)).
rewrite (plus_comm a b).
reflexivity.
Qed.
答案 1 :(得分:9)
嗯,这可能不是你想要的,但是既然你(最初)在Haskell中标记了,而我刚刚在Haskell 今天找到了如何做到这一点,那就有一些代码!< / p>
{-# LANGUAGE TypeFamilies, GADTs, TypeOperators,
ScopedTypeVariables, UndecidableInstances,
PolyKinds, DataKinds #-}
import Data.Type.Equality
import Data.Proxy
data Nat = Z | S Nat
data SNat :: Nat -> * where
Zy :: SNat 'Z
Sy :: SNat n -> SNat ('S n)
infixl 6 :+
type family (:+) (m :: Nat) (n :: Nat) :: Nat where
'Z :+ n = n
'S m :+ n = 'S (m :+ n)
infixl 7 :*
type family (:*) (m :: Nat) (n :: Nat) :: Nat where
'Z :* n = 'Z
('S m) :* n = n :+ (m :* n)
add :: SNat m -> SNat n -> SNat (m :+ n)
add Zy n = n
add (Sy m) n = Sy (add m n)
mul :: SNat m -> SNat n -> SNat (m :* n)
mul Zy _n = Zy
mul (Sy m) n = add n (mul m n)
addP :: proxy1 m -> proxy2 n -> Proxy (m :+ n)
addP _ _ = Proxy
mulP :: proxy1 m -> proxy2 n -> Proxy (m :* n)
mulP _ _ = Proxy
addAssoc :: SNat m -> proxy1 n -> proxy2 o ->
m :+ (n :+ o) :~: (m :+ n) :+ o
addAssoc Zy _ _ = Refl
addAssoc (Sy m) n o = case addAssoc m n o of Refl -> Refl
zeroAddRightUnit :: SNat m -> m :+ 'Z :~: m
zeroAddRightUnit Zy = Refl
zeroAddRightUnit (Sy n) =
case zeroAddRightUnit n of Refl -> Refl
plusSuccRightSucc :: SNat m -> proxy n ->
'S (m :+ n) :~: (m :+ 'S n)
plusSuccRightSucc Zy _ = Refl
plusSuccRightSucc (Sy m) n =
case plusSuccRightSucc m n of Refl -> Refl
addComm :: SNat m -> SNat n ->
m :+ n :~: n :+ m
addComm Zy n = sym $ zeroAddRightUnit n
addComm (Sy m) n =
case addComm m n of
Refl -> plusSuccRightSucc n m
mulComm :: SNat m -> SNat n ->
m :* n :~: n :* m
mulComm Zy Zy = Refl
mulComm (Sy pm) Zy =
case mulComm pm Zy of Refl -> Refl
mulComm Zy (Sy pn) =
case mulComm Zy pn of Refl -> Refl
mulComm (Sy m) (Sy n) =
case mulComm m (Sy n) of {Refl ->
case mulComm n (Sy m) of {Refl ->
case addAssoc n m (mulP n m) of {Refl ->
case addAssoc m n (mulP m n) of {Refl ->
case addComm m n of {Refl ->
case mulComm m n of Refl -> Refl}}}}}
一些额外的免费东西!
distrR :: forall m n o proxy . SNat m -> proxy n -> SNat o ->
(m :+ n) :* o :~: m :* o :+ n :* o
distrR Zy _ _ = Refl
distrR (Sy pm) n o =
case distrR pm n o of {Refl ->
case addAssoc o (mulP pm o) (mulP n o) of
Refl -> Refl}
distrL :: SNat m -> SNat n -> SNat o ->
m :* (n :+ o) :~: m :* n :+ m :* o
distrL m n o =
case mulComm m (add n o) of {Refl ->
case distrR n o m of {Refl ->
case mulComm n m of {Refl ->
case mulComm o m of Refl -> Refl}}}
mulAssoc :: SNat m -> SNat n -> SNat o ->
m :* (n :* o) :~: (m :* n) :* o
mulAssoc Zy _ _ = Refl
mulAssoc (Sy pm) n o = case mulAssoc pm n o of {Refl ->
case distrR n (mulP pm n) o of Refl -> Refl}
答案 2 :(得分:1)
您也可以像这样解决它:
Theorem mult_comm : forall m n : nat,
m * n = n * m.
Proof.
intros.
induction m.
- rewrite <- mult_n_O. reflexivity.
- rewrite <- mult_n_Sm.
rewrite <- plus_1_l.
simpl.
rewrite <- IHm.
rewrite -> plus_comm.
reflexivity.
Qed.
技巧是将S m * n
重写为(1 + m) * n
(使用plus_1_l
)
然后将简化为n + m * n
供参考:
mult_n_O : forall n : nat, 0 = n * 0
mult_n_Sm : forall n m : nat, n * m + n = n * S m
plus_1_l : forall n : nat, 1 + n = S n
plus_comm : forall n m : nat, n + m = m + n
答案 3 :(得分:0)
这是我使用 assert
创建辅助定理为这个问题想出的解决方案,我相信这是本书在这一特定部分中讨论的主题。
Theorem mul_comm : forall m n : nat,
m * n = n * m.
Proof.
intros m n.
induction m as [| m' IHm'].
- rewrite mul_0_r.
reflexivity.
- simpl.
rewrite -> IHm'.
assert (H: forall a b : nat, a * (1 + b) = a + a * b).
{
intros a b.
induction a as [| a' IHa'].
- reflexivity.
- rewrite <- mult_n_Sm.
rewrite -> add_comm.
reflexivity.
}
rewrite -> H.
reflexivity.
Qed.