]> matita.cs.unibo.it Git - helm.git/blob - helm/gTopLevel/fourier.ml
Initial revision
[helm.git] / helm / gTopLevel / fourier.ml
1 (***********************************************************************)
2 (*  v      *   The Coq Proof Assistant  /  The Coq Development Team    *)
3 (* <O___,, *        INRIA-Rocquencourt  &  LRI-CNRS-Orsay              *)
4 (*   \VV/  *************************************************************)
5 (*    //   *      This file is distributed under the terms of the      *)
6 (*         *       GNU Lesser General Public License Version 2.1       *)
7 (***********************************************************************)
8
9 (* $Id$ *)
10
11 (* Méthode d'élimination de Fourier *)
12 (* Référence:
13 Auteur(s) : Fourier, Jean-Baptiste-Joseph
14  
15 Titre(s) : Oeuvres de Fourier [Document électronique]. Tome second. Mémoires publiés dans divers recueils / publ. par les soins de M. Gaston Darboux,...
16  
17 Publication : Numérisation BnF de l'édition de Paris : Gauthier-Villars, 1890
18  
19 Pages: 326-327
20
21 http://gallica.bnf.fr/
22 *)
23
24
25
26
27 (* Un peu de calcul sur les rationnels... 
28 Les opérations rendent des rationnels normalisés,
29 i.e. le numérateur et le dénominateur sont premiers entre eux.
30 *)
31
32
33
34 type rational = {num:int;
35                  den:int}
36 ;;
37 let print_rational x =
38         print_int x.num;
39         print_string "/";
40         print_int x.den
41 ;;
42
43 let rec pgcd x y = if y = 0 then x else pgcd y (x mod y);;
44
45
46 let r0 = {num=0;den=1};;
47 let r1 = {num=1;den=1};;
48
49 let rnorm x = let x = (if x.den<0 then {num=(-x.num);den=(-x.den)} else x) in
50               if x.num=0 then r0
51               else (let d=pgcd x.num x.den in
52                     let d= (if d<0 then -d else d) in
53                     {num=(x.num)/d;den=(x.den)/d});;
54  
55 let rop x = rnorm {num=(-x.num);den=x.den};;
56
57 let rplus x y = rnorm {num=x.num*y.den + y.num*x.den;den=x.den*y.den};;
58
59 let rminus x y = rnorm {num=x.num*y.den - y.num*x.den;den=x.den*y.den};;
60
61 let rmult x y = rnorm {num=x.num*y.num;den=x.den*y.den};;
62
63 let rinv x = rnorm {num=x.den;den=x.num};;
64
65 let rdiv x y = rnorm {num=x.num*y.den;den=x.den*y.num};;
66
67 let rinf x y = x.num*y.den < y.num*x.den;;
68 let rinfeq x y = x.num*y.den <= y.num*x.den;;
69
70 (* {coef;hist;strict}, où coef=[c1; ...; cn; d], représente l'inéquation
71 c1x1+...+cnxn < d si strict=true, <= sinon,
72 hist donnant les coefficients (positifs) d'une combinaison linéaire qui permet d'obtenir l'inéquation à partir de celles du départ.
73 *)
74
75 type ineq = {coef:rational list;
76              hist:rational list;
77              strict:bool};;
78
79 let pop x l = l:=x::(!l);;
80
81 (* sépare la liste d'inéquations s selon que leur premier coefficient est 
82 négatif, nul ou positif. *)
83 let partitionne s =
84    let lpos=ref [] in
85    let lneg=ref [] in
86    let lnul=ref [] in
87    List.iter (fun ie -> match ie.coef with
88                         [] ->  raise (Failure "empty ineq")
89                        |(c::r) -> if rinf c r0
90                                   then pop ie lneg
91                                   else if rinf r0 c then pop ie lpos
92                                               else pop ie lnul)
93              s;
94    [!lneg;!lnul;!lpos]
95 ;;
96 (* initialise les histoires d'une liste d'inéquations données par leurs listes de coefficients et leurs strictitudes (!):
97 (add_hist [(equation 1, s1);...;(équation n, sn)])
98 =
99 [{équation 1, [1;0;...;0], s1};
100  {équation 2, [0;1;...;0], s2};
101  ...
102  {équation n, [0;0;...;1], sn}]
103 *)
104 let add_hist le =
105    let n = List.length le in
106    let i=ref 0 in
107    List.map (fun (ie,s) -> 
108               let h =ref [] in
109               for k=1 to (n-(!i)-1) do pop r0 h; done;
110               pop r1 h;
111               for k=1 to !i do pop r0 h; done;
112               i:=!i+1;
113               {coef=ie;hist=(!h);strict=s})
114              le
115 ;;
116 (* additionne deux inéquations *)      
117 let ie_add ie1 ie2 = {coef=List.map2 rplus ie1.coef ie2.coef;
118                       hist=List.map2 rplus ie1.hist ie2.hist;
119                       strict=ie1.strict || ie2.strict}
120 ;;
121 (* multiplication d'une inéquation par un rationnel (positif) *)
122 let ie_emult a ie = {coef=List.map (fun x -> rmult a x) ie.coef;
123                      hist=List.map (fun x -> rmult a x) ie.hist;
124                      strict= ie.strict}
125 ;;
126 (* on enlève le premier coefficient *)
127 let ie_tl ie = {coef=List.tl ie.coef;hist=ie.hist;strict=ie.strict}
128 ;;
129 (* le premier coefficient: "tête" de l'inéquation *)
130 let hd_coef ie = List.hd ie.coef
131 ;;
132
133 (* calcule toutes les combinaisons entre inéquations de tête négative et inéquations de tête positive qui annulent le premier coefficient.
134 *)
135 let deduce_add lneg lpos =
136    let res=ref [] in
137    List.iter (fun i1 ->
138                  List.iter (fun i2 ->
139                                 let a = rop (hd_coef i1) in
140                                 let b = hd_coef i2 in
141                                 pop (ie_tl (ie_add (ie_emult b i1)
142                                                    (ie_emult a i2))) res)
143                            lpos)
144              lneg;
145    !res
146 ;;
147 (* élimination de la première variable à partir d'une liste d'inéquations:
148 opération qu'on itère dans l'algorithme de Fourier.
149 *)
150 let deduce1 s =
151     match (partitionne s) with 
152       [lneg;lnul;lpos] ->
153     let lnew = deduce_add lneg lpos in
154     (List.map ie_tl lnul)@lnew
155      |_->assert false
156 ;;
157 (* algorithme de Fourier: on élimine successivement toutes les variables.
158 *)
159 let deduce lie =
160    let n = List.length (fst (List.hd lie)) in
161    let lie=ref (add_hist lie) in
162    for i=1 to n-1 do
163       lie:= deduce1 !lie;
164    done;
165    !lie
166 ;;
167
168 (* donne [] si le système a des solutions,
169 sinon donne [c,s,lc]
170 où lc est la combinaison linéaire des inéquations de départ
171 qui donne 0 < c si s=true
172        ou 0 <= c sinon
173 cette inéquation étant absurde.
174 *)
175 let unsolvable lie =
176    let lr = deduce lie in
177    let res = ref [] in
178    (try (List.iter (fun e ->
179          match e with
180            {coef=[c];hist=lc;strict=s} ->
181                   if (rinf c r0 && (not s)) || (rinfeq c r0 && s) 
182                   then (res := [c,s,lc];
183                         raise (Failure "contradiction found"))
184           |_->assert false)
185                              lr)
186    with _ -> ());
187    !res
188 ;;
189
190 (* Exemples:
191
192 let test1=[[r1;r1;r0],true;[rop r1;r1;r1],false;[r0;rop r1;rop r1],false];;
193 deduce test1;;
194 unsolvable test1;;
195
196 let test2=[
197 [r1;r1;r0;r0;r0],false;
198 [r0;r1;r1;r0;r0],false;
199 [r0;r0;r1;r1;r0],false;
200 [r0;r0;r0;r1;r1],false;
201 [r1;r0;r0;r0;r1],false;
202 [rop r1;rop r1;r0;r0;r0],false;
203 [r0;rop r1;rop r1;r0;r0],false;
204 [r0;r0;rop r1;rop r1;r0],false;
205 [r0;r0;r0;rop r1;rop r1],false;
206 [rop r1;r0;r0;r0;rop r1],false
207 ];;
208 deduce test2;;
209 unsolvable test2;;
210
211 *)