politopix  5.0.0
UpdDoubleDescription_Rn.h
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) 2021 : Delos Vincent
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU 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 General Public License for more details.
13 //
14 // You should have received a copy of the GNU 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 
21 #ifndef UPDDOUBLEDESCRIPTION_Rn
22 #define UPDDOUBLEDESCRIPTION_Rn
23 
24 #include <math.h>
25 #include <numeric>
26 #include <set>
27 #include <map>
28 #include "Tracking.h"
29 #include "Neighbours_Rn.h"
30 
31 
32 
50 template< class POLYHEDRON, class ITERATOR, class REDUNDANCY_PROCESSING > class UpdDoubleDescription {
51 
52  public:
53  UpdDoubleDescription(POLYHEDRON poly, ITERATOR ite, REDUNDANCY_PROCESSING redproc, int truncationStep):_redundancyProcessing(redproc) {
54  std::vector< boost::shared_ptr<Generator_Rn_SD> > listOfGenSD;
55  // Generator_Rn => Generator_Rn_SD
56  // From the current generators make a list of generators dedicated to work in the data structure algorithm.
57  // Make sure the list of half-space numbers is sorted as we want to use algorithms further.
58  poly->getListOfGeneratorsSD(listOfGenSD);
59  // Count the number of hyperplanes versus the number of half-spaces.
60  unsigned int nbHyp = 0, nbProcessHyp = 0;
61  {for (ite.begin(); ite.end()!=true; ite.next()) {
62  const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace = ite.current();
63  boost::shared_ptr<Hyperplane_Rn> currentHyp = boost::dynamic_pointer_cast<Hyperplane_Rn>(currentHalfSpace);
64  if (currentHyp) {
65  nbHyp++;
66  if (ite.currentIteratorNumber() < truncationStep)
67  nbProcessHyp++;
68  }
69  }}
70  _redundancyProcessing.initNumberOfVerticesPerHalfSpace(listOfGenSD, truncationStep, nbProcessHyp); // Deal with redundancy.
71  //_redundancyProcessing.dumpListOfRedundantHS( std::cout );
72 
73  // Do the hard job now.
74  _isEmpty = !compute(poly, ite, truncationStep, listOfGenSD);
75 
76  if (_isEmpty == false) {
77  // Set the pointers from the generators to the half-spaces before dealing with redundancy - as the redundancy
78  // processing algorithm will change the numbers of the half-spaces. Here recycle the old pointers stored in
79  // the polyhedron to build the new list with the created generators.
80  poly->setListOfGeneratorsSD(listOfGenSD);
81  // Include all the generators now.
82  _redundancyProcessing.unhookRedundantHalfSpaces(poly);
83  //poly->dump(std::cout);
84  // In some fuzzy cases, computing the intersection between the space spanned by two generators and a hyperplane
85  // provides a fuzzy generator somewhere inside the fuzzy zone. The location of such a generator needs to be
86  // refined later on in the process. Meanwhile the current one is likely to lose half-spaces as the probability
87  // that some of them are redundant is high. So remove them as they are not genuine generators.
88  _redundancyProcessing.unhookRedundantGenerators(poly);
89  }
90  }
91 
95  POLYHEDRON poly,
96  ITERATOR ite,
97  REDUNDANCY_PROCESSING redproc,
98  int truncationStep,
99  TrackingOperatorToResult& trackerVdesc,
100  TrackingOperatorToResult& trackerHdesc):_redundancyProcessing(redproc) {
101  std::vector< boost::shared_ptr<Generator_Rn_SD> > listOfGenSD;
102  // Generator_Rn => Generator_Rn_SD
103  // From the current generators make a list of generators dedicated to work in the data structure algorithm.
104  // Make sure the list of half-space numbers is sorted as we want to use algorithms further.
105  poly->getListOfGeneratorsSD(listOfGenSD);
106  // Count the number of hyperplanes versus the number of half-spaces.
107  unsigned int nbHyp = 0, nbProcessHyp = 0;
108  {for (ite.begin(); ite.end()!=true; ite.next()) {
109  const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace = ite.current();
110  boost::shared_ptr<Hyperplane_Rn> currentHyp = boost::dynamic_pointer_cast<Hyperplane_Rn>(currentHalfSpace);
111  if (currentHyp) {
112  nbHyp++;
113  if (ite.currentIteratorNumber() < truncationStep)
114  nbProcessHyp++;
115  }
116  }}
117  _redundancyProcessing.initNumberOfVerticesPerHalfSpace(listOfGenSD, truncationStep, nbProcessHyp); // Deal with redundancy.
118  //_redundancyProcessing.dumpListOfRedundantHS( std::cout );
119 
120  // Do the hard job now.
121  _isEmpty = !compute(poly, ite, truncationStep, listOfGenSD);
122 
123  if (_isEmpty == false) {
124  // Store the modifications in the binary operation tracker.
125  // Operator1_Entity[i] = (Generator_Rn_SD::Status, Result_Entity[j])
126  // Operator2_Entity[k] = (Generator_Rn_SD::Status, Result_Entity[l])
127  // Result_Entity[m] = (Generator_Rn_SD::Status, (Operator1_Entity[p], Operator2_Entity[q]))
128  unsigned int nbRes=0;
129  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGenSD;
130  {for (iteGenSD=listOfGenSD.begin(); iteGenSD!=listOfGenSD.end(); ++iteGenSD) {
131  // In the tracker, the operand entities have been set to Operator_DELETED by default and the
132  // result entities have been set by default to Result_UNCHANGED.
133  Generator_Rn_SD::Status thisStatus = (*iteGenSD)->getStatus();
134  unsigned int nbOp1 = (*iteGenSD)->getGeneratorNumber();
135  if (thisStatus == Generator_Rn_SD::CREATED || thisStatus == Generator_Rn_SD::CREATED_AND_MODIFIED) {
136  trackerVdesc.setResultEntityAsCreated(nbRes);
137  trackerVdesc.setResult_Operator(nbRes,-1);
138  }
139  else if (thisStatus == Generator_Rn_SD::MODIFIED) {
140  trackerVdesc.setResultEntityAsModified(nbRes);
141  trackerVdesc.setResult_Operator(nbRes,nbOp1);
142  trackerVdesc.setOperatorEntityAsModified(nbOp1);
143  trackerVdesc.setOperator_Result(nbOp1,nbRes);
144  }
145  else if (thisStatus == Generator_Rn_SD::UNCHANGED) {
146  trackerVdesc.setResultEntityAsUnchanged(nbRes);
147  trackerVdesc.setResult_Operator(nbRes,nbOp1);
148  trackerVdesc.setOperatorEntityAsUnchanged(nbOp1);
149  trackerVdesc.setOperator_Result(nbOp1,nbRes);
150  }
151  ++nbRes;
152  }}
153  // Set the pointers from the generators to the half-spaces before dealing with redundancy - as the
154  // redundancy processing algorithm will change the numbers of the half-spaces.
155  poly->setListOfGeneratorsSD(listOfGenSD);
156  // Process the half-spaces now.
157  _redundancyProcessing.markHdescription(trackerHdesc, truncationStep);
158  _redundancyProcessing.unhookRedundantHalfSpaces(poly);
159  //poly->dump(std::cout);
160  // In some fuzzy cases, computing the intersection between the space spanned by two generators and a hyperplane
161  // provides a fuzzy generator somewhere inside the fuzzy zone. The location of such a generator needs to be
162  // refined later on in the process. Meanwhile the current one is likely to lose half-spaces as the probability
163  // that some of them are redundant is high. So remove them as they are not genuine generators.
164  _redundancyProcessing.unhookRedundantGenerators(poly);
165  }
166  }
167 
169 
170  bool getIsEmpty() const {return _isEmpty;}
171 
174  std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_list,
175  const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace,
176  std::vector<double>& GN_IN_sp,
177  std::vector<double>& GN_OUT_sp,
178  std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_IN,
179  std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_OUT,
180  std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_ON)
181  {
182  int GeneratorNumber=0;
183  double TOL = Rn::getTolerance();
184  double halfSpaceNorm =
185  std::inner_product(currentHalfSpace->begin(), currentHalfSpace->end(), currentHalfSpace->begin(), 0.);
186  halfSpaceNorm = sqrt(halfSpaceNorm);
187  std::vector< boost::shared_ptr<Generator_Rn_SD> >::iterator iteGN;
188  for (iteGN=GN_list.begin(); iteGN!=GN_list.end(); ++iteGN) {
189  //const boost::shared_ptr<Generator_Rn_SD>& currentGenerator = iteGN.current();
190  double scalarProduct =
191  std::inner_product((*iteGN)->begin(), (*iteGN)->end(), currentHalfSpace->begin(), 0.);
192  //boost::numeric::ublas::inner_prod(currentGenerator->vect(), currentHalfSpace->vect());
193 #ifdef DEBUG
194  unsigned int RnDIM=currentHalfSpace->dimension();
195  std::cout.precision(15);
196  std::cout << "# V" << GeneratorNumber << " = [";
197  {for (unsigned int ii=0; ii<RnDIM; ii++) {
198  std::cout << (*iteGN)->getCoordinate(ii);
199  if (ii != RnDIM-1)
200  std::cout << " ";
201  }}
202  std::cout << "]" << std::endl << "{ ";
203  {for (unsigned int ii=0; ii<(*iteGN)->numberOfFacets(); ii++) {
204  std::cout << (*iteGN)->getFacet(ii) << " ";
205  }}
206  std::cout << "}" << std::endl;
207  std::cout << "dotP = " << scalarProduct;
208  std::cout << ", dist = " << (scalarProduct+currentHalfSpace->getConstant()) / halfSpaceNorm;
209 #endif
210  //std::cout << "sp = " << scalarProduct << " ";
211  double distanceToHyperplane = (scalarProduct+currentHalfSpace->getConstant()) / halfSpaceNorm;
212  if (distanceToHyperplane > TOL) {
213  GN_IN.push_back((*iteGN));
214  GN_IN_sp.push_back(scalarProduct);
215  }
216  else if (distanceToHyperplane < -TOL) {
217  GN_OUT.push_back((*iteGN));
218  GN_OUT_sp.push_back(scalarProduct);
219  }
220  else {
221  GN_ON.push_back((*iteGN));
222  }
223 #ifdef DEBUG
225  if (distanceToHyperplane > TOL)
226  currentState = HalfSpace_Rn::hs_IN;
227  else if (distanceToHyperplane < -TOL)
228  currentState = HalfSpace_Rn::hs_OUT;
229  else
230  currentState = HalfSpace_Rn::hs_ON;
231  std::cout << ", state = " << HalfSpace_Rn::getStateAsText(currentState) << std::endl;
232 #endif
233  GeneratorNumber++;
234  }
235  }
236 
238  bool compute(POLYHEDRON poly, ITERATOR iteHS, int truncationStep, std::vector< boost::shared_ptr<Generator_Rn_SD> >& listOfGenSD) {
239  // Store the scalar product result.
240  std::vector<double> GN_IN_sp;
241  std::vector<double> GN_OUT_sp;
242  // Store generators IN, ON, OUT or newly created.
243  std::vector< boost::shared_ptr<Generator_Rn_SD> > GN_IN;
244  std::vector< boost::shared_ptr<Generator_Rn_SD> > GN_OUT;
245  std::vector< boost::shared_ptr<Generator_Rn_SD> > GN_ON;
246  std::vector< boost::shared_ptr<Generator_Rn_SD> > GN_new;
247  // Remove redundant half spaces.
248  std::vector< boost::shared_ptr<HalfSpace_Rn> > redundantHS;
249  int halfspaceNumber=truncationStep, generatorNumber=0;
250  unsigned int RnDIM=poly->dimension();
251  double TOL2=Rn::getTolerance()*Rn::getTolerance();
252 
253 #ifdef DEBUG
254  std::cout << std::endl << "UpdDoubleDescription::compute(" << truncationStep << ")" << std::endl;
255 #endif
256  // We use this algorithm to compute vertices for a single polyhedron or to intersect two polyhedra.
257  // In the last case we truncate the polyhedron A generators net by the the polyhedron B half-spaces
258  // so we need to step forward in the half-space list where B constraints begin.
259  //constIteratorOfListOfGeometricObjects< boost::shared_ptr<HalfSpace_Rn> > iteHS(poly->getListOfHalfSpaces());
260  generatorNumber = poly->numberOfGenerators();
261  iteHS.setStep(truncationStep);
262  {for (iteHS.begin(); iteHS.end()!=true; iteHS.next()) {
263  const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace = iteHS.current();
264  boost::shared_ptr<Hyperplane_Rn> currentHyp = boost::dynamic_pointer_cast<Hyperplane_Rn>(currentHalfSpace);
265  bool isHyp = false;
266  if (currentHyp)
267  isHyp = true;
268  // When you add a linear constraint tell whether it is a half-space or a hyperplane.
269  _redundancyProcessing.addHalfSpace(isHyp);
270 #ifdef DEBUG
271  double halfSpaceNorm = std::inner_product(currentHalfSpace->begin(), currentHalfSpace->end(), currentHalfSpace->begin(), 0.);
272  halfSpaceNorm = sqrt(halfSpaceNorm);
273  std::cout << "Facet number " << halfspaceNumber << std::endl;
274  std::cout << "H" << halfspaceNumber << " = ";
275  currentHalfSpace->dump(std::cout);
276  std::cout << ", norm=" << halfSpaceNorm;
277  std::cout << std::endl;
278 #endif
279 
280  // Fill the arrays of generators according to their position with respect to the current half-space.
281  computeVertexStates(listOfGenSD, currentHalfSpace, GN_IN_sp, GN_OUT_sp, GN_IN, GN_OUT, GN_ON);
282 
283  // Check whether the current constraint, i.e. a half-space or a hyperplane, excludes all Generators.
284  // In the case of a half-space, it used to be: if (GN_IN.empty() == true) {
285  if (currentHalfSpace->testEmptyness(GN_IN, GN_OUT, GN_ON)) {
286  // NO INTERSECTION
287 #ifdef DEBUG
288  std::cout << "Truncation is empty or flat." << std::endl;
289 #endif
290  poly->reset();
291  return false;
292  }
293 
294  // Check whether the current constraint is redundant. Only available for polytopes.
295  // For polyhedral cones, replace Rn::getDimension() by (Rn::getDimension()-1).
296  if (GN_OUT.empty() == true) {// && VX_ON.size() < numberOfGeneratorsPerFacet()) {
297  // REDUNDANT HALFSPACE (be careful when modifying a list under iterator)
298  redundantHS.push_back(currentHalfSpace);
299  //_listOfHalfSpaces.removeCurrentHalfSpace(iteHS.currentIteratorNumber());
300  //_listOfHalfSpaces.erase(HSPos);
301  // When chopping a polyhedral body with a hyperplane, if the set of generators OUT is empty,
302  // only keep the generators ON and ignore the generators IN.
303  // In the case of a half-space, keep things unchanged i.e. listOfGeneratorSD = GN_IN + GN_ON
304  currentHalfSpace->noGeneratorsOUT(listOfGenSD, GN_ON);
305 #ifdef DEBUG
306  std::cout << "VX_OUT= " << GN_OUT.size() << std::endl;
307  std::cout << "VX_IN = " << GN_IN.size() << std::endl;
308  std::cout << "VX_ON = " << GN_ON.size() << std::endl;
309  std::cout << "redundantHS = " << redundantHS.size() << std::endl;
310  std::cout << "============================================" << std::endl;
311 #endif
312  }
313  else if (GN_IN.empty() != true) {
314  // Build the list of all possible new generators.
315  Neighbours_Rn newGeneratorsTool;
316  {
317  // OUT-IN & OUT-ON
318  unsigned int count_OUT=0;
319  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_OUT;
320  {for (iteGN_OUT=GN_OUT.begin(); iteGN_OUT!=GN_OUT.end(); ++iteGN_OUT, ++count_OUT) {
321  unsigned int count_IN=0;
322  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_IN;
323  {for (iteGN_IN=GN_IN.begin(); iteGN_IN!=GN_IN.end(); ++iteGN_IN, ++count_IN) {
324  std::vector< unsigned int > commonPFacets;
325  if (_redundancyProcessing.checkNeighbours(poly, *iteGN_IN, *iteGN_OUT, commonPFacets) == true) {
326  // Uncomment only when computing 2D or 3D non fuzzy cases.
327  //if (RnDIM > 3)
328  newGeneratorsTool.addGenerator(
329  commonPFacets,
330  count_IN,
331  count_OUT,
333  //else
334  //newGeneratorsTool.addGeneratorWithoutCheck(
335  //commonPFacets,
336  //count_IN,
337  //count_OUT,
338  //HalfSpace_Rn::hs_IN_OR_OUT);
339  }
340  }}
341  unsigned int count_ON=0;
342  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON;
343  {for (iteGN_ON=GN_ON.begin(); iteGN_ON!=GN_ON.end(); ++iteGN_ON, ++count_ON) {
344  std::vector< unsigned int > commonPFacets;
345  if (_redundancyProcessing.checkNeighbours(poly, *iteGN_ON, *iteGN_OUT, commonPFacets) == true) {
346  //if (RnDIM > 3)
347  newGeneratorsTool.addGenerator(
348  commonPFacets,
349  count_ON,
350  count_OUT,
352  //else
353  //newGeneratorsTool.addGeneratorWithoutCheck(
354  //commonPFacets,
355  //count_ON,
356  //count_OUT,
357  //HalfSpace_Rn::hs_ON);
358  }
359  }}
360  }}
361  // ON-IN & ON-ON
362  unsigned int count_ON1=0;
363  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON1;
364  {for (iteGN_ON1=GN_ON.begin(); iteGN_ON1!=GN_ON.end(); ++iteGN_ON1, ++count_ON1) {
365  unsigned int count_IN=0;
366  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_IN;
367  {for (iteGN_IN=GN_IN.begin(); iteGN_IN!=GN_IN.end(); ++iteGN_IN, ++count_IN) {
368  std::vector< unsigned int > commonPFacets;
369  if (_redundancyProcessing.checkNeighbours(poly, *iteGN_IN, *iteGN_ON1, commonPFacets) == true) {
370  //if (RnDIM > 3)
371  newGeneratorsTool.addGenerator(
372  commonPFacets,
373  count_IN,
374  count_ON1,
376  //else
377  //newGeneratorsTool.addGeneratorWithoutCheck(
378  //commonPFacets,
379  //count_IN,
380  //count_ON1,
381  //HalfSpace_Rn::hs_ON);
382  }
383  }}
384  unsigned int count_ON2=0;
385  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON2;
386  {for (iteGN_ON2=GN_ON.begin(); iteGN_ON2!=GN_ON.end(); ++iteGN_ON2, ++count_ON2) {
387  std::vector< unsigned int > commonPFacets;
388  if (iteGN_ON1 != iteGN_ON2 &&
389  _redundancyProcessing.checkNeighbours(poly, *iteGN_ON1, *iteGN_ON2, commonPFacets) == true) {
390  //if (RnDIM > 3)
391  newGeneratorsTool.addGenerator(
392  commonPFacets,
393  count_ON1,
394  count_ON2,
396  //else
397  //newGeneratorsTool.addGeneratorWithoutCheck(
398  //commonPFacets,
399  //count_ON1,
400  //count_ON2,
401  //HalfSpace_Rn::hs_ON);
402  }
403  }}
404  }}
405  }
406  //newGeneratorsTool.dump(std::cout);
407  for (newGeneratorsTool.begin(); newGeneratorsTool.end()!=true; newGeneratorsTool.next()) {
408 #ifdef DEBUG
409  std::cout << "NGB1= " << newGeneratorsTool.currentGenInNumber() << ", NGB2= " << newGeneratorsTool.currentGenOutNumber() << std::endl;
410 #endif
411  // Create a new Generator as a combination of currentGeneratorIn and currentGeneratorOut.
412  double ay = GN_OUT_sp[newGeneratorsTool.currentGenOutNumber()];
413  double az = GN_IN_sp[newGeneratorsTool.currentGenInNumber()];
414  // currentGeneratorIn and currentGeneratorOut are genuine neighbours.
415  const boost::shared_ptr<Generator_Rn_SD>& currentGeneratorIn = GN_IN[newGeneratorsTool.currentGenInNumber()];
416  const boost::shared_ptr<Generator_Rn_SD>& currentGeneratorOut = GN_OUT[newGeneratorsTool.currentGenOutNumber()];
417  // Mark the new as CREATED.
418  boost::shared_ptr<Generator_Rn_SD> newV(new Generator_Rn_SD(RnDIM, generatorNumber, Generator_Rn_SD::CREATED));
419  ++generatorNumber;
420  poly->createTruncatedGenerator(currentGeneratorOut, currentGeneratorIn, newV, ay, az, currentHalfSpace->getConstant());
421  // Fill in the list of facets for the new Generator.
422  std::vector< unsigned int > commonFacets;
423  // Get facets.
424  _redundancyProcessing.checkNeighbours(poly, currentGeneratorIn, currentGeneratorOut, commonFacets);
425  newV->setAllFacets(commonFacets);
426  // Do not add the current half-space at this step but wait a little bit more.
427 
428  // The new Generator is ready to be inserted in the data structure if not equal to
429  // another one with state ON.
430  bool notEq=true;
431  std::set< unsigned int > setOfFacets;
432  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON_eq;
433  {for (iteGN_ON_eq=GN_ON.begin(); iteGN_ON_eq!=GN_ON.end() && notEq==true; ++iteGN_ON_eq) {
434  if ((*iteGN_ON_eq)->isEqual2(newV, RnDIM, TOL2)) {
435  notEq = false;
436  // newV has no future so just transfer its facets to the current equal generator.
437  // Make sure not to include twice currentHalfSpace.
438  newV->exportFacets(setOfFacets);
439  (*iteGN_ON_eq)->exportFacets(setOfFacets);
440  (*iteGN_ON_eq)->importFacets(setOfFacets);
441  (*iteGN_ON_eq)->orderFacets();
442  }
443  }}
444  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_NEW_eq;
445  {for (iteGN_NEW_eq=GN_new.begin(); iteGN_NEW_eq!=GN_new.end() && notEq==true; ++iteGN_NEW_eq) {
446  if ((*iteGN_NEW_eq)->isEqual2(newV, RnDIM, TOL2)) {
447  notEq = false;
448  // newV has no future so just transfer its facets to the current equal generator.
449  newV->setFacet(halfspaceNumber);
450  newV->exportFacets(setOfFacets);
451  (*iteGN_NEW_eq)->exportFacets(setOfFacets);
452  (*iteGN_NEW_eq)->importFacets(setOfFacets);
453  (*iteGN_NEW_eq)->orderFacets();
454  }
455  }}
456  if (notEq == true) {
457  newV->setFacet(halfspaceNumber);
458  GN_new.push_back(newV);
459 #ifdef DEBUG
460  std::cout << "New Generator = [";
461  newV->save(std::cout);
462  std::cout << "] GeneratorIN [";
463  currentGeneratorIn->save(std::cout);
464  std::cout << "], VX_IN_sp=" << az << " GeneratorOUT [";
465  currentGeneratorOut->save(std::cout);
466  std::cout << "], VX_OUT_sp=" << ay << std::endl;
467 #endif
468  }
469  else {
470 #ifdef DEBUG
471  std::cout << "No new Generator as [";
472  newV->save(std::cout);
473  std::cout << "] is equal to a previous one." << std::endl;
474 #endif
475  }
476  } // for (newGeneratorsTool.begin(); newGeneratorsTool.end()!=true; newGeneratorsTool.next()) {
477 
478 #ifdef DEBUG
479  std::cout << "VX_OUT= " << GN_OUT.size() << std::endl;
480  std::cout << "VX_IN = " << GN_IN.size() << std::endl;
481  std::cout << "VX_ON = " << GN_ON.size() << std::endl;
482  std::cout << "redundantHS = " << redundantHS.size() << std::endl;
483  std::cout << "============================================" << std::endl;
484 #endif
485  // When we perform a flat truncation the set of generators IN
486  // . is transferred into the set of generators OUT as both of them will be dropped
487  // . then it is emptied before receiving the generators ON and NEW i.e. the ones we keep
488  // In the other case of an intersection with a half-space this function does nothing.
489  currentHalfSpace->prepareSetOfGenerators(GN_IN, GN_OUT);
490 
491  // All the generators with state ON must have a new facet.
492  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON;
493  for (iteGN_ON=GN_ON.begin(); iteGN_ON!=GN_ON.end(); ++iteGN_ON) {
494  (*iteGN_ON)->setFacet(halfspaceNumber);
495  if ((*iteGN_ON)->getStatus() == Generator_Rn_SD::CREATED)
496  (*iteGN_ON)->setStatus(Generator_Rn_SD::CREATED_AND_MODIFIED);
497  else if ((*iteGN_ON)->getStatus() == Generator_Rn_SD::UNCHANGED)
498  (*iteGN_ON)->setStatus(Generator_Rn_SD::MODIFIED);
499  // Insert the ON generators in the IN list as this list will be the official one soon.
500  GN_IN.push_back(*iteGN_ON);
501  }
502  // The current face must mark all the vertices with state ON.
503  // No need to do more than marking as all vertices ON are now embedded in GN_IN.
504  _redundancyProcessing.updateNumberOfVerticesPerHalfSpace(halfspaceNumber, GN_ON); // Deal with redundancy.
505 
506  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_new;
507  for (iteGN_new=GN_new.begin(); iteGN_new!=GN_new.end(); ++iteGN_new) {
508  // Insert the new generators in the IN list as this list will be the official one soon.
509  GN_IN.push_back(*iteGN_new);
510  _redundancyProcessing.incrementNumberForVerticesForHalfSpace(*iteGN_new); // Deal with redundancy.
511  }
512  // For the redundancy processing :
513  // . all the vertices with state NEW must have their face counter incremented++
514  // . all the vertices with state ON must have their face counter incremented++ (in a global way)
515  // . all the vertices with state OUT must have their face counter decremented--
516 
517  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_OUT;
518  for (iteGN_OUT=GN_OUT.begin(); iteGN_OUT!=GN_OUT.end(); ++iteGN_OUT) {
519  _redundancyProcessing.decrementNumberForVerticesForHalfSpace(*iteGN_OUT); // Deal with redundancy.
520  }
521 
522  _redundancyProcessing.updateListOfRedundantHalfSpaces(GN_IN, poly->numberOfGeneratorsPerFacet()); // Deal with redundancy.
523 
524  // Remove all the generators OUT and replace them with the set IN-ON-new.
525  listOfGenSD = GN_IN;
526 
527  } // else if (GN_IN.empty() != true) {
528 
529  GN_OUT_sp.clear();
530  GN_OUT.clear();
531  GN_IN_sp.clear();
532  GN_IN.clear();
533  GN_ON.clear();
534  GN_new.clear();
535  halfspaceNumber++;
536  //_redundancyProcessing.dumpSD(std::cout);
537  }} // for (iteHS.begin(); iteHS.end()!=true; iteHS.next()) {
538 
539  return true;
540  }
541 
542 
543  protected:
545  bool _isEmpty;
547  REDUNDANCY_PROCESSING _redundancyProcessing;
548 
549 };
550 
551 
552 
554 template< class POLYHEDRON > class NoRedundancyProcessing {
555  public:
557 
559 
561  virtual bool checkNeighbours(
562  POLYHEDRON poly,
563  const boost::shared_ptr<Generator_Rn>& genIn,
564  const boost::shared_ptr<Generator_Rn>& genOut,
565  std::vector< boost::shared_ptr<HalfSpace_Rn> >& commonFacets) {
566  return poly->checkNeighbours(genIn, genOut, commonFacets);
567  }
568 
570  virtual bool checkNeighbours(
571  POLYHEDRON poly,
572  const boost::shared_ptr<Generator_Rn_SD>& genIn,
573  const boost::shared_ptr<Generator_Rn_SD>& genOut,
574  std::vector< unsigned int >& commonFacets) {
575  return poly->checkNeighbours(genIn, genOut, commonFacets);
576  }
577 
578  void addHalfSpace(bool isHyperplane) {}
579 
581  unsigned int HS,
582  const std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_ON) {}
583 
585  virtual bool checkNeighbours(
586  POLYHEDRON poly,
587  const boost::shared_ptr<Generator_Rn>& genIn,
588  const boost::shared_ptr<Generator_Rn>& genOut,
589  std::vector< HalfSpace_Rn* >& commonFacets) {
590  return poly->checkNeighbours(genIn, genOut, commonFacets);
591  }
592 
594  void initNumberOfVerticesPerHalfSpace(const std::vector< boost::shared_ptr<Generator_Rn_SD> >&, unsigned int nbHS, unsigned int nbHP=0) {}
595 
597  void updateNumberOfVerticesPerHalfSpace(const boost::shared_ptr<HalfSpace_Rn>& , unsigned int) {}
598 
600  void updateNumberOfVerticesPerHalfSpace(const boost::shared_ptr<HalfSpace_Rn>& , const std::vector< boost::shared_ptr<Generator_Rn_SD> >&) {}
601 
603  void incrementNumberForVerticesForHalfSpace(const boost::shared_ptr<Generator_Rn_SD>&) {}
604 
606  void decrementNumberForVerticesForHalfSpace(const boost::shared_ptr<Generator_Rn_SD>&) {}
607 
609  void updateListOfRedundantHalfSpaces(const std::vector< boost::shared_ptr<Generator_Rn_SD> >& listOfGen, int numberOfGeneratorsPerFacet) {}
610 
611  void unhookRedundantHalfSpaces(POLYHEDRON) {}
612 
613  void unhookRedundantGenerators(POLYHEDRON) {}
614 
615  void dumpSD(std::ostream &this_stream) {}
616 
617 };
618 
619 
623 template< class POLYHEDRON > class StrongRedundancyProcessing {
624 
625  public:
627  _neigbourhoodCondition = ngbCond;
628  }
629 
631 
633  const POLYHEDRON,
634  std::vector< unsigned int >&,
635  std::set< unsigned int >& getListOfRedundantHS) {
636  getListOfRedundantHS = _listOfRedundantHS;
637  }
638 
640  void initNumberOfVerticesPerHalfSpace(const std::vector< boost::shared_ptr<Generator_Rn_SD> >& LG, unsigned int nbHS, unsigned int nbHP=0) {
642  _isHalfSpace.clear();
643  _listOfRedundantHS.clear();
646 
647  // First init to 0 to be able to increment
648  {for (unsigned int j=0; j<nbHS; ++j) {
649  _isHalfSpace.push_back(true);
650  }}
651 
652  //std::map< boost::shared_ptr<HalfSpace_Rn>, unsigned int >::const_iterator
653  //mit(numberOfVertexPerHalfSpace.begin()), mend(numberOfVertexPerHalfSpace.end());
654  //for (; mit!=mend; ++mit)
655  //std::cout << mit->first << '\t' << mit->second << std::endl;
656 
657  // Now deal with the set of vertices itself contained by the faces
658  // to see if a given set can be included into another one. But first of
659  // all set the list of back pointers.
660  {for (unsigned int j=0; j<nbHS; ++j) {
661  std::set< unsigned int > genSet;
662  _allGenPerLinearConstraint.push_back(genSet);
663  }}
664  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator constITER_GN;
665  for (constITER_GN=LG.begin(); constITER_GN!=LG.end(); ++constITER_GN) {
666  {for (unsigned int j=0; j<(*constITER_GN)->numberOfFacets(); j++) {
667  unsigned int F = (*constITER_GN)->getFacet(j);
668  // GenPerFacet: number(HalfSpace_Rn) => {Generator_Rn_SD_0*, Generator_Rn_SD_1*, Generator_Rn_SD_2*, ...}
669  // Fill the data structure storing all the generators for a given facet.
670  _allGenPerLinearConstraint[F].insert( (*constITER_GN)->getGeneratorNumber() );
671  }}
672  }
673  //dumpSD(std::cout);
674  }
675 
677  void addHalfSpace(bool isHyperplane) {
678  std::set< unsigned int > genSet;
679  _allGenPerLinearConstraint.push_back(genSet);
681  if (isHyperplane) {
683  _isHalfSpace.push_back(false);
684  }
685  else
686  _isHalfSpace.push_back(true);
687  //std::cout << "size _allGenPerLinearConstraint = " << _allGenPerLinearConstraint.size() << "size _isHalfSpace = " << _isHalfSpace.size() << "size _numberOfVerticesPerLinearConstraint = " << _numberOfVerticesPerLinearConstraint.size() << std::endl;
688  }
689 
692  unsigned int HS,
693  const std::vector< boost::shared_ptr<Generator_Rn_SD> >& GN_ON) {
694  std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_ON;
695  for (iteGN_ON=GN_ON.begin(); iteGN_ON!=GN_ON.end(); ++iteGN_ON)
696  _allGenPerLinearConstraint[ HS ].insert( (*iteGN_ON)->getGeneratorNumber() );
697  }
698 
700  void incrementNumberForVerticesForHalfSpace(const boost::shared_ptr<Generator_Rn_SD>& GEN) {
701  for (unsigned int l=0; l<GEN->numberOfFacets(); ++l) {
702  _allGenPerLinearConstraint[ GEN->getFacet(l) ].insert( GEN->getGeneratorNumber() );
703  }
704  }
705 
707  void decrementNumberForVerticesForHalfSpace(const boost::shared_ptr<Generator_Rn_SD>& GEN) {
708  for (unsigned int l=0; l<GEN->numberOfFacets(); ++l) {
709  _allGenPerLinearConstraint[ GEN->getFacet(l) ].erase( GEN->getGeneratorNumber() );
710  }
711  }
712 
716  POLYHEDRON poly,
717  const boost::shared_ptr<Generator_Rn_SD>& genIn,
718  const boost::shared_ptr<Generator_Rn_SD>& genOut,
719  std::vector< unsigned int >& commonFacets) {
720  // Compute the intersection on sorted lists of facets.
721  std::set_intersection(genIn->facetsBegin(), genIn->facetsEnd(), genOut->facetsBegin(), genOut->facetsEnd(),
722  std::inserter(commonFacets, commonFacets.end()));
723  // For polyhedral cones neigbourhoodCondition() is Rn::getDimension()-1, for polytopes it is Rn::getDimension()-2.
724  if (commonFacets.size() >= _neigbourhoodCondition)
725  return true;
726 
727  return false;
728  }
729 
732  void unhookThisRedundantHalfSpace(std::vector< boost::shared_ptr<Generator_Rn_SD> >& listOfGen,
733  unsigned int thisRedundantHS, unsigned int numberOfGeneratorsPerFacetWithoutHyp) {
734  unsigned int numberOfGeneratorsPerFacet = numberOfGeneratorsPerFacetWithoutHyp - _numberOfProcessedHyperplanes;
735  std::set< unsigned int >& allGenForThisRedundantHS = _allGenPerLinearConstraint[thisRedundantHS];
736  {
737  std::vector< boost::shared_ptr<Generator_Rn_SD> >::iterator itGN = listOfGen.begin();
738  while (itGN != listOfGen.end() || allGenForThisRedundantHS.empty() == false) {
739  if (allGenForThisRedundantHS.find((*itGN)->getGeneratorNumber()) != allGenForThisRedundantHS.end()) {
740  // This generator has to be modified as it is part of the list of generators that point to the redundant facet.
741  // The list of facets is ordered.
742  unsigned int indexOfFacet = 0;
743  while ((*itGN)->getFacet(indexOfFacet) < thisRedundantHS)
744  indexOfFacet++;
745  if ((*itGN)->getFacet(indexOfFacet) == thisRedundantHS) {
746  (*itGN)->removeFacet(indexOfFacet);
747  }
748  else {
749  std::cerr << "indexOfGen = " << itGN-listOfGen.begin() << std::endl;
750  std::cerr << "indexOfFacet = " << indexOfFacet<< std::endl;
751  std::cerr << (*itGN)->vect() << std::endl;
752  std::cerr << "thisRedundantHS = " << thisRedundantHS << std::endl;
753  std::string errorMessage("StrongRedundancyProcessing::unhookThisRedundantHalfSpace() Facet not found.");
754  throw std::out_of_range(errorMessage);
755  }
756  allGenForThisRedundantHS.erase((*itGN)->getGeneratorNumber() );
757  // May be the generator that lost a linear constraint does not hold anymore the right number of contstraints?
758  if ((*itGN)->numberOfFacets() < numberOfGeneratorsPerFacet) {
759  unsigned int genNb = (*itGN)->getGeneratorNumber();
760  {
761  for (unsigned int idFct=0; idFct<(*itGN)->numberOfFacets(); ++idFct) {
762  // Run the list of linear constraints to remove genNb each time it is present.
763  _allGenPerLinearConstraint[ (*itGN)->getFacet(idFct) ].erase(genNb);
764  }
765  }
766  // An iterator pointing to the new location of the element that followed the last element erased by the function call.
767  // This is the container end if the operation erased the last element in the sequence.
768  itGN = listOfGen.erase(itGN);
769  }
770  else
771  itGN++;
772  }
773  else
774  itGN++;
775  }
776  }
777 
778  if (_allGenPerLinearConstraint[thisRedundantHS].empty() == false) {
779  std::cerr << std::endl << "Remaining generators: ";
780  std::copy(_allGenPerLinearConstraint[thisRedundantHS].begin(), _allGenPerLinearConstraint[thisRedundantHS].end(), std::ostream_iterator<unsigned int>(std::cerr, " ") );
781  std::cerr << std::endl;
782  std::string errorMessage("StrongRedundancyProcessing::unhookThisRedundantHalfSpace() Remaining generators.");
783  throw std::domain_error(errorMessage);
784  }
785 
786  //std::cout << "Leaving unhookThisRedundantHalfSpace()" << std::endl;
787  }
788  // number(HalfSpace_Rn1) => {Generator_Rn0*, Generator_Rn1*, Generator_Rn2*, ...}
789  // number(HalfSpace_Rn2) => {Generator_Rn3*, Generator_Rn4*, Generator_Rn5*, ...}
790  // ...
791 
794  virtual void updateListOfRedundantHalfSpaces(std::vector< boost::shared_ptr<Generator_Rn_SD> >& listOfGen, int numberOfGeneratorsPerFacetWithoutHyp) {
795  // Take into account the case where we have hyperplanes.
796  // NB: in the future do not only take into account the number of hyperplanes but also the
797  // dimension of the space they create intersecting each other. Here we make the assumption
798  // we have a full rank matrix.
799  unsigned int numberOfGeneratorsPerFacet = numberOfGeneratorsPerFacetWithoutHyp - _numberOfProcessedHyperplanes;
800  //std::cout << "poly->numberOfGeneratorsPerFacet() " << poly->numberOfGeneratorsPerFacet() << std::endl;
801  //std::cout << "numberOfGeneratorsPerFacet = " << numberOfGeneratorsPerFacet << ", _numberOfProcessedHyperplanes = " << _numberOfProcessedHyperplanes << std::endl;
802  //std::cout << "_numberOfVerticesPerLinearConstraint.size() = " << _numberOfVerticesPerLinearConstraint.size() << std::endl;
803  {for (unsigned int i=0; i<_allGenPerLinearConstraint.size(); ++i) {
804  // Stop when we reach the current half-space being processed, it was the last inserted.
805  //std::cout << "_numberOfVerticesPerLinearConstraint[i] = " << _numberOfVerticesPerLinearConstraint[i] << std::endl;
806  if (_allGenPerLinearConstraint[i].size() < numberOfGeneratorsPerFacet) {
807  if (_listOfRedundantHS.insert( i ).second == true) {
808 #ifdef DEBUG
809  std::cout << "Redundant " << i;
810  std::cout << std::endl;
811 #endif
812  }
813  }
814  }}
815 
820 
821  // Now we've checked that half-spaces have the correct minimum number of generators we need to
822  // perform a more complicated task. Run the list to see if a set of generators can be included
823  // into another one. In this case, and if we don't deal with flat polytopes or polyhedra,
824  // it means that the current half-space is redundant.
825  {
826  unsigned int i1,i2;
827  std::vector< std::set< unsigned int > >::const_iterator it_1, it_2;
828  for (it_1=_allGenPerLinearConstraint.begin(), i1=0; it_1!=_allGenPerLinearConstraint.end(); ++it_1, ++i1) {
829  for (it_2=_allGenPerLinearConstraint.begin(), i2=0; it_2!=_allGenPerLinearConstraint.end(); ++it_2, ++i2) {
830  if (it_1!=it_2 &&
831  _isHalfSpace[i1] == true && _isHalfSpace[i2] == true &&
832  _listOfRedundantHS.find(i1)==_listOfRedundantHS.end() && _listOfRedundantHS.find(i2)==_listOfRedundantHS.end()) {
833  if (it_1->size() > it_2->size()) {
834  if (std::includes(it_1->begin(), it_1->end(), it_2->begin(), it_2->end())) {
835  // We have it_2 \subset it_1.
836  _listOfRedundantHS.insert(i2);
837  unhookThisRedundantHalfSpace(listOfGen, i2, numberOfGeneratorsPerFacetWithoutHyp);
838 #ifdef DEBUG
839  std::cout << "New redundant facet: " << i2 << std::endl;
840 #endif
841  }
842  }
843  else if (it_1->size() < it_2->size()) {
844  if (std::includes(it_2->begin(), it_2->end(), it_1->begin(), it_1->end())) {
845  // We have it_1 \subset it_2.
846  _listOfRedundantHS.insert(i1);
847  unhookThisRedundantHalfSpace(listOfGen, i1, numberOfGeneratorsPerFacetWithoutHyp);
848 #ifdef DEBUG
849  std::cout << "New redundant facet: " << i1 << std::endl;
850 #endif
851  }
852  }
853  else {
854  // Unnecessary check for equality
855  }
856  }
857  }
858  }
859  }
860 
861  }
862 
863  void unhookRedundantHalfSpaces(POLYHEDRON poly) {
864  //fillListOfRedundantHS( poly );
865  // Unhook redundant half-spaces from the vertices.
866  unsigned int hsNb;
867  if (!_listOfRedundantHS.empty()) {
869  {for (iteHS.begin(), hsNb=0; iteHS.end()!=true; iteHS.next(), ++hsNb) {
870  if (_listOfRedundantHS.find(hsNb) != _listOfRedundantHS.end()) {
871  // We have a genuine redundant half-space.
873  {for (iteGN.begin(); iteGN.end()!=true; iteGN.next()) {
874  boost::shared_ptr<Generator_Rn> gen = iteGN.current();
875  {for (int j=gen->numberOfFacets()-1; j>=0; j--) {
876  if (iteHS.current() == gen->getFacet(j))
877  gen->removeFacet(j);
878  }}
879  }}
880  }
881  }}
882  }
883  // Add to the list of redundant half-spaces the ones which are not
884  // referenced at all by vertices from the beginning of the process.
886  {for (iteHS2.begin(), hsNb=0; iteHS2.end()!=true; iteHS2.next(), ++hsNb) {
887  if (_listOfRedundantHS.find(hsNb) == _listOfRedundantHS.end()) {
888  //std::cout << "_numberOfVerticesPerLinearConstraint[] = " << _numberOfVerticesPerLinearConstraint[hsNb] << std::endl;
889  if (_allGenPerLinearConstraint[hsNb].size() == 0) {
890  // The half-space has not been found so it's not in use at all and is redundant.
891  _listOfRedundantHS.insert(hsNb);
892  }
893  }
894  }}
895  if (!_listOfRedundantHS.empty()) {
896 #ifdef DEBUG
897  std::cout << "Remove " << _listOfRedundantHS.size() << " redundant facets: ";
898 #endif
899  std::vector< unsigned int > HS2Remove;
900  std::set< unsigned int >::const_iterator it;
901  {for (it=_listOfRedundantHS.begin(); it!=_listOfRedundantHS.end(); ++it) {
902 #ifdef DEBUG
903  std::cout << *it << " ";
904 #endif
905  HS2Remove.push_back(*it);
906  }}
907  std::sort(HS2Remove.begin(), HS2Remove.end(), std::greater<unsigned int>());
908  std::vector< unsigned int >::const_iterator it2;
909  {for (it2=HS2Remove.begin(); it2!=HS2Remove.end(); ++it2) {
910  // Do not forget to begin by the bigger to remove as we could change the ordering.
911  poly->removeHalfSpace(*it2);
912  }}
913 #ifdef DEBUG
914  std::cout << std::endl;
915 #endif
916  }
917  }
918 
921  void unhookRedundantGenerators(POLYHEDRON poly) {
922  unsigned int minNbFacetsPerGen = poly->neigbourhoodCondition() + 1;
923  std::set< boost::shared_ptr<Generator_Rn> > setToRemove;
925  {for (iteGN.begin(); iteGN.end()!=true; iteGN.next()) {
926  //std::cout << "gen->numberOfFacets() = " << iteGN.current()->numberOfFacets();
927  if (iteGN.current()->numberOfFacets() < minNbFacetsPerGen) {
928  setToRemove.insert( iteGN.current() );
929  //std::cout << " removed! ";
930  }
931  }}
932  if (!setToRemove.empty())
933  poly->removeGenerators(setToRemove);
934  //std::cout << std::endl;
935  }
936 
937  // Mark as UNCHANGED, CREATED or DELETED the half-spaces going through the double description process.
938  void markHdescription(TrackingOperatorToResult& trackerHdesc, unsigned int truncationStep) {
940  // Before truncation step they are UNCHANGED by default, then they are CREATED by default.
941  for (unsigned int i=0; i<truncationStep; ++i)
942  trackerHdesc.setOperatorEntityAsUnchanged(i);
943  for (unsigned int i=truncationStep; i<_numberOfProcessedLinearConstraints; ++i)
944  trackerHdesc.setResultEntityAsCreated(i);
945  std::set< unsigned int >::const_iterator iteRED=_listOfRedundantHS.begin();
946  for ( ; iteRED!=_listOfRedundantHS.end(); ++iteRED)
947  trackerHdesc.setOperatorEntityAsDeleted(*iteRED);
948  }
949 
950  void dumpListOfRedundantHS(POLYHEDRON poly, std::ostream &this_stream) {
951  unsigned int RnDIM=poly->dimension();
952  this_stream << "List of redundant half-spaces :" << std::endl;
953  unsigned int hsNb;
954  if (!_listOfRedundantHS.empty()) {
956  {for (iteHS.begin(), hsNb=0; iteHS.end()!=true; iteHS.next(), ++hsNb) {
957  if (_listOfRedundantHS.find(hsNb) != _listOfRedundantHS.end()) {
958  boost::shared_ptr<HalfSpace_Rn> currentHalfSpace = iteHS.current();
959  this_stream << "H = (" << currentHalfSpace->getConstant() << ", ";
960  {for (unsigned int ii=0; ii<RnDIM; ii++) {
961  this_stream << currentHalfSpace->getCoefficient(ii);
962  if (ii != RnDIM-1)
963  this_stream << ", ";
964  }}
965  this_stream << ")" << std::endl;
966  }
967  }}
968  }
969  }
970 
971  void dumpSD(std::ostream &this_stream) {
972  std::vector< std::set< unsigned int > >::const_iterator iteGHS;
973  this_stream << "*** number(HalfSpace_Rn0) => {Generator_Rn0*, Generator_Rn1*, Generator_Rn2*, ...}" << std::endl;
974  unsigned int counter=0;
975  {for (iteGHS=_allGenPerLinearConstraint.begin(); iteGHS!=_allGenPerLinearConstraint.end(); ++iteGHS) {
976  this_stream << counter << " => { ";
977  std::copy(iteGHS->begin(), iteGHS->end(), std::ostream_iterator<unsigned int>(std::cout, " ") );
978  this_stream << "}" << std::endl;
979  ++counter;
980  }}
981  //this_stream << "*** number of generators per half-spaces : ";
982  //std::copy(_allGenPerLinearConstraint.begin(), _allGenPerLinearConstraint.end(), std::ostream_iterator<unsigned int>(std::cout, " ") );
983  this_stream << std::endl;
984  this_stream << "*** list of redundant half-spaces : ";
985  std::copy(_listOfRedundantHS.begin(), _listOfRedundantHS.end(), std::ostream_iterator<unsigned int>(std::cout, " ") );
986  this_stream << std::endl;
987  }
988 
989  protected:
990  // Deal with the number of generators per half-space.
992  // number(HalfSpace_Rn0) => {Generator_Rn0*, Generator_Rn1*, Generator_Rn2*, ...}
993  std::vector< std::set< unsigned int > > _allGenPerLinearConstraint;
995  std::vector< bool > _isHalfSpace;
997  std::set< unsigned int > _listOfRedundantHS;
1004 };
1005 
1006 #endif
UpdDoubleDescription::~UpdDoubleDescription
virtual ~UpdDoubleDescription()
Definition: UpdDoubleDescription_Rn.h:168
HalfSpace_Rn::hs_OUT
@ hs_OUT
Definition: HalfSpace_Rn.h:47
StrongRedundancyProcessing::addHalfSpace
void addHalfSpace(bool isHyperplane)
Make space for a new half-space.
Definition: UpdDoubleDescription_Rn.h:677
HalfSpace_Rn::hs_UNKNOWN
@ hs_UNKNOWN
Definition: HalfSpace_Rn.h:48
NoRedundancyProcessing::decrementNumberForVerticesForHalfSpace
void decrementNumberForVerticesForHalfSpace(const boost::shared_ptr< Generator_Rn_SD > &)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:606
UpdDoubleDescription::getIsEmpty
bool getIsEmpty() const
Definition: UpdDoubleDescription_Rn.h:170
UpdDoubleDescription::compute
bool compute(POLYHEDRON poly, ITERATOR iteHS, int truncationStep, std::vector< boost::shared_ptr< Generator_Rn_SD > > &listOfGenSD)
The main function splitting the polyhedron cone or polytope 1-skeleton with a list of half-spaces.
Definition: UpdDoubleDescription_Rn.h:238
Neighbours_Rn.h
TrackingOperatorToResult::setResult_Operator
void setResult_Operator(unsigned int nbRes, int nb)
Set the link between the nb-th entity of operator1 and the nbRes-th entity of the result.
Definition: Tracking.h:89
TrackingOperatorToResult::setResultEntityAsUnchanged
void setResultEntityAsUnchanged(unsigned int nb)
Mark as Result_UNCHANGED the nb-th entity before the operation.
Definition: Tracking.h:67
StrongRedundancyProcessing::_allGenPerLinearConstraint
std::vector< std::set< unsigned int > > _allGenPerLinearConstraint
Store all raw back pointers to know which vertices belong to a given half-space.
Definition: UpdDoubleDescription_Rn.h:993
StrongRedundancyProcessing::unhookRedundantGenerators
void unhookRedundantGenerators(POLYHEDRON poly)
Definition: UpdDoubleDescription_Rn.h:921
StrongRedundancyProcessing::~StrongRedundancyProcessing
virtual ~StrongRedundancyProcessing()
Definition: UpdDoubleDescription_Rn.h:630
Neighbours_Rn::end
bool end() const
Iterator function.
Definition: Neighbours_Rn.h:151
HalfSpace_Rn::hs_IN
@ hs_IN
Definition: HalfSpace_Rn.h:46
StrongRedundancyProcessing::fillListOfRedundantHS
void fillListOfRedundantHS(const POLYHEDRON, std::vector< unsigned int > &, std::set< unsigned int > &getListOfRedundantHS)
Definition: UpdDoubleDescription_Rn.h:632
NoRedundancyProcessing::addHalfSpace
void addHalfSpace(bool isHyperplane)
Definition: UpdDoubleDescription_Rn.h:578
Generator_Rn_SD::CREATED_AND_MODIFIED
@ CREATED_AND_MODIFIED
Definition: Generator_Rn.h:293
NoRedundancyProcessing::unhookRedundantGenerators
void unhookRedundantGenerators(POLYHEDRON)
Definition: UpdDoubleDescription_Rn.h:613
StrongRedundancyProcessing::_neigbourhoodCondition
unsigned int _neigbourhoodCondition
To define the relation between generators.
Definition: UpdDoubleDescription_Rn.h:1003
StrongRedundancyProcessing::initNumberOfVerticesPerHalfSpace
void initNumberOfVerticesPerHalfSpace(const std::vector< boost::shared_ptr< Generator_Rn_SD > > &LG, unsigned int nbHS, unsigned int nbHP=0)
Make sure all back pointers from half-spaces to vertices are set.
Definition: UpdDoubleDescription_Rn.h:640
UpdDoubleDescription::computeVertexStates
void computeVertexStates(std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_list, const boost::shared_ptr< HalfSpace_Rn > &currentHalfSpace, std::vector< double > &GN_IN_sp, std::vector< double > &GN_OUT_sp, std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_IN, std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_OUT, std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_ON)
For each generator compute its state according to the current half-space.
Definition: UpdDoubleDescription_Rn.h:173
HalfSpace_Rn::hs_IN_OR_OUT
@ hs_IN_OR_OUT
Definition: HalfSpace_Rn.h:49
StrongRedundancyProcessing::_numberOfProcessedLinearConstraints
unsigned int _numberOfProcessedLinearConstraints
The total number of processed half-spaces.
Definition: UpdDoubleDescription_Rn.h:999
StrongRedundancyProcessing::unhookThisRedundantHalfSpace
void unhookThisRedundantHalfSpace(std::vector< boost::shared_ptr< Generator_Rn_SD > > &listOfGen, unsigned int thisRedundantHS, unsigned int numberOfGeneratorsPerFacetWithoutHyp)
Definition: UpdDoubleDescription_Rn.h:732
Generator_Rn_SD::Status
Status
Definition: Generator_Rn.h:285
TrackingOperatorToResult::setOperatorEntityAsDeleted
void setOperatorEntityAsDeleted(unsigned int nb)
Mark as Operator_DELETED the nb-th entity before the operation.
Definition: Tracking.h:64
NoRedundancyProcessing::initNumberOfVerticesPerHalfSpace
void initNumberOfVerticesPerHalfSpace(const std::vector< boost::shared_ptr< Generator_Rn_SD > > &, unsigned int nbHS, unsigned int nbHP=0)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:594
StrongRedundancyProcessing::StrongRedundancyProcessing
StrongRedundancyProcessing(unsigned int ngbCond)
Definition: UpdDoubleDescription_Rn.h:626
StrongRedundancyProcessing::_listOfRedundantHS
std::set< unsigned int > _listOfRedundantHS
To know whether an half-space has been ticked redundant or not.
Definition: UpdDoubleDescription_Rn.h:997
StrongRedundancyProcessing::dumpSD
void dumpSD(std::ostream &this_stream)
Definition: UpdDoubleDescription_Rn.h:971
NoRedundancyProcessing::updateNumberOfVerticesPerHalfSpace
void updateNumberOfVerticesPerHalfSpace(const boost::shared_ptr< HalfSpace_Rn > &, unsigned int)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:597
StrongRedundancyProcessing::incrementNumberForVerticesForHalfSpace
void incrementNumberForVerticesForHalfSpace(const boost::shared_ptr< Generator_Rn_SD > &GEN)
Make sure all the half-spaces belonging to a given generator have their vertices number incremented.
Definition: UpdDoubleDescription_Rn.h:700
Neighbours_Rn::currentGenInNumber
unsigned int currentGenInNumber() const
Iterator function.
Definition: Neighbours_Rn.h:154
Generator_Rn_SD::MODIFIED
@ MODIFIED
Definition: Generator_Rn.h:289
NoRedundancyProcessing::checkNeighbours
virtual bool checkNeighbours(POLYHEDRON poly, const boost::shared_ptr< Generator_Rn > &genIn, const boost::shared_ptr< Generator_Rn > &genOut, std::vector< boost::shared_ptr< HalfSpace_Rn > > &commonFacets)
Check whether two generators are neighbors in the context of not taking into account redundancy.
Definition: UpdDoubleDescription_Rn.h:561
NoRedundancyProcessing::updateNumberOfVerticesPerHalfSpace
void updateNumberOfVerticesPerHalfSpace(const boost::shared_ptr< HalfSpace_Rn > &, const std::vector< boost::shared_ptr< Generator_Rn_SD > > &)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:600
Neighbours_Rn::next
void next()
Iterator function.
Definition: Neighbours_Rn.h:142
Neighbours_Rn::begin
void begin()
Iterator function.
Definition: Neighbours_Rn.h:139
TrackingOperatorToResult::setNumbersOfEntities
void setNumbersOfEntities(unsigned int nbEntBefore, unsigned int nbEntAfter)
Definition: Tracking.h:47
UpdDoubleDescription::_isEmpty
bool _isEmpty
Store the current state of the intersection.
Definition: UpdDoubleDescription_Rn.h:545
constIteratorOfListOfGeometricObjects::current
const GEOMETRIC_OBJECT current()
Return the current geometric element.
Definition: GeometricObjectIterator_Rn.h:177
UpdDoubleDescription::_redundancyProcessing
REDUNDANCY_PROCESSING _redundancyProcessing
This class is dedicated to dealing with redundant half-spaces with the desired policy.
Definition: UpdDoubleDescription_Rn.h:547
StrongRedundancyProcessing::markHdescription
void markHdescription(TrackingOperatorToResult &trackerHdesc, unsigned int truncationStep)
Definition: UpdDoubleDescription_Rn.h:938
Neighbours_Rn
Class dedicated to degeneration processing when looking for neighbours. Let A be a polytope of wher...
Definition: Neighbours_Rn.h:59
NoRedundancyProcessing::~NoRedundancyProcessing
virtual ~NoRedundancyProcessing()
Definition: UpdDoubleDescription_Rn.h:558
StrongRedundancyProcessing::updateListOfRedundantHalfSpaces
virtual void updateListOfRedundantHalfSpaces(std::vector< boost::shared_ptr< Generator_Rn_SD > > &listOfGen, int numberOfGeneratorsPerFacetWithoutHyp)
Definition: UpdDoubleDescription_Rn.h:794
constIteratorOfListOfGeometricObjects::end
bool end() const
Tell whether we have reached the end of the list.
Definition: GeometricObjectIterator_Rn.h:174
Neighbours_Rn::addGenerator
void addGenerator(const std::vector< unsigned int > &commonFacets, unsigned int numbergenIN, unsigned int numbergenOUT, HalfSpace_Rn::State state)
Tell whether a pseudo neighbor is a genuine one comparing set of half-spaces.
Definition: Neighbours_Rn.h:69
Neighbours_Rn::currentGenOutNumber
unsigned int currentGenOutNumber() const
Iterator function.
Definition: Neighbours_Rn.h:157
TrackingOperatorToResult::setResultEntityAsCreated
void setResultEntityAsCreated(unsigned int nb)
Mark as Result_CREATED the nb-th entity after the operation.
Definition: Tracking.h:76
NoRedundancyProcessing::incrementNumberForVerticesForHalfSpace
void incrementNumberForVerticesForHalfSpace(const boost::shared_ptr< Generator_Rn_SD > &)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:603
StrongRedundancyProcessing::checkNeighbours
bool checkNeighbours(POLYHEDRON poly, const boost::shared_ptr< Generator_Rn_SD > &genIn, const boost::shared_ptr< Generator_Rn_SD > &genOut, std::vector< unsigned int > &commonFacets)
Definition: UpdDoubleDescription_Rn.h:715
TrackingOperatorToResult::setOperatorEntityAsUnchanged
void setOperatorEntityAsUnchanged(unsigned int nb)
Mark as Operator_UNCHANGED the nb-th entity before the operation.
Definition: Tracking.h:58
Generator_Rn_SD::CREATED
@ CREATED
Definition: Generator_Rn.h:291
StrongRedundancyProcessing::dumpListOfRedundantHS
void dumpListOfRedundantHS(POLYHEDRON poly, std::ostream &this_stream)
Definition: UpdDoubleDescription_Rn.h:950
HalfSpace_Rn::getStateAsText
static std::string getStateAsText(const HalfSpace_Rn::State &)
Definition: HalfSpace_Rn.cpp:55
NoRedundancyProcessing
Makes the assumption we do not need to process redundant half-spaces in a specific way.
Definition: UpdDoubleDescription_Rn.h:554
constIteratorOfListOfGeometricObjects
This class is designed to run the list of all geometric objects representing a polytope.
Definition: GeometricObjectIterator_Rn.h:142
NoRedundancyProcessing::checkNeighbours
virtual bool checkNeighbours(POLYHEDRON poly, const boost::shared_ptr< Generator_Rn_SD > &genIn, const boost::shared_ptr< Generator_Rn_SD > &genOut, std::vector< unsigned int > &commonFacets)
Check whether two generators are neighbors in the context of not taking into account redundancy.
Definition: UpdDoubleDescription_Rn.h:570
UpdDoubleDescription
The algorithm implemented here is an incremental algorithm as mentioned in How Good are Convex Hull ...
Definition: UpdDoubleDescription_Rn.h:50
HalfSpace_Rn::State
State
Definition: HalfSpace_Rn.h:44
UpdDoubleDescription::UpdDoubleDescription
UpdDoubleDescription(POLYHEDRON poly, ITERATOR ite, REDUNDANCY_PROCESSING redproc, int truncationStep, TrackingOperatorToResult &trackerVdesc, TrackingOperatorToResult &trackerHdesc)
Definition: UpdDoubleDescription_Rn.h:94
StrongRedundancyProcessing::decrementNumberForVerticesForHalfSpace
void decrementNumberForVerticesForHalfSpace(const boost::shared_ptr< Generator_Rn_SD > &GEN)
Make sure all the half-spaces belonging to a given generator have their vertices number decremented.
Definition: UpdDoubleDescription_Rn.h:707
Generator_Rn_SD
A n-coordinates generator for internal data structure. It can be a vertex or an edge whether it is em...
Definition: Generator_Rn.h:280
StrongRedundancyProcessing::updateNumberOfVerticesPerHalfSpace
void updateNumberOfVerticesPerHalfSpace(unsigned int HS, const std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_ON)
The current face must mark all the vertices with state ON.
Definition: UpdDoubleDescription_Rn.h:691
constIteratorOfListOfGeometricObjects::begin
void begin()
Move the iterator at the beginning of the list.
Definition: GeometricObjectIterator_Rn.h:150
NoRedundancyProcessing::NoRedundancyProcessing
NoRedundancyProcessing()
Definition: UpdDoubleDescription_Rn.h:556
UpdDoubleDescription::UpdDoubleDescription
UpdDoubleDescription(POLYHEDRON poly, ITERATOR ite, REDUNDANCY_PROCESSING redproc, int truncationStep)
Definition: UpdDoubleDescription_Rn.h:53
Tracking.h
StrongRedundancyProcessing::unhookRedundantHalfSpaces
void unhookRedundantHalfSpaces(POLYHEDRON poly)
Definition: UpdDoubleDescription_Rn.h:863
HalfSpace_Rn::hs_ON
@ hs_ON
Definition: HalfSpace_Rn.h:45
TrackingOperatorToResult::setOperator_Result
void setOperator_Result(unsigned int nb, int nbRes)
Set the link between the nb-th entity of operator1 and the nbRes-th entity of the result.
Definition: Tracking.h:86
StrongRedundancyProcessing
This class can be more time-consuming than WeakRedundancyProcessing or NoRedundancyProcessing because...
Definition: UpdDoubleDescription_Rn.h:623
TrackingOperatorToResult::setOperatorEntityAsModified
void setOperatorEntityAsModified(unsigned int nb)
Mark as Operator_MODIFIED the nb-th entity before the operation.
Definition: Tracking.h:61
NoRedundancyProcessing::unhookRedundantHalfSpaces
void unhookRedundantHalfSpaces(POLYHEDRON)
Definition: UpdDoubleDescription_Rn.h:611
NoRedundancyProcessing::updateListOfRedundantHalfSpaces
void updateListOfRedundantHalfSpaces(const std::vector< boost::shared_ptr< Generator_Rn_SD > > &listOfGen, int numberOfGeneratorsPerFacet)
Only useful in the case of dealing and processing redundancy.
Definition: UpdDoubleDescription_Rn.h:609
NoRedundancyProcessing::checkNeighbours
virtual bool checkNeighbours(POLYHEDRON poly, const boost::shared_ptr< Generator_Rn > &genIn, const boost::shared_ptr< Generator_Rn > &genOut, std::vector< HalfSpace_Rn * > &commonFacets)
Check whether two generators are neighbors in the context of not taking into account redundancy.
Definition: UpdDoubleDescription_Rn.h:585
constIteratorOfListOfGeometricObjects::next
void next()
Move the iterator one step forward.
Definition: GeometricObjectIterator_Rn.h:153
Generator_Rn_SD::UNCHANGED
@ UNCHANGED
Definition: Generator_Rn.h:287
NoRedundancyProcessing::dumpSD
void dumpSD(std::ostream &this_stream)
Definition: UpdDoubleDescription_Rn.h:615
StrongRedundancyProcessing::_numberOfProcessedHyperplanes
unsigned int _numberOfProcessedHyperplanes
The total number of processed hyperplanes.
Definition: UpdDoubleDescription_Rn.h:1001
TrackingOperatorToResult::setResultEntityAsModified
void setResultEntityAsModified(unsigned int nb)
Mark as Result_MODIFIED the nb-th entity after the operation.
Definition: Tracking.h:70
StrongRedundancyProcessing::_isHalfSpace
std::vector< bool > _isHalfSpace
Tell if a linear constraint is a half-space or a hyperplane.
Definition: UpdDoubleDescription_Rn.h:995
Rn::getTolerance
static polito_EXPORT double getTolerance()
Give the minimum distance between two points.
Definition: Rn.cpp:31
TrackingOperatorToResult
This class stores static function that dispatch the main geometric values we use.
Definition: Tracking.h:41
NoRedundancyProcessing::updateNumberOfVerticesPerHalfSpace
void updateNumberOfVerticesPerHalfSpace(unsigned int HS, const std::vector< boost::shared_ptr< Generator_Rn_SD > > &GN_ON)
Definition: UpdDoubleDescription_Rn.h:580