bedrock.lang.bi.split_frac
(*
* Copyright (c) 2022 BedRock Systems, Inc.
*
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
Require Export bedrock.lang.bi.fractional.
Require Import bedrock.prelude.numbers.
* Copyright (c) 2022 BedRock Systems, Inc.
*
* This software is distributed under the terms of the BedRock Open-Source License.
* See the LICENSE-BedRock file in the repository root for details.
*)
Require Export bedrock.lang.bi.fractional.
Require Import bedrock.prelude.numbers.
Splitting and combining fractions
- QpTC.Add, QpTC.Mul, QpTC.Div normalizing operations on
- SplitFrac, CombineFrac split and combine Qp expressions built
for emphasis---it's already opaque
Note: Some of the following instances overlap. We keep them to
shorten proof terms, using Cut to avoid backtracking.
Add q1 q2 q sets q := q1 + q2 with simplifications.
Class Add (q1 q2 q : Qp) : Prop := add : q1 + q2 = q.
#[global] Hint Mode Add + + - : typeclass_instances.
#[global] Arguments Add : simpl never.
#[global] Arguments add _ _ {_ _} : assert.
Notation ADD q1 q2 q := (Cut (Add q1 q2 q)) (only parsing).
#[global] Hint Mode Add + + - : typeclass_instances.
#[global] Arguments Add : simpl never.
#[global] Arguments add _ _ {_ _} : assert.
Notation ADD q1 q2 q := (Cut (Add q1 q2 q)) (only parsing).
Class Mul (q1 q2 q : Qp) : Prop := mul : q1 * q2 = q.
#[global] Hint Mode Mul + + - : typeclass_instances.
#[global] Arguments Mul : simpl never.
#[global] Arguments mul _ _ {_ _} : assert.
Notation MUL q1 q2 q := (Cut (Mul q1 q2 q)) (only parsing).
#[global] Hint Mode Mul + + - : typeclass_instances.
#[global] Arguments Mul : simpl never.
#[global] Arguments mul _ _ {_ _} : assert.
Notation MUL q1 q2 q := (Cut (Mul q1 q2 q)) (only parsing).
Class Div (q1 q2 q : Qp) : Prop := div : q1 / q2 = q.
#[global] Hint Mode Div + + - : typeclass_instances.
#[global] Arguments Div : simpl never.
#[global] Arguments div _ _ {_ _} : assert.
Notation DIV q1 q2 q := (Cut (Div q1 q2 q)) (only parsing).
#[global] Hint Mode Div + + - : typeclass_instances.
#[global] Arguments Div : simpl never.
#[global] Arguments div _ _ {_ _} : assert.
Notation DIV q1 q2 q := (Cut (Div q1 q2 q)) (only parsing).
Add
#[global] Instance add_half_half : Add (1/2) (1/2) 1 | 10.
Proof. apply Qp.half_half. Qed.
#[global] Instance add_div_2 q : Add (q/2) (q/2) q | 12.
Proof. apply Qp.div_2. Qed.
#[global] Instance add_div_4 q : Add (q/4) (q/4) (q/2) | 10.
Proof. apply Qp.div_4. Qed.
#[global] Instance add_quarter_three_quarter : Add (1/4) (3/4) 1 | 10.
Proof. apply Qp.quarter_three_quarter. Qed.
#[global] Instance add_three_quarter_quarter : Add (3/4) (1/4) 1 | 10.
Proof. apply Qp.three_quarter_quarter. Qed.
#[global] Instance add_third_two_thirds : Add (1/3) (2/3) 1 | 10.
Proof. apply Qp.third_two_thirds. Qed.
#[global] Instance add_two_thirds_third : Add (2/3) (1/3) 1 | 10.
Proof. apply Qp.two_thirds_third. Qed.
#[global] Instance add_1_1 : Add 1 1 2 | 10.
Proof. apply Qp.add_1_1. Qed.
#[global] Instance add_div_2_mul_ll q p qp :
DIV q p qp -> Add (q / (2 * p)) (q / (2 * p)) qp | 20.
Proof. rewrite /Div/Add=>-[]<-. apply Qp.div_2_mul. Qed.
#[global] Instance add_div_2_mul_rr q p qp :
DIV q p qp -> Add (q / (p * 2)) (q / (p * 2)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
#[global] Instance add_div_2_mul_lr q p qp :
DIV q p qp -> Add (q / (2 * p)) (q / (p * 2)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
#[global] Instance add_div_2_mul_rl q p qp :
DIV q p qp -> Add (q / (p * 2)) (q / (2 * p)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
DIV q p qp -> Add (q / (2 * p)) (q / (2 * p)) qp | 20.
Proof. rewrite /Div/Add=>-[]<-. apply Qp.div_2_mul. Qed.
#[global] Instance add_div_2_mul_rr q p qp :
DIV q p qp -> Add (q / (p * 2)) (q / (p * 2)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
#[global] Instance add_div_2_mul_lr q p qp :
DIV q p qp -> Add (q / (2 * p)) (q / (p * 2)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
#[global] Instance add_div_2_mul_rl q p qp :
DIV q p qp -> Add (q / (p * 2)) (q / (2 * p)) qp | 20.
Proof. rewrite [p*2]comm_L. apply _. Qed.
q + q = 2*q
#[global] Instance add_diag q p : MUL 2 q p -> Add q q p | 21.
Proof. rewrite /Mul=>-[]<-. apply Qp.add_diag. Qed.
Proof. rewrite /Mul=>-[]<-. apply Qp.add_diag. Qed.
#[global] Instance add_mul_l q1 q2 q p pq :
ADD q1 q2 q -> MUL p q pq -> Add (p * q1) (p * q2) pq | 22.
Proof. rewrite /Add/Mul=>-[]<-[]<-. by rewrite Qp.mul_add_distr_l. Qed.
#[global] Instance add_mul_r q1 q2 q p qp :
ADD q1 q2 q -> MUL q p qp -> Add (q1 * p) (q2 * p) qp | 22.
Proof. rewrite /Add/Mul=>-[]<-[]<-. by rewrite Qp.mul_add_distr_r. Qed.
ADD q1 q2 q -> MUL p q pq -> Add (p * q1) (p * q2) pq | 22.
Proof. rewrite /Add/Mul=>-[]<-[]<-. by rewrite Qp.mul_add_distr_l. Qed.
#[global] Instance add_mul_r q1 q2 q p qp :
ADD q1 q2 q -> MUL q p qp -> Add (q1 * p) (q2 * p) qp | 22.
Proof. rewrite /Add/Mul=>-[]<-[]<-. by rewrite Qp.mul_add_distr_r. Qed.
#[global] Instance add_div q1 q2 q p qp :
ADD q1 q2 q -> DIV q p qp -> Add (q1 / p) (q2 / p) qp | 25.
Proof. rewrite /Add/Div=>-[]<-[]<-. by rewrite Qp.div_add_distr. Qed.
#[global] Instance add_xx q1 q2 : Add q1 q2 (q1 + q2) | 50.
Proof. done. Qed.
ADD q1 q2 q -> DIV q p qp -> Add (q1 / p) (q2 / p) qp | 25.
Proof. rewrite /Add/Div=>-[]<-[]<-. by rewrite Qp.div_add_distr. Qed.
#[global] Instance add_xx q1 q2 : Add q1 q2 (q1 + q2) | 50.
Proof. done. Qed.
#[global] Instance mul_22 : Mul 2 2 4 | 10.
Proof. apply Qp.mul_2_2. Qed.
#[global] Instance mul_1x q : Mul 1 q q | 10.
Proof. rewrite /Mul. by rewrite left_id_L. Qed.
#[global] Instance mul_x1 q : Mul q 1 q | 10.
Proof. rewrite /Mul. by rewrite right_id_L. Qed.
#[global] Instance mul_div_r q p : Mul q (p/q) p | 10.
Proof. apply Qp.mul_div_r. Qed.
#[global] Instance mul_div_l q p : Mul (q/p) p q | 10.
Proof. apply Qp.mul_div_l. Qed.
#[global] Instance mul_xx q1 q2 : Mul q1 q2 (q1 * q2) | 50.
Proof. done. Qed.
#[global] Instance div_1 q : Div q 1 q | 10.
Proof. rewrite /Div. by rewrite right_id_L. Qed.
#[global] Instance div_1_2 : Div 1 2 (1/2) | 10.
Proof. done. Qed.
#[global] Instance div_half_2 : Div (1/2) 2 (1/4) | 10.
Proof. rewrite /Div. by rewrite Qp.div_div Qp.mul_2_2. Qed.
#[global] Instance div_1_4 : Div 1 4 (1/4) | 10.
Proof. done. Qed.
#[global] Instance div_mul_cancel_l p q r pq :
DIV p q pq -> Div (r * p) (r * q) pq | 20.
Proof.
intros [?]. rewrite /Div. by rewrite Qp.div_mul_cancel_l div.
Qed.
DIV p q pq -> Div (r * p) (r * q) pq | 20.
Proof.
intros [?]. rewrite /Div. by rewrite Qp.div_mul_cancel_l div.
Qed.
#[global] Instance div_mul_cancel_r p q r pq :
DIV p q pq -> Div (p*r) (q*r) pq | 20.
Proof.
intros [?]. rewrite /Div. by rewrite Qp.div_mul_cancel_r div.
Qed.
DIV p q pq -> Div (p*r) (q*r) pq | 20.
Proof.
intros [?]. rewrite /Div. by rewrite Qp.div_mul_cancel_r div.
Qed.
#[global] Instance div_div p q r qr pqr :
MUL q r qr -> DIV p qr pqr -> Div (p/q) r pqr | 20.
Proof.
intros [?] [?]. rewrite /Div. by rewrite Qp.div_div mul div.
Qed.
#[global] Instance div_xx q1 q2 : Div q1 q2 (q1 / q2) | 50.
Proof. done. Qed.
End QpTC.
MUL q r qr -> DIV p qr pqr -> Div (p/q) r pqr | 20.
Proof.
intros [?] [?]. rewrite /Div. by rewrite Qp.div_div mul div.
Qed.
#[global] Instance div_xx q1 q2 : Div q1 q2 (q1 / q2) | 50.
Proof. done. Qed.
End QpTC.
Splitting fractions
Class SplitFrac (q q1 q2 : Qp) : Prop := split_frac : q = (q1 + q2)%Qp.
#[global] Hint Mode SplitFrac + - - : typeclass_instances.
#[global] Arguments SplitFrac : simpl never.
#[global] Arguments split_frac _ {_ _ _} : assert.
Module split_frac.
#[local] Open Scope Qp_scope.
#[global] Hint Mode SplitFrac + - - : typeclass_instances.
#[global] Arguments SplitFrac : simpl never.
#[global] Arguments split_frac _ {_ _ _} : assert.
Module split_frac.
#[local] Open Scope Qp_scope.
OnAdd hunts for a + in the given term to split on, simplifying
the results. Unlike SplitFrac, this judgment fails rather than
divide by two.
Class OnAdd (q q1 q2 : Qp) : Prop := on_add : q = (q1 + q2)%Qp.
#[global] Hint Mode OnAdd + - - : typeclass_instances.
#[global] Arguments OnAdd : simpl never.
#[global] Arguments on_add _ {_ _ _} : assert.
Notation ON_ADD q q1 q2 := (Cut (OnAdd q q1 q2)) (only parsing).
#[global] Hint Mode OnAdd + - - : typeclass_instances.
#[global] Arguments OnAdd : simpl never.
#[global] Arguments on_add _ {_ _ _} : assert.
Notation ON_ADD q q1 q2 := (Cut (OnAdd q q1 q2)) (only parsing).
Splitting on + and 2*q are the base cases.
2*q = q + q
#[global] Instance on_add_2x q : OnAdd (2 * q) q q | 10.
Proof. rewrite /OnAdd. by rewrite Qp.add_diag. Qed.
#[global] Instance on_add_x2 q : OnAdd (q * 2) q q | 10.
Proof. rewrite comm_L. apply _. Qed.
Proof. rewrite /OnAdd. by rewrite Qp.add_diag. Qed.
#[global] Instance on_add_x2 q : OnAdd (q * 2) q q | 10.
Proof. rewrite comm_L. apply _. Qed.
4*q = 2*q + 2*q
#[global] Instance on_add_4x q : OnAdd (4 * q) (2 * q) (2 * q) | 10.
Proof. rewrite -Qp.mul_2_2 -assoc_L. apply _. Qed.
#[global] Instance on_add_x4 q : OnAdd (q * 4) (q * 2) (q * 2) | 10.
Proof. rewrite [q*4]comm_L [q*2]comm_L. apply _. Qed.
Proof. rewrite -Qp.mul_2_2 -assoc_L. apply _. Qed.
#[global] Instance on_add_x4 q : OnAdd (q * 4) (q * 2) (q * 2) | 10.
Proof. rewrite [q*4]comm_L [q*2]comm_L. apply _. Qed.
To split on + in p * q, attempt to split on + in p. If that
fails, attempt to split on + in q. If that fails, the split in
p * q fails.
(q1 + q2)*p --> q1*p + q2*p
#[global] Instance on_add_mul_r p q q1 q2 q1p q2p :
ON_ADD q q1 q2 -> QpTC.MUL q1 p q1p -> QpTC.MUL q2 p q2p ->
OnAdd (q * p) q1p q2p | 20.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.mul_add_distr_r !QpTC.mul.
Qed.
ON_ADD q q1 q2 -> QpTC.MUL q1 p q1p -> QpTC.MUL q2 p q2p ->
OnAdd (q * p) q1p q2p | 20.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.mul_add_distr_r !QpTC.mul.
Qed.
#[global] Instance on_add_mul_l p q q1 q2 pq1 pq2 :
ON_ADD q q1 q2 -> QpTC.MUL p q1 pq1 -> QpTC.MUL p q2 pq2 ->
OnAdd (p * q) pq1 pq2 | 21.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.mul_add_distr_l !QpTC.mul.
Qed.
ON_ADD q q1 q2 -> QpTC.MUL p q1 pq1 -> QpTC.MUL p q2 pq2 ->
OnAdd (p * q) pq1 pq2 | 21.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.mul_add_distr_l !QpTC.mul.
Qed.
To split on + in p / q, attempt to split on + in p. If that
fails, the in p / q fails.
(q1+q2)/p --> q1/p + q2/p
#[global] Instance on_add_div p q q1 q2 q1p q2p :
ON_ADD q q1 q2 -> QpTC.DIV q1 p q1p -> QpTC.DIV q2 p q2p ->
OnAdd (q / p) q1p q2p | 20.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.div_add_distr !QpTC.div.
Qed.
ON_ADD q q1 q2 -> QpTC.DIV q1 p q1p -> QpTC.DIV q2 p q2p ->
OnAdd (q / p) q1p q2p | 20.
Proof.
intros [?] [?] [?]. rewrite /OnAdd.
by rewrite (on_add q) Qp.div_add_distr !QpTC.div.
Qed.
Class Split (q q1 q2 : Qp) : Prop := split : q = (q1 + q2)%Qp.
#[global] Hint Mode Split + - - : typeclass_instances.
#[global] Arguments Split : simpl never.
#[global] Arguments split _ {_ _ _} : assert.
Notation SPLIT q q1 q2 := (Cut (Split q q1 q2)) (only parsing).
#[global] Instance split_structural q q1 q2 :
ON_ADD q q1 q2 -> Split q q1 q2 | 10.
Proof. by case. Qed.
#[global] Instance split_div_2 q qout :
QpTC.DIV q 2 qout -> Split q qout qout | 50.
Proof.
intros [?]. rewrite /Split. rewrite -(Qp.div_2 q). by f_equal.
Qed.
Goal forall q, Split q (q/2) (q/2).
Proof. apply _. Abort.
Goal forall q, Split (q/2) (q/4) (q/4).
Proof. apply _. Abort.
End split_frac.
#[global] Instance split_frac_split q q1 q2 :
split_frac.SPLIT q q1 q2 -> SplitFrac q q1 q2 | 10.
Proof. by case. Qed.
#[global] Hint Mode Split + - - : typeclass_instances.
#[global] Arguments Split : simpl never.
#[global] Arguments split _ {_ _ _} : assert.
Notation SPLIT q q1 q2 := (Cut (Split q q1 q2)) (only parsing).
#[global] Instance split_structural q q1 q2 :
ON_ADD q q1 q2 -> Split q q1 q2 | 10.
Proof. by case. Qed.
#[global] Instance split_div_2 q qout :
QpTC.DIV q 2 qout -> Split q qout qout | 50.
Proof.
intros [?]. rewrite /Split. rewrite -(Qp.div_2 q). by f_equal.
Qed.
Goal forall q, Split q (q/2) (q/2).
Proof. apply _. Abort.
Goal forall q, Split (q/2) (q/4) (q/4).
Proof. apply _. Abort.
End split_frac.
#[global] Instance split_frac_split q q1 q2 :
split_frac.SPLIT q q1 q2 -> SplitFrac q q1 q2 | 10.
Proof. by case. Qed.
Combining fractions
Class CombineFrac (q1 q2 q : Qp) : Prop := combine_frac : (q1 + q2)%Qp = q.
#[global] Hint Mode CombineFrac + + - : typeclass_instances.
#[global] Arguments CombineFrac : simpl never.
#[global] Arguments combine_frac _ _ {_ _} : assert.
#[global] Instance combine_frac_add q1 q2 q :
QpTC.ADD q1 q2 q -> CombineFrac q1 q2 q | 10.
Proof. by case. Qed.
#[global] Hint Mode CombineFrac + + - : typeclass_instances.
#[global] Arguments CombineFrac : simpl never.
#[global] Arguments combine_frac _ _ {_ _} : assert.
#[global] Instance combine_frac_add q1 q2 q :
QpTC.ADD q1 q2 q -> CombineFrac q1 q2 q | 10.
Proof. by case. Qed.