-
Notifications
You must be signed in to change notification settings - Fork 1
/
PolFBase.v
293 lines (254 loc) · 7.99 KB
/
PolFBase.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
Require Import PolSBase.
Section PolFactorSimpl.
(* The set of the coefficient usually Z or better Q *)
Variable C : Set.
(* Usual operations *)
Variable Cplus : C -> C -> C.
Variable Cmul : C -> C -> C.
Variable Cop : C -> C.
(* Constant *)
Variable C0 : C.
Variable C1 : C.
(* Test to 1 *)
Variable isC1 : C -> bool.
(* Test to 0 *)
Variable isC0 : C -> bool.
(* Test if positive *)
Variable isPos : C -> bool.
(* Divisibility *)
Variable Cdivide : C -> C -> bool.
(* Division *)
Variable Cdiv : C -> C -> C.
(* Gcd *)
Variable Cgcd: C -> C -> C.
(* Test if the difference of two terms is zero *)
Definition is_eq (x y : PExpr C) : bool :=
let r := simpl C Cplus Cmul Cop C0 C1 isC1 isC0 isPos Cdivide Cdiv (PEsub x y) in
match r with
| PEc c => isC0 c
| _ => false
end.
(* Test if the sum of two term is zero *)
Definition is_op (x y : PExpr C) : bool :=
let r := simpl C Cplus Cmul Cop C0 C1 isC1 isC0 isPos Cdivide Cdiv (PEadd x y) in
match r with
| PEc c => isC0 c
| _ => false
end.
Definition test_in (x y : PExpr C) : bool :=
match x, y with
| PEc c1, PEc c2 => if (isC1 (Cgcd c1 c2)) then false else true
| _ , _ => match (is_eq x y) with true => true | false => is_op x y end
end.
(* Return the first factor of a sum *)
Fixpoint first_factor (e : PExpr C) : PExpr C :=
match e with
| PEadd e1 _ => first_factor e1
| PEsub e1 _ => first_factor e1
| PEopp e1 => first_factor e1
| _ => e
end.
(* Split a product in list of products *)
Fixpoint split_factor (e : PExpr C) : list (PExpr C) :=
match e with
| PEmul e1 e2 => split_factor e1 ++ split_factor e2
| PEopp e1 => match split_factor e1 with _::nil => e::nil | l1 => l1 end
| _ => e::nil
end.
(* Split a product in list of products *)
Fixpoint split_factors (e : PExpr C) : list (list (PExpr C)) :=
match e with
| PEadd e1 e2 => split_factors e1 ++ split_factors e2
| PEsub e1 e2 => split_factors e1 ++ split_factors e2
| PEopp e1 =>
match split_factors e1 with (_::nil)::nil => (e::nil)::nil | l1 => l1 end
| _ => split_factor e::nil
end.
(* Application on an optional type *)
Definition oapp (A B : Set) (a : A) (f : A -> B -> B) (l : option B) :=
match l with Some l1 => Some (f a l1) | _ => None end.
Let ocons := fun x => oapp _ _ x (@cons (PExpr C)).
(* Remove an element in a list *)
Fixpoint remove_elem (e: PExpr C) (l: list (PExpr C)) {struct l}
: option (list (PExpr C)) :=
match l with
| nil => None
| cons e1 l1 => if (test_in e e1) then Some l1 else (ocons e1 (remove_elem e l1))
end.
Let oconst (A : Set) (x : PExpr C) :=
oapp _ _ x (fun x (y : A * list (PExpr C)) =>
let (v1,l1) := y in (v1, x::l1)).
(* Remove a constant in a list *)
Fixpoint remove_constant (c : C) (l : list (PExpr C)) {struct l}
: option (C * list (PExpr C)) :=
match l with
| nil => None
| cons (PEc c1) l1 =>
if isC1 (Cgcd c c1)
then oconst _ (PEc c1) (remove_constant c l1)
else Some (Cgcd c c1, cons (PEc (Cdiv c (Cgcd c c1))) l1)
| cons c1 l1 => oconst _ c1 (remove_constant c l1)
end.
(* Strip the element that are not in the list *)
Fixpoint strip (l1 l2: list (PExpr C)) {struct l1} : list (PExpr C) :=
match l1 with
| nil => nil
| cons (PEc c) l3 =>
match remove_constant c l2 with
| None => strip l3 l2
| Some (c1, l4) => cons (PEc c1) (strip l3 l4)
end
| cons e l3 =>
match remove_elem e l2 with
| None => strip l3 l2
| Some l4 => cons e (strip l3 l4)
end
end.
(* iter strip for all the element l2 *)
Fixpoint delta (l1: list (PExpr C)) (l2: list (list (PExpr C))) {struct l2}
: list (PExpr C) :=
match l2 with
| nil => l1
| cons l l4 =>
match strip l1 l with
| nil => nil
| l3 => delta l3 l4
end
end.
Let mkMul := mkPEmul C Cmul Cop C0 isC1 isC0.
Let mkOpp := mkPEopp C Cop.
Let mkAdd := mkPEadd C Cplus Cmul Cop C0 isC1 isC0 isPos.
Let mkSub := mkPEsub C Cplus Cmul Cop C0 isC1 isC0 isPos.
(* Remove an element in a list *)
Fixpoint subst_elem (e: PExpr C) (l: list (PExpr C)) {struct l}
: option (bool * list (PExpr C)) :=
match l with
| nil => None
| cons e1 l1 =>
if is_eq e e1 then Some (true, l1) else
if is_op e e1 then Some (false, l1) else
(oconst _ e1 (subst_elem e l1))
end.
(* Remove a constant in a list *)
Fixpoint subst_constant (c : C) (l : list (PExpr C)) {struct l}
: option (C * list (PExpr C)) :=
match l with
| nil => None
| cons (PEc c1) l1 =>
if (Cdivide c1 c)
then Some (Cdiv c c1, l1)
else oconst _ (PEc c1) (subst_constant c l1)
| cons e1 l1 => oconst _ e1 (subst_constant c l1)
end.
(* Split a product in list of products *)
Fixpoint subst_one_factor (e: PExpr C) (l: list (PExpr C)) {struct e}
: PExpr C * list (PExpr C) :=
match e with
| PEmul e1 e2 =>
let (e3, l1) := subst_one_factor e1 l in
let (e4, l2) := subst_one_factor e2 l1 in
(mkMul e3 e4, l2)
| PEopp e1 =>
let (e3, l1) := subst_one_factor e1 l in
(mkOpp e3, l1)
| PEc c =>
match subst_constant c l with
| None => (e, l)
| Some (c1, l1) => (PEc c1, l1)
end
| _ =>
match subst_elem e l with
| None => (e, l)
| Some (true, l1) => (PEc C1, l1)
| Some (false, l1) => (PEc (Cop C1), l1)
end
end.
(* Return the first factor of a sum *)
Fixpoint subst_factor (l: list (PExpr C)) (e: PExpr C) {struct e} : PExpr C :=
match e with
| PEadd e1 e2 => mkAdd (subst_factor l e1) (subst_factor l e2)
| PEsub e1 e2=> mkSub (subst_factor l e1) (subst_factor l e2)
| PEopp e1 => mkOpp (subst_factor l e1)
| _ => fst (subst_one_factor e l)
end.
Definition get_delta (e : PExpr C) : list (PExpr C) :=
match split_factors e with
| l1::l => delta l1 l
| _ => nil
end.
Fixpoint mkProd (l : list (PExpr C)) {struct l} : (PExpr C) :=
match l with
| nil => PEc C1
| e::nil => e
| e::l1 => mkMul e (mkProd l1)
end.
Fixpoint find_trivial_factor (e : PExpr C) (l : list (list (PExpr C))) {struct l}
: PExpr C :=
match l with
| l1::ll2 =>
let e1 := mkProd l1 in
let e2 :=
simpl C Cplus Cmul Cop C0 C1 isC1 isC0 isPos Cdivide Cdiv (mkSub e e1)
in
match subst_elem e2 l1 with
| None => find_trivial_factor e ll2
| Some (true, l2) => PEmul e2 (mkAdd (mkProd l2) (PEc C1))
| Some (false, l2) => PEmul e2 (mkSub (PEc C1) (mkProd l2))
end
| _ => PEmul (PEc C1) e
end.
Definition isPC1 x := match x with (PEc c) => (isC1 c) | _ => false end.
Definition isPC0 x := match x with (PEc c) => (isC0 c) | _ => false end.
Fixpoint factor (e: PExpr C) : PExpr C :=
let e1 :=
match e with
| PEmul e1 e2 => PEmul (factor e1) (factor e2)
| PEadd e1 e2 => PEadd (factor e1) (factor e2)
| PEsub e1 e2 => PEsub (factor e1) (factor e2)
| PEopp e1 => PEopp (factor e1)
| _ => e end
in
let e2 := get_delta e1 in
if (isPC1 (mkProd e2)) then
find_trivial_factor e1 (split_factors e1)
else
PEmul (mkProd e2) (subst_factor e2 e1).
Definition factor_sub f :=
let e :=
match f with
| PEmul e1 e2 => PEmul (factor e1) (factor e2)
| PEadd e1 e2 => PEadd (factor e1) (factor e2)
| PEsub e1 e2 => PEsub (factor e1) (factor e2)
| PEopp e1 => PEopp (factor e1)
| _ => f end
in
match e with
| PEsub e1 e2 =>
if (isPC0 e1) then
let d1 := (get_delta e2) in
PEmul (mkProd d1) (PEsub (PEc C0) (subst_factor d1 e2))
else
if (isPC0 e2) then
let d1 := (get_delta e1) in
PEmul (mkProd d1) (PEsub (subst_factor d1 e2) (PEc C0))
else
let d := get_delta e in
PEmul (mkProd d) (PEsub (subst_factor d e1) (subst_factor d e2))
| _ =>
let d := get_delta e in
PEmul (mkProd d) (subst_factor d e)
end.
Definition factor_sub_val e d1 :=
let d2 := split_factor d1 in
match e with
| PEsub e1 e2 =>
if (isPC0 e1) then
PEmul d1 (PEsub (PEc C0) (subst_factor d2 e2))
else
if (isPC0 e2) then
PEmul d1 (PEsub (subst_factor d2 e2) (PEc C0))
else
PEmul d1 (PEsub (subst_factor d2 e1) (subst_factor d2 e2))
| _ => (PEmul d1 (subst_factor d2 e))
end.
End PolFactorSimpl.