decomposer.cc: support primal decomposition
[barvinok.git] / piputil.c
blobd82983dbdf47e1a94f01b170d53ae9d290f788dc
1 #include <stdio.h> /* needed for piplib ! */
2 #include <piplib/piplibMP.h>
3 #include <assert.h>
4 #include "piputil.h"
5 #include "config.h"
7 #ifdef HAVE_GROWING_CHERNIKOVA
8 #define MAXRAYS POL_NO_DUAL
9 #else
10 #define MAXRAYS 600
11 #endif
13 static PipMatrix *poly2pip(Polyhedron *P, int pos, int n, int nparam)
15 PipMatrix * matrix;
16 int i, j;
17 unsigned int extra = P->Dimension - pos - n - nparam;
19 matrix = pip_matrix_alloc(P->NbConstraints, P->Dimension+2);
20 for (i = 0; i < P->NbConstraints; ++i) {
21 value_assign(matrix->p[i][0], P->Constraint[i][0]);
22 for (j = 0; j < n; ++j)
23 value_assign(matrix->p[i][1+j], P->Constraint[i][1+pos+j]);
24 for (j = 0; j < pos; ++j)
25 value_assign(matrix->p[i][1+n+j], P->Constraint[i][1+j]);
26 for (j = 0; j < extra; ++j)
27 value_assign(matrix->p[i][1+n+pos+j], P->Constraint[i][1+n+pos+j]);
28 for (j = 1+pos+n+extra; j < P->Dimension+2; ++j)
29 value_assign(matrix->p[i][j], P->Constraint[i][j]);
32 return matrix;
35 static int max_new(PipQuast *q, int max, int d, int *maxd)
37 PipNewparm *p;
39 for (p = q->newparm; p; p = p->next)
40 if (p->rank > max)
41 max = p->rank;
42 if (q->condition) {
43 if (++d > *maxd)
44 *maxd = d;
45 max = max_new(q->next_else, max, d, maxd);
46 max = max_new(q->next_then, max, d, maxd);
48 return max;
52 * v: total number of variables in original problem
53 * pos: position of minimized variables
54 * n: dimension of space in which minimum was taken
55 * i.e., number of minimized vars in original problem
56 * e: number of extra existential variables
57 * d: total dimension
59 struct scan_data {
60 Matrix *M;
61 int v;
62 int pos;
63 int n;
64 int e;
65 int d;
66 void (*f)(struct scan_data *data, PipQuast *q, int i);
69 static int vectorpos2cpos(struct scan_data *data, int j)
71 int np = data->d - data->v - data->e;
72 int l;
74 if (j < data->pos)
75 l = 1+j;
76 else if (j < data->v - data->n)
77 l = 1+data->n+j;
78 else if (j < data->v-data->n+np)
79 l = 1+data->n+data->e+j;
80 else
81 l = 1+data->n+j-np;
83 return l;
87 * returns true if some solution exist in the whole quast q
89 static int full_quast(PipQuast *q)
91 return q->condition ? full_quast(q->next_then) && full_quast(q->next_else)
92 : q->list != NULL;
96 * i: next row
98 * Dimensions in the resulting domain are:
99 * v n e (d-v-n-e)
101 static void scan_quast_r(struct scan_data *data, PipQuast *q, int i)
103 PipNewparm *p;
104 int skip;
106 /* Skip to a (random) leaf if we are only interested in whether
107 * a solution exists.
109 skip = data->n == 0 && full_quast(q);
110 while (skip && q->condition)
111 q = q->next_then;
113 for (p = q->newparm; !skip && p; p = p->next) {
114 int j, l;
115 PipVector *vec = p->vector;
117 value_set_si(data->M->p[i][0], 1);
118 Vector_Set(data->M->p[i]+1, 0, data->d);
120 for (j = 0; j < vec->nb_elements-1; ++j) {
121 l = vectorpos2cpos(data, j);
122 value_assign(data->M->p[i][l], vec->the_vector[j]);
124 l = vectorpos2cpos(data, p->rank);
125 value_oppose(data->M->p[i][l], p->deno);
126 value_assign(data->M->p[i][1+data->d], vec->the_vector[j]);
127 ++i;
129 value_set_si(data->M->p[i][0], 1);
130 Vector_Set(data->M->p[i]+1, 0, data->d);
132 for (j = 0; j < vec->nb_elements-1; ++j) {
133 l = vectorpos2cpos(data, j);
134 value_oppose(data->M->p[i][l], vec->the_vector[j]);
136 l = vectorpos2cpos(data, p->rank);
137 value_assign(data->M->p[i][l], p->deno);
138 value_oppose(data->M->p[i][1+data->d], vec->the_vector[j]);
139 value_addto(data->M->p[i][1+data->d], data->M->p[i][1+data->d], p->deno);
140 value_decrement(data->M->p[i][1+data->d], data->M->p[i][1+data->d]);
141 ++i;
144 if (q->condition) {
145 int j;
146 value_set_si(data->M->p[i][0], 1);
147 Vector_Set(data->M->p[i]+1, 0, data->d);
149 for (j = 0; j < q->condition->nb_elements-1; ++j) {
150 int l = vectorpos2cpos(data, j);
151 value_assign(data->M->p[i][l], q->condition->the_vector[j]);
153 value_assign(data->M->p[i][1+data->d], q->condition->the_vector[j]);
154 scan_quast_r(data, q->next_then, i+1);
156 for (j = 0; j < q->condition->nb_elements-1; ++j) {
157 int l = vectorpos2cpos(data, j);
158 value_oppose(data->M->p[i][l], q->condition->the_vector[j]);
160 value_oppose(data->M->p[i][1+data->d], q->condition->the_vector[j]);
161 value_decrement(data->M->p[i][1+data->d], data->M->p[i][1+data->d]);
162 scan_quast_r(data, q->next_else, i+1);
164 return;
167 /* if data->n is zero, we are only interested in the domains
168 * where a solution exists and not in the actual solution
170 if (q->list && data->n) {
171 PipList *l;
172 int j, k;
173 for (j = 0, l = q->list; l; ++j, l = l->next) {
174 Vector_Set(data->M->p[i], 0, data->d+1);
175 value_set_si(data->M->p[i][1+data->pos+j], -1);
177 for (k = 0; k < l->vector->nb_elements-1; ++k) {
178 int ll = vectorpos2cpos(data, k);
179 value_assign(data->M->p[i][ll], l->vector->the_vector[k]);
181 value_assign(data->M->p[i][1+data->d], l->vector->the_vector[k]);
183 ++i;
186 data->f(data, q, i);
189 static void scan_quast(struct scan_data *data, PipQuast *q)
191 int nparam, nexist, d, i, rows;
193 nparam = data->d - data->n;
195 d = 0;
196 nexist = max_new(q, nparam-1, 0, &d) - nparam+1;
197 rows = 2 * nexist + d + data->n;
199 /* nparam now refers to the number of parameters in the original polyhedron */
200 nparam -= data->v - data->n;
202 data->e = nexist;
203 data->d = data->v + nexist + nparam;
205 data->M = Matrix_Alloc(rows, 1+data->d+1);
207 scan_quast_r(data, q, 0);
208 Matrix_Free(data->M);
211 struct quast2poly_data {
212 struct scan_data scan;
213 Polyhedron* D;
216 static void add_quast_base(struct scan_data *data, PipQuast *q, int i)
218 struct quast2poly_data *qdata = (struct quast2poly_data *)data;
219 if (q->list) {
220 Matrix *C;
221 Polyhedron *P;
222 C = Matrix_Alloc(i, 1+data->d+1);
223 Vector_Copy(data->M->p[0], C->p[0], i * (1+data->d+1));
224 P = Constraints2Polyhedron(C, MAXRAYS);
225 Matrix_Free(C);
226 P->next = qdata->D;
227 qdata->D = P;
232 * nvar: total number of variables, including the minimized variables,
233 * but excluding the parameters
234 * nparam: the number of parameters in the PIP problem, excluding the "big parameter"
235 * for maximization problems, i.e., the
236 * total number of variables minus the minimized variables
237 * pos: position of the first minimized variable
238 * n: number of minimized variables
240 static Polyhedron *quast2poly(PipQuast *q, int nvar, int nparam, int pos, int n)
242 struct quast2poly_data data;
244 data.scan.v = nvar;
245 data.scan.pos = pos;
246 data.scan.n = n;
247 data.scan.d = n+nparam;
249 data.D = 0;
250 data.scan.f = add_quast_base;
252 scan_quast(&data.scan, q);
254 return data.D;
257 Polyhedron *pip_projectout(Polyhedron *P, int pos, int n, int nparam)
259 PipOptions *options;
260 PipMatrix * domain;
261 unsigned int nvar = P->Dimension - nparam;
262 PipMatrix *context = pip_matrix_alloc(0, P->Dimension - n + 2);
263 PipQuast *sol;
264 Polyhedron *min;
266 POL_ENSURE_INEQUALITIES(P);
268 domain = poly2pip(P, pos, n, nparam);
269 #ifdef PIP_DEBUG
270 pip_matrix_print(stderr, domain);
271 pip_matrix_print(stderr, context);
272 #endif
274 options = pip_options_init();
275 options->Urs_unknowns = -1;
276 options->Urs_parms = -1;
277 options->Simplify = 1;
278 sol = pip_solve(domain, context, -1, options);
280 #ifdef PIP_DEBUG
281 pip_quast_print(stderr, sol, 0);
282 #endif
284 min = quast2poly(sol, nvar - n, P->Dimension - n, 0, 0);
286 pip_quast_free(sol);
287 pip_matrix_free(context);
288 pip_matrix_free(domain);
289 pip_options_free(options);
291 return min;