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 */