PIPS
lattice_extraction.c
Go to the documentation of this file.
1 /*
2 
3  $Id: lattice_extraction.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* HPFC module by Fabien COELHO
28  */
29 
30 #include "defines-local.h"
31 #include "workspace-util.h" // for list_to_base()
32 #include "prettyprint.h" // for sc_syst_debug()
33 
34 #include "matrix.h"
35 #include "matrice.h"
36 #include "sparse_sc.h"
37 
38 /*
39 void normalize_system(Psysteme * ps)
40 {
41  Ptsg sg;
42  Psysteme s;
43 
44  DEBUG_SYST(1, "entry system", *ps);
45 
46  sg = sc_to_sg_chernikova(*ps);
47  sc_rm(*ps);
48 
49  s = sg_to_sc_chernikova(sg);
50  sg_rm(sg);
51 
52  DEBUG_SYST(1, "exit system", s);
53 
54  *ps = s;
55 }
56 */
57 
58 /* blindly appends b2 after b1
59  */
61 {
62  Pbase b;
63 
64  if (BASE_NULLE_P(b1)) return b2;
65 
66  for (b=b1; !BASE_NULLE_P(b->succ); b=b->succ);
67  b->succ = b2;
68  return b1;
69 }
70 
71 /* returns a newly allocated base with the scanners ahead
72  */
74  Pbase initial, /* full base */
75  list /* of entity */ ls) /* scanners */
76 {
77  Pbase sb = BASE_NULLE, ob = BASE_NULLE;
78  Pbase b;
79 
80  for (b=initial; !BASE_NULLE_P(b); b=b->succ) {
81  Variable v = var_of(b);
82  if (gen_in_list_p((entity) v, ls))
84  else
85  base_add_dimension(&ob, v);
86  }
87 
88  return append_to(sb, ob);
89 }
90 
91 /* void extract_lattice
92  *
93  * what: extracts a lattice from a set of equalities
94  * how: Hermite form computation on equalities implying scanners
95  * - equalities translated in F and M;
96  * - variables = scanners (s) + others (o) + cst (1)
97  * - F.s + M.o + V == 0
98  * - H = PFQ; // I assert P==I, maybe optimistic for this implementation...
99  * - (1) s = Q.y
100  * - (2) H.y + M.o + V == 0
101  * then
102  * - (2) => new equalities that define some y(r)
103  * - (1) => ddc in some order..., plus replacement in inequalities
104  * - (1) => newscs, but what about the order?
105  *
106  * input: Psysteme and scanners
107  * output: modified system, new scanners and deducibles
108  * side effects:
109  * - may create some new variables
110  * bugs or features:
111  */
112 void
114  Psysteme s, /* the system is modified */
115  list /* of entity */ scanners, /* variables to be scanned */
116  list /* of entity */ *newscs, /* returned new scanners */
117  list /* of expression */ *ddc) /* old deduction */
118 {
119  /* - should try to remove deducibles before hand?
120  */
121  int nscanners, nothers, ntotal, neq;
122  Pbase b, bsorted, byr;
123  Pmatrix FM, F, M, V, P, H, Q, Hl, Hli, Ql, Qr, QlHli,
124  QlHliM, QlHliV, mQr, I, Fnew;
125  Value det_P, det_Q;
126  int i;
127  list /* of entity */ lns = NIL, ltmp = NIL;
128  Pcontrainte eq;
129 
130  neq = sc_nbre_egalites(s);
131 
132  if (neq==0 || !get_bool_property("HPFC_EXTRACT_LATTICE")) {
133  /* void implementation: nothing done!
134  */
135  *newscs = gen_copy_seq(scanners);
136  *ddc = NIL;
137  return;
138  }
139  /* else do the job */
140 
141  DEBUG_SYST(3, "initial system", s);
142  DEBUG_ELST(3, "scanners", scanners);
143 
144  b = sc_base(s);
145  nscanners = gen_length(scanners);
146  ntotal = base_dimension(b);
147  nothers = ntotal - nscanners;
148 
149  message_assert("more scanners than equalities", nscanners>=neq);
150 
151  bsorted = scanners_then_others(b, scanners);
152 
153  DEBUG_BASE(3, "sorted base", bsorted);
154  pips_debug(3, "%d scanners, %d others, %d eqs\n", nscanners, nothers, neq);
155 
156  /* FM (so) + V == 0 */
157  FM = matrix_new(neq, ntotal);
158  V = matrix_new(neq, 1);
159 
160  constraints_to_matrices(sc_egalites(s), bsorted, FM, V);
161 
162  DEBUG_MTRX(4, "FM", FM);
163  DEBUG_MTRX(4, "V", V);
164 
165  /* Fs + Mo + V == 0 */
166  F = matrix_new(neq, nscanners);
167  M = matrix_new(neq, nothers);
168 
169  ordinary_sub_matrix(FM, F, 1, neq, 1, nscanners);
170  ordinary_sub_matrix(FM, M, 1, neq, nscanners+1, ntotal);
171 
172  matrix_free(FM);
173 
174  DEBUG_MTRX(4, "F", F);
175  DEBUG_MTRX(4, "M", M);
176 
177  /* H = P * F * Q */
178  H = matrix_new(neq, nscanners);
179  P = matrix_new(neq, neq);
180  Q = matrix_new(nscanners, nscanners);
181 
182  matrix_hermite(F, P, H, Q, &det_P, &det_Q);
183 
184  DEBUG_MTRX(4, "H", H);
185  DEBUG_MTRX(4, "P", P);
186  DEBUG_MTRX(4, "Q", Q);
187 
188  message_assert("P == I", matrix_diagonal_p(P) && det_P==1);
189 
190  /* H = (Hl 0) */
191  Hl = matrix_new(neq, neq);
192  ordinary_sub_matrix(H, Hl, 1, neq, 1, neq);
193  matrix_free(H);
194 
195  DEBUG_MTRX(4, "Hl", Hl);
196 
197  if (!matrix_triangular_unimodular_p(Hl, true)) {
198  pips_user_warning("fast exit, some yes/no lattice skipped\n");
199  /* and memory leak, by the way */
200  *newscs = gen_copy_seq(scanners);
201  *ddc = NIL;
202  return;
203  }
204 
205  message_assert("Hl is lower triangular unimodular",
207 
208  /* Hli = Hl^-1 */
209  Hli = matrix_new(neq, neq);
211  matrix_free(Hl);
212 
213  DEBUG_MTRX(4, "Hli", Hli);
214 
215  /* Q = (Ql Qr) */
216  Ql = matrix_new(nscanners, neq);
217  Qr = matrix_new(nscanners, nscanners-neq);
218 
219  ordinary_sub_matrix(Q, Ql, 1, nscanners, 1, neq);
220  ordinary_sub_matrix(Q, Qr, 1, nscanners, neq+1, nscanners);
221 
222  DEBUG_MTRX(4, "Ql", Ql);
223  DEBUG_MTRX(4, "Qr", Qr);
224 
225  matrix_free(Q);
226 
227  /* QlHli = Ql * Hl^-1 */
228  QlHli = matrix_new(nscanners, neq);
229  matrix_multiply(Ql, Hli, QlHli);
230 
231  matrix_free(Ql);
232  matrix_free(Hli);
233 
234  /* QlHliM = QlHli * M */
235  QlHliM = matrix_new(nscanners, nothers);
236  matrix_multiply(QlHli, M, QlHliM);
237 
238  matrix_free(M);
239 
240  /* QlHliV = QlHli * V */
241  QlHliV = matrix_new(nscanners, 1);
242  matrix_multiply(QlHli, V, QlHliV);
243 
244  matrix_free(V);
245  matrix_free(QlHli);
246 
247  /* I */
248  I = matrix_new(nscanners, nscanners);
249  matrix_identity(I, 0);
250 
251  /* mQr = - Qr */
252  mQr = matrix_new(nscanners, nscanners-neq);
253  matrix_uminus(Qr, mQr);
254  matrix_free(Qr);
255 
256  /* create nscanners-neq new scanning variables... they are the yr's.
257  */
258  for (i=0; i<nscanners-neq; i++)
259  lns = CONS(ENTITY,
261 
262  byr = list_to_base(lns);
263  bsorted = append_to(byr, bsorted); byr = BASE_NULLE;
264 
265  /* We have: mQr yr + I s + QlHliM o + QlHliV == 0
266  * yr are the new scanners, s the old ones, deducable from the new ones.
267  * the equation must also be used to remove s from the inequalities.
268  *
269  * Fnew = ( mQr I QlHliM )
270  */
271  Fnew = matrix_new(nscanners, 2*nscanners-neq+nothers);
272 
273  insert_sub_matrix(Fnew, mQr, 1, nscanners, 1, nscanners-neq);
274  insert_sub_matrix(Fnew, I, 1, nscanners, nscanners-neq+1, 2*nscanners-neq);
275  insert_sub_matrix(Fnew, QlHliM, 1, nscanners,
276  2*nscanners-neq+1, 2*nscanners-neq+nothers);
277 
278  matrix_free(I);
279  matrix_free(mQr);
280  matrix_free(QlHliM);
281 
282  /* Now we have:
283  * (a) Fnew (yr s o)^t + QlHliV == 0
284  * (b) lns -- the new scanners
285  *
286  * we must
287  * (1) generate deducables from (a),
288  * (2) regenerate inequalities on yr's.
289  */
290 
291  matrices_to_constraints(&eq, bsorted, Fnew, QlHliV);
292  matrix_free(Fnew);
293  matrix_free(QlHliV);
294 
295  /* clean the new system
296  */
297  contraintes_free(sc_egalites(s));
298  sc_egalites(s) = eq;
299  base_rm(sc_base(s));
300  sc_creer_base(s);
301 
302  /* old scanners are deduced now:
303  */
304  *ddc = gen_append(*ddc, simplify_deducable_variables(s, scanners, &ltmp));
305  pips_assert("no vars left", ENDP(ltmp));
306 
307  *newscs = lns;
308 
309  base_rm(bsorted);
310 
311  DEBUG_SYST(3, "resulting system", s);
312  DEBUG_ELST(3, "new scanners", lns);
313 }
314 
315 /* that is all
316  */
int Value
entity node_module
Definition: compiler.c:47
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define F
Definition: freia-utils.c:51
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
list gen_append(list l1, const list l2)
Definition: list.c:471
entity hpfc_new_variable(entity module, basic b)
Definition: compile.c:632
#define DEBUG_SYST(D, W, S)
#define DEBUG_BASE(D, W, B)
#define DEBUG_ELST(D, W, L)
#define DEBUG_MTRX(D, W, M)
list simplify_deducable_variables(Psysteme, list, list *)
list simplify_deducable_variables(syst, vars, pleftvars) Psysteme syst; list vars,...
Definition: io-compile.c:562
static Pbase append_to(Pbase b1, Pbase b2)
HPFC module by Fabien COELHO.
static Pbase scanners_then_others(Pbase initial, list ls)
returns a newly allocated base with the scanners ahead
void extract_lattice(Psysteme s, list scanners, list *newscs, list *ddc)
void extract_lattice
#define matrix_free(m)
Allocation et desallocation d'une matrice.
Definition: matrix-local.h:73
Pmatrix matrix_new(int m, int n)
package matrix
Definition: alloc.c:41
void matrix_hermite(Pmatrix MAT, Pmatrix P, Pmatrix H, Pmatrix Q, Value *det_p, Value *det_q)
package matrix
Definition: hermite.c:78
void matrix_unimodular_triangular_inversion(Pmatrix u, Pmatrix inv_u, bool infer)
package matrix
Definition: inversion.c:53
void matrix_uminus(Pmatrix A, Pmatrix mA)
void matrix_uminus(A, mA)
Definition: matrix.c:558
bool matrix_diagonal_p(Pmatrix Z)
bool matrix_diagonal_p(Pmatrix Z): test de nullite de la matrice Z
Definition: matrix.c:336
void matrix_multiply(const Pmatrix a, const Pmatrix b, Pmatrix c)
void matrix_multiply(Pmatrix a, Pmatrix b, Pmatrix c): multiply rational matrix a by rational matrix ...
Definition: matrix.c:95
bool matrix_triangular_unimodular_p(Pmatrix Z, bool inferieure)
bool matrix_triangular_unimodular_p(Pmatrix Z, bool inferieure) test de la triangulaire et unimodulai...
Definition: matrix.c:403
void ordinary_sub_matrix(Pmatrix, Pmatrix, int, int, int, int)
void ordinary_sub_matrix(Pmatrix A, A_sub, int i1, i2, j1, j2) input : a initialized matrix A,...
Definition: sub-matrix.c:469
void matrix_identity(Pmatrix, int)
void matrix_identity(Pmatrix ID, int level) Construction d'une sous-matrice identity dans ID(level+1....
Definition: sub-matrix.c:322
void insert_sub_matrix(Pmatrix, Pmatrix, int, int, int, int)
void insert_sub_matrix(A, A_sub, i1, i2, j1, j2) input: matrix A and smaller A_sub output: nothing mo...
Definition: sub-matrix.c:487
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
Pbase list_to_base(list l)
Pbase list_to_base(list l): returns the Pbase that contains the variables of list "l",...
#define message_assert(msg, ex)
Definition: newgen_assert.h:47
#define Q
Definition: pip__type.h:39
basic MakeBasic(int)
END_EOLE.
Definition: type.c:128
@ is_basic_int
Definition: ri.h:571
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
void sc_creer_base(Psysteme ps)
void sc_creer_base(Psysteme ps): initialisation des parametres dimension et base d'un systeme lineair...
Definition: sc_alloc.c:129
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
void matrices_to_constraints(Pcontrainte *, Pbase, Pmatrix, Pmatrix)
=======================================================================
void constraints_to_matrices(Pcontrainte, Pbase, Pmatrix, Pmatrix)
=======================================================================
package matrice
Definition: matrix-local.h:63
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:4047
#define base_rm(b)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define var_of(varval)
#define base_dimension(b)
#define BASE_NULLE
MACROS SUR LES BASES.
#define BASE_NULLE_P(b)
#define base_add_dimension(b, v)