21 #ifndef POLYHEDRALCONE_Rn
22 #define POLYHEDRALCONE_Rn
24 #include <boost/numeric/ublas/io.hpp>
25 #include <boost/shared_ptr.hpp>
39 using namespace boost::numeric::ublas;
46 friend class lexIteratorOfListOfHalfSpaces;
47 friend class constIteratorOfListOfHalfSpaces;
64 if (numberOfHalfSpaces()==0 && numberOfGenerators()==0)
66 else if (numberOfGenerators()==0) {
68 const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace = iteHS.
current();
69 return currentHalfSpace->dimension();
73 const boost::shared_ptr<Generator_Rn>& currentGenerator = iteGN.
current();
74 return currentGenerator->dimension();
88 void reset() {_listOfHalfSpaces.clear(); _listOfGenerators.clear();}
96 boost::shared_ptr<HalfSpace_Rn> addHalfSpace(boost::shared_ptr<HalfSpace_Rn> hs,
bool check=
false);
99 void removeHalfSpaceFromListAndGenerators(
const boost::shared_ptr<HalfSpace_Rn>& hs)
throw (std::invalid_argument);
105 void removeHalfSpaces(
const std::set< boost::shared_ptr<HalfSpace_Rn> >& setOfRedundantHS) {
106 _listOfHalfSpaces.removeGeometricObjects( setOfRedundantHS );
110 unsigned int getHalfSpaceNumber(
const boost::shared_ptr<HalfSpace_Rn>& F)
const throw (std::out_of_range) {
113 index = _listOfHalfSpaces.find(F);
115 catch(std::out_of_range& excep) {
116 std::string ex(excep.what());
117 ex += std::string(
" : Catch in PolyhedralCone_Rn::getHalfSpaceNumber()");
118 throw std::out_of_range(ex);
124 const boost::shared_ptr<HalfSpace_Rn>& getHalfSpace(
unsigned int i)
const throw (std::out_of_range);
139 void addGenerator(boost::shared_ptr<Generator_Rn> vx) {_listOfGenerators.push_back(vx);}
142 const boost::shared_ptr<Generator_Rn>& getGenerator(
unsigned int i)
const throw (std::out_of_range);
145 unsigned int getGeneratorNumber(boost::shared_ptr<Generator_Rn> G)
const throw (std::out_of_range,std::invalid_argument);
151 unsigned int generatorNumber=0;
154 boost::shared_ptr<Generator_Rn_SD>
156 {
for (
unsigned int ii=0; ii<iteGN.
current()->numberOfFacets(); ii++) {
157 unsigned int fctNumber = getHalfSpaceNumber( iteGN.
current()->getFacet(ii) );
158 currentGeneratorSD->setFacet(fctNumber);
160 currentGeneratorSD->orderFacets();
161 currentListOfGeneratorsSD.push_back(currentGeneratorSD);
164 return generatorNumber;
170 std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN;
171 {
for (iteGN=gnList.begin(); iteGN!=gnList.end(); ++iteGN) {
174 boost::shared_ptr<Generator_Rn> currentGenerator = (*iteGN)->makeGenerator_Rn();
175 {
for (
unsigned int ii=0; ii<(*iteGN)->numberOfFacets(); ii++) {
176 currentGenerator->setFacet( _listOfHalfSpaces[(*iteGN)->getFacet(ii)] );
178 listOfGenerators.
push_back( currentGenerator );
182 unsigned int nbGN = (*iteGN)->getGeneratorNumber();
183 boost::shared_ptr<Generator_Rn> currentGenerator = _listOfGenerators[nbGN];
184 currentGenerator->clearFacets();
185 {
for (
unsigned int ii=0; ii<(*iteGN)->numberOfFacets(); ii++) {
186 currentGenerator->setFacet( _listOfHalfSpaces[(*iteGN)->getFacet(ii)] );
188 listOfGenerators.
push_back(_listOfGenerators[nbGN]);
192 unsigned int nbGN = (*iteGN)->getGeneratorNumber();
193 listOfGenerators.
push_back(_listOfGenerators[nbGN]);
197 _listOfGenerators.clear();
198 _listOfGenerators = listOfGenerators;
201 void relocateGenerators();
216 const boost::shared_ptr<Generator_Rn>& V2,
217 std::vector< boost::shared_ptr<HalfSpace_Rn> >& commonFacets,
218 const std::set< boost::shared_ptr<HalfSpace_Rn> >& listOfRedundantHS)
const throw (std::invalid_argument) {
219 unsigned int sameHyperplane=0;
220 for (
unsigned int i=0; i<V1->numberOfFacets(); i++) {
221 for (
unsigned int j=0; j<V2->numberOfFacets(); j++) {
222 if (V1->getRawFacet(i)==V2->getRawFacet(j) && listOfRedundantHS.find(V1->getFacet(i))==listOfRedundantHS.end()) {
225 commonFacets.push_back(V1->getFacet(i));
230 if (sameHyperplane >= neigbourhoodCondition())
238 bool isIncluded(
const boost::shared_ptr<PolyhedralCone_Rn>& B)
const;
247 const boost::shared_ptr<Generator_Rn>& V2,
248 std::vector< boost::shared_ptr<HalfSpace_Rn> >& commonFacets,
249 unsigned int topologicalCode=1)
const throw (std::invalid_argument) {
250 unsigned int sameHyperplane=0;
251 for (
unsigned int i=0; i<V1->numberOfFacets(); i++) {
252 for (
unsigned int j=0; j<V2->numberOfFacets(); j++) {
253 if (V1->getRawFacet(i) == V2->getRawFacet(j)) {
256 commonFacets.push_back(V1->getFacet(i));
261 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
274 const boost::shared_ptr<Generator_Rn>& V1,
275 const boost::shared_ptr<Generator_Rn>& V2,
276 std::vector< HalfSpace_Rn* >& commonFacets,
277 unsigned int topologicalCode=1)
const throw (std::invalid_argument) {
278 unsigned int sameHyperplane=0;
279 for (
unsigned int i=0; i<V1->numberOfFacets(); ++i) {
280 for (
unsigned int j=0; j<V2->numberOfFacets(); ++j) {
281 if (V1->getRawFacet(i)==V2->getRawFacet(j)) {
284 commonFacets.push_back(V1->getRawFacet(i));
289 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
300 const boost::shared_ptr<Generator_Rn_SD>& genIn,
301 const boost::shared_ptr<Generator_Rn_SD>& genOut,
302 std::vector< unsigned int >& commonFacets) {
304 std::set_intersection(genIn->facetsBegin(), genIn->facetsEnd(), genOut->facetsBegin(), genOut->facetsEnd(),
305 std::inserter(commonFacets, commonFacets.end()));
307 if (commonFacets.size() >= neigbourhoodCondition())
322 const boost::shared_ptr<Generator_Rn>& V1,
323 const boost::shared_ptr<Generator_Rn>& V2,
324 std::vector< HalfSpace_Rn* >& commonFacets,
325 const std::set< boost::shared_ptr<HalfSpace_Rn> >& listOfRedundantHS,
326 unsigned int topologicalCode=1)
const throw (std::invalid_argument) {
327 unsigned int sameHyperplane=0;
328 for (
unsigned int i=0; i<V1->numberOfFacets(); ++i) {
329 for (
unsigned int j=0; j<V2->numberOfFacets(); ++j) {
330 if (V1->getRawFacet(i)==V2->getRawFacet(j) &&
331 listOfRedundantHS.find(V1->getFacet(i))==listOfRedundantHS.end()) {
334 commonFacets.push_back(V1->getRawFacet(i));
339 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
348 void fillNeighbourMatrix(std::vector< std::vector<unsigned int> >& neighboursA,
unsigned int topologicalCode=1)
const throw (std::out_of_range) {
349 if (neighboursA.size() != numberOfGenerators()) {
350 std::string errorMessage(
"PolyhedralCone_Rn::fillNeighbourMatrix wrong matrix size");
351 throw std::out_of_range(errorMessage);
355 {
for (iteGN_A1.
begin(); iteGN_A1.
end()!=
true; iteGN_A1.
next()) {
356 const boost::shared_ptr<Generator_Rn>& v1_A = iteGN_A1.
current();
358 {
for (iteGN_A2.
begin(); iteGN_A2.
end()!=
true; iteGN_A2.
next()) {
359 const boost::shared_ptr<Generator_Rn>& v2_A = iteGN_A2.
current();
360 std::vector< HalfSpace_Rn* > commonFacets;
363 if (checkNeighbours(v1_A, v2_A, commonFacets, topologicalCode) ==
true) {
394 std::cout <<
"# Dimension NumberOfHalfspaces NumberOfGenerators" << std::endl;
395 std::cout << dimension() <<
" " << numberOfHalfSpaces() <<
" " << numberOfGenerators() << std::endl;
398 bool checkGeneratorsOK = checkGenerators(_listOfGenerators, _listOfHalfSpaces);
401 bool checkFacetsOK = checkFacets();
403 return (checkGeneratorsOK==
true && checkFacetsOK==
true);
413 const boost::shared_ptr<Generator_Rn>& point,
414 const boost::shared_ptr<HalfSpace_Rn>& halfSpace,
415 double halfSpaceNorm)
const;
421 bool checkDuplicateGenerators(
unsigned int& a,
unsigned int& b);
424 void checkGenerator(
unsigned int vtxNumber, std::ostream &this_ostream)
const throw (std::out_of_range) {
425 if (vtxNumber >= _listOfGenerators.size())
426 throw std::out_of_range(
"PolyhedralCone_Rn::checkGenerator(unsigned int fctNumber, std::ostream &this_ostream) inadequate generator number!");
427 this_ostream.precision(15);
429 this_ostream <<
"Check generator " << vtxNumber << std::endl;
430 _listOfGenerators[vtxNumber]->dump(std::cout);
431 this_ostream << std::endl;
432 {
for (
unsigned int i=0; i< _listOfGenerators[vtxNumber]->numberOfFacets(); ++i) {
433 this_ostream << getHalfSpaceNumber( _listOfGenerators[vtxNumber]->getFacet(i) ) <<
" ";
435 this_ostream << std::endl;
436 this_ostream << std::endl;
437 {
for (
unsigned int i=0; i< _listOfGenerators[vtxNumber]->numberOfFacets(); ++i) {
438 this_ostream <<
"H" << getHalfSpaceNumber( _listOfGenerators[vtxNumber]->getFacet(i) ) << std::endl;
439 _listOfGenerators[vtxNumber]->getFacet(i)->dump(this_ostream);
440 this_ostream << std::endl;
442 this_ostream << std::endl;
443 this_ostream <<
"Check generator " << vtxNumber << std::endl;
445 {
for (iteHS_B.
begin(); iteHS_B.
end()!=
true; iteHS_B.
next()) {
446 double halfSpaceNorm = std::inner_product(iteHS_B.
current()->begin(), iteHS_B.
current()->end(), iteHS_B.
current()->begin(), 0.);
447 halfSpaceNorm = sqrt(halfSpaceNorm);
448 double scalarProduct = std::inner_product(_listOfGenerators[vtxNumber]->begin(), _listOfGenerators[vtxNumber]->end(), iteHS_B.
current()->begin(), 0.);
449 double distanceToHyperplane = (scalarProduct+iteHS_B.
current()->getConstant()) / halfSpaceNorm;
451 this_ostream <<
": " << distanceToHyperplane;
452 if (distanceToHyperplane<TOL && distanceToHyperplane>-TOL)
453 this_ostream <<
" (*)";
454 this_ostream << std::endl;
465 std::cout <<
"Check generators..... ";
466 std::vector< std::vector<int> > listOfFacetsPerGenerator(listGenA.size());
468 {
for (iteHS_B.begin(); iteHS_B.end()!=
true; iteHS_B.next()) {
469 double halfSpaceNorm =
470 std::inner_product(iteHS_B.current()->begin(), iteHS_B.current()->end(), iteHS_B.current()->begin(), 0.);
471 halfSpaceNorm = sqrt(halfSpaceNorm);
473 {
for (iteGN_A_.
begin(); iteGN_A_.
end()!=
true; iteGN_A_.
next()) {
476 listOfFacetsPerGenerator[ iteGN_A_.
currentIteratorNumber() ].push_back( iteHS_B.currentIteratorNumber() );
479 << iteHS_B.currentIteratorNumber() << std::endl;
482 bool checkGeneratorsOK=
true;
484 {
for (iteGN_A.
begin(); iteGN_A.
end()!=
true; iteGN_A.
next()) {
487 checkGeneratorsOK =
false;
490 checkGeneratorsOK =
false;
492 if (checkGeneratorsOK ==
true)
493 std::cout <<
"OK" << std::endl;
495 std::cout <<
"KO" << std::endl;
496 {
for (iteGN_A.
begin(); iteGN_A.
end()!=
true; iteGN_A.
next()) {
504 << iteGN_A.
current()->numberOfFacets() << std::endl;
511 return checkGeneratorsOK;
520 void checkFacet(
unsigned int fctNumber, std::ostream &this_ostream)
const throw (std::out_of_range) {
521 if (fctNumber >= _listOfHalfSpaces.size())
522 throw std::out_of_range(
"PolyhedralCone_Rn::checkFacet(unsigned int fctNumber, std::ostream &this_ostream) inadequate facet number!");
523 this_ostream.precision(15);
524 this_ostream <<
"Check facet " << fctNumber << std::endl;
525 _listOfHalfSpaces[fctNumber]->dump(this_ostream);
526 this_ostream << std::endl;
528 double halfSpaceNorm = std::inner_product(
529 _listOfHalfSpaces[fctNumber]->begin(), _listOfHalfSpaces[fctNumber]->end(), _listOfHalfSpaces[fctNumber]->begin(), 0.);
530 halfSpaceNorm = sqrt(halfSpaceNorm);
562 this_ostream << std::endl;
565 double scalarProduct = std::inner_product(iteGN.
current()->begin(),iteGN.
current()->end(), _listOfHalfSpaces[fctNumber]->begin(), 0.);
566 double distanceToHyperplane = (scalarProduct+ _listOfHalfSpaces[fctNumber]->getConstant()) / halfSpaceNorm;
568 this_ostream <<
": " << distanceToHyperplane;
569 if (distanceToHyperplane<TOL && distanceToHyperplane>-TOL)
570 this_ostream <<
" (*)";
571 this_ostream << std::endl;
583 std::cout <<
"Check facets......... ";
584 bool checkFacetsOK=
true;
586 std::vector<int> listOfGeneratorsPerFacetON(numberOfGenerators());
587 std::vector<int> listOfGeneratorsPerFacetOUT(numberOfGenerators());
590 listOfGeneratorsPerFacetON.clear();
591 listOfGeneratorsPerFacetOUT.clear();
593 double halfSpaceNorm = std::inner_product(iteHS.
current()->begin(), iteHS.
current()->end(), iteHS.
current()->begin(), 0.);
594 halfSpaceNorm = sqrt(halfSpaceNorm);
599 listOfGeneratorsPerFacetON.push_back(i);
601 listOfGeneratorsPerFacetOUT.push_back(i);
603 if (listOfGeneratorsPerFacetON.empty() ==
true || listOfGeneratorsPerFacetON.size() < numberOfGeneratorsPerFacet())
604 std::cout<< std::endl <<
"\t=== Facet " << j <<
" has only " << listOfGeneratorsPerFacetON.size() <<
" generators."<< std::endl;
605 if (listOfGeneratorsPerFacetOUT.empty() !=
true) {
606 {
for (
unsigned int i=0; i<listOfGeneratorsPerFacetOUT.size(); i++) {
607 checkFacetsOK =
false;
608 std::cout<< std::endl;
609 std::cout <<
"\t### Facet " << j <<
" excludes generator " << listOfGeneratorsPerFacetOUT[i] << std::endl;
614 if (checkFacetsOK ==
true)
615 std::cout <<
"OK" << std::endl;
616 return checkFacetsOK;
621 bool checkEquality(
const boost::shared_ptr<PolyhedralCone_Rn>& B,
bool getFaceMapping=
false)
const;
627 void negate() {_listOfHalfSpaces.negate(); _listOfGenerators.negate();}
639 virtual void createTruncatedGenerator(
640 const boost::shared_ptr<Generator_Rn_SD>& y,
641 const boost::shared_ptr<Generator_Rn_SD>& z,
642 boost::shared_ptr<Generator_Rn_SD> newG,
double ay,
double az,
double b=0.)
const;
645 boost::shared_ptr<PolyhedralCone_Rn> computeDualPolyhedralCone()
const;
648 virtual void computeMinkowskiSum(
649 const boost::shared_ptr<PolyhedralCone_Rn>& A,
650 const boost::shared_ptr<PolyhedralCone_Rn>& B);
653 void dump(std::ostream &this_ostream)
const;
669 #endif // POLYHEDRALCONE_Rn
unsigned int numberOfHalfSpaces() const
Get the total number of half-spaces.
listOfGeometricObjects< boost::shared_ptr< HalfSpace_Rn > > & getListOfHalfSpaces()
Return the list of half-spaces.
void reset()
Remove all half-spaces and generators.
const listOfGeometricObjects< boost::shared_ptr< Generator_Rn > > & getListOfGenerators() const
Return the list of generators.
virtual unsigned int numberOfGeneratorsPerFacet() const
Each facet in a polyhedral cone has got (n-1) edges.
Creation of a n-coordinate geometric point designed to be shared by its neighbour faces...
void setListOfGenerators(const listOfGeometricObjects< boost::shared_ptr< Generator_Rn > > &gnList)
Set a new list of generators.
const listOfGeometricObjects< boost::shared_ptr< HalfSpace_Rn > > & getListOfHalfSpaces() const
Return the list of half-spaces.
int currentIteratorNumber() const
Return the current position in the list.
Model a polyhedral cone using its two equivalent definitions : the convex hull and the half-space int...
virtual bool checkEdges() const
Always true in the polyhedral cone case.
bool checkGenerators(const listOfGeometricObjects< boost::shared_ptr< Generator_Rn > > &listGenA, const listOfGeometricObjects< boost::shared_ptr< HalfSpace_Rn > > &listHSB, bool check_all=false) const
Check the number of facets per generator and make sure it is compliant with its current constraints...
virtual ~PolyhedralCone_Rn()
Destructor.
virtual void createBoundingBox(double)
At the moment this function is useless in the case of polyhedral cones.
bool checkNeighbours(const boost::shared_ptr< Generator_Rn > &V1, const boost::shared_ptr< Generator_Rn > &V2, std::vector< boost::shared_ptr< HalfSpace_Rn > > &commonFacets, const std::set< boost::shared_ptr< HalfSpace_Rn > > &listOfRedundantHS) const
const GEOMETRIC_OBJECT current()
Return the current geometric element.
unsigned int getListOfGeneratorsSD(std::vector< boost::shared_ptr< Generator_Rn_SD > > ¤tListOfGeneratorsSD)
bool checkNeighbours(const boost::shared_ptr< Generator_Rn > &V1, const boost::shared_ptr< Generator_Rn > &V2, std::vector< boost::shared_ptr< HalfSpace_Rn > > &commonFacets, unsigned int topologicalCode=1) const
void setListOfGeneratorsSD(const std::vector< boost::shared_ptr< Generator_Rn_SD > > &gnList)
Set a new list of generators. The list of half-spaces should have been previously set...
listOfGeometricObjects< boost::shared_ptr< Generator_Rn > > _listOfGenerators
The convex hull of connected points.
PolyhedralCone_Rn(const PolyhedralCone_Rn &A)
Constructor.
void removeHalfSpaces(const std::set< boost::shared_ptr< HalfSpace_Rn > > &setOfRedundantHS)
Remove the half-space number j from its list.
virtual void createBoundingSimplex(double)
At the moment this function is useless in the case of polyhedral cones.
bool checkNeighbours(const boost::shared_ptr< Generator_Rn_SD > &genIn, const boost::shared_ptr< Generator_Rn_SD > &genOut, std::vector< unsigned int > &commonFacets)
Check for polytopes that vertices share (n-1) facets. For polyhedral cones, it must check that vector...
void begin()
Move the iterator at the beginning of the list.
virtual bool isBounded() const
Tell whether this polyhedron is bounded or not, polyhedral cones are not.
unsigned int numberOfGenerators() const
Give the total number of generators.
static polito_EXPORT double getTolerance()
Give the minimum distance between two points.
bool end() const
Tell whether we have reached the end of the list.
void removeGenerator(unsigned int j)
Remove the generator number j from its list.
void checkGenerator(unsigned int vtxNumber, std::ostream &this_ostream) const
Compute all distance from the current point to all half-spaces frontiers.
static polito_EXPORT unsigned int getDimension()
Return the dimension of the cartesian space we work in.
This class is designed to run the list of all geometric objects representing a polytope.
virtual bool checkTopologyAndGeometry() const
As stated by Komei Fukuda "the complexity of the polyhedral verification problem is unknown...
A n-coordinates generator for internal data structure. It can be a vertex or an edge whether it is em...
void next()
Move the iterator one step forward.
void negate()
Compute the symmetrical polyhedral cone.
This class is designed to contain the list of all generators or half-spaces representing a polytope o...
virtual unsigned int dimension() const
Return the space dimension.
listOfGeometricObjects< boost::shared_ptr< HalfSpace_Rn > > _listOfHalfSpaces
The list of half-spaces defining the polytope.
virtual unsigned int neigbourhoodCondition() const
Two edges are neighbours in a polyhedral cone <=> they share at least (n-2) facets.
bool checkNeighboursWithHSnumbers(const boost::shared_ptr< Generator_Rn > &V1, const boost::shared_ptr< Generator_Rn > &V2, std::vector< HalfSpace_Rn * > &commonFacets, const std::set< boost::shared_ptr< HalfSpace_Rn > > &listOfRedundantHS, unsigned int topologicalCode=1) const
Check for polytopes that vertices share (n-1) facets. For polyhedral cones, it must check that vector...
void removeHalfSpace(unsigned int j)
Remove the half-space number j from its list.
void checkFacet(unsigned int fctNumber, std::ostream &this_ostream) const
bool checkFacets() const
Detect redundant half spaces and make sure each facet has the right number of generators. Check that the polytope does not have generators violating a constraint defined by a half-space. Check that the polytope does have at least (n-1) generators per half-space frontier. .
void fillNeighbourMatrix(std::vector< std::vector< unsigned int > > &neighboursA, unsigned int topologicalCode=1) const
void push_back(const GEOMETRIC_OBJECT &gn)
Include a new half space in the list.
unsigned int getHalfSpaceNumber(const boost::shared_ptr< HalfSpace_Rn > &F) const
For a given half-space, return its list index.
bool checkNeighbours(const boost::shared_ptr< Generator_Rn > &V1, const boost::shared_ptr< Generator_Rn > &V2, std::vector< HalfSpace_Rn * > &commonFacets, unsigned int topologicalCode=1) const
Check for polytopes that vertices share (n-1) facets. For polyhedral cones, it must check that vector...
PolyhedralCone_Rn()
Constructor.
void addGenerator(boost::shared_ptr< Generator_Rn > vx)
Add the given generator.