阿格达:偶数的乘积是

时间:2017-02-21 02:23:32

标签: functional-programming agda

我对Agda很新。我正在处理一项来自任务的问题。我已经掌握了大部分内容,但有一个目标就是我被困住了。

data Arith : Set where
 Num : ℕ → Arith
 Plus : Arith → Arith → Arith
 Times : Arith → Arith → Arith

eval : Arith → ℕ
eval (Num x) = x
eval (Plus e1 e2) = eval e1 + eval e2 
eval (Times e1 e2) = eval e1 * eval e2

data Even : ℕ → Set where
 zEven : Even 0
 ssEven : {n : ℕ} → Even n → Even (suc (suc n))

-- [PROBLEM 1]

plusEven : ∀ n m → Even n → Even m → Even (n + m)
plusEven zero m x x₁ = x₁
plusEven (suc zero) m () x₁
plusEven (suc (suc .0)) m (ssEven zEven) x₁ = ssEven x₁
plusEven (suc (suc ._)) m (ssEven (ssEven x)) x₁ = ssEven (ssEven (plusEven _ m  x  x₁ ))

-- [PROBLEM 2]

timesEven : ∀ n m → Even n → Even m → Even (n * m)
timesEven zero m x x₁ = zEven
timesEven (suc ._) zero (ssEven x) x₁ =  (timesEven _ zero x x₁)
timesEven (suc ._) (suc ._) (ssEven x) (ssEven x₁) = ssEven ((λ h → {!!}) (timesEven _ _ x x₁))

我必须证明的目标是

Goal: Even (.n₁ + suc (suc (.n₁ + .n * suc (suc .n₁))))

我觉得我必须使用plusEven一些方法。但目标看起来并不那么简单。我让这个问题困难吗?还是我走在正确的轨道上?有更简单的方法吗?我不想要解决方案。但是,正确的方向推进将是值得赞赏的。我现在已经坚持了一段时间。

3 个答案:

答案 0 :(得分:3)

如果n是偶数,那么n * m也是如此,所以m是否均匀是无关紧要的,因此你应该抛弃这个约束。所以实际的定理是(我nm是隐式的,因为这很方便)

timesEvenLeft  : ∀ {n m} → Even n → Even (n * m)
timesEvenRight : ∀ {n m} → Even m → Even (n * m)

你可以证明n * m ≡ m * n并从前者推导出后者定理。因此,它只是证明第一个。在递归的情况下,您需要在范围内证明Even (suc (suc n) * m)(减少为Even (m + (m + n * m)Even (n * m)(归纳假设)。为此,你还需要另一个引理:

plusDoubleEven : ∀ {n} m → Even n → Even (m + (m + n))

答案 1 :(得分:1)

我真的很喜欢这里发布的答案,他们帮助了我很多。但我不能改变作业中给出的问题。我使用发布的答案来提出解决问题的方法。它花了我一段时间,它看起来有点凌乱,但它的工作原理。我以为我也会在这里发布。

timesEven : ∀ n m → Even n → Even m → Even (n * m)
timesEven zero m x x₁ = zEven
timesEven (suc zero) m () x₁
timesEven (suc (suc n)) zero (ssEven x) x₁ = timesEven n zero x x₁
timesEven (suc (suc n)) (suc zero) x ()
timesEven (suc (suc n)) (suc (suc m)) (ssEven x) (ssEven x₁) = ssEven ((λ h → plusEven m (suc (suc (m + n * suc (suc m)))) x₁  (ssEven (plusEven m (n * suc (suc m)) x₁ h))) (timesEven n (suc (suc m)) x (ssEven x₁)))

答案 2 :(得分:0)

这可能不是你对这个家庭作业的期望,但如果没有做太多的工作,处理这些引理的干净方法,正如@ user3237465暗示的那样,重用自然数字的众所周知的属性。

从这些众所周知的属性中获取更多信息的一种方法是引入$patients = Patient::whereDoesntHave('users', function ($q) use ($vaccine_id) { $q->where('vaccine_id', '=', $vaccine_id); $q->with('Vaccine', 'immunizations'); })->get(); 的替代定义,您可以证明它与归纳属性相当:

Even

然后,您可以使用等式推理证明data Even : ℕ → Set where zEven : Even 0 ssEven : {n : ℕ} → Even n → Even (suc (suc n)) record Even′ (n : ℕ) : Set where constructor mkEven′ field factor : ℕ .equality : n ≡ factor * 2 open Even′ Even⇒Even′ : {n : ℕ} → Even n → Even′ n (...) Even′⇒Even : {n : ℕ} → Even′ n → Even n (...) plusEven,重用标准库中的词条。例如timesEven(Right/Left)的证明变为:

plusEven

Here is a gist包含所有正确的导入和所有证明。