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

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