paulson@3390: (* Title: HOL/Power.thy paulson@3390: ID: $Id$ paulson@3390: Author: Lawrence C Paulson, Cambridge University Computer Laboratory paulson@3390: Copyright 1997 University of Cambridge paulson@3390: paulson@3390: *) paulson@3390: nipkow@16733: header{*Exponentiation*} paulson@14348: nipkow@15131: theory Power haftmann@21413: imports Nat nipkow@15131: begin paulson@14348: haftmann@29608: class power = haftmann@25062: fixes power :: "'a \ nat \ 'a" (infixr "^" 80) haftmann@24996: krauss@21199: subsection{*Powers for Arbitrary Monoids*} paulson@14348: haftmann@22390: class recpower = monoid_mult + power + haftmann@25062: assumes power_0 [simp]: "a ^ 0 = 1" huffman@30273: assumes power_Suc [simp]: "a ^ Suc n = a * (a ^ n)" paulson@14348: krauss@21199: lemma power_0_Suc [simp]: "(0::'a::{recpower,semiring_0}) ^ (Suc n) = 0" huffman@30273: by simp paulson@14348: paulson@14348: text{*It looks plausible as a simprule, but its effect can be strange.*} krauss@21199: lemma power_0_left: "0^n = (if n=0 then 1 else (0::'a::{recpower,semiring_0}))" haftmann@23183: by (induct n) simp_all paulson@14348: paulson@15004: lemma power_one [simp]: "1^n = (1::'a::recpower)" huffman@30273: by (induct n) simp_all paulson@14348: paulson@15004: lemma power_one_right [simp]: "(a::'a::recpower) ^ 1 = a" huffman@30273: unfolding One_nat_def by simp paulson@14348: krauss@21199: lemma power_commutes: "(a::'a::recpower) ^ n * a = a * a ^ n" huffman@30273: by (induct n) (simp_all add: mult_assoc) krauss@21199: huffman@28131: lemma power_Suc2: "(a::'a::recpower) ^ Suc n = a ^ n * a" huffman@30273: by (simp add: power_commutes) huffman@28131: paulson@15004: lemma power_add: "(a::'a::recpower) ^ (m+n) = (a^m) * (a^n)" huffman@30273: by (induct m) (simp_all add: mult_ac) paulson@14348: paulson@15004: lemma power_mult: "(a::'a::recpower) ^ (m*n) = (a^m) ^ n" huffman@30273: by (induct n) (simp_all add: power_add) paulson@14348: krauss@21199: lemma power_mult_distrib: "((a::'a::{recpower,comm_monoid_mult}) * b) ^ n = (a^n) * (b^n)" huffman@30273: by (induct n) (simp_all add: mult_ac) paulson@14348: nipkow@25874: lemma zero_less_power[simp]: paulson@15004: "0 < (a::'a::{ordered_semidom,recpower}) ==> 0 < a^n" huffman@30273: by (induct n) (simp_all add: mult_pos_pos) paulson@14348: nipkow@25874: lemma zero_le_power[simp]: paulson@15004: "0 \ (a::'a::{ordered_semidom,recpower}) ==> 0 \ a^n" huffman@30273: by (induct n) (simp_all add: mult_nonneg_nonneg) paulson@14348: nipkow@25874: lemma one_le_power[simp]: paulson@15004: "1 \ (a::'a::{ordered_semidom,recpower}) ==> 1 \ a^n" paulson@15251: apply (induct "n") huffman@30273: apply simp_all wenzelm@14577: apply (rule order_trans [OF _ mult_mono [of 1 _ 1]]) huffman@30273: apply (simp_all add: order_trans [OF zero_le_one]) paulson@14348: done paulson@14348: obua@14738: lemma gt1_imp_ge0: "1 < a ==> 0 \ (a::'a::ordered_semidom)" paulson@14348: by (simp add: order_trans [OF zero_le_one order_less_imp_le]) paulson@14348: paulson@14348: lemma power_gt1_lemma: paulson@15004: assumes gt1: "1 < (a::'a::{ordered_semidom,recpower})" wenzelm@14577: shows "1 < a * a^n" paulson@14348: proof - wenzelm@14577: have "1*1 < a*1" using gt1 by simp wenzelm@14577: also have "\ \ a * a^n" using gt1 wenzelm@14577: by (simp only: mult_mono gt1_imp_ge0 one_le_power order_less_imp_le wenzelm@14577: zero_le_one order_refl) wenzelm@14577: finally show ?thesis by simp paulson@14348: qed paulson@14348: nipkow@25874: lemma one_less_power[simp]: huffman@24376: "\1 < (a::'a::{ordered_semidom,recpower}); 0 < n\ \ 1 < a ^ n" huffman@30273: by (cases n, simp_all add: power_gt1_lemma) huffman@24376: paulson@14348: lemma power_gt1: paulson@15004: "1 < (a::'a::{ordered_semidom,recpower}) ==> 1 < a ^ (Suc n)" huffman@30273: by (simp add: power_gt1_lemma) paulson@14348: paulson@14348: lemma power_le_imp_le_exp: paulson@15004: assumes gt1: "(1::'a::{recpower,ordered_semidom}) < a" wenzelm@14577: shows "!!n. a^m \ a^n ==> m \ n" wenzelm@14577: proof (induct m) paulson@14348: case 0 wenzelm@14577: show ?case by simp paulson@14348: next paulson@14348: case (Suc m) wenzelm@14577: show ?case wenzelm@14577: proof (cases n) wenzelm@14577: case 0 huffman@30273: from prems have "a * a^m \ 1" by simp wenzelm@14577: with gt1 show ?thesis wenzelm@14577: by (force simp only: power_gt1_lemma wenzelm@14577: linorder_not_less [symmetric]) wenzelm@14577: next wenzelm@14577: case (Suc n) wenzelm@14577: from prems show ?thesis wenzelm@14577: by (force dest: mult_left_le_imp_le huffman@30273: simp add: order_less_trans [OF zero_less_one gt1]) wenzelm@14577: qed paulson@14348: qed paulson@14348: wenzelm@14577: text{*Surely we can strengthen this? It holds for @{text "0 (a^m = a^n) = (m=n)" wenzelm@14577: by (force simp add: order_antisym power_le_imp_le_exp) paulson@14348: paulson@14348: text{*Can relax the first premise to @{term "0 m < n" wenzelm@14577: by (simp add: order_less_le [of m n] order_less_le [of "a^m" "a^n"] wenzelm@14577: power_le_imp_le_exp) paulson@14348: paulson@14348: paulson@14348: lemma power_mono: paulson@15004: "[|a \ b; (0::'a::{recpower,ordered_semidom}) \ a|] ==> a^n \ b^n" paulson@15251: apply (induct "n") huffman@30273: apply simp_all nipkow@25874: apply (auto intro: mult_mono order_trans [of 0 a b]) paulson@14348: done paulson@14348: paulson@14348: lemma power_strict_mono [rule_format]: paulson@15004: "[|a < b; (0::'a::{recpower,ordered_semidom}) \ a|] wenzelm@14577: ==> 0 < n --> a^n < b^n" paulson@15251: apply (induct "n") huffman@30273: apply (auto simp add: mult_strict_mono order_le_less_trans [of 0 a b]) paulson@14348: done paulson@14348: paulson@14348: lemma power_eq_0_iff [simp]: nipkow@30056: "(a^n = 0) \ nipkow@30056: (a = (0::'a::{mult_zero,zero_neq_one,no_zero_divisors,recpower}) & n\0)" paulson@15251: apply (induct "n") huffman@30273: apply (auto simp add: no_zero_divisors) paulson@14348: done paulson@14348: nipkow@30056: nipkow@25134: lemma field_power_not_zero: nipkow@25134: "a \ (0::'a::{ring_1_no_zero_divisors,recpower}) ==> a^n \ 0" paulson@14348: by force paulson@14348: paulson@14353: lemma nonzero_power_inverse: huffman@22991: fixes a :: "'a::{division_ring,recpower}" huffman@22991: shows "a \ 0 ==> inverse (a ^ n) = (inverse a) ^ n" paulson@15251: apply (induct "n") huffman@30273: apply (auto simp add: nonzero_inverse_mult_distrib power_commutes) huffman@22991: done (* TODO: reorient or rename to nonzero_inverse_power *) paulson@14353: paulson@14348: text{*Perhaps these should be simprules.*} paulson@14348: lemma power_inverse: huffman@22991: fixes a :: "'a::{division_ring,division_by_zero,recpower}" huffman@22991: shows "inverse (a ^ n) = (inverse a) ^ n" huffman@22991: apply (cases "a = 0") huffman@22991: apply (simp add: power_0_left) huffman@22991: apply (simp add: nonzero_power_inverse) huffman@22991: done (* TODO: reorient or rename to inverse_power *) paulson@14348: avigad@16775: lemma power_one_over: "1 / (a::'a::{field,division_by_zero,recpower})^n = avigad@16775: (1 / a)^n" avigad@16775: apply (simp add: divide_inverse) avigad@16775: apply (rule power_inverse) avigad@16775: done avigad@16775: wenzelm@14577: lemma nonzero_power_divide: paulson@15004: "b \ 0 ==> (a/b) ^ n = ((a::'a::{field,recpower}) ^ n) / (b ^ n)" paulson@14353: by (simp add: divide_inverse power_mult_distrib nonzero_power_inverse) paulson@14353: wenzelm@14577: lemma power_divide: paulson@15004: "(a/b) ^ n = ((a::'a::{field,division_by_zero,recpower}) ^ n / b ^ n)" paulson@14353: apply (case_tac "b=0", simp add: power_0_left) wenzelm@14577: apply (rule nonzero_power_divide) wenzelm@14577: apply assumption paulson@14353: done paulson@14353: paulson@15004: lemma power_abs: "abs(a ^ n) = abs(a::'a::{ordered_idom,recpower}) ^ n" paulson@15251: apply (induct "n") huffman@30273: apply (auto simp add: abs_mult) paulson@14348: done paulson@14348: paulson@30730: lemma abs_power_minus [simp]: paulson@30730: fixes a:: "'a::{ordered_idom,recpower}" shows "abs((-a) ^ n) = abs(a ^ n)" paulson@30730: by (simp add: abs_minus_cancel power_abs) paulson@30730: paulson@24286: lemma zero_less_power_abs_iff [simp,noatp]: paulson@15004: "(0 < (abs a)^n) = (a \ (0::'a::{ordered_idom,recpower}) | n=0)" paulson@14353: proof (induct "n") paulson@14353: case 0 huffman@30273: show ?case by simp paulson@14353: next paulson@14353: case (Suc n) huffman@30273: show ?case by (auto simp add: prems zero_less_mult_iff) paulson@14353: qed paulson@14353: paulson@14353: lemma zero_le_power_abs [simp]: paulson@15004: "(0::'a::{ordered_idom,recpower}) \ (abs a)^n" huffman@22957: by (rule zero_le_power [OF abs_ge_zero]) paulson@14353: huffman@28131: lemma power_minus: "(-a) ^ n = (- 1)^n * (a::'a::{ring_1,recpower}) ^ n" huffman@28131: proof (induct n) huffman@28131: case 0 show ?case by simp huffman@28131: next huffman@28131: case (Suc n) then show ?case huffman@30273: by (simp del: power_Suc add: power_Suc2 mult_assoc) paulson@14348: qed paulson@14348: paulson@14348: text{*Lemma for @{text power_strict_decreasing}*} paulson@14348: lemma power_Suc_less: paulson@15004: "[|(0::'a::{ordered_semidom,recpower}) < a; a < 1|] paulson@14348: ==> a * a^n < a^n" paulson@15251: apply (induct n) huffman@30273: apply (auto simp add: mult_strict_left_mono) paulson@14348: done paulson@14348: paulson@14348: lemma power_strict_decreasing: paulson@15004: "[|n < N; 0 < a; a < (1::'a::{ordered_semidom,recpower})|] paulson@14348: ==> a^N < a^n" wenzelm@14577: apply (erule rev_mp) paulson@15251: apply (induct "N") huffman@30273: apply (auto simp add: power_Suc_less less_Suc_eq) wenzelm@14577: apply (rename_tac m) paulson@14348: apply (subgoal_tac "a * a^m < 1 * a^n", simp) wenzelm@14577: apply (rule mult_strict_mono) huffman@30273: apply (auto simp add: order_less_imp_le) paulson@14348: done paulson@14348: paulson@14348: text{*Proof resembles that of @{text power_strict_decreasing}*} paulson@14348: lemma power_decreasing: paulson@15004: "[|n \ N; 0 \ a; a \ (1::'a::{ordered_semidom,recpower})|] paulson@14348: ==> a^N \ a^n" wenzelm@14577: apply (erule rev_mp) paulson@15251: apply (induct "N") huffman@30273: apply (auto simp add: le_Suc_eq) wenzelm@14577: apply (rename_tac m) paulson@14348: apply (subgoal_tac "a * a^m \ 1 * a^n", simp) wenzelm@14577: apply (rule mult_mono) huffman@30273: apply auto paulson@14348: done paulson@14348: paulson@14348: lemma power_Suc_less_one: paulson@15004: "[| 0 < a; a < (1::'a::{ordered_semidom,recpower}) |] ==> a ^ Suc n < 1" wenzelm@14577: apply (insert power_strict_decreasing [of 0 "Suc n" a], simp) paulson@14348: done paulson@14348: paulson@14348: text{*Proof again resembles that of @{text power_strict_decreasing}*} paulson@14348: lemma power_increasing: paulson@15004: "[|n \ N; (1::'a::{ordered_semidom,recpower}) \ a|] ==> a^n \ a^N" wenzelm@14577: apply (erule rev_mp) paulson@15251: apply (induct "N") huffman@30273: apply (auto simp add: le_Suc_eq) paulson@14348: apply (rename_tac m) paulson@14348: apply (subgoal_tac "1 * a^n \ a * a^m", simp) wenzelm@14577: apply (rule mult_mono) nipkow@25874: apply (auto simp add: order_trans [OF zero_le_one]) paulson@14348: done paulson@14348: paulson@14348: text{*Lemma for @{text power_strict_increasing}*} paulson@14348: lemma power_less_power_Suc: paulson@15004: "(1::'a::{ordered_semidom,recpower}) < a ==> a^n < a * a^n" paulson@15251: apply (induct n) huffman@30273: apply (auto simp add: mult_strict_left_mono order_less_trans [OF zero_less_one]) paulson@14348: done paulson@14348: paulson@14348: lemma power_strict_increasing: paulson@15004: "[|n < N; (1::'a::{ordered_semidom,recpower}) < a|] ==> a^n < a^N" wenzelm@14577: apply (erule rev_mp) paulson@15251: apply (induct "N") huffman@30273: apply (auto simp add: power_less_power_Suc less_Suc_eq) paulson@14348: apply (rename_tac m) paulson@14348: apply (subgoal_tac "1 * a^n < a * a^m", simp) wenzelm@14577: apply (rule mult_strict_mono) nipkow@25874: apply (auto simp add: order_less_trans [OF zero_less_one] order_less_imp_le) paulson@14348: done paulson@14348: nipkow@25134: lemma power_increasing_iff [simp]: nipkow@25134: "1 < (b::'a::{ordered_semidom,recpower}) ==> (b ^ x \ b ^ y) = (x \ y)" nipkow@25134: by (blast intro: power_le_imp_le_exp power_increasing order_less_imp_le) paulson@15066: paulson@15066: lemma power_strict_increasing_iff [simp]: nipkow@25134: "1 < (b::'a::{ordered_semidom,recpower}) ==> (b ^ x < b ^ y) = (x < y)" nipkow@25134: by (blast intro: power_less_imp_less_exp power_strict_increasing) paulson@15066: paulson@14348: lemma power_le_imp_le_base: nipkow@25134: assumes le: "a ^ Suc n \ b ^ Suc n" nipkow@25134: and ynonneg: "(0::'a::{ordered_semidom,recpower}) \ b" nipkow@25134: shows "a \ b" nipkow@25134: proof (rule ccontr) nipkow@25134: assume "~ a \ b" nipkow@25134: then have "b < a" by (simp only: linorder_not_le) nipkow@25134: then have "b ^ Suc n < a ^ Suc n" nipkow@25134: by (simp only: prems power_strict_mono) nipkow@25134: from le and this show "False" nipkow@25134: by (simp add: linorder_not_less [symmetric]) nipkow@25134: qed wenzelm@14577: huffman@22853: lemma power_less_imp_less_base: huffman@22853: fixes a b :: "'a::{ordered_semidom,recpower}" huffman@22853: assumes less: "a ^ n < b ^ n" huffman@22853: assumes nonneg: "0 \ b" huffman@22853: shows "a < b" huffman@22853: proof (rule contrapos_pp [OF less]) huffman@22853: assume "~ a < b" huffman@22853: hence "b \ a" by (simp only: linorder_not_less) huffman@22853: hence "b ^ n \ a ^ n" using nonneg by (rule power_mono) huffman@22853: thus "~ a ^ n < b ^ n" by (simp only: linorder_not_less) huffman@22853: qed huffman@22853: paulson@14348: lemma power_inject_base: wenzelm@14577: "[| a ^ Suc n = b ^ Suc n; 0 \ a; 0 \ b |] paulson@15004: ==> a = (b::'a::{ordered_semidom,recpower})" paulson@14348: by (blast intro: power_le_imp_le_base order_antisym order_eq_refl sym) paulson@14348: huffman@22955: lemma power_eq_imp_eq_base: huffman@22955: fixes a b :: "'a::{ordered_semidom,recpower}" huffman@22955: shows "\a ^ n = b ^ n; 0 \ a; 0 \ b; 0 < n\ \ a = b" huffman@30273: by (cases n, simp_all del: power_Suc, rule power_inject_base) huffman@22955: huffman@29978: text {* The divides relation *} huffman@29978: huffman@29978: lemma le_imp_power_dvd: huffman@29978: fixes a :: "'a::{comm_semiring_1,recpower}" huffman@29978: assumes "m \ n" shows "a^m dvd a^n" huffman@29978: proof huffman@29978: have "a^n = a^(m + (n - m))" huffman@29978: using `m \ n` by simp huffman@29978: also have "\ = a^m * a^(n - m)" huffman@29978: by (rule power_add) huffman@29978: finally show "a^n = a^m * a^(n - m)" . huffman@29978: qed huffman@29978: huffman@29978: lemma power_le_dvd: huffman@29978: fixes a b :: "'a::{comm_semiring_1,recpower}" huffman@29978: shows "a^n dvd b \ m \ n \ a^m dvd b" huffman@29978: by (rule dvd_trans [OF le_imp_power_dvd]) huffman@29978: paulson@14348: nipkow@30313: lemma dvd_power_same: nipkow@30313: "(x::'a::{comm_semiring_1,recpower}) dvd y \ x^n dvd y^n" nipkow@30313: by (induct n) (auto simp add: mult_dvd_mono) nipkow@30313: nipkow@30313: lemma dvd_power_le: nipkow@30313: "(x::'a::{comm_semiring_1,recpower}) dvd y \ m >= n \ x^n dvd y^m" nipkow@30313: by(rule power_le_dvd[OF dvd_power_same]) nipkow@30313: nipkow@30313: lemma dvd_power [simp]: nipkow@30313: "n > 0 | (x::'a::{comm_semiring_1,recpower}) = 1 \ x dvd x^n" nipkow@30313: apply (erule disjE) nipkow@30313: apply (subgoal_tac "x ^ n = x^(Suc (n - 1))") nipkow@30313: apply (erule ssubst) nipkow@30313: apply (subst power_Suc) nipkow@30313: apply auto nipkow@30313: done nipkow@30313: nipkow@30313: paulson@14348: subsection{*Exponentiation for the Natural Numbers*} paulson@3390: haftmann@25836: instantiation nat :: recpower haftmann@25836: begin haftmann@21456: haftmann@25836: primrec power_nat where haftmann@25836: "p ^ 0 = (1\nat)" haftmann@25836: | "p ^ (Suc n) = (p\nat) * (p ^ n)" wenzelm@14577: haftmann@25836: instance proof paulson@14438: fix z n :: nat paulson@14348: show "z^0 = 1" by simp paulson@14348: show "z^(Suc n) = z * (z^n)" by simp paulson@14348: qed paulson@14348: huffman@30273: declare power_nat.simps [simp del] huffman@30273: haftmann@25836: end haftmann@25836: huffman@23305: lemma of_nat_power: huffman@23305: "of_nat (m ^ n) = (of_nat m::'a::{semiring_1,recpower}) ^ n" huffman@30273: by (induct n, simp_all add: of_nat_mult) huffman@23305: huffman@30079: lemma nat_one_le_power [simp]: "Suc 0 \ i ==> Suc 0 \ i^n" huffman@30079: by (rule one_le_power [of i n, unfolded One_nat_def]) paulson@14348: nipkow@25162: lemma nat_zero_less_power_iff [simp]: "(x^n > 0) = (x > (0::nat) | n=0)" haftmann@21413: by (induct "n", auto) paulson@14348: nipkow@30056: lemma nat_power_eq_Suc_0_iff [simp]: nipkow@30056: "((x::nat)^m = Suc 0) = (m = 0 | x = Suc 0)" nipkow@30056: by (induct_tac m, auto) nipkow@30056: nipkow@30056: lemma power_Suc_0[simp]: "(Suc 0)^n = Suc 0" nipkow@30056: by simp nipkow@30056: paulson@14348: text{*Valid for the naturals, but what if @{text"0nat)" haftmann@21413: assumes less: "i^m < i^n" haftmann@21413: shows "m < n" haftmann@21413: proof (cases "i = 1") haftmann@21413: case True with less power_one [where 'a = nat] show ?thesis by simp haftmann@21413: next haftmann@21413: case False with nonneg have "1 < i" by auto haftmann@21413: from power_strict_increasing_iff [OF this] less show ?thesis .. haftmann@21413: qed paulson@14348: ballarin@17149: lemma power_diff: ballarin@17149: assumes nz: "a ~= 0" ballarin@17149: shows "n <= m ==> (a::'a::{recpower, field}) ^ (m-n) = (a^m) / (a^n)" ballarin@17149: by (induct m n rule: diff_induct) huffman@30273: (simp_all add: nonzero_mult_divide_cancel_left nz) ballarin@17149: paulson@3390: end