21 #ifndef POLYHEDRALCONE_Rn
22 #define POLYHEDRALCONE_Rn
24 #include <boost/numeric/ublas/io.hpp>
25 #include <boost/shared_ptr.hpp>
41 using namespace boost::numeric::ublas;
48 friend class lexIteratorOfListOfHalfSpaces;
49 friend class constIteratorOfListOfHalfSpaces;
66 if (numberOfHalfSpaces()==0 && numberOfGenerators()==0)
68 else if (numberOfGenerators()==0) {
70 const boost::shared_ptr<HalfSpace_Rn>& currentHalfSpace = iteHS.
current();
71 return currentHalfSpace->dimension();
75 const boost::shared_ptr<Generator_Rn>& currentGenerator = iteGN.
current();
76 return currentGenerator->dimension();
90 void reset() {_listOfHalfSpaces.clear(); _listOfGenerators.clear();}
98 boost::shared_ptr<HalfSpace_Rn> addHalfSpace(boost::shared_ptr<HalfSpace_Rn> hs,
bool check=
false);
101 void removeHalfSpaceFromListAndGenerators(
const boost::shared_ptr<HalfSpace_Rn>& hs);
107 void removeHalfSpaces(
const std::set< boost::shared_ptr<HalfSpace_Rn> >& setOfRedundantHS) {
108 _listOfHalfSpaces.removeGeometricObjects( setOfRedundantHS );
115 index = _listOfHalfSpaces.find(F);
117 catch(std::out_of_range& excep) {
119 std::cerr << std::endl;
120 std::string ex(excep.what());
121 ex += std::string(
" : Catch in PolyhedralCone_Rn::getHalfSpaceNumber()");
122 throw std::out_of_range(ex);
128 const boost::shared_ptr<HalfSpace_Rn>& getHalfSpace(
unsigned int i)
const;
146 void addGenerator(boost::shared_ptr<Generator_Rn> vx) {_listOfGenerators.push_back(vx);}
149 const boost::shared_ptr<Generator_Rn>& getGenerator(
unsigned int i)
const;
152 unsigned int getGeneratorNumber(boost::shared_ptr<Generator_Rn> G)
const;
157 unsigned int getListOfGeneratorsSD(std::vector< boost::shared_ptr<Generator_Rn_SD> >& currentListOfGeneratorsSD)
const {
158 unsigned int generatorNumber=0;
165 for (
unsigned int ii=0; ii<iteGN.
current()->numberOfFacets(); ii++) {
166 unsigned int fctNumber = getHalfSpaceNumber( iteGN.
current()->getFacet(ii) );
167 currentGeneratorSD->setFacet(fctNumber);
170 currentGeneratorSD->orderFacets();
171 currentListOfGeneratorsSD.push_back(currentGeneratorSD);
175 return generatorNumber;
181 std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN;
183 for (iteGN=gnList.begin(); iteGN!=gnList.end(); ++iteGN) {
185 boost::shared_ptr<Generator_Rn> currentGenerator = (*iteGN)->makeGenerator_Rn();
187 for (
unsigned int ii=0; ii<(*iteGN)->numberOfFacets(); ii++)
188 currentGenerator->setFacet( _listOfHalfSpaces[(*iteGN)->getFacet(ii)] );
190 listOfGenerators.
push_back( currentGenerator );
194 unsigned int nbGN = (*iteGN)->getGeneratorNumber();
195 boost::shared_ptr<Generator_Rn> currentGenerator = _listOfGenerators[nbGN];
196 currentGenerator->clearFacets();
198 for (
unsigned int ii=0; ii<(*iteGN)->numberOfFacets(); ii++)
199 currentGenerator->setFacet( _listOfHalfSpaces[(*iteGN)->getFacet(ii)] );
201 listOfGenerators.
push_back(_listOfGenerators[nbGN]);
205 unsigned int nbGN = (*iteGN)->getGeneratorNumber();
206 listOfGenerators.
push_back(_listOfGenerators[nbGN]);
211 _listOfGenerators.clear();
212 _listOfGenerators = listOfGenerators;
215 void relocateGenerators();
230 const boost::shared_ptr<Generator_Rn>& V2,
231 std::vector< boost::shared_ptr<HalfSpace_Rn> >& commonFacets,
232 const std::set< boost::shared_ptr<HalfSpace_Rn> >& listOfRedundantHS)
const {
233 unsigned int sameHyperplane=0;
234 for (
unsigned int i=0; i<V1->numberOfFacets(); i++) {
235 for (
unsigned int j=0; j<V2->numberOfFacets(); j++) {
236 if (V1->getRawFacet(i)==V2->getRawFacet(j) && listOfRedundantHS.find(V1->getFacet(i))==listOfRedundantHS.end()) {
239 commonFacets.push_back(V1->getFacet(i));
244 if (sameHyperplane >= neigbourhoodCondition())
252 bool isIncluded(
const boost::shared_ptr<PolyhedralCone_Rn>& B)
const;
261 const boost::shared_ptr<Generator_Rn>& V2,
262 std::vector< boost::shared_ptr<HalfSpace_Rn> >& commonFacets,
263 unsigned int topologicalCode=1)
const {
264 unsigned int sameHyperplane=0;
265 for (
unsigned int i=0; i<V1->numberOfFacets(); i++) {
266 for (
unsigned int j=0; j<V2->numberOfFacets(); j++) {
267 if (V1->getRawFacet(i) == V2->getRawFacet(j)) {
270 commonFacets.push_back(V1->getFacet(i));
275 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
288 const boost::shared_ptr<Generator_Rn>& V1,
289 const boost::shared_ptr<Generator_Rn>& V2,
290 std::vector< HalfSpace_Rn* >& commonFacets,
291 unsigned int topologicalCode=1)
const {
292 unsigned int sameHyperplane=0;
293 for (
unsigned int i=0; i<V1->numberOfFacets(); ++i) {
294 for (
unsigned int j=0; j<V2->numberOfFacets(); ++j) {
295 if (V1->getRawFacet(i)==V2->getRawFacet(j)) {
298 commonFacets.push_back(V1->getRawFacet(i));
303 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
314 const boost::shared_ptr<Generator_Rn_SD>& genIn,
315 const boost::shared_ptr<Generator_Rn_SD>& genOut,
316 std::vector< unsigned int >& commonFacets)
const {
318 std::set_intersection(genIn->facetsBegin(), genIn->facetsEnd(), genOut->facetsBegin(), genOut->facetsEnd(),
319 std::inserter(commonFacets, commonFacets.end()));
321 if (commonFacets.size() >= neigbourhoodCondition())
336 const boost::shared_ptr<Generator_Rn>& V1,
337 const boost::shared_ptr<Generator_Rn>& V2,
338 std::vector< HalfSpace_Rn* >& commonFacets,
339 const std::set< boost::shared_ptr<HalfSpace_Rn> >& listOfRedundantHS,
340 unsigned int topologicalCode=1)
const {
341 unsigned int sameHyperplane=0;
342 for (
unsigned int i=0; i<V1->numberOfFacets(); ++i) {
343 for (
unsigned int j=0; j<V2->numberOfFacets(); ++j) {
344 if (V1->getRawFacet(i)==V2->getRawFacet(j) &&
345 listOfRedundantHS.find(V1->getFacet(i))==listOfRedundantHS.end()) {
348 commonFacets.push_back(V1->getRawFacet(i));
353 if (sameHyperplane >= neigbourhoodCondition()-topologicalCode+1) {
362 void fillNeighbourMatrix(std::vector< std::vector<unsigned int> >& neighboursA,
unsigned int topologicalCode=1)
const {
363 if (neighboursA.size() != numberOfGenerators()) {
364 std::string errorMessage(
"PolyhedralCone_Rn::fillNeighbourMatrix wrong matrix size");
365 throw std::out_of_range(errorMessage);
369 {
for (iteGN_A1.
begin(); iteGN_A1.
end()!=
true; iteGN_A1.
next()) {
370 const boost::shared_ptr<Generator_Rn>& v1_A = iteGN_A1.
current();
372 {
for (iteGN_A2.
begin(); iteGN_A2.
end()!=
true; iteGN_A2.
next()) {
373 const boost::shared_ptr<Generator_Rn>& v2_A = iteGN_A2.
current();
374 std::vector< HalfSpace_Rn* > commonFacets;
377 if (checkNeighbours(v1_A, v2_A, commonFacets, topologicalCode) ==
true) {
403 if (neighboursA.size() != numberOfGenerators()) {
404 std::string errorMessage(
"PolyhedralCone_Rn::fillIrredundantNeighbourMatrix wrong matrix size");
405 throw std::out_of_range(errorMessage);
408 std::vector< boost::shared_ptr<Generator_Rn_SD> > listOfGenSD;
412 getListOfGeneratorsSD(listOfGenSD);
414 unsigned int count_OUT=0;
415 std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_OUT;
416 {
for (iteGN_OUT=listOfGenSD.begin(); iteGN_OUT!=listOfGenSD.end(); ++iteGN_OUT, ++count_OUT) {
417 unsigned int count_IN=0;
418 std::vector< boost::shared_ptr<Generator_Rn_SD> >::const_iterator iteGN_IN;
419 {
for (iteGN_IN=listOfGenSD.begin(); iteGN_IN!=listOfGenSD.end(); ++iteGN_IN, ++count_IN) {
420 std::vector< unsigned int > commonFacets;
421 if (count_IN!=count_OUT && checkNeighbours(*iteGN_IN, *iteGN_OUT, commonFacets) ==
true)
430 for (newGeneratorsTool.
begin(); newGeneratorsTool.
end()!=
true; newGeneratorsTool.
next()) {
444 std::cerr.precision(15);
445 std::cout.precision(15);
446 std::cout <<
"# Dimension NumberOfHalfspaces NumberOfGenerators" << std::endl;
447 std::cout << dimension() <<
" " << numberOfHalfSpaces() <<
" " << numberOfGenerators() << std::endl;
450 bool checkGeneratorsOK = checkGenerators(_listOfGenerators, _listOfHalfSpaces, check_all);
453 bool checkFacetsOK = checkFacets();
455 return (checkGeneratorsOK==
true && checkFacetsOK==
true);
463 unsigned int dim = thisGen->dimension();
465 {
for (
unsigned int i=0; i<dim; ++i) {
468 return checkPoint(thisPoint);
474 const boost::shared_ptr<Generator_Rn>& point,
475 const boost::shared_ptr<HalfSpace_Rn>& halfSpace,
476 double halfSpaceNorm)
const;
482 bool checkDuplicateGenerators(
unsigned int& a,
unsigned int& b);
486 if (vtxNumber >= _listOfGenerators.size())
487 throw std::out_of_range(
"PolyhedralCone_Rn::checkGenerator(unsigned int fctNumber, std::ostream &this_ostream) inadequate generator number!");
488 this_ostream.precision(15);
490 this_ostream <<
"Check generator " << vtxNumber << std::endl;
491 _listOfGenerators[vtxNumber]->dump(std::cout);
492 this_ostream << std::endl;
493 {
for (
unsigned int i=0; i< _listOfGenerators[vtxNumber]->numberOfFacets(); ++i) {
494 this_ostream << getHalfSpaceNumber( _listOfGenerators[vtxNumber]->getFacet(i) ) <<
" ";
496 this_ostream << std::endl;
497 this_ostream << std::endl;
498 {
for (
unsigned int i=0; i< _listOfGenerators[vtxNumber]->numberOfFacets(); ++i) {
499 this_ostream <<
"H" << getHalfSpaceNumber( _listOfGenerators[vtxNumber]->getFacet(i) ) << std::endl;
500 _listOfGenerators[vtxNumber]->getFacet(i)->dump(this_ostream);
501 this_ostream << std::endl;
503 this_ostream << std::endl;
504 this_ostream <<
"Check generator " << vtxNumber << std::endl;
506 {
for (iteHS_B.
begin(); iteHS_B.
end()!=
true; iteHS_B.
next()) {
507 double halfSpaceNorm = std::inner_product(iteHS_B.
current()->begin(), iteHS_B.
current()->end(), iteHS_B.
current()->begin(), 0.);
508 halfSpaceNorm = sqrt(halfSpaceNorm);
509 double scalarProduct = std::inner_product(_listOfGenerators[vtxNumber]->begin(), _listOfGenerators[vtxNumber]->end(), iteHS_B.
current()->begin(), 0.);
510 double distanceToHyperplane = (scalarProduct+iteHS_B.
current()->getConstant()) / halfSpaceNorm;
512 this_ostream <<
": " << distanceToHyperplane;
513 if (distanceToHyperplane<TOL && distanceToHyperplane>-TOL)
514 this_ostream <<
" (*)";
515 this_ostream << std::endl;
526 std::cout <<
"Check generators..... ";
528 std::vector< std::vector<int> > listOfFacetsPerGenerator(listGenA.size());
530 {
for (iteHS_B.
begin(); iteHS_B.
end()!=
true; iteHS_B.
next()) {
531 double halfSpaceNorm =
532 std::inner_product(iteHS_B.
current()->begin(), iteHS_B.
current()->end(), iteHS_B.
current()->begin(), 0.);
533 halfSpaceNorm = sqrt(halfSpaceNorm);
535 {
for (iteGN_A_.
begin(); iteGN_A_.
end()!=
true; iteGN_A_.
next()) {
536 double scalarProduct = std::inner_product(iteGN_A_.
current()->begin(), iteGN_A_.
current()->end(), iteHS_B.
current()->begin(), 0.);
537 double distanceToHyperplane = (scalarProduct+iteHS_B.
current()->getConstant()) / halfSpaceNorm;
538 if (distanceToHyperplane > TOL) {
541 else if (distanceToHyperplane < -TOL) {
546 iteGN_A_.
current()->dump(std::cerr);
547 std::cerr <<
" (d=" << distanceToHyperplane <<
")" << std::endl;
555 bool checkGeneratorsOK=
true;
557 {
for (iteGN_A.
begin(); iteGN_A.
end()!=
true; iteGN_A.
next()) {
560 checkGeneratorsOK =
false;
563 checkGeneratorsOK =
false;
565 if (checkGeneratorsOK ==
true)
566 std::cout <<
"OK" << std::endl;
568 std::cout <<
"KO" << std::endl;
569 {
for (iteGN_A.
begin(); iteGN_A.
end()!=
true; iteGN_A.
next()) {
577 << iteGN_A.
current()->numberOfFacets() << std::endl;
584 return checkGeneratorsOK;
595 bool isOutFromB =
false;
596 double distFromB = std::numeric_limits<int>::max();
598 std::vector< std::vector<int> > listOfFacetsPerGenerator(_listOfGenerators.size());
600 {
for (iteHS_B.
begin(); iteHS_B.
end()!=
true; iteHS_B.
next()) {
601 double halfSpaceNorm =
602 std::inner_product(iteHS_B.
current()->begin(), iteHS_B.
current()->end(), iteHS_B.
current()->begin(), 0.);
603 halfSpaceNorm = sqrt(halfSpaceNorm);
605 {
for (iteGN_A_.
begin(); iteGN_A_.
end()!=
true; iteGN_A_.
next()) {
606 double scalarProduct = std::inner_product(iteGN_A_.
current()->begin(), iteGN_A_.
current()->end(), iteHS_B.
current()->begin(), 0.);
607 double distanceToHyperplane = (scalarProduct+iteHS_B.
current()->getConstant()) / halfSpaceNorm;
608 if (distanceToHyperplane > TOL) {
611 else if (distanceToHyperplane < -TOL) {
624 if (distanceToHyperplane < distFromB)
625 distFromB = distanceToHyperplane;
629 bool isOutFromA =
false;
630 double distFromA = std::numeric_limits<int>::max();
632 std::vector< std::vector<int> > listOfFacetsPerGenerator(B->_listOfGenerators.size());
634 {
for (iteHS_A.
begin(); iteHS_A.
end()!=
true; iteHS_A.
next()) {
635 double halfSpaceNorm =
636 std::inner_product(iteHS_A.
current()->begin(), iteHS_A.
current()->end(), iteHS_A.
current()->begin(), 0.);
637 halfSpaceNorm = sqrt(halfSpaceNorm);
639 {
for (iteGN_B_.
begin(); iteGN_B_.
end()!=
true; iteGN_B_.
next()) {
640 double scalarProduct = std::inner_product(iteGN_B_.
current()->begin(), iteGN_B_.
current()->end(), iteHS_A.
current()->begin(), 0.);
641 double distanceToHyperplane = (scalarProduct+iteHS_A.
current()->getConstant()) / halfSpaceNorm;
642 if (distanceToHyperplane > TOL) {
645 else if (distanceToHyperplane < -TOL) {
658 if (distanceToHyperplane < distFromA)
659 distFromA = distanceToHyperplane;
663 if (isOutFromA ==
true)
664 std::cout <<
"Outside A : distance = " << distFromA << std::endl;
665 if (isOutFromB ==
true)
666 std::cout <<
"Outside B : distance = " << distFromB << std::endl;
667 return std::min(distFromA, distFromB);
674 void removeGenerators(
const std::set< boost::shared_ptr<Generator_Rn> >& setToRemove) {_listOfGenerators.removeGeometricObjects(setToRemove);}
679 void checkFacet(
unsigned int fctNumber, std::ostream &this_ostream)
const {
680 if (fctNumber >= _listOfHalfSpaces.size())
681 throw std::out_of_range(
"PolyhedralCone_Rn::checkFacet(unsigned int fctNumber, std::ostream &this_ostream) inadequate facet number!");
682 this_ostream.precision(15);
683 this_ostream <<
"Check facet " << fctNumber << std::endl;
684 _listOfHalfSpaces[fctNumber]->dump(this_ostream);
685 this_ostream << std::endl;
687 double halfSpaceNorm = std::inner_product(
688 _listOfHalfSpaces[fctNumber]->begin(), _listOfHalfSpaces[fctNumber]->end(), _listOfHalfSpaces[fctNumber]->begin(), 0.);
689 halfSpaceNorm = sqrt(halfSpaceNorm);
721 this_ostream << std::endl;
724 double scalarProduct = std::inner_product(iteGN.
current()->begin(),iteGN.
current()->end(), _listOfHalfSpaces[fctNumber]->begin(), 0.);
725 double distanceToHyperplane = (scalarProduct+ _listOfHalfSpaces[fctNumber]->getConstant()) / halfSpaceNorm;
727 this_ostream <<
": " << distanceToHyperplane;
728 if (distanceToHyperplane<TOL && distanceToHyperplane>-TOL)
729 this_ostream <<
" (*)";
730 this_ostream << std::endl;
742 std::cout <<
"Check facets......... ";
743 bool checkFacetsOK=
true;
745 std::vector<int> listOfGeneratorsPerFacetON(numberOfGenerators());
746 std::vector<int> listOfGeneratorsPerFacetOUT(numberOfGenerators());
749 listOfGeneratorsPerFacetON.clear();
750 listOfGeneratorsPerFacetOUT.clear();
752 double halfSpaceNorm = std::inner_product(iteHS.
current()->begin(), iteHS.
current()->end(), iteHS.
current()->begin(), 0.);
753 halfSpaceNorm = sqrt(halfSpaceNorm);
758 listOfGeneratorsPerFacetON.push_back(i);
760 listOfGeneratorsPerFacetOUT.push_back(i);
762 if (listOfGeneratorsPerFacetON.empty() ==
true || listOfGeneratorsPerFacetON.size() < numberOfGeneratorsPerFacet())
763 std::cout<< std::endl <<
"\t=== Facet " << j <<
" has only " << listOfGeneratorsPerFacetON.size() <<
" generators."<< std::endl;
764 if (listOfGeneratorsPerFacetOUT.empty() !=
true) {
765 {
for (
unsigned int i=0; i<listOfGeneratorsPerFacetOUT.size(); i++) {
766 checkFacetsOK =
false;
767 std::cout<< std::endl;
768 std::cout <<
"\t### Facet " << j <<
" excludes generator " << listOfGeneratorsPerFacetOUT[i] << std::endl;
773 if (checkFacetsOK ==
true)
774 std::cout <<
"OK" << std::endl;
775 return checkFacetsOK;
780 bool checkEquality(
const boost::shared_ptr<PolyhedralCone_Rn>& B,
bool getFaceMapping=
false)
const;
784 listOfGeneratorsPerFacet.clear();
785 listOfGeneratorsPerFacet.resize(numberOfHalfSpaces());
789 const boost::shared_ptr<HalfSpace_Rn>& thisFacet = iteHS.
current();
792 {
for (
unsigned int i=0; i<iteGN.
current()->numberOfFacets(); ++i) {
793 if (iteGN.
current()->getFacet(i) == thisFacet) {
795 listOfGeneratorsPerFacet[facetNb].push_back(vtxNb);
806 void negate() {_listOfHalfSpaces.negate(); _listOfGenerators.negate();}
818 virtual double createTruncatedGenerator(
819 const boost::shared_ptr<Generator_Rn_SD>& y,
820 const boost::shared_ptr<Generator_Rn_SD>& z,
821 boost::shared_ptr<Generator_Rn_SD> newG,
double ay,
double az,
double b=0.)
const;
839 boost::shared_ptr<PolyhedralCone_Rn> computeDualPolyhedralCone()
const;
842 virtual void dump(std::ostream &this_ostream)
const;
845 void dumpScilab(std::ostream &this_ostream)
const;
862 #endif // POLYHEDRALCONE_Rn