#include "symmetriccomplex.h" #include #include "polyhedralcone.h" #include "printer.h" #include "lp.h" #include "linalg.h" #include "determinant.h" #include "log.h" #include // {ab+aa+cc+dd,ba+ca+db} SymmetricComplex::Cone::Cone(set const &indices_, int dimension_, int multiplicity_, bool sortWithSymmetry, SymmetricComplex const &complex): dimension(dimension_), multiplicity(multiplicity_), isKnownToBeNonMaximalFlag(false) { indices=vector(indices_.size()); int j=0; for(set::const_iterator i=indices_.begin();i!=indices_.end();i++,j++) indices[j]=*i; IntegerMatrix const &vertices=complex.getVertices(); IntegerVector sum(vertices.getWidth()); for(int i=0;isortKey[i]){isBetter=false;break;} if(sum[(*k)[i]]::const_iterator it=indexMap.find(v); assert(it!=indexMap.end()); return it->second; } void SymmetricComplex::Cone::remap(SymmetricComplex &complex) { IntegerMatrix const &vertices=complex.getVertices(); IntegerVector sum(vertices.getWidth()); for(int i=0;i indicesNew(indices.size()); int I=0; for(vector::const_iterator i=indices.begin();i!=indices.end();i++,I++) { IntegerVector ny=SymmetryGroup::compose(bestPermutation,complex.vertices[*i]); map::const_iterator it=complex.indexMap.find(ny); assert(it!=complex.indexMap.end()); indicesNew[I]=it->second; } indices=indicesNew; } set SymmetricComplex::Cone::indexSet()const { set ret; for(vector::const_iterator i=indices.begin();i!=indices.end();i++) ret.insert(*i); return ret; } bool SymmetricComplex::Cone::isSubsetOf(Cone const &c)const { int next=0; for(int i=0;i=c.indices.size())return false; if(indices[i]==c.indices[next])break; next++; } } return true; /* set b=c.indexSet(); for(vector::const_iterator i=indices.begin();i!=indices.end();i++) if(b.count(*i)==0)return false; return true; */ } SymmetricComplex::Cone SymmetricComplex::Cone::permuted(IntegerVector const &permutation, SymmetricComplex const &complex, bool withSymmetry)const { /* Cone ret; ret.dimension=dimension; ret.multiplicity=multiplicity;*/ set r; for(vector::const_iterator i=indices.begin();i!=indices.end();i++) { IntegerVector ny=SymmetryGroup::compose(permutation,complex.vertices[*i]); map::const_iterator it=complex.indexMap.find(ny); if(it==complex.indexMap.end()) { AsciiPrinter(Stderr).printVector(complex.vertices[*i]); AsciiPrinter(Stderr).printVector(ny); assert(0); } r.insert(it->second); } return Cone(r,dimension,multiplicity,withSymmetry,complex); } /* void SymmetricComplex::Cone::computeRelativeInteriorPoint(SymmetricComplex const &complex) { IntegerMatrix const &vertices=complex.getVertices(); IntegerVector sum(vertices.getWidth()); for(const_iterator i=begin();i!=end();i++) sum+=vertices[*i]; relativeInteriorPoint=sum; sum.sort(); summary=sum; } */ /*void SymmetricComplex::Cone::computeSmallestRepresentative(SymmetricComplex const &complex) { if(relativeInteriorPoint.size()==0)computeRelativeInteriorPoint(complex); LexicographicTermOrder myOrder; smallestRepresentative=relativeInteriorPoint; for(SymmetryGroup::ElementContainer::const_iterator k=complex.sym.elements.begin();k!=complex.sym.elements.end();k++) if(myOrder(SymmetryGroup::compose(*k,relativeInteriorPoint),smallestRepresentative)) smallestRepresentative=SymmetryGroup::compose(*k,relativeInteriorPoint); } */ bool SymmetricComplex::Cone::operator<(Cone const & b)const { /* if(ignoreSymmetry)return ((set)*this)<(b);*/ return sortKey possibleMatches; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { */ /* AsciiPrinter(Stderr).printVector(i->summary); AsciiPrinter(Stderr).printVector(temp.summary); fprintf(stderr,"\n");*/ /* if(i->dimension==temp.dimension) if(i->summary==temp.summary) { possibleMatches.insert(i->relativeInteriorPoint); } } for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) { if(possibleMatches.find(SymmetryGroup::compose(*k,temp.relativeInteriorPoint))!=possibleMatches.end()) return true; } */ /* for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) { Cone c2=c.permuted(*k,*this); for(list::const_iterator i=cones.begin();i!=cones.end();i++) { if(c2==*i)return true; } }*/ // return false; } void SymmetricComplex::insert(Cone const &c) { if(c.dimension>dimension)dimension=c.dimension; // Cone temp=c; /* temp.computeRelativeInteriorPoint(*this); temp.computeSmallestRepresentative(*this); */ if(!contains(c))//#2 { cones.insert(c); //cones.push_back(temp); // fprintf(Stderr,"INSERTING\n"); // cones.back().computeRelativeInteriorPoint(*this); } else { // if(c.isKnownToBeNonMaximal())cones.find(c)->setKnownToBeNonMaximal(); if(c.isKnownToBeNonMaximal()){cones.erase(c);cones.insert(c);}// mark as non-maximal } } int SymmetricComplex::getMaxDim()const {/* int ret=-1; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { if(i->dimension>ret)ret=i->dimension; } return ret;*/ return dimension; } int SymmetricComplex::getMinDim()const { int ret=100000; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { if(i->dimensiondimension; } return ret; } bool SymmetricComplex::isMaximal(Cone const &c)const { if(c.isKnownToBeNonMaximal())return false; if(c.dimension==dimension)return true; for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) { Cone c2=c.permuted(*k,*this,false); for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { if(i->dimension>c.dimension) if(c2.isSubsetOf(*i) && !i->isSubsetOf(c2))return false; } } return true; } IntegerVector SymmetricComplex::dimensionsAtInfinity()const { /* Using a double description like method this routine computes the dimension of the intersection of each cone in the complex with the plane x_0=0 */ IntegerVector ret(cones.size()); int I=0; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++,I++) { IntegerVectorList raysAtInfinity; for(vector::const_iterator j=i->indices.begin();j!=i->indices.end();j++) { if(vertices[*j][0]==0)raysAtInfinity.push_back(vertices[*j]); for(vector::const_iterator k=j;k!=i->indices.end();k++) if(vertices[*j][0]*vertices[*k][0]<0) raysAtInfinity.push_back(((vertices[*j][0]>0)?1:-1)*(vertices[*j][0])*vertices[*k].toVector()+ ((vertices[*k][0]>0)?1:-1)*(vertices[*k][0])*vertices[*j].toVector()); } ret[I]=rankOfMatrix(raysAtInfinity); } return ret; } string SymmetricComplex::toString(int dimLow, int dimHigh, bool onlyMaximal, bool group, ostream *multiplicities, bool compressed, bool tPlaneSort, bool xml)const { stringstream ret; if(!onlyMaximal) { if(xml)ret<<"\n"; if(xml)if(multiplicities)*multiplicities<<"\n"; } IntegerVector additionalSortKeys(cones.size()); if(tPlaneSort)additionalSortKeys=dimensionsAtInfinity(); int lowKey=additionalSortKeys.min(); int highKey=additionalSortKeys.max(); if(xml)if(onlyMaximal) { if(compressed) ret<<"\n"; else ret<<"vertices.getHeight()<<"\">\n"; if(multiplicities)*multiplicities<<"\n"; } for(int d=dimLow;d<=dimHigh;d++) { log1 cerr << "Processing dimension "<\n"; else ret<<"vertices.getHeight()<<"\">\n"; if(multiplicities)*multiplicities<<"\n"; } } int I=0; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++,I++) if(additionalSortKeys[I]==key) if(i->dimension==d) { numberOfOrbitsOfThisDimension++; if(!onlyMaximal || isMaximal(*i)) { numberOfOrbitsOutput++; bool isMax=isMaximal(*i); bool newOrbit=true; set > temp; for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) { Cone temp1=i->permuted(*k,*this,false); temp.insert(temp1.indexSet()); if(compressed)break; } for(set >::const_iterator j=temp.begin();j!=temp.end();j++) { if(!xml)ret << "{";else ret<<""; for(set::const_iterator a=j->begin();a!=j->end();a++) { if(a!=j->begin())ret<<" "; ret << *a; } if(!xml)ret << "}";else ret<<""; if(!xml) { if(group)if(newOrbit)ret << "\t# New orbit"; if(newDimension)ret << "\t# Dimension "<"; *multiplicities << i->multiplicity; if(xml)*multiplicities<<""; if(!xml) { if(group)if(newOrbit)*multiplicities << "\t# New orbit"; if(newDimension)*multiplicities << "\t# Dimension "<\n"; if(multiplicities)*multiplicities<<"\n"; } } } log1 cerr<<"Number of orbits of this dimension: " << numberOfOrbitsOfThisDimension << endl; log1 cerr<<"Number of orbits output: " << numberOfOrbitsOutput << endl; } if(xml)if(onlyMaximal) { ret<<"\n"; if(multiplicities)*multiplicities<<"\n"; } if(!onlyMaximal) { if(xml)ret<<"\n"; if(xml)if(multiplicities)*multiplicities<<"\n"; } return ret.str(); } IntegerVector SymmetricComplex::fvector(bool boundedPart)const { int min=getMinDim(); IntegerVector ret(getMaxDim()-min+1); for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { /* set temp; for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) temp.insert(i->permuted(*k,*this));*/ /* set temp; for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++) temp.insert(SymmetryGroup::compose(*k,i->sortKey)); */ bool doAdd=!boundedPart; if(boundedPart) { bool isBounded=true; for(vector::const_iterator j=i->indices.begin();j!=i->indices.end();j++) if(vertices[*j][0]==0)isBounded=false; doAdd=isBounded; } if(doAdd) ret[i->dimension-min]+=sym.orbitSize(i->sortKey); } return ret; } bool SymmetricComplex::isPure()const { int dim=-1; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) { gfan_log2{static int a;if(!((a++)&63))fprintf(Stderr,"%i\n",a);}//log0 if(isMaximal(*i)) { int dim2=i->dimension; if(dim==-1)dim=dim2; if(dim!=dim2)return false; } } return true; } bool SymmetricComplex::isSimplicial()const { int linealityDim=getMinDim(); for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) if(!i->isSimplicial(linealityDim)) return false; return true; } void SymmetricComplex::remap() { for(ConeContainer::iterator i=cones.begin();i!=cones.end();i++) { Cone const&j=*i; Cone &j2=const_cast(j);//DANGER: cast away const. This does not change the sort key in the container, so should be OK. j2.remap(*this); } } int SymmetricComplex::numberOfConesOfDimension(int d)const { assert(sym.isTrivial()); int ret=0; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) if(d==i->dimension) { ret++; } return ret; } int SymmetricComplex::dimensionIndex(Cone const &c) { assert(sym.isTrivial()); int ret=0; for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) if(c.dimension==i->dimension) { if(!(c<*i)&&!(*i &indices_, vector &signs) { indices_=vector(); signs=vector(); int d=c.dimension; IntegerVectorList l; for(int i=0;i indices; for(vector::const_iterator j=c.indices.begin();j!=c.indices.end();j++)if(dotLong(vertices[*j],*i)==0)indices.insert(*j); Cone facet(indices,d-1,1,true,*this); IntegerVectorList complementBasis2=facet.orthogonalComplement(*this); for(IntegerVectorList::const_iterator j=completion.begin();j!=completion.end();j++)complementBasis2.push_back(*j); indices_.push_back(dimensionIndex(facet)); signs.push_back(sign*determinantSign(complementBasis2)); } } IntegerMatrix SymmetricComplex::boundaryMap(int d) { assert(sym.isTrivial()); IntegerMatrix ret(numberOfConesOfDimension(d-1),numberOfConesOfDimension(d)); for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++) if(d==i->dimension) { int I=dimensionIndex(*i); vector indices; vector signs; boundary(*i,indices,signs); for(int j=0;j