1################################################################################ 2## 3## simpcomp / io.gi 4## 5## simpcomp IO functions 6## 7## $Id$ 8## 9################################################################################ 10 11#make list to dense string (not containing any spaces 12SCIntFunc.ListToDenseString:=function(item) 13 if(IsStringRep(item)) then 14 return Concatenation(["\"",item,"\""]); 15 elif(IsList(item) and not IsStringRep(item)) then 16 return Concatenation("[", 17 JoinStringsWithSeparator(List(item,SCIntFunc.ListToDenseString),","),"]"); 18 else 19 return String(item); 20 fi; 21end; 22 23 24 25 26#parsing variables 27SCIntFunc.parseDelim:=','; 28SCIntFunc.parseOpenstruct:='['; 29SCIntFunc.parseClosestruct:=']'; 30SCIntFunc.parseArray:=['0','1','2','3','4','5','6','7','8','9',' ',',', 31 '[',']','\'','\"']; 32SCIntFunc.parseChar:='\''; 33SCIntFunc.parseString:='\"'; 34SCIntFunc.parseEscape:='\\'; 35 36#reader functions for reading xml (pc)data 37SCIntFunc.ReadInteger:= 38function(string) 39 if IsEmptyString(string) or not ForAll(string,x->IsDigitChar(x) or x='-') then 40 Info(InfoSimpcomp,1,"SCIntFunc.ReadInteger: error reading from string \"", 41 string,"\"."); 42 return fail; 43 else 44 return Int(string); 45 fi; 46end; 47 48SCIntFunc.ReadBoolean:= 49function(string) 50 local b; 51 b:=SCIntFunc.ReadInteger(string); 52 if(b<>fail) then 53 if(b=0) then 54 return false; 55 elif(b=1) then 56 return true; 57 fi; 58 fi; 59 Info(InfoSimpcomp,1,"SCIntFunc.ReadBoolean: error reading from string \"", 60 string,"\"."); 61 return fail; 62end; 63 64SCIntFunc.BooleanToString:= 65function(b) 66 if(b=false) then 67 return "0"; 68 elif(b=true) then 69 return "1"; 70 else 71 return "2"; 72 fi; 73end; 74 75SCIntFunc.ReadString:= 76function(string) 77 return String(string); 78end; 79 80 81SCIntFunc.ReadArray:= 82function(string) 83 local p,ret,ReadArrayInteger,ReadArrayString,ReadArrayArray; 84 85 ReadArrayInteger:=function(arr,pos) 86 local p,int; 87 88 int:=[]; 89 90 for p in [pos..Length(arr)] do 91 if(IsDigitChar(arr[p]) or arr[p]='-') then 92 Add(int,arr[p]); 93 else 94 break; 95 fi; 96 od; 97 98 if(int=[] or (p=Length(arr) and not arr[Length(arr)]=']')) then 99 Info(InfoSimpcomp,1,"ReadArrayInteger: error reading from string \"", 100 arr,"\" at position ",pos,"."); 101 return [fail,pos]; 102 else 103 return [Int(int),p]; 104 fi; 105 end; 106 107 ReadArrayString:=function(arr,pos) 108 local p,int,delim,escape,str; 109 110 str:=[]; 111 escape:=false; 112 delim:=arr[pos]; 113 for p in [pos+1..Length(arr)] do 114 if(arr[p]=SCIntFunc.parseEscape) then 115 escape:=true; 116 continue; 117 fi; 118 119 if(escape) then 120 Add(str,arr[p]); 121 escape:=false; 122 elif(arr[p]=delim) then 123 return [str,p+1]; 124 else 125 Add(str,arr[p]); 126 fi; 127 od; 128 129 Info(InfoSimpcomp,1,"ReadArrayString: error reading from string \"", 130 arr,"\" at position ",pos,"."); 131 return [fail,pos]; 132 end; 133 134 ReadArrayArray:=function(arr,pos) 135 local p,int,ret,a,range; 136 137 a:=[]; 138 range:=false; 139 p:=pos+1; 140 while p<=Length(arr) do 141 if(arr[p]=' ' or arr[p]=',') then 142 p:=p+1; 143 continue; 144 fi; 145 146 if(range and not (IsDigitChar(arr[p]) or arr[p]='-')) then 147 return fail; 148 fi; 149 150 if(not range and arr[p]=']') then 151 return [a,p+1]; 152 elif(arr[p]='[') then 153 ret:=ReadArrayArray(arr,p); 154 elif(IsDigitChar(arr[p]) or arr[p]='-') then 155 ret:=ReadArrayInteger(arr,p); 156 elif(arr[p]='\'' or arr[p]='\"') then 157 ret:=ReadArrayString(arr,p); 158 elif(arr[p]='.' and p<Length(arr) and arr[p+1]='.') then 159 range:=true; 160 p:=p+2; 161 continue; 162 else 163 Info(InfoSimpcomp,1,"ReadArrayArray: unknown type in string \"", 164 arr,"\" at position ",pos,"."); 165 ret:=fail; 166 fi; 167 168 if(ret=fail or ret[1]=fail) then 169 return fail; 170 fi; 171 172 if(not range) then 173 Add(a,ret[1]); 174 p:=ret[2]; 175 else 176 range:=[a[Length(a)]..ret[1]]; 177 a[Length(a)]:=range; 178 p:=ret[2]; 179 range:=false; 180 fi; 181 od; 182 183 return fail; 184 end; 185 186 187 for p in [1..Length(string)] do 188 if(string[p]=' ') then 189 continue; 190 fi; 191 192 if(string[p]='[') then 193 ret:=ReadArrayArray(string,p); 194 if(ret=fail) then 195 return fail; 196 else 197 return ret[1]; 198 fi; 199 else 200 break; 201 fi; 202 od; 203 204 Info(InfoSimpcomp,1,"SCIntFunc.ReadArray: no starting sequence found ", 205 "in string \"",string,"\"."); 206 return fail; 207end; 208 209SCIntFunc.ReadPerm:= 210function(arr) 211 local a; 212 a:=SCIntFunc.ReadArray(arr); 213 if(a<>fail) then 214 return PermList(a); 215 else 216 return fail; 217 fi; 218end; 219 220SCIntFunc.PermToString:= 221function(p) 222 return SCIntFunc.ListToDenseString(ListPerm(p)); 223end; 224 225 226SCIntFunc.ReadPermGroup:= 227function(arr) 228 local a,g; 229 a:=SCIntFunc.ReadArray(arr); 230 231 if(a<>fail) then 232 if a <> [] and a<>[[]] then 233 if(IsString(a[1]) and a[1]<>[]) then 234 if(a[2]<>[]) then 235 g:=Group(List(a[2],x->PermList(x))); 236 else 237 g:=Group(()); 238 fi; 239 SetStructureDescription(g,a[1]); 240 SetName(g,a[1]); 241 return g; 242 else 243 return Group(List(a,x->PermList(x))); 244 fi; 245 else 246 return Group(()); 247 fi; 248 else 249 return fail; 250 fi; 251end; 252 253SCIntFunc.PermGroupToString:= 254function(g) 255 if(HasName(g) and Name(g)<>"") then 256 return String([Name(g),List(GeneratorsOfGroup(g),x->ListPerm(x))]); 257 else 258 return String([StructureDescription(g), 259 List(GeneratorsOfGroup(g),x->ListPerm(x))]); 260 fi; 261end; 262 263 264 265 266 267#position object (gets splitted into elements when serialized to xml, 268#as opposed to list) 269SCPositionalObjectFamily:=NewFamily("SCPositionalObjectFamily", 270 SCIsPositionalObject and IsPositionalObjectRep and IsMutable); 271SCPositionalObjectType:=NewType(SCPositionalObjectFamily,SCIsPositionalObject); 272 273#create positional object from list 274SCIntFunc.SCPositionalObjectFromList:= 275function(list) 276 return Objectify(SCPositionalObjectType,rec(data:=list)); 277end; 278 279#methods for positional object 280InstallMethod( 281 \[\],"for SCPositionalObject", 282 [SCIsPositionalObject,IsInt], 283function(po, pos) 284 return po!.data[pos]; 285end); 286 287InstallMethod( 288 IsBound\[\],"for SCPositionalObject", 289 [SCIsPositionalObject,IsInt], 290function(po, pos) 291 return IsBound(po!.data[pos]); 292end); 293 294InstallMethod( 295 \[\]\:\=,"for SCPositionalObject", 296 [SCIsPositionalObject and IsMutable,IsInt,IsObject], 297function(po, pos, val) 298 po!.data[pos]:=val; 299end); 300 301InstallMethod( 302 Unbind\[\],"for SCPositionalObject", 303 [SCIsPositionalObject and IsMutable,IsInt], 304function(po, pos) 305 Unbind(po!.data[pos]); 306end); 307 308InstallMethod( 309 Length,"for SCPositionalObject", 310 [SCIsPositionalObject], 311function(po) 312 return Length(po!.data); 313end); 314 315InstallMethod( 316 ViewObj,"for SCPositionalObject", 317 [SCIsPositionalObject], 318function(po) 319 ViewObj(po!.data); 320end); 321 322InstallMethod( 323 PrintObj,"for SCPositionalObject", 324 [SCIsPositionalObject], 325function(po) 326 PrintObj(po!.data); 327end); 328 329 330#serialize object to xml 331SCIntFunc.SCObjectToXML:= 332function(object,name,ident) 333 local type,prefix,subitems,processed; 334 335 if(object=fail) then 336 return ""; 337 fi; 338 339 processed:=false; 340 for type in RecNames(SCIntFunc.SCXMLIOHandlers) do 341 if(not SCIntFunc.SCXMLIOHandlers.(type)[1](object)) then 342 continue; 343 else 344 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t")); 345 346 if(SCIntFunc.SCXMLIOHandlers.(type)[4]=true) then 347 #atomic type 348 return Concatenation([prefix,"<",String(name)," type=\"",type,"\">", 349 SCIntFunc.SCXMLIOHandlers.(type)[2](object),"</",name,">\n"]); 350 else 351 #compound type 352 return Concatenation([prefix,"<",String(name)," type=\"",type,"\">\n", 353 SCIntFunc.SCXMLIOHandlers.(type)[2](object,ident),prefix,"</",name, 354 ">\n"]); 355 fi; 356 fi; 357 od; 358 359 Info(InfoSimpcomp,3,"SCIntFunc.SCObjectToXML: ignoring property ",name, 360 " -- unknown type."); 361 return ""; 362end; 363 364 365#element reading handler for xml reader 366SCIntFunc.SCXMLElementHandler:= 367function(target,pos,root) 368 local type,content,c,value,data,lpos; 369 370 if(root.name="PCDATA" or root.name="XMLPI" or 371 root.name="XMLCOMMENT" or root.name="Ignore") then 372 #ignore processing instructions & comments 373 return 0; 374 fi; 375 376 #assume type string 377 type:="SCString"; 378 value:=fail; 379 380 if "attributes" in RecNames(root) and "type" in RecNames(root.attributes) then 381 type:=root.attributes.type; 382 fi; 383 384 385 if(type="SCEmpty") then 386 return 1; 387 fi; 388 389 390 if(not type in RecNames(SCIntFunc.SCXMLIOHandlers)) then 391 Info(InfoSimpcomp,3,"SCIntFunc.SCXMLElementHandler: warning, ignoring ", 392 "unknown type \"",type,"\"."); 393 return 0; 394 fi; 395 396 value:=fail; 397 if(SCIntFunc.SCXMLIOHandlers.(type)[4]=true) then 398 #atomic content 399 content:=fail; 400 for c in root.content do 401 if c.name="PCDATA" then 402 content:=c.content; 403 break; 404 fi; 405 od; 406 407 if(content=fail) then 408 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: getting content of ", 409 "xml node ",root," failed."); 410 return -1; 411 fi; 412 413 value:=SCIntFunc.SCXMLIOHandlers.(type)[3](content); 414 else 415 #xml content 416 value:=SCIntFunc.SCXMLIOHandlers.(type)[3](root); 417 fi; 418 419 if(value=fail) then 420 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: I/O handler ", 421 "for property ",root.name," failed."); 422 return -1; 423 fi; 424 425 if(IsRecord(target)) then 426 target.(root.name):=value; 427 elif(IsList(target)) then 428 target[pos]:=value; 429 else 430 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLElementHandler: target object ", 431 "neither of Record nor of List type. target=",target,"."); 432 return -1; 433 fi; 434 435 return 1; 436end; 437 438#deserialize xml to object 439SCIntFunc.SCXMLToObject:= 440function(xml) 441 local n,tree,items,pos; 442 443 if(IsEmptyString(xml)) then 444 return []; 445 fi; 446 tree:=ParseTreeXMLString(xml); 447 if(tree=fail) then 448 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLToObject: parsing xml ", 449 "input string failed."); 450 return fail; 451 fi; 452 if tree.name="WHOLEDOCUMENT" then 453 #start processing 454 items:=[]; 455 pos:=1; 456 for n in tree.content do 457 if(SCIntFunc.SCXMLElementHandler(items,pos,n)>0) then 458 pos:=pos+1; 459 460 fi; 461 od; 462 return items; 463 fi; 464 465 Info(InfoSimpcomp,1,"SCIntFunc.SCXMLToObject: xml document root not found."); 466 return fail; 467end; 468 469 470#serialize record to xml 471SCIntFunc.RecordToXML:= 472function(object,ident) 473 local key,subitems; 474 475 if(not IsRecord(object)) then 476 Info(InfoSimpcomp,1,"SCIntFunc.RecordToXML: first argument must be ", 477 "of type Record."); 478 return ""; 479 fi; 480 481 subitems:=""; 482 for key in RecNames(object) do 483 Append(subitems,SCIntFunc.SCObjectToXML(object.(key),key,ident+1)); 484 od; 485 return subitems; 486end; 487 488 489#deserialize record from xml 490SCIntFunc.RecordFromXML:= 491function(root) 492 local c,r; 493 r:=rec(); 494 for c in root.content do 495 SCIntFunc.SCXMLElementHandler(r,1,c); 496 od; 497 return r; 498end; 499 500 501#serialize positional object to xml 502SCIntFunc.PositionalObjectToXML:= 503function(object,ident) 504 local key,subitems,prefix; 505 subitems:=""; 506 507 if(not SCIsPositionalObject(object)) then 508 Info(InfoSimpcomp,1,"SCIntFunc.PositionalObjectToXML: first argument ", 509 "must be of type SCPositionalObject."); 510 return ""; 511 fi; 512 513 514 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t")); 515 for key in [1..Length(object)] do 516 if(not IsBound(object[key])) then 517 Append(subitems,Concatenation(prefix, 518 "\t<Entry type=\"SCEmpty\"></Entry>\n")); 519 else 520 Append(subitems,SCIntFunc.SCObjectToXML(object[key],"Entry",ident+1)); 521 fi; 522 od; 523 return subitems; 524end; 525 526 527#deserialize positional object from xml 528SCIntFunc.PositionalObjectFromXML:= 529function(root) 530 local c,po,pos; 531 po:=[]; 532 pos:=1; 533 for c in root.content do 534 if(SCIntFunc.SCXMLElementHandler(po,pos,c)>0) then 535 pos:=pos+1; 536 fi; 537 od; 538 return SCIntFunc.SCPositionalObjectFromList(po); 539end; 540 541 542 543#serialize fp group to xml 544SCIntFunc.FpGroupToXML:= 545function(object,ident) 546 local key,subitems,prefix; 547 subitems:=""; 548 549 if(not IsFpGroup(object)) then 550 Info(InfoSimpcomp,1,"SCIntFunc.FpGroupToXML: first argument must be ", 551 "of type FpGroup."); 552 return ""; 553 fi; 554 555 556 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t")); 557 558 Append(subitems,Concatenation(prefix,"\t<Generators type=\"SCArray\">", 559 String(List(GeneratorsOfGroup(object),String)),"</Generators>\n")); 560 Append(subitems,Concatenation(prefix,"\t<Relators type=\"SCArray\">", 561 String(List(RelatorsOfFpGroup(object),String)),"</Relators>\n")); 562 563 #return subitems; 564 return ""; 565end; 566 567 568#deserialize fp group from xml 569SCIntFunc.FpGroupFromXML:= 570function(root) 571 local c,po,pos; 572 po:=[]; 573 pos:=1; 574 for c in root.content do 575 if(SCIntFunc.SCXMLElementHandler(po,pos,c)>0) then 576 pos:=pos+1; 577 fi; 578 od; 579 return []; 580end; 581 582 583#serialize simplicial complex object to xml 584SCIntFunc.SCSimplicialComplexToXML:= 585function(object,ident) 586 local key,subitems,prefix; 587 subitems:=""; 588 589 if(not SCIsSimplicialComplex(object)) then 590 Info(InfoSimpcomp,1,"SCIsSimplicialComplex: first argument must be of ", 591 "type SCSimplicialComplex."); 592 return ""; 593 fi; 594 595 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t")); 596 subitems:=""; 597 598 #legacy format v1 599 #for key in SCPropertiesNames(object) do 600 # Append(subitems,SCIntFunc.SCObjectToXML(SCPropertyByName(object,key), 601 # key,ident+1)); 602 #od; 603 604 #new format v2 605 for key in KnownAttributesOfObject(object) do 606 Append(subitems,SCIntFunc.SCObjectToXML(object!.(key),key,ident+1)); 607 od; 608 609 return subitems; 610end; 611 612 613#deserialize simplicial complex object from xml, legacy format 1 614SCIntFunc.SCSimplicialComplexFromXMLv1Legacy:=rec( 615Facets:=SCFacetsEx, 616Faces:=SCFaceLatticeEx, 617VertexLabels:=SCFacetsEx, 618StronglyConnected:=SCIsStronglyConnected, 619Connected:=SCIsConnected, 620Generators:=SCGeneratorsEx, 621MinimalNonFaces:=SCMinimalNonFacesEx, 622Pure:=SCIsPure, 623PM:=SCIsPseudoManifold, 624CentrallySymmetric:=SCIsCentrallySymmetric, 625CohomologyBasis:=SCCohomologyBasis, 626HomologyBasis:=SCHomologyBasis, 627); 628 629SCIntFunc.SCSimplicialComplexFromXMLv1:= 630function(root) 631 local props,key,fkey,sc; 632 633 props:=SCIntFunc.RecordFromXML(root); 634 sc:=SCIntFunc.SCNew(); 635 636 for key in RecNames(props) do 637 if(IsBound(SCIntFunc.SCSimplicialComplexFromXMLv1Legacy.(key))) then 638 fkey:=SCIntFunc.SCSimplicialComplexFromXMLv1Legacy.(key); 639 elif(IsBound(SCIntFunc.SCPropertyHandlers.(key))) then 640 fkey:=SCIntFunc.SCPropertyHandlers.(key); 641 else 642 fkey:=EvalString(key); 643 fi; 644 if(Setter(fkey)=false or Setter(fkey)=fail) then 645 Info(InfoSimpcomp,2,"SCIntFunc.SCSimplicialComplexFromXMLv1: legacy ", 646 "format, skipped loading attribute '",key,"'"); 647 continue; 648 fi; 649 Setter(fkey)(sc,props.(key)); 650 od; 651 652 return sc; 653end; 654 655 656#deserialize simplicial complex object from xml, format 2 657SCIntFunc.SCSimplicialComplexFromXMLv2:= 658function(root) 659 local props,key,sc; 660 661 props:=SCIntFunc.RecordFromXML(root); 662 sc:=SCIntFunc.SCNew(); 663 664 for key in RecNames(props) do 665 Setter(EvalString(key))(sc,props.(key)); 666 od; 667 668 return sc; 669end; 670 671 672 673#serialize library repository object to xml 674SCIntFunc.SCLibraryRepositoryToXML:= 675function(object,ident) 676 local key,subitems,prefix; 677 subitems:=""; 678 679 if(not SCIsLibRepository(object)) then 680 Info(InfoSimpcomp,1,"SCIntFunc.SCLibraryRepositoryToXML: first argument ", 681 "must be of type SCLibRepository."); 682 return ""; 683 fi; 684 685 prefix:=Concatenation(ListWithIdenticalEntries(ident,"\t")); 686 subitems:=""; 687 for key in SCPropertiesNames(object) do 688 if(key="Loaded") then continue; fi; 689 Append(subitems,SCIntFunc.SCObjectToXML(SCPropertyByName(object,key), 690 key,ident+1)); 691 od; 692 return subitems; 693end; 694 695 696#deserialize library repository object from xml 697SCIntFunc.SCLibraryRepositoryFromXML:= 698function(root) 699 local props; 700 701 props:=SCIntFunc.RecordFromXML(root); 702 703 if(props=fail) then 704 return fail; 705 fi; 706 707 return SCIntFunc.LibRepositoryEmptyWithAttributes(props); 708end; 709 710 711 712################################################################################ 713##<#GAPDoc Label="SCLoad"> 714## <ManSection> 715## <Func Name="SCLoad" Arg="filename"/> 716## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 717## success, <K>fail</K> otherwise.</Returns> 718## <Description> 719## Loads a simplicial complex stored in a binary format (using 720## <C>IO_Pickle</C>) from a file specified in <Arg>filename</Arg> (as string). 721## If <Arg>filename</Arg> does not end in <C>.scb</C>, this suffix is 722## appended to the file name. 723## <Example> 724## gap> c:=SCBdSimplex(3);; 725## gap> SCSave(c,"/tmp/bddelta3"); 726## true 727## gap> d:=SCLoad("/tmp/bddelta3"); 728## [SimplicialComplex 729## 730## Properties known: AutomorphismGroup, AutomorphismGroupOrder, 731## AutomorphismGroupStructure, AutomorphismGroupTransitivity, 732## Chi, Dim, F, Facets, Generators, HasBoundary, Homology, 733## IsConnected, IsStronglyConnected, Name, TopologicalType, 734## SCVertices. 735## 736## Name="S^2_4" 737## Dim=2 738## TopologicalType="S^2" 739## Chi=2 740## F=[4, 6, 4] 741## Homology=[[0, []], [0, []], [1, []]] 742## AutomorphismGroupStructure="S4" 743## 744## /SimplicialComplex] 745## gap> c=d; 746## </Example> 747## </Description> 748## </ManSection> 749##<#/GAPDoc> 750################################################################################ 751InstallGlobalFunction(SCLoad, 752 function(filename) 753 754 local lf,fh,c; 755 756 if(not IsString(filename)) then 757 Info(InfoSimpcomp,1,"SCLoad: first argument must be of type String."); 758 return fail; 759 fi; 760 761 #try to detect format (xml,binary) by extension 762 if(Length(filename)>2 and 763 filename{[Length(filename)-2..Length(filename)]}=".sc") then 764 Info(InfoSimpcomp,2,"SCLoad: assuming XML format for file '", 765 filename,"', falling back to SCLoadXML."); 766 return SCLoadXML(filename); 767 fi; 768 769 lf:=ShallowCopy(filename); 770 if(Length(filename)<4 or 771 filename{[Length(filename)-3..Length(filename)]}<>".scb") then 772 Append(lf,".scb"); 773 fi; 774 775 fh:=IO_File(lf,"r"); 776 777 if(fh=fail) then 778 Info(InfoSimpcomp,1,"SCLoad: Error opening file '",lf,"' for reading."); 779 return fail; 780 fi; 781 782 #unpickle 783 c:=IO_Unpickle(fh); 784 785 IO_Close(fh); 786 787 if(c=IO_Error) then 788 Info(InfoSimpcomp,1,"SCLoad: Error loading simplicial complex from file '", 789 lf,"'."); 790 return fail; 791 else 792 return c; 793 fi; 794 795end); 796 797 798################################################################################ 799##<#GAPDoc Label="SCLoadXML"> 800## <ManSection> 801## <Func Name="SCLoadXML" Arg="filename"/> 802## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 803## success, <K>fail</K> otherwise.</Returns> 804## <Description> 805## Loads a simplicial complex stored in XML format from a file specified in 806## <Arg>filename</Arg> (as string). If <Arg>filename</Arg> does not end in 807## <C>.sc</C>, this suffix is appended to the file name. 808## <Example> 809## gap> c:=SCBdSimplex(3);; 810## gap> SCSaveXML(c,"/tmp/bddelta3"); 811## true 812## gap> d:=SCLoadXML("/tmp/bddelta3"); 813## [SimplicialComplex 814## 815## Properties known: AutomorphismGroup, AutomorphismGroupOrder, 816## AutomorphismGroupStructure, AutomorphismGroupTransitivity, 817## Chi, Dim, F, Facets, Generators, HasBoundary, Homology, 818## IsConnected, IsStronglyConnected, Name, TopologicalType, 819## SCVertices. 820## 821## Name="S^2_4" 822## Dim=2 823## TopologicalType="S^2" 824## Chi=2 825## F=[4, 6, 4] 826## Homology=[[0, []], [0, []], [1, []]] 827## AutomorphismGroupStructure="S4" 828## 829## /SimplicialComplex] 830## gap> c=d; 831## </Example> 832## </Description> 833## </ManSection> 834##<#/GAPDoc> 835################################################################################ 836InstallGlobalFunction(SCLoadXML, 837 function(filename) 838 839 local data,obj,lf; 840 841 if(not IsString(filename)) then 842 Info(InfoSimpcomp,1,"SCLoadXML: first argument must be of type String."); 843 return fail; 844 fi; 845 846 lf:=ShallowCopy(filename); 847 if(Length(filename)<3 or 848 filename{[Length(filename)-2..Length(filename)]}<>".sc") then 849 Append(lf,".sc"); 850 fi; 851 852 data:=StringFile(lf); 853 if(data=fail or IsEmptyString(data)) then 854 Info(InfoSimpcomp,1,"SCLoadXML: error reading file \"",lf,"\"."); 855 return fail; 856 fi; 857 858 obj:=SCIntFunc.SCXMLToObject(data); 859 860 if(obj=fail or Length(obj)<1 or not SCIsSimplicialComplex(obj[1])) then 861 Info(InfoSimpcomp,1,"SCLoadXML: error loading simplicial complex from file."); 862 return fail; 863 fi; 864 865 return obj[1]; 866end); 867 868 869 870################################################################################ 871##<#GAPDoc Label="SCSave"> 872## <ManSection> 873## <Func Name="SCSave" Arg="complex, filename"/> 874## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 875## <Description> 876## Saves a simplicial complex in a binary format (using <C>IO_Pickle</C>) to 877## a file specified in <Arg>filename</Arg> (as string). If <Arg>filename</Arg> 878## does not end in <C>.scb</C>, this suffix is appended to the file name. 879## <Example> 880## gap> c:=SCBdSimplex(3);; 881## gap> SCSave(c,"/tmp/bddelta3"); 882## true 883## </Example> 884## </Description> 885## </ManSection> 886##<#/GAPDoc> 887################################################################################ 888InstallGlobalFunction(SCSave, 889 function(complex,filename) 890 891 local fh,lf; 892 893 if(not SCIsSimplicialComplex(complex) or not IsString(filename)) then 894 Info(InfoSimpcomp,1,"SCSave: first argument must be of type ", 895 "SCSimplicialComplex, second of type String."); 896 return fail; 897 fi; 898 899 lf:=ShallowCopy(filename); 900 if(Length(filename)>2 and 901 filename{[Length(filename)-2..Length(filename)]}=".sc") then 902 Append(lf,"b"); 903 fi; 904 905 if(Length(lf)<4 or lf{[Length(lf)-3..Length(lf)]}<>".scb") then 906 Append(lf,".scb"); 907 fi; 908 909 Info(InfoSimpcomp,3,"SCSave: Saving simplicial complex to file '",lf,"'."); 910 fh:=IO_File(lf,"w"); 911 912 if(fh=fail) then 913 Info(InfoSimpcomp,1,"SCSave: Error opening file '",lf,"' for writing."); 914 return fail; 915 fi; 916 917 #pickle 918 if(IO_Pickle(fh,complex)<>IO_OK) then 919 Info(InfoSimpcomp,1,"SCSave: Error saving simplicial complex to file '", 920 lf,"'."); 921 IO_Close(fh); 922 return fail; 923 else 924 IO_Close(fh); 925 return true; 926 fi; 927end); 928 929 930################################################################################ 931##<#GAPDoc Label="SCSaveXML"> 932## <ManSection> 933## <Func Name="SCSaveXML" Arg="complex, filename"/> 934## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 935## <Description> 936## Saves a simplicial complex <Arg>complex</Arg> to a file specified by 937## <Arg>filename</Arg> (as string) in XML format. If <Arg>filename</Arg> does 938## not end in <C>.sc</C>, this suffix is appended to the file name. 939## <Example> 940## gap> c:=SCBdSimplex(3);; 941## gap> SCSaveXML(c,"/tmp/bddelta3"); 942## true 943## </Example> 944## </Description> 945## </ManSection> 946##<#/GAPDoc> 947################################################################################ 948InstallGlobalFunction(SCSaveXML, 949 function(complex,filename) 950 951 local buf,lf; 952 953 if(not SCIsSimplicialComplex(complex) or not IsString(filename)) then 954 Info(InfoSimpcomp,1,"SCSaveXML: first argument must be of type ", 955 "SCSimplicialComplex, second of type String."); 956 return fail; 957 fi; 958 959 lf:=ShallowCopy(filename); 960 961 if(Length(filename)>3 and 962 filename{[Length(filename)-3..Length(filename)]}=".scb") then 963 lf:=lf{[1..Length(lf)-1]}; 964 fi; 965 966 if(Length(lf)<3 or lf{[Length(lf)-2..Length(lf)]}<>".sc") then 967 Append(lf,".sc"); 968 fi; 969 970 Info(InfoSimpcomp,3,"SCSaveXML: saving simplicial complex to file '",lf,"'."); 971 972 buf:=Concatenation("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", 973 SCIntFunc.SCObjectToXML(complex,"SimplicialComplexV2",0)); 974 975 if(FileString(lf,buf)=fail) then 976 Info(InfoSimpcomp,1,"SCSaveXML: file \"",filename,"\" not writeable!"); 977 return fail; 978 else 979 return true; 980 fi; 981end); 982 983 984SCIntFunc.SCGetSimplicialComplexAttributesXMLEx:= 985function(sc,attrs) 986 local buf,pname,prop,ptype; 987 988 if(Length(attrs)>0 and not ForAll(attrs,IsString)) then 989 Info(InfoSimpcomp,1,"SCIntFunc.SCGetSimplicialComplexAttributesXMLEx: ", 990 "invalid attribute list."); 991 return fail; 992 fi; 993 994 buf:=""; 995 996 for pname in Intersection(SCPropertiesNames(sc),attrs) do 997 prop:=SCPropertyByName(sc,pname); 998 Append(buf,SCIntFunc.SCObjectToXML(prop,pname,1)); 999 od; 1000 1001 return buf; 1002end; 1003 1004 1005SCIntFunc.SCGetSimplicialComplexAttributesXML:= 1006function(sc,attrs) 1007 local buf; 1008 1009 buf:=SCIntFunc.SCGetSimplicialComplexAttributesXMLEx(sc,attrs); 1010 if(buf=fail) then return fail; fi; 1011 1012 return Concatenation(["<SimplicialComplex>\n",buf,"</SimplicialComplex>\n\n"]); 1013end; 1014 1015################################################################################ 1016##<#GAPDoc Label="SCExportMacaulay2"> 1017## <ManSection> 1018## <Func Name="SCExportMacaulay2" Arg="complex, ring, filename [, alphalabels]"/> 1019## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 1020## <Description> 1021## Exports the facet list of a given simplicial complex <Arg>complex</Arg> in 1022## <C>Macaulay2</C> format to a file specified by <Arg>filename</Arg>. The 1023## argument <Arg>ring</Arg> can either be the ring of integers (specified by 1024## <C>Integers</C>) or the ring of rationals (sepcified by <C>Rationals</C>). 1025## The optional boolean argument <Arg>alphalabels</Arg> labels the complex 1026## with characters from <M>a, \dots ,z</M> in the exported file if a value of 1027## <K>true</K> is supplied, while the standard labeling of the vertices is 1028## <M>v_1, \dots ,v_n</M> where <M>n</M> is the number of vertices of 1029## <Arg>complex</Arg>. If <Arg>complex</Arg> has more than <M>26</M> 1030## vertices, the argument <Arg>alphalabels</Arg> is ignored. 1031## <Example> 1032## gap> c:=SCBdCrossPolytope(4);; 1033## gap> SCExportMacaulay2(c,Integers,"/tmp/bdbeta4.m2"); 1034## true 1035## </Example> 1036## </Description> 1037## </ManSection> 1038##<#/GAPDoc> 1039################################################################################ 1040InstallGlobalFunction(SCExportMacaulay2, 1041function(arg) 1042 local complex,filename,ring,alpha,buf,i,s,v,verts,lut,facets; 1043 1044 if(Length(arg)<3 or Length(arg)>4 or not SCIsSimplicialComplex(arg[1]) or 1045 (not IsIntegers(arg[2]) and not IsRationals(arg[2])) or 1046 not IsStringRep(arg[3])) then 1047 Info(InfoSimpcomp,1,"SCExportMacaulay2: invalid arguments, first", 1048 "argument must be of type SCSimplicialComplex, seconds a ring ", 1049 "(Integers or Rationals), third a string."); 1050 return fail; 1051 fi; 1052 1053 complex:=arg[1]; 1054 ring:=arg[2]; 1055 filename:=arg[3]; 1056 1057 if(SCIsEmpty(complex)) then 1058 Info(InfoSimpcomp,1,"SCExportMacaulay2: empty complex, duh."); 1059 return true; 1060 fi; 1061 1062 if(Length(arg)=4 and IsBool(arg[4]) and arg[4]=true) then 1063 alpha:=true; 1064 else 1065 alpha:=false; 1066 fi; 1067 1068 1069 buf:=["-- simpcomp export of complex ",SCName(complex), 1070 "\n\nloadPackage \"SimplicialComplexes\";\n\nR = "]; 1071 1072 if(IsIntegers(ring)) then 1073 Add(buf,"ZZ["); 1074 else 1075 Add(buf,"QQ["); 1076 fi; 1077 1078 verts:=Union(SCSkelEx(complex,0)); 1079 1080 #dump variables 1081 if(Length(verts)<27 and alpha) then 1082 lut:=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o", 1083 "p","q","r","s","t","u","v","w","x","y","z"]; 1084 Add(buf,Concatenation("a..",lut[Length(verts)])); 1085 else 1086 lut:=[1..Length(verts)]; 1087 for i in [1..Length(verts)] do 1088 Add(buf,Concatenation("v",String(i))); 1089 if(i<Length(verts)) then 1090 Add(buf,", "); 1091 fi; 1092 od; 1093 fi; 1094 Add(buf,"];\nFacets = {"); 1095 1096 facets:=SCFacetsEx(complex); 1097 for s in [1..Length(facets)] do 1098 for v in [1..Length(facets[s])] do 1099 if not alpha then 1100 Add(buf,Concatenation("v",String(lut[Position(verts,facets[s][v])]))); 1101 else 1102 Add(buf,String(lut[Position(verts,facets[s][v])])); 1103 fi; 1104 1105 if(v<Length(facets[s])) then 1106 Add(buf,"*"); 1107 elif(s<Length(facets)) then 1108 Add(buf,", "); 1109 fi; 1110 od; 1111 od; 1112 Add(buf,"}\n"); 1113 1114 Add(buf,"complex = simplicialComplex Facets;\n\n-- end of export"); 1115 1116 if(FileString(filename,String(Concatenation(buf)))=fail) then 1117 Info(InfoSimpcomp,1,"SCExportMacaulay2: file \"",filename, 1118 "\" not writeable!"); 1119 return fail; 1120 else 1121 return true; 1122 fi; 1123 1124end); 1125 1126 1127################################################################################ 1128##<#GAPDoc Label="SCExportPolymake"> 1129## <ManSection> 1130## <Func Name="SCExportPolymake" Arg="complex, filename"/> 1131## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 1132## <Description> 1133## Exports the facet list with vertex labels of a given simplicial complex 1134## <Arg>complex</Arg> in <C>polymake</C> format to a file specified by 1135## <Arg>filename</Arg>. Currently, only the export in the format of 1136## <C>polymake</C> version 2.3 is supported. 1137## <Example> 1138## gap> c:=SCBdCrossPolytope(4);; 1139## gap> SCExportPolymake(c,"/tmp/bdbeta4.poly"); 1140## true 1141## </Example> 1142## </Description> 1143## </ManSection> 1144##<#/GAPDoc> 1145################################################################################ 1146InstallGlobalFunction(SCExportPolymake, 1147function(complex,filename) 1148 local buf,i,s,v,verts; 1149 1150 buf:=["_application topaz\n_version 2.3\n_type SimplicialComplex\n\nFACETS\n"]; 1151 1152 verts:=SCVertices(complex); 1153 1154 for s in SCFacetsEx(complex) do 1155 Add(buf,"{ "); 1156 for v in s do 1157 Append(buf,[String(Position(verts,v)-1)," "]); 1158 od; 1159 Add(buf,"}\n"); 1160 od; 1161 1162 #print vertex labels 1163 Add(buf,"\nVERTEX_LABELS\n"); 1164 1165 for i in [1..Length(verts)] do 1166 Add(buf,SCIntFunc.ListToDenseString(verts[i])); 1167 if(i<Length(verts)) then Add(buf," "); fi; 1168 od; 1169 Add(buf,"\n\n"); 1170 1171 if(FileString(filename,String(Concatenation(buf)))=fail) then 1172 Info(InfoSimpcomp,1,"SCExportPolymake: file \"",filename,"\" not ", 1173 "writeable!"); 1174 return fail; 1175 else 1176 return true; 1177 fi; 1178 1179end); 1180 1181 1182################################################################################ 1183##<#GAPDoc Label="SCExportRecognizer"> 1184## <ManSection> 1185## <Func Name="SCExportPolymake" Arg="complex, filename"/> 1186## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 1187## <Description> 1188## Exports the gluings of the tetrahedra of a given combinatorial 1189## <M>3</M>-manifold <Arg>complex</Arg> in a format compatible with Matveev's 1190## <M>3</M>-manifold software <C>Recognizer</C>. 1191## <Example> 1192## gap> c:=SCBdCrossPolytope(4);; 1193## gap> SCExportRecognizer(c,"/tmp/bdbeta4.mv"); 1194## true 1195## </Example> 1196## </Description> 1197## </ManSection> 1198##<#/GAPDoc> 1199################################################################################ 1200InstallGlobalFunction(SCExportRecognizer, 1201function(complex,filename) 1202 local buf,i,dim,pm,facets,done,j,k,l,elm,trig,f3; 1203 1204 dim := SCDim(complex); 1205 pm := SCIsPseudoManifold(complex); 1206 if dim <> 3 or pm <> true then 1207 Info(InfoSimpcomp,1,"SCExportRecognizer: input must be a 3-dimensional ", 1208 "weak pseudomanifold."); 1209 return fail; 1210 fi; 1211 1212 buf:=["triangulation\n"]; 1213 facets := SCFacetsEx(complex); 1214 if facets = fail then 1215 return fail; 1216 fi; 1217 f3 := Size(facets); 1218 done := List([1..f3],x->[false,false,false,false]); 1219 for i in [1..f3] do 1220 for j in [4,3,2,1] do 1221 if done[i][j] = true then continue; fi; 1222 elm := [1..4]; 1223 Remove(elm,j); 1224 Append(buf,["t",String(i),"(",String(elm[1]),",",String(elm[2]),",", 1225 String(elm[3]),") - "]); 1226 trig := facets[i]{elm}; 1227 for k in [i+1..f3] do 1228 if IsSubset(facets[k],trig) then 1229 elm := [Position(facets[k],trig[1]),Position(facets[k],trig[2]), 1230 Position(facets[k],trig[3])]; 1231 Append(buf,["t",String(k),"(",String(elm[1]),",",String(elm[2]),",", 1232 String(elm[3]),"),\n"]); 1233 for l in [1..4] do 1234 if not l in elm then 1235 done[k][l] := true; 1236 break; 1237 fi; 1238 od; 1239 break; 1240 fi; 1241 od; 1242 od; 1243 od; 1244 Add(buf,"end\n"); 1245 if(FileString(filename,String(Concatenation(buf)))=fail) then 1246 Info(InfoSimpcomp,1,"SCExportRecognizer: file \"",filename, 1247 "\" not writeable!"); 1248 return fail; 1249 else 1250 return true; 1251 fi; 1252 1253end); 1254 1255################################################################################ 1256##<#GAPDoc Label="SCExportJavaView"> 1257## <ManSection> 1258## <Func Name="SCExportJavaView" Arg="complex, file, coords"/> 1259## <Returns><K>true</K> on success, <K>fail</K> otherwise.</Returns> 1260## <Description> 1261## Exports the 2-skeleton of the given simplicial complex <Arg>complex</Arg> 1262## (or the facets if the complex is of dimension 2 or less) in <C>JavaView</C> 1263## format (file name suffix <C>.jvx</C>) to a file specified by 1264## <Arg>filename</Arg> (as string). The list <Arg>coords</Arg> must contain a 1265## <M>3</M>-tuple of real coordinates for each vertex of <Arg>complex</Arg>, 1266## either as tuple of length three containing the coordinates (Warning: 1267## as &GAP; only has rudimentary support for floating point values, currently 1268## only integer numbers can be used as coordinates when providing 1269## <Arg>coords</Arg> as list of <M>3</M>-tuples) or as string of the form 1270## <C>"x.x y.y z.z"</C> with decimal numbers <C>x.x</C>, <C>y.y</C>, 1271## <C>z.z</C> for the three coordinates (i.e. <C>"1.0 0.0 0.0"</C>). 1272## <Example> 1273## gap> coords:=[[1,0,0],[0,1,0],[0,0,1]];; 1274## gap> SCExportJavaView(SCBdSimplex(2),"/tmp/triangle.jvx",coords); 1275## true 1276## </Example> 1277## </Description> 1278## </ManSection> 1279##<#/GAPDoc> 1280################################################################################ 1281InstallGlobalFunction(SCExportJavaView, 1282function(complex,filename,coords) 1283 local buf,v,f,verts,vertices,trigs,i,name,fl,dim; 1284 1285 if(SCIsEmpty(complex)) then 1286 Info(InfoSimpcomp,1,"SCExportJavaView: empty complex, nothing to do."); 1287 return true; 1288 fi; 1289 1290 buf:=[]; 1291 dim:=SCDim(complex); 1292 if(dim=fail) then 1293 return fail; 1294 fi; 1295 1296 if(dim<3) then 1297 trigs:=SCFacetsEx(complex); 1298 else 1299 trigs:=SCSkelEx(complex,2); 1300 fi; 1301 1302 verts:=Union(SCSkelEx(complex,0)); 1303 1304 if(trigs=fail or verts=fail or Length(verts)<>Length(coords)) then 1305 if(Length(verts)<>Length(coords)) then 1306 Info(InfoSimpcomp,1,"SCExportJavaView: vertex count must match ", 1307 "coordinate count."); 1308 fi; 1309 return fail; 1310 fi; 1311 1312 name:=SCPropertyByName(complex,"Name"); 1313 1314 if(name=fail) then 1315 name:="Unnamed simplcicial complex"; 1316 fi; 1317 1318 1319 Append(buf,Concatenation("\ 1320 <?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>\n\ 1321 <!DOCTYPE jvx-model SYSTEM \"http://www.javaview.de/rsrc/jvx.dtd\">\n\ 1322 <jvx-model>\n\ 1323 <meta generator=\"<Package>simpcomp</Package>\"/>\n\ 1324 <meta dtd=\"1.11.001\"/>\n\ 1325 <meta date=\"\"/>\n\ 1326 <version type=\"dump\">1.0</version>\n\ 1327 <title>",name,"</title>\n\ 1328 <geometries>\n")); 1329 1330 Append(buf,Concatenation("\ 1331 <geometry name=\"",String(verts),"\">\n\ 1332 <pointSet point=\"show\" dim=\"3\">\n\ 1333 <points num=\"",String(Length(verts)),"\">\n")); 1334 1335 vertices:=[]; 1336 for v in [1..Length(verts)] do 1337 if(not IsString(coords[v])) then 1338 #coordinates as list 1339 vertices[v]:=Concatenation("<p name=\"",String(verts[v]),"\">"); 1340 1341 #convert to floating point 1342 for i in [1..3] do 1343 1344 if(not IsInt(coords[v][i])) then 1345 Info(InfoSimpcomp,1,"SCExportJavaView: currently only integer ", 1346 "coordinates are supported when passed as list of coordinate ", 1347 "tuples. Use list of strings instead."); 1348 return fail; 1349 fi; 1350 1351 fl:=ShallowCopy(String(coords[v][i])); 1352 1353 if(PositionSublist(fl,".")=fail) then 1354 Append(fl,".0"); 1355 fi; 1356 1357 Append(vertices[v],fl); 1358 1359 if(i<3) then 1360 Append(vertices[v]," "); 1361 fi; 1362 od; 1363 1364 Append(vertices[v],"</p>"); 1365 else 1366 #coordinates as string 1367 vertices[v]:=Concatenation("<p name=\"",String(verts[v]),"\">", 1368 coords[v],"</p>"); 1369 fi; 1370 Append(buf,Concatenation("\t\t\t",vertices[v],"\n")); 1371 od; 1372 1373 1374 Append(buf,Concatenation("\ 1375 <thickness>4.0</thickness>\n\ 1376 <color type=\"rgb\">255 0 0</color>\n\ 1377 <colorTag type=\"rgb\">255 0 255</colorTag>\n\ 1378 <labelAtt font=\"text\" horAlign=\"head\" name=\"SansSerif\" verAlign=\"middle\" style=\"plain\" visible=\"show\">\n\ 1379 <xOffset>0</xOffset>\n\ 1380 <yOffset>0</yOffset>\n\ 1381 <size>20</size>\n\ 1382 <color type=\"rgb\">0 0 0</color>\n\ 1383 </labelAtt>\n\ 1384 </points>\n\ 1385 </pointSet>\n\ 1386 <faceSet color=\"show\" edge=\"show\" face=\"show\">\n\ 1387 <faces num=\"",String(Length(trigs)),"\">\n")); 1388 1389 for f in trigs do 1390 Append(buf,"\t\t\t<f>"); 1391 for v in [1..Length(f)] do 1392 if(v>1) then Append(buf," "); fi; 1393 Append(buf,String(Position(verts,f[v])-1)); 1394 od; 1395 Append(buf,"</f>\n"); 1396 od; 1397 1398 Append(buf,"\ 1399 <color type=\"rgb\">0 255 0</color>\n\ 1400 <colorTag type=\"rgb\">255 0 255</colorTag>\n\ 1401 <creaseAngle>3.2</creaseAngle>\n\ 1402 </faces>\n\ 1403 <neighbours num=\"1\">\n\ 1404 <nb>-1 -1 -1</nb>\n\ 1405 </neighbours>\n\ 1406 <edges>\n\ 1407 <thickness>1.0</thickness>\n\ 1408 <color type=\"rgb\">0 0 0</color>\n\ 1409 <colorTag type=\"rgb\">255 0 255</colorTag>\n\ 1410 </edges>\n\ 1411 <colors num=\"1\" type=\"rgb\">\n\ 1412 <c>119 236 158</c>\n\ 1413 </colors>\n\ 1414 </faceSet>\n\ 1415 <center visible=\"hide\">\n\ 1416 <p>0.0 0.0 0.0</p>\n\ 1417 </center>\n\ 1418 <material>\n\ 1419 <ambientIntensity>0.2</ambientIntensity>\n\ 1420 <diffuse>\n\ 1421 <color type=\"rgb\">204 204 204</color>\n\ 1422 </diffuse>\n\ 1423 <emissive>\n\ 1424 <color type=\"rgb\">0 0 0</color>\n\ 1425 </emissive>\n\ 1426 <shininess>10.0</shininess>\n\ 1427 <specular>\n\ 1428 <color type=\"rgb\">255 255 255</color>\n\ 1429 </specular>\n\ 1430 <transparency visible=\"show\">0.5</transparency>\n\ 1431 </material>\n\ 1432 </geometry>\n\ 1433 </geometries>\n\ 1434 </jvx-model>\n"); 1435 1436 if(FileString(filename,buf)=fail) then 1437 Info(InfoSimpcomp,1,"SCExportJavaView: filename \"",filename, 1438 "\" not writeable!"); 1439 return fail; 1440 else 1441 return true; 1442 fi; 1443 1444end); 1445 1446################################################################################ 1447##<#GAPDoc Label="SCExportLatexTable"> 1448## <ManSection> 1449## <Func Name="SCExportLatexTable" Arg="complex, filename, itemsperline"/> 1450## <Returns><K>true</K> on success, <K>fail</K> otherwise.</Returns> 1451## <Description> 1452## Exports the facet list of a given simplicial complex <Arg>complex</Arg> 1453## (or any list given as first argument) in form of a &LaTeX; table to a file 1454## specified by <Arg>filename</Arg>. The argument <Arg>itemsperline</Arg> 1455## specifies how many columns the exported table should have. The faces are 1456## exported in the format <M>\langle v_1,\dots,v_k \rangle</M>. 1457## <Example> 1458## gap> c:=SCBdSimplex(5);; 1459## gap> SCExportLatexTable(c,"/tmp/bd5simplex.tex",5); 1460## </Example> 1461## </Description> 1462## </ManSection> 1463##<#/GAPDoc> 1464################################################################################ 1465InstallGlobalFunction(SCExportLatexTable, 1466function(complex,filename,itemsperline) 1467 local i,j,buf,facets; 1468 1469 if(not SCIsSimplicialComplex(complex) and not IsList(complex)) then 1470 Info(InfoSimpcomp,1,"SCExportLatexTable: first argument must be of type ", 1471 "SCSimplicialComplex or a list of faces."); 1472 return fail; 1473 fi; 1474 1475 if(SCIsSimplicialComplex(complex)) then 1476 facets:=SCFacets(complex); 1477 else 1478 facets:=complex; 1479 fi; 1480 1481 if(facets=fail) then 1482 return fail; 1483 fi; 1484 1485 buf:=Concatenation(["\\begin{tabular}{", 1486 Concatenation(ListWithIdenticalEntries(itemsperline,"l")),"}\n"]); 1487 1488 for i in [1..Length(facets)] do 1489 Append(buf,"$\\langle "); 1490 1491 for j in [1..Length(facets[i])-1] do 1492 Append(buf, 1493 Concatenation([SCIntFunc.ListToDenseString(facets[i][j]),"\\,"])); 1494 od; 1495 Append(buf,SCIntFunc.ListToDenseString(facets[i][Length(facets[i])])); 1496 1497 1498 Append(buf," \\rangle$"); 1499 1500 if(i=Length(facets)) then 1501 Append(buf,"."); 1502 Append(buf, 1503 Concatenation(ListWithIdenticalEntries(-(i mod itemsperline) mod itemsperline,"&"))); 1504 Append(buf,"\n"); 1505 break; 1506 fi; 1507 1508 if(i mod itemsperline=0) then 1509 Append(buf,",\\\\\n\n"); 1510 else 1511 Append(buf,", &\n"); 1512 fi; 1513 od; 1514 1515 Append(buf,"\\end{tabular}"); 1516 buf:=ReplacedString(buf,"\"",""); 1517 1518 if(FileString(filename,buf)=fail) then 1519 Info(InfoSimpcomp,1,"SCExportLatexTable: file \"",filename, 1520 "\" not writeable!"); 1521 return fail; 1522 fi; 1523 1524 return true; 1525end); 1526 1527 1528SCIntFunc.SCPrintSCToString:= 1529function(sc) 1530 local buf,props,prop,p; 1531 1532 buf:="[SimplicialComplex\n\n"; 1533 1534 Append(buf," Properties known: "); 1535 props:=List(SCPropertiesNames(sc)); 1536 Sort(props); 1537 1538 for p in [1..Length(props)] do 1539 Append(buf,props[p]); 1540 if(p=Length(props)) then 1541 Append(buf,".\n"); 1542 else 1543 Append(buf,", "); 1544 fi; 1545 od; 1546 1547 for p in ["Facets","Faces","Incidences"] do 1548 if(p in props) then 1549 prop:=SCPropertyByName(sc,p); 1550 if(IsStringRep(prop)) then 1551 Append(buf,Concatenation([" ",p,"=\"",prop,"\"\n"])); 1552 else 1553 Append(buf,Concatenation([" ",p,"=",String(prop),"\n"])); 1554 fi; 1555 fi; 1556 od; 1557 1558 for p in SortedList(Difference(props,["Facets","Faces","Incidences"])) do 1559 prop:=SCPropertyByName(sc,p); 1560 if(IsStringRep(prop)) then 1561 Append(buf,Concatenation([" ",p,"=\"",prop,"\"\n"])); 1562 else 1563 Append(buf,Concatenation([" ",p,"=",String(prop),"\n"])); 1564 fi; 1565 od; 1566 1567 Append(buf,"\n/SimplicialComplex]\n"); 1568 return buf; 1569end; 1570 1571 1572################################################################################ 1573##<#GAPDoc Label="SCImportPolymake"> 1574## <ManSection> 1575## <Func Name="SCImportPolymake" Arg="filename"/> 1576## <Returns>simplicial complex of type <C>SCSimplicialComplex</C> upon 1577## success, <K>fail</K> otherwise.</Returns> 1578## <Description> 1579## Imports the facet list of a <C>topaz</C> <C>polymake</C> file specified by 1580## <Arg>filename</Arg> (discarding any vertex labels) and creates a 1581## simplicial complex object from these facets. 1582## <Example> 1583## gap> c:=SCBdCrossPolytope(4);; 1584## gap> SCExportPolymake(c,"/tmp/bdbeta4.poly"); 1585## gap> d:=SCImportPolymake("/tmp/bdbeta4.poly"); 1586## [SimplicialComplex 1587## 1588## Properties known: Chi, Dim, Facets, SCVertices. 1589## 1590## Name="unnamed complex m" 1591## Dim=3 1592## 1593## /SimplicialComplex] 1594## gap> c=d; 1595## </Example> 1596## </Description> 1597## </ManSection> 1598##<#/GAPDoc> 1599################################################################################ 1600InstallGlobalFunction(SCImportPolymake, 1601function(filename) 1602 local file,lines,fpos,lidx,v,verts,s,facets,sc; 1603 1604 file:=StringFile(filename); 1605 1606 if(file=fail) then 1607 Info(InfoSimpcomp,1,"SCImportPolymake: error reading file \"", 1608 filename,"\"."); 1609 return fail; 1610 fi; 1611 1612 1613 lines:=SplitString(file,"\n"); 1614 Apply(lines,NormalizedWhitespace); 1615 1616 fpos:=Position(lines,"VERTICES_IN_FACETS"); 1617 if(fpos=fail) then 1618 fpos:=Position(lines,"FACETS"); 1619 fi; 1620 1621 1622 if(fpos=fail) then 1623 Info(InfoSimpcomp,1,"SCImportPolymake: could neither find section ", 1624 "VERTICES_IN_FACETS nor section FACETS in polymake file."); 1625 return fail; 1626 fi; 1627 1628 facets:=[]; 1629 for lidx in [fpos+1..Length(lines)] do 1630 if(not IsBound(lines[lidx]) or IsEmptyString(lines[lidx]) or 1631 lines[lidx]=" ") then 1632 break; 1633 fi; 1634 verts:=SplitString(lines[lidx]," ","{}"); 1635 s:=[]; 1636 for v in verts do 1637 if(IsEmpty(v)) then continue; fi; 1638 Add(s,Rat(v)); 1639 od; 1640 Add(facets,s+1); 1641 od; 1642 1643 sc:=SCFromFacets(facets); 1644 1645 if(sc<>fail) then 1646 SCRename(sc,Concatenation("polymake import '",filename,"'")); 1647 fi; 1648 1649 return sc; 1650end); 1651 1652 1653 1654#general io pickling function 1655SCIntFunc.GeneralPicklerIgnoreList:=[ 1656"ComputedSCHomalgBoundaryMatricess", "ComputedSCHomalgCoboundaryMatricess", 1657 "ComputedSCHomalgHomologys", "ComputedSCHomalgCohomologys" 1658]; 1659SCIntFunc.GeneralPickler:= 1660function(f,c,id) 1661 local p; 1662 1663 # write SCSimplicialComplex tag 1664 IO_AddToPickled(c); 1665 if IO_Write(f,id) = fail then 1666 IO_FinalizePickled(); 1667 return IO_Error; 1668 fi; 1669 1670 # write number of attributes 1671 if IO_WriteSmallInt(f,Length(KnownAttributesOfObject(c))) = IO_Error then 1672 IO_FinalizePickled(); 1673 return IO_Error; 1674 fi; 1675 1676 # pickle all attributes 1677 for p in KnownAttributesOfObject(c) do 1678 if(p in SCIntFunc.GeneralPicklerIgnoreList) then 1679 Info(InfoSimpcomp,3,"SCIntFunc.GeneralPickler: ignoring attribute ",p, 1680 " as it is in ignore list (no pickler available)."); 1681 continue; 1682 fi; 1683 1684 # write attribute name 1685 if(IO_Pickle(f,p)<>IO_OK) then 1686 IO_FinalizePickled(); 1687 return IO_Error; 1688 fi; 1689 1690 # write attribute value 1691 if(IO_Pickle(f,c!.(p))<>IO_OK) then 1692 IO_FinalizePickled(); 1693 return IO_Error; 1694 fi; 1695 od; 1696 1697 IO_FinalizePickled(); 1698 return IO_OK; 1699end; 1700 1701#general io unpickling function 1702SCIntFunc.GeneralUnpickler:= 1703function(f,c) 1704 local i,len,name,ob; 1705 1706 # read number of attributes 1707 len:=IO_ReadSmallInt(f); 1708 if len = IO_Error then 1709 Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error during ", 1710 "unpicking of attribute name"); 1711 return c; 1712 fi; 1713 1714 # do unpickling 1715 IO_AddToUnpickled(c); 1716 for i in [1..len] do 1717 # read attribute name 1718 name:=IO_Unpickle(f); 1719 if name = IO_Error or not(IsString(name)) then 1720 Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error while ", 1721 "unpicking attribute name"); 1722 fi; 1723 1724 # read attribute value 1725 ob:=IO_Unpickle(f); 1726 if IO_Result(ob) then 1727 if ob = IO_Error then 1728 Info(InfoSimpcomp,1,"SCIntFunc.GeneralUnpickler: Error while ", 1729 "unpicking attribute value of '",name,"'"); 1730 fi; 1731 else 1732 Setter(EvalString(name))(c,ob); 1733 fi; 1734 od; 1735 IO_FinalizeUnpickled(); 1736end; 1737 1738 1739#pickler for SCSimplicialComplex 1740InstallMethod(IO_Pickle, "for SCSimplicialComplex", 1741[ IsFile, SCIsSimplicialComplex ], 1742function(f,c) 1743 return SCIntFunc.GeneralPickler(f,c,"SCSC"); 1744end); 1745 1746 1747# unpickler for SCSimplicialComplex 1748IO_Unpicklers.SCSC:= 1749function(f) 1750 local c; 1751 1752 # SCSimplicialComplex 1753 c:=SCIntFunc.SCNew(); 1754 1755 SCIntFunc.GeneralUnpickler(f,c); 1756 return c; 1757end; 1758 1759# pickler for SCLibraryRepository 1760InstallMethod(IO_Pickle, "for SCLibRepository", 1761[ IsFile, SCIsLibRepository ], 1762function(f,lr) 1763 IO_AddToPickled(lr); 1764 1765 # write SCLibRepository tag 1766 if IO_Write(f,"SCLR") = fail then 1767 IO_FinalizePickled(); 1768 return IO_Error; 1769 fi; 1770 1771 if(IO_Pickle(f,lr!.Properties)<>IO_OK) then 1772 IO_FinalizePickled(); 1773 return IO_Error; 1774 fi; 1775 1776 IO_FinalizePickled(); 1777 return IO_OK; 1778end); 1779 1780 1781# unpickler for SCLibraryRepository 1782IO_Unpicklers.SCLR:= 1783function(f) 1784 local prop; 1785 1786 #get library properties 1787 prop:=IO_Unpickle(f); 1788 1789 if IO_Result(prop) then 1790 if prop = IO_Error then 1791 Info(InfoSimpcomp,1,"IO_Unpicklers.SCLR: Error while unpicking ", 1792 "library repository. Delete file complexes.idx and complexes.idxb ", 1793 "and recreate them with SCLibInit."); 1794 return IO_Error; 1795 fi; 1796 else 1797 return SCIntFunc.LibRepositoryEmptyWithAttributes(prop); 1798 fi; 1799end; 1800 1801#handler functions for file load/save operations 1802SCIntFunc.SCXMLIOHandlers:= 1803rec( 1804 SCSimplicialComplex:=[SCIsSimplicialComplex, 1805 SCIntFunc.SCSimplicialComplexToXML,SCIntFunc.SCSimplicialComplexFromXMLv1, 1806 false], 1807 SCSimplicialComplexV2:=[SCIsSimplicialComplex, 1808 SCIntFunc.SCSimplicialComplexToXML,SCIntFunc.SCSimplicialComplexFromXMLv2, 1809 false], 1810 SCLibraryRepository:=[SCIsLibRepository,SCIntFunc.SCLibraryRepositoryToXML, 1811 SCIntFunc.SCLibraryRepositoryFromXML,false], 1812 SCRecord:=[IsRecord,SCIntFunc.RecordToXML,SCIntFunc.RecordFromXML,false], 1813 SCPositionalObject:=[SCIsPositionalObject,SCIntFunc.PositionalObjectToXML, 1814 SCIntFunc.PositionalObjectFromXML,false], 1815 SCInteger:=[IsInt,String,SCIntFunc.ReadInteger,true], 1816 SCBoolean:=[IsBool,SCIntFunc.BooleanToString,SCIntFunc.ReadBoolean,true], 1817 SCString:=[IsStringRep,String,SCIntFunc.ReadString,true], 1818 SCArray:=[IsList,SCIntFunc.ListToDenseString,SCIntFunc.ReadArray,true], 1819 SCPerm:=[IsPerm,SCIntFunc.PermToString,SCIntFunc.ReadPerm,true], 1820 SCPermGroup:=[IsPermGroup,SCIntFunc.PermGroupToString,SCIntFunc.ReadPermGroup, 1821 true], 1822 SCFpGroup:=[IsFpGroup,SCIntFunc.FpGroupToXML,SCIntFunc.FpGroupFromXML,false] 1823); 1824 1825 1826################################################################################ 1827 1828################################################################################ 1829##<#GAPDoc Label="SCExportSnapPy"> 1830## <ManSection> 1831## <Func Name="SCExportSnapPy" Arg="complex, filename"/> 1832## <Returns><K>true</K> upon success, <K>fail</K> otherwise.</Returns> 1833## <Description> 1834## Exports the facet list and orientability of a given combinatorial 1835## <M>3</M>-pseudomanifold <Arg>complex</Arg> in <C>SnapPy</C> format to a 1836## file specified by <Arg>filename</Arg>. 1837## <Example> 1838## gap> SCLib.SearchByAttribute("Dim=3 and F=[8,28,56,28]"); 1839## gap> c:=SCLib.Load(last[1][1]);; 1840## gap> SCExportSnapPy(c,"/tmp/M38.tri"); 1841## true 1842## </Example> 1843## </Description> 1844## </ManSection> 1845##<#/GAPDoc> 1846################################################################################ 1847InstallGlobalFunction(SCExportSnapPy, 1848function(complex,filename) 1849 local curvertex,buf,dim,name,orient,lks,i,pmflag,lksconn,kleinb,torus, 1850 sphere,lktype,neighbors,gluings,cusps,j,k,trig,remoteidx,verts,facets; 1851 1852 dim:=SCDim(complex); 1853 if dim=fail then 1854 return fail; 1855 fi; 1856 1857 if dim<>3 then 1858 Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a 3-dimensional ", 1859 "simplicial complex."); 1860 return fail; 1861 fi; 1862 1863 kleinb:=0; 1864 torus:=0; 1865 sphere:=0; 1866 1867 if SCIsManifold(complex) then 1868 sphere:=SCNumFaces(complex,0); 1869 lktype:=ListWithIdenticalEntries(sphere,0); 1870 fi; 1871 1872 if sphere=0 then 1873 1874 lks:=SCLinks(complex,0); 1875 pmflag:=true; 1876 for i in [1..Size(lks)] do 1877 if not SCIsManifold(lks[i]) then 1878 pmflag:=false; 1879 break; 1880 fi; 1881 od; 1882 1883 if pmflag<>true then 1884 Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ", 1885 "3-pseudomanifold."); 1886 return fail; 1887 fi; 1888 1889 lksconn:=true; 1890 for i in [1..Size(lks)] do 1891 if not SCIsConnected(lks[i]) then 1892 lksconn:=false; 1893 break; 1894 fi; 1895 od; 1896 1897 if lksconn<>true then 1898 Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ", 1899 "3-pseudomanifold with connected links."); 1900 return fail; 1901 fi; 1902 1903 lktype:=[]; 1904 for i in [1..Size(lks)] do 1905 if SCEulerCharacteristic(lks[i])=2 then 1906 lktype[i]:=0; 1907 sphere:=sphere+1; 1908 elif SCEulerCharacteristic(lks[i])=0 then 1909 if SCIsOrientable(lks[i]) then 1910 lktype[i]:=1; 1911 torus:=torus+1; 1912 else 1913 lktype[i]:=2; 1914 kleinb:=kleinb+1; 1915 fi; 1916 else 1917 Info(InfoSimpcomp,1,"SCExportSnapPy: argument must be a combinatorial ", 1918 "3-pseudomanifold with links of type S^2, T^2 or K^2."); 1919 return fail; 1920 fi; 1921 od; 1922 1923 fi; 1924 1925 name:=SCName(complex); 1926 if name=fail then 1927 return fail; 1928 fi; 1929 1930 buf:=["% Triangulation\n"]; 1931 Append(buf,[name,"\nunknown 0.0\n"]); 1932 1933 orient:=SCIsOrientable(complex); 1934 if orient=fail then 1935 return fail; 1936 fi; 1937 1938 if orient=true then 1939 Append(buf,["oriented_manifold\nCS_unknown\n\n"]); 1940 else 1941 Append(buf,["nonorientable_manifold\nCS_unknown\n\n"]); 1942 fi; 1943 1944 verts:=SCVertices(complex); 1945 1946 Append(buf,[String(torus)," ",String(kleinb),"\n"]); 1947 for i in [1..SCNumFaces(complex,0)] do 1948 if lktype[i]=0 then 1949 #Append(buf,[" internal 0 0\n"]); 1950 continue; 1951 elif lktype[i]=1 then 1952 Append(buf,[" torus 0 0\n"]); 1953 elif lktype[i]=2 then 1954 Append(buf,[" Klein bottle 0 0\n"]); 1955 fi; 1956 od; 1957 1958 neighbors:=[]; 1959 gluings:=[]; 1960 cusps:=[]; 1961 facets:=SCFacets(complex); 1962 if facets=fail then 1963 return fail; 1964 fi; 1965 for j in [1..Size(facets)] do 1966 neighbors[j]:=[]; 1967 gluings[j]:=[]; 1968 cusps[j]:=[]; 1969 for trig in Combinations(facets[j],3) do 1970 curvertex:=Difference(facets[j],trig)[1]; 1971 k:=Position(facets[j],curvertex); 1972 for i in [1..Size(facets)] do 1973 if facets[i] = facets[j] then continue; fi; 1974 if IsSubset(facets[i],trig) then 1975 remoteidx:=Position(facets[i],Difference(facets[i],trig)[1]); 1976 neighbors[j][k]:=i-1; 1977 gluings[j][k]:=[]; 1978 gluings[j][k][k]:=remoteidx-1; 1979 gluings[j][k][Position(facets[j],trig[1])]:= 1980 Position(facets[i],trig[1])-1; 1981 gluings[j][k][Position(facets[j],trig[2])]:= 1982 Position(facets[i],trig[2])-1; 1983 gluings[j][k][Position(facets[j],trig[3])]:= 1984 Position(facets[i],trig[3])-1; 1985 cusps[j][k]:=curvertex-1; 1986 break; 1987 fi; 1988 od; 1989 od; 1990 od; 1991 1992 Append(buf,["\n",String(SCNumFaces(complex,dim)),"\n"]); 1993 for i in [1..Size(facets)] do 1994 Append(buf,[" ",String(neighbors[i][1])," ", 1995 String(neighbors[i][2])," ",String(neighbors[i][3])," ", 1996 String(neighbors[i][4]),"\n"]); 1997 Append(buf,[" ",String(gluings[i][1][1]),String(gluings[i][1][2]), 1998 String(gluings[i][1][3]),String(gluings[i][1][4])," ", 1999 String(gluings[i][2][1]),String(gluings[i][2][2]), 2000 String(gluings[i][2][3]),String(gluings[i][2][4])," ", 2001 String(gluings[i][3][1]),String(gluings[i][3][2]), 2002 String(gluings[i][3][3]),String(gluings[i][3][4])," ", 2003 String(gluings[i][4][1]),String(gluings[i][4][2]), 2004 String(gluings[i][4][3]),String(gluings[i][4][4]),"\n"]); 2005 Append(buf,[" ",String(cusps[i][1])," ",String(cusps[i][2])," ", 2006 String(cusps[i][3])," ",String(cusps[i][4]),"\n"]); 2007 Append(buf,[" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"]); 2008 Append(buf,[" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"]); 2009 Append(buf,[" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"]); 2010 Append(buf,[" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"]); 2011 Append(buf,[" 0 0\n\n"]); 2012 od; 2013 2014 if(FileString(filename,String(Concatenation(buf)))=fail) then 2015 Info(InfoSimpcomp,1,"SCExportSnapPy: file \"",filename,"\" not writeable!"); 2016 return fail; 2017 else 2018 return true; 2019 fi; 2020 2021end); 2022