2 #include "normalization.h"
4 static int is_unit_row(Value
*row
, int pos
, int len
)
6 if (!value_one_p(row
[pos
]) && !value_mone_p(row
[pos
]))
8 return First_Non_Zero(row
+pos
+1, len
-(pos
+1)) == -1;
11 /* Transform the constraints C to "standard form".
12 * In particular, if C is described by
14 * then this function returns a matrix H = A U, A = H Q, such
15 * that D x' = D Q x >= -b(p), with D a diagonal matrix with
16 * positive entries. The calling function can then construct
17 * the standard form H' x' - I s + b(p) = 0, with H' the rows of H
18 * that are not positive multiples of unit vectors
19 * (since those correspond to D x' >= -b(p)).
20 * The number of rows in H' is returned in *rows_p.
21 * Optionally returns the matrix that maps the new variables
22 * back to the old variables x = U x'.
23 * Note that the rows of H (and C) may be reordered by this function.
25 Matrix
*standard_constraints(Matrix
*C
, unsigned nparam
, int *rows_p
,
28 unsigned dim
= C
->NbColumns
- 2;
29 unsigned nvar
= dim
- nparam
;
35 /* move constraints only involving parameters down
36 * and move unit vectors (if there are any) to the right place.
38 for (d
= 0, j
= C
->NbRows
; d
< j
; ++d
) {
40 index
= First_Non_Zero(C
->p
[d
]+1, nvar
);
43 is_unit_row(C
->p
[d
]+1, index
, nvar
)) {
44 Vector_Exchange(C
->p
[d
], C
->p
[index
], dim
+2);
50 while (d
< --j
&& First_Non_Zero(C
->p
[j
]+1, nvar
) == -1)
54 Vector_Exchange(C
->p
[d
], C
->p
[j
], dim
+2);
56 M
= Matrix_Alloc(d
, nvar
);
57 for (j
= 0; j
< d
; ++j
)
58 Vector_Copy(C
->p
[j
]+1, M
->p
[j
], nvar
);
60 neg_left_hermite(M
, &H
, &Q
, &U
);
68 /* Rearrange rows such that top of H is lower diagonal and
69 * compute the number of non (multiple of) unit-vector rows.
71 rows
= H
->NbRows
-nvar
;
72 for (i
= 0; i
< H
->NbColumns
; ++i
) {
73 for (j
= i
; j
< H
->NbRows
; ++j
)
74 if (value_notzero_p(H
->p
[j
][i
]))
77 Vector_Exchange(C
->p
[i
], C
->p
[j
], dim
+2);
78 Vector_Exchange(H
->p
[i
], H
->p
[j
], H
->NbColumns
);
80 if (First_Non_Zero(H
->p
[i
], i
) != -1)
90 * Transform the constraints of P, which may have existentially
91 * quantified variables to "standard form".
93 * We need to make sure that the new variables are affine
94 * combinations of only the original variables (and not
95 * of any of the existentially quantified variables).
96 * We therefore first apply standard_constraints on
97 * the constraints involving only the variables and
98 * then apply the same procedure on the remaining
99 * constraints with the variables as parameters.
101 * Perhaps we are overly careful here. Moving the constraints
102 * involving existentially quantified variables down should prevent
103 * the regular variables from being replaced by linear combinations
104 * of existential variables.
106 static Matrix
*exist_standard_constraints(Polyhedron
*P
, unsigned nvar
)
109 unsigned exist
= P
->Dimension
- nvar
;
110 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
, 2+P
->Dimension
);
111 Matrix
*M1
= Matrix_Alloc(P
->NbConstraints
, 2+nvar
);
112 Matrix
*M2
= Matrix_Alloc(P
->NbConstraints
, 2+P
->Dimension
);
116 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
117 value_assign(M
->p
[i
][0], P
->Constraint
[i
][0]);
118 Vector_Copy(P
->Constraint
[i
]+1, M
->p
[i
]+1+exist
, nvar
);
119 Vector_Copy(P
->Constraint
[i
]+1+nvar
, M
->p
[i
]+1, exist
);
120 value_assign(M
->p
[i
][1+P
->Dimension
], P
->Constraint
[i
][1+P
->Dimension
]);
122 Gauss(M
, P
->NbEq
, P
->Dimension
+1);
123 for (i
= i1
= i2
= 0; i
< M
->NbRows
; ++i
) {
124 if (First_Non_Zero(M
->p
[i
]+1, exist
) == -1) {
125 value_assign(M1
->p
[i1
][0], M
->p
[i
][0]);
126 Vector_Copy(M
->p
[i
]+1+exist
, M1
->p
[i1
]+1, nvar
+1);
129 Vector_Copy(M
->p
[i
], M2
->p
[i2
], M
->NbColumns
);
137 S1
= standard_constraints(M1
, 0, NULL
, NULL
);
138 S2
= standard_constraints(M2
, nvar
, NULL
, NULL
);
140 M
= Matrix_Alloc(P
->NbConstraints
, 2+P
->Dimension
);
141 for (i
= 0; i
< M1
->NbRows
; ++i
) {
142 value_assign(M
->p
[i
][0], M1
->p
[i
][0]);
143 Vector_Copy(S1
->p
[i
], M
->p
[i
]+1, nvar
);
144 value_assign(M
->p
[i
][1+P
->Dimension
], M1
->p
[i
][1+nvar
]);
146 for (i
= 0; i
< M2
->NbRows
; ++i
) {
147 value_assign(M
->p
[M1
->NbRows
+i
][0], M2
->p
[i
][0]);
148 Vector_Copy(M2
->p
[i
]+1+exist
, M
->p
[M1
->NbRows
+i
]+1, nvar
);
149 Vector_Copy(S2
->p
[i
], M
->p
[M1
->NbRows
+i
]+1+nvar
, exist
);
150 value_assign(M
->p
[M1
->NbRows
+i
][1+P
->Dimension
],
151 M2
->p
[i
][1+P
->Dimension
]);
154 /* Make sure "standard" constraints for existential variables
155 * have only non-positive coefficients for the variables.
157 assert(M2
->NbRows
>= exist
);
159 for (i
= 0; i
< exist
; ++i
) {
160 assert(value_pos_p(S2
->p
[i
][i
]));
161 for (i1
= 0; i1
< nvar
; ++i1
) {
162 if (value_negz_p(M
->p
[M1
->NbRows
+i
][1+i1
]))
164 mpz_cdiv_q(c
, M
->p
[M1
->NbRows
+i
][1+i1
], S2
->p
[i
][i
]);
166 for (i2
= i
; i2
< M2
->NbRows
; ++i2
)
167 value_addmul(M
->p
[M1
->NbRows
+i2
][1+i1
], c
, S2
->p
[i2
][i
]);
179 * For those variables x that may attain negative values,
180 * compute a translations t such that x' = x + t is sure
181 * to attain only non-negative values, i.e., if M is
187 * A x' + b - A t >= 0
189 * are sure to attain only non-negative values.
191 static Vector
*compute_shifts(Matrix
*M
)
194 unsigned dim
= M
->NbColumns
-2;
195 Vector
*shifts
= Vector_Alloc(M
->NbColumns
);
196 for (c
= 0, r
= 0; c
< dim
; ++c
) {
197 for ( ; r
< M
->NbRows
; ++r
) {
198 if (value_notzero_p(M
->p
[r
][1+c
]))
201 assert(r
< M
->NbRows
);
202 assert(value_pos_p(M
->p
[r
][1+c
]));
204 Inner_Product(M
->p
[r
]+1, shifts
->p
+1, c
, &shifts
->p
[1+c
]);
205 value_subtract(shifts
->p
[1+c
], M
->p
[r
][1+dim
], shifts
->p
[1+c
]);
206 if (value_pos_p(shifts
->p
[1+c
]))
207 mpz_cdiv_q(shifts
->p
[1+c
], shifts
->p
[1+c
], M
->p
[r
][1+c
]);
209 value_set_si(shifts
->p
[1+c
], 0);
215 * Given a union of polyhedra, with possibly existentially
216 * quantified variables, but no parameters, apply a unimodular
217 * transformation with constant translation to the variables,
218 * and a unimodular transformation with a translation possibly
219 * depending on the variables to the existentially quantified variables,
220 * such that all variables and all existentially quantified variables
221 * attain only non-negative values.
223 Polyhedron
*skew_to_positive_orthant(Polyhedron
*D
, unsigned nvar
,
227 Polyhedron
*R
= NULL
;
228 Polyhedron
**next
= &R
;
230 for (P
= D
; P
; P
= P
->next
) {
232 Vector
*shifts
, *offsets
;
235 M
= exist_standard_constraints(P
, nvar
);
236 shifts
= compute_shifts(M
);
238 offsets
= Vector_Alloc(P
->NbConstraints
);
239 Matrix_Vector_Product(M
, shifts
->p
, offsets
->p
);
242 C
= Matrix_Alloc(P
->NbConstraints
, P
->Dimension
+2);
243 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
244 value_assign(C
->p
[i
][0], M
->p
[i
][0]);
245 Vector_Copy(M
->p
[i
]+1, C
->p
[i
]+1, P
->Dimension
);
246 value_subtract(C
->p
[i
][1+P
->Dimension
],
247 M
->p
[i
][1+P
->Dimension
], offsets
->p
[i
]);
249 Vector_Free(offsets
);
252 *next
= Constraints2Polyhedron(C
, MaxRays
);
255 next
= &(*next
)->next
;