Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Matrices/generic_integer_linear_solvers.adb, Revision 1.1
1.1 ! maekawa 1: package body Generic_Integer_Linear_Solvers is
! 2:
! 3: use Common_Divisors;
! 4:
! 5: -- SCALERS :
! 6:
! 7: function Divisors ( a : Matrix ) return Vectors.Vector is
! 8:
! 9: -- DESCRIPTION :
! 10: -- Returns a vector containing the gcd of the elements of each row.
! 11:
! 12: v : Vectors.Vector(a'range(1));
! 13:
! 14: begin
! 15: for i in a'range(1) loop
! 16: v(i) := a(i,a'first(2));
! 17: if not Equal(v(i),one)
! 18: then for j in (a'first(2)+1)..a'last(2) loop
! 19: v(i) := gcd(v(i),a(i,j));
! 20: exit when Equal(v(i),one);
! 21: end loop;
! 22: end if;
! 23: end loop;
! 24: return v;
! 25: end Divisors;
! 26:
! 27: function Scale ( a : Matrix ) return Matrix is
! 28:
! 29: v : Vectors.Vector(a'range(1)) := Divisors(a);
! 30: b : Matrix(a'range(1),a'range(2));
! 31:
! 32: begin
! 33: for i in b'range(1) loop
! 34: if (Equal(v(i),one) or Equal(v(i),zero))
! 35: then for j in b'range(2) loop
! 36: b(i,j) := a(i,j);
! 37: end loop;
! 38: else for j in b'range(2) loop
! 39: b(i,j) := a(i,j) / v(i);
! 40: end loop;
! 41: end if;
! 42: end loop;
! 43: return b;
! 44: end Scale;
! 45:
! 46: procedure Scale ( a : in out Matrix; v : out Vectors.Vector ) is
! 47:
! 48: dv : Vectors.Vector(a'range(1)) := Divisors(a);
! 49:
! 50: begin
! 51: for i in a'range(1) loop
! 52: if (Equal(dv(i),one) or Equal(dv(i),zero))
! 53: then null;
! 54: else for j in a'range(2) loop
! 55: a(i,j) := a(i,j) / dv(i);
! 56: end loop;
! 57: end if;
! 58: end loop;
! 59: v := dv;
! 60: end Scale;
! 61:
! 62: procedure Scale ( a : in out Matrix ) is
! 63:
! 64: v : Vectors.Vector(a'range(1)) := Divisors(a);
! 65:
! 66: begin
! 67: for i in a'range(1) loop
! 68: if (Equal(v(i),one) or Equal(v(i),zero))
! 69: then null;
! 70: else for j in a'range(2) loop
! 71: a(i,j) := a(i,j) / v(i);
! 72: end loop;
! 73: end if;
! 74: end loop;
! 75: end Scale;
! 76:
! 77: procedure Scale ( a : in out Matrix; row,col : in integer ) is
! 78:
! 79: g : number := a(row,col);
! 80:
! 81: begin
! 82: if not Equal(g,one)
! 83: then for l in (col+1)..a'last(2) loop
! 84: g := gcd(g,a(row,l));
! 85: exit when Equal(g,one);
! 86: end loop;
! 87: end if;
! 88: if (not Equal(g,zero)) and (not Equal(g,one))
! 89: then for l in row..a'last(2) loop
! 90: a(row,l) := a(row,l)/g;
! 91: end loop;
! 92: end if;
! 93: end Scale;
! 94:
! 95: -- STATIC TRIANGULATORS :
! 96:
! 97: procedure Upper_Triangulate ( l : out Matrix; a : in out Matrix ) is
! 98:
! 99: row,pivot : integer;
! 100: temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
! 101: ll : Matrix(a'range(1),a'range(1));
! 102:
! 103: begin
! 104: for i in ll'range(1) loop
! 105: for j in ll'range(2) loop
! 106: Copy(zero,ll(i,j));
! 107: end loop;
! 108: Copy(one,ll(i,i));
! 109: end loop;
! 110: row := a'first(1);
! 111: for j in a'first(2)..a'last(2) loop
! 112: pivot := row-1; -- find pivot
! 113: for i in row..a'last(1) loop
! 114: if not Equal(a(i,j),zero)
! 115: then pivot := i;
! 116: exit;
! 117: end if;
! 118: end loop;
! 119: if pivot >= row
! 120: then if pivot /= row -- interchange if necessary
! 121: then for k in a'range(2) loop
! 122: Copy(a(row,k),temp);
! 123: Copy(a(pivot,k),a(row,k));
! 124: Copy(temp,a(pivot,k));
! 125: end loop;
! 126: for k in ll'range(2) loop
! 127: Copy(ll(row,k),temp);
! 128: Copy(ll(pivot,k),ll(row,k));
! 129: Copy(temp,ll(pivot,k));
! 130: end loop;
! 131: end if;
! 132: for i in (row+1)..a'last(1) loop -- make zeroes
! 133: if not Equal(a(i,j),zero)
! 134: then gcd(a(row,j),a(i,j),ka,lb,d);
! 135: aa := a(row,j)/d; bb := a(i,j)/d;
! 136: if Equal(aa,bb) and then Equal(ka,zero)
! 137: then Copy(lb,ka); Copy(zero,lb);
! 138: end if;
! 139: if Equal(aa,-bb) and then Equal(ka,zero)
! 140: then ka := -lb; Copy(zero,lb);
! 141: end if;
! 142: for k in j..a'last(2) loop
! 143: Copy(a(row,k),a_rowk); Clear(a(row,k));
! 144: -- a_rowk := a(row,k);
! 145: Copy(a(i,k),a_ik); Clear(a(i,k)); -- a_ik := a(i,k);
! 146: a(row,k) := ka*a_rowk + lb*a_ik;
! 147: a(i,k) := -bb*a_rowk + aa*a_ik;
! 148: end loop;
! 149: for k in ll'range(2) loop
! 150: a_rowk := ll(row,k);
! 151: a_ik := ll(i,k);
! 152: ll(row,k) := ka*a_rowk + lb*a_ik;
! 153: ll(i,k) := -bb*a_rowk + aa*a_ik;
! 154: end loop;
! 155: end if;
! 156: end loop;
! 157: row := row + 1;
! 158: end if;
! 159: exit when row > a'last(1);
! 160: end loop;
! 161: l := ll;
! 162: end Upper_Triangulate;
! 163:
! 164: procedure Upper_Triangulate ( a : in out Matrix ) is
! 165:
! 166: row,pivot : integer;
! 167: temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
! 168:
! 169: begin
! 170: row := a'first(1);
! 171: for j in a'first(2)..a'last(2) loop
! 172: pivot := row-1; -- find pivot
! 173: for i in row..a'last(1) loop
! 174: if not Equal(a(i,j),zero)
! 175: then pivot := i;
! 176: exit;
! 177: end if;
! 178: end loop;
! 179: if pivot >= row
! 180: then if pivot /= row -- interchange if necessary
! 181: then for k in a'range(2) loop
! 182: Copy(a(row,k),temp);
! 183: Copy(a(pivot,k),a(row,k));
! 184: Copy(temp,a(pivot,k));
! 185: end loop;
! 186: end if;
! 187: for i in (row+1)..a'last(1) loop -- make zeroes
! 188: if not Equal(a(i,j),zero)
! 189: then gcd(a(row,j),a(i,j),ka,lb,d);
! 190: aa := a(row,j)/d; bb := a(i,j)/d;
! 191: if Equal(aa,bb) and then Equal(ka,zero)
! 192: then Copy(lb,ka); Copy(zero,lb);
! 193: end if;
! 194: if Equal(aa,-bb) and then Equal(ka,zero)
! 195: then ka := -lb; Copy(zero,lb);
! 196: end if;
! 197: for k in j..a'last(2) loop
! 198: Copy(a(row,k),a_rowk); Clear(a(row,k));
! 199: --a_rowk := a(row,k);
! 200: Copy(a(i,k),a_ik); Clear(a(i,k)); --a_ik := a(i,k);
! 201: a(row,k) := ka*a_rowk + lb*a_ik;
! 202: a(i,k) := -bb*a_rowk + aa*a_ik;
! 203: end loop;
! 204: end if;
! 205: end loop;
! 206: row := row + 1;
! 207: end if;
! 208: exit when row > a'last(1);
! 209: end loop;
! 210: end Upper_Triangulate;
! 211:
! 212: procedure Upper_Triangulate
! 213: ( a : in out Matrix;
! 214: ipvt : in out Standard_Integer_Vectors.Vector ) is
! 215:
! 216: row,pivot,tmppiv : integer;
! 217: temp,aa,bb,ka,lb,d,a_rowk,a_ik : number;
! 218:
! 219: begin
! 220: row := a'first(1);
! 221: for j in a'first(2)..a'last(2) loop
! 222: pivot := row-1; -- find pivot
! 223: for i in row..a'last(1) loop
! 224: if not Equal(a(i,j),zero)
! 225: then pivot := i;
! 226: exit;
! 227: end if;
! 228: end loop;
! 229: if pivot >= row
! 230: then if pivot /= row -- interchange if necessary
! 231: then for k in a'range(2) loop
! 232: Copy(a(row,k),temp);
! 233: Copy(a(pivot,k),a(row,k));
! 234: Copy(temp,a(pivot,k));
! 235: end loop;
! 236: tmppiv := ipvt(row);
! 237: ipvt(row) := ipvt(pivot);
! 238: ipvt(pivot) := tmppiv;
! 239: end if;
! 240: for i in (row+1)..a'last(1) loop -- make zeroes
! 241: if not Equal(a(i,j),zero)
! 242: then gcd(a(row,j),a(i,j),ka,lb,d);
! 243: aa := a(row,j)/d; bb := a(i,j)/d;
! 244: if Equal(aa,bb) and then Equal(ka,zero)
! 245: then Copy(lb,ka); Copy(zero,lb);
! 246: end if;
! 247: if Equal(aa,-bb) and then Equal(ka,zero)
! 248: then ka := -lb; Copy(zero,lb);
! 249: end if;
! 250: for k in j..a'last(2) loop
! 251: Copy(a(row,k),a_rowk); Clear(a(row,k));
! 252: -- a_rowk := a(row,k);
! 253: Copy(a(i,k),a_ik); Clear(a(i,k)); -- a_ik := a(i,k);
! 254: a(row,k) := ka*a_rowk + lb*a_ik;
! 255: a(i,k) := -bb*a_rowk + aa*a_ik;
! 256: end loop;
! 257: end if;
! 258: end loop;
! 259: row := row + 1;
! 260: end if;
! 261: exit when row > a'last(1);
! 262: end loop;
! 263: end Upper_Triangulate;
! 264:
! 265: procedure Lower_Triangulate ( a : in out Matrix; u : out Matrix ) is
! 266:
! 267: column,pivot : integer;
! 268: temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
! 269: uu : Matrix(a'range(2),a'range(2));
! 270:
! 271: begin
! 272:
! 273: for i in uu'range(1) loop
! 274: for j in uu'range(2) loop
! 275: Copy(zero,uu(i,j));
! 276: end loop;
! 277: Copy(one,uu(i,i));
! 278: end loop;
! 279: column := a'first(2);
! 280: for i in a'first(1)..a'last(1) loop
! 281: pivot := column-1; -- find pivot
! 282: for j in column..a'last(2) loop
! 283: if not Equal(a(i,j),zero)
! 284: then pivot := j;
! 285: exit;
! 286: end if;
! 287: end loop;
! 288: if pivot >= column
! 289: then if pivot /= column -- interchange if necessary
! 290: then for k in a'range(1) loop
! 291: Copy(a(k,column),temp);
! 292: Copy(a(k,pivot),a(k,column));
! 293: Copy(temp,a(k,pivot));
! 294: end loop;
! 295: for k in uu'range(1) loop
! 296: Copy(uu(k,column),temp);
! 297: Copy(uu(k,pivot),uu(k,column));
! 298: Copy(temp,uu(k,pivot));
! 299: end loop;
! 300: end if;
! 301: for j in (column+1)..a'last(2) loop -- make zeroes
! 302: if not Equal(a(i,j),zero)
! 303: then gcd(a(i,column),a(i,j),ka,lb,d);
! 304: aa := a(i,column)/d; bb := a(i,j)/d;
! 305: if Equal(aa,bb) and then Equal(ka,zero)
! 306: then Copy(lb,ka); Copy(zero,lb);
! 307: end if;
! 308: if Equal(aa,-bb) and then Equal(ka,zero)
! 309: then ka := -lb; Copy(zero,lb);
! 310: end if;
! 311: for k in i..a'last(1) loop
! 312: Copy(a(k,column),a_kcolumn); Clear(a(k,column));
! 313: -- a_kcolumn := a(k,column);
! 314: Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
! 315: a(k,column) := a_kcolumn*ka + a_kj*lb;
! 316: a(k,j) := a_kcolumn*(-bb) + a_kj*aa;
! 317: end loop;
! 318: for k in uu'range(1) loop
! 319: Copy(uu(k,column),a_kcolumn); Clear(uu(k,column));
! 320: -- a_kcolumn := uu(k,column);
! 321: Copy(uu(k,j),a_kj); Clear(u(k,j)); -- a_kj := uu(k,j);
! 322: uu(k,column) := a_kcolumn*ka + a_kj*lb;
! 323: uu(k,j) := a_kcolumn*(-bb) + a_kj*aa;
! 324: end loop;
! 325: end if;
! 326: end loop;
! 327: column := column + 1;
! 328: end if;
! 329: exit when column > a'last(2);
! 330: end loop;
! 331: u := uu;
! 332: end Lower_Triangulate;
! 333:
! 334: procedure Lower_Triangulate ( a : in out Matrix ) is
! 335:
! 336: column,pivot : integer;
! 337: temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
! 338:
! 339: begin
! 340: column := a'first(2);
! 341: for i in a'first(1)..a'last(1) loop
! 342: pivot := column-1; -- find pivot
! 343: for j in column..a'last(2) loop
! 344: if not Equal(a(i,j),zero)
! 345: then pivot := j;
! 346: exit;
! 347: end if;
! 348: end loop;
! 349: if pivot >= column
! 350: then if pivot /= column -- interchange if necessary
! 351: then for k in a'range(1) loop
! 352: Copy(a(k,column),temp);
! 353: Copy(a(k,pivot),a(k,column));
! 354: Copy(temp,a(k,pivot));
! 355: end loop;
! 356: end if;
! 357: for j in (column+1)..a'last(2) loop -- make zeroes
! 358: if not Equal(a(i,j),zero)
! 359: then gcd(a(i,column),a(i,j),ka,lb,d);
! 360: aa := a(i,column)/d; bb := a(i,j)/d;
! 361: if Equal(aa,bb) and then Equal(ka,zero)
! 362: then Copy(lb,ka); Copy(zero,lb);
! 363: end if;
! 364: if Equal(aa,-bb) and then Equal(ka,zero)
! 365: then ka := -lb; Copy(zero,lb);
! 366: end if;
! 367: for k in i..a'last(1) loop
! 368: Copy(a(k,column),a_kcolumn); Clear(a(k,column));
! 369: -- a_kcolumn := a(k,column);
! 370: Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
! 371: a(k,column) := a_kcolumn*ka + a_kj*lb;
! 372: a(k,j) := a_kcolumn*(-bb) + a_kj*aa;
! 373: end loop;
! 374: end if;
! 375: end loop;
! 376: column := column + 1;
! 377: end if;
! 378: exit when column > a'last(2);
! 379: end loop;
! 380: end Lower_Triangulate;
! 381:
! 382: procedure Lower_Triangulate
! 383: ( a : in out Matrix;
! 384: ipvt : in out Standard_Integer_Vectors.Vector ) is
! 385:
! 386: column,pivot,tmppiv : integer;
! 387: temp,aa,bb,ka,lb,d,a_kcolumn,a_kj : number;
! 388:
! 389: begin
! 390: column := a'first(2);
! 391: for i in a'first(1)..a'last(1) loop
! 392: pivot := column-1; -- find pivot
! 393: for j in column..a'last(2) loop
! 394: if not Equal(a(i,j),zero)
! 395: then pivot := j;
! 396: exit;
! 397: end if;
! 398: end loop;
! 399: if pivot >= column
! 400: then if pivot /= column -- interchange if necessary
! 401: then for k in a'range(1) loop
! 402: Copy(a(k,column),temp);
! 403: Copy(a(k,pivot),a(k,column));
! 404: Copy(temp,a(k,pivot));
! 405: end loop;
! 406: tmppiv := ipvt(column);
! 407: ipvt(column) := ipvt(pivot);
! 408: ipvt(pivot) := tmppiv;
! 409: end if;
! 410: for j in (column+1)..a'last(2) loop -- make zeroes
! 411: if not Equal(a(i,j),zero)
! 412: then gcd(a(i,column),a(i,j),ka,lb,d);
! 413: aa := a(i,column)/d; bb := a(i,j)/d;
! 414: if Equal(aa,bb) and then Equal(ka,zero)
! 415: then Copy(lb,ka); Copy(zero,lb);
! 416: end if;
! 417: if Equal(aa,-bb) and then Equal(ka,zero)
! 418: then ka := -lb; Copy(zero,lb);
! 419: end if;
! 420: for k in i..a'last(1) loop
! 421: Copy(a(k,column),a_kcolumn); Clear(a(k,column));
! 422: -- a_kcolumn := a(k,column);
! 423: Copy(a(k,j),a_kj); Clear(a(k,j)); -- a_kj := a(k,j);
! 424: a(k,column) := a_kcolumn*ka + a_kj*lb;
! 425: a(k,j) := a_kcolumn*(-bb) + a_kj*aa;
! 426: end loop;
! 427: end if;
! 428: end loop;
! 429: column := column + 1;
! 430: end if;
! 431: exit when column > a'last(2);
! 432: end loop;
! 433: end Lower_Triangulate;
! 434:
! 435: -- SELECTORS :
! 436:
! 437: function Det ( a : Matrix ) return number is
! 438:
! 439: -- NOTE :
! 440: -- The triangulation is implemented independently to keep track
! 441: -- of row interchanges.
! 442:
! 443: res : number := one;
! 444: m : matrix(a'range(1),a'range(2));
! 445: row,pivot : integer;
! 446: temp,aa,bb,ka,lb,d,m_rowk,m_ik : number;
! 447:
! 448: begin
! 449: Copy(a,m); -- triangulate m
! 450: row := m'first(1);
! 451: for j in m'first(2)..m'last(2) loop
! 452: pivot := row-1; -- find pivot
! 453: for i in row..m'last(1) loop
! 454: if not Equal(m(i,j),zero)
! 455: then pivot := i;
! 456: exit;
! 457: end if;
! 458: end loop;
! 459: if pivot >= row
! 460: then if pivot /= row -- interchange if necessary
! 461: then for k in m'range(2) loop
! 462: Copy(m(row,k),temp);
! 463: Copy(m(pivot,k),m(row,k));
! 464: Copy(temp,m(pivot,k));
! 465: end loop;
! 466: Min(res);
! 467: end if;
! 468: for i in (row+1)..m'last(1) loop -- make zeroes
! 469: if not Equal(m(i,j),zero)
! 470: then gcd(m(row,j),m(i,j),ka,lb,d);
! 471: aa := m(row,j)/d; bb := m(i,j)/d;
! 472: if Equal(aa,bb) and then Equal(ka,zero)
! 473: then Copy(lb,ka); Copy(zero,lb);
! 474: end if;
! 475: if Equal(aa,-bb) and then Equal(ka,zero)
! 476: then ka := -lb; Copy(zero,lb);
! 477: end if;
! 478: for k in j..m'last(2) loop
! 479: Copy(m(row,k),m_rowk); Clear(m(row,k));
! 480: -- m_rowk := m(row,k);
! 481: Copy(m(i,k),m_ik); Clear(m(i,k)); -- m_ik := m(i,k);
! 482: m(row,k) := ka*m_rowk + lb*m_ik;
! 483: m(i,k) := -bb*m_rowk + aa*m_ik;
! 484: end loop;
! 485: end if;
! 486: end loop;
! 487: row := row + 1;
! 488: end if;
! 489: exit when row > m'last(1);
! 490: end loop;
! 491: for k in m'range(1) loop
! 492: Mul(res,m(k,k));
! 493: end loop;
! 494: Clear(m);
! 495: return res;
! 496: end Det;
! 497:
! 498: function Per ( i,n : natural; a : matrix;
! 499: kk : Standard_Integer_Vectors.Vector ) return number is
! 500: begin
! 501: if i = n+1
! 502: then return one;
! 503: else declare
! 504: res,acc : number;
! 505: kkk : Standard_Integer_Vectors.Vector(kk'range) := kk;
! 506: begin
! 507: Copy(zero,res);
! 508: for j in kk'range loop
! 509: if not Equal(a(i,j),zero) and then (kk(j) /= 0)
! 510: then kkk(j) := kkk(j) - 1;
! 511: acc := Per(i+1,n,a,kkk);
! 512: Add(res,acc);
! 513: Clear(acc);
! 514: kkk(j) := kkk(j) + 1;
! 515: end if;
! 516: end loop;
! 517: return res;
! 518: end;
! 519: end if;
! 520: end Per;
! 521:
! 522: function Per ( i,n : natural; a : matrix;
! 523: kk : Standard_Integer_Vectors.Vector; max : number )
! 524: return number is
! 525: begin
! 526: if i = n+1
! 527: then return one;
! 528: else declare
! 529: res,acc : number;
! 530: kkk : Standard_Integer_Vectors.Vector(kk'range) := kk;
! 531: begin
! 532: Copy(zero,res);
! 533: for j in kk'range loop
! 534: if not Equal(a(i,j),zero) and then (kk(j) /= 0)
! 535: then kkk(j) := kkk(j) - 1;
! 536: acc := a(i,j)*Per(i+1,n,a,kkk,max);
! 537: Add(res,acc);
! 538: Clear(acc);
! 539: kkk(j) := kkk(j) + 1;
! 540: end if;
! 541: exit when (res > max) or Equal(res,max);
! 542: end loop;
! 543: return res;
! 544: end;
! 545: end if;
! 546: end Per;
! 547:
! 548: function Per ( a : matrix; k : Standard_Integer_Vectors.Vector )
! 549: return number is
! 550:
! 551: -- ALGORITHM :
! 552: -- Row expansion without memory, as developed by C.W. Wampler,
! 553: -- see `Bezout Number Calculations for Multi-Homogeneous Polynomial
! 554: -- Systems', Appl. Math. Comput. 51:(2-3), 143-157, 1992.
! 555:
! 556: begin
! 557: return Per(1,a'last(1),a,k);
! 558: end Per;
! 559:
! 560: function Per ( a : matrix; k : Standard_Integer_Vectors.Vector;
! 561: max : number ) return number is
! 562:
! 563: -- ALGORITHM :
! 564: -- Row expansion without memory, as developed by C.W. Wampler,
! 565: -- see `Bezout Number Calculations for Multi-Homogeneous Polynomial
! 566: -- Systems', Appl. Math. Comput. 51:(2-3), 143-157, 1992.
! 567:
! 568: begin
! 569: return Per(1,a'last(1),a,k,max);
! 570: end Per;
! 571:
! 572: function Rank ( a : Matrix ) return natural is
! 573:
! 574: res : natural := 0;
! 575: m : Matrix(a'range(1),a'range(2));
! 576: column : integer;
! 577:
! 578: begin
! 579: Copy(a,m);
! 580: Upper_Triangulate(m);
! 581: -- compute the length of chain of nonzero elements in m :
! 582: -- search first nonzero element in first row of m :
! 583: column := m'first(2)-1;
! 584: for k in m'range(2) loop
! 585: if not Equal(m(m'first(1),k),zero)
! 586: then column := k;
! 587: end if;
! 588: exit when (column = k);
! 589: end loop;
! 590: if column < m'first(2)
! 591: then return 0; -- all elements of m are zero
! 592: else for k in m'range(1) loop
! 593: exit when column > m'last(2);
! 594: if not Equal(m(k,column),zero)
! 595: then res := res + 1;
! 596: else -- search for next nonzero element on row k :
! 597: for l in column+1..m'last(2) loop
! 598: if not Equal(m(k,l),zero)
! 599: then column := l;
! 600: res := res + 1;
! 601: end if;
! 602: exit when (column = l);
! 603: end loop;
! 604: end if;
! 605: column := column + 1;
! 606: end loop;
! 607: end if;
! 608: Clear(m);
! 609: return res;
! 610: end Rank;
! 611:
! 612: -- DYNAMIC TRIANGULATOR :
! 613:
! 614: procedure Triangulate ( l : in integer; m : in out matrix;
! 615: ipvt : in out Standard_Integer_Vectors.vector;
! 616: piv : out integer ) is
! 617:
! 618: -- DESCRIPTION :
! 619: -- Updates lth row of m such that m remains upper triangular.
! 620:
! 621: tmp,a,b,lcmab,faca,facb : number;
! 622: pivot,index,tmppiv : integer;
! 623:
! 624: begin
! 625: Switch(ipvt,l,m); -- pivoting for previous unknowns
! 626: index := 1; -- update : make l-1 zeroes in row l
! 627: for k in 1..(l-1) loop
! 628: if (not Equal(m(l,index),zero))
! 629: and then (not Equal(m(k,index),zero)) -- make m(l,index) zero
! 630: then a := m(k,index); b := m(l,index);
! 631: lcmab := lcm(a,b);
! 632: if lcmab < zero then lcmab := -lcmab; end if;
! 633: facb := lcmab/b; faca := lcmab/a;
! 634: if facb > zero
! 635: then for i in index..m'last(2) loop
! 636: m(l,i) := facb*m(l,i) - faca*m(k,i);
! 637: end loop;
! 638: else for i in index..m'last(2) loop
! 639: m(l,i) := -facb*m(l,i) + faca*m(k,i);
! 640: end loop;
! 641: end if;
! 642: end if;
! 643: if not Equal(m(k,index),zero)
! 644: then index := index + 1;
! 645: end if;
! 646: end loop;
! 647: pivot := 0; -- search pivot
! 648: for k in l..m'last(2)-1 loop
! 649: if not Equal(m(l,k),zero)
! 650: then pivot := k;
! 651: end if;
! 652: exit when pivot /= 0;
! 653: end loop;
! 654: if pivot > l
! 655: then for k in 1..l loop -- interchange columns l and pivot
! 656: Copy(m(k,l),tmp);
! 657: Copy(m(k,pivot),m(k,l));
! 658: Copy(tmp,m(k,pivot));
! 659: end loop;
! 660: tmppiv := ipvt(l);
! 661: ipvt(l) := ipvt(pivot);
! 662: ipvt(pivot) := tmppiv;
! 663: end if;
! 664: piv := pivot;
! 665: end Triangulate;
! 666:
! 667: procedure Switch ( ipvt : in Standard_Integer_Vectors.vector;
! 668: index : in integer; m : in out matrix ) is
! 669:
! 670: tmpv : Vectors.Vector(m'range(2));
! 671:
! 672: begin
! 673: for k in tmpv'range loop
! 674: Copy(m(index,k),tmpv(k));
! 675: end loop;
! 676: for k in tmpv'range loop
! 677: Copy(tmpv(ipvt(k)),m(index,k));
! 678: end loop;
! 679: Vectors.Clear(tmpv);
! 680: end Switch;
! 681:
! 682: procedure Switch ( ipvt : in Standard_Integer_Vectors.vector;
! 683: first,last : in integer; m : in out matrix) is
! 684:
! 685: tmpv : Vectors.Vector(m'range(2));
! 686:
! 687: begin
! 688: for index in first..last loop
! 689: for k in tmpv'range loop
! 690: Copy(m(index,k),tmpv(k));
! 691: end loop;
! 692: for k in tmpv'range loop
! 693: Copy(tmpv(ipvt(k)),m(index,k));
! 694: end loop;
! 695: Vectors.Clear(tmpv);
! 696: end loop;
! 697: end Switch;
! 698:
! 699: procedure Switch ( l,pivot,index : in integer; m : in out matrix ) is
! 700:
! 701: tmp : number;
! 702:
! 703: begin
! 704: if l /= pivot
! 705: then Copy(m(index,l),tmp);
! 706: Copy(m(index,pivot),m(index,l));
! 707: Copy(tmp,m(index,pivot));
! 708: end if;
! 709: end Switch;
! 710:
! 711: procedure Switch ( l,pivot : in integer;
! 712: first,last : in integer; m : in out matrix ) is
! 713:
! 714: tmp : number;
! 715:
! 716: begin
! 717: if l /= pivot
! 718: then for index in first..last loop
! 719: Copy(m(index,l),tmp);
! 720: Copy(m(index,pivot),m(index,l));
! 721: Copy(tmp,m(index,pivot));
! 722: end loop;
! 723: end if;
! 724: end Switch;
! 725:
! 726: -- SOLVERS :
! 727:
! 728: function Check0 ( a : Matrix; x : Vectors.Vector ) return boolean is
! 729:
! 730: -- DESCRIPTION :
! 731: -- Returns true if x is a solution of the system a*x = 0.
! 732:
! 733: tmp : Vectors.Vector(a'range(1));
! 734:
! 735: begin
! 736: tmp := a*x;
! 737: for i in tmp'range loop
! 738: if not Equal(tmp(i),zero)
! 739: then Vectors.Clear(tmp); return false;
! 740: end if;
! 741: end loop;
! 742: Vectors.Clear(tmp);
! 743: return true;
! 744: end Check0;
! 745:
! 746: procedure Solve0 ( a : in Matrix; x : in out Vectors.Vector ) is
! 747:
! 748: -- ALGORITHM :
! 749: -- An intermediate, generating matrix tmp will be constructed,
! 750: -- such that
! 751: -- 1) the solution x to tmp*x = 0 is the same of a*x = 0;
! 752: -- 2) tmp(i,i) and tmp(i,ind) are the only nonzero entries.
! 753: -- Before this construction, it will be checked whether there
! 754: -- exists a zero column and the index ind must be determined.
! 755: -- After the definition of tmp, the back substitution process
! 756: -- yields a solution.
! 757:
! 758: piv,ind : integer;
! 759: tmp : Matrix(a'first(1)..(a'last(1)+1),a'range(2));
! 760: res : Vectors.Vector(x'range);
! 761: pivots : Standard_Integer_Vectors.Vector(x'range);
! 762: zero_column : boolean;
! 763:
! 764: begin
! 765: -- initialization of tmp,ind and pivots :
! 766: for i in tmp'range(1) loop
! 767: for j in tmp'range(2) loop
! 768: Copy(zero,tmp(i,j));
! 769: end loop;
! 770: end loop;
! 771: for i in pivots'range loop
! 772: pivots(i) := i;
! 773: end loop;
! 774: ind := x'first(1)-1;
! 775: for i in a'range(1) loop
! 776: piv := pivots'first-1;
! 777: for j in a'range(2) loop
! 778: if not Equal(a(i,j),zero)
! 779: then piv := pivots(j);
! 780: pivots(j) := pivots(i);
! 781: pivots(i) := piv;
! 782: exit;
! 783: end if;
! 784: end loop;
! 785: zero_column := true;
! 786: for j in a'first(1)..i loop
! 787: Copy(a(j,pivots(i)),tmp(j,i));
! 788: if zero_column and then not Equal(tmp(j,i),zero)
! 789: then zero_column := false;
! 790: end if;
! 791: end loop;
! 792: if piv < pivots'first or else zero_column or else Equal(tmp(i,i),zero)
! 793: then ind := i; exit;
! 794: end if;
! 795: end loop;
! 796: if zero_column
! 797: then for i in x'range loop
! 798: Copy(zero,x(i));
! 799: end loop;
! 800: Copy(one,x(ind));
! 801: elsif (ind < x'first(1)) and (a'last(1) >= a'last(2))
! 802: then for i in x'range loop
! 803: Copy(zero,x(i));
! 804: end loop;
! 805: else
! 806: if ind < x'first(1)
! 807: then ind := a'last(1)+1;
! 808: for j in tmp'range(2) loop
! 809: Copy(zero,tmp(ind,j));
! 810: end loop;
! 811: zero_column := true;
! 812: for j in a'range(1) loop
! 813: Copy(a(j,pivots(ind)),tmp(j,ind));
! 814: if zero_column and then not Equal(tmp(j,ind),zero)
! 815: then zero_column := false;
! 816: end if;
! 817: end loop;
! 818: end if;
! 819: if zero_column
! 820: then for i in x'range loop
! 821: Copy(zero,x(i));
! 822: end loop;
! 823: Copy(one,x(ind));
! 824: else
! 825: -- construct generating matrix :
! 826: for i in reverse (tmp'first(2)+1)..(ind-1) loop -- i = column
! 827: for k in tmp'first(1)..(i-1) loop
! 828: if not Equal(tmp(k,i),zero) -- make tmp(k,i) zero
! 829: then declare
! 830: aa,bb,d : number;
! 831: begin
! 832: d := gcd(tmp(i,i),tmp(k,i));
! 833: aa := tmp(i,i)/d; bb := tmp(k,i)/d;
! 834: for l in k..(i-1) loop
! 835: Mul(tmp(k,l),aa);
! 836: end loop;
! 837: Copy(zero,tmp(k,i)); --aa*tmp(k,i) - bb*tmp(i,i);
! 838: tmp(k,ind) := aa*tmp(k,ind) - bb*tmp(i,ind);
! 839: end;
! 840: Scale(tmp,k,k); -- to avoid numeric_error
! 841: end if;
! 842: end loop; -- upper half of ith colum consists of zero entries
! 843: end loop;
! 844: -- generate x by back substitution :
! 845: x(ind) := tmp(x'first,x'first);
! 846: for i in (x'first+1)..(ind-1) loop
! 847: if not Equal(tmp(i,i),zero)
! 848: then x(ind) := lcm(tmp(i,i),x(ind));
! 849: end if;
! 850: end loop;
! 851: for i in x'first..(ind-1) loop
! 852: if Equal(tmp(i,i),zero)
! 853: then Copy(zero,x(i));
! 854: else x(i) := -(tmp(i,ind)*x(ind))/tmp(i,i);
! 855: end if;
! 856: end loop;
! 857: end if;
! 858: end if;
! 859: for i in res'range loop -- take pivots into account
! 860: Copy(zero,res(i));
! 861: end loop;
! 862: for i in x'first..ind loop
! 863: Copy(x(i),res(pivots(i)));
! 864: end loop;
! 865: Vectors.Copy(res,x);
! 866: end Solve0;
! 867:
! 868: procedure Solve1 ( a : in Matrix; x : in out Vectors.Vector;
! 869: b : in Vectors.Vector; fail : out boolean ) is
! 870:
! 871: acc : number;
! 872:
! 873: begin
! 874: fail := false;
! 875: for i in reverse x'range loop
! 876: Copy(b(i),x(i));
! 877: for j in (i+1)..x'last loop
! 878: acc := a(i,j)*x(j);
! 879: Sub(x(i),acc);
! 880: Clear(acc);
! 881: end loop;
! 882: if not Equal(x(i),zero) and then not Equal(a(i,i),zero)
! 883: then acc := Rmd(x(i),a(i,i));
! 884: if Equal(acc,zero)
! 885: then Div(x(i),a(i,i));
! 886: else fail := true;
! 887: end if;
! 888: Clear(acc);
! 889: if fail
! 890: then Vectors.Clear(x); return;
! 891: end if;
! 892: end if;
! 893: end loop;
! 894: end Solve1;
! 895:
! 896: procedure Solve1 ( a : in Matrix; b : in out Vectors.Vector;
! 897: fail : out boolean ) is
! 898:
! 899: acc : number;
! 900:
! 901: begin
! 902: fail := false;
! 903: for i in reverse b'range loop
! 904: for j in (i+1)..b'last loop
! 905: acc := a(i,j)*b(j);
! 906: Sub(b(i),acc);
! 907: Clear(acc);
! 908: end loop;
! 909: if not Equal(b(i),zero) and then not Equal(a(i,i),zero)
! 910: then acc := Rmd(b(i),a(i,i));
! 911: if Equal(acc,zero)
! 912: then Div(b(i),a(i,i));
! 913: else fail := true;
! 914: end if;
! 915: Clear(acc);
! 916: if fail
! 917: then Vectors.Clear(b); return;
! 918: end if;
! 919: end if;
! 920: end loop;
! 921: end Solve1;
! 922:
! 923: function Solve ( m : Matrix; ipvt : Standard_Integer_Vectors.Vector )
! 924: return Vectors.Vector is
! 925:
! 926: x,res : Vectors.Vector(ipvt'range);
! 927: a : matrix(m'first(1)..m'last(1)-1,m'range(2));
! 928: ind : integer := a'first(1); -- index for the current row number
! 929: cnt0 : natural := 0; -- counts the number of zero rows
! 930:
! 931: begin
! 932: for k in a'range(1) loop
! 933: if not Equal(m(k,k),zero) -- otherwise : skip zero row !
! 934: then for l in a'range(2) loop
! 935: Copy(m(k,l),a(ind,l));
! 936: end loop;
! 937: ind := ind + 1;
! 938: else for l in a'range(2) loop
! 939: Copy(m(k,l),a(a'last(1) - cnt0,l));
! 940: end loop;
! 941: cnt0 := cnt0 + 1;
! 942: end if;
! 943: end loop;
! 944: for i in x'range loop
! 945: Copy(zero,x(i));
! 946: end loop;
! 947: Solve0(a,x);
! 948: for k in res'range loop
! 949: res(ipvt(k)) := x(k);
! 950: end loop;
! 951: if res(res'last) < zero
! 952: then Vectors.Min(res);
! 953: end if;
! 954: Clear(a);
! 955: return res;
! 956: end Solve;
! 957:
! 958: end Generic_Integer_Linear_Solvers;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>