1############################################################################# 2## 3## HomalgRing.gi MatricesForHomalg package Mohamed Barakat 4## 5## Copyright 2007-2009 Mohamed Barakat, RWTH Aachen 6## 7## Implementation stuff for homalg rings. 8## 9############################################################################# 10 11#################################### 12# 13# representations: 14# 15#################################### 16 17## <#GAPDoc Label="IsHomalgInternalRingRep"> 18## <ManSection> 19## <Filt Type="Representation" Arg="R" Name="IsHomalgInternalRingRep"/> 20## <Returns><C>true</C> or <C>false</C></Returns> 21## <Description> 22## The internal representation of &homalg; rings. <P/> 23## (It is a representation of the &GAP; category <C>IsHomalgRing</C>.) 24## </Description> 25## </ManSection> 26## <#/GAPDoc> 27## 28DeclareRepresentation( "IsHomalgInternalRingRep", 29 IsHomalgRing and IsHomalgRingOrFinitelyPresentedModuleRep, 30 [ "ring", "homalgTable" ] ); 31 32## 33DeclareRepresentation( "IsContainerForWeakPointersOnIdentityMatricesRep", 34 IsContainerForWeakPointersRep, 35 [ "weak_pointers" ] ); 36 37#################################### 38# 39# families and types: 40# 41#################################### 42 43# a new family: 44BindGlobal( "TheFamilyOfHomalgRingElements", 45 NewFamily( "TheFamilyOfHomalgRingElements" ) ); 46 47# a new family: 48BindGlobal( "TheFamilyOfHomalgRings", 49 CollectionsFamily( TheFamilyOfHomalgRingElements ) ); 50 51# a new type: 52BindGlobal( "TheTypeHomalgInternalRing", 53 NewType( TheFamilyOfHomalgRings, 54 IsHomalgInternalRingRep ) ); 55 56# a new family: 57BindGlobal( "TheFamilyOfContainersForWeakPointersOfIdentityMatrices", 58 NewFamily( "TheFamilyOfContainersForWeakPointersOfIdentityMatrices" ) ); 59 60# a new type: 61BindGlobal( "TheTypeContainerForWeakPointersOnIdentityMatrices", 62 NewType( TheFamilyOfContainersForWeakPointersOfIdentityMatrices, 63 IsContainerForWeakPointersOnIdentityMatricesRep ) ); 64 65#################################### 66# 67# global variables: 68# 69#################################### 70 71## 72InstallValue( CommonHomalgTableForRings, 73 rec( 74 RingName := 75 function( R ) 76 local minimal_polynomial, var, brackets, r; 77 78 if IsBound( R!.MinimalPolynomialOfPrimitiveElement ) then 79 minimal_polynomial := R!.MinimalPolynomialOfPrimitiveElement; 80 fi; 81 82 ## the Weyl algebra (relative version): 83 if HasRelativeIndeterminateDerivationsOfRingOfDerivations( R ) then 84 85 var := RelativeIndeterminateDerivationsOfRingOfDerivations( R ); 86 87 brackets := [ "<", ">" ]; 88 89 ## the Weyl algebra: 90 elif HasIndeterminateDerivationsOfRingOfDerivations( R ) then 91 92 var := IndeterminateDerivationsOfRingOfDerivations( R ); 93 94 brackets := [ "<", ">" ]; 95 96 ## the exterior algebra (relative version): 97 elif HasRelativeIndeterminateAntiCommutingVariablesOfExteriorRing( R ) then 98 99 var := RelativeIndeterminateAntiCommutingVariablesOfExteriorRing( R ); 100 101 brackets := [ "{", "}" ]; 102 103 ## the exterior algebra: 104 elif HasIndeterminateAntiCommutingVariablesOfExteriorRing( R ) then 105 106 var := IndeterminateAntiCommutingVariablesOfExteriorRing( R ); 107 108 brackets := [ "{", "}" ]; 109 110 ## the (free) polynomial ring (relative version): 111 elif HasBaseRing( R ) and HasRelativeIndeterminatesOfPolynomialRing( R ) and 112 not IsIdenticalObj( R, BaseRing( R ) ) then 113 114 var := RelativeIndeterminatesOfPolynomialRing( R ); 115 116 brackets := [ "[", "]" ]; 117 118 ## the (free) polynomial ring: 119 elif HasIndeterminatesOfPolynomialRing( R ) then 120 121 var := IndeterminatesOfPolynomialRing( R ); 122 123 brackets := [ "[", "]" ]; 124 125 elif HasRationalParameters( R ) then 126 127 var := RationalParameters( R ); 128 129 if IsBound( minimal_polynomial ) then 130 brackets := [ "[", "]" ]; 131 else 132 brackets := [ "(", ")" ]; 133 fi; 134 135 fi; 136 137 if not IsBound( var ) then 138 return fail; 139 fi; 140 141 var := JoinStringsWithSeparator( List( var, String ) ); 142 143 var := Concatenation( brackets[1], var, brackets[2] ); 144 145 if HasBaseRing( R ) and HasCoefficientsRing( R ) and 146 not IsIdenticalObj( BaseRing( R ), CoefficientsRing( R ) ) then 147 r := RingName( BaseRing( R ) ); 148 elif HasCoefficientsRing( R ) then 149 r := CoefficientsRing( R ); 150 if IsBound( r!.MinimalPolynomialOfPrimitiveElement ) and IsSubset( RingName( r ), "/" ) then 151 r := Concatenation( "(", RingName( r ), ")" ); 152 else 153 r := RingName( r ); 154 fi; 155 else 156 r := "(some ring)"; 157 fi; 158 159 r := Concatenation( r, var ); 160 161 if IsBound( minimal_polynomial ) then 162 r := Concatenation( r, "/(", minimal_polynomial, ")" ); 163 fi; 164 165 return String( r ); 166 167 end, 168 169 ) 170); 171 172#################################### 173# 174# methods for attributes: 175# 176#################################### 177 178## 179InstallMethod( Zero, 180 "for homalg rings", 181 [ IsHomalgInternalRingRep ], 10001, 182 183 function( R ) 184 185 return Zero( R!.ring ); 186 187end ); 188 189## 190InstallMethod( Zero, 191 "for homalg rings", 192 [ IsHomalgInternalRingRep ], 10001, 193 194 function( R ) 195 local RP; 196 197 RP := homalgTable( R ); 198 199 if IsBound( RP!.Zero ) then 200 return RP!.Zero; 201 fi; 202 203 TryNextMethod( ); 204 205end ); 206 207## 208InstallMethod( One, 209 "for homalg rings", 210 [ IsHomalgInternalRingRep ], 1001, 211 212 function( R ) 213 214 return One( R!.ring ); 215 216end ); 217 218## 219InstallMethod( One, 220 "for homalg rings", 221 [ IsHomalgInternalRingRep ], 1001, 222 223 function( R ) 224 local RP; 225 226 RP := homalgTable( R ); 227 228 if IsBound( RP!.One ) then 229 return RP!.One; 230 fi; 231 232 TryNextMethod( ); 233 234end ); 235 236## 237InstallMethod( MinusOne, 238 "for homalg rings", 239 [ IsHomalgInternalRingRep ], 240 241 function( R ) 242 243 return -One( R ); 244 245end ); 246 247## 248InstallMethod( MinusOne, 249 "for homalg rings", 250 [ IsHomalgInternalRingRep ], 251 252 function( R ) 253 local RP; 254 255 RP := homalgTable( R ); 256 257 if IsBound( RP!.MinusOne ) then 258 return RP!.MinusOne; 259 fi; 260 261 TryNextMethod( ); 262 263end ); 264 265## 266InstallMethod( ZeroMutable, 267 "for homalg ring elements", 268 [ IsHomalgRingElement ], 269 270 function( r ) 271 272 return Zero( HomalgRing( r ) ); 273 274end ); 275 276## 277InstallMethod( OneMutable, 278 "for homalg ring elements", 279 [ IsHomalgRingElement ], 280 281 function( r ) 282 283 return One( HomalgRing( r ) ); 284 285end ); 286 287## 288InstallMethod( Inverse, 289 "for homalg ring elements", 290 [ IsHomalgRingElement ], 291 292 function( r ) 293 294 return One( r ) / r; 295 296end ); 297 298## 299InstallMethod( MinusOneMutable, 300 "for homalg ring elements", 301 [ IsHomalgRingElement ], 302 303 function( r ) 304 305 return MinusOne( HomalgRing( r ) ); 306 307end ); 308 309## 310InstallMethod( Characteristic, 311 "for homalg ring elements", 312 [ IsHomalgRingElement ], 313 314 function( r ) 315 316 return Characteristic( HomalgRing( r ) ); 317 318end ); 319 320## for the computeralgebra course 321InstallOtherMethod( IndeterminateOfLaurentPolynomial, 322 "for homalg ring elements", 323 [ IsHomalgRingElement ], 324 325 function( r ) 326 local R, indets; 327 328 R := HomalgRing( r ); 329 330 indets := IndeterminatesOfPolynomialRing( R ); 331 332 return indets[Length( indets )]; 333 334end ); 335 336## for the computeralgebra course 337InstallOtherMethod( CoefficientsRing, 338 "for ring elements", 339 [ IsRingElement ], 340 341 function( r ) 342 local R; 343 344 if IsHomalgRingElement( r ) then 345 R := HomalgRing( r ); 346 else 347 R := DefaultRing( r ); 348 fi; 349 350 return CoefficientsRing( R ); 351 352end ); 353 354## 355InstallMethod( AssociatedPolynomialRing, 356 "for homalg fields", 357 [ IsHomalgRing and IsFieldForHomalg ], 358 359 function( R ) 360 local a, r; 361 362 if not HasRationalParameters( R ) then 363 Error( "the field has no rational parameters" ); 364 elif not HasCoefficientsRing( R ) then 365 Error( "the field has no subfield of coefficients" ); 366 fi; 367 368 r := CoefficientsRing( R ); 369 370 a := RationalParameters( R ); 371 372 return r * List( a, String ); 373 374end ); 375 376## 377InstallMethod( PolynomialRingWithProductOrdering, 378 "for homalg rings", 379 [ IsHomalgRing ], 380 381 function( R ) 382 local B, C; 383 384 if not IsIdenticalObj( BaseRing( R ), CoefficientsRing( R ) ) then 385 TryNextMethod( ); 386 fi; 387 388 return R; 389 390end ); 391 392## 393InstallMethod( BaseRing, 394 "for homalg rings", 395 [ IsHomalgRing and HasCoefficientsRing ], 396 397 CoefficientsRing ); 398 399#################################### 400# 401# methods for operations: 402# 403#################################### 404 405## 406InstallMethod( HomalgRing, 407 "for homalg rings", 408 [ IsHomalgRing ], 409 410 function( R ) 411 412 return R; 413 414end ); 415 416## 417InstallMethod( \=, 418 "for two homalg rings", 419 [ IsHomalgRing, IsHomalgRing ], 10001, 420 421 IsIdenticalObj ); 422 423## 424InstallMethod( HomalgRing, 425 "for homalg ring elements", 426 [ IsHomalgRingElement ], 427 428 function( r ) 429 430 return r!.ring; 431 432end ); 433 434## 435InstallMethod( LT, 436 "for homalg ring elements", 437 [ IsHomalgRingElement, IsHomalgRingElement ], 438 439 function( a, b ) 440 441 return LT( String( a ), String( b ) ); 442 443end ); 444 445## 446InstallMethod( INV, 447 "for homalg ring elements", 448 [ IsHomalgRingElement ], 449 450 function( r ) 451 452 return Inverse( r ); 453 454end ); 455 456## 457InstallMethod( \*, 458 "for homalg ring elements", 459 [ IS_RAT, IsHomalgRingElement ], 460 461 function( a, b ) 462 463 if IS_INT( a ) then 464 TryNextMethod( ); 465 fi; 466 467 return ( NUMERATOR_RAT( a ) * b ) / ( DENOMINATOR_RAT( a ) * One( b ) ); 468 469end ); 470 471## 472InstallMethod( \*, 473 "for homalg ring elements", 474 [ IsHomalgRingElement, IS_RAT ], 475 476 function( a, b ) 477 478 if IS_INT( b ) then 479 TryNextMethod( ); 480 fi; 481 482 return ( NUMERATOR_RAT( b ) * a ) / ( DENOMINATOR_RAT( b ) * One( a ) ); 483 484end ); 485 486## 487InstallMethod( \+, 488 "for homalg ring elements", 489 [ IS_RAT, IsHomalgRingElement ], 490 491 function( a, b ) 492 493 return a * One( b ) + b; 494 495end ); 496 497## 498InstallMethod( \+, 499 "for homalg ring elements", 500 [ IsHomalgRingElement, IS_RAT ], 501 502 function( a, b ) 503 504 return a + b * One( a ); 505 506end ); 507 508## 509InstallMethod( Indeterminates, 510 "for homalg rings", 511 [ IsHomalgRing and HasIndeterminatesOfPolynomialRing ], 512 513 function( R ) 514 515 return IndeterminatesOfPolynomialRing( R ); 516 517end ); 518 519## 520InstallMethod( Indeterminates, 521 "for homalg rings", 522 [ IsHomalgRing and HasIndeterminatesOfExteriorRing ], 523 524 function( R ) 525 526 return IndeterminatesOfExteriorRing( R ); 527 528end ); 529 530## 531InstallMethod( Indeterminates, 532 "for homalg rings", 533 [ IsHomalgRing and HasIndeterminateCoordinatesOfRingOfDerivations ], 534 535 function( R ) 536 537 return 538 Concatenation( 539 IndeterminateCoordinatesOfRingOfDerivations( R ), 540 IndeterminateDerivationsOfRingOfDerivations( R ) 541 ); 542 543end ); 544 545## 546InstallMethod( Indeterminates, 547 "for homalg fields", 548 [ IsHomalgRing and IsFieldForHomalg ], 549 550 function( R ) 551 552 return [ ]; 553 554end ); 555 556## 557InstallMethod( Indeterminates, 558 "for homalg ring of integers", 559 [ IsHomalgRing and IsIntegersForHomalg ], 560 561 function( R ) 562 563 return [ ]; 564 565end ); 566 567## Fallback method 568InstallMethod( RelativeIndeterminatesOfPolynomialRing, 569 "for homalg rings", 570 [ IsHomalgRing and HasCoefficientsRing ], 571 572 IndeterminatesOfPolynomialRing ); 573 574## 575InstallMethod( AssignGeneratorVariables, 576 "for homalg rings", 577 [ IsHomalgRing ], 578 579 function( R ) 580 local indets; 581 582 indets := Indeterminates( R ); 583 584 DoAssignGenVars( indets ); 585 586 return; 587 588end ); 589 590## 591InstallMethod( ExportIndeterminates, 592 "for homalg rings", 593 [ IsHomalgRing ], 594 595 function( R ) 596 local indets, x_name, x; 597 598 indets := Indeterminates( R ); 599 600 for x in indets do 601 x_name := String( x ); 602 if IsBoundGlobal( x_name ) then 603 if not IsHomalgRingElement( ValueGlobal( x_name ) ) then 604 Error( "the name ", x_name, " is not bound to a homalg ring element\n" ); 605 elif IsReadOnlyGlobal( x_name ) then 606 MakeReadWriteGlobal( x_name ); 607 fi; 608 UnbindGlobal( x_name ); 609 fi; 610 BindGlobal( x_name, x ); 611 od; 612 613 return indets; 614 615end ); 616 617## 618InstallMethod( ExportRationalParameters, 619 "for homalg rings", 620 [ IsHomalgRing and HasRationalParameters ], 621 622 function( R ) 623 local params, x_name, x; 624 625 params := RationalParameters( R ); 626 627 for x in params do 628 x_name := String( x ); 629 if IsBoundGlobal( x_name ) then 630 if not IsHomalgRingElement( ValueGlobal( x_name ) ) then 631 Error( "the name ", x_name, " is not bound to a homalg ring element\n" ); 632 elif IsReadOnlyGlobal( x_name ) then 633 MakeReadWriteGlobal( x_name ); 634 fi; 635 UnbindGlobal( x_name ); 636 fi; 637 BindGlobal( x_name, x ); 638 od; 639 640 return params; 641 642end ); 643 644## 645InstallMethod( ExportVariables, 646 "for homalg rings", 647 [ IsHomalgRing ], 648 649 function( R ) 650 651 return ExportIndeterminates( R ); 652 653end ); 654 655## 656InstallMethod( ExportVariables, 657 "for homalg rings", 658 [ IsHomalgRing and HasRationalParameters ], 659 660 function( R ) 661 662 return Concatenation( 663 ExportIndeterminates( R ), 664 ExportRationalParameters( R ) ); 665 666end ); 667 668## 669InstallMethod( Indeterminate, 670 "for homalg rings", 671 [ IsHomalgRing, IsPosInt ], 672 673 function( R, i ) 674 675 return Indeterminates( R )[i]; 676 677end ); 678 679## 680InstallMethod( ProductOfIndeterminates, 681 "for homalg rings", 682 [ IsHomalgRing ], 683 684 function( R ) 685 686 return Product( Indeterminates( R ) ); 687 688end ); 689 690## 691InstallMethod( ProductOfIndeterminatesOverBaseRing, 692 "for homalg rings", 693 [ IsHomalgRing and HasIndeterminatesOfPolynomialRing ], 694 695 function( R ) 696 697 return Product( IndeterminatesOfPolynomialRing( R ) ); 698 699end ); 700 701## 702InstallMethod( ProductOfIndeterminatesOverBaseRing, 703 "for homalg rings", 704 [ IsHomalgRing and HasRelativeIndeterminatesOfPolynomialRing ], 100, ## otherwise the above method is triggered :( 705 706 function( R ) 707 708 return Product( RelativeIndeterminatesOfPolynomialRing( R ) ); 709 710end ); 711 712## provided to avoid branching in the code and always returns fail 713InstallMethod( PositionOfTheDefaultPresentation, 714 "for ring elements", 715 [ IsRingElement ], 716 717 function( r ) 718 719 return fail; 720 721end ); 722 723## 724InstallMethod( \=, 725 "for two homalg ring elements", 726 [ IsHomalgRingElement, IsHomalgRingElement ], 727 728 function( r1, r2 ) 729 730 if IsIdenticalObj( HomalgRing( r1 ), HomalgRing( r2 ) ) then 731 return IsZero( r1 - r2 ); 732 fi; 733 734 return false; 735 736end ); 737 738## 739InstallMethod( \=, 740 "for a rational and a homalg ring element", 741 [ IS_RAT, IsHomalgRingElement ], 742 743 function( r1, r2 ) 744 745 return r1 / HomalgRing( r2 ) = r2; 746 747end ); 748 749## 750InstallMethod( \=, 751 "for a homalg ring element and a rational", 752 [ IsHomalgRingElement, IS_RAT ], 753 754 function( r1, r2 ) 755 756 return r1 = r2 / HomalgRing( r1 ); 757 758end ); 759 760## 761InstallMethod( StandardBasisRowVectors, 762 "for homalg rings", 763 [ IsInt, IsHomalgRing ], 764 765 function( n, R ) 766 local id; 767 768 id := HomalgIdentityMatrix( n, R ); 769 770 return List( [ 1 .. n ], r -> CertainRows( id, [ r ] ) ); 771 772end ); 773 774## 775InstallMethod( StandardBasisColumnVectors, 776 "for homalg rings", 777 [ IsInt, IsHomalgRing ], 778 779 function( n, R ) 780 local id; 781 782 id := HomalgIdentityMatrix( n, R ); 783 784 return List( [ 1 .. n ], c -> CertainColumns( id, [ c ] ) ); 785 786end ); 787 788## 789InstallMethod( RingName, 790 "for homalg rings", 791 [ IsHomalgRing ], 792 793 function( R ) 794 local RP, var, r, c; 795 796 if HasName( R ) then 797 return Name( R ); 798 fi; 799 800 ## ask the ring table 801 RP := homalgTable( R ); 802 803 if IsBound(RP!.RingName) then 804 805 if IsFunction( RP!.RingName ) then 806 r := RP!.RingName( R ); 807 else 808 r := RP!.RingName; 809 fi; 810 811 if r <> fail then 812 return r; 813 fi; 814 815 fi; 816 817 ## residue class rings/fields of the integers 818 if HasIsResidueClassRingOfTheIntegers( R ) and 819 IsResidueClassRingOfTheIntegers( R ) and 820 HasCharacteristic( R ) then 821 822 c := Characteristic( R ); 823 824 if c = 0 then 825 return "Z"; 826 elif IsPrime( c ) then 827 if HasDegreeOverPrimeField( R ) and DegreeOverPrimeField( R ) > 1 then 828 r := [ "GF(", String( c ), "^", String( DegreeOverPrimeField( R ) ), ")" ]; 829 else 830 r := [ "GF(", String( c ), ")" ]; 831 fi; 832 else 833 r := [ "Z/", String( c ), "Z" ]; 834 fi; 835 836 return String( Concatenation( r ) ); 837 838 fi; 839 840 ## the rationals 841 if HasIsRationalsForHomalg( R ) and IsRationalsForHomalg( R ) then 842 return "Q"; 843 fi; 844 845 return "(homalg ring)"; 846 847end ); 848 849## 850InstallMethod( homalgRingStatistics, 851 "for homalg rings", 852 [ IsHomalgRing ], 853 854 function( R ) 855 856 return R!.statistics; 857 858end ); 859 860## 861InstallMethod( IncreaseRingStatistics, 862 "for homalg rings", 863 [ IsHomalgRing, IsString ], 864 865 function( R, s ) 866 867 R!.statistics.(s) := R!.statistics.(s) + 1; 868 869end ); 870 871## 872InstallMethod( DecreaseRingStatistics, 873 "for homalg rings", 874 [ IsHomalgRing, IsString ], 875 876 function( R, s ) 877 878 R!.statistics.(s) := R!.statistics.(s) - 1; 879 880end ); 881 882## 883InstallOtherMethod( AsList, 884 "for homalg internal rings", 885 [ IsHomalgInternalRingRep ], 886 887 function( r ) 888 889 return AsList( r!.ring ); 890 891end ); 892 893## 894InstallMethod( homalgSetName, 895 "for homalg ring elements", 896 [ IsHomalgRingElement, IsString ], 897 898 SetName ); 899 900## 901InstallMethod( IrreducibleFactors, 902 "for ring elements", 903 [ IsRingElement ], 904 905 PrimeDivisors ); 906 907## 908InstallMethod( IrreducibleFactors, 909 "for homalg ring elements", 910 [ IsHomalgRingElement ], 911 912 function( r ) 913 local R, factors; 914 915 R := HomalgRing( r ); 916 917 if IsHomalgInternalRingRep( R ) then 918 if not IsBound( r!.IrreducibleFactors ) then 919 r!.IrreducibleFactors := PrimeDivisors( EvalString( String( r ) ) ); 920 fi; 921 fi; 922 923 factors := RadicalDecompositionOp( HomalgMatrix( [ r ], 1, 1, R ) ); 924 925 r!.Factors := List( factors, a -> a[ 1, 1 ] ); 926 927 return r!.Factors; 928 929end ); 930 931## 932InstallMethod( Factors, 933 "for homalg ring elements", 934 [ IsHomalgRingElement ], 935 936 function( r ) 937 local R, factors, primary, prime, one, divide; 938 939 R := HomalgRing( r ); 940 941 if IsHomalgInternalRingRep( R ) then 942 if not IsBound( r!.Factors ) then 943 r!.Factors := Factors( EvalString( String( r ) ) ); 944 fi; 945 fi; 946 947 factors := PrimaryDecompositionOp( HomalgMatrix( [ r ], 1, 1, R ) ); 948 949 primary := List( factors, a -> a[1][ 1, 1 ] ); 950 prime := List( factors, a -> a[2][ 1, 1 ] ); 951 952 one := One( R ); 953 954 divide := 955 function( q, p ) 956 local list; 957 958 list := [ ]; 959 960 repeat 961 q := q / p; 962 Add( list, p ); 963 until IsZero( DecideZero( one, q ) ); 964 965 return list; 966 967 end; 968 969 factors := List( [ 1 .. Length( factors ) ], i -> divide( primary[i], prime[i] ) ); 970 971 factors := Concatenation( factors ); 972 973 factors[1] := ( r / Product( factors ) ) * factors[1]; 974 975 r!.Factors := factors; 976 977 return r!.Factors; 978 979end ); 980 981## 982InstallMethod( Roots, 983 "for homalg ring elements", 984 [ IsHomalgRingElement ], 985 986 function( r ) 987 local R, roots; 988 989 R := HomalgRing( r ); 990 991 if not IsHomalgInternalRingRep( R ) then 992 TryNextMethod( ); 993 fi; 994 995 if not IsBound( r!.Roots ) then 996 roots := RootsOfUPol( EvalString( String( r ) ) ); 997 Sort( roots ); 998 r!.Roots := roots; 999 fi; 1000 1001 return r!.Roots; 1002 1003end ); 1004 1005## 1006InstallMethod( DecideZero, 1007 "for homalg ring elements", 1008 [ IsHomalgRingElement ], 1009 1010 function( r ) 1011 1012 IsZero( r ); 1013 1014 return r; 1015 1016end ); 1017 1018## 1019InstallMethod( SetRingProperties, 1020 "for homalg rings", 1021 [ IsHomalgRing and IsFreePolynomialRing, IsHomalgRing, IsList ], 1022 1023 function( S, R, var ) 1024 local param, paramS, d; 1025 1026 d := Length( var ); 1027 1028 if d > 0 then 1029 SetIsFinite( S, false ); 1030 fi; 1031 1032 SetCoefficientsRing( S, R ); 1033 1034 if HasRationalParameters( R ) then 1035 param := RationalParameters( R ); 1036 paramS := List( param, a -> a / S ); 1037 Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end ); 1038 SetRationalParameters( S, paramS ); 1039 fi; 1040 1041 if HasCharacteristic( R ) then 1042 SetCharacteristic( S, Characteristic( R ) ); 1043 fi; 1044 1045 SetIsCommutative( S, true ); 1046 1047 SetIndeterminatesOfPolynomialRing( S, var ); 1048 1049 if HasContainsAField( R ) and ContainsAField( R ) then 1050 SetContainsAField( S, true ); 1051 fi; 1052 1053 if d > 0 then 1054 SetIsLeftArtinian( S, false ); 1055 SetIsRightArtinian( S, false ); 1056 fi; 1057 1058 if HasGlobalDimension( R ) then 1059 SetGlobalDimension( S, d + GlobalDimension( R ) ); 1060 fi; 1061 1062 if HasKrullDimension( R ) then 1063 SetKrullDimension( S, d + KrullDimension( R ) ); 1064 fi; 1065 1066 SetGeneralLinearRank( S, 1 ); ## Quillen-Suslin Theorem (see [McCRob, 11.5.5] 1067 1068 if d = 1 then ## [McCRob, 11.5.7] 1069 SetElementaryRank( S, 1 ); 1070 elif d > 2 then 1071 SetElementaryRank( S, 2 ); 1072 fi; 1073 1074 SetIsIntegralDomain( S, true ); 1075 1076 SetBasisAlgorithmRespectsPrincipalIdeals( S, true ); 1077 1078end ); 1079 1080## 1081InstallMethod( SetRingProperties, 1082 "for homalg rings", 1083 [ IsHomalgRing and IsWeylRing, IsHomalgRing and IsFreePolynomialRing, IsList ], 1084 1085 function( S, R, der ) 1086 local r, b, param, paramS, var, d; 1087 1088 r := CoefficientsRing( R ); 1089 1090 if HasBaseRing( R ) then 1091 b := BaseRing( R ); 1092 else 1093 b := r; 1094 fi; 1095 1096 var := IndeterminatesOfPolynomialRing( R ); 1097 var := List( var, a -> a / S ); 1098 1099 d := Length( var ); 1100 1101 if d > 0 then 1102 SetIsFinite( S, false ); 1103 fi; 1104 1105 SetCoefficientsRing( S, r ); 1106 1107 if HasRationalParameters( r ) then 1108 param := RationalParameters( r ); 1109 paramS := List( param, a -> a / S ); 1110 Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramS[i], Name( param[i] ) ); end ); 1111 SetRationalParameters( S, paramS ); 1112 fi; 1113 1114 SetCharacteristic( S, Characteristic( R ) ); 1115 1116 SetIsCommutative( S, der = [ ] ); 1117 1118 SetCenter( S, Center( b ) ); 1119 1120 SetIndeterminateCoordinatesOfRingOfDerivations( S, var ); 1121 1122 if HasRelativeIndeterminatesOfPolynomialRing( R ) then 1123 SetRelativeIndeterminateCoordinatesOfRingOfDerivations( 1124 S, RelativeIndeterminatesOfPolynomialRing( R ) ); 1125 fi; 1126 1127 SetIndeterminateDerivationsOfRingOfDerivations( S, der ); 1128 1129 if d > 0 then 1130 SetIsLeftArtinian( S, false ); 1131 SetIsRightArtinian( S, false ); 1132 fi; 1133 1134 SetIsLeftNoetherian( S, true ); 1135 SetIsRightNoetherian( S, true ); 1136 1137 if HasGlobalDimension( r ) then 1138 SetGlobalDimension( S, d + GlobalDimension( r ) ); 1139 fi; 1140 1141 if HasIsFieldForHomalg( b ) and IsFieldForHomalg( b ) and Characteristic( S ) = 0 then 1142 SetGeneralLinearRank( S, 2 ); ## [Stafford78], [McCRob, 11.2.15(i)] 1143 SetIsSimpleRing( S, true ); ## [Coutinho, Thm 2.2.1] 1144 fi; 1145 1146 if HasIsIntegralDomain( r ) and IsIntegralDomain( r ) then 1147 SetIsIntegralDomain( S, true ); 1148 fi; 1149 1150 if d > 0 then 1151 SetIsLeftPrincipalIdealRing( S, false ); 1152 SetIsRightPrincipalIdealRing( S, false ); 1153 SetIsPrincipalIdealRing( S, false ); 1154 fi; 1155 1156 SetBasisAlgorithmRespectsPrincipalIdeals( S, true ); 1157 1158 SetAreUnitsCentral( S, true ); 1159 1160end ); 1161 1162## 1163InstallMethod( SetRingProperties, 1164 "for homalg rings", 1165 [ IsHomalgRing and IsLocalizedWeylRing, IsString ], 1166 1167 function( S, _var ) 1168 local var, d; 1169 1170 var := SplitString( _var, ",", "[]" ); 1171 var := List( var, a -> a / S ); 1172 1173 SetIndeterminateCoordinatesOfRingOfDerivations( S, var ); 1174 1175 d := Length( var ); 1176 1177 ## SetCoefficientsRing( S, r ); 1178 1179 SetCharacteristic( S, 0 ); 1180 1181 SetIsCommutative( S, false ); 1182 1183 ## SetCenter( S, r ); 1184 1185 SetIndeterminateCoordinatesOfRingOfDerivations( S, var ); 1186 1187 ## SetIndeterminateDerivationsOfRingOfDerivations( S, der ); 1188 1189 if d > 0 then 1190 SetIsLeftArtinian( S, false ); 1191 SetIsRightArtinian( S, false ); 1192 fi; 1193 1194 SetIsLeftNoetherian( S, true ); 1195 SetIsRightNoetherian( S, true ); 1196 1197 SetGlobalDimension( S, d + 0 ); ## Janet only knows Q as the coefficient ring 1198 1199 ## SetGeneralLinearRank( S, 2 ); ## [Stafford78], [McCRob, 11.2.15(i)] 1200 SetIsSimpleRing( S, true ); ## [Coutinho, Thm 2.2.1] 1201 1202 if d > 0 then 1203 SetIsPrincipalIdealRing( S, false ); 1204 fi; 1205 1206 if d = 1 then 1207 SetIsLeftPrincipalIdealRing( S, true ); 1208 SetIsRightPrincipalIdealRing( S, true ); 1209 elif d > 0 then 1210 SetIsLeftPrincipalIdealRing( S, false ); 1211 SetIsRightPrincipalIdealRing( S, false ); 1212 fi; 1213 1214 SetIsIntegralDomain( S, true ); 1215 1216 SetBasisAlgorithmRespectsPrincipalIdeals( S, true ); 1217 1218 SetAreUnitsCentral( S, false ); 1219 1220end ); 1221 1222## 1223InstallMethod( SetRingProperties, 1224 "for homalg rings", 1225 [ IsHomalgRing and IsExteriorRing, IsHomalgRing and IsFreePolynomialRing, IsList ], 1226 1227 function( A, S, anti ) 1228 local r, d, param, paramA, comm, T; 1229 1230 r := CoefficientsRing( S ); 1231 1232 d := Length( anti ); 1233 1234 SetCoefficientsRing( A, r ); 1235 1236 if HasRationalParameters( r ) then 1237 param := RationalParameters( r ); 1238 paramA := List( param, a -> a / A ); 1239 Perform( [ 1 .. Length( param ) ], function( i ) SetName( paramA[i], Name( param[i] ) ); end ); 1240 SetRationalParameters( A, paramA ); 1241 fi; 1242 1243 SetCharacteristic( A, Characteristic( S ) ); 1244 1245 if d <= 1 or Characteristic( A ) = 2 then 1246 1247 ## the Center is then automatically set to S 1248 SetIsCommutative( A, true ); 1249 1250 else 1251 1252 ## the center is the even part, which is 1253 ## bigger than the coefficients ring r 1254 SetIsCommutative( A, false ); 1255 1256 fi; 1257 1258 SetIsSuperCommutative( A, true ); 1259 1260 SetIsIntegralDomain( A, d = 0 ); 1261 1262 comm := [ ]; 1263 1264 if HasBaseRing( S ) then 1265 T := BaseRing( S ); 1266 if HasIndeterminatesOfPolynomialRing( T ) then 1267 comm := IndeterminatesOfPolynomialRing( T ); 1268 fi; 1269 fi; 1270 1271 SetIndeterminateAntiCommutingVariablesOfExteriorRing( A, anti ); 1272 1273 SetIndeterminatesOfExteriorRing( A, Concatenation( comm, anti ) ); 1274 1275 SetBasisAlgorithmRespectsPrincipalIdeals( A, true ); 1276 1277 SetAreUnitsCentral( S, true ); 1278 1279end ); 1280 1281## 1282InstallMethod( SetRingProperties, 1283 "for homalg rings", 1284 [ IsHomalgRing and IsPrincipalIdealRing and IsCommutative, IsInt ], 1285 1286 function( R, c ) 1287 local RP, powers; 1288 1289 SetCharacteristic( R, c ); 1290 1291 if HasIsFieldForHomalg( R ) and IsFieldForHomalg( R ) then 1292 TryNextMethod( ); 1293 elif HasIsResidueClassRingOfTheIntegers( R ) and 1294 IsResidueClassRingOfTheIntegers( R ) then 1295 TryNextMethod( ); 1296 fi; 1297 1298 if c = 0 then 1299 SetContainsAField( R, false ); 1300 SetIsIntegralDomain( R, true ); 1301 SetIsArtinian( R, false ); 1302 SetKrullDimension( R, 1 ); ## FIXME: it is not set automatically although an immediate method is installed 1303 elif not IsPrime( c ) then 1304 SetIsSemiLocalRing( R, true ); 1305 SetIsIntegralDomain( R, false ); 1306 powers := List( Collected( FactorsInt( c ) ), a -> a[2] ); 1307 if Set( powers ) = [ 1 ] then 1308 SetIsSemiSimpleRing( R, true ); 1309 else 1310 SetIsRegular( R, false ); 1311 if Length( powers ) = 1 then 1312 SetIsLocal( R, true ); 1313 fi; 1314 fi; 1315 SetKrullDimension( R, 0 ); 1316 fi; 1317 1318 RP := homalgTable( R ); 1319 1320 if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then 1321 if IsBound( RP!.RowRankOfMatrixOverDomain ) then 1322 RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain; 1323 fi; 1324 1325 if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then 1326 RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain; 1327 fi; 1328 fi; 1329 1330 SetBasisAlgorithmRespectsPrincipalIdeals( R, true ); 1331 1332end ); 1333 1334## 1335InstallMethod( SetRingProperties, 1336 "for homalg rings", 1337 [ IsHomalgRing and IsResidueClassRingOfTheIntegers, IsInt ], 1338 1339 function( R, c ) 1340 local RP, powers; 1341 1342 SetCharacteristic( R, c ); 1343 1344 SetIsRationalsForHomalg( R, false ); 1345 1346 if c = 0 then 1347 SetIsIntegersForHomalg( R, true ); 1348 SetContainsAField( R, false ); 1349 SetIsArtinian( R, false ); 1350 SetKrullDimension( R, 1 ); ## FIXME: it is not set automatically although an immediate method is installed 1351 elif IsPrime( c ) then 1352 SetIsFieldForHomalg( R, true ); 1353 SetRingProperties( R, c ); 1354 else 1355 SetIsSemiLocalRing( R, true ); 1356 SetIsIntegralDomain( R, false ); 1357 powers := List( Collected( FactorsInt( c ) ), a -> a[2] ); 1358 if Set( powers ) = [ 1 ] then 1359 SetIsSemiSimpleRing( R, true ); 1360 else 1361 SetIsRegular( R, false ); 1362 if Length( powers ) = 1 then 1363 SetIsLocal( R, true ); 1364 fi; 1365 fi; 1366 SetKrullDimension( R, 0 ); 1367 fi; 1368 1369 RP := homalgTable( R ); 1370 1371 if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then 1372 if IsBound( RP!.RowRankOfMatrixOverDomain ) then 1373 RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain; 1374 fi; 1375 1376 if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then 1377 RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain; 1378 fi; 1379 fi; 1380 1381 SetBasisAlgorithmRespectsPrincipalIdeals( R, true ); 1382 1383end ); 1384 1385## 1386InstallMethod( SetRingProperties, 1387 "for homalg rings", 1388 [ IsHomalgRing and IsFieldForHomalg, IsInt ], 1389 1390 function( R, c ) 1391 local RP; 1392 1393 SetCharacteristic( R, c ); 1394 1395 if HasRationalParameters( R ) and Length( RationalParameters( R ) ) > 0 then 1396 SetIsRationalsForHomalg( R, false ); 1397 SetIsResidueClassRingOfTheIntegers( R, false ); 1398 else 1399 SetDegreeOverPrimeField( R, 1 ); 1400 fi; 1401 1402 RP := homalgTable( R ); 1403 1404 if IsBound( RP!.RowRankOfMatrixOverDomain ) then 1405 RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain; 1406 fi; 1407 1408 if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then 1409 RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain; 1410 fi; 1411 1412 SetFilterObj( R, IsField ); 1413 SetLeftActingDomain( R, R ); 1414 1415 SetBasisAlgorithmRespectsPrincipalIdeals( R, true ); 1416 1417end ); 1418 1419## 1420InstallMethod( SetRingProperties, 1421 "for homalg rings", 1422 [ IsHomalgRing and IsFieldForHomalg, IsInt, IsInt ], 1423 1424 function( R, c, d ) 1425 local RP; 1426 1427 SetCharacteristic( R, c ); 1428 SetDegreeOverPrimeField( R, d ); 1429 1430 if HasRationalParameters( R ) and Length( RationalParameters( R ) ) > 0 then 1431 SetIsRationalsForHomalg( R, false ); 1432 SetIsResidueClassRingOfTheIntegers( R, false ); 1433 fi; 1434 1435 RP := homalgTable( R ); 1436 1437 if IsBound( RP!.RowRankOfMatrixOverDomain ) then 1438 RP!.RowRankOfMatrix := RP!.RowRankOfMatrixOverDomain; 1439 fi; 1440 1441 if IsBound( RP!.ColumnRankOfMatrixOverDomain ) then 1442 RP!.ColumnRankOfMatrix := RP!.ColumnRankOfMatrixOverDomain; 1443 fi; 1444 1445 SetFilterObj( R, IsField ); 1446 SetLeftActingDomain( R, R ); 1447 1448 SetBasisAlgorithmRespectsPrincipalIdeals( R, true ); 1449 1450end ); 1451 1452## 1453InstallMethod( UnusedVariableName, 1454 "for a homalg ring and a string", 1455 [ IsHomalgRing, IsString ], 1456 1457 function( R, t ) 1458 local var; 1459 1460 var := [ ]; 1461 1462 if HasRationalParameters( R ) then 1463 Append( var, List( RationalParameters( R ), Name ) ); 1464 fi; 1465 1466 if HasIndeterminatesOfPolynomialRing( R ) then 1467 Append( var, List( IndeterminatesOfPolynomialRing( R ), Name ) ); 1468 fi; 1469 1470 while true do 1471 1472 if not t in var then 1473 return t; 1474 fi; 1475 1476 t := Concatenation( t, "_" ); 1477 od; 1478 1479end ); 1480 1481## 1482InstallMethod( EuclideanQuotient, 1483 "for a homalg ring and two homalg ring elements", 1484 [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ], 1485 1486 function( R, a, b ) 1487 1488 return EuclideanQuotient( R!.ring, a, b ); 1489 1490end ); 1491 1492## 1493InstallMethod( EuclideanRemainder, 1494 "for a homalg ring and two homalg ring elements", 1495 [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ], 1496 1497 function( R, a, b ) 1498 1499 return EuclideanRemainder( R!.ring, a, b ); 1500 1501end ); 1502 1503## 1504InstallMethod( QuotientRemainder, 1505 "for a homalg ring and two homalg ring elements", 1506 [ IsHomalgInternalRingRep and IsPrincipalIdealRing and IsCommutative, IsRingElement, IsRingElement ], 1507 1508 function( R, a, b ) 1509 1510 return QuotientRemainder( R!.ring, a, b ); 1511 1512end ); 1513 1514#################################### 1515# 1516# constructor functions and methods: 1517# 1518#################################### 1519 1520## 1521InstallGlobalFunction( CreateHomalgRing, 1522 function( arg ) 1523 local nargs, r, IdentityMatrices, statistics, asserts, 1524 homalg_ring, table, properties, ar, type, matrix_type, 1525 ring_element_constructor, finalizers, c, el; 1526 1527 nargs := Length( arg ); 1528 1529 if nargs = 0 then 1530 Error( "expecting a ring as the first argument\n" ); 1531 fi; 1532 1533 r := arg[1]; 1534 1535 IdentityMatrices := ContainerForWeakPointers( TheTypeContainerForWeakPointersOnIdentityMatrices ); 1536 Unbind( IdentityMatrices!.active ); 1537 Unbind( IdentityMatrices!.deleted ); 1538 Unbind( IdentityMatrices!.accessed ); 1539 Unbind( IdentityMatrices!.cache_misses ); 1540 1541 statistics := rec( 1542 BasisOfRowModule := 0, 1543 BasisOfColumnModule := 0, 1544 BasisOfRowsCoeff := 0, 1545 BasisOfColumnsCoeff := 0, 1546 DecideZeroRows := 0, 1547 DecideZeroColumns := 0, 1548 DecideZeroRowsEffectively := 0, 1549 DecideZeroColumnsEffectively := 0, 1550 SyzygiesGeneratorsOfRows := 0, 1551 SyzygiesGeneratorsOfColumns := 0, 1552 RelativeSyzygiesGeneratorsOfRows := 0, 1553 RelativeSyzygiesGeneratorsOfColumns := 0, 1554 PartiallyReducedBasisOfRowModule := 0, 1555 PartiallyReducedBasisOfColumnModule := 0, 1556 ReducedBasisOfRowModule := 0, 1557 ReducedBasisOfColumnModule := 0, 1558 ReducedSyzygiesGeneratorsOfRows := 0, 1559 ReducedSyzygiesGeneratorsOfColumns := 0 1560 ); 1561 1562 1563 ## <#GAPDoc Label="asserts"> 1564 ## Below you can find the record of the available level-4 assertions, 1565 ## which is a &GAP;-component of every &homalg; ring. Each assertion can 1566 ## thus be overwritten by package developers or even ordinary users. 1567 ## <Listing Type="Code"><![CDATA[ 1568 asserts := 1569 rec( 1570 BasisOfRowModule := 1571 function( B ) return ( NrRows( B ) = 0 ) = IsZero( B ); end, 1572 1573 BasisOfColumnModule := 1574 function( B ) return ( NrColumns( B ) = 0 ) = IsZero( B ); end, 1575 1576 BasisOfRowsCoeff := 1577 function( B, T, M ) return B = T * M; end, 1578 1579 BasisOfColumnsCoeff := 1580 function( B, M, T ) return B = M * T; end, 1581 1582 DecideZeroRows_Effectively := 1583 function( M, A, B ) return M = DecideZeroRows( A, B ); end, 1584 1585 DecideZeroColumns_Effectively := 1586 function( M, A, B ) return M = DecideZeroColumns( A, B ); end, 1587 1588 DecideZeroRowsEffectively := 1589 function( M, A, T, B ) return M = A + T * B; end, 1590 1591 DecideZeroColumnsEffectively := 1592 function( M, A, B, T ) return M = A + B * T; end, 1593 1594 DecideZeroRowsWRTNonBasis := 1595 function( B ) 1596 local R; 1597 R := HomalgRing( B ); 1598 if not ( HasIsBasisOfRowsMatrix( B ) and 1599 IsBasisOfRowsMatrix( B ) ) and 1600 IsBound( R!.DecideZeroWRTNonBasis ) then 1601 if R!.DecideZeroWRTNonBasis = "warn" then 1602 Info( InfoWarning, 1, 1603 "about to reduce with respect to a matrix", 1604 "with IsBasisOfRowsMatrix not set to true" ); 1605 elif R!.DecideZeroWRTNonBasis = "error" then 1606 Error( "about to reduce with respect to a matrix", 1607 "with IsBasisOfRowsMatrix not set to true\n" ); 1608 fi; 1609 fi; 1610 end, 1611 1612 DecideZeroColumnsWRTNonBasis := 1613 function( B ) 1614 local R; 1615 R := HomalgRing( B ); 1616 if not ( HasIsBasisOfColumnsMatrix( B ) and 1617 IsBasisOfColumnsMatrix( B ) ) and 1618 IsBound( R!.DecideZeroWRTNonBasis ) then 1619 if R!.DecideZeroWRTNonBasis = "warn" then 1620 Info( InfoWarning, 1, 1621 "about to reduce with respect to a matrix", 1622 "with IsBasisOfColumnsMatrix not set to true" ); 1623 elif R!.DecideZeroWRTNonBasis = "error" then 1624 Error( "about to reduce with respect to a matrix", 1625 "with IsBasisOfColumnsMatrix not set to true\n" ); 1626 fi; 1627 fi; 1628 end, 1629 1630 ReducedBasisOfRowModule := 1631 function( M, B ) 1632 return GenerateSameRowModule( B, BasisOfRowModule( M ) ); 1633 end, 1634 1635 ReducedBasisOfColumnModule := 1636 function( M, B ) 1637 return GenerateSameColumnModule( B, BasisOfColumnModule( M ) ); 1638 end, 1639 1640 ReducedSyzygiesGeneratorsOfRows := 1641 function( M, S ) 1642 return GenerateSameRowModule( S, SyzygiesGeneratorsOfRows( M ) ); 1643 end, 1644 1645 ReducedSyzygiesGeneratorsOfColumns := 1646 function( M, S ) 1647 return GenerateSameColumnModule( S, SyzygiesGeneratorsOfColumns( M ) ); 1648 end, 1649 1650 ); 1651 ## ]]></Listing> 1652 ## <#/GAPDoc> 1653 1654 homalg_ring := rec( 1655 ring := r, 1656 IdentityMatrices := IdentityMatrices, 1657 statistics := statistics, 1658 asserts := asserts, 1659 DecideZeroWRTNonBasis := "warn/error" 1660 ); 1661 1662 if nargs > 1 and IshomalgTable( arg[nargs] ) then 1663 table := arg[nargs]; 1664 else 1665 table := CreateHomalgTable( r ); 1666 fi; 1667 1668 if not IsBound( table!.InitialMatrix ) and IsBound( table!.ZeroMatrix ) then 1669 table!.InitialMatrix := table!.ZeroMatrix; 1670 fi; 1671 1672 if not IsBound( table!.InitialIdentityMatrix ) and IsBound( table!.IdentityMatrix ) then 1673 table!.InitialIdentityMatrix := table!.IdentityMatrix; 1674 fi; 1675 1676 properties := [ ]; 1677 1678 for ar in arg{[ 2 .. nargs ]} do 1679 if IsFilter( ar ) then 1680 Add( properties, ar ); 1681 elif not IsBound( type ) and IsList( ar ) and Length( ar ) = 2 and ForAll( ar, IsType ) then 1682 type := ar; 1683 elif not IsBound( ring_element_constructor ) and IsFunction( ar ) then 1684 ring_element_constructor := ar; 1685 elif not IsBound( finalizers ) and IsList( ar ) and ForAll( ar, IsFunction ) then 1686 finalizers := ar; 1687 fi; 1688 od; 1689 1690 if IsBound( type ) then 1691 matrix_type := type[2]; 1692 type := type[1]; 1693 elif IsSemiringWithOneAndZero( r ) then 1694 matrix_type := ValueGlobal( "TheTypeHomalgInternalMatrix" ); ## will be defined later in HomalgMatrix.gi 1695 type := TheTypeHomalgInternalRing; 1696 else 1697 Error( "the types of the ring and matrices were not specified\n" ); 1698 fi; 1699 1700 ## Objectify: 1701 ObjectifyWithAttributes( 1702 homalg_ring, type, 1703 homalgTable, table ); 1704 1705 if IsBound( matrix_type ) then 1706 SetTypeOfHomalgMatrix( homalg_ring, matrix_type ); 1707 fi; 1708 1709 if properties <> [ ] then 1710 for ar in properties do 1711 Setter( ar )( homalg_ring, true ); 1712 od; 1713 fi; 1714 1715 if IsBound( HOMALG_MATRICES.RingCounter ) then 1716 HOMALG_MATRICES.RingCounter := HOMALG_MATRICES.RingCounter + 1; 1717 else 1718 HOMALG_MATRICES.RingCounter := 1; 1719 fi; 1720 1721 ## this has to be done before we call 1722 ## ring_element_constructor below 1723 homalg_ring!.creation_number := HOMALG_MATRICES.RingCounter; 1724 1725 ## do not invoke SetRingProperties here, since I might be 1726 ## the first step of creating a residue class ring! 1727 1728 ## this has to be invoked before we set the distinguished ring elements below; 1729 ## these functions are used to finalize the construction of the ring 1730 if IsBound( finalizers ) then 1731 Perform( finalizers, function( f ) f( homalg_ring ); end ); 1732 fi; 1733 1734 ## add distinguished ring elements like 0 and 1 1735 ## (sometimes also -1) to the homalg table: 1736 if IsBound( ring_element_constructor ) then 1737 1738 for c in NamesOfComponents( table ) do 1739 if IsRingElement( table!.(c) ) then 1740 table!.(c) := ring_element_constructor( table!.(c), homalg_ring ); 1741 fi; 1742 od; 1743 1744 ## set the attribute 1745 SetRingElementConstructor( homalg_ring, ring_element_constructor ); 1746 1747 fi; 1748 1749 if IsBound( HOMALG_MATRICES.ByASmallerPresentation ) and HOMALG_MATRICES.ByASmallerPresentation = true then 1750 homalg_ring!.ByASmallerPresentation := true; 1751 fi; 1752 1753 ## e.g. needed to construct residue class rings 1754 homalg_ring!.ConstructorArguments := arg; 1755 1756 homalg_ring!.interpret_rationals_func := 1757 function( r ) 1758 local d; 1759 d := DenominatorRat( r ) / homalg_ring; 1760 if IsZero( d ) or not IsUnit( homalg_ring, d ) then 1761 return fail; 1762 fi; 1763 return r / homalg_ring; 1764 end; 1765 1766 return homalg_ring; 1767 1768end ); 1769 1770## <#GAPDoc Label="HomalgRingOfIntegers"> 1771## <ManSection> 1772## <Func Arg="" Name="HomalgRingOfIntegers" Label="constructor for the integers"/> 1773## <Returns>a &homalg; ring</Returns> 1774## <Func Arg="c" Name="HomalgRingOfIntegers" Label="constructor for the residue class rings of the integers"/> 1775## <Returns>a &homalg; ring</Returns> 1776## <Description> 1777## The no-argument form returns the ring of integers <M>&ZZ;</M> for &homalg;. <P/> 1778## The one-argument form accepts an integer <A>c</A> and returns 1779## the ring <M>&ZZ; / c </M> for &homalg;: 1780## <List> 1781## <Item><A>c</A><M> = 0</M> defaults to <M>&ZZ;</M></Item> 1782## <Item>if <A>c</A> is a prime power then the package &GaussForHomalg; is loaded (if it fails to load an error is issued)</Item> 1783## <Item>otherwise, the residue class ring constructor <C>/</C> 1784## (&see; <Ref Oper="\/" Label="constructor for residue class rings" Style="Number"/>) is invoked</Item> 1785## </List> 1786## The operation <C>SetRingProperties</C> is automatically invoked to set the ring properties. <P/> 1787## If for some reason you don't want to use the &GaussForHomalg; package (maybe because you didn't install it), then use<P/> 1788## <C>HomalgRingOfIntegers</C>( ) <C>/</C> <A>c</A>; <P/> 1789## but note that the computations will then be considerably slower. 1790## </Description> 1791## </ManSection> 1792## <#/GAPDoc> 1793## 1794InstallGlobalFunction( HomalgRingOfIntegers, 1795 function( arg ) 1796 local nargs, R, c, d, rel; 1797 1798 nargs := Length( arg ); 1799 1800 if nargs = 0 or arg[1] = 0 then 1801 c := 0; 1802 R := CreateHomalgRing( Integers ); 1803 elif IsInt( arg[1] ) then 1804 c := arg[1]; 1805 if Length( Collected( FactorsInt( c ) ) ) = 1 and IsPackageMarkedForLoading( "GaussForHomalg", ">= 2018.09.20") then 1806 R := HOMALG_RING_OF_INTEGERS_PRIME_POWER_HELPER( arg, c ); 1807 else 1808 R := HomalgRingOfIntegers( ); 1809 rel := HomalgRingRelationsAsGeneratorsOfLeftIdeal( [ c ], R ); 1810 return R / rel; 1811 fi; 1812 else 1813 Error( "the first argument must be an integer\n" ); 1814 fi; 1815 1816 SetIsResidueClassRingOfTheIntegers( R, true ); 1817 1818 SetRingProperties( R, c ); 1819 1820 return R; 1821 1822end ); 1823 1824## 1825InstallMethod( HomalgRingOfIntegersInUnderlyingCAS, 1826 "for an integer and homalg internal ring", 1827 [ IsInt, IsHomalgInternalRingRep ], 1828 1829 HomalgRingOfIntegers ); 1830 1831## 1832InstallOtherMethod( \in, 1833 "for an integer and a homalg internal ring", 1834 [ IsObject, IsHomalgInternalRingRep ], 100001, 1835 1836 function( z, R ) 1837 1838 if not IsInt( Zero( R ) ) then 1839 TryNextMethod( ); 1840 fi; 1841 1842 if IsInt( z ) then 1843 return true; 1844 fi; 1845 1846 if not ( HasIsFieldForHomalg( R ) and IsFieldForHomalg( R ) ) then 1847 TryNextMethod( ); 1848 fi; 1849 1850 if IsRat( z ) then 1851 return true; 1852 fi; 1853 1854 TryNextMethod( ); 1855 1856end ); 1857 1858## 1859InstallMethod( ParseListOfIndeterminates, 1860 "for lists", 1861 [ IsList ], 1862 1863 function( _indets ) 1864 local err, l, indets, i, v, l1, l2, p1, p2, c; 1865 1866 if _indets = [ ] then 1867 return [ ]; 1868 fi; 1869 1870 err := function( ) Error( "a list of variable strings or range strings is expected\n" ); end; 1871 1872 if ForAll( _indets, IsRingElement and HasName ) then 1873 return ParseListOfIndeterminates( List( _indets, Name ) ); 1874 fi; 1875 1876 if not ForAll( _indets, e -> IsStringRep( e ) or ( IsList( e ) and ForAll( e, IsInt ) ) ) then 1877 TryNextMethod( ); 1878 fi; 1879 1880 l := Length( _indets ); 1881 1882 indets := [ ]; 1883 1884 for i in [ 1 .. l ] do 1885 v := _indets[i]; 1886 if Position( v, ',' ) <> fail then 1887 err( ); 1888 elif ForAll( v, IsInt ) then 1889 ## do nothing 1890 elif Position( v, '.' ) = fail then 1891 if i < l and ForAll( _indets[ i + 1 ], IsInt ) then 1892 Append( indets, List( _indets[ i + 1 ], i -> Concatenation( v, String( i ) ) ) ); 1893 else 1894 Add( indets, v ); 1895 fi; 1896 elif PositionSublist( v, ".." ) = fail then 1897 err( ); 1898 else 1899 v := SplitString( v, "." ); 1900 v := Filtered( v, s -> not IsEmpty( s ) ); 1901 if Length( v ) <> 2 then 1902 err( ); 1903 fi; 1904# p1 := PositionProperty( v[1], c -> Position( "0123456789", c ) <> fail ); 1905# p2 := PositionProperty( v[2], c -> Position( "0123456789", c ) <> fail ); 1906 l1 := Flat( List( "0123456789", c -> Positions( v[1], c ) ) ); 1907 Sort( l1 ); 1908 l2 := Flat( List( "0123456789", c -> Positions( v[2], c ) ) ); 1909 Sort( l2 ); 1910 if l1 = [] or l2 = [] then 1911 err( ); 1912 fi; 1913 p1 := l1[1]; 1914 p2 := l2[1]; 1915 for i in [ 2 .. Length( l1 ) ] do 1916 if l1[i-1] + 1 <> l1[i] then 1917 p1 := l1[i]; 1918 fi; 1919 od; 1920 for i in [ 2 .. Length( l2 ) ] do 1921 if l2[i-1] + 1 <> l2[i] then 1922 p2 := l2[i]; 1923 fi; 1924 od; 1925 if p1 = 1 then 1926 err( ); 1927 fi; 1928 c := v[1]{[ 1 .. p1 - 1 ]}; 1929 if p1 = p2 and c <> v[2]{[ 1 .. p2 - 1 ]} then 1930 err( ); 1931 fi; 1932 p1 := EvalString( v[1]{[ p1 .. Length( v[1] ) ]} ); 1933 p2 := EvalString( v[2]{[ p2 .. Length( v[2] ) ]} ); 1934 Append( indets, List( [ p1 .. p2 ], i -> Concatenation( c, String( i ) ) ) ); 1935 fi; 1936 od; 1937 1938 return indets; 1939 1940end ); 1941 1942## 1943InstallGlobalFunction( _PrepareInputForPolynomialRing, 1944 function( R, indets ) 1945 local var, nr_var, properties, r, var_of_base_ring, param; 1946 1947 if HasRingRelations( R ) then 1948 Error( "polynomial rings over homalg residue class rings are not supported yet\nUse the generic residue class ring constructor '/' provided by homalg after defining the ambient ring\nfor help type: ?homalg: constructor for residue class rings\n" ); 1949 fi; 1950 1951 ## get the new indeterminates for the ring and save them in var 1952 if IsString( indets ) and indets <> "" then 1953 var := SplitString( indets, "," ); 1954 elif indets <> [ ] and ForAll( indets, i -> IsString( i ) and i <> "" ) then 1955 var := indets; 1956 else 1957 Error( "either a non-empty list of indeterminates or a comma separated string of them must be provided as the second argument\n" ); 1958 fi; 1959 1960 if not IsDuplicateFree( var ) then 1961 Error( "your list of indeterminates is not duplicate free: ", var, "\n" ); 1962 fi; 1963 1964 nr_var := Length( var ); 1965 1966 properties := [ IsCommutative ]; 1967 1968 ## K[x] is a principal ideal ring for a field K 1969 if Length( var ) = 1 and HasIsFieldForHomalg( R ) and IsFieldForHomalg( R ) then 1970 Add( properties, IsPrincipalIdealRing ); 1971 fi; 1972 1973 ## r is set to the ring of coefficients 1974 ## further a check is done, whether the old indeterminates (if exist) and the new 1975 ## ones are disjoint 1976 if HasIndeterminatesOfPolynomialRing( R ) then 1977 r := CoefficientsRing( R ); 1978 var_of_base_ring := IndeterminatesOfPolynomialRing( R ); 1979 var_of_base_ring := List( var_of_base_ring, Name ); 1980 if Intersection2( var_of_base_ring, var ) <> [ ] then 1981 Error( "the following indeterminates are already elements of the base ring: ", Intersection2( var_of_base_ring, var ), "\n" ); 1982 fi; 1983 else 1984 r := R; 1985 var_of_base_ring := [ ]; 1986 fi; 1987 1988 var := Concatenation( var_of_base_ring, var ); 1989 1990 if HasRationalParameters( r ) then 1991 param := Concatenation( ",", JoinStringsWithSeparator( RationalParameters( r ) ) ); 1992 else 1993 param := ""; 1994 fi; 1995 1996 return [ r, var, nr_var, properties, param ]; 1997 1998end ); 1999 2000## 2001InstallMethod( PolynomialRing, 2002 "for homalg internal rings", 2003 [ IsHomalgInternalRingRep, IsList ], 2004 2005 function( R, indets ) 2006 local ar, r, var, nr_var, properties, S, l; 2007 2008 ar := _PrepareInputForPolynomialRing( R, indets ); 2009 2010 r := ar[1]; 2011 var := ar[2]; ## all indeterminates, relative and base 2012 nr_var := ar[3]; ## the number of relative indeterminates 2013 properties := ar[4]; 2014 2015 ## create the new ring 2016 S := PolynomialRing( r!.ring, var ); 2017 2018 var := IndeterminatesOfPolynomialRing( S ); 2019 2020 S := CallFuncList( CreateHomalgRing, Concatenation( [ S ], properties ) ); 2021 2022 SetIsFreePolynomialRing( S, true ); 2023 2024 if HasIndeterminatesOfPolynomialRing( R ) and IndeterminatesOfPolynomialRing( R ) <> [ ] then 2025 SetBaseRing( S, R ); 2026 l := Length( var ); 2027 SetRelativeIndeterminatesOfPolynomialRing( S, var{[ l - nr_var + 1 .. l ]} ); 2028 fi; 2029 2030 SetRingProperties( S, r, var ); 2031 2032 S!.pre_matrix_constructor := a -> One( S ) * a; 2033 2034 return S; 2035 2036end ); 2037 2038## 2039InstallMethod( \*, 2040 "for homalg rings", 2041 [ IsHomalgRing, IsList ], 1001, ## a high rank is necessary to overwrite the default behaviour of applying R to each list element 2042 2043 function( R, indets ) 2044 2045 return PolynomialRing( R, ParseListOfIndeterminates( indets ) ); 2046 2047end ); 2048 2049## 2050InstallMethod( \*, 2051 "for homalg rings", 2052 [ IsHomalgRing, IsString ], 1001, ## for this method to be triggered first it has to have at least the same rank as the above method 2053 2054 function( R, indets ) 2055 2056 if indets = "" then 2057 return R; 2058 else 2059 return R * SplitString( indets, "," ); 2060 fi; 2061 2062end ); 2063 2064## 2065InstallOtherMethod( \[\], 2066 "for homalg rings", 2067 [ IsHomalgRing, IsString ], 1001, ## for this method to be triggered first it has to have at least the same rank as the above method 2068 2069 function( R, indets ) 2070 2071 return R * indets; 2072 2073end ); 2074 2075## 2076InstallMethod( \*, 2077 "for homalg rings", 2078 [ IsHomalgRing and IsFreePolynomialRing and HasCoefficientsRing, 2079 IsHomalgRing and IsFreePolynomialRing and HasCoefficientsRing ], 2080 2081 function( R1, R2 ) 2082 local r, var2; 2083 2084 r := CoefficientsRing( R1 ); 2085 2086 if not IsIdenticalObj( r, CoefficientsRing( R2 ) ) then 2087 TryNextMethod( ); 2088 fi; 2089 2090 var2 := IndeterminatesOfPolynomialRing( R2 ); 2091 var2 := List( var2, Name ); 2092 var2 := JoinStringsWithSeparator( var2 ); 2093 2094 return PolynomialRing( R1, var2 ); 2095 2096end ); 2097 2098## 2099InstallMethod( PolynomialRing, 2100 "for homalg rings", 2101 [ IsHomalgRing, IsString ], 1001, 2102 2103 function( R, _var ) 2104 local var; 2105 2106 if _var = "" then 2107 return R; 2108 fi; 2109 2110 var := ParseListOfIndeterminates( SplitString( _var, "," ) ); 2111 2112 return PolynomialRing( R, var ); 2113 2114end ); 2115 2116## 2117InstallMethod( PolynomialRingWithLexicographicOrdering, 2118 "for homalg rings", 2119 [ IsHomalgRing and HasIndeterminatesOfPolynomialRing ], 2120 2121 function( R ) 2122 local indets; 2123 2124 indets := IndeterminatesOfPolynomialRing( R ); 2125 2126 indets := List( indets, String ); 2127 2128 return PolynomialRing( CoefficientsRing( R ), indets : order := "lex" ); 2129 2130end ); 2131 2132## 2133InstallMethod( RingOfDerivations, 2134 "for homalg rings", 2135 [ IsHomalgRing and IsCommutative, IsString ], 1001, 2136 2137 function( S, _der ) 2138 local der, A; 2139 2140 der := ParseListOfIndeterminates( SplitString( _der, "," ) ); 2141 2142 A := RingOfDerivations( S, der ); 2143 2144 S!.RingOfDerivations := A; 2145 2146 return A; 2147 2148end ); 2149 2150## 2151InstallMethod( RingOfDerivations, 2152 "for homalg rings", 2153 [ IsHomalgRing ], 2154 2155 function( R ) 2156 local var, A; 2157 2158 if IsBound(R!.RingOfDerivations) then 2159 return R!.RingOfDerivations; 2160 fi; 2161 2162 if HasRelativeIndeterminatesOfPolynomialRing( R ) then 2163 var := RelativeIndeterminatesOfPolynomialRing( R ); 2164 else 2165 var := IndeterminatesOfPolynomialRing( R ); 2166 fi; 2167 2168 var := List( var, x -> Concatenation( "D", Name( x ) ) ); 2169 2170 A := RingOfDerivations( R, var ); 2171 2172 R!.RingOfDerivations := A; 2173 2174 return A; 2175 2176end ); 2177 2178## 2179InstallMethod( ExteriorRing, 2180 "for homalg rings", 2181 [ IsHomalgRing and IsFreePolynomialRing, IsList ], 2182 2183 function( S, _anti ) 2184 local anti, Base, A; 2185 2186 if IsString( _anti ) then 2187 return ExteriorRing( S, SplitString( _anti, "," ) ); 2188 else 2189 anti := ParseListOfIndeterminates( _anti ); 2190 fi; 2191 2192 if HasBaseRing( S ) then 2193 Base := BaseRing( S ); 2194 else 2195 Base := CoefficientsRing( S ); 2196 fi; 2197 A := ExteriorRing( S, CoefficientsRing( S ), Base, anti ); 2198 2199 SetRingProperties( A, S, anti ); 2200 2201 return A; 2202 2203end ); 2204 2205## 2206InstallMethod( KoszulDualRing, 2207 "for homalg rings", 2208 [ IsHomalgRing and IsFreePolynomialRing, IsList ], 2209 2210 function( S, anti ) 2211 local A; 2212 2213 if IsBound(S!.KoszulDualRing) then 2214 return S!.KoszulDualRing; 2215 fi; 2216 2217 A := ExteriorRing( S, anti ); 2218 2219 ## thanks GAP4 2220 A!.KoszulDualRing := S; 2221 S!.KoszulDualRing := A; 2222 2223 return A; 2224 2225end ); 2226 2227## 2228InstallMethod( KoszulDualRing, 2229 "for homalg rings", 2230 [ IsHomalgRing ], 10000, 2231 2232 function( S ) 2233 2234 if IsBound(S!.KoszulDualRing) then 2235 return S!.KoszulDualRing; 2236 fi; 2237 2238 TryNextMethod( ); 2239 2240end ); 2241 2242## 2243InstallMethod( KoszulDualRing, 2244 "for homalg rings", 2245 [ IsHomalgRing and IsFreePolynomialRing ], 2246 2247 function( S ) 2248 local l, Base, l_base, s1, s2, i; 2249 2250 l := IndeterminatesOfPolynomialRing( S ); 2251 2252 if HasBaseRing( S ) then 2253 Base := BaseRing( S ); 2254 else 2255 Base := CoefficientsRing( S ); 2256 fi; 2257 2258 if HasIsFreePolynomialRing( Base ) and IsFreePolynomialRing( Base ) then 2259 l_base := List( Indeterminates( Base ), a -> a / S ); 2260 else 2261 l_base := []; 2262 fi; 2263 2264 l := Difference( l, l_base ); 2265 2266 s1 := List( l, String ); 2267 2268 l := Length( l ); 2269 2270 s2 := List( [ 0 .. l - 1 ], a -> Concatenation( "e", String( a ) ) ); 2271 2272 for i in s1 do 2273 if not ( Position( s2, i ) = fail ) then 2274 Info( InfoWarning, 1, 2275 "KoszulDualRing: Variable name ", i, " already in use" 2276 ); 2277 fi; 2278 od; 2279 2280 return KoszulDualRing( S, s2 ); 2281 2282end ); 2283 2284## 2285InstallGlobalFunction( HomalgRingElement, 2286 function( arg ) 2287 local nargs, R; 2288 2289 nargs := Length( arg ); 2290 2291 R := arg[nargs]; 2292 2293 if HasRingElementConstructor( R ) then 2294 return CallFuncList( RingElementConstructor( R ), arg ); 2295 elif not IsHomalgInternalRingRep( R ) then 2296 Error( "the non-internal homalg ring must contain a ring element constructor as the attribute RingElementConstructor\n" ); 2297 elif IsString( arg[1] ) then 2298 return One( R ) * EvalString( arg[1] ); 2299 fi; 2300 2301 return One( R ) * arg[1]; 2302 2303end ); 2304 2305## 2306InstallMethod( \/, 2307 "for ring elements", 2308 [ IsRingElement, IsHomalgRing ], 2309 2310 function( r, R ) 2311 2312 return HomalgRingElement( String( r ), R ); 2313 2314end ); 2315 2316## 2317InstallMethod( \/, 2318 "for strings", 2319 [ IsStringRep and IsString, IsHomalgRing ], 2320 2321 function( r, R ) 2322 2323 return HomalgRingElement( r, R ); 2324 2325end ); 2326 2327## 2328InstallMethod( \/, 2329 "for strings", 2330 [ IsString, IsHomalgRing ], 2331 2332 function( r, R ) 2333 2334 # IsStringRep( r ) is false since otherwise the method above would have been chosen 2335 r := CopyToStringRep( r ); 2336 2337 return HomalgRingElement( r, R ); 2338 2339end ); 2340 2341## 2342InstallMethod( \/, 2343 "for homalg ring elements", 2344 [ IsHomalgRingElement, IsHomalgRing ], 2345 2346 function( r, R ) 2347 2348 if IsIdenticalObj( HomalgRing( r ), R ) then 2349 return r; 2350 fi; 2351 2352 return HomalgRingElement( String( r ), R ); 2353 2354end ); 2355 2356## 2357InstallGlobalFunction( StringToElementStringList, 2358 function( arg ) 2359 2360 return SplitString( arg[1], ",", "[ ]\n" ); 2361 2362end ); 2363 2364## 2365InstallGlobalFunction( _CreateHomalgRingToTestProperties, 2366 function( arg ) 2367 local homalg_ring, type; 2368 2369 homalg_ring := rec( ); 2370 2371 type := TheTypeHomalgInternalRing; 2372 2373 ## Objectify: 2374 CallFuncList( ObjectifyWithAttributes, Concatenation([ homalg_ring, type ], arg ) ); 2375 2376 return homalg_ring; 2377 2378end ); 2379 2380## 2381InstallMethod( UnivariatePolynomial, 2382 "for a list and a string", 2383 [ IsList, IsString ], 2384 2385 function( coeffs, r ) 2386 local pol; 2387 2388 pol := List( Reversed( [ 1 .. Length( coeffs ) ] ), 2389 i -> Concatenation( "(", String( coeffs[i] ), ")*", r, "^", String( i - 1 ) ) 2390 ); 2391 2392 return JoinStringsWithSeparator( pol, "+" ); 2393 2394end ); 2395 2396## 2397InstallMethod( Homogenization, 2398 "for a homalg ring element and a homalg ring", 2399 [ IsHomalgRingElement, IsHomalgRing ], 2400 2401 function( r, S ) 2402 local R, d, indetsR, indetsS, indR, indS, z, coeffs, monoms, diff; 2403 2404 if IsZero( r ) then 2405 return Zero( S ); 2406 fi; 2407 2408 R := HomalgRing( r ); 2409 2410 if not HasIsFreePolynomialRing( R ) and IsFreePolynomialRing( R ) and 2411 not HasIsFreePolynomialRing( S ) and IsFreePolynomialRing( S ) then 2412 TryNextMethod( ); 2413 fi; 2414 2415 d := Degree( r ); 2416 2417 if d = 0 then 2418 return r / S; 2419 fi; 2420 2421 indetsR := Indeterminates( R ); 2422 indetsS := Indeterminates( S ); 2423 2424 indS := List( indetsS, String ); 2425 indR := List( indetsR, String ); 2426 2427 2428 if not IsSubset( indS, indR ) then 2429 Error( "the indeterminates of the second argument do not contain the indeterminates of the ring underlying the given ring element\n" ); 2430 fi; 2431 2432 z := Difference( indS, indR ); 2433 2434 if Length( z ) <> 1 then 2435 Error( "the indeterminates of the second argument are not exactly one more than the indeterminates of the ring underlying the given ring element\n" ); 2436 fi; 2437 2438 z := Filtered( indetsS, a -> String( a ) = z[1] )[1]; 2439 2440 coeffs := Coefficients( r ); 2441 monoms := coeffs!.monomials; 2442 2443 coeffs := List( EntriesOfHomalgMatrix( coeffs ), c -> c / S ); 2444 monoms := List( monoms, m -> ( m / S ) * z^( d - Degree( m ) ) ); 2445 2446 return Sum( ListN( coeffs, monoms, \* ) ); 2447 2448end ); 2449 2450## 2451InstallMethod( \*, 2452 "for an FFE and a homalg ring element", 2453 [ IsFFE, IsHomalgRingElement ], 2454 2455 function( f, r ) 2456 local R, e; 2457 2458 R := HomalgRing( r ); 2459 2460 e := LogFFE( f, Z( Characteristic( R ), DegreeOverPrimeField( R ) ) ); 2461 2462 return PrimitiveElement( R )^e * r; 2463 2464end ); 2465 2466## 2467InstallMethod( \*, 2468 "for a homalg ring element and an FFE", 2469 [ IsHomalgRingElement, IsFFE ], 2470 2471 function( r, f ) 2472 2473 return f * r; 2474 2475end ); 2476 2477## the second argument is there for method selection 2478InstallMethod( LcmOp, 2479 "for homalg objects", 2480 [ IsList, IsHomalgRingElement ], 2481 2482 function( L, r ) 2483 2484 return Iterated( L, LcmOp ); 2485 2486end ); 2487 2488## 2489InstallMethod( LcmOp, 2490 "for homalg ring elements", 2491 [ IsHomalgRingElement, IsHomalgRingElement ], 2492 2493 function( p, q ) 2494 local R, pp, qq; 2495 2496 if IsZero( p ) or IsZero( q ) then 2497 return Zero( p ); 2498 fi; 2499 2500 R := HomalgRing( p ); 2501 2502 pp := HomalgMatrix( [ p ], 1, 1, R ); 2503 qq := HomalgMatrix( [ q ], 1, 1, R ); 2504 2505 ## this can be expressed categorically 2506 return p * SyzygiesOfRows( pp, qq )[ 1, 1 ]; 2507 2508end ); 2509 2510## 2511InstallOtherMethod( GcdOp, 2512 "for homalg ring elements", 2513 [ IsHomalgRingElement, IsHomalgRingElement ], 2514 2515 function( p, q ) 2516 local R, pp, qq; 2517 2518 if IsZero( p ) or IsZero( q ) then 2519 return Zero( p ); 2520 fi; 2521 2522 R := HomalgRing( p ); 2523 2524 pp := HomalgMatrix( [ p ], 1, 1, R ); 2525 qq := HomalgMatrix( [ q ], 1, 1, R ); 2526 2527 ## this can be expressed categorically 2528 return q / SyzygiesOfRows( pp, qq )[ 1, 1 ]; 2529 2530end ); 2531 2532## 2533InstallMethod( CoefficientsRing, 2534 "for homalg ring elements", 2535 [ IsHomalgRingElement ], 2536 2537 function( r ) 2538 2539 return CoefficientsRing( HomalgRing( r ) ); 2540 2541end ); 2542 2543## 2544InstallMethod( CoefficientsRing, 2545 "for homalg fields", 2546 [ IsHomalgRing and IsFieldForHomalg ], 2547 2548 IdFunc ); 2549 2550## 2551InstallMethod( CoefficientsRing, 2552 "for homalg ring of integers", 2553 [ IsHomalgRing and IsIntegersForHomalg ], 2554 2555 IdFunc ); 2556 2557## 2558InstallMethod( BaseRing, 2559 "for homalg fields", 2560 [ IsHomalgRing and IsFieldForHomalg ], 2561 2562 IdFunc ); 2563 2564## 2565InstallMethod( BaseRing, 2566 "for homalg ring of integers", 2567 [ IsHomalgRing and IsIntegersForHomalg ], 2568 2569 IdFunc ); 2570 2571## 2572InstallMethod( Size, 2573 "for a homalg ring", 2574 [ IsHomalgRing ], 2575 2576 function( R ) 2577 local p, d; 2578 2579 p := Characteristic( R ); 2580 2581 if p = 0 then 2582 return infinity; 2583 fi; 2584 2585 if not HasDegreeOverPrimeField( R ) then 2586 TryNextMethod( ); 2587 fi; 2588 2589 return p^DegreeOverPrimeField( R ); 2590 2591end ); 2592 2593#################################### 2594# 2595# View, Print, and Display methods: 2596# 2597#################################### 2598 2599## 2600InstallMethod( String, 2601 "for homalg rings", 2602 [ IsHomalgRing ], 2603 2604 RingName ); 2605 2606## 2607InstallMethod( ViewObj, 2608 "for homalg rings", 2609 [ IsHomalgRing ], 100, 2610 2611 function( o ) 2612 2613 Print( RingName( o ) ); 2614 2615end ); 2616 2617## 2618InstallMethod( Display, 2619 "for homalg rings", 2620 [ IsHomalgRing ], 2621 2622 function( o ) 2623 2624 Print( "<A" ); 2625 2626 if HasIsZero( o ) and IsZero( o ) then 2627 Print( " zero" ); 2628 fi; 2629 2630 if IsBound( o!.description ) then 2631 Print( o!.description ); 2632 elif IsHomalgInternalRingRep( o ) then 2633 Print( "n internal" ); 2634 fi; 2635 2636 if IsPreHomalgRing( o ) then 2637 Print( " pre-homalg" ); 2638 fi; 2639 2640 Print( " ring>", "\n" ); 2641 2642end ); 2643 2644## 2645InstallMethod( DisplayRing, 2646 "for homalg rings", 2647 [ IsHomalgRing ], 2648 2649 function( o ) 2650 2651 Display( o ); 2652 2653end ); 2654 2655## 2656InstallMethod( ViewObj, 2657 "for homalg ring elements", 2658 [ IsHomalgRingElement ], 2659 2660 function( o ) 2661 2662 Print( Name( o ) ); ## this sets the attribute Name and the view method is never triggered again (as long as Name is set) 2663 2664end ); 2665 2666## 2667InstallMethod( Display, 2668 "for homalg ring elements", 2669 [ IsHomalgRingElement ], 2670 2671 function( o ) 2672 2673 Print( Name( o ), "\n" ); ## this sets the attribute Name and the display method is never triggered again (as long as Name is set) 2674 2675end ); 2676 2677## 2678InstallMethod( Display, 2679 "for weak pointer containers of identity matrices", 2680 [ IsContainerForWeakPointersOnIdentityMatricesRep ], 2681 2682 function( o ) 2683 local weak_pointers; 2684 2685 weak_pointers := o!.weak_pointers; 2686 2687 Print( Filtered( [ 1 .. LengthWPObj( weak_pointers ) ], i -> IsBoundElmWPObj( weak_pointers, i ) ), "\n" ); 2688 2689end ); 2690