1 /*
2  * gfanlib_symmetriccomplex.cpp
3  *
4  *  Created on: Nov 16, 2010
5  *      Author: anders
6  */
7 
8 #include "gfanlib_symmetriccomplex.h"
9 #include "gfanlib_polymakefile.h"
10 
11 #include <sstream>
12 #include <iostream>
13 
14 namespace gfan{
15 
Cone(std::set<int> const & indices_,int dimension_,Integer multiplicity_,bool sortWithSymmetry,SymmetricComplex const & complex)16 SymmetricComplex::Cone::Cone(std::set<int> const &indices_, int dimension_, Integer multiplicity_, bool sortWithSymmetry, SymmetricComplex const &complex):
17   isKnownToBeNonMaximalFlag(false),
18   dimension(dimension_),
19   multiplicity(multiplicity_),
20   sortKeyPermutation(complex.n)
21 {
22   indices=IntVector(indices_.size());
23   int j=0;
24   for(std::set<int>::const_iterator i=indices_.begin();i!=indices_.end();i++,j++)
25     indices[j]=*i;
26 
27   ZMatrix const &vertices=complex.getVertices();
28   ZVector sum(vertices.getWidth());
29   for(unsigned i=0;i<indices.size();i++)
30     sum+=vertices[indices[i]];
31 
32   if(sortWithSymmetry)
33     {
34       sortKey=complex.sym.orbitRepresentative(sum,&sortKeyPermutation);
35     }
36   else
37     {
38       sortKey=sum;
39     }
40 }
41 
42 
indexOfVertex(ZVector const & v) const43 int SymmetricComplex::indexOfVertex(ZVector const &v)const
44 {
45 //  std::cerr<<v<<std::endl<<"In";
46 //  for(std::map<ZVector,int>::const_iterator i =indexMap.begin();i!=indexMap.end();i++)std::cerr<<i->first;
47 
48   std::map<ZVector,int>::const_iterator it=indexMap.find(v);
49   assert(it!=indexMap.end());
50   return it->second;
51 }
52 
53 
remap(SymmetricComplex & complex)54 void SymmetricComplex::Cone::remap(SymmetricComplex &complex)
55 {
56   ZMatrix const &vertices=complex.getVertices();
57   ZVector sum(vertices.getWidth());
58   for(unsigned i=0;i<indices.size();i++)
59     sum+=vertices[indices[i]];
60 
61   unsigned n=sum.size();
62   Permutation const &bestPermutation=sortKeyPermutation;
63 
64   assert(bestPermutation.size()==n);
65 
66   IntVector indicesNew(indices.size());
67   int I=0;
68   for(unsigned i=0;i<indices.size();i++,I++)
69     {
70       ZVector ny=bestPermutation.apply(complex.vertices[indices[i]]);
71       std::map<ZVector,int>::const_iterator it=complex.indexMap.find(ny);
72       assert(it!=complex.indexMap.end());
73       indicesNew[I]=it->second;
74     }
75   indices=indicesNew;
76 }
77 
78 
indexSet() const79 std::set<int> SymmetricComplex::Cone::indexSet()const
80 {
81   std::set<int> ret;
82   for(unsigned i=0;i<indices.size();i++)
83     ret.insert(indices[i]);
84 
85   return ret;
86 }
87 
isSubsetOf(Cone const & c) const88 bool SymmetricComplex::Cone::isSubsetOf(Cone const &c)const
89 {
90   unsigned next=0;
91   for(unsigned i=0;i<indices.size();i++)
92     {
93       while(1)
94         {
95           if(next>=c.indices.size())return false;
96           if(indices[i]==c.indices[next])break;
97           next++;
98         }
99     }
100   return true;
101 }
102 
103 
permuted(Permutation const & permutation,SymmetricComplex const & complex,bool withSymmetry) const104 SymmetricComplex::Cone SymmetricComplex::Cone::permuted(Permutation const &permutation, SymmetricComplex const &complex, bool withSymmetry)const
105 {
106   std::set<int> r;
107   for(unsigned i=0;i<indices.size();i++)
108     {
109       ZVector ny=permutation.apply(complex.vertices[indices[i]]);
110       std::map<ZVector,int>::const_iterator it=complex.indexMap.find(ny);
111       if(it==complex.indexMap.end())
112         {
113 //          AsciiPrinter(Stderr).printVector(complex.vertices[indices[i]]);
114 //          AsciiPrinter(Stderr).printVector(ny);
115 
116           assert(0);
117         }
118       r.insert(it->second);
119     }
120 
121 
122   return Cone(r,dimension,multiplicity,withSymmetry,complex);
123 }
124 
125 
operator <(Cone const & b) const126 bool SymmetricComplex::Cone::operator<(Cone const & b)const
127 {
128   return sortKey<b.sortKey;
129 }
130 
131 
isSimplicial(int linealityDim) const132 bool SymmetricComplex::Cone::isSimplicial(int linealityDim)const
133 {
134   return (indices.size()+linealityDim)==dimension;
135 }
136 
137 
orthogonalComplement(SymmetricComplex & complex) const138 ZMatrix SymmetricComplex::Cone::orthogonalComplement(SymmetricComplex &complex)const
139 {
140   ZMatrix l;
141   for(unsigned i=0;i<indices.size();i++)
142     l.appendRow(complex.vertices[indices[i]]);
143 
144   return l.reduceAndComputeKernel();
145 //  FieldMatrix m=integerMatrixToFieldMatrix(rowsToIntegerMatrix(l,complex.n),Q);
146 //  return fieldMatrixToIntegerMatrixPrimitive(m.reduceAndComputeKernel()).getRows();
147 }
148 
149 
SymmetricComplex(ZMatrix const & rays,ZMatrix const & linealitySpace_,SymmetryGroup const & sym_)150 SymmetricComplex::SymmetricComplex(ZMatrix const &rays, ZMatrix const &linealitySpace_, SymmetryGroup const &sym_):
151   n(rays.getWidth()),
152   linealitySpace(canonicalizeSubspace(linealitySpace_)),
153   sym(sym_),
154   dimension(-1)
155 {
156   assert(rays.getWidth()==linealitySpace.getWidth());
157 //  vertices=rowsToIntegerMatrix(v,n);
158   vertices=rays;
159 
160   for(int i=0;i<vertices.getHeight();i++)indexMap[vertices[i]]=i;
161 }
162 
163 
contains(Cone const & c) const164 bool SymmetricComplex::contains(Cone const &c)const
165 {
166   Cone temp=c;
167   return cones.find(temp)!=cones.end();///////////////////!!!!!!!!!!!!!!!!!!!!!!!
168 }
169 
170 
insert(Cone const & c)171 void SymmetricComplex::insert(Cone const &c)
172 {
173         if(c.dimension>dimension)dimension=c.dimension;
174   if(!contains(c))//#2
175     {
176       cones.insert(c);
177     }
178   else
179     {
180       if(c.isKnownToBeNonMaximal()){cones.erase(c);cones.insert(c);}// mark as non-maximal
181     }
182 }
183 
184 
getLinDim() const185 int SymmetricComplex::getLinDim()const
186 {
187 	return linealitySpace.getHeight();
188 }
189 
getMaxDim() const190 int SymmetricComplex::getMaxDim()const
191 {
192   return dimension;
193 }
194 
195 
getMinDim() const196 int SymmetricComplex::getMinDim()const
197 {
198   int ret=100000;
199   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
200     {
201       if(i->dimension<ret)ret=i->dimension;
202     }
203   return ret;
204 }
205 
206 
isMaximal(Cone const & c) const207 bool SymmetricComplex::isMaximal(Cone const &c)const
208 {
209   if(c.isKnownToBeNonMaximal())return false;
210   if(c.dimension==dimension)return true;
211   for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++)
212     {
213       Cone c2=c.permuted(*k,*this,false);
214       for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
215         {
216           if(i->dimension>c.dimension)
217             if(c2.isSubsetOf(*i) && !i->isSubsetOf(c2))return false;
218         }
219     }
220   return true;
221 }
222 
223 #if 0
224 IntVector SymmetricComplex::dimensionsAtInfinity()const
225 {
226   /* Using a double description like method this routine computes the
227      dimension of the intersection of each cone in the complex with
228      the plane x_0=0 */
229   IntVector ret(cones.size());
230 
231   int I=0;
232   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++,I++)
233     {
234       ZMatrix raysAtInfinity;
235       for(int j=0;j<i->indices.size();j++)
236         {
237           if(vertices[i->indices[j]][0]==0)raysAtInfinity.push_back(vertices[i->indices[j]]);
238           for(vector<int>::const_iterator k=j;k!=i->indices.end();k++)
239             if(vertices[*j][0]*vertices[*k][0]<0)
240               raysAtInfinity.push_back(((vertices[*j][0]>0)?1:-1)*(vertices[*j][0])*vertices[*k]+
241                                        ((vertices[*k][0]>0)?1:-1)*(vertices[*k][0])*vertices[*j]);
242         }
243       ret[I]=rankOfMatrix(raysAtInfinity);
244     }
245   return ret;
246 }
247 #endif
248 
buildConeLists(bool onlyMaximal,bool compressed,std::vector<std::vector<IntVector>> * conelist,std::vector<std::vector<Integer>> * multiplicities) const249 void SymmetricComplex::buildConeLists(bool onlyMaximal, bool compressed, std::vector<std::vector<IntVector > >*conelist, std::vector<std::vector<Integer > > *multiplicities)const
250 {
251   int dimLow=this->linealitySpace.getHeight();
252   int dimHigh=this->getMaxDim();
253   if(dimHigh<dimLow)dimHigh=dimLow-1;
254   if(conelist)*conelist=std::vector<std::vector<IntVector> >(dimHigh-dimLow+1);
255   if(multiplicities)*multiplicities=std::vector<std::vector<Integer> >(dimHigh-dimLow+1);
256   for(int d=dimLow;d<=dimHigh;d++)
257     {
258       int numberOfOrbitsOutput=0;
259       int numberOfOrbitsOfThisDimension=0;
260       // bool newDimension=true;
261         {
262           int I=0;
263           for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++,I++)
264                   if(i->dimension==d)
265                     {
266                   numberOfOrbitsOfThisDimension++;
267               if(!onlyMaximal || isMaximal(*i))
268                 {
269                   numberOfOrbitsOutput++;
270                   // bool isMax=isMaximal(*i);
271                   // bool newOrbit=true;
272                   std::set<std::pair<std::set<int>,Integer> > temp;
273                     for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++)
274                       {
275                         Cone temp1=i->permuted(*k,*this,false);
276                         temp.insert(std::pair<std::set<int>,Integer>(temp1.indexSet(),temp1.multiplicity));
277                         if(compressed)break;
278                     }
279                   for(std::set<std::pair<std::set<int>,Integer> >::const_iterator j=temp.begin();j!=temp.end();j++)
280                     {
281                       IntVector temp;
282                       for(std::set<int>::const_iterator k=j->first.begin();k!=j->first.end();k++)temp.push_back(*k);
283                       if(conelist)(*conelist)[d-dimLow].push_back(temp);
284                       if(multiplicities)(*multiplicities)[d-dimLow].push_back(j->second);
285  /*                     if(isMax)if(multiplicities)
286                         {
287 
288                           *multiplicities << i->multiplicity;
289                           if(group)if(newOrbit)*multiplicities << "\t# New orbit";
290                           if(newDimension)*multiplicities << "\t# Dimension "<<d;
291                           *multiplicities << std::endl;
292                         }*/
293                       // newOrbit=false;
294                       // newDimension=false;
295                     }
296               }
297                     }
298         }
299     }
300 
301 }
302 
toStringJustCones(int dimLow,int dimHigh,bool onlyMaximal,bool group,std::ostream * multiplicities,bool compressed,bool tPlaneSort) const303 std::string SymmetricComplex::toStringJustCones(int dimLow, int dimHigh, bool onlyMaximal, bool group, std::ostream *multiplicities, bool compressed, bool tPlaneSort)const
304 {
305   std::stringstream ret;
306 
307   ZVector additionalSortKeys(cones.size());
308 //  if(tPlaneSort)additionalSortKeys=dimensionsAtInfinity();
309 //  Integer lowKey=additionalSortKeys.min();
310 //  Integer highKey=additionalSortKeys.max();
311 
312   for(int d=dimLow;d<=dimHigh;d++)
313     {
314       int numberOfOrbitsOutput=0;
315       int numberOfOrbitsOfThisDimension=0;
316       bool newDimension=true;
317  //     for(int key=lowKey;key<=highKey;key++)
318         {
319           int I=0;
320           for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++,I++)
321  //           if(additionalSortKeys[I]==key)
322                   if(i->dimension==d)
323                     {
324                       numberOfOrbitsOfThisDimension++;
325               if(!onlyMaximal || isMaximal(*i))
326                 {
327                   numberOfOrbitsOutput++;
328                   bool isMax=isMaximal(*i);
329                   bool newOrbit=true;
330                   std::set<std::set<int> > temp;
331                     for(SymmetryGroup::ElementContainer::const_iterator k=sym.elements.begin();k!=sym.elements.end();k++)
332                       {
333                         Cone temp1=i->permuted(*k,*this,false);
334                         temp.insert(temp1.indexSet());
335                         if(compressed)break;
336                     }
337                   for(std::set<std::set<int> >::const_iterator j=temp.begin();j!=temp.end();j++)
338                     {
339                       ret << "{";
340                       for(std::set<int>::const_iterator a=j->begin();a!=j->end();a++)
341                         {
342                           if(a!=j->begin())ret<<" ";
343                           ret << *a;
344                         }
345                       ret << "}";
346                       if(group)if(newOrbit)ret << "\t# New orbit";
347                       if(newDimension)ret << "\t# Dimension "<<d;
348                       ret <<std::endl;
349                       if(isMax)if(multiplicities)
350                         {
351                           *multiplicities << i->multiplicity;
352                           if(group)if(newOrbit)*multiplicities << "\t# New orbit";
353                           if(newDimension)*multiplicities << "\t# Dimension "<<d;
354                           *multiplicities << std::endl;
355                         }
356                       newOrbit=false;
357                       newDimension=false;
358                     }
359               }
360                     }
361         }
362     }
363 
364   return ret.str();
365 }
366 
367 
fvector(bool boundedPart) const368 ZVector SymmetricComplex::fvector(bool boundedPart)const
369 {
370   int min=getMinDim();
371   int dimHigh=getMaxDim();
372   if(dimHigh<min)dimHigh=min-1;
373   ZVector ret(dimHigh-min+1);
374 
375   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
376     {
377       bool doAdd=!boundedPart;
378       if(boundedPart)
379         {
380           bool isBounded=true;
381           for(unsigned j=0;j<i->indices.size();j++)
382             if(vertices[i->indices[j]][0].sign()==0)isBounded=false;
383           doAdd=isBounded;
384         }
385       if(doAdd)
386         ret[i->dimension-min]+=Integer(sym.orbitSize(i->sortKey));
387     }
388   return ret;
389 }
390 
391 
isPure() const392 bool SymmetricComplex::isPure()const
393 {
394   int dim=-1;
395   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
396     {
397       if(isMaximal(*i))
398         {
399           int dim2=i->dimension;
400           if(dim==-1)dim=dim2;
401           if(dim!=dim2)return false;
402         }
403     }
404   return true;
405 }
406 
407 
isSimplicial() const408 bool SymmetricComplex::isSimplicial()const
409 {
410   int linealityDim=getMinDim();
411   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
412     if(!i->isSimplicial(linealityDim))
413       return false;
414   return true;
415 }
416 
417 
remap()418 void SymmetricComplex::remap()
419 {
420   for(ConeContainer::iterator i=cones.begin();i!=cones.end();i++)
421     {
422       Cone const&j=*i;
423       Cone &j2=const_cast<Cone&>(j);//DANGER: cast away const. This does not change the sort key in the container, so should be OK.
424       j2.remap(*this);
425     }
426 }
427 
428 
numberOfConesOfDimension(int d) const429 int SymmetricComplex::numberOfConesOfDimension(int d)const
430 {
431   assert(sym.isTrivial());
432 
433   int ret=0;
434   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
435     if(d==i->dimension)
436       {
437         ret++;
438       }
439   return ret;
440 }
441 
442 
dimensionIndex(Cone const & c)443 int SymmetricComplex::dimensionIndex(Cone const &c)
444 {
445   assert(sym.isTrivial());
446 
447   int ret=0;
448   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
449     if(c.dimension==i->dimension)
450       {
451         if(!(c<*i)&&!(*i<c))
452           return ret;
453         else
454           ret++;
455       }
456   return ret;
457 }
458 
459 #if 0
460 void SymmetricComplex::boundary(Cone const &c, vector<int> &indices_, vector<int> &signs)
461 {
462   indices_=vector<int>();
463   signs=vector<int>();
464   int d=c.dimension;
465 
466 
467   IntegerVectorList l;
468   for(int i=0;i<c.indices.size();i++)
469     l.push_back(vertices[c.indices[i]]);
470   IntegerVectorList facetNormals=PolyhedralCone(l,IntegerVectorList(),n).extremeRays();
471   IntegerVectorList complementBasis=c.orthogonalComplement(*this);
472   for(IntegerVectorList::const_iterator i=facetNormals.begin();i!=facetNormals.end();i++)
473     {
474       IntegerVectorList complementBasis1=complementBasis;
475       complementBasis1.push_back(*i);
476       FieldMatrix m=integerMatrixToFieldMatrix(rowsToIntegerMatrix(complementBasis1,n),Q);
477       IntegerVectorList completion=fieldMatrixToIntegerMatrixPrimitive(m.reduceAndComputeKernel()).getRows();
478       for(IntegerVectorList::const_iterator j=completion.begin();j!=completion.end();j++)complementBasis1.push_back(*j);
479       int sign=determinantSign(complementBasis1);
480 
481       set<int> indices;
482       for(vector<int>::const_iterator j=c.indices.begin();j!=c.indices.end();j++)if(dotLong(vertices[*j],*i)==0)indices.insert(*j);
483       Cone facet(indices,d-1,1,true,*this);
484       IntegerVectorList complementBasis2=facet.orthogonalComplement(*this);
485       for(IntegerVectorList::const_iterator j=completion.begin();j!=completion.end();j++)complementBasis2.push_back(*j);
486       indices_.push_back(dimensionIndex(facet));
487       signs.push_back(sign*determinantSign(complementBasis2));
488     }
489 }
490 
491 
492 IntegerMatrix SymmetricComplex::boundaryMap(int d)
493 {
494   assert(sym.isTrivial());
495 
496   IntegerMatrix ret(numberOfConesOfDimension(d-1),numberOfConesOfDimension(d));
497 
498   for(ConeContainer::const_iterator i=cones.begin();i!=cones.end();i++)
499     if(d==i->dimension)
500       {
501         int I=dimensionIndex(*i);
502         vector<int> indices;
503         vector<int> signs;
504         boundary(*i,indices,signs);
505         for(int j=0;j<indices.size();j++)
506           {
507               ret[indices[j]][I]+=signs[j];
508           }
509       }
510   return ret;
511 }
512 #endif
513 
514 
toString(int flags) const515   std::string SymmetricComplex::toString(int flags)const
516   {
517     PolymakeFile polymakeFile;
518     polymakeFile.create("NONAME","PolyhedralFan","PolyhedralFan",flags&FPF_xml);
519 
520 
521 
522 
523 
524     polymakeFile.writeCardinalProperty("AMBIENT_DIM",n);
525     polymakeFile.writeCardinalProperty("DIM",getMaxDim());
526     polymakeFile.writeCardinalProperty("LINEALITY_DIM",linealitySpace.getHeight());
527     //    polymakeFile.writeMatrixProperty("RAYS",rays,true,comments);
528         polymakeFile.writeMatrixProperty("RAYS",vertices,true);
529     polymakeFile.writeCardinalProperty("N_RAYS",vertices.getHeight());
530 
531 
532     polymakeFile.writeMatrixProperty("LINEALITY_SPACE",linealitySpace,n);
533     polymakeFile.writeMatrixProperty("ORTH_LINEALITY_SPACE",kernel(linealitySpace),n);
534 
535 /*
536     if(flags & FPF_primitiveRays)
537     {
538       ZMatrix primitiveRays;
539       for(int i=0;i<rays.getHeight();i++)
540         for(PolyhedralConeList::const_iterator j=cones.begin();j!=cones.end();j++)
541           if(j->contains(*i)&&(j->dimensionOfLinealitySpace()+1==j->dimension()))
542             primitiveRays.push_back(j->semiGroupGeneratorOfRay());
543 
544       polymakeFile.writeMatrixProperty("PRIMITIVE_RAYS",rowsToIntegerMatrix(primitiveRays,n));
545     }
546 */
547 #if 0
548     ZMatrix generatorsOfLinealitySpace=cones.begin()->generatorsOfLinealitySpace();
549 
550     log1 fprintf(Stderr,"Building symmetric complex.\n");
551     for(PolyhedralConeList::const_iterator i=cones.begin();i!=cones.end();i++)
552       {
553         {
554           static int t;
555   //        log1 fprintf(Stderr,"Adding faces of cone %i\n",t++);
556         }
557   //      gfan_log2 fprintf(Stderr,"Dim: %i\n",i->dimension());
558 
559         addFacesToSymmetricComplex(symCom,*i,i->getHalfSpaces(),generatorsOfLinealitySpace);
560       }
561 
562   //  log1 cerr<<"Remapping";
563     symCom.remap();
564   //  log1 cerr<<"Done remapping";
565 
566 
567     PolyhedralFan f=*this;
568 #endif
569 
570   //  log1 fprintf(Stderr,"Computing f-vector.\n");
571     ZVector fvector=this->fvector();
572     polymakeFile.writeCardinalVectorProperty("F_VECTOR",fvector);
573   //  log1 fprintf(Stderr,"Done computing f-vector.\n");
574 
575     if(flags&FPF_boundedInfo)
576       {
577   //      log1 fprintf(Stderr,"Computing bounded f-vector.\n");
578         ZVector fvectorBounded=this->fvector(true);
579         polymakeFile.writeCardinalVectorProperty("F_VECTOR_BOUNDED",fvectorBounded);
580   //      log1 fprintf(Stderr,"Done computing bounded f-vector.\n");
581       }
582 #if 0
583     {
584       Integer euler;
585       int mul=-1;
586       for(int i=0;i<fvector.size();i++,mul*=-1)euler+=Integer(mul)*fvector[i];
587       polymakeFile.writeCardinalProperty("MY_EULER",euler);
588     }
589 #endif
590   //  log1 fprintf(Stderr,"Checking if complex is simplicial and pure.\n");
591     polymakeFile.writeCardinalProperty("SIMPLICIAL",isSimplicial());
592     polymakeFile.writeCardinalProperty("PURE",isPure());
593   //  log1 fprintf(Stderr,"Done checking.\n");
594 
595 
596     if(flags&FPF_cones)polymakeFile.writeStringProperty("CONES",toStringJustCones(getMinDim(),getMaxDim(),false,flags&FPF_group, 0,false,flags&FPF_tPlaneSort));
597     if(flags&FPF_maximalCones)polymakeFile.writeStringProperty("MAXIMAL_CONES",toStringJustCones(getMinDim(),getMaxDim(),true,flags&FPF_group, 0,false,flags&FPF_tPlaneSort));
598     if(flags&FPF_conesCompressed)polymakeFile.writeStringProperty("CONES_ORBITS",toStringJustCones(getMinDim(),getMaxDim(),false,flags&FPF_group, 0,true,flags&FPF_tPlaneSort));
599     if((flags&FPF_conesCompressed) && (flags&FPF_maximalCones))polymakeFile.writeStringProperty("MAXIMAL_CONES_ORBITS",toStringJustCones(getMinDim(),getMaxDim(),true,flags&FPF_group, 0,true,flags&FPF_tPlaneSort));
600 
601     if(!sym.isTrivial())
602       {
603         polymakeFile.writeMatrixProperty("SYMMETRY_GENERATORS",IntToZMatrix(sym.getGenerators()));
604       }
605 
606     std::stringstream s;
607     polymakeFile.writeStream(s);
608     return s.str();
609 
610     #if 0
611 
612     if(flags&FPF_conesCompressed)
613     {
614   //    log1 fprintf(Stderr,"Producing list of cones up to symmetry.\n");
615       polymakeFile.writeStringProperty("CONES_ORBITS",symCom.toString(symCom.getMinDim(),symCom.getMaxDim(),false,flags&FPF_group,0,true,flags&FPF_tPlaneSort));
616   //    log1 fprintf(Stderr,"Done producing list of cones up to symmetry.\n");
617   //    log1 fprintf(Stderr,"Producing list of maximal cones up to symmetry.\n");
618       stringstream multiplicities;
619       polymakeFile.writeStringProperty("MAXIMAL_CONES_ORBITS",symCom.toString(symCom.getMinDim(),symCom.getMaxDim(),true,flags&FPF_group, &multiplicities,true,flags&FPF_tPlaneSort));
620       if(flags&FPF_multiplicities)polymakeFile.writeStringProperty("MULTIPLICITIES_ORBITS",multiplicities.str());
621   //    log1 fprintf(Stderr,"Done producing list of maximal cones up to symmetry.\n");
622     }
623 
624     if(flags&FPF_conesExpanded)
625       {
626         if(flags&FPF_cones)
627           {
628   //          log1 fprintf(Stderr,"Producing list of cones.\n");
629             polymakeFile.writeStringProperty("CONES",symCom.toString(symCom.getMinDim(),symCom.getMaxDim(),false,flags&FPF_group,0,false,flags&FPF_tPlaneSort));
630   //          log1 fprintf(Stderr,"Done producing list of cones.\n");
631           }
632         if(flags&FPF_maximalCones)
633           {
634   //          log1 fprintf(Stderr,"Producing list of maximal cones.\n");
635             stringstream multiplicities;
636             polymakeFile.writeStringProperty("MAXIMAL_CONES",symCom.toString(symCom.getMinDim(),symCom.getMaxDim(),true,flags&FPF_group, &multiplicities,false,flags&FPF_tPlaneSort));
637             if(flags&FPF_multiplicities)polymakeFile.writeStringProperty("MULTIPLICITIES",multiplicities.str());
638   //          log1 fprintf(Stderr,"Done producing list of maximal cones.\n");
639           }
640       }
641   #endif
642     #if 0
643     if(flags&FPF_values)
644       {
645         {
646           ZMatrix values;
647           for(int i=0;i<linealitySpaceGenerators.getHeight();i++)
648             {
649               ZVector v(1);
650               v[0]=evaluatePiecewiseLinearFunction(linealitySpaceGenerators[i]);
651               values.appendRow(v);
652             }
653           polymakeFile.writeMatrixProperty("LINEALITY_VALUES",rowsToIntegerMatrix(values,1));
654         }
655         {
656           ZMatrix values;
657           for(IntegerVectorList::const_iterator i=rays.begin();i!=rays.end();i++)
658             {
659               ZVector v(1);
660               v[0]=evaluatePiecewiseLinearFunction(*i);
661               values.push_back(v);
662             }
663           polymakeFile.writeMatrixProperty("RAY_VALUES",rowsToIntegerMatrix(values,1));
664         }
665       }
666   #endif
667 
668 
669   //  log1 fprintf(Stderr,"Producing final string for output.\n");
670   /*  stringstream s;
671     polymakeFile.writeStream(s);
672     string S=s.str();
673   //  log1 fprintf(Stderr,"Printing string.\n");
674     p->printString(S.c_str());
675   *///  log1 fprintf(Stderr,"Done printing string.\n");
676   }
677 
makeZCone(IntVector const & indices) const678   ZCone SymmetricComplex::makeZCone(IntVector const &indices)const
679   {
680     ZMatrix generators(indices.size(),getAmbientDimension());
681     for(unsigned i=0;i<indices.size();i++)
682       generators[i]=vertices[indices[i]];
683     return ZCone::givenByRays(generators,linealitySpace);
684   }
685 }
686