let poly_tm = `poly`;;
let dest_poly tm =
let poly,[l;var] = strip_ncomb 2 tm in
if not (poly = poly_tm) then failwith "dest_poly: not a poly"
else l,var;;
let is_poly tm = fst (strip_comb tm) = `poly`;;
(* ------------------------------------------------------------------------- *)
(* Get the lead variable in polynomial; &1 if a constant. *)
(* ------------------------------------------------------------------------- *)
let polyvar =
let dummy_tm = `&1` in
fun tm -> if is_ratconst tm then dummy_tm else lhand(rand tm);;
(*
let k00 = `&3 * x * y pow 2 + &2 * x pow 2 * y * z + z * x + &3 * y * z`
let k0 = `(&0 + y * (&0 + z * &3)) + x * (((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2)))`;;
# polyvar k0;;
val it : Term.term = `x`
*)
(* ---------------------------------------------------------------------- *)
(* Is a constant polynomial (wrt variable ordering) *)
(* ---------------------------------------------------------------------- *)
let is_constant vars p =
assert (not (vars = []));
try
let l,r = dest_plus p in
let x,r2 = dest_mult r in
if x = hd vars then false else true
with _ ->
if p = hd vars then false else true;;
(* ------------------------------------------------------------------------- *)
(* We only use this as a handy way to do derivatives. *)
(* ------------------------------------------------------------------------- *)
let POLY = prove
(`(poly [] x = &0) /\
(poly [__c__] x = __c__) /\
(poly (CONS __h__ __t__) x = __h__ + x * poly __t__ x)`,
REWRITE_TAC[poly] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Convert in and out of list representations. *)
(* ------------------------------------------------------------------------- *)
(* THIS IS BAD CODE!!! It depends on the names of the variables in POLY *)
let POLY_ENLIST_CONV vars =
let lem = GEN rx POLY in
let [cnv_0; cnv_1; cnv_2] =
map (fun th -> GEN_REWRITE_CONV I [GSYM th]) (CONJUNCTS (ISPEC (hd vars) lem))
and zero_tm = rzero in
let rec conv tm =
if polyvar tm = hd vars then
(funpow 2 RAND_CONV conv THENC cnv_2) tm
else if tm = zero_tm then cnv_0 tm
else cnv_1 tm in
conv;;
(*
map GSYM (CONJUNCTS (ISPEC (hd vars) lem))
POLY_ENLIST_CONV vars p in
let tm = `&0 + c * &1`
POLY_ENLIST_CONV vars tm
#trace conv
POLY_ENLIST_CONV vars tm
let vars = [ry;rx]
let tm = `&0 + y * (&0 + x * &1)`
let k1 = rhs(concl (POLY_ENLIST_CONV [`x:real`;`y:real`;`z:real`] k0));;
POLY_ENLIST_CONV [`x:real`;`y:real`;`z:real`] k0;;
val it : Hol.thm =
|- k0 =
poly [&0 + y * (&0 + z * &3);
&0 * z * &1 + y * (&0 + y * &3);
&0 + y * (&0 + z * &2)] x
*)
let POLY_DELIST_CONV =
let [cnv_0; cnv_1; cnv_2] =
map (fun th -> GEN_REWRITE_CONV I [th]) (CONJUNCTS POLY) in
let rec conv tm =
(cnv_0 ORELSEC cnv_1 ORELSEC (cnv_2 THENC funpow 2 RAND_CONV conv)) tm in
conv;;
(*
# POLY_DELIST_CONV `poly [&5; &6; &7] x`;;
val it : Hol.thm = |- poly [&5; &6; &7] x = &5 + x * (&6 + x * &7)
*)
(* ------------------------------------------------------------------------- *)
(* Differentiation within list representation. *)
(* ------------------------------------------------------------------------- *)
(* let poly_diff_aux = new_recursive_definition list_RECURSION *)
(* `(poly_diff_aux n [] = []) /\ *)
(* (poly_diff_aux n (CONS h t) = CONS (&n * h) (poly_diff_aux (SUC n) t))`;; *)
(* let poly_diff = new_definition *)
(* `poly_diff l = if l = [] then [] else poly_diff_aux 1 (TL l)`;; *)
let POLY_DIFF_LEMMA = prove
(`!l n x. ((\x. (x pow (SUC n)) * poly l x) diffl
((x pow n) * poly (
poly_diff_aux (SUC n) l) x))(x)`,
(* {{{ Proof *)
LIST_INDUCT_TAC THEN
REWRITE_TAC[poly;
poly_diff_aux;
REAL_MUL_RZERO;
DIFF_CONST] THEN
MAP_EVERY X_GEN_TAC [`n:num`; `x:real`] THEN
REWRITE_TAC[REAL_LDISTRIB; REAL_MUL_ASSOC] THEN
ONCE_REWRITE_TAC[GSYM(ONCE_REWRITE_RULE[REAL_MUL_SYM] (CONJUNCT2 pow))] THEN
POP_ASSUM(MP_TAC o SPECL [`SUC n`; `x:real`]) THEN
SUBGOAL_THEN `(((\x. (x pow (SUC n)) * h)) diffl
((x pow n) * &(SUC n) * h))(x)`
(fun th -> DISCH_THEN(MP_TAC o CONJ th)) THENL
[REWRITE_TAC[REAL_MUL_ASSOC] THEN ONCE_REWRITE_TAC[REAL_MUL_SYM] THEN
MP_TAC(SPEC `\x. x pow (SUC n)`
DIFF_CMUL) THEN BETA_TAC THEN
DISCH_THEN MATCH_MP_TAC THEN
MP_TAC(SPEC `SUC n`
DIFF_POW) THEN REWRITE_TAC[
SUC_SUB1] THEN
DISCH_THEN(MATCH_ACCEPT_TAC o ONCE_REWRITE_RULE[REAL_MUL_SYM]);
DISCH_THEN(MP_TAC o MATCH_MP
DIFF_ADD) THEN BETA_TAC THEN
REWRITE_TAC[REAL_MUL_ASSOC]]);;
(* }}} *)
let POLY_DIFF = prove
(`!l x. ((\x. poly l x) diffl (poly (
poly_diff l) x))(x)`,
(* {{{ Proof *)
LIST_INDUCT_TAC THEN REWRITE_TAC[
POLY_DIFF_CLAUSES] THEN
ONCE_REWRITE_TAC[SYM(ETA_CONV `\x. poly l x`)] THEN
REWRITE_TAC[poly;
DIFF_CONST] THEN
MAP_EVERY X_GEN_TAC [`x:real`] THEN
MP_TAC(SPECL [`t:(real)list`; `0`; `x:real`]
POLY_DIFF_LEMMA) THEN
REWRITE_TAC[SYM(num_CONV `1`)] THEN REWRITE_TAC[pow; REAL_MUL_LID] THEN
REWRITE_TAC[
POW_1] THEN
DISCH_THEN(MP_TAC o CONJ (SPECL [`h:real`; `x:real`]
DIFF_CONST)) THEN
DISCH_THEN(MP_TAC o MATCH_MP
DIFF_ADD) THEN BETA_TAC THEN
REWRITE_TAC[REAL_ADD_LID]);;
(* }}} *)
let CANON_POLY_DIFF_CONV =
let aux_conv0 = GEN_REWRITE_CONV I [CONJUNCT1 poly_diff_aux]
and aux_conv1 = GEN_REWRITE_CONV I [CONJUNCT2 poly_diff_aux]
and diff_conv0 = GEN_REWRITE_CONV I (butlast (CONJUNCTS POLY_DIFF_CLAUSES))
and diff_conv1 = GEN_REWRITE_CONV I [last (CONJUNCTS POLY_DIFF_CLAUSES)] in
let rec POLY_DIFF_AUX_CONV tm =
(aux_conv0 ORELSEC
(aux_conv1 THENC
RAND_CONV (LAND_CONV NUM_SUC_CONV THENC POLY_DIFF_AUX_CONV))) tm in
diff_conv0 ORELSEC
(diff_conv1 THENC POLY_DIFF_AUX_CONV);;
(*
# POLY_DIFF_CONV (mk_comb(`poly_diff`,k2));;
val it : Hol.thm =
|- poly_diff k2 =
[&1 * (&0 * z * &1 + y * (&0 + y * &3)); &2 * (&0 + y * (&0 + z * &2))]
*)
(* ------------------------------------------------------------------------- *)
(* Whether the first of two items comes earlier in the list. *)
(* ------------------------------------------------------------------------- *)
let rec earlier l x y =
match l with
h::t -> if h = y then false
else if h = x then true
else earlier t x y
| [] -> false;;
(* ------------------------------------------------------------------------- *)
(* Add polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLY_ADD_CONV =
let [cnv_r; cnv_l; cnv_2; cnv_0] = (map REWR_CONV o CONJUNCTS o REAL_ARITH)
`(pol1 + (d + y * q) = (pol1 + d) + y * q) /\
((c + x * p) + pol2 = (c + pol2) + x * p) /\
((c + x * p) + (d + x * q) = (c + d) + x * (p + q)) /\
(c + x * &0 = c)`
and dest_add = dest_binop `(+)` in
let rec POLY_ADD_CONV vars tm =
let pol1,pol2 = dest_add tm in
let x = polyvar pol1 and y = polyvar pol2 in
if not(is_var x) & not(is_var y) then REAL_RAT_REDUCE_CONV tm else
if not(is_var y) or earlier vars x y then
(cnv_l THENC LAND_CONV (POLY_ADD_CONV vars)) tm
else if not(is_var x) or earlier vars y x then
(cnv_r THENC LAND_CONV (POLY_ADD_CONV vars)) tm
else
(cnv_2 THENC COMB_CONV(RAND_CONV(POLY_ADD_CONV vars)) THENC
TRY_CONV cnv_0) tm in
POLY_ADD_CONV;;
(*
# POLY_ADD_CONV [`x:real`;`y:real`;`z:real`] (mk_binop `(+)` k0 k0) ;;
val it : Hol.thm =
|- ((&0 + y * (&0 + z * &3)) +
x *
(((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2)))) +
(&0 + y * (&0 + z * &3)) +
x * (((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2))) =
(&0 + y * (&0 + z * &6)) +
x * (((&0 + z * &2) + y * (&0 + y * &6)) + x * (&0 + y * (&0 + z * &4)))
*)
(* ------------------------------------------------------------------------- *)
(* Negate polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLY_NEG_CONV =
let cnv = REWR_CONV(REAL_ARITH `--(c + x * p) = --c + x * --p`) in
let rec POLY_NEG_CONV tm =
if is_ratconst(rand tm) then REAL_RAT_NEG_CONV tm else
(cnv THENC COMB_CONV(RAND_CONV POLY_NEG_CONV)) tm in
POLY_NEG_CONV;;
(* ------------------------------------------------------------------------- *)
(* Subtract polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLY_SUB_CONV =
let cnv = REWR_CONV real_sub in
fun vars -> cnv THENC RAND_CONV POLY_NEG_CONV THENC POLY_ADD_CONV vars;;
(* ------------------------------------------------------------------------- *)
(* Multiply polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLY_MUL_CONV =
let [cnv_l1; cnv_r1; cnv_2; cnv_l0; cnv_r0] =
(map REWR_CONV o CONJUNCTS o REAL_ARITH)
`(pol1 * (d + y * q) = (pol1 * d) + y * (pol1 * q)) /\
((c + x * p) * pol2 = (c * pol2) + x * (p * pol2)) /\
(pol1 * (d + x * q) = pol1 * d + (&0 + x * pol1 * q)) /\
(&0 * pol2 = &0) /\
(pol1 * &0 = &0)`
and dest_mul = dest_binop `( * )`
and zero_tm = `&0` in
let rec POLY_MUL_CONV vars tm =
let pol1,pol2 = dest_mul tm in
if pol1 = zero_tm then cnv_l0 tm
else if pol2 = zero_tm then cnv_r0 tm
else if is_ratconst pol1 & is_ratconst pol2 then REAL_RAT_MUL_CONV tm else
let x = polyvar pol1 and y = polyvar pol2 in
if not(is_var y) or earlier vars x y then
(cnv_r1 THENC COMB_CONV(RAND_CONV(POLY_MUL_CONV vars))) tm
else if not(is_var x) or earlier vars y x then
(cnv_l1 THENC COMB_CONV(RAND_CONV(POLY_MUL_CONV vars))) tm
else
(cnv_2 THENC COMB2_CONV (RAND_CONV(POLY_MUL_CONV vars))
(funpow 2 RAND_CONV (POLY_MUL_CONV vars)) THENC
POLY_ADD_CONV vars) tm in
POLY_MUL_CONV;;
(*
# POLY_MUL_CONV [`x:real`;`y:real`;`z:real`] (mk_binop `( * )` k0 k0) ;;
val it : Hol.thm =
|- ((&0 + y * (&0 + z * &3)) +
x *
(((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2)))) *
((&0 + y * (&0 + z * &3)) +
x *
(((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2)))) =
(&0 + y * (&0 + y * (&0 + z * (&0 + z * &9)))) +
x *
((&0 + y * ((&0 + z * (&0 + z * &6)) + y * (&0 + y * (&0 + z * &18)))) +
x *
(((&0 + z * (&0 + z * &1)) +
y * (&0 + y * ((&0 + z * (&6 + z * &12)) + y * (&0 + y * &9)))) +
x *
((&0 + y * ((&0 + z * (&0 + z * &4)) + y * (&0 + y * (&0 + z * &12)))) +
x * (&0 + y * (&0 + y * (&0 + z * (&0 + z * &4)))))))
*)
(* ------------------------------------------------------------------------- *)
(* Exponentiate polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLY_POW_CONV =
let [cnv_0; cnv_1] = map REWR_CONV (CONJUNCTS real_pow)
and zero_tm = `0` in
let rec POLY_POW_CONV vars tm =
if rand tm = zero_tm then cnv_0 tm else
(RAND_CONV num_CONV THENC cnv_1 THENC
RAND_CONV (POLY_POW_CONV vars) THENC
POLY_MUL_CONV vars) tm in
POLY_POW_CONV;;
(*
# POLY_POW_CONV [`x:real`;`y:real`;`z:real`] (mk_binop `(pow)` k0 `2`) ;;
val it : Hol.thm =
|- ((&0 + y * (&0 + z * &3)) +
x *
(((&0 + z * &1) + y * (&0 + y * &3)) + x * (&0 + y * (&0 + z * &2)))) pow
2 =
(&0 + y * (&0 + y * (&0 + z * (&0 + z * &9)))) +
x *
((&0 + y * ((&0 + z * (&0 + z * &6)) + y * (&0 + y * (&0 + z * &18)))) +
x *
(((&0 + z * (&0 + z * &1)) +
y * (&0 + y * ((&0 + z * (&6 + z * &12)) + y * (&0 + y * &9)))) +
x *
((&0 + y * ((&0 + z * (&0 + z * &4)) + y * (&0 + y * (&0 + z * &12)))) +
x * (&0 + y * (&0 + y * (&0 + z * (&0 + z * &4)))))))
*)
(* ------------------------------------------------------------------------- *)
(* Convert expression to canonical polynomials. *)
(* ------------------------------------------------------------------------- *)
let POLYNATE_CONV =
let cnv_var = REWR_CONV(REAL_ARITH `x = &0 + x * &1`)
and cnv_div = REWR_CONV real_div
and neg_tm = `(--)`
and add_tm = `(+)`
and sub_tm = `(-)`
and mul_tm = `( * )`
and pow_tm = `(pow)`
and div_tm = `(/)` in
let rec POLYNATE_CONV vars tm =
if is_var tm then cnv_var tm
else if is_ratconst tm then REFL tm else
let lop,r = dest_comb tm in
if lop = neg_tm
then (RAND_CONV(POLYNATE_CONV vars) THENC POLY_NEG_CONV) tm else
let op,l = dest_comb lop in
if op = pow_tm then
(LAND_CONV(POLYNATE_CONV vars) THENC POLY_POW_CONV vars) tm
else if op = div_tm then
(cnv_div THENC
COMB2_CONV (RAND_CONV(POLYNATE_CONV vars)) REAL_RAT_REDUCE_CONV THENC
POLY_MUL_CONV vars) tm else
let cnv = if op = add_tm then POLY_ADD_CONV
else if op = sub_tm then POLY_SUB_CONV
else if op = mul_tm then POLY_MUL_CONV
else failwith "POLYNATE_CONV: unknown operation" in
(BINOP_CONV (POLYNATE_CONV vars) THENC cnv vars) tm in
POLYNATE_CONV;;
(*
POLYNATE_CONV [`x:real`;`y:real`] `x + y`;;
POLYNATE_CONV [`x:real`;`y:real`] `x * y + &2 * y`;;
*)
(* ------------------------------------------------------------------------- *)
(* Pure term manipulation versions; will optimize eventually. *)
(* ------------------------------------------------------------------------- *)
let poly_add_ =
let add_tm = `(+)` in
fun vars p1 p2 ->
rand(concl(POLY_ADD_CONV vars (mk_comb(mk_comb(add_tm,p1),p2))));;
let poly_sub_ =
let sub_tm = `(-)` in
fun vars p1 p2 ->
rand(concl(POLY_SUB_CONV vars (mk_comb(mk_comb(sub_tm,p1),p2))));;
let poly_mul_ =
let mul_tm = `( * )` in
fun vars p1 p2 ->
rand(concl(POLY_MUL_CONV vars (mk_comb(mk_comb(mul_tm,p1),p2))));;
let poly_neg_ =
let neg_tm = `(--)` in
fun p -> rand(concl(POLY_NEG_CONV(mk_comb(neg_tm,p))));;
let poly_pow_ =
let pow_tm = `(pow)` in
fun vars p k ->
rand(concl(POLY_POW_CONV vars
(mk_comb(mk_comb(pow_tm,p),mk_small_numeral k))));;
(* ------------------------------------------------------------------------- *)
(* Get the degree of a polynomial. *)
(* ------------------------------------------------------------------------- *)
let rec degree_ vars tm =
if polyvar tm = hd vars then 1 + degree_ vars (funpow 2 rand tm)
else 0;;
(* ------------------------------------------------------------------------- *)
(* Get the list of coefficients. *)
(* ------------------------------------------------------------------------- *)
let rec coefficients vars tm =
if polyvar tm = hd vars then (lhand tm)::coefficients vars (funpow 2 rand tm)
else [tm];;
(* ------------------------------------------------------------------------- *)
(* Get the head constant. *)
(* ------------------------------------------------------------------------- *)
let head vars p = last(coefficients vars p);;
(* ---------------------------------------------------------------------- *)
(* Remove the head coefficient *)
(* ---------------------------------------------------------------------- *)
let rec behead vars tm =
try
let c,r = dest_plus tm in
let x,p = dest_mult r in
if not (x = hd vars) then failwith "" else
let p' = behead vars p in
if p' = rzero then c
else mk_plus c (mk_mult x p')
with _ -> rzero;;
(*
behead [`x:real`] `&1 + x * (&1 + x * (&0 + y * &1))`
*)
let BEHEAD =
let lem = ARITH_RULE `a + b * &0 = a` in
fun vars zthm tm ->
let tm' = behead vars tm in
(* note: pure rewrite is ok here, as tm is in canonical form *)
let thm1 = PURE_REWRITE_CONV[zthm] tm in
let thm2 = PURE_REWRITE_CONV[lem] (rhs(concl thm1)) in
let thm3 = TRANS thm1 thm2 in
thm3;;
let BEHEAD3 =
let lem = ARITH_RULE `a + b * &0 = a` in
fun vars zthm tm ->
let tm' = behead vars tm in
(* note slight hack here:
BEHEAD was working fine if
p = a + x * b where a <> b. But
when they were equal, dropping multiple levels
broke the reconstruction. Thus, we only do conversion
on the right except when the head variable has been fully eliminated *)
let conv =
let l,r = dest_binop rp tm in
let l1,r1 = dest_binop rm r in
if l1 = hd vars then RAND_CONV(PURE_ONCE_REWRITE_CONV[zthm])
else PURE_ONCE_REWRITE_CONV[zthm] in
let thm1 = conv tm in
let thm2 = PURE_REWRITE_CONV[lem] (rhs(concl thm1)) in
let thm3 = TRANS thm1 thm2 in
thm3;;
let BEHEAD = BEHEAD3;;
(*
let vars = [`z:real`;`x:real`]
let zthm = (ASSUME `&0 + x * &1 = &0`)
let tm = `(&0 + x * &1) + z * (&0 + x * &1)`
behead vars tm
BEHEAD vars zthm tm
BEHEAD2 vars zthm tm
BEHEAD3 vars zthm tm
let tm = `(&0 + x * &1)`
BEHEAD3 vars zthm tm
let vars = [`x:real`]
let tm = `&1 + x * (&1 + x * (&0 + y * &1))`
let zthm = (ASSUME `&0 + y * &1 = &0`)
BEHEAD vars zthm tm
BEHEAD2 vars zthm tm
*)
(* ------------------------------------------------------------------------- *)
(* Test whether a polynomial is a constant w.r.t. the head variable. *)
(* ------------------------------------------------------------------------- *)
let is_const_poly vars tm = polyvar tm <> hd vars;;
(* ------------------------------------------------------------------------- *)
(* Get the constant multiple of the "maximal" monomial (implicit lex order) *)
(* ------------------------------------------------------------------------- *)
let rec headconst p =
try rat_of_term p with Failure _ -> headconst(funpow 2 rand p);;
(* ------------------------------------------------------------------------- *)
(* Monicize; return |- const * pol = monic-pol *)
(* ------------------------------------------------------------------------- *)
let MONIC_CONV =
let mul_tm = `( * ):real->real->real` in
fun vars p ->
let c = Int 1 // headconst p in
POLY_MUL_CONV vars (mk_comb(mk_comb(mul_tm,term_of_rat c),p));;
(* ------------------------------------------------------------------------- *)
(* Pseudo-division of s by p; head coefficient of p assumed nonzero. *)
(* Returns |- a^k s = p q + r for some q and r with deg(r) < deg(p). *)
(* Optimized only for the trivial case of equal head coefficients; no GCDs. *)
(* ------------------------------------------------------------------------- *)
let PDIVIDE =
let zero_tm = `&0`
and add0_tm = `(+) (&0)`
and add_tm = `(+)`
and mul_tm = `( * )`
and pow_tm = `(pow)`
and one_tm = `&1` in
let mk_varpow vars k =
let mulx_tm = mk_comb(mul_tm,hd vars) in
funpow k (fun t -> mk_comb(add0_tm,mk_comb(mulx_tm,t))) one_tm in
let rec pdivide_aux vars a n p s =
if s = zero_tm then (0,zero_tm,s) else
let b = head vars s and m = degree_ vars s in
if m < n then (0,zero_tm,s) else
let xp = mk_varpow vars (m - n) in
let p' = poly_mul_ vars xp p in
if a = b then
let (k,q,r) = pdivide_aux vars a n p (poly_sub_ vars s p') in
(k,poly_add_ vars q (poly_mul_ vars xp (poly_pow_ vars a k)),r)
else
let (k,q,r) = pdivide_aux vars a n p
(poly_sub_ vars (poly_mul_ vars a s) (poly_mul_ vars b p')) in
let q' = poly_add_ vars q (poly_mul_ vars b
(poly_mul_ vars (poly_pow_ vars a k) xp)) in
(k+1,q',r) in
fun vars s p ->
let a = head vars p in
let (k,q,r) = pdivide_aux vars a (degree_ vars p) p s in
let th1 = POLY_MUL_CONV vars (mk_comb(mk_comb(mul_tm,q),p)) in
let th2 = AP_THM (AP_TERM add_tm th1) r in
let th3 = CONV_RULE(RAND_CONV(POLY_ADD_CONV vars)) th2 in
let th4 = POLY_POW_CONV vars
(mk_comb(mk_comb(pow_tm,a),mk_small_numeral k)) in
let th5 = AP_THM (AP_TERM mul_tm th4) s in
let th6 = CONV_RULE(RAND_CONV(POLY_MUL_CONV vars)) th5 in
TRANS th6 (GSYM th3);;
(* ------------------------------------------------------------------------- *)
(* Produce sign theorem for rational constant. *)
(* ------------------------------------------------------------------------- *)
let SIGN_CONST =
let zero = Int 0
and zero_tm = `&0`
and eq_tm = `(=):real->real->bool`
and gt_tm = `(>):real->real->bool`
and lt_tm = `(<):real->real->bool` in
fun tm ->
let x = rat_of_term tm in
if x =/ zero then
EQT_ELIM(REAL_RAT_EQ_CONV(mk_comb(mk_comb(eq_tm,tm),zero_tm)))
else if x >/ zero then
EQT_ELIM(REAL_RAT_GT_CONV(mk_comb(mk_comb(gt_tm,tm),zero_tm)))
else
EQT_ELIM(REAL_RAT_LT_CONV(mk_comb(mk_comb(lt_tm,tm),zero_tm)));;
(*
SIGN_CONST `-- &5`;;
val it : Hol.thm = |- &5 > &0
*)
(* ------------------------------------------------------------------------- *)
(* Differentiation conversion in main representation. *)
(* ------------------------------------------------------------------------- *)
let POLY_DERIV_CONV =
let poly_diff_tm = `poly_diff`
and pth = GEN_REWRITE_RULE I [SWAP_FORALL_THM] POLY_DIFF in
fun vars tm ->
let th1 = POLY_ENLIST_CONV vars tm in
let th2 = SPECL [hd vars; lhand(rand(concl th1))] pth in
CONV_RULE(RATOR_CONV
(COMB2_CONV (RAND_CONV(ABS_CONV(POLY_DELIST_CONV)))
(LAND_CONV(CANON_POLY_DIFF_CONV THENC
LIST_CONV (POLY_MUL_CONV vars)) THENC
POLY_DELIST_CONV))) th2;;
(*
let k0 = (rhs o concl) (POLYNATE_CONV [`x:real`] `x pow 2 * y`);;
let vars = [`x:real`]
let tm = k0
let k1 = concl th2
let k2 = rator k1
let l,r = dest_comb k2
RATOR_CONV
(RAND_CONV(ABS_CONV(POLY_DELIST_CONV))) l
(LAND_CONV(POLY_DIFF_CONV THENC LIST_CONV (CANON_POLY_MUL_CONV vars)) THENC POLY_DELIST_CONV) r
(LAND_CONV(POLY_DIFF_CONV THENC LIST_CONV (CANON_POLY_MUL_CONV vars))) r
(LAND_CONV(POLY_DIFF_CONV)) r
POLY_DERIV_CONV [`x:real`] (rhs(concl((POLYNATE_CONV [`x:real`] `x pow 2 * y`))));;
val it : Hol.thm =
|- ((\x. &0 + x * (&0 + x * (&0 + y * &1))) diffl &0 + x * (&0 + y * &2)) x
*)
(* ---------------------------------------------------------------------- *)
(* POLYATOM_CONV *)
(* ---------------------------------------------------------------------- *)
(*
This is the AFN_CONV argument to the lifting function LIFT_QELIM_CONV
*)
(* }}} *)
(* }}} *)
(* }}} *)
let POLYATOM_CONV vars tm =
let thm1 = ONCE_REWRITE_CONV[real_gt;real_ge;eq_lem] tm in
let l,r = dest_eq (concl thm1) in
let thm2 = ONCE_REWRITE_CONV[lt_lem;le_lem] r in
let op,l',r' = get_binop (rhs (concl thm2)) in
let thm3a = POLYNATE_CONV vars l' in
let thm3b = AP_TERM op thm3a in
let thm3 = AP_THM thm3b rzero in
end_itlist TRANS [thm1;thm2;thm3];;
(*
let k0 = `x pow 2 + y * x - &5 > x + &10`
let k0 = `x pow 2 + y * x - &5 >= x + &10`
let k0 = `x pow 2 + y * x - &5 < x + &10`
let k0 = `x pow 2 + y * x - &5 <= x + &10`
let k0 = `x pow 2 + y * x - &5 = x + &10`
let tm = k0;;
let vars = [`x:real`;`y:real`]
POLYATOM_CONV vars k0
let vars = [`e:real`; `k:real`;`f:real`;`a:real`]
prioritize_real()
let tm = `k < e`
let liouville =
`&6 * (w pow 2 + x pow 2 + y pow 2 + z pow 2) pow 2 =
(((w + x) pow 4 + (w + y) pow 4 + (w + z) pow 4 +
(x + y) pow 4 + (x + z) pow 4 + (y + z) pow 4) +
((w - x) pow 4 + (w - y) pow 4 + (w - z) pow 4 +
(x - y) pow 4 + (x - z) pow 4 + (y - z) pow 4))`
let lvars = [`w:real`;`x:real`;`y:real`; `z:real`]
POLYATOM_CONV lvars liouville
*)
(* ---------------------------------------------------------------------- *)
(* Factoring *)
(* ---------------------------------------------------------------------- *)
let weakfactor x pol =
let rec weakfactor k x pol =
try
let ls,rs = dest_plus pol in
if not (ls = rzero) then failwith "" else
let lm,rm = dest_mult rs in
if not (lm = x) then failwith "" else
weakfactor (k + 1) x rm
with Failure _ ->
k,pol in
weakfactor 0 x pol;;
let poly_var x = mk_plus rzero (mk_mult x rone);;
(*
poly_var rx
*)
let POW_PROD_SUM = prove_by_refinement(
`!x n m. (x pow n) * x pow m = x pow (n + m)`,
(* {{{ Proof *)
[
STRIP_TAC THEN STRIP_TAC THEN INDUCT_TAC;
REWRITE_TAC[
real_pow];
NUM_SIMP_TAC;
REAL_SIMP_TAC;
REWRITE_TAC[
real_pow];
REWRITE_TAC[ARITH_RULE `n + SUC m = SUC (n + m)`];
REWRITE_TAC[
real_pow];
POP_ASSUM (SUBST1_TAC o GSYM);
REAL_ARITH_TAC;
]);;
(* }}} *)
let lem1 = REAL_ARITH `x * x = x pow 2`;;
let lem2 = GSYM (CONJUNCT2 real_pow);;
let lem3 = REAL_ARITH `!x. x = x pow 1`;;
let SIMP_POW_CONV tm =
let thm1 = ((REWRITE_CONV [GSYM REAL_MUL_ASSOC;lem1;lem2;POW_PROD_SUM]) THENC (ARITH_SIMP_CONV[])) tm in
let _,r = dest_eq (concl thm1) in
if can dest_pow r then thm1 else
let thm2 = ISPEC r lem3 in
thm2;;
(*
SIMP_POW_CONV `x * x * x * x * x`
SIMP_POW_CONV `x * x * (x * x) * x`
SIMP_POW_CONV `x * (x * (x * x)) *(x * x)`
SIMP_POW_CONV `x:real`
*)
let WEAKFACTOR_CONV x pol =
let k,pol' = weakfactor x pol in
let thm1 = ((itlist2 (fun x y z -> ((funpow y RAND_CONV) x) THENC z)
(replicate (GEN_REWRITE_CONV I [REAL_ADD_LID]) k)
(0--(k-1)) ALL_CONV) THENC
(PURE_REWRITE_CONV[REAL_MUL_ASSOC])) pol in
let thm2 = (CONV_RULE (RAND_CONV (LAND_CONV SIMP_POW_CONV))) thm1 in
thm2;;
(*
let pol = `&0 + x * (&0 + x * (&0 + y * &1))`
let pol = `&0 + x * (&0 + x * (&0 + x * (&0 + x * (&0 + x * (&0 + x * (&0 + y * &1))))))`
let pol = `&0 + x * (&0 + x * (&0 + x * (&0 + x * (&0 + x * (&1 + x * (&0 + y * &1))))))`
let pol = `&1 + x * (&0 + x * (&0 + y * &1))`
let pol = `&0 + x * (&1 + x * (&0 + y * &1))`
WEAKFACTOR_CONV rx pol
weakfactor rx pol
*)