Module Exploration1.
(** With bogus subtraction, this omega_example1 theorem even True? Yes it is; let's try again, the hard way, to find the proof. *)
(** And here's the easy way. *)
(** Here we have used the [omega] tactic, made available by importing [Coq.omega.Omega] as we have done above.  Omega is an algorithm for integer linear programming, invented in 1991 by William Pugh. Because ILP is NP-complete, we might expect that this algorithm is exponential-time in the worst case, and indeed that's true: if you have [N] equations, it could take [2^N] time.  But in the typical cases that result from reasoning about programs, omega is much faster than that.  Coq's [omega] tactic is an implementation of this algorithm that generates a machine-checkable Coq proof.  It "understands" the types Z and nat, and these operators: [<] [=] [>] [<=] [>=] [+] [-] [~], as well as multiplication by small integer literals (such as 0,1,2,3...) and some uses of [\/] and [/\].  Omega does _not_ understand other operators.  It treats things like [a*b] and [f x y] as if they were variables.  That is, it can prove [f x y > a*b -> f x y + 3 >= a*b], in the same way it would prove [u > v -> u+3 >= v].  Now let's consider a silly little program: swap the first two elements of a list, if they are out of order. *)
Definition maybe_swap (al: list nat) : list nat :=
match al with
| a :: b :: ar => if a >? b then b::a::ar else a::b::ar
| _ => al
end.
Example maybe_swap_123:
maybe_swap [1; 2; 3] = [1; 2; 3].
(** Moral of this story: When proving things about a program that uses boolean comparisons [(a <? b)], use [bdestruct].  Then use [omega].  Let's review that proof without all the comments. *)

Theorem maybe_swap_idempotent':
forall al, maybe_swap (maybe_swap al) = maybe_swap al.