source: git/Singular/LIB/signcond.lib @ d3b3ab

spielwiese
Last change on this file since d3b3ab was d3b3ab, checked in by Hans Schönemann <hannes@…>, 18 years ago
*gmg: new libs *hannes: examples fixed git-svn-id: file:///usr/local/Singular/svn/trunk@7991 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.9 KB
Line 
1// $Id: signcond.lib,v 1.2 2005-05-02 12:24:16 Singular Exp $
2// E. Tobis  12.Nov.2004
3// last change 16. Apr. 2005 (G.-M. Greuel)
4///////////////////////////////////////////////////////////////////////////////
5category="Symbolic-numerical solving"
6info="
7LIBRARY: signcond.lib Routines for computing realizable sign conditions
8AUTHOR:               Enrique A. Tobis, etobis@dc.uba.ar
9
10OVERVIEW:  Routines to determine the number of solutions of a multivariate
11           polynomial system which satisfy a given sign configuration.
12           References: Basu, Pollack, Roy, \"Algorithms in Real Algebraic
13           Geometry\", Springer, 2003.
14
15PROCEDURES:
16  signcnd(P,I)   The sign conditions realized the polynomials of P on a V(I)
17  psigncnd(P,l)  Pretty prints the output of signcnd (l)
18  firstoct(I)    The number of elements of V(I) with every coordinate > 0
19
20KEYWORDS: real roots,sign conditions
21";
22
23LIB "mrrcount.lib";
24LIB "linalg.lib";
25///////////////////////////////////////////////////////////////////////////////
26
27proc firstoct(ideal I)
28"USAGE:    firstoct(i); i ideal
29RETURN:   number: the number of points of V(i) lying in the first orthant
30ASSUME:   i is a Groebner basis
31SEE ALSO: signcnd
32EXAMPLE:  example firstoct; shows an example"
33{
34  ideal firstoctant;
35  int j;
36  list result;
37  int n;
38
39  if (isparam(I)) {
40    ERROR("This procedure cannot operate with parametric arguments");
41  }
42
43  for (j = nvars(basering);j > 0;j--) {
44    firstoctant = firstoctant + var(j);
45  }
46
47  result = signcnd(firstoctant,I);
48
49  list fst;
50  for (j = nvars(basering);j > 0;j--) {
51    fst[j] = 1;
52  }
53
54  n = isIn(fst,result[1]);
55
56  if (n != -1) {
57    return (result[2][n]);
58  } else {
59    return (0);
60  }
61}
62example
63{
64  echo = 2;
65  ring r = 0,(x,y),dp;
66  ideal i = (x-2)*(x+3)*x,y*(y-1);
67  firstoct(i);
68}
69///////////////////////////////////////////////////////////////////////////////
70
71proc signcnd(ideal P,ideal I)
72"USAGE:     signcnd(P,i); ideal P,i. i must be a grobner basis
73RETURN:    list: the sign conditions realized by the polynomials of P on V(I).
74           See the example for an explanation of the output.
75SEE ALSO:  firstoct
76EXAMPLE:   example signcnd; shows an example"
77{
78  ideal B;
79
80  // Cumulative stuff
81  matrix M;
82  matrix SQs;
83  matrix C;
84  list Signs;
85  list Exponents;
86
87  // Used to store the precalculated SQs
88  list SQvalues;
89  list SQpositions;
90
91  int i;
92
93  // Variables for each step
94  matrix Mi;
95  matrix M3x3[3][3];
96  matrix M3x3inv[3][3]; // Constant matrices
97  matrix c[3][1];
98  matrix sq[3][1];
99  int j;
100  list exponentsi;
101  list signi;
102  int numberOfNonZero;
103
104  if (isparam(P) || isparam(I)) {
105    ERROR("This procedure cannot operate with parametric arguments");
106  }
107
108  M3x3 = matrix(1,3,3);
109  M3x3 = 1,1,1,0,1,-1,0,1,1; // The 3x3 matrix
110  M3x3inv = inverse(M3x3);
111
112  // First, we compute sturmquery(1,V(I))
113  I = groebner(I);
114  B = qbase(I);
115  sq[1,1] = sturmquery(1,B,I); // Number of real roots in V(I)
116  SQvalues = SQvalues + list(sq[1,1]);
117  SQpositions = SQpositions + list(1);
118
119  // We initialize the cumulative variables
120  M = matrix(1,1,1);
121  Exponents = list(list());
122  Signs = list(list());
123
124  i = 1;
125
126  while (i <= size(P)) { // for each poly in P
127
128    sq[2,1] = sturmquery(P[i],B,I);
129    sq[3,1] = sturmquery(P[i]^2,B,I);
130
131
132    c = M3x3inv*sq;
133
134    // We have to eliminate the 0 elements in c
135    exponentsi = list();
136    signi = list();
137
138
139    // We determine the list of signs which correspond to a nonzero
140    // number of roots
141    numberOfNonZero = 3;
142
143    if (c[1,1] != 0) {
144      signi = list(0);
145    } else {
146      numberOfNonZero--;
147    }
148
149    if (c[2,1] != 0) {
150      signi = signi + list(1);
151    } else {
152      numberOfNonZero--;
153    }
154
155    if (c[3,1] != 0) {
156      signi = signi + list(-1);
157    } else {
158      numberOfNonZero--;
159    }
160
161    // We now determine the little matrix we'll work with,
162    // and the list of exponents
163    if (numberOfNonZero == 3) {
164      Mi = M3x3;
165      exponentsi = list(0,1,2);
166    } else {if (numberOfNonZero == 2) {
167      Mi = matrix(1,2,2);
168      Mi[1,2] = 1;
169      if (c[1,1] != 0 && c[2,1] != 0) { // 0,1
170        Mi[2,1] = 0;
171        Mi[2,2] = 1;
172      } else {if (c[1,1] != 0 && c[3,1] != 0) { // 0,-1
173        Mi[2,1] = 0;
174        Mi[2,2] = -1;
175      } else { // 1,-1
176        Mi[2,1] = 1;
177        Mi[2,2] = -1;
178      }}
179      exponentsi = list(0,1);
180    } else {if (numberOfNonZero == 1) {
181      Mi = matrix(1,1,1);
182      exponentsi = list(0);
183    }}}
184
185    // We store the Sturm Queries we'll need later
186    if (numberOfNonZero == 2) {
187      SQvalues = SQvalues + list(sq[2,1]);
188      SQpositions = SQpositions + list(size(Exponents)+1);
189    } else {if (numberOfNonZero == 3) {
190      SQvalues = SQvalues + list(sq[2,1],sq[3,1]);
191      SQpositions = SQpositions + list(size(Exponents)+1,size(Exponents)*2+1);
192    }}
193
194    // Now, we accumulate information
195    M = tensor(Mi,M);
196    Signs = expprod(Signs,signi);
197    Exponents = expprod(Exponents,exponentsi);
198
199    i++;
200  }
201
202  // At this point, we have the cumulative matrix,
203  // the vector of exponents and the matching sign conditions.
204  // We have to solve the big linear system to finish.
205
206  M = inverse(M);
207
208  // We have to compute the constants vector (the Sturm Queries)
209
210  SQs = matrix(1,size(Exponents),1);
211
212  j = 1; // We'll iterate over the presaved SQs
213
214  for (i = 1;i <= size(Exponents);i++) {
215    if (j <= size(SQvalues)) {
216      if (SQpositions[j] == i) {
217        SQs[i,1] = SQvalues[j];
218        j++;
219      } else {
220      SQs[i,1] = sturmquery(evalp(Exponents[i],P),B,I);
221      }
222    } else {
223        SQs[i,1] = sturmquery(evalp(Exponents[i],P),B,I);
224    }
225  }
226
227  C = M*SQs;
228
229  list result;
230  result[2] = list();
231  result[1] = list();
232
233  // We have to filter the 0 elements of C
234  for (i = 1;i <= size(Signs);i++) {
235    if (C[i,1] != 0) {
236      result[1] = result[1] + list(Signs[i]);
237      result[2] = result[2] + list(C[i,1]);
238    }
239  }
240
241  return (result);
242}
243example
244{
245  echo = 2;
246  ring r = 0,(x,y),dp;
247  ideal i = (x-2)*(x+3)*x,y*(y-1);
248  ideal P = x,y;
249  list l = signcnd(P,i);
250  echo = 0;
251
252  print("The output of signcnd is a list of two lists. Both lists have the
253same");
254  print("length. That length is the number of sign conditions realized by the");
255  print ("polynomials of P on the set V(i). In this example, that number
256is");
257  print("print(size(l[1]));");
258  print(size(l[1]));
259  print("Each element of the first list indicates a sign condition of the");
260  print("polynomials of P. For example,");
261  print("print(l[1][2]);");
262  print(l[1][2]);
263  print("means P[1] > 0,P[2] = 0");
264  print("Each element of the second list indicates how many elements of V(I)");
265  print("give rise to the sign condition expressed by the same position on the");
266  print("first list. For example");
267  print("print(l[2][2]);");
268  print(l[2][2]);
269  print("indicates that exactly 1 elemnt of V(I) gives rise to the condition");
270  print("P[1] > 0,P[2] = 0.");
271  print("The procedure psigncnd performs some pretty printing on this output.");
272}
273///////////////////////////////////////////////////////////////////////////////
274
275proc psigncnd(ideal P,list l)
276"USAGE:     psigncnd(P,I); ideal P, list l
277RETURN:    list: a formatted version of l
278SEE ALSO:  signcnd
279EXAMPLE:   example psigncnd; shows an example"
280{
281  string s;
282  int n = size(l[1]);
283  int i;
284
285  for (i = 1;i <= n;i++) {
286    s = s + string(l[2][i]) + " elements of V(I) satisfy " + psign(P,l[1][i])
287        + sprintf("%n",12);
288  }
289  return(s);
290}
291example
292{
293  echo = 2;
294  ring r = 0,(x,y),dp;
295  ideal i = (x-2)*(x+3)*x,(y-1)*(y+2)*(y+4);
296  ideal P = x,y;
297  list l = signcnd(P,i);
298  psigncnd(P,l);
299}
300///////////////////////////////////////////////////////////////////////////////
301
302static proc psign(ideal P,list s)
303{
304  int i;
305  int n = size(P);
306  string output;
307
308  output = "{P[1]";
309
310  if (s[1] == -1) {
311    output = output + " < 0";
312  };
313  if (s[1] == 0) {
314    output = output + " = 0";
315  };
316  if (s[1] == 1) {
317    output = output + " > 0";
318  };
319
320  for (i = 2;i <= n;i++) {
321    output = output + ",";
322    output = output + "P[" + string(i) + "]";
323    if (s[i] == -1) {
324      output = output + " < 0";
325    };
326    if (s[i] == 0) {
327      output = output + " = 0";
328    };
329    if (s[i] == 1) {
330      output = output + " > 0";
331    };
332
333  }
334  output = output + "}";
335  return (output);
336}
337///////////////////////////////////////////////////////////////////////////////
338
339static proc isIn(list a,list b) //a is a list. b is a list of lists
340{
341  int i,j;
342  int found;
343
344  found = 0;
345  i = 1;
346  while (i <= size(b) && !found) {
347    j = 1;
348    found = 1;
349    if (size(a) != size(b[i])) {
350      found = 0;
351    } else {
352      while(j <= size(a)) {
353        found = found && a[j] == b[i][j];
354        j++;
355      }
356    }
357    i++;
358  }
359
360  if (found) {
361    return (i-1);
362  } else {
363    return (-1);
364  }
365}
366///////////////////////////////////////////////////////////////////////////////
367
368static proc expprod(list A,list B) // Computes the product of the list of lists A and the list B.
369{
370  int i,j;
371  list result;
372  int la,lb;
373
374  if (size(A) == 0) {
375    A = list(list());
376  }
377
378  la = size(A);
379  lb = size(B);
380
381  result[la*lb] = 0;
382
383
384  for (i = 0;i < lb;i++) {
385    for (j = 0;j < la;j++) {
386      result[i*la+j+1] = A[j+1] + list(B[i+1]);
387    }
388  }
389
390  return (result);
391}
392///////////////////////////////////////////////////////////////////////////////
393
394static proc initlist(int n) // Returns an n-element list of 0s.
395{
396  list l;
397  int i;
398  l[n] = 0;
399  for (i = 1;i < n;i++) {
400    l[i] = 0;
401  }
402  return(l);
403}
404///////////////////////////////////////////////////////////////////////////////
405
406static proc evalp(list exp,ideal P) // Elevates each polynomial in P to the appropriate
407{
408  int i;
409  int n;
410  poly result;
411
412  n = size(exp);
413  result = 1;
414
415  for (i = 1;i <= n; i++) {
416    result = result * (P[i]^exp[i]);
417  }
418  return (result);
419}
420///////////////////////////////////////////////////////////////////////////////
421
422static proc incexp(list exp)
423{
424  int k;
425
426  k = 1;
427
428  while (exp[k] == 2) { // We assume exp is not the last exponent (i.e. 2,...,2)
429    exp[k] = 0;
430    k++;
431  }
432
433  // exp[k] < 2
434  exp[k] = exp[k] + 1;
435
436  return (exp);
437}
438///////////////////////////////////////////////////////////////////////////////
439
Note: See TracBrowser for help on using the repository browser.