polylib
7.01
SolveDio.c
Go to the documentation of this file.
1
#include <
polylib/polylib.h
>
2
#include <stdlib.h>
3
4
// static void RearrangeMatforSolveDio(Matrix *M);
5
6
// /*
7
// * Solve Diophantine Equations :
8
// * This function takes as input a system of equations in the form
9
// * Ax + C = 0 and finds the solution for it, if it exists
10
// *
11
// * Input : The matrix form the system of the equations Ax + C = 0
12
// * ( a pointer to a Matrix. )
13
// * A pointer to the pointer, where the matrix U
14
// * corresponding to the free variables of the equation
15
// * is stored.
16
// * A pointer to the pointer of a vector is a solution to T.
17
// *
18
// *
19
// * Output : The above matrix U and the vector T.
20
// *
21
// * Algorithm :
22
// * Given an integral matrix A, we can split it such that
23
// * A = HU, where H is in HNF (lowr triangular)
24
// * and U is unimodular.
25
// * So Ax = c -> HUx = c -> Ht = c ( where Ux = t).
26
// * Solving for Ht = c is easy.
27
// * Using 't' we find x = U(inverse) * t.
28
// *
29
// * Steps :
30
// * 1) For the above algorithm to work correctly to
31
// * need the condition that the first 'rank' rows are
32
// * the rows which contribute to the rank of the matrix.
33
// * So first we copy Input into a matrix 'A' and
34
// * rearrange the rows of A (if required) such that
35
// * the first rank rows contribute to the rank.
36
// * 2) Extract A and C from the matrix 'A'. A = n * l matrix.
37
// * 3) Find the Hermite normal form of the matrix A.
38
// * ( the matrices the lower tri. H and the unimod U).
39
// * 4) Using H, find the values of T one by one.
40
// * Here we use a sort of Gaussian elimination to find
41
// * the solution. You have a lower triangular matrix
42
// * and a vector,
43
// * [ [a11, 0], [a21, a22, 0] ...,[arank1...a rankrank 0]]
44
// * and the solution vector [t1.. tn] and the vector
45
// * [ c1, c2 .. cl], now as we are traversing down the
46
// * rows one by one, we will have all the information
47
// * needed to calculate the next 't'.
48
// *
49
// * That is to say, when you want to calculate t2,
50
// * you would have already calculated the value of t1
51
// * and similarly if you are calculating t3, you will
52
// * need t1 and t2 which will be available by that time.
53
// * So, we apply a sort of Gaussian Elimination inorder
54
// * to find the vector T.
55
// *
56
// * 5) After finding t_rank, the remaining (l-rank) t's are
57
// * made equal to zero, and we verify, if these values
58
// * agree with the remaining (n-rank) rows of A.
59
// *
60
// * 6) If a solution exists, find the values of X using
61
// * U (inverse) * T.
62
// */
63
// int SolveDiophantine(Matrix *M, Matrix **U, Vector **X) {
64
65
// int i, j, k1, k2, min, rank;
66
// Matrix *A, *temp, *hermi, *unimod, *unimodinv;
67
// Value *C; /* temp storage for the vector C */
68
// Value *T; /* storage for the vector t */
69
// Value sum, tmp;
70
71
// #ifdef DOMDEBUG
72
// FILE *fp;
73
// fp = fopen("_debug", "a");
74
// fprintf(fp, "\nEntered SOLVEDIOPHANTINE\n");
75
// fclose(fp);
76
// #endif
77
78
// value_init(sum);
79
// value_init(tmp);
80
81
// /* Ensuring that the first rank row of A contribute to the rank*/
82
// A = Matrix_Copy(M);
83
// RearrangeMatforSolveDio(A);
84
// temp = Matrix_Alloc(A->NbRows - 1, A->NbColumns - 1);
85
86
// /* Copying A into temp, ignoring the Homogeneous part */
87
// for (i = 0; i < A->NbRows - 1; i++)
88
// for (j = 0; j < A->NbColumns - 1; j++)
89
// value_assign(temp->p[i][j], A->p[i][j]);
90
91
// /* Copying C into a temp, ignoring the Homogeneous part */
92
// C = (Value *)malloc(sizeof(Value) * (A->NbRows - 1));
93
// k1 = A->NbRows - 1;
94
95
// for (i = 0; i < k1; i++) {
96
// value_init(C[i]);
97
// value_oppose(C[i], A->p[i][A->NbColumns - 1]);
98
// }
99
// Matrix_Free(A);
100
101
// /* Finding the HNF of temp */
102
// Hermite(temp, &hermi, &unimod);
103
104
// /* Testing for existence of a Solution */
105
106
// min = (hermi->NbRows <= hermi->NbColumns) ? hermi->NbRows : hermi->NbColumns;
107
// rank = 0;
108
// for (i = 0; i < min; i++) {
109
// if (value_notzero_p(hermi->p[i][i]))
110
// rank++;
111
// else
112
// break;
113
// }
114
115
// /* Solving the Equation using Gaussian Elimination*/
116
117
// T = (Value *)malloc(sizeof(Value) * temp->NbColumns);
118
// k2 = temp->NbColumns;
119
// for (i = 0; i < k2; i++)
120
// value_init(T[i]);
121
122
// for (i = 0; i < rank; i++) {
123
// value_set_si(sum, 0);
124
// for (j = 0; j < i; j++) {
125
// value_addmul(sum, T[j], hermi->p[i][j]);
126
// }
127
// value_subtract(tmp, C[i], sum);
128
// value_modulus(tmp, tmp, hermi->p[i][i]);
129
// if (value_notzero_p(tmp)) { /* no solution to the equation */
130
// *U = Matrix_Alloc(0, 0);
131
// *X = Vector_Alloc(0);
132
// Matrix_Free(unimod);
133
// Matrix_Free(hermi);
134
// Matrix_Free(temp);
135
// value_clear(sum);
136
// value_clear(tmp);
137
// for (i = 0; i < k1; i++)
138
// value_clear(C[i]);
139
// for (i = 0; i < k2; i++)
140
// value_clear(T[i]);
141
// free(C);
142
// free(T);
143
// return (-1);
144
// };
145
// value_subtract(tmp, C[i], sum);
146
// value_division(T[i], tmp, hermi->p[i][i]);
147
// }
148
149
// /** Case when rank < Number of Columns; **/
150
151
// for (i = rank; i < hermi->NbColumns; i++)
152
// value_set_si(T[i], 0);
153
154
// /** Solved the equtions **/
155
// /** When rank < hermi->NbRows; Verifying whether the solution agrees
156
// with the remaining n-rank rows as well. **/
157
158
// for (i = rank; i < hermi->NbRows; i++) {
159
// value_set_si(sum, 0);
160
// for (j = 0; j < hermi->NbColumns; j++) {
161
// value_addmul(sum, T[j], hermi->p[i][j]);
162
// }
163
// if (value_ne(sum, C[i])) {
164
// *U = Matrix_Alloc(0, 0);
165
// *X = Vector_Alloc(0);
166
// Matrix_Free(unimod);
167
// Matrix_Free(hermi);
168
// Matrix_Free(temp);
169
// value_clear(sum);
170
// value_clear(tmp);
171
// for (i = 0; i < k1; i++)
172
// value_clear(C[i]);
173
// for (i = 0; i < k2; i++)
174
// value_clear(T[i]);
175
// free(C);
176
// free(T);
177
// return (-1);
178
// }
179
// }
180
// unimodinv = Matrix_Alloc(unimod->NbRows, unimod->NbColumns);
181
// Matrix_Inverse(unimod, unimodinv);
182
// Matrix_Free(unimod);
183
// *X = Vector_Alloc(M->NbColumns - 1);
184
185
// if (rank == hermi->NbColumns)
186
// *U = Matrix_Alloc(0, 0);
187
// else { /* Extracting the General solution form U(inverse) */
188
189
// *U = Matrix_Alloc(hermi->NbColumns, hermi->NbColumns - rank);
190
// for (i = 0; i < U[0]->NbRows; i++)
191
// for (j = 0; j < U[0]->NbColumns; j++)
192
// value_assign(U[0]->p[i][j], unimodinv->p[i][j + rank]);
193
// }
194
195
// for (i = 0; i < unimodinv->NbRows; i++) {
196
197
// /* Calculating the vector X = Uinv * T */
198
// value_set_si(sum, 0);
199
// for (j = 0; j < unimodinv->NbColumns; j++) {
200
// value_addmul(sum, unimodinv->p[i][j], T[j]);
201
// }
202
// value_assign(X[0]->p[i], sum);
203
// }
204
205
// /*
206
// for (i = rank; i < A->NbColumns; i ++)
207
// X[0]->p[i] = 0;
208
// */
209
// Matrix_Free(unimodinv);
210
// Matrix_Free(hermi);
211
// Matrix_Free(temp);
212
// value_clear(sum);
213
// value_clear(tmp);
214
// for (i = 0; i < k1; i++)
215
// value_clear(C[i]);
216
// for (i = 0; i < k2; i++)
217
// value_clear(T[i]);
218
// free(C);
219
// free(T);
220
// return (rank);
221
// } /* SolveDiophantine */
222
223
// /*
224
// * Rearrange :
225
// * This function takes as input a matrix M (pointer to it)
226
// * and it returns the tranformed matrix M, such that the first
227
// * 'rank' rows of the new matrix M are the ones which contribute
228
// * to the rank of the matrix M.
229
// *
230
// * 1) For a start we try to put all the zero rows at the end.
231
// * 2) Then cur = 1st row of the remaining matrix.
232
// * 3) nextrow = 2ndrow of M.
233
// * 4) temp = cur + nextrow
234
// * 5) If (rank(temp) == temp->NbRows.) {cur = temp;nextrow ++}
235
// * 6) Else (Exchange the nextrow of M with the currentlastrow.
236
// * and currentlastrow --).
237
// * 7) Repeat steps 4,5,6 till it is no longer possible.
238
// *
239
// */
240
// static void RearrangeMatforSolveDio(Matrix *M) {
241
242
// int i, j, curend, curRow, min, rank = 1;
243
// Bool add = True;
244
// Matrix *A, *L, *H, *U;
245
246
// /* Though I could have used the Lattice function
247
// Extract Linear Part, I chose not to use it so that
248
// this function can be independent of Lattice Operations */
249
250
// L = Matrix_Alloc(M->NbRows - 1, M->NbColumns - 1);
251
// for (i = 0; i < L->NbRows; i++)
252
// for (j = 0; j < L->NbColumns; j++)
253
// value_assign(L->p[i][j], M->p[i][j]);
254
255
// /* Putting the zero rows at the end */
256
// curend = L->NbRows - 1;
257
// for (i = 0; i < curend; i++) {
258
// for (j = 0; j < L->NbColumns; j++)
259
// if (value_notzero_p(L->p[i][j]))
260
// break;
261
// if (j == L->NbColumns) {
262
// ExchangeRows(M, i, curend);
263
// curend--;
264
// }
265
// }
266
267
// /* Trying to put the redundant rows at the end */
268
269
// if (curend > 0) { /* there are some useful rows */
270
271
// Matrix *temp;
272
// A = Matrix_Alloc(1, L->NbColumns);
273
274
// for (i = 0; i < L->NbColumns; i++)
275
// value_assign(A->p[0][i], L->p[0][i]);
276
// curRow = 1;
277
// while (add == True) {
278
// temp = AddANullRow(A);
279
// for (i = 0; i < A->NbColumns; i++)
280
// value_assign(temp->p[curRow][i], L->p[curRow][i]);
281
// Hermite(temp, &H, &U);
282
// for (i = 0; i < H->NbRows; i++)
283
// if (value_zero_p(H->p[i][i]))
284
// break;
285
// if (i != H->NbRows) {
286
// ExchangeRows(M, curRow, curend);
287
// curend--;
288
// } else {
289
// curRow++;
290
// rank++;
291
// Matrix_Free(A);
292
// A = Matrix_Copy(temp);
293
// Matrix_Free(temp);
294
// }
295
// Matrix_Free(H);
296
// Matrix_Free(U);
297
// min = (curend >= L->NbColumns) ? L->NbColumns : curend;
298
// if (rank == min || curRow >= curend)
299
// break;
300
// }
301
// Matrix_Free(A);
302
// }
303
// Matrix_Free(L);
304
// return;
305
// } /* RearrangeMatforSolveDio */
polylib.h
source
kernel
SolveDio.c
Generated by
1.9.4