(* ========================================================================= *)
(* Geometric algebra. *)
(* *)
(* (c) Copyright, John Harrison 1998-2008 *)
(* ========================================================================= *)
needs "Multivariate/vectors.ml";;
needs "Library/binary.ml";;
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* Some basic lemmas, mostly set theory. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Index type for "multivectors" (k-vectors for all k <= N). *)
(* ------------------------------------------------------------------------- *)
let multivector_tybij =
new_type_definition "multivector" ("mk_multivector","dest_multivector")
multivector_tybij_th;;
(* ------------------------------------------------------------------------- *)
(* The bijections we use for indexing. *)
(* *)
(* Note that we need a *single* bijection over the entire space that also *)
(* works for the various subsets. Hence the tedious explicit construction. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Indexing directly via subsets. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("$$",(25,"left"));;
parse_as_binder "lambdas";;
(* ------------------------------------------------------------------------- *)
(* Crucial properties. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Also componentwise operations; they all work in this style. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Basis vectors indexed by subsets of 1..N. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Linear and bilinear functions are determined by their effect on basis. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* A way of proving linear properties by extension from basis. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Injection from regular vectors. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Subspace of k-vectors. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("multivector",(12,"right"));;
(* ------------------------------------------------------------------------- *)
(* k-grade part of a multivector. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("grade",(22,"right"));;
(* ------------------------------------------------------------------------- *)
(* General product construct. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* This is always bilinear. *)
(* ------------------------------------------------------------------------- *)
let PRODUCT_LADD = (MATCH_MP BILINEAR_LADD o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_RADD = (MATCH_MP BILINEAR_RADD o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_LMUL = (MATCH_MP BILINEAR_LMUL o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_RMUL = (MATCH_MP BILINEAR_RMUL o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_LNEG = (MATCH_MP BILINEAR_LNEG o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_RNEG = (MATCH_MP BILINEAR_RNEG o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_LZERO = (MATCH_MP BILINEAR_LZERO o SPEC_ALL) BILINEAR_PRODUCT;;
let PRODUCT_RZERO = (MATCH_MP BILINEAR_RZERO o SPEC_ALL) BILINEAR_PRODUCT;;
(* ------------------------------------------------------------------------- *)
(* Under suitable conditions, it's also associative. *)
(* ------------------------------------------------------------------------- *)
let PRODUCT_ASSOCIATIVE = prove
(`!op mult. (!s t. s
SUBSET 1..dimindex(:N) /\ t
SUBSET 1..dimindex(:N)
==> (op s t)
SUBSET 1..dimindex(:N)) /\
(!s t u. op s (op t u) = op (op s t) u) /\
(!s t u. mult t u * mult s (op t u) = mult s t * mult (op s t) u)
==> !x y z:real^(N)multivector.
Product mult op x (Product mult op y z) =
Product mult op (Product mult op x y) z`,
let SUM_SWAP_POWERSET =
SIMP_RULE[
FINITE_POWERSET;
FINITE_NUMSEG]
(repeat(SPEC `{s | s
SUBSET 1..dimindex(:N)}`)
(ISPEC `f:(num->bool)->(num->bool)->
real`
SUM_SWAP)) in
let SWAP_TAC cnv n =
GEN_REWRITE_TAC (cnv o funpow n BINDER_CONV) [SUM_SWAP_POWERSET] THEN
REWRITE_TAC[] in
let SWAPS_TAC cnv ns x =
MAP_EVERY (SWAP_TAC cnv) ns THEN MATCH_MP_TAC
SUM_EQ THEN X_GEN_TAC x THEN
REWRITE_TAC[
IN_ELIM_THM] THEN STRIP_TAC in
REWRITE_TAC[
Product_DEF] THEN REPEAT STRIP_TAC THEN
SIMP_TAC[
MULTIVECTOR_EQ;
MULTIVECTOR_VSUM_COMPONENT;
MBASIS_COMPONENT;
MULTIVECTOR_MUL_COMPONENT] THEN
SIMP_TAC[GSYM
SUM_LMUL; GSYM
SUM_RMUL] THEN
X_GEN_TAC `r:num->bool` THEN STRIP_TAC THEN
SWAPS_TAC RAND_CONV [1;0] `s:num->bool` THEN
SWAP_TAC LAND_CONV 0 THEN SWAPS_TAC RAND_CONV [1;0] `t:num->bool` THEN
SWAP_TAC RAND_CONV 0 THEN SWAPS_TAC LAND_CONV [0] `u:num->bool` THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC;
REAL_ARITH `(if p then a else &0) * b = if p then a * b else &0`;
REAL_ARITH `a * (if p then b else &0) = if p then a * b else &0`] THEN
SIMP_TAC[
SUM_DELTA] THEN ASM_SIMP_TAC[
IN_ELIM_THM] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[REAL_MUL_LID;
REAL_MUL_RID] THEN
ASM_REWRITE_TAC[] THEN REWRITE_TAC[
REAL_MUL_AC]);;
(* ------------------------------------------------------------------------- *)
(* Geometric product. *)
(* ------------------------------------------------------------------------- *)
overload_interface
("*",
`geom_mul:real^(N)multivector->real^(N)multivector->real^(N)multivector`);;
let GEOM_LADD = (MATCH_MP BILINEAR_LADD o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_RADD = (MATCH_MP BILINEAR_RADD o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_LMUL = (MATCH_MP BILINEAR_LMUL o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_RMUL = (MATCH_MP BILINEAR_RMUL o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_LNEG = (MATCH_MP BILINEAR_LNEG o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_RNEG = (MATCH_MP BILINEAR_RNEG o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_LZERO = (MATCH_MP BILINEAR_LZERO o SPEC_ALL) BILINEAR_GEOM;;
let GEOM_RZERO = (MATCH_MP BILINEAR_RZERO o SPEC_ALL) BILINEAR_GEOM;;
(* ------------------------------------------------------------------------- *)
(* Outer product. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("outer",(20,"right"));;
let outer = new_definition
`!x y:real^(N)multivector.
x outer y =
Product (\s t. if ~(s INTER t = {}) then &0
else --(&1) pow CARD {i,j | i IN 1..dimindex(:N) /\
j IN 1..dimindex(:N) /\
i IN s /\ j IN t /\ i > j})
(\s t. (s DIFF t) UNION (t DIFF s))
x y`;;
let OUTER = prove
(`!x y:real^(N)multivector.
x
outer y =
Product (\s t. if ~(s
INTER t = {}) then &0
else --(&1) pow
CARD {i,j | i
IN 1..dimindex(:N) /\
j
IN 1..dimindex(:N) /\
i
IN s /\ j
IN t /\ i > j})
(
UNION)
x y`,
let OUTER_LADD = (MATCH_MP BILINEAR_LADD o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_RADD = (MATCH_MP BILINEAR_RADD o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_LMUL = (MATCH_MP BILINEAR_LMUL o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_RMUL = (MATCH_MP BILINEAR_RMUL o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_LNEG = (MATCH_MP BILINEAR_LNEG o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_RNEG = (MATCH_MP BILINEAR_RNEG o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_LZERO = (MATCH_MP BILINEAR_LZERO o SPEC_ALL) BILINEAR_OUTER;;
let OUTER_RZERO = (MATCH_MP BILINEAR_RZERO o SPEC_ALL) BILINEAR_OUTER;;
(* ------------------------------------------------------------------------- *)
(* Inner product. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("inner",(20,"right"));;
let inner = new_definition
`!x y:real^(N)multivector.
x inner y =
Product (\s t. if s = {} \/ t = {} \/
~((s DIFF t) = {} /\ ~(t DIFF s = {}))
then &0
else --(&1) pow CARD {i,j | i IN 1..dimindex(:N) /\
j IN 1..dimindex(:N) /\
i IN s /\ j IN t /\ i > j})
(\s t. (s DIFF t) UNION (t DIFF s))
x y`;;
let INNER_LADD = (MATCH_MP BILINEAR_LADD o SPEC_ALL) BILINEAR_INNER;;
let INNER_RADD = (MATCH_MP BILINEAR_RADD o SPEC_ALL) BILINEAR_INNER;;
let INNER_LMUL = (MATCH_MP BILINEAR_LMUL o SPEC_ALL) BILINEAR_INNER;;
let INNER_RMUL = (MATCH_MP BILINEAR_RMUL o SPEC_ALL) BILINEAR_INNER;;
let INNER_LNEG = (MATCH_MP BILINEAR_LNEG o SPEC_ALL) BILINEAR_INNER;;
let INNER_RNEG = (MATCH_MP BILINEAR_RNEG o SPEC_ALL) BILINEAR_INNER;;
let INNER_LZERO = (MATCH_MP BILINEAR_LZERO o SPEC_ALL) BILINEAR_INNER;;
let INNER_RZERO = (MATCH_MP BILINEAR_RZERO o SPEC_ALL) BILINEAR_INNER;;
(* ------------------------------------------------------------------------- *)
(* Actions of products on basis and singleton basis. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Some simple consequences. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Just for generality, normalize a set enumeration. *)
(* ------------------------------------------------------------------------- *)
let SETENUM_NORM_CONV =
let conv =
GEN_REWRITE_CONV I [EXTENSION] THENC
GEN_REWRITE_CONV TOP_SWEEP_CONV [IN_SING; IN_INSERT] THENC
BINDER_CONV(EQT_INTRO o DISJ_ACI_RULE) THENC
GEN_REWRITE_CONV I [FORALL_SIMP] in
fun tm ->
let nums = dest_setenum tm in
let nums' = map mk_numeral (sort (</) (map dest_numeral (setify nums))) in
if nums' = nums then REFL tm else
let eq = mk_eq(tm,mk_setenum(nums',fst(dest_fun_ty(type_of tm)))) in
EQT_ELIM(conv eq);;
(* ------------------------------------------------------------------------- *)
(* Conversion to split extended basis combinations. *)
(* *)
(* Also 1-step merge from left, which can be DEPTH_CONV'd. In this case the *)
(* order must be correct. *)
(* ------------------------------------------------------------------------- *)
let MBASIS_SPLIT_CONV,MBASIS_MERGE_CONV =
let setlemma = SET_RULE
`((!x:num. x IN {} ==> a < x) <=> T) /\
((!x:num. x IN (y INSERT s) ==> a < x) <=>
a < y /\ (!x. x IN s ==> a < x))` in
let SET_CHECK_CONV =
GEN_REWRITE_CONV TOP_SWEEP_CONV [setlemma] THENC NUM_REDUCE_CONV
and INST_SPLIT = PART_MATCH (lhs o rand) MBASIS_SPLIT
and INST_MERGE = PART_MATCH (lhs o rand) (GSYM MBASIS_SPLIT) in
let rec conv tm =
if length(dest_setenum(rand tm)) <= 1 then REFL tm else
let th = MP_CONV SET_CHECK_CONV (INST_SPLIT tm) in
let th' = RAND_CONV conv (rand(concl th)) in
TRANS th th' in
(fun tm ->
try let op,se = dest_comb tm in
if fst(dest_const op) = "mbasis" & forall is_numeral (dest_setenum se)
then (RAND_CONV SETENUM_NORM_CONV THENC conv) tm
else fail()
with Failure _ -> failwith "MBASIS_SPLIT_CONV"),
(fun tm -> try MP_CONV SET_CHECK_CONV (INST_MERGE tm)
with Failure _ -> failwith "MBASIS_MERGE_CONV");;
(* ------------------------------------------------------------------------- *)
(* Convergent (if slow) rewrite set to bubble into position. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Group the final "c1 % mbasis s1 + ... + cn % mbasis sn". *)
(* ------------------------------------------------------------------------- *)
let MBASIS_GROUP_CONV tm =
let tms = striplist(dest_binary "vector_add") tm in
if length tms = 1 then LAND_CONV REAL_POLY_CONV tm else
let vadd_tm = rator(rator tm) in
let mk_vadd = mk_binop vadd_tm in
let mbs = map (snd o dest_binary "%") tms in
let tmbs = zip mbs tms and mset = setify mbs in
let grps = map (fun x -> map snd (filter (fun (x',_) -> x' = x) tmbs))
mset in
let tm' = end_itlist mk_vadd (map (end_itlist mk_vadd) grps) in
let th1 = AC VECTOR_ADD_AC (mk_eq(tm,tm'))
and th2 =
(GEN_REWRITE_CONV DEPTH_CONV [GSYM VECTOR_ADD_RDISTRIB] THENC
DEPTH_BINOP_CONV vadd_tm (LAND_CONV REAL_POLY_CONV)) tm' in
TRANS th1 th2;;
(* ------------------------------------------------------------------------- *)
(* Overall conversion. *)
(* ------------------------------------------------------------------------- *)
let OUTER_CANON_CONV =
ONCE_DEPTH_CONV MBASIS_SPLIT_CONV THENC
GEN_REWRITE_CONV TOP_DEPTH_CONV
[VECTOR_SUB; VECTOR_NEG_MINUS1;
OUTER_LADD; OUTER_RADD; OUTER_LMUL; OUTER_RMUL; OUTER_LZERO; OUTER_RZERO;
VECTOR_ADD_LDISTRIB; VECTOR_ADD_RDISTRIB; VECTOR_MUL_ASSOC;
VECTOR_MUL_LZERO; VECTOR_MUL_RZERO] THENC
REAL_RAT_REDUCE_CONV THENC
PURE_SIMP_CONV[OUTER_ACI; ARITH_GT; ARITH_GE; OUTER_LMUL; OUTER_RMUL;
OUTER_LZERO; OUTER_RZERO] THENC
PURE_REWRITE_CONV[VECTOR_MUL_LZERO; VECTOR_MUL_RZERO;
VECTOR_ADD_LID; VECTOR_ADD_RID; VECTOR_MUL_ASSOC] THENC
GEN_REWRITE_CONV I [GSYM VECTOR_MUL_LID] THENC
PURE_REWRITE_CONV
[VECTOR_ADD_LDISTRIB; VECTOR_ADD_RDISTRIB; VECTOR_MUL_ASSOC] THENC
REAL_RAT_REDUCE_CONV THENC PURE_REWRITE_CONV[GSYM VECTOR_ADD_ASSOC] THENC
DEPTH_CONV MBASIS_MERGE_CONV THENC
MBASIS_GROUP_CONV THENC
GEN_REWRITE_CONV DEPTH_CONV [GSYM VECTOR_ADD_RDISTRIB] THENC
REAL_RAT_REDUCE_CONV;;
(* ------------------------------------------------------------------------- *)
(* Iterated operation in order. *)
(* I guess this ought to be added to the core... *)
(* ------------------------------------------------------------------------- *)
let seqiterate_EXISTS = prove
(`!op f. ?h.
!s. h s = if
INFINITE s \/ s = {} then
neutral op else
let i =
minimal x. x
IN s in
if s = {i} then f(i) else op (f i) (h (s
DELETE i))`,
REPEAT GEN_TAC THEN REWRITE_TAC[
INFINITE] THEN
MATCH_MP_TAC(MATCH_MP
WF_REC (ISPEC `CARD:(num->bool)->num`
WF_MEASURE)) THEN
REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
LET_TAC THEN CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN AP_TERM_TAC THEN
FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[
MEASURE] THEN
RULE_ASSUM_TAC(REWRITE_RULE[DE_MORGAN_THM]) THEN
SUBGOAL_THEN `?i:num. i
IN s` MP_TAC THENL
[ASM_MESON_TAC[
MEMBER_NOT_EMPTY]; ALL_TAC] THEN
GEN_REWRITE_TAC LAND_CONV [
MINIMAL] THEN
ASM_SIMP_TAC[
CARD_DELETE;
CARD_EQ_0; ARITH_RULE `n - 1 < n <=> ~(n = 0)`]);;
let EXISTS_SWAP = prove
(`!P. (?f. P f) <=> (?f:A->B->C. P (\b a. f a b))`,
GEN_TAC THEN EQ_TAC THEN DISCH_THEN CHOOSE_TAC THENL
[EXISTS_TAC `\a b. (f:B->A->C) b a` THEN ASM_REWRITE_TAC[ETA_AX];
ASM_MESON_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* In the "common" case this agrees with ordinary iteration. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Outermorphism extension. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Reversion operation. *)
(* ------------------------------------------------------------------------- *)