SOLVED: I have a solution after following white-wolf's advice. If you are interested in my solution feel free to message me.
I am trying to write a proof in Agda for commutativity for multiplication:
lem3 : (x y : ℕ) → (x * y) ≡ (y * x)
lem3 0 y rewrite pr3a y = refl
lem3 (suc x) y rewrite lem3 x y | pr3b x y = refl
where we have:
pr3a : (x : ℕ) → (x * 0) ≡ 0
pr3a 0 = refl
pr3a (suc x) with (x * 0) | pr3a x
... | .0 | refl = refl
pr3b : (x y : ℕ) → y + y * x ≡ y * suc x
pr3b 0 0 = refl
pr3b 0 (suc y) rewrite pr3b 0 y = refl
pr3b (suc x) y = {!!}
I am having trouble filing this final goal. The expected type is y + y * suc x ≡ y * suc (suc x), and I had expected that using rewrite would give me y * suc (suc x) ≡ y * suc (suc x) as a goal. However:
pr3b (suc x) y rewrite pr3b x y = {!!}
expects the same goal as before: y + y * suc x ≡ y * suc (suc x).
It is my understanding that rewrite would effectively substitute the RHS into the LHS for x = x, giving y * suc x ≡ y * suc x, and then use x = suc x to give y * suc (suc x) ≡ y * suc (suc x). Am I mis-understanding how rewrite works or have I made some other error?
Your goal is y + y * suc x ≡ y * suc (suc x). Your induction hypothesis is y + y * x ≡ y * suc x. I can check that by putting pr3b x y inside the goal and typing C-c C-.
Goal: y + y * suc x ≡ y * suc (suc x)
Have: y + y * x ≡ y * suc x
This means that with a rewrite you should be able to replace y * suc x with y * x. However, you see that the two sides are switched, so you have to rewrite with symmetry like so
pr3b : (x y : ℕ) → y + y * x ≡ y * suc x
pr3b 0 0 = refl
pr3b 0 (suc y) rewrite pr3b 0 y = refl
pr3b (suc x) y rewrite sym $ pr3b x y = {!!}
This promotes the goal to y + (y + y * x) ≡ y * suc (suc x). This particular proof requires associativity and commutativity of addition to be completed.
Edit
I think you should try to prove this by induction on y instead of x.
Related
Suppose I have the following Agda code which compiles (where +-assoc and +-comm are taken from the plf course. It seems labourious to require the explicit sub expressions in each step in order for the code to simplify; however removing any one of the explicit expressions causes the code to fail to compile.
How can I get better type inference when writing proofs?
+-swap : ∀ (m n p : ℕ) -> m + (n + p) ≡ n + (m + p)
+-swap zero n p = refl
+-swap (suc m) n p =
begin
suc m + (n + p)
≡⟨ +-comm (suc m) (n + p) ⟩
(n + p) + (suc m)
≡⟨ +-assoc n p (suc m) ⟩
n + (p + suc m)
≡⟨ cong (n +_) (+-comm p (suc m)) ⟩
n + (suc m + p)
∎
If my understanding of your requirement is correct, you would like to be able to omit the intermediate expressions such as suc m + (n + p)
The whole point of the ≡-Reasoning module which provides the user with operators such as _∎, _≡⟨_⟩_ and begin_ is to make these quantities explicit so that the proof is more readable, and each reasoning step can be shown and understood clearly.
This means that if you want to omit these quantities, you should not use this library, and instead use one of the following methods to prove such equality proofs.
In a purpose of self-containment, here are the required imports:
module EqProofs where
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
open ≡-Reasoning
A first possibility is to use the equality reasoning module, as you did:
+-swap₁ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₁ zero n p = refl
+-swap₁ (suc m) n p = begin
suc m + (n + p) ≡⟨ +-comm (suc m) (n + p) ⟩
(n + p) + (suc m) ≡⟨ +-assoc n p (suc m) ⟩
n + (p + suc m) ≡⟨ cong (n +_) (+-comm p (suc m)) ⟩
n + (suc m + p) ∎
But you can also give the term explicitly using the transitivity of the equality:
+-swap₂ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₂ zero _ _ = refl
+-swap₂ (suc m) n p =
trans
(+-comm (suc m) (n + p))
(trans
(+-assoc n p (suc m))
(cong (n +_) (+-comm p (suc m))))
Or you can use rewrite to simplify the goal using equality proofs:
+-swap₃ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₃ zero _ _ = refl
+-swap₃ (suc m) n p
rewrite +-comm (suc m) (n + p)
| +-assoc n p (suc m)
| cong (n +_) (+-comm p (suc m)) = refl
In the two last possibilities, the intermediate quantity are hidded (and easily inferred by Agda), as you wanted.
Edit:
You can omit some of (not all of them though, since the type checker needs information to solve constraints) the required parameters using underscores. This can be done in all cases except when using rewrite, as follows:
+-swap₁ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₁ zero n p = refl
+-swap₁ (suc m) n p = begin
suc m + (n + p) ≡⟨ +-comm _ (n + p) ⟩
(n + p) + (suc m) ≡⟨ +-assoc n p _ ⟩
n + (p + suc m) ≡⟨ cong (n +_) (+-comm p _) ⟩
n + (suc m + p) ∎
+-swap₂ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₂ zero _ _ = refl
+-swap₂ (suc m) n p =
trans
(+-comm _ (n + p))
(trans
(+-assoc n p _)
(cong (n +_) (+-comm p _)))
+-swap₃ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₃ zero _ _ = refl
+-swap₃ (suc m) n p
rewrite +-comm (suc m) (n + p)
| +-assoc n p (suc m)
| cong (n +_) (+-comm p (suc m)) = refl
Edit n°2:
As a side note, you can prove this property without having to pattern match on either of its arguments. Here is this proof, using chained equality. You can noticed that only a few parameters have to be explicitly provided, while the others can be replaced by underscores:
+-swap₄ : ∀ (m n p : ℕ) → m + (n + p) ≡ n + (m + p)
+-swap₄ m n p = begin
m + (n + p) ≡⟨ +-assoc m _ _ ⟩
(m + n) + p ≡⟨ cong (_+ p) (+-comm m _) ⟩
(n + m) + p ≡⟨ +-assoc n _ _ ⟩
n + (m + p) ∎
I am trying to define the sum of 1..n ∈ ℕ as n * (n + 1) / 2 in Agda
and need a proof that n*(n + 1) is even for that.
The proof is pretty simple, but there seems to be a concept I don't understand, as I am new to Agda (though neither to maths nor haskell) and learned it from http://www.cse.chalmers.se/~ulfn/papers/afp08/tutorial.pdf
(pointers to more advanced tutorials more than welcome!).
open import Data.Nat
open import Relation.Binary.PropositionalEquality
open import Data.Sum
-- A natural number is even, if there is a k ∈ ℕ with k * 2 = n.
data IsEven : ℕ → Set where
even : (k : ℕ) → IsEven (k * 2)
-- A product is even, if one of the factors is even.
even-product : {n m : ℕ} → IsEven n ⊎ IsEven m → IsEven (m * n)
even-product {n} {m} (inj₁ (even k)) = even (m * k)
even-product {n} {m} (inj₂ (even k)) = even (n * k)
The code returns
m != 2 of type ℕ
when checking that the expression even (k * m) has type
IsEven (k * 2 * m)
I already tried using with patterns to convince the compiler that k * 2 is in fact n, but to no avail. Switching m * k to k * m gives
k * m != m of type ℕ
when checking that the expression even (k * m) has type
IsEven (m * (k * 2))
You can find out what the problem is by putting {! !} markers around your attempted solution and using the C-c C-. shortcut.
even-product : {n m : ℕ} → IsEven n ⊎ IsEven m → IsEven (m * n)
even-product {n} {m} (inj₁ (even k)) = {!even (m * k)!}
even-product {n} {m} (inj₂ (even k)) = {!even (n * k)!}
Reloading the file and then pressing C-c C-. with your cursor in the first hole gives the following response:
Goal: IsEven (m * (k * 2))
Have: IsEven (m * k * 2)
————————————————————————————————————————————————————————————
n : ℕ
m : ℕ
k : ℕ
Now the problem is clear: the goal is to prove that (m * (k * 2)) is even, but you have a proof that (m * k * 2) is even.
To fix this problem, you have to use the fact that * is associative. I'll postulate it here by means of example, but obviously you'd want to give it an actual proof later.
postulate
*-assoc : (k l m : ℕ) → k * (l * m) ≡ (k * l) * m
Now we can use the rewrite keyword with *-assoc to fix the first case:
even-product : {n m : ℕ} → IsEven n ⊎ IsEven m → IsEven (m * n)
even-product {n} {m} (inj₁ (even k)) rewrite *-assoc m k 2 = even (m * k)
even-product {n} {m} (inj₂ (even k)) = {!even (n * k)!}
In the second case, C-c C-. gives the following response:
Goal: IsEven (k * 2 * n)
Have: IsEven (n * k * 2)
————————————————————————————————————————————————————————————
m : ℕ
n : ℕ
k : ℕ
So now you need to use commutativity of * as well as associativity. I'll leave the full solution as an exercise to the reader.
Isn't it easier to prove that the 2 * sum(1..n) = n * (n+1)? Which shows that n*(n+1) is even?
I have a proof of the (obvious) statement that looking up elements in a flattened representation of a matrix as an m * n length vector is the same as a Vector-of-Vector representation. But my proof feels clunky. [I won't give the proof of it here, as doing so would bias the search!]. To make this question self-contained, below I give a self-contained Agda module with a few lemmas that are helpful. [Some of these lemmas should probably be in the standard library, but are not.]
Basically, I am looking for an elegant way to fill the hole at the bottom, the proof of lookup∘concat. If you can make my lemmas more elegant as well, do feel free!
module NNN where
open import Data.Nat
open import Data.Nat.Properties.Simple
open import Data.Nat.Properties
open import Data.Vec
open import Data.Fin using (Fin; inject≤; fromℕ; toℕ)
open import Data.Fin.Properties using (bounded)
open import Data.Product using (_×_; _,_)
open import Relation.Binary.PropositionalEquality
-- some useful lemmas
cong+r≤ : ∀ {i j} → i ≤ j → (k : ℕ) → i + k ≤ j + k
cong+r≤ {0} {j} z≤n k = n≤m+n j k
cong+r≤ {suc i} {0} () k -- absurd
cong+r≤ {suc i} {suc j} (s≤s i≤j) k = s≤s (cong+r≤ {i} {j} i≤j k)
cong+l≤ : ∀ {i j} → i ≤ j → (k : ℕ) → k + i ≤ k + j
cong+l≤ {i} {j} i≤j k =
begin (k + i
≡⟨ +-comm k i ⟩
i + k
≤⟨ cong+r≤ i≤j k ⟩
j + k
≡⟨ +-comm j k ⟩
k + j ∎)
where open ≤-Reasoning
cong*r≤ : ∀ {i j} → i ≤ j → (k : ℕ) → i * k ≤ j * k
cong*r≤ {0} {j} z≤n k = z≤n
cong*r≤ {suc i} {0} () k -- absurd
cong*r≤ {suc i} {suc j} (s≤s i≤j) k = cong+l≤ (cong*r≤ i≤j k) k
sinj≤ : ∀ {i j} → suc i ≤ suc j → i ≤ j
sinj≤ {0} {j} _ = z≤n
sinj≤ {suc i} {0} (s≤s ()) -- absurd
sinj≤ {suc i} {suc j} (s≤s p) = p
i*n+k≤m*n : ∀ {m n} → (i : Fin m) → (k : Fin n) →
(suc (toℕ i * n + toℕ k) ≤ m * n)
i*n+k≤m*n {0} {_} () _
i*n+k≤m*n {_} {0} _ ()
i*n+k≤m*n {suc m} {suc n} i k =
begin (suc (toℕ i * suc n + toℕ k)
≡⟨ cong suc (+-comm (toℕ i * suc n) (toℕ k)) ⟩
suc (toℕ k + toℕ i * suc n)
≡⟨ refl ⟩
suc (toℕ k) + (toℕ i * suc n)
≤⟨ cong+r≤ (bounded k) (toℕ i * suc n) ⟩
suc n + (toℕ i * suc n)
≤⟨ cong+l≤ (cong*r≤ (sinj≤ (bounded i)) (suc n)) (suc n) ⟩
suc n + (m * suc n)
≡⟨ refl ⟩
suc m * suc n ∎)
where open ≤-Reasoning
fwd : {m n : ℕ} → (Fin m × Fin n) → Fin (m * n)
fwd {m} {n} (i , k) = inject≤ (fromℕ (toℕ i * n + toℕ k)) (i*n+k≤m*n i k)
lookup∘concat : ∀ {m n} {A : Set} (i : Fin m) (j : Fin n)
(xss : Vec (Vec A n) m) →
lookup (fwd (i , j)) (concat xss) ≡ lookup j (lookup i xss)
lookup∘concat i j xss = {!!}
It's better to define fwd by induction, then the rest follows.
open import Data.Nat.Base
open import Data.Fin hiding (_+_)
open import Data.Vec
open import Data.Vec.Properties
open import Relation.Binary.PropositionalEquality
fwd : ∀ {m n} -> Fin m -> Fin n -> Fin (m * n)
fwd {suc m} {n} zero j = inject+ (m * n) j
fwd {n = n} (suc i) j = raise n (fwd i j)
-- This should be in the standard library.
lookup-++-raise : ∀ {m n} {A : Set} (j : Fin n) (xs : Vec A m) (ys : Vec A n)
-> lookup (raise m j) (xs ++ ys) ≡ lookup j ys
lookup-++-raise j [] ys = refl
lookup-++-raise j (x ∷ xs) ys = lookup-++-raise j xs ys
lookup∘concat : ∀ {m n} {A : Set} i j (xss : Vec (Vec A n) m)
-> lookup (fwd i j) (concat xss) ≡ lookup j (lookup i xss)
lookup∘concat zero j (xs ∷ xss) = lookup-++-inject+ xs (concat xss) j
lookup∘concat (suc i) j (xs ∷ xss)
rewrite lookup-++-raise (fwd i j) xs (concat xss) = lookup∘concat i j xss
The soundness proof for fwd:
module Soundness where
open import Data.Nat.Properties.Simple
open import Data.Fin.Properties
soundness : ∀ {m n} (i : Fin m) (j : Fin n) -> toℕ (fwd i j) ≡ toℕ i * n + toℕ j
soundness {suc m} {n} zero j = sym (inject+-lemma (m * n) j)
soundness {n = n} (suc i) j rewrite toℕ-raise n (fwd i j)
| soundness i j
= sym (+-assoc n (toℕ i * n) (toℕ j))
I'm trying to prove the following:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc x} = {!!}
I'm brand new to Adga and don't even really know where to start. Any suggestions or guidance? Obviously very easy to prove on paper but I am unsure of what to tell Agda.
I defined my pow function as follows:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc zero) = x
x pow (suc y) = x * (x pow y)
When you pattern match on n in 1-pow and find out it is zero, Agda will take a look at the definition of _pow_ and check if one of the function clauses matches. The first one does, so it will apply that definition and 1 pow zero becomes 1. 1 is obviously equal to 1, so refl will work for the proof.
What about the case when n was suc x? Here's the problem: Agda cannot commit to the second clause (because x could be zero) nor the third clause (because x could be suc y for some y). So you have to go one step further to make sure Agda applies the definition of _pow_:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = {!!}
1-pow {suc (suc x)} = {!!}
Let's check out what is the type of the first hole. Agda tells us it is 1 ≡ 1, so we can use refl again. The last one is a bit trickier, we are supposed to produce something of type 1 * 1 pow (suc x) ≡ 1. Assuming your are using the standard definition of _*_ (i.e. recursion on the left argument and repeated addition on the left side, such as the one in the standard library), this should reduce to 1 pow (suc x) + 0 ≡ 1. Induction hypothesis (that is, 1-pow applied to suc x) tells us that 1 pow (suc x) ≡ 1.
So we are almost there, but we don't know that n + 0 ≡ n (that's because addition is defined by recursion on the left argument, so we can't simplify this expression). One option is to prove this fact, which I leave as an exercise. Here's a hint, though: you might find this function useful.
cong : ∀ {a b} {A : Set a} {B : Set b}
(f : A → B) {x y} → x ≡ y → f x ≡ f y
cong f refl = refl
It's already part of the Relation.Binary.PropositionalEquality module, so you don't need to define it yourself.
So, to recap: we know that n + 0 ≡ n and 1 pow (suc x) ≡ 1 and we need 1 pow (suc x) + 0 ≡ 1. These two facts fit together quite nicely - the equality is transitive, so we should be able to merge 1 pow (suc x) + 0 ≡ 1 pow (suc x) and 1 pow (suc x) ≡ 1 into one proof and indeed, this is the case:
1-pow {suc (suc x)} = trans (+0 (1 pow suc x)) (1-pow {suc x})
And that's it!
Let me mention few other approaches.
The whole proof could also be done using a proof that 1 * x ≡ x, though this is hardly different from what we did before.
You could simplify _pow_ to:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc y) = x * (x pow y)
This is slightly more convenient to work with. The proof would be changed accordingly (i.e. it wouldn't have the second clause of the original proof).
And lastly, you could do this:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = refl
1-pow {suc (suc x)} = cong (λ x → x + 0) (1-pow {suc x})
Try to figure out why that works! If you have any problems, let me know in the comments and I'll help you.
Given the following code :
(define (g x y) (* x y))
(define (f x y z)
(define (h x y)(g (+ x y) x z))h)
Notice that I pass 3 arguments into g ,where g accepts only 2 .
However ,no error message is presented from the interpreter , why ?
Regards
You aren't actually calling h here, only returning it. Properly formatted your code should look like:
(define (f x y z)
(define (h x y)
(g (+ x y) x z))
h)
So when you call (f 1 2 3) you get back h. If you call
((f 1 2 3) 1 2)
then the interpreter will give an error.