VQCS.Qalgebra
Require Export Quantity.
Generalizable Variable tA Aadd Azero Aopp Amul Aone Ainv.
Generalizable Variable tB Badd Bzero Bopp Bmul Bone Binv.
Definition qop1 {tA} (f : tA -> tA) (q : @Quantity tA) : @Quantity tA :=
match q with
| Qmake v n => Qmake (f v) n
| _ => !!
end.
match q with
| Qmake v n => Qmake (f v) n
| _ => !!
end.
General binary quantity operation on same unit
Definition qop2 {tA} (f : tA -> tA -> tA) (q1 q2 : @Quantity tA) : @Quantity tA :=
match q1, q2 with
| Qmake v1 n1, Qmake v2 n2 => if neqb n1 n2 then Qmake (f v1 v2)%A n1 else !!
| _, _ => !!
end.
match q1, q2 with
| Qmake v1 n1, Qmake v2 n2 => if neqb n1 n2 then Qmake (f v1 v2)%A n1 else !!
| _, _ => !!
end.
General binary quantity operation on convertible untis, adopting the unit of
the left operand q1
Definition qop2l {tA} (ARmul : R -> tA -> tA) (f : tA -> tA -> tA)
(q1 q2 : @Quantity tA) : @Quantity tA :=
if qcvtbleb q1 q2 then qop2 f q1 (q2q ARmul q2 q1) else !!.
(q1 q2 : @Quantity tA) : @Quantity tA :=
if qcvtbleb q1 q2 then qop2 f q1 (q2q ARmul q2 q1) else !!.
General binary quantity operation on convertible untis, adopting the unit of
the right operand q2
Definition qop2r {tA} (ARmul : R -> tA -> tA) (f : tA -> tA -> tA)
(q1 q2 : @Quantity tA) : @Quantity tA :=
if qcvtbleb q1 q2 then qop2 f (q2q ARmul q1 q2) q2 else !!.
(q1 q2 : @Quantity tA) : @Quantity tA :=
if qcvtbleb q1 q2 then qop2 f (q2q ARmul q1 q2) q2 else !!.
General unary quantity operation, on which the quantity is dimensionless
Definition qdim0op1 {tA} (f : tA -> tA) (q : @Quantity tA) : @Quantity tA :=
match q with
| Qmake v n => if ndim1b n then Qmake (f v) n else !!
| _ => !!
end.
match q with
| Qmake v n => if ndim1b n then Qmake (f v) n else !!
| _ => !!
end.
General binary quantity operation, on which the quantity is dimensionless
Definition qdim0op2 {tA} (f : tA -> tA -> tA) (q1 q2 : @Quantity tA)
: @Quantity tA :=
match q1, q2 with
| Qmake v1 n1, Qmake v2 n2 =>
if ndim1b n1 && ndim1b n2 then Qmake (f v1 v2) n1 else !!
| _, _ => !!
end.
: @Quantity tA :=
match q1, q2 with
| Qmake v1 n1, Qmake v2 n2 =>
if ndim1b n1 && ndim1b n2 then Qmake (f v1 v2) n1 else !!
| _, _ => !!
end.
Section qadd_qopp_qsub.
Context {tA} (ARmul : R -> tA -> tA) (Aadd : tA -> tA -> tA) (Aopp : tA -> tA).
Context {tA} (ARmul : R -> tA -> tA) (Aadd : tA -> tA -> tA) (Aopp : tA -> tA).
Quantity addition using same unit
Definition qadd (q1 q2 : Quantity) : Quantity := qop2 Aadd q1 q2.
Infix "+" := qadd : Quantity_scope.
Infix "+" := qadd : Quantity_scope.
Quantity addition using the unit of the left operand q1
Definition qaddl (q1 q2 : Quantity) : Quantity := qop2l ARmul Aadd q1 q2.
Infix "'+" := qaddl : Quantity_scope.
Infix "'+" := qaddl : Quantity_scope.
Quantity addition using the unit of the right operand q1
Definition qaddr (q1 q2 : Quantity) : Quantity := qop2r ARmul Aadd q1 q2.
Infix "+'" := qaddr : Quantity_scope.
Infix "+'" := qaddr : Quantity_scope.
Quantity opposition
Definition qopp (q : Quantity) : Quantity := qop1 Aopp q.
Notation "- q" := (qopp q) : Quantity_scope.
Notation "- q" := (qopp q) : Quantity_scope.
Quantity subtraction using same unit
Quantity subtraction using the unit of the left operand q1
Quantity subtraction using the unit of the right operand q1
Definition qsubr (q1 q2 : Quantity) : Quantity := q1 +' - q2.
Infix "-'" := qsubr : Quantity_scope.
Context `{HASGroup : ASGroup _ Aadd}.
Infix "-'" := qsubr : Quantity_scope.
Context `{HASGroup : ASGroup _ Aadd}.
qadd is associative.
Lemma qadd_assoc (q1 q2 q3 : Quantity) : (q1 + q2) + q3 = q1 + (q2 + q3).
Proof.
unfold qadd, qop2.
destruct q1 as [v1 n1|], q2 as [v2 n2|], q3 as [v3 n3|]; try easy.
- bdestruct (neqb n1 n2); subst; auto.
+ bdestruct (neqb n2 n3); subst; auto. rewrite neqb_refl. f_equal. asgroup.
+ bdestruct (neqb n2 n3); subst; auto. apply neqb_false_iff in H.
rewrite H. auto.
- bdestruct (neqb n1 n2); subst; auto.
Qed.
Proof.
unfold qadd, qop2.
destruct q1 as [v1 n1|], q2 as [v2 n2|], q3 as [v3 n3|]; try easy.
- bdestruct (neqb n1 n2); subst; auto.
+ bdestruct (neqb n2 n3); subst; auto. rewrite neqb_refl. f_equal. asgroup.
+ bdestruct (neqb n2 n3); subst; auto. apply neqb_false_iff in H.
rewrite H. auto.
- bdestruct (neqb n1 n2); subst; auto.
Qed.
qadd is commutative.
Lemma qadd_comm (q1 q2 : Quantity) : q1 + q2 = q2 + q1.
Proof.
unfold qadd, qop2. destruct q1 as [v1 n1|], q2 as [v2 n2|]; try easy.
rewrite neqb_comm. bdestruct (neqb n2 n1); subst; auto. f_equal. asgroup.
Qed.
Proof.
unfold qadd, qop2. destruct q1 as [v1 n1|], q2 as [v2 n2|]; try easy.
rewrite neqb_comm. bdestruct (neqb n2 n1); subst; auto. f_equal. asgroup.
Qed.
qadd left with !! equal to !!.
qadd right with !! equal to !!.
Lemma qadd_qinvalid_r (q : Quantity) : q + !! = !!.
Proof. rewrite qadd_comm. auto. Qed.
Context `{HGroup : Group _ Aadd Azero Aopp}.
End qadd_qopp_qsub.
Proof. rewrite qadd_comm. auto. Qed.
Context `{HGroup : Group _ Aadd Azero Aopp}.
End qadd_qopp_qsub.
Quantity inversion
Quantity inversion
Definition qinv (q : Quantity) : Quantity :=
match q with
| Qmake v n => Qmake (Ainv v) (ninv n)
| _ => !!
end.
Notation "/ q" := (qinv q) : Quantity_scope.
End qinv.
match q with
| Qmake v n => Qmake (Ainv v) (ninv n)
| _ => !!
end.
Notation "/ q" := (qinv q) : Quantity_scope.
End qinv.
multiplication or division of two quantities that may have different units.
For example, scalar multiplication of vectors or matrices
Section qmul_qdiv.
Context {tA tB} (AmulB : tA -> tB -> tB) (Binv : tB -> tB).
Infix "*" := AmulB : A_scope.
Notation qinv := (qinv Binv).
Context {tA tB} (AmulB : tA -> tB -> tB) (Binv : tB -> tB).
Infix "*" := AmulB : A_scope.
Notation qinv := (qinv Binv).
Quantity multiplication
Definition qmul (q1 : @Quantity tA) (q2 : @Quantity tB) : @Quantity tB :=
match q1,q2 with
| Qmake v1 n1, Qmake v2 n2 => Qmake (v1 * v2)%A (nmul n1 n2)
| _, _ => !!
end.
Infix "*" := qmul : Quantity_scope.
match q1,q2 with
| Qmake v1 n1, Qmake v2 n2 => Qmake (v1 * v2)%A (nmul n1 n2)
| _, _ => !!
end.
Infix "*" := qmul : Quantity_scope.
Power of quantity with an integer numbers
Section qpow.
Context (ApowerZ : tA -> Z -> tA).
Definition qpow (q : @Quantity tA) (z : Z) : @Quantity tA :=
match q with
| Qmake v n => Qmake (ApowerZ v z) (npow n z)
| !! => !!
end.
Notation "q ^ n" := (qpow q n) : Quantity_scope.
Notation " q ² " := (q ^ 2) : Quantity_scope.
Notation " q ³ " := (q ^ 3) : Quantity_scope.
Notation " q ⁴ " := (q ^ 4) : Quantity_scope.
Notation " q ⁵ " := (q ^ 5) : Quantity_scope.
End qpow.
Context (ApowerZ : tA -> Z -> tA).
Definition qpow (q : @Quantity tA) (z : Z) : @Quantity tA :=
match q with
| Qmake v n => Qmake (ApowerZ v z) (npow n z)
| !! => !!
end.
Notation "q ^ n" := (qpow q n) : Quantity_scope.
Notation " q ² " := (q ^ 2) : Quantity_scope.
Notation " q ³ " := (q ^ 3) : Quantity_scope.
Notation " q ⁴ " := (q ^ 4) : Quantity_scope.
Notation " q ⁵ " := (q ^ 5) : Quantity_scope.
End qpow.
Quantity division
Definition qdiv (q1 : @Quantity tA) (q2 : @Quantity tB) : @Quantity tB :=
qmul q1 (qinv q2).
Infix "/" := qdiv : Quantity_scope.
qmul q1 (qinv q2).
Infix "/" := qdiv : Quantity_scope.
qmul left cancellation law
Lemma qmul_cancel_l q1 q2 q3 : q1 * q2 = q1 * q3 -> q2 = q3.
Proof.
intros. unfold qmul in *. destruct q1,q2,q3. inv H.
Abort.
Proof.
intros. unfold qmul in *. destruct q1,q2,q3. inv H.
Abort.
qmul right cancellation law
Properties for qmul with specific element types
Section qmul_specific.
Context `{HASGroup : ASGroup tA Amul}.
Notation qmul := (qmul Amul).
Infix "*" := qmul : Quantity_scope.
Context `{HASGroup : ASGroup tA Amul}.
Notation qmul := (qmul Amul).
Infix "*" := qmul : Quantity_scope.
qmul is associative
Lemma qmul_assoc (q1 q2 q3 : Quantity) : (q1 * q2) * q3 = q1 * (q2 * q3).
Proof.
unfold qmul. destruct q1 as [v1 n1|], q2 as [v2 n2|], q3 as [v3 n3|]; try easy.
f_equal. asgroup. apply nmul_assoc.
Qed.
Proof.
unfold qmul. destruct q1 as [v1 n1|], q2 as [v2 n2|], q3 as [v3 n3|]; try easy.
f_equal. asgroup. apply nmul_assoc.
Qed.
qmul is commutative
Lemma qmul_comm (q1 q2 : Quantity) : q1 * q2 = q2 * q1.
Proof.
unfold qmul. destruct q1 as [v1 n1|], q2 as [v2 n2|]; try easy.
f_equal. asgroup. apply nmul_comm.
Qed.
Context `{HAMonoid : AMonoid tA Amul Aone}.
Notation qone := (qone Aone).
Proof.
unfold qmul. destruct q1 as [v1 n1|], q2 as [v2 n2|]; try easy.
f_equal. asgroup. apply nmul_comm.
Qed.
Context `{HAMonoid : AMonoid tA Amul Aone}.
Notation qone := (qone Aone).
qone is the left identity for multiplication
Lemma qmul_1_l q : qone * q = q.
Proof.
unfold qmul. unfold qone. destruct q as [v n|]; auto.
f_equal. amonoid. apply nmul_1_l.
Qed.
Lemma qmul_1_r q : q * qone = q.
Proof. rewrite qmul_comm. apply qmul_1_l. Qed.
Instance qmul_Monoid : Monoid qmul qone.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Qed.
Instance qmul_AMonoid : AMonoid qmul qone.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Qed.
Context `{HAGroup : AGroup tA Amul Aone Ainv}.
Notation qinv := (qinv Ainv).
Lemma qmul_qinv_l : forall q, q <> !! -> qcoef q <> Some 0 -> qinv q * q = qone.
Proof.
intros. unfold qmul, qinv, qone. destruct q as [v n|]; auto; try easy.
f_equal. apply HAGroup.
apply nmul_ninv_l. cbv in H0. destruct n. simpl. intro. destruct H0.
rewrite H1. auto.
Qed.
Instance qmul_Group : Group qmul qone qinv.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Abort.
End qmul_specific.
Proof.
unfold qmul. unfold qone. destruct q as [v n|]; auto.
f_equal. amonoid. apply nmul_1_l.
Qed.
Lemma qmul_1_r q : q * qone = q.
Proof. rewrite qmul_comm. apply qmul_1_l. Qed.
Instance qmul_Monoid : Monoid qmul qone.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Qed.
Instance qmul_AMonoid : AMonoid qmul qone.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Qed.
Context `{HAGroup : AGroup tA Amul Aone Ainv}.
Notation qinv := (qinv Ainv).
Lemma qmul_qinv_l : forall q, q <> !! -> qcoef q <> Some 0 -> qinv q * q = qone.
Proof.
intros. unfold qmul, qinv, qone. destruct q as [v n|]; auto; try easy.
f_equal. apply HAGroup.
apply nmul_ninv_l. cbv in H0. destruct n. simpl. intro. destruct H0.
rewrite H1. auto.
Qed.
Instance qmul_Group : Group qmul qone qinv.
Proof.
repeat constructor.
all: try apply qmul_assoc; try apply qmul_1_l; try apply qmul_1_r;
try apply qmul_comm.
Abort.
End qmul_specific.