#include "gfanlib_traversal.h" #include "gfanlib_symmetry.h" #include #include #include //#include "log.h" using namespace std; using namespace gfan; static list rowsToList(ZMatrix const &m) { list ret; for(int i=0;i EFirst; struct ESecond{// L2 maybe zero, in that case i1==i2 list* L1; list::iterator i1; list *L2; list::iterator i2; ESecond():L1(0),L2(0){}; ESecond(list* L1_,list::iterator i1_,list* L2_,list::iterator i2_): L1(L1_), i1(i1_), L2(L2_), i2(i2_) { } }; SymmetryGroup const &sym; map theSet; int theSetSize; public: Boundary(SymmetryGroup const &sym_): sym(sym_), theSetSize(0) { } int size()const { return theSetSize; } pair normalForm(ZVector const &ridge, ZVector const &ray)const { pair ret; Permutation perm(ridge.size()); ret.first=sym.orbitRepresentative(ridge,&perm); ret.second=sym.orbitRepresentativeFixing(perm.apply(ray),ret.first); return ret; } bool containsFlip(ZVector const &ridge, ZVector const &ray, list *storedInList_, list::iterator listIterator_, list *storedInList2_, list::iterator listIterator2_) { assert(ridge.size()==ray.size()); EFirst p=normalForm(ridge,ray); if(theSet.count(p)==1) { theSet[p].L1->erase(theSet[p].i1); if(theSet[p].L2)theSet[p].L2->erase(theSet[p].i2); theSet.erase(p); theSetSize--; return true; } theSet[p]=ESecond(storedInList_,listIterator_,storedInList2_,listIterator2_); theSetSize++; return false; } /** * This routine remove rays from rays, such that only one ridge-ray pair is left for each orbit. * The routine allows an additional list of vectors with the same number of elements as rays to be passed. * The routine will remove those vectors from this set which correspond to rays removed from rays. * * To do this it must know the symmetry group. */ void removeDuplicates(ZVector const &ridge, list &rays, list *normals=0)const { list ret; list normalsRet; set representatives; list::const_iterator I; if(normals)I=normals->begin(); for(list::const_iterator i=rays.begin();i!=rays.end();i++) { ZVector rep=sym.orbitRepresentativeFixing(*i,ridge); if(representatives.count(rep)==0) { representatives.insert(rep); ret.push_back(*i); if(normals)normalsRet.push_back(*I); } if(normals)I++; } rays=ret; if(normals)*normals=normalsRet; } void print()const { cerr<< "Boundary" <::const_iterator i=theSet.begin();i!=theSet.end();i++) { cerr << i->first.first << i->first.second; cerr << endl; } cerr< rays; ZVector parentRay; }; struct pathStepFacet { list ridges; list ridgesRayUniqueVector;//stores the ray of the link that we came from }; /** We need to simulate two mutually recursive functions. An actual implementation of these two functions would probably not work since the recursion depth could easily be 10000. Here follows a sketch of the simulation lav kegle find ridges skriv ned i objekt put paa stakken L1: if ridges in top element compute tropical curve construct stak object with rays; set parrentRidge,ridgeRays push ridge else pop facet if empty break; goto L2 L2: if(ridgeRays not empty) change CONE <---entry point push facet else pop ridge change CONE goto L1 The strategy for marking is as follows Before a vertex is pushed the edges that needs to be taken are written in its data. A edge is only written if its orbit has not been marked. Each time an edge is written it is simultaneously marked. */ static void printStack(list const &facetStack, list const &ridgeStack) { list::const_iterator i=facetStack.begin(); list::const_iterator j=ridgeStack.begin(); cerr<<"STACK:"<ridgeStack.size())goto entry; do { cerr<<"RIDGE:"<parentRidge<rays<parentRay; cerr<ridges; cerr<> a; } void traverse(FanTraverser &traverser, Target &target, SymmetryGroup const *symmetryGroup) { //TO DO: at the moment a conetraverser can only report that it has no state if it is traversing a complete fan. //This is because symmetricTraverse needs go BACK to compute the links of previously seen facets. //Alternative the links should be computed and stored the first time a facet is seen. //Or the conetraverse should be given more info about the ridge to make computations quicker. int lastNumberOfEdges=0; float averageEdge=0; int n=traverser.refToPolyhedralCone().ambientDimension();//symmetryGroup->sizeOfBaseSet(); SymmetryGroup localSymmetryGroup(n); if(!symmetryGroup)symmetryGroup=&localSymmetryGroup; ZMatrix linealitySpaceGenerators=traverser.refToPolyhedralCone().generatorsOfLinealitySpace(); int d=traverser.refToPolyhedralCone().dimension(); Boundary boundary(*symmetryGroup); list facetStack; list ridgeStack; int numberOfCompletedFacets=0; int numberOfCompletedRidges=0; int stackSize=0; ZVector facetUniqueVector; goto entry; while(1) { L1: // printStack(facetStack,ridgeStack); //if we have more ProcessRidge calls to do if(!facetStack.front().ridges.empty()) { //ProcessRidge "called" pathStepRidge top; if(traverser.hasNoState()) top.parentRay=facetStack.front().ridgesRayUniqueVector.front(); else { ZCone link=traverser.refToPolyhedralCone().link(facetStack.front().ridges.front()); link.canonicalize(); top.parentRay=link.getUniquePoint(); } top.parentRidge=facetStack.front().ridges.front(); // AsciiPrinter(Stderr)< rays; if(traverser.hasNoState()) { rays.push_back(top.parentRay); rays.push_back(-top.parentRay); } else rays=traverser.link(facetStack.front().ridges.front()); assert(!rays.empty()); boundary.removeDuplicates(top.parentRidge,rays); ridgeStack.push_front(top);stackSize++; ZVector ridgeRidgeRidge=facetStack.front().ridges.front(); for(list::const_iterator i=rays.begin();i!=rays.end();i++) { ridgeStack.front().rays.push_front(*i); if(boundary.containsFlip(ridgeRidgeRidge,*i,&ridgeStack.front().rays,ridgeStack.front().rays.begin(),0,ridgeStack.front().rays.begin())) ridgeStack.front().rays.pop_front(); } // "state saved" ready to do calls to ProcessFacet numberOfCompletedRidges++; } else { // No more calls to do - we now return from ProcessFacet //THIS IS THE PLACE TO CHANGE CONE BACK facetStack.pop_front();stackSize--; if(facetStack.empty())break; // log1 cerr<<"BACK"< facetNormals=rowsToList(traverser.refToPolyhedralCone().getFacets()); pathStepFacet stepFacet; list ridges; for(list::iterator i=facetNormals.begin();i!=facetNormals.end();i++) { ZVector v(n); // for(IntegerVectorList::const_iterator j=extremeRays.begin();j!=extremeRays.end();j++) for(int j=0;j::const_iterator I=facetNormals.begin(); for(list::const_iterator i=ridges.begin();i!=ridges.end();i++,I++) { ZVector rayUniqueVector; if(d==n) { rayUniqueVector =I->normalized(); // if(dotLong(rayUniqueVector,*I) } else { ZCone rayCone=traverser.refToPolyhedralCone().link(*i); rayCone.canonicalize(); rayUniqueVector=rayCone.getUniquePoint(); // debug<