1############################################################################# 2## 3## Complexes.gi homalg package Mohamed Barakat 4## 5## Copyright 2007-2008 Lehrstuhl B für Mathematik, RWTH Aachen 6## 7## Implementations of homalg procedures for complexes. 8## 9############################################################################# 10 11#################################### 12# 13# methods for operations: 14# 15#################################### 16 17## 18InstallMethod( DefectOfExactness, 19 "for a homalg complexes", 20 [ IsComplexOfFinitelyPresentedObjectsRep, IsInt ], 21 22 function( C, i ) 23 local degrees, mor, def; 24 25 degrees := ObjectDegreesOfComplex( C ); 26 27 ## never use the following: 28 #elif HasIsGradedObject( C ) and IsGradedObject( C ) then 29 # return CertainObject( C, i ); 30 31 if PositionSet( degrees, i ) = fail then 32 Error( "the second argument ", i, " is outside the degree range of the complex\n" ); 33 elif i = degrees[1] then 34 mor := CertainMorphism( C, i + 1 ); 35 def := Cokernel( mor ); 36 elif i = degrees[Length( degrees )] then 37 mor := CertainMorphism( C, i ); 38 def := Kernel( mor ); 39 else 40 mor := CertainTwoMorphismsAsSubcomplex( C, i ); 41 mor := AsATwoSequence( mor ); 42 def := DefectOfExactness( mor ); 43 fi; 44 45 return def; 46 47end ); 48 49## 50InstallMethod( DefectOfExactness, 51 "for a homalg complexes", 52 [ IsCocomplexOfFinitelyPresentedObjectsRep, IsInt ], 53 54 function( C, i ) 55 local degrees, mor, def; 56 57 degrees := ObjectDegreesOfComplex( C ); 58 59 ## never use the following: 60 #elif HasIsGradedObject( C ) and IsGradedObject( C ) then 61 # return CertainObject( C, i ); 62 63 if PositionSet( degrees, i ) = fail then 64 Error( "the second argument ", i, " is outside the degree range of the complex\n" ); 65 elif i = degrees[1] then 66 mor := CertainMorphism( C, i ); 67 def := Kernel( mor ); 68 elif i = degrees[Length( degrees )] then 69 mor := CertainMorphism( C, i - 1 ); 70 def := Cokernel( mor ); 71 else 72 mor := CertainTwoMorphismsAsSubcomplex( C, i ); 73 mor := AsATwoSequence( mor ); 74 def := DefectOfExactness( mor ); 75 fi; 76 77 return def; 78 79end ); 80 81## 82InstallMethod( Homology, 83 "for a homalg complexes", 84 [ IsHomalgComplex, IsInt ], 85 86 function( C, i ) 87 88 if IsCocomplexOfFinitelyPresentedObjectsRep( C ) then 89 Error( "this is a cocomplex: use \033[1mCohomology\033[0m instead\n" ); 90 fi; 91 92 return DefectOfExactness( C, i ); 93 94end ); 95 96## 97InstallMethod( Cohomology, 98 "for a homalg complexes", 99 [ IsHomalgComplex, IsInt ], 100 101 function( C, i ) 102 103 if IsComplexOfFinitelyPresentedObjectsRep( C ) then 104 Error( "this is a complex: use \033[1mHomology\033[0m instead\n" ); 105 fi; 106 107 return DefectOfExactness( C, i ); 108 109end ); 110 111## 112InstallMethod( DefectOfExactness, 113 "for a homalg complexes", 114 [ IsComplexOfFinitelyPresentedObjectsRep ], 115 116 function( C ) 117 local display, display_string, SimplifyObject, left, degrees, l, 118 morphisms, T, H, i, S; 119 120 if HasIsATwoSequence( C ) and IsATwoSequence( C ) then 121 TryNextMethod( ); 122 fi; 123 124 if IsBound( C!.DisplayHomology ) and C!.DisplayHomology = true then 125 display := true; 126 else 127 display := false; 128 fi; 129 130 if IsBound( C!.StringBeforeDisplay ) and IsStringRep( C!.StringBeforeDisplay ) then 131 display_string := C!.StringBeforeDisplay; 132 else 133 display_string := ""; 134 fi; 135 136 if IsBound( C!.HomologyOnLessGenerators ) then 137 if C!.HomologyOnLessGenerators = true then 138 SimplifyObject := ValueGlobal( "OnLessGenerators" ); 139 elif IsFunction( C!.HomologyOnLessGenerators ) then 140 SimplifyObject := C!.HomologyOnLessGenerators; 141 else 142 SimplifyObject := a -> a; 143 fi; 144 else 145 SimplifyObject := a -> a; 146 fi; 147 148 ## never use the following: 149 #if IsGradedObject( C ) then 150 # H := C; 151 152 if IsBound(C!.HomologyGradedObject) then 153 H := C!.HomologyGradedObject; 154 fi; 155 156 if IsBound( H ) then 157 SimplifyObject( H ); 158 159 if display then 160 for i in ObjectsOfComplex( H ) do 161 Print( display_string ); 162 Display( i ); 163 od; 164 fi; 165 166 return H; 167 fi; 168 169 if not IsComplex( C ) then 170 Error( "the input is not a complex" ); 171 fi; 172 173 left := IsHomalgLeftObjectOrMorphismOfLeftObjects( C ); 174 175 degrees := MorphismDegreesOfComplex( C ); 176 177 l := Length(degrees); 178 179 morphisms := MorphismsOfComplex( C ); 180 181 if not IsBound( C!.SkipLowestDegreeHomology ) then 182 T := Cokernel( morphisms[1] ); 183 H := HomalgComplex( T, degrees[1] - 1 ); 184 else 185 if left then 186 T := DefectOfExactness( morphisms[2], morphisms[1] ); 187 else 188 T := DefectOfExactness( morphisms[1], morphisms[2] ); 189 fi; 190 H := HomalgComplex( T, degrees[1] ); 191 morphisms := morphisms{[ 2 .. l ]}; 192 l := l - 1; 193 fi; 194 195 SimplifyObject( T ); 196 197 if display then 198 Print( display_string ); 199 Display( T ); 200 fi; 201 202 for i in [ 1 .. l - 1 ] do 203 if left then 204 S := DefectOfExactness( morphisms[i + 1], morphisms[i] ); 205 else 206 S := DefectOfExactness( morphisms[i], morphisms[i + 1] ); 207 fi; 208 Add( H, TheZeroMorphism( S, T ) ); 209 T := S; 210 211 SimplifyObject( T ); 212 213 if display then 214 Print( display_string ); 215 Display( T ); 216 fi; 217 od; 218 219 if not ( IsBound( C!.SkipHighestDegreeHomology ) and C!.SkipHighestDegreeHomology = true ) then 220 S := Kernel( morphisms[l] ); 221 Add( H, TheZeroMorphism( S, T ) ); 222 223 SimplifyObject( S ); 224 225 if display then 226 Print( display_string ); 227 Display( S ); 228 fi; 229 fi; 230 231 SetIsGradedObject( H, true ); 232 233 C!.HomologyGradedObject := H; 234 235 return H; 236 237end ); 238 239## 240InstallMethod( DefectOfExactness, 241 "for a homalg complexes", 242 [ IsCocomplexOfFinitelyPresentedObjectsRep ], 243 244 function( C ) 245 local display, display_string, SimplifyObject, left, degrees, l, 246 morphisms, S, H, i, T; 247 248 if IsBound( C!.DisplayCohomology ) and C!.DisplayCohomology = true then 249 display := true; 250 else 251 display := false; 252 fi; 253 254 if IsBound( C!.CohomologyOnLessGenerators ) then 255 if C!.CohomologyOnLessGenerators = true then 256 SimplifyObject := ValueGlobal( "OnLessGenerators" ); 257 elif IsFunction( C!.CohomologyOnLessGenerators ) then 258 SimplifyObject := C!.CohomologyOnLessGenerators; 259 else 260 SimplifyObject := a -> a; 261 fi; 262 else 263 SimplifyObject := a -> a; 264 fi; 265 266 if IsBound( C!.StringBeforeDisplay ) and IsStringRep( C!.StringBeforeDisplay ) then 267 display_string := C!.StringBeforeDisplay; 268 else 269 display_string := ""; 270 fi; 271 272 ## never use the following: 273 #if IsGradedObject( C ) then 274 # H := C; 275 276 if IsBound(C!.CohomologyGradedObject) then 277 H := C!.CohomologyGradedObject; 278 fi; 279 280 if IsBound( H ) then 281 SimplifyObject( H ); 282 283 if display then 284 for i in ObjectsOfComplex( H ) do 285 Print( display_string ); 286 Display( i ); 287 od; 288 fi; 289 290 return H; 291 fi; 292 293 if not IsComplex( C ) then 294 Error( "the input is not a cocomplex" ); 295 fi; 296 297 left := IsHomalgLeftObjectOrMorphismOfLeftObjects( C ); 298 299 degrees := MorphismDegreesOfComplex( C ); 300 301 l := Length(degrees); 302 303 morphisms := MorphismsOfComplex( C ); 304 305 if not IsBound( C!.SkipLowestDegreeCohomology ) then 306 S := Kernel( morphisms[1] ); 307 H := HomalgCocomplex( S, degrees[1] ); 308 else 309 if left then 310 S := DefectOfExactness( morphisms[1], morphisms[2] ); 311 else 312 S := DefectOfExactness( morphisms[2], morphisms[1] ); 313 fi; 314 H := HomalgCocomplex( S, degrees[1] + 1 ); 315 morphisms := morphisms{[ 2 .. l ]}; 316 l := l - 1; 317 fi; 318 319 SimplifyObject( S ); 320 321 if display then 322 Print( display_string ); 323 Display( S ); 324 fi; 325 326 for i in [ 1 .. l - 1 ] do 327 if left then 328 T := DefectOfExactness( morphisms[i], morphisms[i + 1] ); 329 else 330 T := DefectOfExactness( morphisms[i + 1], morphisms[i] ); 331 fi; 332 Add( H, TheZeroMorphism( S, T ) ); 333 S := T; 334 335 SimplifyObject( S ); 336 337 if display then 338 Print( display_string ); 339 Display( S ); 340 fi; 341 od; 342 343 if not ( IsBound( C!.SkipHighestDegreeCohomology ) and C!.SkipHighestDegreeCohomology = true ) then 344 T := Cokernel( morphisms[l] ); 345 Add( H, TheZeroMorphism( S, T ) ); 346 347 SimplifyObject( T ); 348 349 if display then 350 Print( display_string ); 351 Display( T ); 352 fi; 353 fi; 354 355 SetIsGradedObject( H, true ); 356 357 C!.CohomologyGradedObject := H; 358 359 return H; 360 361end ); 362 363## 364InstallMethod( Homology, ### defines: Homology (HomologyModules) 365 "for a homalg complexes", 366 [ IsHomalgComplex ], 367 368 function( C ) 369 370 if IsCocomplexOfFinitelyPresentedObjectsRep( C ) then 371 Error( "this is a cocomplex: use \033[1mCohomology\033[0m instead\n" ); 372 fi; 373 374 return DefectOfExactness( C ); 375 376end ); 377 378## 379InstallMethod( Cohomology, ### defines: Cohomology (CohomologyModules) 380 "for a homalg complexes", 381 [ IsHomalgComplex ], 382 383 function( C ) 384 385 if IsComplexOfFinitelyPresentedObjectsRep( C ) then 386 Error( "this is a complex: use \033[1mHomology\033[0m instead\n" ); 387 fi; 388 389 return DefectOfExactness( C ); 390 391end ); 392 393InstallMethod( HorseShoeResolution, 394 "for homalg complexes", 395 [ IsList, IsHomalgChainMorphism, IsHomalgChainMorphism, IsHomalgMorphism ], 396 397 function( l, d_phi, d_psi, dEj2 ) 398 local dEj, dN, dE, dM, psi, phi, j, dMj, dNj, mu, SyzygiesObjectEmb_j_M, SyzygiesObjectEmb_j_N, epsilonM, epsilonN, epsilon_j, Pj; 399 400 dEj := dEj2; 401 402 dN := Source( d_phi ); 403 dE := Range( d_phi ); 404 dM := Range( d_psi ); 405 406 if IsComplexOfFinitelyPresentedObjectsRep( dN ) then 407 psi := CertainMorphism( d_psi, l[1] - 1 ); 408 phi := CertainMorphism( d_phi, l[1] - 1 ); 409 else 410 psi := CertainMorphism( d_psi, l[1] + 1 ); 411 phi := CertainMorphism( d_phi, l[1] + 1 ); 412 fi; 413 414 if not IsIdenticalObj( dE, Source( d_psi ) ) then 415 Error( "expected a two composable chain morphisms" ); 416 fi; 417 418 for j in l do 419 420 mu := KernelEmb( dEj ); 421 422 dMj := CertainMorphism( dM, j ); 423 dNj := CertainMorphism( dN, j ); 424 425 SyzygiesObjectEmb_j_M := ImageObjectEmb( dMj ); 426 SyzygiesObjectEmb_j_N := ImageObjectEmb( dNj ); 427 428 psi := CompleteImageSquare( mu, psi, SyzygiesObjectEmb_j_M ); 429 phi := CompleteImageSquare( SyzygiesObjectEmb_j_N, phi, mu ); 430 431 # The HorseShoeResolution produces short exact sequences in each degree 432 Assert( 4, IsMorphism( phi ) ); 433 SetIsMorphism( phi, true ); 434 Assert( 4, IsMonomorphism( phi ) ); 435 SetIsMonomorphism( phi, true ); 436 437 Assert( 4, IsMorphism( psi ) ); 438 SetIsMorphism( psi, true ); 439 Assert( 4, IsEpimorphism( psi ) ); 440 SetIsEpimorphism( psi, true ); 441 442 SetKernelEmb( psi, phi ); 443 SetCokernelEpi( phi, psi ); 444 445 # if certain objects are known to be zero, the remaining morphism is an isomorphism 446 if HasIsZero( Source( phi ) ) then 447 Assert( 4, IsMorphism( psi ) ); 448 SetIsMorphism( psi, true ); 449 Assert( 4, IsMonomorphism( psi ) = IsZero( Source( phi ) ) ); 450 SetIsMonomorphism( psi, IsZero( Source( phi ) ) ); 451 fi; 452 if HasIsZero( Range( psi ) ) then 453 Assert( 4, IsMorphism( phi ) ); 454 SetIsMorphism( phi, true ); 455 Assert( 4, IsEpimorphism( phi ) = IsZero( Range( psi ) ) ); 456 SetIsEpimorphism( phi, IsZero( Range( psi ) ) ); 457 fi; 458 459 epsilonM := ImageObjectEpi( dMj ); 460 epsilonN := ImageObjectEpi( dNj ); 461 462 epsilonM := epsilonM / psi; ## projective lift or something similar 463 epsilonN := PreCompose( epsilonN, phi ); 464 465 epsilon_j := CoproductMorphism( epsilonN, epsilonM ); 466 467 Pj := Source( epsilon_j ); 468 469 dEj := PreCompose( epsilon_j, mu ); 470 471 psi := EpiOnRightFactor( Pj ); 472 phi := MonoOfLeftSummand( Pj ); 473 474 if IsComplexOfFinitelyPresentedObjectsRep( dN ) then 475 Add( dE, dEj ); 476 Add( d_psi, psi ); 477 Add( d_phi, phi ); 478 else 479 Add( dEj, dE ); 480 Add( psi, d_psi ); 481 Add( phi, d_phi ); 482 fi; 483 484 od; 485 486 ## check assertions 487 Assert( 4, IsMorphism( d_psi ) ); 488 Assert( 4, IsMorphism( d_phi ) ); 489 490end ); 491 492## 0 <-- M <-(psi)- E <-(phi)- N <-- 0 493## or 494## 0 --> N -(phi)-> E -(psi)-> M --> 0 495InstallMethod( Resolution, ### defines: Resolution (generalizes ResolveShortExactSeq) 496 "for homalg complexes", 497 [ IsInt, IsHomalgComplex and IsShortExactSequence ], 498 499 function( _q, C ) 500 local q, degrees, psi, phi, M, E, N, dM, dN, j, 501 index_pair_psi, index_pair_phi, epsilonN, epsilonM, epsilon, 502 dj, SetEpi, Pj, dE, d_psi, d_phi, horse_shoe, mu, epsilon_j; 503 504 q := _q; 505 506 if q = 0 then q := 1; fi; 507 508 degrees := ObjectDegreesOfComplex( C ); 509 510 if IsComplexOfFinitelyPresentedObjectsRep( C ) then 511 psi := CertainMorphism( C, degrees[2] ); 512 phi := CertainMorphism( C, degrees[3] ); 513 else 514 phi := CertainMorphism( C, degrees[1] ); 515 psi := CertainMorphism( C, degrees[2] ); 516 fi; 517 518 M := Range( psi ); 519 E := Source( psi ); 520 N := Source( phi ); 521 522 # For a category not having enough projectives, we need to resolve M 523 # with a resolution adapted to the morphism psi, such that the PostDivide 524 # used below works. 525 # For example for the category of coherent sheaves on projective space 526 # we compute a locally free resolution of M, where the zeroth object of 527 # the resolution is build the way such that "epsilonM/psi" works. 528 dM := ResolutionWithRespectToMorphism( q, M, psi ); 529 dN := Resolution( q, N ); 530 531 if q < 0 then 532 q := Maximum( List( [ M, N ], LengthOfResolution ) ); 533 dM := ResolutionWithRespectToMorphism( q, M, psi ); 534 dN := Resolution( q, N ); 535 fi; 536 537 LockObjectOnCertainPresentation( N ); 538 LockObjectOnCertainPresentation( E ); 539 LockObjectOnCertainPresentation( M ); 540 541 index_pair_psi := PairOfPositionsOfTheDefaultPresentations( psi ); 542 index_pair_phi := PairOfPositionsOfTheDefaultPresentations( phi ); 543 544 if IsBound( C!.resolutions ) and 545 IsBound( C!.resolutions.(String( [ index_pair_psi, index_pair_phi ] )) ) then 546 547 horse_shoe := C!.resolutions.(String( [ index_pair_psi, index_pair_phi ] )); 548 549 if IsComplexOfFinitelyPresentedObjectsRep( C ) then 550 d_psi := CertainMorphism( horse_shoe, degrees[2] ); 551 d_phi := CertainMorphism( horse_shoe, degrees[3] ); 552 else 553 d_psi := CertainMorphism( horse_shoe, degrees[1] ); 554 d_phi := CertainMorphism( horse_shoe, degrees[2] ); 555 fi; 556 557 j := HighestDegree( d_psi ); 558 559 if j <> HighestDegree( d_phi ) then 560 Error( "the highest degrees of the two chain morphisms in the horse shoe do not coincide\n" ); 561 fi; 562 563 psi := CertainMorphism( d_psi, j ); 564 phi := CertainMorphism( d_phi, j ); 565 566 dE := Source( d_psi ); 567 568 dj := CertainMorphism( dE, j ); 569 570 SetEpi := false; 571 572 else 573 574 j := 0; 575 576 epsilonM := CokernelEpi( LowestDegreeMorphism( dM ) ); 577 epsilonN := CokernelEpi( LowestDegreeMorphism( dN ) ); 578 579 epsilonM := epsilonM / psi; ## projective lift or something similar 580 epsilonN := PreCompose( epsilonN, phi ); 581 582 dj := CoproductMorphism( epsilonN, epsilonM ); 583 584 Assert( 4, IsMorphism( dj ) ); 585 SetIsMorphism( dj, true ); 586 Assert( 4, IsEpimorphism( dj ) ); 587 SetIsEpimorphism( dj, true ); 588 589 Pj := Source( dj ); 590 591 dE := HomalgComplex( Pj ); 592 593 psi := EpiOnRightFactor( Pj ); 594 phi := MonoOfLeftSummand( Pj ); 595 596 d_psi := HomalgChainMorphism( psi, dE, dM ); 597 d_phi := HomalgChainMorphism( phi, dN, dE ); 598 599 if IsComplexOfFinitelyPresentedObjectsRep( C ) then 600 horse_shoe := HomalgComplex( d_psi, degrees[2] ); 601 Add( horse_shoe, d_phi ); 602 else 603 horse_shoe := HomalgCocomplex( d_phi, degrees[1] ); 604 Add( horse_shoe, d_psi ); 605 fi; 606 607 C!.resolutions := rec( ); 608 C!.resolutions.(String( [ index_pair_psi, index_pair_phi ] )) := horse_shoe; 609 610 SetEpi := true; 611 612 fi; 613 614 # up to now, only the horse shoe has been created 615 # now we fill the interior 616 # (if there is anything to fill) 617 if j + 1 <= q then 618 HorseShoeResolution( [ j + 1 .. q ] , d_phi, d_psi, dj ); 619 fi; 620 621 if SetEpi and MorphismDegreesOfComplex( dE ) <> [] then 622 SetCokernelEpi( LowestDegreeMorphism( dE ), dj ); 623 fi; 624 625 Assert( 5, IsMorphism( d_psi ) ); 626 SetIsMorphism( d_psi, true ); 627 SetIsEpimorphism( d_psi, true ); 628 629 Assert( 5, IsMorphism( d_phi ) ); 630 SetIsMorphism( d_phi, true ); 631 SetIsMonomorphism( d_phi, true ); 632 633 SetIsRightAcyclic( dE, true ); 634 SetIsShortExactSequence( horse_shoe, true ); 635 636 UnlockObject( N ); 637 UnlockObject( E ); 638 UnlockObject( M ); 639 640 return horse_shoe; 641 642end ); 643 644## 645InstallMethod( Resolution, 646 "for homalg complexes", 647 [ IsHomalgComplex ], 648 649 function( C ) 650 651 return Resolution( -1, C ); 652 653end ); 654 655## 656InstallMethod( CompleteComplexByResolution, 657 "for homalg complexes", 658 [ IsInt, IsComplexOfFinitelyPresentedObjectsRep ], 659 660 function( q, C ) 661 local zero, cpx, seq, mor, emb, ker, P, epi, i; 662 663 if q = infinity then 664 ## FIXME: should become obsolete 665 q := -1; 666 elif q = 0 then 667 return C; 668 fi; 669 670 if HasIsZero( C ) then 671 zero := IsZero( C ); 672 fi; 673 674 if HasIsComplex( C ) then 675 cpx := IsComplex( C ); 676 fi; 677 678 if HasIsSequence( C ) then 679 seq := IsSequence( C ); 680 fi; 681 682 mor := HighestDegreeMorphism( C ); 683 684 emb := KernelEmb( mor ); 685 686 ker := Source( emb ); 687 688 epi := CoveringEpi( ker ); 689 690 Add( C, PreCompose( epi, emb ) ); 691 692 if q > 1 then 693 694 P := Resolution( q - 1, ker ); 695 696 for i in [ 1 .. HighestDegree( P ) ] do 697 Add( C, CertainMorphism( P, i ) ); 698 od; 699 700 fi; 701 702 if IsBound( zero ) then 703 SetIsZero( C, zero ); 704 fi; 705 706 if IsBound( cpx ) then 707 SetIsComplex( C, cpx ); 708 fi; 709 710 if IsBound( seq ) then 711 SetIsSequence( C, seq ); 712 fi; 713 714 return C; 715 716end ); 717 718## 719InstallMethod( CompleteComplexByResolution, 720 "for homalg complexes", 721 [ IsInt, IsCocomplexOfFinitelyPresentedObjectsRep ], 722 723 function( q, C ) 724 local zero, cpx, seq, mor, emb, ker, P, epi, i; 725 726 if q = infinity then 727 ## FIXME: should become obsolete 728 q := -1; 729 elif q = 0 then 730 return C; 731 fi; 732 733 if HasIsZero( C ) then 734 zero := IsZero( C ); 735 fi; 736 737 if HasIsComplex( C ) then 738 cpx := IsComplex( C ); 739 fi; 740 741 if HasIsSequence( C ) then 742 seq := IsSequence( C ); 743 fi; 744 745 mor := LowestDegreeMorphism( C ); 746 747 emb := KernelEmb( mor ); 748 749 ker := Source( emb ); 750 751 epi := CoveringEpi( ker ); 752 753 Add( PreCompose( epi, emb ), C ); 754 755 if q > 1 then 756 757 P := Resolution( q - 1, ker ); 758 759 for i in [ 1 .. HighestDegree( P ) ] do 760 Add( CertainMorphism( P, i ), C ); 761 od; 762 763 fi; 764 765 if IsBound( zero ) then 766 SetIsZero( C, zero ); 767 fi; 768 769 if IsBound( cpx ) then 770 SetIsComplex( C, cpx ); 771 fi; 772 773 if IsBound( seq ) then 774 SetIsSequence( C, seq ); 775 fi; 776 777 return C; 778 779end ); 780 781## 782InstallMethod( CompleteComplexByResolution, 783 "for homalg complexes", 784 [ IsHomalgComplex ], 785 786 function( C ) 787 788 return CompleteComplexByResolution( infinity, C ); 789 790end ); 791 792#======================================================================= 793# Connecting homomorphism 794# 795# 0 796# | 797# | 798# | 799# v 800# 0 <--- Hs[n-1] <--- Zs[n-1] <--(bs[n])-- Cs[n]/Bs[n] <--- Hs[n] <--- 0 801# | | | | 802# | (i[n-1]) (i[n]) | 803# | | | | 804# v v v v 805# 0 <--- H[n-1] <--- Z[n-1] <--(b[n])--- C[n]/B[n] <--- H[n] <--- 0 806# | | | | 807# | (j[n-1]) (j[n]) | 808# | | | | 809# v v v v 810# 0 <--- Hq[n-1] <--- Zq[n-1] <--(bq[n])-- Cq[n]/Bq[n] <--- Hq[n] <--- 0 811# | 812# | 813# | 814# v 815# 0 816# 817#_______________________________________________________________________ 818InstallMethod( ConnectingHomomorphism, 819 "for homalg complexes", 820 [ IsStaticFinitelyPresentedObjectRep, 821 IsStaticMorphismOfFinitelyGeneratedObjectsRep, 822 IsStaticMorphismOfFinitelyGeneratedObjectsRep, 823 IsStaticMorphismOfFinitelyGeneratedObjectsRep, 824 IsStaticFinitelyPresentedObjectRep ], 825 826 function( Hqn, jn, bn, in_1, Hsn_1 ) 827 local iota_Hqn, iota_Hsn_1, snake; 828 829 iota_Hqn := NaturalGeneralizedEmbedding( Hqn ); 830 iota_Hsn_1 := NaturalGeneralizedEmbedding( Hsn_1 ); 831 832 snake := iota_Hqn; 833 snake := snake / jn; 834 snake := PreCompose( snake, bn ); ## the connecting homomorphism is what b[n] induces between certain subfactors of C[n] and C[n-1] 835 snake := snake / in_1; ## lift 836 snake := snake / iota_Hsn_1; ## lift 837 838 ## check assertion 839 Assert( 3, IsMorphism( snake ) ); 840 841 SetIsMorphism( snake, true ); 842 843 return snake; 844 845end ); 846 847## 848InstallMethod( ConnectingHomomorphism, 849 "for short exact sequences of complexes", 850 [ IsComplexOfFinitelyPresentedObjectsRep and IsShortExactSequence, IsInt ], 851 852 function( E, n ) 853 local j, i, Cq, C, Cs, Hqn, jn, bn, in_1, Hsn_1; 854 855 j := LowestDegreeMorphism( E ); 856 i := HighestDegreeMorphism( E ); 857 858 Cq := Range( j ); 859 C := Source( j ); 860 Cs := Source( i ); 861 862 Hqn := DefectOfExactness( Cq, n ); 863 jn := CertainMorphism( j, n ); 864 bn := CertainMorphism( C, n ); 865 in_1 := CertainMorphism( i, n - 1 ); 866 Hsn_1 := DefectOfExactness( Cs, n - 1 ); 867 868 return ConnectingHomomorphism( Hqn, jn, bn, in_1, Hsn_1 ); 869 870end ); 871 872## 873InstallMethod( ConnectingHomomorphism, 874 "for short exact sequences of complexes", 875 [ IsCocomplexOfFinitelyPresentedObjectsRep and IsShortExactSequence, IsInt ], 876 877 function( E, n ) 878 local i, j, Cs, C, Cq, Hqn, jn, bn, inp1, Hsnp1; 879 880 i := LowestDegreeMorphism( E ); 881 j := HighestDegreeMorphism( E ); 882 883 Cs := Source( i ); 884 C := Range( i ); 885 Cq := Range( j ); 886 887 Hqn := DefectOfExactness( Cq, n ); 888 jn := CertainMorphism( j, n ); 889 bn := CertainMorphism( C, n ); 890 inp1 := CertainMorphism( i, n + 1 ); 891 Hsnp1 := DefectOfExactness( Cs, n + 1 ); 892 893 return ConnectingHomomorphism( Hqn, jn, bn, inp1, Hsnp1 ); 894 895end ); 896 897## 898InstallMethod( ConnectingHomomorphism, 899 "for short exact sequences of complexes", 900 [ IsComplexOfFinitelyPresentedObjectsRep and IsShortExactSequence ], 901 902 function( E ) 903 local degrees, l, S, T, con, n; 904 905 degrees := DegreesOfChainMorphism( LowestDegreeMorphism( E ) ); 906 907 l := Length( degrees ); 908 909 if l < 2 then 910 Error( "complex too small\n" ); 911 fi; 912 913 S := DefectOfExactness( LowestDegreeObject( E ) ); 914 T := DefectOfExactness( HighestDegreeObject( E ) ); 915 916 n := degrees[2]; 917 918 con := HomalgChainMorphism( ConnectingHomomorphism( E, n ), S, T, [ n, -1 ] ); 919 920 for n in degrees{[ 3 .. l ]} do 921 Add( con, ConnectingHomomorphism( E, n ) ); 922 od; 923 924 SetIsGradedMorphism( con, true ); 925 926 return con; 927 928end ); 929 930## 931InstallMethod( ConnectingHomomorphism, 932 "for short exact sequences of complexes", 933 [ IsCocomplexOfFinitelyPresentedObjectsRep and IsShortExactSequence ], 934 935 function( E ) 936 local degrees, l, S, T, con, n; 937 938 degrees := DegreesOfChainMorphism( HighestDegreeMorphism( E ) ); 939 940 l := Length( degrees ); 941 942 if l < 2 then 943 Error( "cocomplex too small\n" ); 944 fi; 945 946 S := DefectOfExactness( HighestDegreeObject( E ) ); 947 T := DefectOfExactness( LowestDegreeObject( E ) ); 948 949 n := degrees[1]; 950 951 con := HomalgChainMorphism( ConnectingHomomorphism( E, n ), S, T, [ n, 1 ] ); 952 953 for n in degrees{[ 2 .. l - 1 ]} do 954 Add( con, ConnectingHomomorphism( E, n ) ); 955 od; 956 957 SetIsGradedMorphism( con, true ); 958 959 return con; 960 961end ); 962 963## 964InstallMethod( ExactTriangle, 965 "for short exact sequences of complexes", 966 [ IsComplexOfFinitelyPresentedObjectsRep and IsShortExactSequence ], 967 968 function( E ) 969 local deg, j, i, con, triangle; 970 971 deg := LowestDegree( E ) + 1; 972 973 j := DefectOfExactness( LowestDegreeMorphism( E ) ); 974 i := DefectOfExactness( HighestDegreeMorphism( E ) ); 975 con := ConnectingHomomorphism( E ); 976 977 triangle := HomalgComplex( j, deg ); 978 Add( triangle, i ); 979 Add( triangle, con ); 980 981 SetIsExactTriangle( triangle, true ); 982 983 return triangle; 984 985end ); 986 987## 988InstallMethod( ExactTriangle, 989 "for short exact sequences of complexes", 990 [ IsCocomplexOfFinitelyPresentedObjectsRep and IsShortExactSequence ], 991 992 function( E ) 993 local deg, j, i, con, triangle; 994 995 deg := LowestDegree( E ); 996 997 i := DefectOfExactness( LowestDegreeMorphism( E ) ); 998 j := DefectOfExactness( HighestDegreeMorphism( E ) ); 999 con := ConnectingHomomorphism( E ); 1000 1001 triangle := HomalgCocomplex( i, deg ); 1002 Add( triangle, j ); 1003 Add( triangle, con ); 1004 1005 SetIsExactTriangle( triangle, true ); 1006 1007 return triangle; 1008 1009end ); 1010 1011## [HS. Proof of Lemma. VIII.9.4] 1012InstallMethod( DefectOfExactnessSequence, 1013 "for homalg two-morphisms complexes", 1014 [ IsHomalgComplex and IsATwoSequence ], 1015 1016 function( cpx_post_pre ) 1017 local pre, post, F_Z, F_B, Z_B, H, F_H, H_Z, C; 1018 1019 pre := HighestDegreeMorphism( cpx_post_pre ); 1020 post := LowestDegreeMorphism( cpx_post_pre ); 1021 1022 ## read: F <- Z 1023 F_Z := KernelEmb( post ); 1024 1025 ## read: F <- B 1026 F_B := ImageObjectEmb( pre ); 1027 1028 ## read: Z <- B 1029 Z_B := F_B / F_Z; ## lift 1030 1031 H := DefectOfExactness( cpx_post_pre ); 1032 1033 ## read: F <- H 1034 F_H := NaturalGeneralizedEmbedding( H ); 1035 1036 ## read: H <- Z 1037 H_Z := F_Z / F_H; ## generalized lift 1038 1039 C := HomalgComplex( H_Z ); 1040 1041 Add( C, Z_B ); 1042 1043 SetIsShortExactSequence( C, true ); 1044 1045 ## read: H <- Z <- B, (H := Z/B) 1046 return C; 1047 1048end ); 1049 1050## for convenience 1051InstallMethod( DefectOfExactnessSequence, 1052 "for composable homalg morphisms", 1053 [ IsStaticMorphismOfFinitelyGeneratedObjectsRep, 1054 IsStaticMorphismOfFinitelyGeneratedObjectsRep ], 1055 1056 function( phi, psi ) 1057 1058 return DefectOfExactnessSequence( AsATwoSequence( phi, psi ) ); 1059 1060end ); 1061 1062## [HS. Proof of Lemma. VIII.9.4] 1063InstallMethod( DefectOfExactnessCosequence, 1064 "for homalg two-morphisms complexes", 1065 [ IsHomalgComplex and IsATwoSequence ], 1066 1067 function( cpx_post_pre ) 1068 local pre, post, Z_F, B_F, B_Z, H, H_F, Z_H, C; 1069 1070 pre := HighestDegreeMorphism( cpx_post_pre ); 1071 post := LowestDegreeMorphism( cpx_post_pre ); 1072 1073 ## read: Z -> F 1074 Z_F := KernelEmb( post ); 1075 1076 ## read: B -> F 1077 B_F := ImageObjectEmb( pre ); 1078 1079 ## read: B -> Z 1080 B_Z := B_F / Z_F; ## lift 1081 1082 H := DefectOfExactness( cpx_post_pre ); 1083 1084 ## read: H -> F 1085 H_F := NaturalGeneralizedEmbedding( H ); 1086 1087 ## read: Z -> H 1088 Z_H := Z_F / H_F; ## generalized lift 1089 1090 C := HomalgCocomplex( B_Z ); 1091 1092 Add( C, Z_H ); 1093 1094 SetIsShortExactSequence( C, true ); 1095 1096 ## read: B -> Z -> H, (H := Z/B) 1097 return C; 1098 1099end ); 1100 1101## for convenience 1102InstallMethod( DefectOfExactnessCosequence, 1103 "for homalg composable maps", 1104 [ IsStaticMorphismOfFinitelyGeneratedObjectsRep, 1105 IsStaticMorphismOfFinitelyGeneratedObjectsRep ], 1106 1107 function( phi, psi ) 1108 1109 return DefectOfExactnessCosequence( AsATwoSequence( phi, psi ) ); 1110 1111end ); 1112 1113## the Cartan-Eilenberg resolution [HS. Lemma VIII.9.4] 1114InstallMethod( Resolution, ### defines: Resolution 1115 "for homalg complexes", 1116 [ IsInt, IsComplexOfFinitelyPresentedObjectsRep ], 1117 1118 function( _q, C ) 1119 local q, degrees, l, def, d, mor, index_pairs, QFB, FB, CE, natural_epis, 1120 HZB, Z, ZB, PZ, relZ, BFZ, BF, i, FZ; 1121 1122 if not IsComplex( C ) then 1123 Error( "the second argument is not a complex\n" ); 1124 fi; 1125 1126 # Do the HorseShoeResolution in that case 1127 if HasIsShortExactSequence( C ) and IsShortExactSequence( C ) then 1128 TryNextMethod( ); 1129 fi; 1130 1131 q := _q; 1132 1133 degrees := ObjectDegreesOfComplex( C ); 1134 1135 l := Length( degrees ) - 1; 1136 1137 def := ObjectsOfComplex( DefectOfExactness( C ) ); 1138 1139 if l = 0 then 1140 return HomalgComplex( Resolution( q, def[1] ), degrees[1] ); 1141 fi; 1142 1143 d := List( def, M -> Resolution( q, M ) ); 1144 1145 if q < 0 then 1146 q := Maximum( List( def, LengthOfResolution ) ); 1147 d := List( def, M -> Resolution( q, M ) ); 1148 fi; 1149 1150 mor := MorphismsOfComplex( C ); 1151 1152 index_pairs := List( mor, PairOfPositionsOfTheDefaultPresentations ); 1153 1154 ## F/B = Q <- F <- B (horse shoe) 1155 QFB := Resolution( q, CokernelSequence( mor[1] ) ); 1156 1157 ## F <- B 1158 FB := HighestDegreeMorphism( QFB ); 1159 1160 ## F 1161 CE := HomalgComplex( Range( FB ), degrees[1] ); 1162 1163 ## enrich CE with the natrual epis 1164 natural_epis := rec( ); 1165 1166 CE!.NaturalEpis := natural_epis; 1167 1168 natural_epis.(String( [ 0, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Range( FB ) ) ); 1169 1170 if l > 1 then 1171 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1172 ## Z/B =: H <- Z <- B 1173 HZB := DefectOfExactnessSequence( mor[2], mor[1] ); 1174 1175 ## Z <- B 1176 ZB := HighestDegreeMorphism( HZB ); 1177 1178 Z := Range( ZB ); 1179 1180 ## horse shoe 1181 HZB := Resolution( q, HZB ); 1182 1183 ## Z <- B 1184 ZB := HighestDegreeMorphism( HZB ); 1185 1186 ## the horse shoe resolution of Z 1187 PZ := Range( ZB ); 1188 1189 ## make this horse shoe resolution of Z the standard one 1190 SetCurrentResolution( Z, PZ ); 1191 1192 ## B <- F <- Z (horse shoe) 1193 BFZ := Resolution( q, KernelSequence( mor[1] ) ); 1194 1195 ## B <- F 1196 BF := LowestDegreeMorphism( BFZ ); 1197 1198 ## enrich CE with the natrual epi 1199 natural_epis.(String( [ 1, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( BF ) ) ); 1200 1201 ## F[i] <- F[i+1] 1202 Add( CE, BF * FB ); 1203 1204 ## F <- Z 1205 FZ := HighestDegreeMorphism( BFZ ); 1206 else 1207 ## Z/B =: H <- Z <- B 1208 HZB := DefectOfExactnessSequence( mor[1], mor[2] ); 1209 1210 ## Z <- B 1211 ZB := HighestDegreeMorphism( HZB ); 1212 1213 Z := Range( ZB ); 1214 1215 ## horse shoe 1216 HZB := Resolution( q, HZB ); 1217 1218 ## Z <- B 1219 ZB := HighestDegreeMorphism( HZB ); 1220 1221 ## the horse shoe resolution of Z 1222 PZ := Range( ZB ); 1223 1224 ## make this horse shoe resolution of Z the standard one 1225 SetCurrentResolution( Z, PZ ); 1226 1227 ## B <- F <- Z (horse shoe) 1228 BFZ := Resolution( q, KernelSequence( mor[1] ) ); 1229 1230 ## B <- F 1231 BF := LowestDegreeMorphism( BFZ ); 1232 1233 ## enrich CE with the natrual epi 1234 natural_epis.(String( [ 1, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( BF ) ) ); 1235 1236 ## F[i] <- F[i+1] 1237 Add( CE, FB * BF ); 1238 1239 ## F <- Z 1240 FZ := HighestDegreeMorphism( BFZ ); 1241 fi; 1242 fi; 1243 1244 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1245 for i in [ 3 .. l ] do 1246 ## Z/B =: H <- Z <- B 1247 HZB := DefectOfExactnessSequence( mor[i], mor[i-1] ); 1248 1249 Z := Range( HighestDegreeMorphism( HZB ) ); 1250 1251 ## horse shoe 1252 HZB := Resolution( q, HZB ); 1253 1254 ## the horse shoe resolution of Z 1255 PZ := Range( HighestDegreeMorphism( HZB ) ); 1256 1257 ## make this horse shoe resolution of Z the standard one 1258 SetCurrentResolution( Z, PZ ); 1259 1260 ## B <- F <- Z (horse shoe) 1261 BFZ := Resolution( q, KernelSequence( mor[i-1] ) ); 1262 1263 ## B <- F 1264 BF := LowestDegreeMorphism( BFZ ); 1265 1266 ## enrich CE with the natrual epi 1267 natural_epis.(String( [ i - 1, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( BF ) ) ); 1268 1269 ## F[i] <- F[i+1] 1270 Add( CE, BF * ZB * FZ ); 1271 1272 ## Z <- B 1273 ZB := HighestDegreeMorphism( HZB ); 1274 1275 ## F <- Z 1276 FZ := HighestDegreeMorphism( BFZ ); 1277 od; 1278 else 1279 for i in [ 3 .. l ] do 1280 ## Z/B =: H <- Z <- B 1281 HZB := DefectOfExactnessSequence( mor[i-1], mor[i] ); 1282 1283 Z := Range( HighestDegreeMorphism( HZB ) ); 1284 1285 ## horse shoe 1286 HZB := Resolution( q, HZB ); 1287 1288 ## the horse shoe resolution of Z 1289 PZ := Range( HighestDegreeMorphism( HZB ) ); 1290 1291 ## make this horse shoe resolution of Z the standard one 1292 SetCurrentResolution( Z, PZ ); 1293 1294 ## B <- F <- Z (horse shoe) 1295 BFZ := Resolution( q, KernelSequence( mor[i-1] ) ); 1296 1297 ## B <- F 1298 BF := LowestDegreeMorphism( BFZ ); 1299 1300 ## enrich CE with the natrual epi 1301 natural_epis.(String( [ i - 1, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( BF ) ) ); 1302 1303 ## F[i] <- F[i+1] 1304 Add( CE, FZ * ZB * BF ); 1305 1306 ## Z <- B 1307 ZB := HighestDegreeMorphism( HZB ); 1308 1309 ## F <- Z 1310 FZ := HighestDegreeMorphism( BFZ ); 1311 od; 1312 fi; 1313 1314 ## B <- F <- Z 1315 BFZ := Resolution( q, KernelSequence( mor[l] ) ); 1316 1317 BF := LowestDegreeMorphism( BFZ ); 1318 1319 ## enrich CE with the natrual epi 1320 natural_epis.(String( [ l, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( BF ) ) ); 1321 1322 if l > 1 then 1323 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1324 Add( CE, BF * ZB * FZ ); 1325 else 1326 Add( CE, FZ * ZB * BF ); 1327 fi; 1328 else 1329 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1330 Add( CE, BF * FB ); 1331 else 1332 Add( CE, FB * BF ); 1333 fi; 1334 fi; 1335 1336 if HasIsExactSequence( C ) and IsExactSequence( C ) then 1337 SetIsExactSequence( CE, true ); 1338 elif HasIsRightAcyclic( C ) and IsRightAcyclic( C ) then 1339 SetIsRightAcyclic( CE, true ); 1340 elif HasIsLeftAcyclic( C ) and IsLeftAcyclic( C ) then 1341 SetIsLeftAcyclic( CE, true ); 1342 elif HasIsAcyclic( C ) and IsAcyclic( C ) then 1343 SetIsAcyclic( CE, true ); 1344 else 1345 SetIsComplex( CE, true ); 1346 fi; 1347 1348 ## the Cartan-Eilenberg resolution: 1349 return CE; 1350 1351end ); 1352 1353## the Cartan-Eilenberg resolution [HS. Lemma VIII.9.4] 1354InstallMethod( Resolution, ### defines: Resolution 1355 "for homalg complexes", 1356 [ IsInt, IsCocomplexOfFinitelyPresentedObjectsRep ], 1357 1358 function( _q, C ) 1359 local q, degrees, l, def, d, mor, index_pairs, ZFB, FB, CE, natural_epis, 1360 i, BZH, Z, PZ, relZ, BZ, ZF, BFQ, BF; 1361 1362 if not IsComplex( C ) then 1363 Error( "the second argument is not a cocomplex\n" ); 1364 fi; 1365 1366 # Do the HorseShoeResolution in that case 1367 if HasIsShortExactSequence( C ) and IsShortExactSequence( C ) then 1368 TryNextMethod( ); 1369 fi; 1370 1371 q := _q; 1372 1373 degrees := ObjectDegreesOfComplex( C ); 1374 1375 l := Length( degrees ) - 1; 1376 1377 def := ObjectsOfComplex( DefectOfExactness( C ) ); 1378 1379 if l = 0 then 1380 return HomalgCocomplex( Resolution( q, def[1] ), degrees[1] ); 1381 fi; 1382 1383 d := List( def, M -> Resolution( q, M ) ); 1384 1385 if q < 0 then 1386 q := Maximum( List( def, LengthOfResolution ) ); 1387 d := List( def, M -> Resolution( q, M ) ); 1388 fi; 1389 1390 mor := MorphismsOfComplex( C ); 1391 1392 index_pairs := List( mor, PairOfPositionsOfTheDefaultPresentations ); 1393 1394 ## Z -> F -> B (horse shoe) 1395 ZFB := Resolution( q, KernelCosequence( mor[1] ) ); 1396 1397 ## F -> B 1398 FB := HighestDegreeMorphism( ZFB ); 1399 1400 ## F 1401 CE := HomalgCocomplex( Source( FB ), degrees[1] ); 1402 1403 ## enrich CE with the natrual epis 1404 natural_epis := rec( ); 1405 1406 CE!.NaturalEpis := natural_epis; 1407 1408 natural_epis.(String( [ 0, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Source( FB ) ) ); 1409 1410 for i in [ 2 .. l ] do 1411 1412 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1413 ## B -> Z -> H := Z/B 1414 BZH := DefectOfExactnessCosequence( mor[i-1], mor[i] ); 1415 else 1416 ## B -> Z -> H := Z/B 1417 BZH := DefectOfExactnessCosequence( mor[i], mor[i-1] ); 1418 fi; 1419 1420 ## B -> Z 1421 BZ := LowestDegreeMorphism( BZH ); 1422 1423 Z := Range( BZ ); 1424 1425 ## horse shoe 1426 BZH := Resolution( q, BZH ); 1427 1428 ## B -> Z 1429 BZ := LowestDegreeMorphism( BZH ); 1430 1431 ## the horse shoe resolution of Z 1432 PZ := Range( BZ ); 1433 1434 ## make this horse shoe resolution of Z the standard one 1435 SetCurrentResolution( Z, PZ ); 1436 1437 ## Z -> F -> B (horse shoe) 1438 ZFB := Resolution( q, KernelCosequence( mor[i] ) ); 1439 1440 ## Z -> F 1441 ZF := LowestDegreeMorphism( ZFB ); 1442 1443 ## enrich CE with the natrual epi 1444 natural_epis.(String( [ i - 1, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Range( ZF ) ) ); 1445 1446 ## F[i-1] -> F[i] 1447 Add( CE, PreCompose( PreCompose( FB, BZ ), ZF ) ); 1448 1449 ## F -> B 1450 FB := HighestDegreeMorphism( ZFB ); 1451 od; 1452 1453 ## B -> F -> Q = F/B 1454 BFQ := Resolution( q, CokernelCosequence( mor[l] ) ); 1455 1456 BF := LowestDegreeMorphism( BFQ ); 1457 1458 ## enrich CE with the natrual epi 1459 natural_epis.(String( [ l, 0 ] )) := CokernelEpi( LowestDegreeMorphism( Range( BF ) ) ); 1460 1461 if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then 1462 Add( CE, FB * BF ); 1463 else 1464 Add( CE, BF * FB ); 1465 fi; 1466 1467 if HasIsExactSequence( C ) and IsExactSequence( C ) then 1468 SetIsExactSequence( CE, true ); 1469 elif HasIsRightAcyclic( C ) and IsRightAcyclic( C ) then 1470 SetIsRightAcyclic( CE, true ); 1471 elif HasIsLeftAcyclic( C ) and IsLeftAcyclic( C ) then 1472 SetIsLeftAcyclic( CE, true ); 1473 elif HasIsAcyclic( C ) and IsAcyclic( C ) then 1474 SetIsAcyclic( CE, true ); 1475 else 1476 SetIsComplex( CE, true ); 1477 fi; 1478 1479 ## the Cartan-Eilenberg resolution: 1480 return CE; 1481 1482end ); 1483 1484