Agda Theorems for Powers - function

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.

Related

If statement doesn't evaluate

I know that questions like these seem to be looked down upon, but I haven't been able to find answers on the internet. I have the following function:
fun count :: "'a ⇒ 'a list ⇒ nat" where
"count a [] = 0"
| "count a (b # xs) = (count a xs) + (if a = b then 1 else 0)"
It counts the number of elements in a list that match with the given item. Simple enough, however, when I do the following:
value "count x [x,x,y,x,y]"
I get this as the output
"(if x = y then 1 else 0) + 1 + (if x = y then 1 else 0) + 1 + 1" :: "nat"
So you can see that there are hanging "if" statements and unevaluated additions in the output. Is it possible to make Isabelle simplify this?
I don't think so. The value command is more of a purely diagnostic tool and it is mostly meant for evaluation of ground terms (i.e. no free variables). The reason why you get a result at all is that it falls back from its standard method (compiling to ML, running the ML code, and converting the result back to HOL terms) to NBE (normalisation by evaluation, which is much slower and, at least in my experience, not that useful most of the time).
One trick that I do sometimes is to set up a lemma
lemma "count x [x, x, y, x, y] = myresult"
where the myresult on the right-hand side is just a dummy variable. Then I do
apply simp
and look at the resulting proof state (in case you don't see anything: try switching on "Editor Output State" in the options):
proof (prove)
goal (1 subgoal):
1. (x = y ⟶ Suc (Suc (Suc (Suc (Suc 0)))) = myresult) ∧
(x ≠ y ⟶ Suc (Suc (Suc 0)) = myresult)
It's a bit messy, but you can read of the result fairly well: if x = y, then the result is 5, otherwise it's 3. A simple hack to get rid of the Suc in the output is to cast to int, i.e. lemma "int (count x [x, x, y, x, y]) = myresult". Then you get:
(x = y ⟶ myresult = 5) ∧ (x ≠ y ⟶ myresult = 3)

Agda rewrite does not change goal in _*_ commutativity proof

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.

Prove that n times an even number yields an even number in Agda

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?

Proving identity for binary operator on Fin

I've defined an operator, +- (ignore the terrible name), as follows:
infixr 10 +-
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n} {m} FZ f' = rewrite plusCommutative n m in weakenN n f'
(+-) {n = S n} (FS f) f' = FS (f +- f')
The intention is that it behaves exactly like + as defined on Fin, but the upper bound of the result is tighter by 1. As far as I can tell, it works correctly.
The problem I'm having is in trying to prove that (FZ +- f) = f for any f : Fin n. I'm not expecting this to be true in general, because it will usually be the case that FZ +- f has a looser bound than f on account of the call to weakenN. However, in the particular case where the FZ has type Fin 1, then the types (and the values) ought to match up.
Is there any way of indicating to Idris that I only want to assert the equality in that particular case, rather than for all possible types of FZ? Or is there a completely different approach that I ought to be taking?
If we reshuffle the definition for (+-) a bit, the proof becomes easy:
import Data.Fin
infixr 10 +-
total
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n = Z} {m = m} a b = b
(+-) {n = (S n)}{m = m} FZ b = rewrite plusCommutative (S n) m in weakenN (S n) b
(+-) {n = (S n)}{m = m} (FS a) b = FS (a +- b)
lem : (f : Fin (S n)) -> the (Fin 1) FZ +- f = f
lem FZ = Refl
lem (FS x) = Refl
This checks out because the rewrite on the right hand side of the (+-) definition happens to normalize to concrete values instead of substitutions/coercions.
On the other hand, if we'd like to stick with the original definition for (+-), then the rewrite doesn't go away, and we're in for a whole world of pain, because now we have to work with heterogeneous equalities. I did a proof with heterogeneous equalities in Agda, however I couldn't get it to work in Idris on short notice, and I believe making it work would be a rather painful experience. Here it is in Agda.
Note though that we would have to add one more case to the original definition in order to make proving properties about it feasible in the first place. That's because it doesn't pass the coverage checker as it is. It's evident to us that Fin 1 only has FZ as constructor, but this has to be also explained to the compiler:
(+-) : Fin (S n) -> Fin (S m) -> Fin (S (n + m))
(+-) {n} {m} FZ f' = rewrite plusCommutative n m in weakenN n f'
(+-) {n = Z} (FS FZ) f' impossible
(+-) {n = S n} (FS f) f' = FS (f +- f')

How can I prove a type is valid in Agda?

I'm trying to do proofs over dependent functions, and I'm running into a snag.
So let's say we have a theorem f-equal
f-equal : ∀ {A B} {f : A → B} {x y : A} → x ≡ y → f x ≡ f y
f-equal refl = refl
I'm trying to prove a more general notion of equality preservation over dependent functions, and running into a snag. Namely, the type
Π-equal : ∀ {A} {B : A → Set} {f : {a : A} → B a} {x y : A} →
x ≡ y → f x ≡ f y
is making the compiler unhappy, because it can't figure out that f x and f y are of the same type. This seems like it oughta be a fixable issue. Is it?
note; the equivalence relation used is defined like this:
data _≡_ {A : Set}(x : A) : A → Set where
refl : x ≡ x
You can explicitly change the type of f x:
Π-equal : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> (p : x ≡ y) -> P.subst B p (f x) ≡ f y
Π-equal refl = refl
Or
Π-equal'T : ∀ {α β} {A : Set α} {B : A -> Set β} -> ((x : A) -> B x) -> (x y : A) -> x ≡ y -> Set β
Π-equal'T f x y p with f x | f y
...| fx | fy rewrite p = fx ≡ fy
Π-equal' : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> (p : x ≡ y) -> Π-equal'T f x y p
Π-equal' refl = refl
Or you can use heterogeneous equality:
Π-equal'' : ∀ {α β} {A : Set α} {B : A -> Set β} {f : (x : A) -> B x} {x y : A}
-> x ≡ y -> f x ≅ f y
Π-equal'' refl = refl
The subst function also can be useful, here is it's type (C-c C-d P.subst in Emacs):
{a p : .Agda.Primitive.Level} {A : Set a} (P : A → Set p)
{x y : A} →
x ≡ y → P x → P y
Imports used:
open import Relation.Binary.PropositionalEquality as P
open import Relation.Binary.HeterogeneousEquality as H
BTW, your f-equal is cong in the standard library.
It can be handled by heterogeneous equality, which can be imported from Relation.Binary.HeterogeneousEquality:
data _≅_ {ℓ} {A : Set ℓ} (x : A) : {B : Set ℓ} → B → Set ℓ where
refl : x ≅ x
Intuitively, het. equality carries evidence about the equality of the types involved as well as the equality of values.
You can find analogues for functions for standard equality (subst, trans, cong, etc.) in the module. Also, you can convert back and forth standard and het. equality using ≅-to-≡ and ≡-to-≅, but only when the types on the sides are demonstrably equal.
Note that the "rewrite" syntax can't be used with het. equality.
Alternatively, we can use standard equality with one of the sides coerced to the appropriate type:
Π-equal :
∀ {A : Set} {B : A → Set}{f : ∀ a → B a}{x y : A} → (p : x ≡ y) → subst B p (f x) ≡ f y
Π-equal refl = refl
This approach is actually equivalent to het. equality, but I find het. equality much easier to work with.