politopix  4.1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NormalFan_Rn.cpp
Go to the documentation of this file.
1 // politopix allows to make computations on polytopes such as finding vertices, intersecting, Minkowski sums, ...
2 // Copyright (C) 2011-2015 : Delos Vincent
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //
19 // I2M (UMR CNRS 5295 / University of Bordeaux)
20 
22 #include "DoubleDescription_Rn.h"
23 #include "NormalFan_Rn.h"
24 #include "IO_Polytope.h"
25 #include <math.h>
26 #include <numeric>
27 #include <sstream>
28 
29 
30 // Constructor
31 NormalFan_Rn::NormalFan_Rn(const boost::shared_ptr<Polytope_Rn>& A) {
32  boost::shared_ptr<PolyhedralCone_Rn> primalCone;
33  for (unsigned int u=0; u<A->numberOfGenerators(); u++) {
34  boost::shared_ptr<Generator_Rn> vx1 = A->getGenerator(u);
36  // STEP1 : split the polytope into its primal polyhedral cones //
38  primalCone.reset(new PolyhedralCone_Rn());
39  // Insert all half-spaces connected to the current vertex into the primal cone.
40  for (unsigned int i=0; i<vx1->numberOfFacets(); i++)
41  primalCone->addHalfSpace(vx1->getFacet(i));
43  // STEP 2 : build the dual polyhedral cone //
45  boost::shared_ptr<PolyhedralCone_Rn> dualCone = primalCone->computeDualPolyhedralCone();
46  // Insert the dual in its list.
47  _listOfPolyhedralCones.push_back(dualCone);
48  // Set the anchor for the corresponding cone.
49  _listOfVertices.push_back(vx1);
50  //std::cout << "$$$$$$$$$$$$ " << u << std::endl;
51  //dualCone->dump(std::cout);
52  //dualCone->checkTopologyAndGeometry();
53  //for (unsigned int k=0; k<Rn::getDimension(); k++) {
54  //vx1->setCoordinate(k, vx1->getCoordinate(k));
55  //std::cout << vx1->getCoordinate(k) << " ";
56  //}
57  //std::cout << std::endl;
58  //dualCone->checkTopologyAndGeometry();
59  //std::cout << "###########################################"<< std::endl;
60  //std::ostringstream stream_;
61  //stream_ << "cone_p4ns";
62  //stream_ << u;
63  //std::string FileOut = stream_.str();
64  //FileOut += ".pcon";
65  //IO_Polytope::save(FileOut, dualCone);
66  }
67 }
68 
69 // CHECK POLYHEDRON
70 bool NormalFan_Rn::checkTopologyAndGeometry() const throw (std::domain_error) {
71  return true;
72 }
73 
75  const std::vector< boost::shared_ptr<HalfSpace_Rn> >& allHS,
76  boost::shared_ptr<Polytope_Rn>& Pol) {
77  unsigned int RnDIM = Rn::getDimension();
78  double TOL = Rn::getTolerance();
79  double TTOL = 2*TOL;
80  Rn::setTolerance(TOL);
81  std::vector< double > arrayOfNorms(allHS.size());
82  std::vector< boost::shared_ptr<HalfSpace_Rn> >::const_iterator iteHS;
83  unsigned int hs = 0;
84  {for (iteHS = allHS.begin(), hs=0; iteHS!=allHS.end(); ++iteHS, ++hs) {
85  double halfSpaceNorm = std::inner_product((*iteHS)->begin(), (*iteHS)->end(), (*iteHS)->begin(), 0.);
86  arrayOfNorms[hs] = sqrt(halfSpaceNorm);
87  }}
88  unsigned int cone = 0;
89  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::iterator itePC;
90  {for (itePC=_listOfPolyhedralCones.begin(), cone=0; itePC!=_listOfPolyhedralCones.end(); ++itePC, ++cone) {
92  //std::cout << std::endl << "### Cone" << cone << std::endl;
93  const listOfGeometricObjects< boost::shared_ptr<Generator_Rn> >& listOfEdges = (*itePC)->getListOfGenerators();
95  std::vector< bool > arrayOfEgdesOKforHS(allHS.size());
96  {for (unsigned int i=0; i<arrayOfEgdesOKforHS.size(); ++i)
97  arrayOfEgdesOKforHS[i] = false;
98  }
99  bool coneOKforHS = true;
100  {for (iteHS = allHS.begin(), hs=0; iteHS!=allHS.end() && coneOKforHS==true; ++iteHS, ++hs) {
101  unsigned int countON = 0;
102  bool IN = false, OUT = false;
103  {for (iteGN.begin(); iteGN.end()!=true; iteGN.next()) {
104  double scalarProduct = std::inner_product(iteGN.current()->begin(), iteGN.current()->end(), (*iteHS)->begin(), 0.);
105  double distanceToHyperplane = scalarProduct / arrayOfNorms[hs];
106 
108  //std::cout.precision(15);
109  //std::cout << "# E" << iteGN.currentIteratorNumber() << " = [";
110  //{for (unsigned int ii=0; ii<RnDIM; ii++) {
111  //std::cout << iteGN.current()->getCoordinate(ii);
112  //if (ii != RnDIM-1)
113  //std::cout << ", ";
114  //}}
115  //std::cout << "] => ";
116  //(*iteHS)->dump(std::cout);
117  //std::cout << ", dotP = " << scalarProduct;
118  //std::cout << ", dist = " << distanceToHyperplane;
120 
121  if (distanceToHyperplane > TOL) {
122  IN = true;
123 
125  //std::cout << " (IN)" << std::endl;
127 
128  }
129  else if (distanceToHyperplane < -TOL) {
130  OUT = true;
131 
133  //std::cout << " (OUT)" << std::endl;
135 
136  }
137  else {
138  ++countON;
139 
141  //std::cout << " (ON)" << std::endl;
143 
144  }
145  }}
146  if ((IN==true && OUT==true) || (countON>=1))
147  arrayOfEgdesOKforHS[hs] = true;
148  else
149  coneOKforHS = false;
150  }}
151  bool allHSOK = true;
153  //std::cout << "Array of boolean {";
154  {for (unsigned int i=0; i<arrayOfEgdesOKforHS.size(); ++i) {
156  //std::cout << " " << (arrayOfEgdesOKforHS[i]==true? "T" : "F");
157  if (arrayOfEgdesOKforHS[i] == false)
158  allHSOK = false;
159  }}
161  //std::cout << " }, result = " << (allHSOK==true? "T" : "F") << std::endl;
162  //_listOfVertices[cone]->dump(std::cout);
163  //std::cout<< std::endl;
164  if (allHSOK == true)
165  Pol->addGenerator(_listOfVertices[cone]);
166  }}
167 
168  // Restore the previous configuration.
169  Rn::setTolerance(TOL);
170 }
171 
172 
173 // ALGORITHMS
175 #ifdef DEBUG
176  std::cout << std::endl << "NormalFan_Rn::computeCommonRefinement()" << std::endl;
177 #endif
178  unsigned int RnDIM=Rn::getDimension();
179  unsigned int currentCone1Nb=0,currentCone2Nb=0;
180  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::const_iterator endLPC1=NF1.getListOfPolyhedralCones().end();
181  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::const_iterator endLPC2=NF2.getListOfPolyhedralCones().end();
182  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::const_iterator LPC1=NF1.getListOfPolyhedralCones().begin();
183  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::const_iterator LPC2=NF2.getListOfPolyhedralCones().begin();
184  std::vector< boost::shared_ptr<Generator_Rn> >::const_iterator LVX1=NF1.getListOfGenerators().begin();
185  std::vector< boost::shared_ptr<Generator_Rn> >::const_iterator LVX2=NF2.getListOfGenerators().begin();
186  {for (; LPC1!=endLPC1; ++LPC1, ++LVX1) {
187  {for (; LPC2!=endLPC2; ++LPC2, ++LVX2) {
188  boost::shared_ptr<PolyhedralCone_Rn> intersectionCone(new PolyhedralCone_Rn());
189  boost::shared_ptr<PolyhedralCone_Rn> Ca = *LPC1;
190  boost::shared_ptr<PolyhedralCone_Rn> Cb = *LPC2;
191  // Fill the data structures.
193  {for (iteGNA.begin(); iteGNA.end()!=true; iteGNA.next()) {
194  // Make a deep copy of each generator
195  boost::shared_ptr<Generator_Rn> gn(new Generator_Rn( *(iteGNA.current()) ));
196  intersectionCone->addGenerator(gn);
197  }}
199  for (iteHSB.begin(); iteHSB.end()!=true; iteHSB.next())
200  intersectionCone->addHalfSpace(iteHSB.current());
201 #ifdef DEBUG
202  std::cout << "=== Cone from A number " << currentCone1Nb << std::endl;
203  std::cout << "=== Cone from B number " << currentCone2Nb << std::endl;
204 #endif
205  // Compute the intersection between the two polyhedral cones.
206  TrackingOperatorToResult trackerVdesc,trackerHdesc;
207  constIteratorOfListOfGeometricObjects< boost::shared_ptr<HalfSpace_Rn> > lexmin_ite(intersectionCone->getListOfHalfSpaces());
208  StrongRedundancyProcessing< boost::shared_ptr<PolyhedralCone_Rn> > NRP(intersectionCone->neigbourhoodCondition());
210  StrongRedundancyProcessing< boost::shared_ptr<PolyhedralCone_Rn> > > DD(intersectionCone, lexmin_ite, NRP, 0, trackerVdesc, trackerHdesc);
211  bool notEmpty = !DD.getIsEmpty();
212 #ifdef DEBUG
213  std::cout << "@@@ nbEDG=" << intersectionCone->numberOfGenerators() << "( ";
214 #endif
215  // The second test is necessary when dealing with parallelism.
216  if (notEmpty == true && intersectionCone->numberOfGenerators() >= RnDIM) {
217  // Set the anchor for the corresponding cone.
218  boost::shared_ptr<Generator_Rn> VX(new Generator_Rn(RnDIM));
219  VX->makeSum((*LVX1),(*LVX2));
220 #ifdef DEBUG
221  for (unsigned int k=0; k<RnDIM; ++k)
222  std::cout << (*LVX1)->getCoordinate(k) << "+" << (*LVX2)->getCoordinate(k) << "=" << VX->getCoordinate(k) << "\t";
223 #endif
224  _listOfVertices.push_back(VX);
225  _listOfPolyhedralCones.push_back(intersectionCone);
226  // Now deal with generators MODIFIED and CREATED.
227  const std::vector< std::pair< StatusAfter, int > >& res = trackerVdesc.getResultToOperator();
228  std::vector< std::pair< StatusAfter, int > >::const_iterator iteGN_INTER=res.begin();
229  unsigned int counterV=0;
230  // The generators created by the intersection have to be added just the way they are.
231  // The generators modified by the intersection have to keep their old half-spaces and add the new ones.
232  {for ( ; iteGN_INTER!=res.end(); ++iteGN_INTER) {
233  if (iteGN_INTER->first == Result_CREATED) {
234  Ca->addGenerator(intersectionCone->getGenerator(counterV));
235  }
236  else if (iteGN_INTER->first == Result_MODIFIED) {
237  int nbModGEN = iteGN_INTER->second;
238  // At this moment the new half-spaces are not marked as such, so just use the properties of the sets.
239  std::set< boost::shared_ptr<HalfSpace_Rn> > setOfFacets1,setOfFacets2;
240  Ca->getGenerator(nbModGEN)->exportFacets(setOfFacets1);
241  intersectionCone->getGenerator(counterV)->exportFacets(setOfFacets2);
242  setOfFacets1.insert(setOfFacets2.begin(), setOfFacets2.end());
243  Ca->getGenerator(nbModGEN)->clearFacets();
244  Ca->getGenerator(nbModGEN)->importFacets(setOfFacets1);
245  }
246  ++counterV;
247  }}
248  const std::vector< std::pair< StatusAfter, int > >& resH = trackerHdesc.getResultToOperator();
249  std::vector< std::pair< StatusAfter, int > >::const_iterator iteHS_INTER=resH.begin();
250  unsigned int counterH=0;
251  // The new list of half-spaces contain the old list plus the ones of Cb which are not redundant.
252  {for ( ; iteHS_INTER!=res.end(); ++iteHS_INTER) {
253  if (iteHS_INTER->first == Result_CREATED) {
254  Ca->addHalfSpace(intersectionCone->getHalfSpace(counterH));
255  }
256  ++counterH;
257  }}
258  }
259 #ifdef DEBUG
260  std::cout << ")" << std::endl;
261 #endif
262  ++currentCone2Nb;
263  }}
264  ++currentCone1Nb;
265  }}
266 }
267 
269 void NormalFan_Rn::dump(std::ostream& out) const {
270  out << std::endl << "#NORMAL FAN" << std::endl;
271  unsigned int nb=0;
272  std::vector< boost::shared_ptr<Generator_Rn> >::const_iterator iteVX=_listOfVertices.begin();
273  std::vector< boost::shared_ptr<PolyhedralCone_Rn> >::const_iterator itePC=_listOfPolyhedralCones.begin();
274  {for (; itePC!=_listOfPolyhedralCones.end(); ++itePC, ++iteVX) {
275  out << "#" << nb << std::endl;
276  out << "# anchor (";
277  for (unsigned int k=0; k<Rn::getDimension(); k++)
278  out << (*iteVX)->getCoordinate(k) << " ";
279  out << ")" << std::endl;
280  (*itePC)->dump(std::cout);
281  ++nb;
282  }}
283 }
void computeCommonRefinement(const NormalFan_Rn &NA, const NormalFan_Rn &NB)
Compute .
Model a polyhedral cone using its two equivalent definitions : the convex hull and the half-space int...
const std::vector< std::pair< StatusAfter, int > > & getResultToOperator() const
Definition: Tracking.h:95
const GEOMETRIC_OBJECT current()
Return the current geometric element.
void begin()
Move the iterator at the beginning of the list.
std::vector< boost::shared_ptr< PolyhedralCone_Rn > > _listOfPolyhedralCones
The list of polyhedral cones partitioning the whole space.
Definition: NormalFan_Rn.h:86
static polito_EXPORT void setTolerance(double t)
Give the minimum distance between two points.
Definition: Rn.cpp:33
static polito_EXPORT double getTolerance()
Give the minimum distance between two points.
Definition: Rn.cpp:31
bool end() const
Tell whether we have reached the end of the list.
This class stores static function that dispatch the main geometric values we use. ...
Definition: Tracking.h:41
const std::vector< boost::shared_ptr< PolyhedralCone_Rn > > & getListOfPolyhedralCones() const
Definition: NormalFan_Rn.h:61
static polito_EXPORT unsigned int getDimension()
Return the dimension of the cartesian space we work in.
Definition: Rn.cpp:29
This class can be more time-consuming than WeakRedundancyProcessing or NoRedundancyProcessing because...
const std::vector< boost::shared_ptr< Generator_Rn > > & getListOfGenerators() const
Definition: NormalFan_Rn.h:59
std::vector< boost::shared_ptr< Generator_Rn > > _listOfVertices
The list of vertices attached to their respective dual polyhedral cones.
Definition: NormalFan_Rn.h:88
A n-coordinates generator, which can be a vertex or an edge whether it is contained by a polytope or ...
Definition: Generator_Rn.h:38
This class is designed to run the list of all geometric objects representing a polytope.
Model a normal fan.
Definition: NormalFan_Rn.h:37
void next()
Move the iterator one step forward.
This class is designed to contain the list of all generators or half-spaces representing a polytope o...
bool checkTopologyAndGeometry() const
void dump(std::ostream &out) const
Dump the polyhedral structure on std::cout.
NormalFan_Rn()
Constructor.
Definition: NormalFan_Rn.h:42
void computeHyperplanesSeparationForProjection(const std::vector< boost::shared_ptr< HalfSpace_Rn > > &, boost::shared_ptr< Polytope_Rn > &)
The algorithm implemented here is an incremental algorithm as mentioned in How Good are Convex Hull ...