source: git/Singular/LIB/interval.lib @ ef7108

fieker-DuValspielwiese
Last change on this file since ef7108 was ef7108, checked in by Hans Schoenemann <hannes@…>, 3 years ago
libs: version
  • Property mode set to 100644
File size: 30.7 KB
Line 
1///////////////////////////////////////////////////////////////////
2version="version interval.lib 4.2.0.1 Dec_2020 ";
3info="
4LIBRARY:    interval.lib implements interval arithmetic on polynomials
5AUTHORS:    Dominik Bendle
6            Clara Petroll
7
8OVERLOADS:
9// intervals
10[           intervalGet         indexing
11=           intervalAssign      assigning
12==          intervalEqual       equality
13print       intervalPrint       pretty print
14+           intervalAdd         addition
15-           intervalNegate      negation (unary)
16-           intervalSubtract    subtraction
17*           intervalMultiply    multiplication
18/           intervalDivide      division
19^           intervalPotentiate  potentiation
20
21// boxes
22=           boxSet              assigning
23[           boxGet              indexing
24==          boxEqual            equality
25print       boxPrint            printing
26-           boxSubtract         subraction
27intersect   boxIntersect        intersection
28
29// intervalmatrices
30[           ivmatGet            indexing
31print       ivmatPrint          printing
32nrows       ivmatNrows          number of rows
33ncols       ivmatNcols          number of columns
34det         determinant         determinant
35*           ivmatMultiply       matrix multiplication
36
37PROCEDURES:
38length2()               length/size if interval
39bounds2()               construct interval for given bounds.
40
41intervalmatrixInit()    initialises an interval matrix
42unitMatrix2()           unit matrix
43applyMatrix()           apply matrix to box
44ivmatGaussian2()        Gaussian elimination on matrices
45
46evalPolyAtBox2()        evaluate interval extension of polynomial
47exclusionTest()         first version of our exclusion test
48
49SEE ALSO: rootisolation_lib
50";
51///////////////////////////////////////////////////////////////////
52
53static proc mod_init()
54{
55    newstruct("interval", "list l");
56    system("install", "interval", "[",      intervalGet,        2);
57    system("install", "interval", "=",      intervalAssign,     1);
58    system("install", "interval", "==",     intervalEqual,      2);
59    system("install", "interval", "string", intervalString,     1);
60    system("install", "interval", "print",  intervalPrint,      1);
61    system("install", "interval", "+",      intervalAdd,        2);
62    system("install", "interval", "-",      intervalNegate,     1);
63    system("install", "interval", "-",      intervalSubtract,   2);
64    system("install", "interval", "*",      intervalMultiply,   2);
65    system("install", "interval", "/",      intervalDivide,     2);
66    system("install", "interval", "^",      intervalPotentiate, 2);
67
68    newstruct("box", "list intervals");
69    system("install", "box", "=",           boxAssign,      1);
70    system("install", "box", "[",           boxGet,         2);
71    system("install", "box", "==",          boxEqual,       2);
72    system("install", "box", "print",       boxPrint,       1);
73    system("install", "box", "-",           boxSubtract,    2);
74    system("install", "box", "intersect",   boxIntersect,   4);
75
76    newstruct("ivmat", "list rows");
77    system("install", "ivmat", "print", ivmatPrint,             1);
78    system("install", "ivmat", "[",     ivmatGet,               2);
79    system("install", "ivmat", "nrows", ivmatNrows,             1);
80    system("install", "ivmat", "ncols", ivmatNcols,             1);
81    system("install", "ivmat", "det",   determinant,            1);
82    system("install", "ivmat", "*",     ivmatMultiplyGeneral,   2);
83}
84
85///////////////////////////////////////////////////////////////////
86
87// INTERVAL FUNCTIONS
88
89proc bounds2(number a, number b)
90"USAGE: bounds2(a, b), a, b number
91RETURN: interval [a, b]."
92{
93    // depends on inplementation (TODO)
94    interval OUT;
95    // bounds need not be supplied in order
96    if (a < b) {
97        OUT.l = list(a, b);
98    } else {
99        OUT.l = list(b, a);
100    }
101
102    return(OUT);
103}
104
105proc intervalAssign(def input)
106"USAGE: I = input, input number, int, ...
107RETURN: interval I
108EXAMPLE: assigning intervals with ="
109{
110    if(typeof(input) == "number") { return(bounds2(input, input)); }
111    if(typeof(input) == "int"   ) { return(intervalAssign(number(input)));  }
112
113    ERROR("input not supported.");
114}
115example
116{
117    echo = 2;
118    ring R = 0,x,lp;
119
120    interval I = 1; I;
121    I = 3/7;        I;
122}
123
124proc intervalGet(interval I, int n)
125"USAGE: I[n], interval I, int n
126RETURN: get lower or upper bound of interval"
127{
128    // depends on implementation (TODO)
129    if (n == 1 || n == 2) {
130        return(I.l[n]);
131    }
132    ERROR("index wrong.");
133}
134example
135{
136    echo = 2;
137    ring R = 0,x,lp;
138    interval I = bounds2(0/1, 1/1);
139
140    I[1];
141    I[2];
142}
143
144proc intervalEqual(interval I, interval J)
145"USAGE: I == J, I, J interval
146RETURN: 1 if bounds are equal, 0 else
147EXAMPLE: test intervals for equality"
148{
149    return(I[1] == J[1] && I[2] == J[2]);
150}
151example
152{
153    echo = 2;
154    ring R = 0,x,lp;
155
156    interval I = bounds2(0, 1);
157    interval J = bounds2(0, 1);
158    interval K = bounds2(0, 2);
159
160    I == J;
161    I == K;
162}
163
164proc length2(interval I)
165"USAGE: length2(I), I interval
166RETURN: length/size in measure sense
167EXAMPLE: compute length of intervals"
168{
169    return(I[2] - I[1]);
170}
171example
172{
173    echo = 2;
174    ring R = 0,x,lp;
175
176    interval I = bounds2(0, 1);    I;
177    length2(I);
178
179    I = bounds2(-1/2, 3/7);        I;
180    length2(I);
181}
182
183proc intervalString(interval I)
184"USAGE: string(I), I interval
185RETURN: string representation of I
186EXAMPLE: convert interval to string"
187{
188    return(string("[", I[1], ", ", I[2], "]"));
189}
190example
191{
192    echo = 2;
193    ring R = 0,x,lp;
194
195    interval I = bounds2(0, 3/2);
196    string("I = ", I, "!");
197}
198
199proc intervalPrint(interval I)
200"USAGE: I;, I interval
201EXAMPLE: prints interval in readable format"
202{
203    string(I);
204}
205example
206{
207    echo = 2;
208    ring R = 0,x,lp;
209
210    interval I = bounds2(1/5, 7/3);
211    I;
212}
213
214proc intervalAdd(interval I, interval J)
215"USAGE: I + J, I, J interval
216RETURN: I+J
217EXAMPLE: adds two intervalls"
218{
219    // independent of implementation
220    return(bounds2(I[1] + J[1], I[2] + J[2]));
221}
222example
223{
224    echo = 2;
225    ring R = 0,x,lp;
226    interval I = bounds2(0/1, 1/2);    I;
227    interval J = bounds2(2/3, 1/1);    J;
228
229    J = I+J;                                    J;
230}
231
232proc intervalNegate(interval I)
233"USAGE: (-I), I interval
234RETURN: -I
235EXAMPLE: computes negation of interval"
236{
237    return(bounds2(-I[2], -I[1]));
238}
239example
240{
241    echo = 2;
242    ring R = 0,x,lp;
243    interval I = bounds2(1/3, 1/2);    I;
244    I = -I;                                     I;
245}
246
247proc intervalSubtract(interval I, interval J)
248"USAGE: I - J, I, J, interval,
249RETURN: I-J
250EXAMPLE: subtracts two intervals"
251{
252    return(I + (-J));
253}
254example
255{
256    echo = 2;
257    ring R = 0,x,lp;
258    interval I = bounds2(3/2, 14/5);   I;
259    interval J = bounds2(1/7, 2/3);    J;
260
261    J = I - J;                                  J;
262}
263
264proc intervalMultiply(interval I, interval J)
265"USAGE: I * J; I, J interval
266RETURN: product I*J
267EXAMPLE: multiplies intervals (and scalars)"
268{
269    number lo = min(I[1] * J[1], I[1] * J[2], I[2] * J[1], I[2]*J[2]);
270    number up = max(I[1] * J[1], I[1] * J[2], I[2] * J[1], I[2]*J[2]);
271
272    return(bounds2(lo, up));
273}
274example
275{
276    echo = 2;
277    ring R = 0,x,lp;
278
279    interval I = bounds2(1/3, 3/1);    I;
280    interval J = bounds2(-2/5, 1/7);   J;
281
282    J = I * J;                                  J;
283
284    J = 1/2 * J;                                J;
285}
286
287proc intervalDivide(interval I, interval J)
288"USAGE: I/J, I, J, interval
289RETURN: I/J (division)
290EXAMPLE: divide intervals, demonstrate zero case"
291{
292    if (J[1]*J[2] > 0) {
293        interval Jinv = bounds2(1/J[2], 1/J[1]);
294        return(I * Jinv);
295    } else {
296        ERROR("Divisor contains zero.");
297    }
298}
299example
300{
301    echo = 2;
302    ring R = 0,x,lp;
303
304    interval I = bounds2(1/1, 3/1);    I;
305    interval J = bounds2(2/3, 3/2);    J;
306
307    I/J;
308    J/I;
309
310    I = bounds2(-2/1, 1/2);            I;
311
312    I/J;
313    J/I;
314}
315
316proc intervalPotentiate(interval I, int n)
317"USAGE: I^n, interval I, int n
318RETURN: I^n with stricter bounds than naive multiplication
319EXAMPLE: potentiates an interval"
320{
321    if (n % 2 == 1 || I[1]*I[2] >= 0 || n == 0) {
322        return(bounds2(I[1]^n, I[2]^n));
323    } else {
324        return(bounds2(0, max(I[1]^n, I[2]^n)));
325    }
326}
327example
328{
329    echo = 2;
330    ring R = 0,x,lp;
331
332    interval I = bounds2(-1/3, 3/2);   I;
333    I^1;
334    I^2;
335    I^3;
336    I^4;
337
338    interval J = bounds2(1/5, 2/5);    J;
339    J^1;
340    J^2;
341    J^3;
342    J^4;
343}
344
345///////////////////////////////////////////////////////////////////
346
347// BOX FUNCTIONS
348
349proc boxAssign(list intervals)
350"USAGE: B = I1,I2,.., I1, I2 interval
351RETURN: Box consisting of given intervals honoring amount of ring variables
352EXAMPLE: construct box from intervals"
353{
354    int v = nvars(basering);
355    int s = size(intervals);
356    box B;
357
358    // make sure box has same number of intervals as ring variables
359    interval z = 0;
360    for (int i = 1; i <= v; i++) {
361        if (i <= s) {
362            if (typeof(intervals[i]) == "interval") {
363                B.intervals[i] = intervals[i];
364            } else {
365                ERROR("Non-interval given.");
366            }
367        } else {
368            B.intervals[i] = z;
369        }
370    }
371
372    return(B);
373}
374example
375{
376    echo = 2;
377
378    ring R = 0,x,lp;
379    interval I = bounds2(1, 2);
380    box B = list(I); B;
381
382    ring S = 0,x(1..15),lp;
383    I = bounds2(1/2, 2/3);
384    B = list(I, I^2, I^3); B;
385}
386
387proc boxSet(box B, int n, interval I)
388"USAGE: boxSet(B, n, I), B box, n int, I interval
389RETURN: B where B[i] == I
390EXAMPLE: modify box"
391{
392    if (n >= 1 && n <= nvars(basering)) {
393        B.intervals[n] = I;
394    }
395    return(B);
396}
397example
398{
399    echo = 2;
400    ring R = 0,x(1..3),lp;
401
402    interval I = 1;
403    box B = list(I); B;
404    B = boxSet(B, 3, bounds2(1, 2));   B;
405}
406
407proc boxPrint(box B)
408"USAGE: B;, B box,
409RETURN: pretty output
410EXAMPLE: output a box"
411{
412    string(B.intervals);
413}
414example
415{
416    echo = 2;
417    ring R = 0,x(1..4),lp;
418
419    interval I = bounds2(1, 2);
420    box B = list(I,I+1,I+2,I+4);  B;
421    B = list(I,I^2);              B;
422}
423
424proc boxGet(box B, int n)
425"USAGE: B[n], B box, n int
426RETURN: n-th interval of box
427EXAMPLE: returns interval"
428{
429    return(B.intervals[n]);
430}
431example
432{
433    echo = 2;
434    ring R = 0,x(1..5),lp;
435
436    interval I = bounds2(1/3, 5);
437    box B = list(I, I/I, I+I, I-1/I, I^4);
438
439    B;
440    B[3];
441}
442
443proc boxEqual(box B, box C)
444"USAGE: B == C, B, C box
445RETURN: 1 if all bounds are equal, 0 else
446EXAMPLE: test boxes for equality"
447{
448    int n = nvars(basering);
449    for (int i = 1; i <= n; i++) {
450        if (!(B[i] == C[i])) { return(0); }
451    }
452    return(1);
453}
454example
455{
456    echo = 2;
457    ring R = 0,x,lp;
458
459    interval I = bounds2(0,1);
460    interval J = bounds2(1,2);
461    box B = list(I, J);
462    box C = list(J, I);
463    box D = list(I, J);
464
465    B == C;
466    B == D;
467}
468
469proc boxSubtract(box B, box C)
470"USAGE: B-C, B, C box
471RETURN: componentwise subtraction"
472{
473    int n = nvars(basering);
474    box OUT;
475    for (int i = 1; i <= n; i++) { OUT.intervals[i] = B[i] - C[i]; };
476    return(OUT);
477}
478
479proc lengthBox(box B)
480"USAGE: lengthBox(B), B box
481RETURN: length/size in measure sense
482EXAMPLE: compute length of boxes"
483{
484    number maximum = 0;
485    int n = nvars(basering);
486
487    for (int i=1; i <= n; i++) { maximum = max(maximum, length2(B[i])); }
488
489    return(maximum);
490}
491example
492{
493    echo = 2;
494    ring R = 0,(x,y),lp;
495
496    interval I = bounds2(0, 1);    I;
497    interval J = bounds2(1,3);     J;
498
499    box B = list(I, J);
500
501    lengthBox(B);
502}
503
504proc boxCenter(box M)
505"USAGE: boxCenter(M), M ivmat
506RETURN: box containing center elements of M
507EXAMPLE: compute center box"
508{
509    int n = nvars(basering);
510
511    box C;
512    int i;
513
514    for (i = 1; i <= n; i++) {
515        C.intervals[i] = interval((M[i][1] + M[i][2])/2);
516    }
517
518    return(C);
519}
520example
521{
522    echo = 2;
523    ring R = 0,(x,y),lp;
524    interval I1 = bounds2(1/3, 7/4);
525    interval I2 = bounds2(0,2);
526
527    box B= list(I1,I2);
528
529    boxCenter(B);
530}
531
532proc splitBox(box B, ideal I)
533"USAGE: splitBox(box, I), box list of intervals, I ideal
534RETURN: new list of smaller boxes, such that intersection of borders does not contain zeros of I
535EXAMPLE: split two-dimensional interval into two"
536{
537    // at first split only at largest interval
538    int imax = 1;
539    int n = nvars(basering);
540
541    for (int i = 2; i <= n; i++) {
542        if (length2(B[i]) > length2(B[imax])) { imax = i; }
543    }
544
545    number ratio = 1/2;
546    number mean;
547    box intersection;
548    ideal Inew;
549
550    while(1) {
551        mean = ratio * B[imax][1] + (1 - ratio) * B[imax][2];
552
553        intersection = evalIdealAtBox(I, boxSet(B, imax, mean));
554        for (i = 1; i <= n; i++) {
555            // check if any interval does not contain zero
556            if (intersection[i][1]*intersection[i][2] > 0) { break; }
557        }
558
559        Inew = I + (var(imax) - mean);
560        // check if groebner basis is trivial
561        if (std(Inew) == 1) { break; }
562
563        // else there must?/might be a zero on the intersection,
564        // so decrease ratio slightly
565        ratio = ratio * 9/10;
566
567        // make sure algorithm terminates, after taking too many steps
568        if ( ratio < 1/100 ) { print("splitBox took too long"); break; }
569    }
570
571    // now split boxes
572    box boxLeft  = boxSet(B, imax, bounds2(B[imax][1], mean));
573    box boxRight = boxSet(B, imax, bounds2(mean, B[imax][2]));
574
575    return(list(boxLeft, boxRight));
576}
577example
578{
579    echo = 2;
580    ring R = 0,(x,y),lp;
581
582    box B = list(bounds2(0,1),
583                 bounds2(0,2));
584
585    B;
586    splitBox(B,1);
587}
588
589proc boxIntersect
590"USAGE: intersect(B1, B2, ...) Bi box
591RETURN: intersection B of the boxes Bi or -1 if the intersection is empty
592EXAMPLE: intersect boxes"
593{
594    int ninput = size(#);
595    if (ninput == 0) { return(-1) };
596
597    int n = nvars(basering);
598    int i, j;
599
600    for (i = 1; i <= ninput; i++) {
601        if (typeof(#[i]) <> "box") {
602            ERROR("Need to intersect boxes.");
603        }
604    }
605
606    box OUT;
607    number lower, upper;
608
609    for (i = 1; i <= n; i++) {
610        lower = #[1][i][1];
611        upper = #[1][i][2];
612        for (j = 2; j <= ninput; j ++) {
613            lower = max(lower, #[j][i][1]);
614            upper = min(upper, #[j][i][2]);
615        }
616
617        if (upper < lower) { return(-1); }
618
619        OUT.intervals[i] = bounds2(lower, upper);
620    }
621
622    return(OUT);
623}
624example
625{
626    echo = 2;
627    ring R = 0,(x,y),lp;
628
629    interval I = bounds2(0,1);
630    interval J = bounds2(1/2, 3/2);
631
632    box B = list(I, J);
633    box C = list(J, I);
634    box D = list(I, I + 2);
635
636    intersect(B, C);
637    intersect(C, D);
638}
639
640proc boxIsinterior(box A, box B)
641"USAGE: boxIsinterior(A, B), A, B box
642RETURN: 1 if A contained in int(B) else 0
643EXAMPLE: boxIsinterior"
644{
645    int n = nvars(basering);
646    for (int i=1; i<= n; i++) {
647        if (A[i][1] <= B[i][1] || A[i][2] >= B[i][2]){return(0);}
648    }
649    return(1);
650}
651example
652{
653    echo=2;
654    ring R=0,(x,y,z), lp;
655    box A=list(bounds2(1,2), bounds2(2,3), bounds2(1/2,7/2)); A;
656    box B1=list(bounds2(0,5/2), bounds2(1,4), bounds2(0,9)); B1;
657    boxIsinterior(A,B1);
658
659    box B2=list(bounds2(2,4), bounds2(1,4), bounds2(0,9)); B2;
660    boxIsinterior(A,B2);
661}
662
663///////////////////////////////////////////////////////////////////
664
665// MATRIX FUNCTIONS
666
667proc intervalmatrixInit(numrows, numcols)
668"USAGE: intervalmatrixInit(m, n) m, n int
669RETURN: mxn matrix of [0,0]-intervals
670EXAMPLE: initialises an interval matrix"
671{
672    ivmat A;
673    A.rows = list();
674    int i, j;
675    interval z = 0;
676
677    for (i = 1; i <= numrows; i++) {
678        A.rows[i] = list();
679        for (j=1; j <= numcols; j++) {
680            A.rows[i][j] = z;
681        }
682    }
683
684    return(A);
685}
686example
687{
688    echo = 2;
689    ring R = 0,x(1..5),lp;
690
691    ivmat A = intervalmatrixInit(4, 5); A;
692}
693
694proc ivmatNrows(ivmat M)
695"USAGE: nrows(M), M ivmat
696RETURN: number of rows of M
697EXAMPLE: calculate number of rows"
698{
699    return(size(M.rows));
700}
701example
702{
703    echo = 2;
704    ring R = 0,x,lp;
705
706    ivmat A = intervalmatrixInit(2,3);
707    nrows(A);
708}
709
710proc ivmatNcols(ivmat M)
711"USAGE: ncols(M), M ivmat
712RETURN: number of columns of M
713EXAMPLE: calculate number of columns"
714{
715    return(size(M.rows[1]));
716}
717example
718{
719    echo = 2;
720    ring R = 0,x,lp;
721
722    ivmat A = intervalmatrixInit(2,3);
723    ncols(A);
724}
725
726proc ivmatAssign(int m, int n, list #)
727"USAGE: ivmatAssign(m, n, L), m, n int, L list of intervals
728RETURN: interval matrix containing intervals L in row major order
729EXAMPLE: builds matrix from intervals"
730{
731    list intervals;
732    if (size(#) == 1 && typeof(#[1]) == "list") { intervals = #[1]; }
733    else                                        { intervals = #;    }
734
735    int ivsize = size(intervals);
736    int i, j;
737    int counter = 1;
738    ivmat A = intervalmatrixInit(m, n);
739
740    for (i = 1; i <= m; i++) {
741        for (j = 1; j <= n; j++) {
742            if (counter <= ivsize) {
743                A.rows[i][j] = intervals[counter];
744                counter++;
745            }
746        }
747    }
748
749    return(A);
750}
751example
752{
753    echo = 2;
754    ring R = 0,(x,y),lp;
755
756    interval I = bounds2(1, 2);
757    ivmat A = ivmatAssign(2, 2, I, I^2, I/I, -I);
758    A;
759}
760
761proc ivmatPrint(ivmat A)
762"USAGE: A; A ivmat
763RETURN: nothing
764EXAMPLE: prints a matrix"
765{
766    int m = nrows(A);
767    for (int i = 1; i <= m; i++) {
768        string(A.rows[i]);
769    }
770}
771example
772{
773    example ivmatAssign;
774}
775
776proc ivmatGet(ivmat A, int i)
777"USAGE: A[i], A ivmat, i int
778RETURN: list A[i] of i-th row of A
779EXAMPLE: get single interals of matrix"
780{
781    return(A.rows[i]);
782}
783example
784{
785    echo = 2;
786    ring R = 0,x,lp;
787
788    ivmat A = ivmatAssign(2, 2, bounds2(1, 2));
789    A[1][1];
790    A[1][2];
791}
792
793proc ivmatSet(ivmat A, int i, int j, interval I)
794"USAGE: ivmatSet(A, i, j, I), A ivmat, i, j, int, I interval
795RETURN: ivmat A where A[i][j] == I
796EXAMPLE: assign values of A"
797{
798    A.rows[i][j] = I;
799    return(A);
800}
801example
802{
803    echo = 2;
804    ring R = 0,x,lp;
805    ivmat A = intervalmatrixInit(2,2);             A;
806    A = ivmatSet(A, 1, 2, bounds2(1, 2));  A;
807}
808
809proc diagMatrix(int n, interval I)
810"USAGE: diagMatrix(n, I), n int, I interval
811RETURN: diagonal nxn-matrix E where E[i][i] == I for all 1 <= i <= n
812EXAMPLE: create diagonal matrix"
813{
814    ivmat E = intervalmatrixInit(n, n);
815    for (int i = 1; i <= n; i++) {
816        E.rows[i][i] = I;
817    }
818    return(E);
819}
820example
821{
822    echo = 2;
823    ring R = 0,x,lp;
824    ivmat A = diagMatrix(2, bounds2(1, 2)); A;
825}
826
827proc unitMatrix2(int n)
828"USAGE: unitMatrix2(n)
829RETURN: nxn unit matrix
830EXAMPLE: create unit matrix"
831{
832    return(diagMatrix(n, 1));
833}
834example
835{
836    echo = 2;
837    ring R = 0,x,lp;
838
839    ivmat E = unitMatrix2(4); E;
840}
841
842proc determinant(ivmat A)
843"USAGE: det(A), A ivmat
844RETURN: determinant calculated by standard interval arithmetic
845EXAMPLE: calculates a determinant"
846{
847    int n = ncols(A);
848    if (n == 1) { return(A[1][1]); }
849
850    interval I = 0;
851    for (int i = 1; i <= n; i++) {
852        I = I + A[1][i] * cofactor(A, 1, i);
853    }
854    return(I);
855}
856example
857{
858    echo = 2;
859    ring R = 0,x,lp;
860
861    ivmat E = unitMatrix2(3); E;
862    det(E);
863
864    E = diagMatrix(3, bounds2(2, 5/2)); E;
865    det(E);
866
867    interval I = bounds2(1/3, 4/3);
868    ivmat A = ivmatAssign(2, 2, I, I+1, I+2, I^2); A;
869    det(A);
870}
871
872proc cofactor(ivmat A, int i, int j)
873"USAGE: cofactor(A, i, j), A ivmat, i, j int
874RETURN: cofactor of A at position (i,j)
875EXAMPLE: compute cofactors"
876{
877    int n = ncols(A);
878    if (n == 1) { return(A[1][1]); }
879
880    ivmat M = intervalmatrixInit(n-1, n-1);
881
882    // create m-1 x n-1 submatrix (minor) without row i, column j
883    int k, l;
884    for (k = 1; k < n; k++) {
885        for (l = 1; l < n; l++) {
886            M.rows[k][l] = A[k + (k>=i)][l + (l>=j)];
887        }
888    }
889
890    return( (-1)^(i+j) * det(M) );
891}
892example
893{
894    echo = 2;
895    ring R = 0,x,lp;
896
897    interval I = bounds2(1, 2);
898    interval J = bounds2(2, 5/2);
899    interval z = 0;
900
901    ivmat A = ivmatAssign(2,2,I,z,z,J); A;
902
903    cofactor(A, 2, 1);
904}
905
906proc adjunct(ivmat A)
907"USAGE: adjuct(A), A ivmat
908RETURN: adjuct matrix i.e. transpose cofactor matrix
909EXAMPLE: compute adjunct matrix"
910{
911    int n = size(A[1]);
912    ivmat adj = intervalmatrixInit(n, n);
913
914    int i, j;
915    for (i = 1; i <= n; i++) {
916        for (j = 1; j <= n; j++) {
917            adj.rows[i][j] = cofactor(A, j, i);
918        }
919    }
920
921    return(adj);
922}
923example
924{
925    echo = 2;
926    ring R = 0,x,lp;
927
928    interval I = bounds2(1, 2);
929    interval J = bounds2(2, 5/2);
930    interval z = 0;
931
932    ivmat A = ivmatAssign(2,2,I,z,z,J); A;
933
934    adjunct(A);
935}
936
937proc ivmatCenter(ivmat M)
938"USAGE: ivmatCenter(M), M ivmat
939RETURN: martix containing center elements of M
940EXAMPLE: compute center matrix"
941{
942    int m = nrows(M);
943    int n = ncols(M);
944
945    matrix C[m][n];
946    int i, j;
947
948    for (i = 1; i <= m; i++) {
949        for (j = 1; j <= n; j++) {
950            C[i, j] = (M[i][j][1] + M[i][j][2])/2;
951        }
952    }
953
954    return(C);
955}
956example
957{
958    echo = 2;
959    ring R = 0,x,lp;
960
961    interval I = bounds2(1/3, 7/4);
962    ivmat M = diagMatrix(3, I);
963    M = ivmatSet(M, 3, 2, bounds2(1, 3/2)); M;
964
965    ivmatCenter(M);
966}
967
968proc ivmatRadius(ivmat M)
969"USAGE: ivmatRadius(M), M ivmat
970RETURN: martix containing radius elements of M
971EXAMPLE: compute radius matrix"
972{
973    int m = nrows(M);
974    int n = ncols(M);
975
976    matrix C[m][n];
977    int i, j;
978
979    for (i = 1; i <= m; i++) {
980        for (j = 1; j <= n; j++) {
981            C[i, j] = length2(M[i][j])/2;
982        }
983    }
984
985    return(C);
986}
987example
988{
989    echo = 2;
990    ring R = 0,x,lp;
991
992    interval I = bounds2(1/3, 7/4);
993    ivmat M = diagMatrix(3, I);
994    M = ivmatSet(M, 3, 2, bounds2(1, 3/2)); M;
995
996    ivmatRadius(M);
997}
998
999proc ivmatMultiply(ivmat A, ivmat B)
1000"USAGE: A*B, A, B ivmat
1001RETURN: matrix product of A and B
1002EXAMPLE: multiply matrices"
1003{
1004    int m = nrows(A);
1005    int n = ncols(B);
1006    int p = ncols(A);
1007
1008    if (p <> nrows(B)) { ERROR("Matrices have wrong dimensions!"); }
1009
1010    ivmat C = intervalmatrixInit(m, n);
1011    int i, j, k;
1012    interval I;
1013
1014    for (i = 1; i <= m; i++) {
1015        for (j = 1; j <= n; j++) {
1016            I = 0;
1017            for (k = 1; k <= p; k++) {
1018                I = I + A[i][k] * B[k][j];
1019            }
1020            C.rows[i][j] = I;
1021        }
1022    }
1023
1024    return(C);
1025}
1026example
1027{
1028    echo = 3;
1029    ring R = 0,x,lp;
1030
1031    interval I = bounds2(0, 1);
1032    ivmat E = intervalmatrixInit(3,3);
1033    for (int i = 1; i<=3; i++) { E = ivmatSet(E, i, i, I+i); } E;
1034
1035    interval z = 0;
1036    interval J1 = bounds2(1/3, 3/7);
1037    interval J2 = bounds2(2, 5/2);
1038    interval J3 = bounds2(6/7, 8/7);
1039    interval J4 = bounds2(1, 2);
1040
1041    ivmat A = ivmatAssign(3,3, J1, z, J2, J3, J3^2, z, z, J4, J2*J4); A;
1042
1043    E * A;
1044    A * E;
1045
1046    A * adjunct(A);
1047    det(A);
1048}
1049
1050proc ivmatGaussian2(ivmat A)
1051"USAGE: ivmatGaussian2(A) A ivmat
1052RETURN: 0 if A not invertible, 1,Ainv if A invertible
1053EXAMPLE: some matrix"
1054{
1055    int n = nrows(A);
1056    if (n <> ncols(A)) { ERROR("Matrix non-square"); }
1057
1058    ivmat Ainv = unitMatrix2(n);
1059    list tmp;
1060    interval TMP;
1061
1062    int i, j, pos;
1063    for (pos = 1; pos <= n; pos++) {
1064        i = pos;
1065
1066        // get non-zero interval on diagonal
1067        while(A[i][pos][1] * A[i][pos][2] <= 0) {
1068            i++;
1069            // if no non-zero intervals exist, then matrix must be singular
1070            if (i > n) { return(0); }
1071        }
1072        if (i <> pos) {
1073            tmp = A.rows[i];
1074            A.rows[i] = A.rows[pos];
1075            A.rows[pos] = tmp;
1076
1077            tmp = Ainv.rows[i];
1078            Ainv.rows[i] = Ainv.rows[pos];
1079            Ainv.rows[pos] = tmp;
1080        }
1081
1082        // pivot (pos,pos)
1083        TMP = A[pos][pos];
1084        A.rows[pos][pos] = interval(1);
1085
1086        for (j = 1; j <= n; j++) {
1087            if (pos <> j) { A.rows[pos][j] = A[pos][j]/TMP; }
1088            Ainv.rows[pos][j] = Ainv[pos][j]/TMP;
1089        }
1090
1091        // clear entries above and below
1092        for (i = 1; i <= n; i++) {
1093            if (i <> pos) {
1094                TMP = A[i][pos];
1095                A.rows[i][pos] = interval(0);
1096                for (j = 1; j <= n; j++) {
1097                    if (j <> pos) { A.rows[i][j] = A[i][j] - A[pos][j]*TMP; }
1098                    Ainv.rows[i][j] = Ainv[i][j] - Ainv[pos][j]*TMP;
1099                }
1100            }
1101        }
1102    }
1103    return(1, Ainv);
1104}
1105example
1106{
1107    echo = 2;
1108    ring R = 0,(x,y),lp;
1109
1110    ideal I = 2x2-xy+2y2-2,2x2-3xy+3y2-2;
1111    box B = list(bounds2(7/8, 9/8), bounds2(-1/10, 1/20));
1112
1113    ivmat J = evalJacobianAtBox (I, B); J;
1114
1115    list result = ivmatGaussian2(J);
1116    ivmat Jinv = result[2];
1117    Jinv;
1118
1119    Jinv * J;
1120
1121    ivmat Jadj = diagMatrix(2, 1/det(J)) * adjunct(J);
1122    Jadj;
1123
1124    Jadj * J;
1125}
1126
1127proc applyMatrix(ivmat A, box b)
1128"USAGE: A * b, A ivmat, b box
1129RETURN: A*b
1130EXAMPLE: apply matrix to box"
1131{
1132    int n = nvars(basering);
1133
1134    if (ncols(A) <> n || nrows(A) <> n) { ERROR("Matrix has wrong dimensions"); }
1135
1136    int i, j;
1137    box result;
1138    interval tmp;
1139
1140    for (i = 1; i <= n; i++) {
1141        tmp = 0;
1142        for (j = 1; j <= n; j++) {
1143            tmp = tmp + A[i][j] * b[j];
1144        }
1145        result.intervals[i] = tmp;
1146    }
1147
1148    return(result);
1149}
1150example
1151{
1152    echo = 3;
1153    ring R = 0,(x,y,z),lp;
1154
1155    ideal I = xyz3+z2y2+x,x4+y3+2z+3,xyz+1/2;
1156    interval J = bounds2(1/2, 3/2);
1157    box B = list(J,J,J);
1158
1159    ivmat A = evalJacobianAtBox(I, B); A;
1160    A*B;
1161
1162    unitMatrix2(3) * B;
1163
1164    diagMatrix(3, bounds2(0, 1)) * B;
1165}
1166
1167proc ivmatMultiplyGeneral(ivmat A, B)
1168"USAGE: A * B, A ivmat, B ivmat or box
1169RETURN: usual matrix product where box is a nx1 matrix
1170EXAMPLE: multiply matrices with matrices and boxes"
1171{
1172    if (typeof(B) == "ivmat") { return(ivmatMultiply(A, B)); }
1173    if (typeof(B) == "box")   { return(applyMatrix(A, B)); }
1174    ERROR("Type not supported.");
1175}
1176example
1177{
1178    example ivmatMultiply;
1179    example applyMatrix;
1180}
1181
1182///////////////////////////////////////////////////////////////////
1183
1184// POLYNOMIAL APPLICATIONS
1185
1186// naive (?) implementation
1187proc evalPolyAtBox2(poly f, box B)
1188"USAGE: evalPolyAtBox2(f, B), f poly, B box
1189RETURN: interval extension ff(intervals)
1190EXAMPLE: computes interval extension of polynomial f"
1191{
1192    int numvars = nvars(basering);
1193
1194    // neutral elemen of addition
1195    interval resultWhole = 0;
1196    interval resultMonom;
1197
1198    int i;
1199    number coeff;
1200    intvec exponent;
1201
1202    // handle each monomial separately
1203    while (f <> 0) {
1204        coeff = leadcoef(f);
1205        exponent = leadexp(f);
1206
1207        // neutral element of multiplication
1208        resultMonom = 1;
1209
1210        for (i = 1; i <= numvars; i++) {
1211            resultMonom = resultMonom * B[i] ^ exponent[i];
1212        }
1213
1214        resultWhole = resultWhole + coeff * resultMonom;
1215        f = f - lead(f);
1216    }
1217
1218    return(resultWhole);
1219}
1220example
1221{
1222    echo = 2;
1223    ring R = 0,x,lp;
1224    interval I1 = bounds2(0, 1); I1;
1225
1226    poly f = x3 + 4x + 3;
1227
1228    evalPolyAtBox2(f, list(I1));
1229
1230    ring S = 0,(x,y,z),lp;
1231    interval I2 = bounds2(0, 1);
1232    box B = list(I2, I2, I2);
1233
1234    poly f = xyz2 + 2x2 + (3/2)*y3x + z + 1;
1235
1236    evalPolyAtBox2(f, B);
1237}
1238
1239proc evalJacobianAtBox(ideal I, box B)
1240"USAGE: evalJacobianAtBox(I, B), I ideal B box
1241RETURN: jacobian matrix of I where polynomials are evaluated at the given box
1242EXAMPLE: evalate Jacobian at box"
1243{
1244    matrix J = jacob(I);
1245    int m = nrows(J);
1246    int n = ncols(J);
1247    ivmat M = intervalmatrixInit(m, n);
1248
1249    int i, j;
1250
1251    for (i = 1; i <= m; i++) {
1252        for (j = 1; j <=n ; j++) {
1253            M.rows[i][j] = evalPolyAtBox2(J[i,j], B);
1254        }
1255    }
1256    return(M);
1257}
1258example
1259{
1260    echo = 2;
1261    ring R = 0,(x,y),lp;
1262    ideal I = 2x2-xy+2y2-2, 2x2-3xy+3y2-2;
1263
1264    interval J = bounds2(-1,1);
1265    evalJacobianAtBox(I, list(J,J));
1266}
1267
1268proc testPolyBox(ideal I, box B)
1269"USAGE: testPolyBox(I, intervals) or testPolyBox(I, I1, I2, ..)
1270        I ideal, intervals list of intervals, I1, I2, .. intervals
1271RETURN: -1, if ideal has no zeros in given box, 1, if unique zero in given box
1272        0 if test is inconclusive
1273EXAMPLE: tests the above for intersection of ellipses."
1274{
1275    int numvars = nvars(basering);
1276    int i;
1277
1278    interval tmp;
1279
1280    for (i = 1; i <= ncols(I); i++) {
1281        tmp = evalPolyAtBox2(I[i], B);
1282        // check if 0 contained in every interval
1283        // return -1 if not
1284        if (tmp[1]*tmp[2] > 0) { return(-1, B); }
1285    }
1286
1287    if (ncols(I) == numvars) {
1288        // calculate center as box of intervals instead of numbers
1289        // so we may reuse other procedures
1290        box Bcenter = boxCenter(B);
1291
1292        ivmat J = evalJacobianAtBox(I, B);
1293        list inverse = ivmatGaussian2(J);
1294
1295        // only continue if J is invertible , i.e. J contains no singular matrix
1296        if (!inverse[1]) { return(0, B); }
1297        ivmat Jinverse = inverse[2];
1298
1299        // calculate Bcenter - f(B)^(-1)f(Bcenter)
1300        box fB = evalIdealAtBox(I, Bcenter);
1301        fB = Bcenter - (Jinverse * fB);
1302
1303        def Bint = intersect(B, fB);
1304
1305        // if intersection is emtpy Bint == -1
1306        if (typeof(Bint) == "int") { return(-1, B); }
1307        B = Bint;
1308
1309        // if equality holds, fB is contained in box B
1310        // by paper, fB contains unique solution
1311        if (fB == B) { return(1, B) };
1312    }
1313
1314    // no condition could be verified
1315    return(0, B);
1316}
1317example
1318{
1319    echo = 2;
1320    ring R = 0,(x,y),lp;
1321    ideal I = 2x2-xy+2y2-2, 2x2-3xy+3y2-2;
1322
1323    interval unit = bounds2(0, 1);
1324    // there may be common zeros in [0,1]x[0,1]
1325    testPolyBox(I, list(unit, unit));
1326
1327    // there are no common zeros in [0,0.5]x[0,0.5]
1328    testPolyBox(I, list(unit/2, unit/2));
1329}
1330
1331proc evalIdealAtBox(ideal I, box B)
1332"USAGE: evaluate ideal at list of intervals i.e. at a box
1333RETURN: list
1334EXAMPLE: evalIdealAtBox"
1335{
1336    list resu;
1337
1338    for (int j = 1; j <= size(I); j++) {
1339        resu[j]=evalPolyAtBox2(I[j], B);
1340    }
1341
1342    return(box(resu));
1343}
1344example
1345{
1346    echo = 2;
1347    ring R = 0,(x,y),lp;
1348    interval I1 = bounds2(0, 1); I1;
1349    interval I2 = bounds2(0, 1); I2;
1350
1351    poly f = xy2 + 2x2 + (3/2)*y3x  + 1;
1352    poly g = 3x2 + 2y;
1353
1354    ideal I = f,g;
1355    list intervals = I1,I2;
1356
1357    evalIdealAtBox(I,intervals);
1358}
1359
1360proc exclusionTest(ideal I, box start, number limitsize)
1361"USAGE: exclusion test for roots with interval arithmetic
1362RETURN: list of boxes
1363EXAMPLE: exclusionTest for intersection of two ellipses"
1364{
1365    //set of boxes smaller than size
1366    list B_size;
1367    //set of boxes which exactly contain one solution
1368    list B_star;
1369    //set of boxes initialised to input
1370    list B = list(start);
1371    //help set of boxes
1372    list B_prime;
1373
1374    int i;
1375    int zeroTest;
1376
1377    while (size(B) <> 0) {
1378        // B_prime is empty set
1379        B_prime = list();
1380
1381        for (i=1; i<=size(B); i++) {
1382            //case that maybe there is a root in the box
1383            zeroTest, B[i] = testPolyBox(I,B[i]);
1384
1385            // maybe refine boxes in Bstar in later steps
1386            if (zeroTest == 1) { B_star = insert(B_star, B[i]); };
1387            if (zeroTest == 0) {
1388                //case that box is smaller than the input limitsize
1389                if (lengthBox(B[i]) <= limitsize){
1390                    B_size = insert(B_size, B[i]);
1391                } else {
1392                    // else split the box and put the smaller boxes to B_prime
1393                    B_prime = B_prime + splitBox(B[i], I);
1394                }
1395            }
1396        }
1397
1398        // set B=B_prime
1399        B = B_prime;
1400    }
1401    return(B_size, B_star);
1402}
1403example
1404{
1405    echo = 2;
1406
1407    ring R = 0,(x,y),lp;
1408    ideal I = 2x2-xy+2y2-2,2x2-3xy+3y2-2;  // V(I) has four elements
1409
1410    interval i = bounds2(-3/2,3/2);
1411    box B = list(i, i);
1412
1413    list result = exclusionTest(I, B, 1/512);
1414    size(result[1]);
1415    size(result[2]);
1416}
1417
1418// vim: ft=singular
Note: See TracBrowser for help on using the repository browser.