Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Path: gap4r8 / pkg / NormalizInterface-1.0.2 / Normaliz.git / Qsource / libQnormaliz / Qfull_cone.cpp
Views: 418384/*1* Normaliz2* Copyright (C) 2007-2014 Winfried Bruns, Bogdan Ichim, Christof Soeger3* This program is free software: you can redistribute it and/or modify4* it under the terms of the GNU General Public License as published by5* the Free Software Foundation, either version 3 of the License, or6* (at your option) any later version.7*8* This program is distributed in the hope that it will be useful,9* but WITHOUT ANY WARRANTY; without even the implied warranty of10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11* GNU General Public License for more details.12*13* You should have received a copy of the GNU General Public License14* along with this program. If not, see <http://www.gnu.org/licenses/>.15*16* As an exception, when this program is distributed through (i) the App Store17* by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or (iii) Google Play18* by Google Inc., then that store may impose any digital rights management,19* device limits and/or redistribution restrictions that are required by its20* terms of service.21*/2223//---------------------------------------------------------------------------2425#include <stdlib.h>26#include <set>27#include <map>28#include <iostream>29#include <string>30#include <algorithm>31#include <time.h>32#include <deque>3334#include "libQnormaliz/Qfull_cone.h"35#include "libQnormaliz/Qcone_helper.h"36#include "libQnormaliz/Qvector_operations.h"37#include "libQnormaliz/Qlist_operations.h"38#include "libQnormaliz/Qmap_operations.h"39#include "libQnormaliz/Qmy_omp.h"40#include "libQnormaliz/Qinteger.h"41// #include "libQnormaliz/Qsublattice_representation.h"42// #include "libQnormaliz/Qoffload_handler.h"4344//---------------------------------------------------------------------------4546// const size_t RecBoundTriang=1000000; // if number(supphyps)*size(triang) > RecBoundTriang47// we pass to (non-recirsive) pyramids48// now in build_cone4950const size_t EvalBoundTriang=2500000; // if more than EvalBoundTriang simplices have been stored51// evaluation is started (whenever possible)5253const size_t EvalBoundPyr=200000; // the same for stored pyramids of level > 05455const size_t EvalBoundLevel0Pyr=200000; // 1000000; // the same for stored level 0 pyramids5657// const size_t EvalBoundRecPyr=200000; // the same for stored RECURSIVE pyramids5859// const size_t IntermedRedBoundHB=2000000; // bound for number of HB elements before60// intermediate reduction is called6162const int largePyramidFactor=20; // pyramid is large if largePyramidFactor*Comparisons[Pyramid_key.size()-dim] > old_nr_supp_hyps6364const int SuppHypRecursionFactor=200; // pyramids for supphyps formed if Pos*Neg > this factor*dim^46566const size_t RAM_Size=1000000000; // we assume that there is at least 1 GB of RAM6768const long GMP_time_factor=20; // factor by which GMP arithmetic differs from long long6970//---------------------------------------------------------------------------7172namespace libQnormaliz {73using namespace std;7475//---------------------------------------------------------------------------76//private77//---------------------------------------------------------------------------7879template<typename Number>80void Full_Cone<Number>::check_simpliciality_hyperplane(const FACETDATA& hyp) const{81size_t nr_gen_in_hyp=0;82for(size_t i=0; i<nr_gen;++i)83if(in_triang[i]&& hyp.GenInHyp.test(i))84nr_gen_in_hyp++;85if((hyp.simplicial && nr_gen_in_hyp!=dim-2) || (!hyp.simplicial && nr_gen_in_hyp==dim-2)){86// NOTE: in_triang set at END of main loop in build_cone87cout << "Simplicial " << hyp.simplicial << " dim " << dim << " gen_in_hyp " << nr_gen_in_hyp << endl;88assert(false);89}90}9192template<typename Number>93void Full_Cone<Number>::set_simplicial(FACETDATA& hyp){94size_t nr_gen_in_hyp=0;95for(size_t i=0; i<nr_gen;++i)96if(in_triang[i]&& hyp.GenInHyp.test(i))97nr_gen_in_hyp++;98hyp.simplicial=(nr_gen_in_hyp==dim-2);99}100101template<typename Number>102void Full_Cone<Number>::number_hyperplane(FACETDATA& hyp, const size_t born_at, const size_t mother){103// add identifying number, the birth day and the number of mother104105hyp.Mother=mother;106hyp.BornAt=born_at;107if(!multithreaded_pyramid){108hyp.Ident=HypCounter[0];109HypCounter[0]++;110return;111}112113int tn;114if(omp_get_level()==0)115tn=0;116else117tn = omp_get_ancestor_thread_num(1);118hyp.Ident=HypCounter[tn];119HypCounter[tn]+=omp_get_max_threads();120121}122123//---------------------------------------------------------------------------124125template<typename Number>126bool Full_Cone<Number>::is_hyperplane_included(FACETDATA& hyp) {127if (!is_pyramid) { // in the topcone we always have ov_sp > 0128return true;129}130//check if it would be an excluded hyperplane131Number ov_sp = v_scalar_product(hyp.Hyp,Order_Vector);132if (ov_sp > 0) {133return true;134} else if (ov_sp == 0) {135for (size_t i=0; i<dim; i++) {136if (hyp.Hyp[i]>0) {137return true;138} else if (hyp.Hyp[i]<0) {139return false;140}141}142}143return false;144}145146//---------------------------------------------------------------------------147148template<typename Number>149void Full_Cone<Number>::add_hyperplane(const size_t& new_generator, const FACETDATA & positive,const FACETDATA & negative,150list<FACETDATA>& NewHyps, bool known_to_be_simplicial){151// adds a new hyperplane found in find_new_facets to this cone (restricted to generators processed)152153size_t k;154155FACETDATA NewFacet; NewFacet.Hyp.resize(dim); NewFacet.GenInHyp.resize(nr_gen);156157for (k = 0; k <dim; k++) {158NewFacet.Hyp[k]=positive.ValNewGen*negative.Hyp[k]-negative.ValNewGen*positive.Hyp[k];159if(!check_range(NewFacet.Hyp[k]))160break;161}162163/* cout << "==========================================" << endl;164cout << NewFacet.Hyp;165cout << "==========================================" << endl; */166167v_simplify(NewFacet.Hyp);168169NewFacet.ValNewGen=0;170NewFacet.GenInHyp=positive.GenInHyp & negative.GenInHyp; // new hyperplane contains old gen iff both pos and neg do171if(known_to_be_simplicial){172NewFacet.simplicial=true;173check_simpliciality_hyperplane(NewFacet);174}175else176set_simplicial(NewFacet);177NewFacet.GenInHyp.set(new_generator); // new hyperplane contains new generator178number_hyperplane(NewFacet,nrGensInCone,positive.Ident);179180NewHyps.push_back(NewFacet);181}182183184//---------------------------------------------------------------------------185186187template<typename Number>188void Full_Cone<Number>::find_new_facets(const size_t& new_generator){189// our Fourier-Motzkin implementation190// the special treatment of simplicial facets was inserted because of line shellings.191// At present these are not computed.192193//to see if possible to replace the function .end with constant iterator since push-back is performed.194195// for dimension 0 and 1 F-M is never necessary and can lead to problems196// when using dim-2197if (dim <= 1)198return;199200// NEW: new_generator is the index of the generator being inserted201202size_t i,k,nr_zero_i;203size_t subfacet_dim=dim-2; // NEW dimension of subfacet204size_t facet_dim=dim-1; // NEW dimension of facet205206const bool tv_verbose = false; //verbose && !is_pyramid; // && Support_Hyperplanes.nr_of_rows()>10000; //verbose in this method call207208209// preparing the computations, the various types of facets are sorted into the deques210deque <FACETDATA*> Pos_Simp,Pos_Non_Simp;211deque <FACETDATA*> Neg_Simp,Neg_Non_Simp;212deque <FACETDATA*> Neutral_Simp, Neutral_Non_Simp;213214boost::dynamic_bitset<> Zero_Positive(nr_gen),Zero_Negative(nr_gen); // here we collect the vertices that lie in a215// postive resp. negative hyperplane216217bool simplex;218219if (tv_verbose) verboseOutput()<<"transform_values:"<<flush;220221typename list<FACETDATA>::iterator ii = Facets.begin();222223for (; ii != Facets.end(); ++ii) {224// simplex=true;225// nr_zero_i=0;226simplex=ii->simplicial; // at present simplicial, will become nonsimplicial if neutral227/* for (size_t j=0; j<nr_gen; j++){228if (ii->GenInHyp.test(j)) {229if (++nr_zero_i > facet_dim) {230simplex=false;231break;232}233}234}*/235236if (ii->ValNewGen==0) {237ii->GenInHyp.set(new_generator); // Must be set explicitly !!238ii->simplicial=false; // simpliciality definitly gone with the new generator239if (simplex) {240Neutral_Simp.push_back(&(*ii)); // simplicial without the new generator241} else {242Neutral_Non_Simp.push_back(&(*ii)); // nonsim�plicial already without the new generator243}244}245else if (ii->ValNewGen>0) {246Zero_Positive |= ii->GenInHyp;247if (simplex) {248Pos_Simp.push_back(&(*ii));249} else {250Pos_Non_Simp.push_back(&(*ii));251}252}253else if (ii->ValNewGen<0) {254Zero_Negative |= ii->GenInHyp;255if (simplex) {256Neg_Simp.push_back(&(*ii));257} else {258Neg_Non_Simp.push_back(&(*ii));259}260}261}262263// TO DO: Negativliste mit Zero_Positive verfeinern, also die aussondern, die nicht genug positive Erz enthalten264// Eventuell sogar Rang-Test einbauen.265// Letzteres könnte man auch bei den positiven machen, bevor sie verarbeitet werden266267boost::dynamic_bitset<> Zero_PN(nr_gen);268Zero_PN = Zero_Positive & Zero_Negative;269270size_t nr_PosSimp = Pos_Simp.size();271size_t nr_PosNonSimp = Pos_Non_Simp.size();272size_t nr_NegSimp = Neg_Simp.size();273size_t nr_NegNonSimp = Neg_Non_Simp.size();274size_t nr_NeuSimp = Neutral_Simp.size();275size_t nr_NeuNonSimp = Neutral_Non_Simp.size();276277if (tv_verbose) verboseOutput()<<" PS "<<nr_PosSimp<<", P "<<nr_PosNonSimp<<", NS "<<nr_NegSimp<<", N "<<nr_NegNonSimp<<", ZS "<<nr_NeuSimp<<", Z "<<nr_NeuNonSimp<<endl;278279if (tv_verbose) verboseOutput()<<"transform_values: subfacet of NS: "<<flush;280281vector< list<pair < boost::dynamic_bitset<>, int> > > Neg_Subfacet_Multi(omp_get_max_threads()) ;282283boost::dynamic_bitset<> zero_i, subfacet;284285// This parallel region cannot throw a NormalizException286#pragma omp parallel for private(zero_i,subfacet,k,nr_zero_i)287for (i=0; i<nr_NegSimp;i++){288zero_i=Zero_PN & Neg_Simp[i]->GenInHyp;289290nr_zero_i=0;291for(size_t j=0;j<nr_gen;j++){292if(zero_i.test(j))293nr_zero_i++;294if(nr_zero_i>subfacet_dim){295break;296}297}298299if(nr_zero_i==subfacet_dim) // NEW This case treated separately300Neg_Subfacet_Multi[omp_get_thread_num()].push_back(pair <boost::dynamic_bitset<>, int> (zero_i,i));301302if(nr_zero_i==facet_dim){303for (k =0; k<nr_gen; k++) {304if(zero_i.test(k)) {305subfacet=zero_i;306subfacet.reset(k); // remove k-th element from facet to obtain subfacet307Neg_Subfacet_Multi[omp_get_thread_num()].push_back(pair <boost::dynamic_bitset<>, int> (subfacet,i));308}309}310}311}312313list < pair < boost::dynamic_bitset<>, int> > Neg_Subfacet_Multi_United;314for(int i=0;i<omp_get_max_threads();++i)315Neg_Subfacet_Multi_United.splice(Neg_Subfacet_Multi_United.begin(),Neg_Subfacet_Multi[i]);316Neg_Subfacet_Multi_United.sort();317318319if (tv_verbose) verboseOutput()<<Neg_Subfacet_Multi_United.size() << ", " << flush;320321list< pair < boost::dynamic_bitset<>, int > >::iterator jj;322list< pair < boost::dynamic_bitset<>, int > >::iterator del;323jj =Neg_Subfacet_Multi_United.begin(); // remove negative subfacets shared324while (jj!= Neg_Subfacet_Multi_United.end()) { // by two neg simpl facets325del=jj++;326if (jj!=Neg_Subfacet_Multi_United.end() && (*jj).first==(*del).first) { //delete since is the intersection of two negative simplicies327Neg_Subfacet_Multi_United.erase(del);328del=jj++;329Neg_Subfacet_Multi_United.erase(del);330}331}332333size_t nr_NegSubfMult = Neg_Subfacet_Multi_United.size();334if (tv_verbose) verboseOutput() << nr_NegSubfMult << ", " << flush;335336vector<list<FACETDATA> > NewHypsSimp(nr_PosSimp);337vector<list<FACETDATA> > NewHypsNonSimp(nr_PosNonSimp);338339map < boost::dynamic_bitset<>, int > Neg_Subfacet;340size_t nr_NegSubf=0;341342// size_t NrMatches=0, NrCSF=0, NrRank=0, NrComp=0, NrNewF=0;343344/* deque<bool> Indi(nr_NegNonSimp);345for(size_t j=0;j<nr_NegNonSimp;++j)346Indi[j]=false; */347348if(multithreaded_pyramid){349#pragma omp atomic350nrTotalComparisons+=nr_NegNonSimp*nr_PosNonSimp;351}352else{353nrTotalComparisons+=nr_NegNonSimp*nr_PosNonSimp;354}355356357//=====================================================================358// parallel from here359360bool skip_remaining = false;361#ifndef NCATCH362std::exception_ptr tmp_exception;363#endif364365#pragma omp parallel private(jj)366{367size_t i,j,k,nr_zero_i;368boost::dynamic_bitset<> subfacet(dim-2);369jj = Neg_Subfacet_Multi_United.begin();370size_t jjpos=0;371int tn = omp_get_ancestor_thread_num(1);372373bool found;374// This for region cannot throw a NormalizException375#pragma omp for schedule(dynamic)376for (size_t j=0; j<nr_NegSubfMult; ++j) { // remove negative subfacets shared377for(;j > jjpos; ++jjpos, ++jj) ; // by non-simpl neg or neutral facets378for(;j < jjpos; --jjpos, --jj) ;379380subfacet=(*jj).first;381found=false;382for (i = 0; i <nr_NeuSimp; i++) {383found=subfacet.is_subset_of(Neutral_Simp[i]->GenInHyp);384if(found)385break;386}387if (!found) {388for (i = 0; i <nr_NeuNonSimp; i++) {389found=subfacet.is_subset_of(Neutral_Non_Simp[i]->GenInHyp);390if(found)391break;392}393if(!found) {394for (i = 0; i <nr_NegNonSimp; i++) {395found=subfacet.is_subset_of(Neg_Non_Simp[i]->GenInHyp);396if(found)397break;398}399}400}401if (found) {402jj->second=-1;403}404}405406#pragma omp single407{ //remove elements that where found in the previous loop408jj = Neg_Subfacet_Multi_United.begin();409map < boost::dynamic_bitset<>, int > ::iterator last_inserted=Neg_Subfacet.begin(); // used to speedup insertion into the new map410for (; jj!= Neg_Subfacet_Multi_United.end(); ++jj) {411if ((*jj).second != -1) {412last_inserted = Neg_Subfacet.insert(last_inserted,*jj);413}414}415nr_NegSubf=Neg_Subfacet.size();416}417418#pragma omp single nowait419{Neg_Subfacet_Multi_United.clear();}420421422boost::dynamic_bitset<> zero_i(nr_gen);423map <boost::dynamic_bitset<>, int> ::iterator jj_map;424425426#pragma omp single nowait427if (tv_verbose) {428verboseOutput() << "PS vs NS and PS vs N , " << flush;429}430431vector<key_t> key(nr_gen);432size_t nr_missing;433bool common_subfacet;434// we cannot use nowait here because of the way we handle exceptions in this loop435#pragma omp for schedule(dynamic) //nowait436for (size_t i =0; i<nr_PosSimp; i++){437438if (skip_remaining) continue;439#ifndef NCATCH440try {441#endif442zero_i=Zero_PN & Pos_Simp[i]->GenInHyp;443nr_zero_i=0;444for(j=0;j<nr_gen && nr_zero_i<=facet_dim;j++)445if(zero_i.test(j)){446key[nr_zero_i]=j;447nr_zero_i++;448}449450if(nr_zero_i<subfacet_dim)451continue;452453// first PS vs NS454455if (nr_zero_i==subfacet_dim) { // NEW slight change in logic. Positive simpl facet shared at most456jj_map=Neg_Subfacet.find(zero_i); // one subfacet with negative simpl facet457if (jj_map!=Neg_Subfacet.end()) {458add_hyperplane(new_generator,*Pos_Simp[i],*Neg_Simp[(*jj_map).second],NewHypsSimp[i],true);459(*jj_map).second = -1; // block subfacet in further searches460}461}462if (nr_zero_i==facet_dim){ // now there could be more such subfacets. We make all and search them.463for (k =0; k<nr_gen; k++) { // BOOST ROUTINE464if(zero_i.test(k)) {465subfacet=zero_i;466subfacet.reset(k); // remove k-th element from facet to obtain subfacet467jj_map=Neg_Subfacet.find(subfacet);468if (jj_map!=Neg_Subfacet.end()) {469add_hyperplane(new_generator,*Pos_Simp[i],*Neg_Simp[(*jj_map).second],NewHypsSimp[i],true);470(*jj_map).second = -1;471// Indi[j]=true;472}473}474}475}476477// now PS vs N478479for (j=0; j<nr_NegNonSimp; j++){ // search negative facet with common subfacet480nr_missing=0;481common_subfacet=true;482for(k=0;k<nr_zero_i;k++) {483if(!Neg_Non_Simp[j]->GenInHyp.test(key[k])) {484nr_missing++;485if(nr_missing==2 || nr_zero_i==subfacet_dim) {486common_subfacet=false;487break;488}489}490}491492if(common_subfacet){493add_hyperplane(new_generator,*Pos_Simp[i],*Neg_Non_Simp[j],NewHypsSimp[i],true);494if(nr_zero_i==subfacet_dim) // only one subfacet can lie in negative hyperplane495break;496}497}498#ifndef NCATCH499} catch(const std::exception& ) {500tmp_exception = std::current_exception();501skip_remaining = true;502#pragma omp flush(skip_remaining)503}504#endif505506} // PS vs NS and PS vs N507508if (!skip_remaining) {509#pragma omp single nowait510if (tv_verbose) {511verboseOutput() << "P vs NS and P vs N" << endl;512}513514list<FACETDATA*> AllNonSimpHyp;515typename list<FACETDATA*>::iterator a;516517for(i=0;i<nr_PosNonSimp;++i)518AllNonSimpHyp.push_back(&(*Pos_Non_Simp[i]));519for(i=0;i<nr_NegNonSimp;++i)520AllNonSimpHyp.push_back(&(*Neg_Non_Simp[i]));521for(i=0;i<nr_NeuNonSimp;++i)522AllNonSimpHyp.push_back(&(*Neutral_Non_Simp[i]));523size_t nr_NonSimp = nr_PosNonSimp+nr_NegNonSimp+nr_NeuNonSimp;524525bool ranktest;526FACETDATA *hp_i, *hp_j, *hp_t; // pointers to current hyperplanes527528size_t missing_bound, nr_common_zero;529boost::dynamic_bitset<> common_zero(nr_gen);530vector<key_t> common_key;531common_key.reserve(nr_gen);532vector<int> key_start(nrGensInCone);533534#pragma omp for schedule(dynamic) // nowait535for (size_t i =0; i<nr_PosNonSimp; i++){ //Positive Non Simp vs.Negative Simp and Non Simp536537if (skip_remaining) continue;538539#ifndef NCATCH540try {541#endif542jj_map = Neg_Subfacet.begin(); // First the Simp543for (j=0; j<nr_NegSubf; ++j,++jj_map) {544if ( (*jj_map).second != -1 ) { // skip used subfacets545if(jj_map->first.is_subset_of(Pos_Non_Simp[i]->GenInHyp)){546add_hyperplane(new_generator,*Pos_Non_Simp[i],*Neg_Simp[(*jj_map).second],NewHypsNonSimp[i],true);547(*jj_map).second = -1; // has now been used548}549}550}551552// Now the NonSimp553554hp_i=Pos_Non_Simp[i];555zero_i=Zero_PN & hp_i->GenInHyp; // these are the potential vertices in an intersection556nr_zero_i=0;557int last_existing=-1;558for(size_t jj=0;jj<nrGensInCone;jj++) // we make a "key" of the potential vertices in the intersection559{560j=GensInCone[jj];561if(zero_i.test(j)){562key[nr_zero_i]=j;563for(size_t kk= last_existing+1;kk<=jj;kk++) // used in the extension test564key_start[kk]=nr_zero_i; // to find out from which generator on both have existed565nr_zero_i++;566last_existing= jj;567}568}569if(last_existing< (int)nrGensInCone-1)570for(size_t kk=last_existing+1;kk<nrGensInCone;kk++)571key_start[kk]=nr_zero_i;572573if (nr_zero_i<subfacet_dim)574continue;575576// now nr_zero_i is the number of vertices in hp_i that have a chance to lie in a negative facet577// and key contains the indices578579missing_bound=nr_zero_i-subfacet_dim; // at most this number of generators can be missing580// to have a chance for common subfacet581582for (j=0; j<nr_NegNonSimp; j++){583584585hp_j=Neg_Non_Simp[j];586587if(hp_i->Ident==hp_j->Mother || hp_j->Ident==hp_i->Mother){ // mother and daughter coming together588add_hyperplane(new_generator,*hp_i,*hp_j,NewHypsNonSimp[i],false); // their intersection is a subfacet589continue; // simplicial set in add_hyperplane590}591592593bool extension_test=hp_i->BornAt==hp_j->BornAt || (hp_i->BornAt<hp_j->BornAt && hp_j->Mother!=0)594|| (hp_j->BornAt<hp_i->BornAt && hp_i->Mother!=0);595596// extension_test=false;597598size_t both_existing_from=key_start[max(hp_i->BornAt,hp_j->BornAt)];599600nr_missing=0;601nr_common_zero=0;602common_key.clear();603size_t second_loop_bound=nr_zero_i;604common_subfacet=true;605606// We use the following criterion:607// if the two facets are not mother and daughter (taken care of already), then608// they cannot have intersected in a subfacet at the time when the second was born.609// In other words: they can only intersect in a subfacet now, if at least one common vertex610// has been added after the birth of the younger one.611// this is indicated by "extended".612613if(extension_test){614bool extended=false;615second_loop_bound=both_existing_from; // fisrt we find the common vertices inserted from the step616// where both facets existed the first time617for(k=both_existing_from;k<nr_zero_i;k++){618if(!hp_j->GenInHyp.test(key[k])) {619nr_missing++;620if(nr_missing>missing_bound) {621common_subfacet=false;622break;623}624}625else {626extended=true; // in this case they have a common vertex added after their common existence627common_key.push_back(key[k]);628nr_common_zero++;629}630}631632if(!extended || !common_subfacet) //633continue;634}635636637for(k=0;k<second_loop_bound;k++) { // now the remaining638if(!hp_j->GenInHyp.test(key[k])) {639nr_missing++;640if(nr_missing>missing_bound) {641common_subfacet=false;642break;643}644}645else {646common_key.push_back(key[k]);647nr_common_zero++;648}649}650651if(!common_subfacet)652continue;653/* #pragma omp atomic654NrCSF++;*/655656if(using_GMP<Number>())657ranktest = (nr_NonSimp > GMP_time_factor*dim*dim*nr_common_zero/3); // in this case the rank computation takes longer658else659ranktest = (nr_NonSimp > dim*dim*nr_common_zero/3);660661if(ranktest) {662663// cout << "Rangtest" << endl;664665/* #pragma omp atomic666NrRank++; */667668Matrix<Number>& Test = Top_Cone->RankTest[tn];669if (Test.rank_submatrix(Generators,common_key)<subfacet_dim) {670common_subfacet=false;671}672} // ranktest673else{ // now the comparison test674675/* #pragma omp atomic676NrComp++; */677678common_zero = zero_i & hp_j->GenInHyp;679for (a=AllNonSimpHyp.begin();a!=AllNonSimpHyp.end();++a){680hp_t=*a;681if ((hp_t!=hp_i) && (hp_t!=hp_j) && common_zero.is_subset_of(hp_t->GenInHyp)) {682common_subfacet=false;683AllNonSimpHyp.splice(AllNonSimpHyp.begin(),AllNonSimpHyp,a); // for the "darwinistic" mewthod684break;685}686}687} // else688if (common_subfacet) { //intersection of i and j is a subfacet689add_hyperplane(new_generator,*hp_i,*hp_j,NewHypsNonSimp[i],false); //simplicial set in add_hyperplane690/* #pragma omp atomic691NrNewF++; */692// Indi[j]=true;693}694}695#ifndef NCATCH696} catch(const std::exception& ) {697tmp_exception = std::current_exception();698skip_remaining = true;699#pragma omp flush(skip_remaining)700}701#endif702} // end for703} // end !skip_remaining704} //END parallel705706#ifndef NCATCH707if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);708#endif709//=====================================================================710// parallel until here711712713/* if(!is_pyramid)714cout << "Matches " << NrMatches << " pot. common subf " << NrCSF << " rank test " << NrRank << " comp test "715<< NrComp << " neww hyps " << NrNewF << endl; */716717718for(i=0;i<nr_PosSimp;i++)719Facets.splice(Facets.end(),NewHypsSimp[i]);720721for(i=0;i<nr_PosNonSimp;i++)722Facets.splice(Facets.end(),NewHypsNonSimp[i]);723724//removing the negative hyperplanes725// now done in build_cone726727if (tv_verbose) verboseOutput()<<"transform_values: done"<<endl;728729}730731//---------------------------------------------------------------------------732733template<typename Number>734void Full_Cone<Number>::extend_triangulation(const size_t& new_generator){735// extends the triangulation of this cone by including new_generator736// simplicial facets save us from searching the "brother" in the existing triangulation737// to which the new simplex gets attached738739size_t listsize =old_nr_supp_hyps; // Facets.size();740vector<typename list<FACETDATA>::iterator> visible;741visible.reserve(listsize);742typename list<FACETDATA>::iterator i = Facets.begin();743744listsize=0;745for (; i!=Facets.end(); ++i)746if (i->ValNewGen < 0){ // visible facet747visible.push_back(i);748listsize++;749}750751#ifndef NCATCH752std::exception_ptr tmp_exception;753#endif754755typename list< SHORTSIMPLEX<Number> >::iterator oldTriBack = --TriangulationBuffer.end();756#pragma omp parallel private(i)757{758size_t k,l;759bool one_not_in_i, not_in_facet;760size_t not_in_i=0;761// size_t facet_dim=dim-1;762// size_t nr_in_i=0;763764list< SHORTSIMPLEX<Number> > Triangulation_kk;765typename list< SHORTSIMPLEX<Number> >::iterator j;766767vector<key_t> key(dim);768769// if we only want a partial triangulation but came here because of a deep level770// mark if this part of the triangulation has not to be evaluated771bool skip_eval = false;772773#pragma omp for schedule(dynamic)774for (size_t kk=0; kk<listsize; ++kk) {775776#ifndef NCATCH777try {778#endif779i=visible[kk];780781/* nr_in_i=0;782for(size_t m=0;m<nr_gen;m++){783if(i->GenInHyp.test(m))784nr_in_i++;785if(nr_in_i>facet_dim){786break;787}788}*/789790skip_eval = Top_Cone->do_partial_triangulation && i->ValNewGen == -1791&& is_hyperplane_included(*i);792793if (i->simplicial){ // simplicial794l=0;795for (k = 0; k <nr_gen; k++) {796if (i->GenInHyp[k]==1) {797key[l]=k;798l++;799}800}801key[dim-1]=new_generator;802803if (skip_eval)804store_key(key,0,0,Triangulation_kk);805else806store_key(key,-i->ValNewGen,0,Triangulation_kk);807continue;808} // end simplicial809810size_t irrelevant_vertices=0;811for(size_t vertex=0;vertex<nrGensInCone;++vertex){812813if(i->GenInHyp[GensInCone[vertex]]==0) // lead vertex not in hyperplane814continue;815816if(irrelevant_vertices<dim-2){817++irrelevant_vertices;818continue;819}820821j=TriSectionFirst[vertex];822bool done=false;823for(;!done;j++)824{825done=(j==TriSectionLast[vertex]);826key=j->key;827one_not_in_i=false; // true indicates that one gen of simplex is not in hyperplane828not_in_facet=false; // true indicates that a second gen of simplex is not in hyperplane829for(k=0;k<dim;k++){830if ( !i->GenInHyp.test(key[k])) {831if(one_not_in_i){832not_in_facet=true;833break;834}835one_not_in_i=true;836not_in_i=k;837}838}839840if(not_in_facet) // simplex does not share facet with hyperplane841continue;842843key[not_in_i]=new_generator;844if (skip_eval)845store_key(key,0,j->vol,Triangulation_kk);846else847store_key(key,-i->ValNewGen,j->vol,Triangulation_kk);848849} // j850851} // for vertex852853#ifndef NCATCH854} catch(const std::exception& ) {855tmp_exception = std::current_exception();856}857#endif858859} // omp for kk860861if (multithreaded_pyramid) {862#pragma omp critical(TRIANG)863TriangulationBuffer.splice(TriangulationBuffer.end(),Triangulation_kk);864} else865TriangulationBuffer.splice(TriangulationBuffer.end(),Triangulation_kk);866867} // parallel868869#ifndef NCATCH870if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);871#endif872873// GensInCone.push_back(new_generator); // now in extend_cone874TriSectionFirst.push_back(++oldTriBack);875TriSectionLast.push_back(--TriangulationBuffer.end());876}877878//---------------------------------------------------------------------------879880template<typename Number>881void Full_Cone<Number>::store_key(const vector<key_t>& key, const Number& height,882const Number& mother_vol, list< SHORTSIMPLEX<Number> >& Triangulation){883// stores a simplex given by key and height in Triangulation884// mother_vol is the volume of the simplex to which the new one is attached885886SHORTSIMPLEX<Number> newsimplex;887newsimplex.key=key;888newsimplex.height=height;889newsimplex.vol=0;890891if(multithreaded_pyramid){892#pragma omp atomic893TriangulationBufferSize++;894}895else {896TriangulationBufferSize++;897}898int tn;899if(omp_get_level()==0)900tn=0;901else902tn = omp_get_ancestor_thread_num(1);903904if (height == 0) Top_Cone->triangulation_is_partial = true;905906if (keep_triangulation){907Triangulation.push_back(newsimplex);908return;909}910911bool Simpl_available=true;912913typename list< SHORTSIMPLEX<Number> >::iterator F;914915if(Top_Cone->FS[tn].empty()){916if (Top_Cone->FreeSimpl.empty()) {917Simpl_available=false;918} else {919#pragma omp critical(FREESIMPL)920{921if (Top_Cone->FreeSimpl.empty()) {922Simpl_available=false;923} else {924// take 1000 simplices from FreeSimpl or what you can get925F = Top_Cone->FreeSimpl.begin();926size_t q;927for (q = 0; q < 1000; ++q, ++F) {928if (F == Top_Cone->FreeSimpl.end())929break;930}931932if(q<1000)933Top_Cone->FS[tn].splice(Top_Cone->FS[tn].begin(),934Top_Cone->FreeSimpl);935else936Top_Cone->FS[tn].splice(Top_Cone->FS[tn].begin(),937Top_Cone->FreeSimpl,Top_Cone->FreeSimpl.begin(),F);938} // if empty global (critical)939} // critical940} // if empty global941} // if empty thread942943if (Simpl_available) {944Triangulation.splice(Triangulation.end(),Top_Cone->FS[tn],945Top_Cone->FS[tn].begin());946Triangulation.back() = newsimplex;947} else {948Triangulation.push_back(newsimplex);949}950}951952//---------------------------------------------------------------------------953954template<typename Number>955void Full_Cone<Number>::process_pyramids(const size_t new_generator,const bool recursive){956957/*958959We distinguish two types of pyramids:960961(i) recursive pyramids that give their support hyperplanes back to the mother.962(ii) independent pyramids that are not linked to the mother.963964The parameter "recursive" indicates whether the pyramids that will be created965in process_pyramid(s) are of type (i) or (ii).966967Every pyramid can create subpyramids of both types (not the case in version 2.8 - 2.10).968969Whether "this" is of type (i) or (ii) is indicated by do_all_hyperplanes.970971The creation of (sub)pyramids of type (i) can be blocked by setting recursion_allowed=false.972(Not done in this version.)973974is_pyramid==false for the top_cone and ==true else.975976multithreaded_pyramid indicates whether parallelization takes place within the977computation of a pyramid or whether it is computed in a single thread (defined in build_cone).978979Recursie pyramids are processed immediately after creation (as in 2.8). However, there980are two exceptions:981982(a) In order to avoid very long waiting times for the computation of the "large" ones,983these are treated as follows: the support hyperplanes of "this" coming from their bases984(as negative hyperplanes of "this") are computed by matching them with the985positive hyperplanes of "this". This Fourier-Motzkin step is much more986efficient if a pyramid is large. For triangulation a large recursive987pyramid is then stored as a pyramid of type (ii).988989(b) If "this" is processed in a parallelized loop calling process_pyramids, then990the loop in process_pyramids cannot be interrupted for the evaluation of simplices. As a991consequence an extremely long lst of simplices could arise if many small subpyramids of "this"992are created in process_pyramids. In order to prevent this dangeous effect, small recursive993subpyramids are stored for later triangulation if the simplex buffer has reached its994size bound.995996Pyramids of type (ii) are stpred in Pyramids. The store_level of the created pyramids is 0997for all pyramids created (possibly recursively) from the top cone. Pyramids created998in evaluate_stored_pyramids get the store level for their subpyramids in that routine and999transfer it to their recursive daughters. (correction March 4, 2015).10001001Note: the top cone has pyr_level=-1. The pyr_level has no algorithmic relevance1002at present, but it shows the depth of the pyramid recursion at which the pyramid has been1003created.10041005*/100610071008size_t start_level=omp_get_level(); // allows us to check that we are on level 01009// outside the loop and can therefore call evaluation1010// in order to empty the buffers1011vector<key_t> Pyramid_key;1012Pyramid_key.reserve(nr_gen);1013bool skip_triang; // make hyperplanes but skip triangulation (recursive pyramids only)10141015deque<bool> done(old_nr_supp_hyps,false);1016bool skip_remaining;1017#ifndef NCATCH1018std::exception_ptr tmp_exception;1019#endif1020typename list< FACETDATA >::iterator hyp;1021size_t nr_done=0;10221023do{ // repeats processing until all hyperplanes have been processed10241025hyp=Facets.begin();1026size_t hyppos=0;1027skip_remaining = false;10281029const long VERBOSE_STEPS = 50;1030long step_x_size = old_nr_supp_hyps-VERBOSE_STEPS;1031const size_t RepBound=10000;10321033#pragma omp parallel for private(skip_triang) firstprivate(hyppos,hyp,Pyramid_key) schedule(dynamic) reduction(+: nr_done)1034for (size_t kk=0; kk<old_nr_supp_hyps; ++kk) {10351036if (skip_remaining) continue;10371038if(verbose && old_nr_supp_hyps>=RepBound){1039#pragma omp critical(VERBOSE)1040while ((long)(kk*VERBOSE_STEPS) >= step_x_size) {1041step_x_size += old_nr_supp_hyps;1042verboseOutput() << "." <<flush;1043}1044}10451046#ifndef NCATCH1047try {1048#endif1049for(;kk > hyppos; hyppos++, hyp++) ;1050for(;kk < hyppos; hyppos--, hyp--) ;10511052if(done[hyppos])1053continue;10541055done[hyppos]=true;10561057nr_done++;10581059if (hyp->ValNewGen == 0){ // MUST BE SET HERE1060hyp->GenInHyp.set(new_generator);1061if(recursive) hyp->simplicial=false; // in the recursive case1062}10631064if (hyp->ValNewGen >= 0) // facet not visible1065continue;10661067skip_triang = false;1068if (Top_Cone->do_partial_triangulation && hyp->ValNewGen>=-1) { //ht1 criterion1069skip_triang = is_hyperplane_included(*hyp);1070if (skip_triang) {1071Top_Cone->triangulation_is_partial = true;1072if (!recursive) {1073continue;1074}1075}1076}10771078Pyramid_key.clear(); // make data of new pyramid1079Pyramid_key.push_back(new_generator);1080for(size_t i=0;i<nr_gen;i++){1081if(in_triang[i] && hyp->GenInHyp.test(i)) {1082Pyramid_key.push_back(i);1083}1084}10851086// now we can store the new pyramid at the right place (or finish the simplicial ones)1087if (recursive && skip_triang) { // mark as "do not triangulate"1088process_pyramid(Pyramid_key, new_generator,store_level,0, recursive,hyp,start_level);1089} else { //default1090process_pyramid(Pyramid_key, new_generator,store_level,-hyp->ValNewGen, recursive,hyp,start_level);1091}1092// interrupt parallel execution if it is really parallel1093// to keep the triangulationand pyramid buffers under control1094if (start_level==0) {1095if (check_evaluation_buffer_size() || Top_Cone->check_pyr_buffer(store_level)) {1096skip_remaining = true;1097}1098}10991100#ifndef NCATCH1101} catch(const std::exception& ) {1102tmp_exception = std::current_exception();1103skip_remaining = true;1104#pragma omp flush(skip_remaining)1105}1106#endif1107} // end parallel loop over hyperplanes11081109#ifndef NCATCH1110if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1111#endif11121113if (start_level==0 && check_evaluation_buffer_size()) {1114Top_Cone->evaluate_triangulation();1115}11161117if (start_level==0 && Top_Cone->check_pyr_buffer(store_level)) {1118Top_Cone->evaluate_stored_pyramids(store_level);1119}11201121if (verbose && old_nr_supp_hyps>=RepBound)1122verboseOutput() << endl;11231124} while (nr_done < old_nr_supp_hyps);112511261127evaluate_large_rec_pyramids(new_generator);11281129}11301131//---------------------------------------------------------------------------11321133template<typename Number>1134void Full_Cone<Number>::process_pyramid(const vector<key_t>& Pyramid_key,1135const size_t new_generator,const size_t store_level, Number height, const bool recursive,1136typename list< FACETDATA >::iterator hyp, size_t start_level){1137// processes simplicial pyramids directly, stores other pyramids into their depots11381139#pragma omp atomic1140Top_Cone->totalNrPyr++;11411142if(Pyramid_key.size()==dim){ // simplicial pyramid completely done here1143#pragma omp atomic // only for saving memory1144Top_Cone->nrSimplicialPyr++;1145if(recursive){ // the facets may be facets of the mother cone and if recursive==true must be given back1146Matrix<Number> H(dim,dim);1147Number dummy_vol;1148Generators.simplex_data(Pyramid_key,H, dummy_vol,false);1149list<FACETDATA> NewFacets;1150FACETDATA NewFacet;1151NewFacet.GenInHyp.resize(nr_gen);1152for (size_t i=0; i<dim;i++) {1153NewFacet.Hyp = H[i];1154NewFacet.GenInHyp.set();1155NewFacet.GenInHyp.reset(i);1156NewFacet.simplicial=true;1157NewFacets.push_back(NewFacet);1158}1159select_supphyps_from(NewFacets,new_generator,Pyramid_key); // takes itself care of multithreaded_pyramid1160}1161if (height != 0 && (do_triangulation || do_partial_triangulation)) {1162if(multithreaded_pyramid) {1163#ifndef NCATCH1164std::exception_ptr tmp_exception;1165#endif1166#pragma omp critical(TRIANG)1167{1168#ifndef NCATCH1169try{1170#endif1171store_key(Pyramid_key,height,0,TriangulationBuffer);1172nrTotalComparisons+=dim*dim/2;1173#ifndef NCATCH1174} catch(const std::exception& ) {1175tmp_exception = std::current_exception();1176}1177#endif1178} // end critical1179#ifndef NCATCH1180if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1181#endif1182} else {1183store_key(Pyramid_key,height,0,TriangulationBuffer);1184nrTotalComparisons+=dim*dim/2;1185}1186}1187}1188else { // non-simplicial11891190bool large=(largePyramidFactor*Comparisons[Pyramid_key.size()-dim] > old_nr_supp_hyps); // Pyramid_key.size()>largePyramidFactor*dim;11911192if (!recursive || (large && (do_triangulation || do_partial_triangulation) && height!=0) ) { // must also store for triangulation if recursive and large1193vector<key_t> key_wrt_top(Pyramid_key.size());1194for(size_t i=0;i<Pyramid_key.size();i++)1195key_wrt_top[i]=Top_Key[Pyramid_key[i]];1196#pragma omp critical(STOREPYRAMIDS)1197{1198// cout << "store_level " << store_level << " large " << large << " pyr level " << pyr_level << endl;1199Top_Cone->Pyramids[store_level].push_back(key_wrt_top);1200Top_Cone->nrPyramids[store_level]++;1201} // critical1202if(!recursive) // in this case we need only store for future triangulation, and that has been done1203return;1204}1205// now we are in the recursive case and must compute support hyperplanes of the subpyramid1206if(large){ // large recursive pyramid1207if(multithreaded_pyramid){1208#pragma omp critical(LARGERECPYRS)1209LargeRecPyrs.push_back(*hyp); // LargeRecPyrs are kept and evaluated locally1210}1211else1212LargeRecPyrs.push_back(*hyp);1213return; // done with the large recusive pyramids1214}12151216// only recursive small ones left12171218Full_Cone<Number> Pyramid(*this,Pyramid_key);1219Pyramid.Mother = this;1220Pyramid.Mother_Key = Pyramid_key; // need these data to give back supphyps1221Pyramid.apex=new_generator;1222if (height == 0) { //indicates "do not triangulate"1223Pyramid.do_triangulation = false;1224Pyramid.do_partial_triangulation = false;1225// Pyramid.do_Hilbert_basis = false;1226// Pyramid.do_deg1_elements=false;1227}12281229bool store_for_triangulation=(store_level!=0) //loop in process_pyramids cannot be interrupted1230&& (Pyramid.do_triangulation || Pyramid.do_partial_triangulation) // we must (partially) triangulate1231&& (start_level!=0 && Top_Cone->TriangulationBufferSize > 2*EvalBoundTriang); // evaluation buffer already full // EvalBoundTriang12321233if (store_for_triangulation) {1234vector<key_t> key_wrt_top(Pyramid_key.size());1235for(size_t i=0;i<Pyramid_key.size();i++)1236key_wrt_top[i]=Top_Key[Pyramid_key[i]];1237#pragma omp critical(STOREPYRAMIDS)1238{1239Top_Cone->Pyramids[store_level].push_back(key_wrt_top);1240Top_Cone->nrPyramids[store_level]++;1241} // critical1242// Now we must suppress immediate triangulation1243Pyramid.do_triangulation = false;1244Pyramid.do_partial_triangulation = false;1245// Pyramid.do_Hilbert_basis = false;1246// Pyramid.do_deg1_elements=false;1247}12481249Pyramid.build_cone();12501251if(multithreaded_pyramid){1252#pragma omp atomic1253nrTotalComparisons+=Pyramid.nrTotalComparisons;1254} else1255nrTotalComparisons+=Pyramid.nrTotalComparisons;1256} // else non-simplicial1257}125812591260//---------------------------------------------------------------------------12611262template<typename Number>1263void Full_Cone<Number>::find_and_evaluate_start_simplex(){12641265size_t i,j;1266Number factor;126712681269/* Simplex<Number> S = find_start_simplex();1270vector<key_t> key=S.read_key(); // generators indexed from 0 */12711272vector<key_t> key=find_start_simplex();1273assert(key.size()==dim); // safety heck1274if(verbose){1275verboseOutput() << "Start simplex ";1276for(size_t i=0;i<key.size();++i)1277verboseOutput() << key[i]+1 << " ";1278verboseOutput() << endl;1279}1280Matrix<Number> H(dim,dim);1281Number vol;1282Generators.simplex_data(key,H,vol,do_partial_triangulation || do_triangulation);12831284// H.pretty_print(cout);128512861287for (i = 0; i < dim; i++) {1288in_triang[key[i]]=true;1289GensInCone.push_back(key[i]);1290if (deg1_triangulation && isComputed(ConeProperty::Grading))1291deg1_triangulation = (gen_degrees[key[i]] == 1);1292}12931294nrGensInCone=dim;12951296nrTotalComparisons=dim*dim/2;1297if(using_GMP<Number>())1298nrTotalComparisons*=GMP_time_factor/2; // because of the linear algebra involved in this routine1299Comparisons.push_back(nrTotalComparisons);13001301for (i = 0; i <dim; i++) {1302FACETDATA NewFacet; NewFacet.GenInHyp.resize(nr_gen);1303NewFacet.Hyp=H[i];1304NewFacet.simplicial=true; // indeed, the start simplex is simplicial1305for(j=0;j < dim;j++)1306if(j!=i)1307NewFacet.GenInHyp.set(key[j]);1308NewFacet.ValNewGen=-1; // must be taken negative since opposite facet1309number_hyperplane(NewFacet,0,0); // created with gen 01310Facets.push_back(NewFacet); // was visible before adding this vertex1311}13121313if(!is_pyramid){1314//define Order_Vector, decides which facets of the simplices are excluded1315Order_Vector = vector<Number>(dim,0);1316// Matrix<Number> G=S.read_generators();1317for(i=0;i<dim;i++){1318factor=(unsigned long) (1+i%10); // (2*(rand()%(2*dim))+3);1319for(j=0;j<dim;j++)1320Order_Vector[j]+=factor*Generators[key[i]][j];1321}1322}13231324//the volume is an upper bound for the height1325if(do_triangulation || (do_partial_triangulation && vol>1))1326{1327store_key(key,vol,1,TriangulationBuffer);1328if(do_only_multiplicity) {1329#pragma omp atomic1330TotDet++;1331}1332} else if (do_partial_triangulation) {1333triangulation_is_partial = true;1334}13351336if(do_triangulation){ // we must prepare the sections of the triangulation1337for(i=0;i<dim;i++)1338{1339// GensInCone.push_back(key[i]); // now done in first loop since always needed1340TriSectionFirst.push_back(TriangulationBuffer.begin());1341TriSectionLast.push_back(TriangulationBuffer.begin());1342}1343}13441345}134613471348//---------------------------------------------------------------------------13491350template<typename Number>1351void Full_Cone<Number>::select_supphyps_from(const list<FACETDATA>& NewFacets,1352const size_t new_generator, const vector<key_t>& Pyramid_key){1353// the mother cone (=this) selects supphyps from the list NewFacets supplied by the daughter1354// the daughter provides the necessary information via the parameters13551356size_t i;1357boost::dynamic_bitset<> in_Pyr(nr_gen);1358for (i=0; i<Pyramid_key.size(); i++) {1359in_Pyr.set(Pyramid_key[i]);1360}1361// the new generator is always the first in the pyramid1362assert(Pyramid_key[0] == new_generator);136313641365typename list<FACETDATA>::const_iterator pyr_hyp = NewFacets.begin();1366bool new_global_hyp;1367FACETDATA NewFacet;1368NewFacet.GenInHyp.resize(nr_gen);1369Number test;1370for (; pyr_hyp!=NewFacets.end(); ++pyr_hyp) {1371if(!pyr_hyp->GenInHyp.test(0)) // new gen not in hyp1372continue;1373new_global_hyp=true;1374for (i=0; i<nr_gen; ++i){1375if(in_Pyr.test(i) || !in_triang[i])1376continue;1377test=v_scalar_product(Generators[i],pyr_hyp->Hyp);1378if(test<=0){1379new_global_hyp=false;1380break;1381}13821383}1384if(new_global_hyp){1385NewFacet.Hyp=pyr_hyp->Hyp;1386NewFacet.GenInHyp.reset();1387// size_t gens_in_facet=0;1388for (i=0; i<Pyramid_key.size(); ++i) {1389if (pyr_hyp->GenInHyp.test(i) && in_triang[Pyramid_key[i]]) {1390NewFacet.GenInHyp.set(Pyramid_key[i]);1391// gens_in_facet++;1392}1393}1394/* for (i=0; i<nr_gen; ++i) {1395if (NewFacet.GenInHyp.test(i) && in_triang[i]) {1396gens_in_facet++;1397}1398}*/1399// gens_in_facet++; // Note: new generator not yet in in_triang1400NewFacet.GenInHyp.set(new_generator);1401NewFacet.simplicial=pyr_hyp->simplicial; // (gens_in_facet==dim-1);1402check_simpliciality_hyperplane(NewFacet);1403number_hyperplane(NewFacet,nrGensInCone,0); //mother unknown1404if(multithreaded_pyramid){1405#pragma omp critical(GIVEBACKHYPS)1406Facets.push_back(NewFacet);1407} else {1408Facets.push_back(NewFacet);1409}1410}1411}1412}14131414//---------------------------------------------------------------------------1415template<typename Number>1416void Full_Cone<Number>::match_neg_hyp_with_pos_hyps(const FACETDATA& hyp, size_t new_generator,list<FACETDATA*>& PosHyps, boost::dynamic_bitset<>& Zero_P){14171418size_t missing_bound, nr_common_zero;1419boost::dynamic_bitset<> common_zero(nr_gen);1420vector<key_t> common_key;1421common_key.reserve(nr_gen);1422vector<key_t> key(nr_gen);1423bool common_subfacet;1424list<FACETDATA> NewHyp;1425size_t subfacet_dim=dim-2;1426size_t nr_missing;1427typename list<FACETDATA*>::iterator a;1428list<FACETDATA> NewHyps;1429Matrix<Number> Test(0,dim);14301431boost::dynamic_bitset<> zero_hyp=hyp.GenInHyp & Zero_P; // we intersect with the set of gens in positive hyps14321433size_t nr_zero_hyp=0;1434vector<int> key_start(nrGensInCone);1435size_t j;1436int last_existing=-1;1437for(size_t jj=0;jj<nrGensInCone;jj++)1438{1439j=GensInCone[jj];1440if(zero_hyp.test(j)){1441key[nr_zero_hyp]=j;1442for(size_t kk= last_existing+1;kk<=jj;kk++)1443key_start[kk]=nr_zero_hyp;1444nr_zero_hyp++;1445last_existing= jj;1446}1447}1448if(last_existing< (int)nrGensInCone-1)1449for(size_t kk=last_existing+1;kk<nrGensInCone;kk++)1450key_start[kk]=nr_zero_hyp;14511452if (nr_zero_hyp<dim-2)1453return;14541455int tn = omp_get_ancestor_thread_num(1);1456missing_bound=nr_zero_hyp-subfacet_dim; // at most this number of generators can be missing1457// to have a chance for common subfacet14581459typename list< FACETDATA*>::iterator hp_j_iterator=PosHyps.begin();14601461FACETDATA* hp_j;14621463for (;hp_j_iterator!=PosHyps.end();++hp_j_iterator){ //match hyp with the given Pos1464hp_j=*hp_j_iterator;14651466if(hyp.Ident==hp_j->Mother || hp_j->Ident==hyp.Mother){ // mother and daughter coming together1467// their intersection is a subfacet1468add_hyperplane(new_generator,*hp_j,hyp,NewHyps,false); // simplicial set in add_hyperplane1469continue;1470}147114721473bool extension_test=hyp.BornAt==hp_j->BornAt || (hyp.BornAt<hp_j->BornAt && hp_j->Mother!=0)1474|| (hp_j->BornAt<hyp.BornAt && hyp.Mother!=0);14751476size_t both_existing_from=key_start[max(hyp.BornAt,hp_j->BornAt)];14771478nr_missing=0;1479nr_common_zero=0;1480common_key.clear();1481size_t second_loop_bound=nr_zero_hyp;1482common_subfacet=true;1483boost::dynamic_bitset<> common_zero(nr_gen);14841485if(extension_test){1486bool extended=false;1487second_loop_bound=both_existing_from;1488for(size_t k=both_existing_from;k<nr_zero_hyp;k++){1489if(!hp_j->GenInHyp.test(key[k])) {1490nr_missing++;1491if(nr_missing>missing_bound) {1492common_subfacet=false;1493break;1494}1495}1496else {1497extended=true;1498common_key.push_back(key[k]);1499common_zero.set(key[k]);1500nr_common_zero++;1501}1502}15031504if(!extended || !common_subfacet) //1505continue;1506}15071508for(size_t k=0;k<second_loop_bound;k++) {1509if(!hp_j->GenInHyp.test(key[k])) {1510nr_missing++;1511if(nr_missing>missing_bound) {1512common_subfacet=false;1513break;1514}1515}1516else {1517common_key.push_back(key[k]);1518common_zero.set(key[k]);1519nr_common_zero++;1520}1521}15221523if(!common_subfacet)1524continue;15251526assert(nr_common_zero >=subfacet_dim);152715281529if (!hp_j->simplicial){15301531bool ranktest;1532/* if(using_GMP<Number>())1533ranktest = (old_nr_supp_hyps > 10*GMP_time_factor*dim*dim*nr_common_zero/3); // in this case the rank computation takes longer1534else1535ranktest = (old_nr_supp_hyps > 10*dim*dim*nr_common_zero/3); */15361537ranktest=true;15381539if(ranktest){1540// cout << "Rank" << endl;1541Matrix<Number>& Test = Top_Cone->RankTest[tn];1542if(Test.rank_submatrix(Generators,common_key)<subfacet_dim)1543common_subfacet=false; // don't make a hyperplane1544}1545else{ // now the comparison test1546// cout << "Compare" << endl;1547auto hp_t=Facets.begin();1548for (;hp_t!=Facets.end();++hp_t){1549if(hp_t->simplicial)1550continue;1551if ((hp_t->Ident!=hyp.Ident) && (hp_t->Ident!=hp_j->Ident) && common_zero.is_subset_of(hp_t->GenInHyp)) {1552common_subfacet=false;1553break;1554}1555}1556} // else1557} // !simplicial15581559if(common_subfacet)1560add_hyperplane(new_generator,*hp_j,hyp,NewHyps,false); // simplicial set in add_hyperplane1561} // for15621563if(multithreaded_pyramid)1564#pragma omp critical(GIVEBACKHYPS)1565Facets.splice(Facets.end(),NewHyps);1566else1567Facets.splice(Facets.end(),NewHyps);15681569}15701571//---------------------------------------------------------------------------1572template<typename Number>1573void Full_Cone<Number>::collect_pos_supphyps(list<FACETDATA*>& PosHyps, boost::dynamic_bitset<>& Zero_P, size_t& nr_pos){15741575// positive facets are collected in a list15761577typename list<FACETDATA>::iterator ii = Facets.begin();1578nr_pos=0;15791580for (size_t ij=0; ij< old_nr_supp_hyps; ++ij, ++ii)1581if (ii->ValNewGen>0) {1582Zero_P |= ii->GenInHyp;1583PosHyps.push_back(&(*ii));1584nr_pos++;1585}1586}15871588//---------------------------------------------------------------------------1589template<typename Number>1590void Full_Cone<Number>::evaluate_large_rec_pyramids(size_t new_generator){15911592size_t nrLargeRecPyrs=LargeRecPyrs.size();1593if(nrLargeRecPyrs==0)1594return;15951596if(verbose)1597verboseOutput() << "large pyramids " << nrLargeRecPyrs << endl;15981599list<FACETDATA*> PosHyps;1600boost::dynamic_bitset<> Zero_P(nr_gen);1601size_t nr_pos;1602collect_pos_supphyps(PosHyps,Zero_P,nr_pos);16031604nrTotalComparisons+=nr_pos*nrLargeRecPyrs;1605#ifndef NCATCH1606std::exception_ptr tmp_exception;1607#endif16081609const long VERBOSE_STEPS = 50;1610long step_x_size = nrLargeRecPyrs-VERBOSE_STEPS;1611const size_t RepBound=100;16121613#pragma omp parallel1614{1615size_t ppos=0;1616typename list<FACETDATA>::iterator p=LargeRecPyrs.begin();16171618#pragma omp for schedule(dynamic)1619for(size_t i=0; i<nrLargeRecPyrs; i++){1620for(; i > ppos; ++ppos, ++p) ;1621for(; i < ppos; --ppos, --p) {};16221623if(verbose && nrLargeRecPyrs>=RepBound){1624#pragma omp critical(VERBOSE)1625while ((long)(i*VERBOSE_STEPS) >= step_x_size) {1626step_x_size += nrLargeRecPyrs;1627verboseOutput() << "." <<flush;1628}1629}16301631#ifndef NCATCH1632try {1633#endif1634match_neg_hyp_with_pos_hyps(*p,new_generator,PosHyps,Zero_P);1635#ifndef NCATCH1636} catch(const std::exception& ) {1637tmp_exception = std::current_exception();1638}1639#endif1640}1641} // parallel1642#ifndef NCATCH1643if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1644#endif16451646if(verbose && nrLargeRecPyrs>=RepBound)1647verboseOutput() << endl;16481649LargeRecPyrs.clear();1650}16511652//---------------------------------------------------------------------------16531654template<typename Number>1655bool Full_Cone<Number>::check_pyr_buffer(const size_t level){1656if(level==0)1657return(nrPyramids[0] > EvalBoundLevel0Pyr);1658else1659return(nrPyramids[level] > EvalBoundPyr);1660}16611662//---------------------------------------------------------------------------16631664template<typename Number>1665void Full_Cone<Number>::evaluate_stored_pyramids(const size_t level){1666// evaluates the stored non-recursive pyramids16671668assert(!omp_in_parallel());16691670if(Pyramids[level].empty())1671return;1672if (Pyramids.size() < level+2) {1673Pyramids.resize(level+2); // provide space for a new generation1674nrPyramids.resize(level+2, 0);1675}16761677size_t eval_down_to = 0;16781679#ifdef NMZ_MIC_OFFLOAD1680#ifndef __MIC__1681// only on host and if offload is available1682if (level == 0 && nrPyramids[0] > EvalBoundLevel0Pyr) {1683eval_down_to = EvalBoundLevel0Pyr;1684}1685#endif1686#endif16871688vector<char> Done(nrPyramids[level],0);1689if (verbose) {1690verboseOutput() << "**************************************************" << endl;16911692for (size_t l=0; l<=level; ++l) {1693if (nrPyramids[l]>0) {1694verboseOutput() << "level " << l << " pyramids remaining: "1695<< nrPyramids[l] << endl;1696}1697}1698verboseOutput() << "**************************************************" << endl;1699}1700typename list<vector<key_t> >::iterator p;1701size_t ppos;1702bool skip_remaining;1703#ifndef NCATCH1704std::exception_ptr tmp_exception;1705#endif17061707while (nrPyramids[level] > eval_down_to) {17081709p = Pyramids[level].begin();1710ppos=0;1711skip_remaining = false;17121713#pragma omp parallel for firstprivate(p,ppos) schedule(dynamic)1714for(size_t i=0; i<nrPyramids[level]; i++){1715if (skip_remaining)1716continue;1717for(; i > ppos; ++ppos, ++p) ;1718for(; i < ppos; --ppos, --p) ;17191720if(Done[i])1721continue;1722Done[i]=1;17231724#ifndef NCATCH1725try {1726#endif1727Full_Cone<Number> Pyramid(*this,*p);1728// Pyramid.recursion_allowed=false;1729Pyramid.do_all_hyperplanes=false;1730if (level>=2 && do_partial_triangulation){ // limits the descent of do_partial_triangulation1731Pyramid.do_triangulation=true;1732Pyramid.do_partial_triangulation=false;1733}1734Pyramid.store_level=level+1;1735Pyramid.build_cone();1736if (check_evaluation_buffer_size() || Top_Cone->check_pyr_buffer(level+1)) {1737// interrupt parallel execution to keep the buffer under control1738skip_remaining = true;1739}1740#ifndef NCATCH1741} catch(const std::exception& ) {1742tmp_exception = std::current_exception();1743skip_remaining = true;1744#pragma omp flush(skip_remaining)1745}1746#endif1747} //end parallel for1748#ifndef NCATCH1749if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1750#endif17511752// remove done pyramids1753p = Pyramids[level].begin();1754for(size_t i=0; p != Pyramids[level].end(); i++){1755if (Done[i]) {1756p=Pyramids[level].erase(p);1757nrPyramids[level]--;1758Done[i]=0;1759} else {1760++p;1761}1762}17631764if (check_evaluation_buffer_size()) {1765if (verbose)1766verboseOutput() << nrPyramids[level] <<1767" pyramids remaining on level " << level << ", ";1768Top_Cone->evaluate_triangulation();1769}17701771if (Top_Cone->check_pyr_buffer(level+1)) {1772evaluate_stored_pyramids(level+1);1773}17741775} //end while (nrPyramids[level] > 0)17761777if (verbose) {1778verboseOutput() << "**************************************************" << endl;1779verboseOutput() << "all pyramids on level "<< level << " done!"<<endl;1780if (nrPyramids[level+1] == 0) {1781for (size_t l=0; l<=level; ++l) {1782if (nrPyramids[l]>0) {1783verboseOutput() << "level " << l << " pyramids remaining: "1784<< nrPyramids[l] << endl;1785}1786}1787verboseOutput() << "**************************************************" << endl;1788}1789}1790if(check_evaluation_buffer())1791{1792Top_Cone->evaluate_triangulation();1793}17941795evaluate_stored_pyramids(level+1);1796}1797179817991800//---------------------------------------------------------------------------18011802/* builds the cone successively by inserting generators */1803template<typename Number>1804void Full_Cone<Number>::build_cone() {1805// if(dim>0){ //correction needed to include the 0 cone;18061807// cout << "Pyr " << pyr_level << endl;18081809long long RecBoundSuppHyp;1810RecBoundSuppHyp = dim*dim*dim*SuppHypRecursionFactor; //dim^3 * 501811if(using_GMP<Number>())1812RecBoundSuppHyp*=GMP_time_factor; // pyramid building is more difficult for complicated arithmetic18131814size_t RecBoundTriang=1000000; // if number(supphyps)*size(triang) > RecBoundTriang pass to pyramids1815if(using_GMP<Number>())1816RecBoundTriang*=GMP_time_factor;18171818tri_recursion=false;18191820multithreaded_pyramid=(omp_get_level()==0);18211822if(!use_existing_facets){1823if(multithreaded_pyramid){1824HypCounter.resize(omp_get_max_threads());1825for(size_t i=0;i<HypCounter.size();++i)1826HypCounter[i]=i+1;1827} else{1828HypCounter.resize(1);1829HypCounter[0]=1;1830}18311832find_and_evaluate_start_simplex();1833}18341835size_t last_to_be_inserted; // good to know in case of do_all_hyperplanes==false1836last_to_be_inserted=nr_gen-1; // because we don't need to compute support hyperplanes in this case1837for(int j=nr_gen-1;j>=0;--j){1838if(!in_triang[j]){1839last_to_be_inserted=j;1840break;1841}1842} // last_to_be_inserted now determined18431844bool is_new_generator;1845typename list< FACETDATA >::iterator l;184618471848for (size_t i=start_from;i<nr_gen;++i) {18491850start_from=i;18511852if (in_triang[i])1853continue;18541855if(do_triangulation && TriangulationBufferSize > 2*RecBoundTriang) // emermergency brake1856tri_recursion=true; // to switch off production of simplices in favor1857// of non-recursive pyramids1858Number scalar_product;1859is_new_generator=false;1860l=Facets.begin();1861old_nr_supp_hyps=Facets.size(); // Facets will be xtended in the loop18621863long long nr_pos=0, nr_neg=0;1864long long nr_neg_simp=0, nr_pos_simp=0;1865vector<Number> L;1866#ifndef NCATCH1867std::exception_ptr tmp_exception;1868#endif18691870size_t lpos=0;1871#pragma omp parallel for private(L,scalar_product) firstprivate(lpos,l) reduction(+: nr_pos, nr_neg)1872for (size_t k=0; k<old_nr_supp_hyps; k++) {1873#ifndef NCATCH1874try {1875#endif1876for(;k > lpos; lpos++, l++) ;1877for(;k < lpos; lpos--, l--) ;18781879L=Generators[i];1880scalar_product=v_scalar_product(L,(*l).Hyp);1881l->ValNewGen=scalar_product;1882if (scalar_product<0) {1883is_new_generator=true;1884nr_neg++;1885if(l->simplicial)1886#pragma omp atomic1887nr_neg_simp++;1888}1889if (scalar_product>0) {1890nr_pos++;1891if(l->simplicial)1892#pragma omp atomic1893nr_pos_simp++;1894}1895#ifndef NCATCH1896} catch(const std::exception& ) {1897tmp_exception = std::current_exception();1898}1899#endif1900} //end parallel for1901#ifndef NCATCH1902if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1903#endif19041905if(!is_new_generator)1906continue;19071908// the i-th generator is used in the triangulation1909// in_triang[i]=true; // now at end of loop1910if (deg1_triangulation && isComputed(ConeProperty::Grading))1911deg1_triangulation = (gen_degrees[i] == 1);19121913/* if(!is_pyramid && verbose )1914verboseOutput() << "Neg " << nr_neg << " Pos " << nr_pos << " NegSimp " <<nr_neg_simp << " PosSimp " <<nr_pos_simp << endl;*/1915// First we test whether to go to recursive pyramids because of too many supphyps1916// cout << "GMP " << using_GMP<Number>() << " Bound " << RecBoundSuppHyp << " " << nr_neg*nr_pos-(nr_neg_simp*nr_pos_simp) << endl;1917if (recursion_allowed && nr_neg*nr_pos-(nr_neg_simp*nr_pos_simp) > RecBoundSuppHyp) { // use pyramids because of supphyps1918/* if(!is_pyramid && verbose )1919verboseOutput() << "Building pyramids" << endl; */1920if (do_triangulation)1921tri_recursion = true; // We can not go back to classical triangulation1922if(check_evaluation_buffer()){1923Top_Cone->evaluate_triangulation();1924}19251926process_pyramids(i,true); //recursive1927lastGen=i;1928nextGen=i+1;1929}1930else{ // now we check whether to go to pyramids because of the size of triangulation1931// once we have done so, we must stay with it1932if( tri_recursion || (do_triangulation1933&& (nr_neg*TriangulationBufferSize > RecBoundTriang1934|| 3*omp_get_max_threads()*TriangulationBufferSize>EvalBoundTriang ))){ // go to pyramids because of triangulation1935if(check_evaluation_buffer()){1936Top_Cone->evaluate_triangulation();1937}1938tri_recursion=true;1939process_pyramids(i,false); //non-recursive1940}1941else{ // no pyramids necesary1942if(do_partial_triangulation)1943process_pyramids(i,false); // non-recursive1944if(do_triangulation)1945extend_triangulation(i);1946}19471948if(do_all_hyperplanes || i!=last_to_be_inserted)1949find_new_facets(i);1950}19511952// removing the negative hyperplanes if necessary1953if(do_all_hyperplanes || i!=last_to_be_inserted){1954l=Facets.begin();1955for (size_t j=0; j<old_nr_supp_hyps;j++){1956if (l->ValNewGen<0) {1957l=Facets.erase(l);1958}1959else1960++l;1961}1962}19631964GensInCone.push_back(i);1965nrGensInCone++;19661967Comparisons.push_back(nrTotalComparisons);19681969if(verbose) {1970verboseOutput() << "gen="<< i+1 <<", ";1971if (do_all_hyperplanes || i!=last_to_be_inserted) {1972verboseOutput() << Facets.size()<<" hyp";1973} else {1974verboseOutput() << Support_Hyperplanes.nr_of_rows()<<" hyp";1975}1976if(nrPyramids[0]>0)1977verboseOutput() << ", " << nrPyramids[0] << " pyr";1978if(do_triangulation||do_partial_triangulation)1979verboseOutput() << ", " << TriangulationBufferSize << " simpl";1980verboseOutput()<< endl;1981}19821983in_triang[i]=true;19841985} // loop over i19861987start_from=nr_gen;19881989if (is_pyramid && do_all_hyperplanes) // must give supphyps back to mother1990Mother->select_supphyps_from(Facets, apex, Mother_Key);19911992// transfer Facets --> SupportHyperplanes1993if (do_all_hyperplanes) {1994nrSupport_Hyperplanes = Facets.size();1995Support_Hyperplanes = Matrix<Number>(nrSupport_Hyperplanes,0);1996typename list<FACETDATA>::iterator IHV=Facets.begin();1997for (size_t i=0; i<nrSupport_Hyperplanes; ++i, ++IHV) {1998swap(Support_Hyperplanes[i],IHV->Hyp);1999}2000is_Computed.set(ConeProperty::SupportHyperplanes);2001}2002Support_Hyperplanes.set_nr_of_columns(dim);200320042005if(do_extreme_rays && do_all_hyperplanes)2006compute_extreme_rays(true);20072008transfer_triangulation_to_top(); // transfer remaining simplices to top2009if(check_evaluation_buffer()){2010Top_Cone->evaluate_triangulation();2011}20122013// } // end if (dim>0)20142015Facets.clear();20162017}20182019template<typename Number>2020void Full_Cone<Number>::start_message() {20212022if (verbose) {2023verboseOutput()<<"************************************************************"<<endl;2024verboseOutput()<<"starting primal algorithm ";2025if (do_partial_triangulation) verboseOutput()<<"with partial triangulation ";2026if (do_triangulation) {2027verboseOutput()<<"with full triangulation ";2028}2029if (!do_triangulation && !do_partial_triangulation) verboseOutput()<<"(only support hyperplanes) ";2030verboseOutput()<<"..."<<endl;2031}2032}20332034template<typename Number>2035void Full_Cone<Number>::end_message() {20362037if (verbose) {2038verboseOutput() << "------------------------------------------------------------"<<endl;2039}2040}204120422043//---------------------------------------------------------------------------20442045template<typename Number>2046void Full_Cone<Number>::build_top_cone() {20472048if(dim==0)2049return;20502051// if( ( !do_bottom_dec || deg1_generated || dim==1 || (!do_triangulation && !do_partial_triangulation))) {2052build_cone();2053// }20542055evaluate_stored_pyramids(0); // force evaluation of remaining pyramids2056}20572058//---------------------------------------------------------------------------20592060template<typename Number>2061bool Full_Cone<Number>::check_evaluation_buffer(){20622063return(omp_get_level()==0 && check_evaluation_buffer_size());2064}20652066//---------------------------------------------------------------------------20672068template<typename Number>2069bool Full_Cone<Number>::check_evaluation_buffer_size(){20702071return(!Top_Cone->keep_triangulation &&2072Top_Cone->TriangulationBufferSize > EvalBoundTriang);2073}20742075//---------------------------------------------------------------------------20762077template<typename Number>2078void Full_Cone<Number>::transfer_triangulation_to_top(){ // NEW EVA20792080size_t i;20812082// cout << "Pyr level " << pyr_level << endl;20832084if(!is_pyramid) { // we are in top cone2085if(check_evaluation_buffer()){2086evaluate_triangulation();2087}2088return; // no transfer necessary2089}20902091// now we are in a pyramid20922093// cout << "In pyramid " << endl;2094int tn = 0;2095if (omp_in_parallel())2096tn = omp_get_ancestor_thread_num(1);20972098typename list< SHORTSIMPLEX<Number> >::iterator pyr_simp=TriangulationBuffer.begin();2099while (pyr_simp!=TriangulationBuffer.end()) {2100if (pyr_simp->height == 0) { // it was marked to be skipped2101Top_Cone->FS[tn].splice(Top_Cone->FS[tn].end(), TriangulationBuffer, pyr_simp++);2102--TriangulationBufferSize;2103} else {2104for (i=0; i<dim; i++) // adjust key to topcone generators2105pyr_simp->key[i]=Top_Key[pyr_simp->key[i]];2106++pyr_simp;2107}2108}21092110// cout << "Keys transferred " << endl;2111#pragma omp critical(TRIANG)2112{2113Top_Cone->TriangulationBuffer.splice(Top_Cone->TriangulationBuffer.end(),TriangulationBuffer);2114Top_Cone->TriangulationBufferSize += TriangulationBufferSize;2115}2116TriangulationBufferSize = 0;21172118}21192120//---------------------------------------------------------------------------2121template<typename Number>2122void Full_Cone<Number>::get_supphyps_from_copy(bool from_scratch){21232124if(isComputed(ConeProperty::SupportHyperplanes)) // we have them already2125return;21262127Full_Cone copy((*this).Generators);2128copy.verbose=verbose;2129if(!from_scratch){2130copy.start_from=start_from;2131copy.use_existing_facets=true;2132copy.keep_order=true;2133copy.HypCounter=HypCounter;2134copy.Extreme_Rays_Ind=Extreme_Rays_Ind;2135copy.in_triang=in_triang;2136copy.old_nr_supp_hyps=old_nr_supp_hyps;2137if(isComputed(ConeProperty::ExtremeRays))2138copy.is_Computed.set(ConeProperty::ExtremeRays);2139copy.GensInCone=GensInCone;2140copy.nrGensInCone=nrGensInCone;2141copy.Comparisons=Comparisons;2142if(!Comparisons.empty())2143copy.nrTotalComparisons=Comparisons[Comparisons.size()-1];21442145typename list< FACETDATA >::const_iterator l=Facets.begin();21462147for(size_t i=0;i<old_nr_supp_hyps;++i){2148copy.Facets.push_back(*l);2149++l;2150}2151}21522153copy.dualize_cone();21542155std::swap(Support_Hyperplanes,copy.Support_Hyperplanes);2156nrSupport_Hyperplanes = copy.nrSupport_Hyperplanes;2157is_Computed.set(ConeProperty::SupportHyperplanes);2158do_all_hyperplanes = false;2159}21602161//---------------------------------------------------------------------------21622163template<typename Number>2164void Full_Cone<Number>::evaluate_triangulation(){21652166assert(omp_get_level()==0);21672168if (TriangulationBufferSize == 0)2169return;21702171if (keep_triangulation) {2172Triangulation.splice(Triangulation.end(),TriangulationBuffer);2173} else {2174// #pragma omp critical(FREESIMPL)2175FreeSimpl.splice(FreeSimpl.begin(),TriangulationBuffer);2176}2177TriangulationBufferSize=0;21782179}21802181//---------------------------------------------------------------------------21822183template<typename Number>2184void Full_Cone<Number>::primal_algorithm(){21852186primal_algorithm_initialize();21872188/***** Main Work is done in build_top_cone() *****/2189build_top_cone(); // evaluates if keep_triangulation==false2190/***** Main Work is done in build_top_cone() *****/21912192check_pointed();2193if(!pointed){2194throw NonpointedException();2195}21962197primal_algorithm_finalize();2198primal_algorithm_set_computed();2199}22002201//---------------------------------------------------------------------------22022203template<typename Number>2204void Full_Cone<Number>::primal_algorithm_initialize() {22052206}22072208//---------------------------------------------------------------------------22092210template<typename Number>2211void Full_Cone<Number>::primal_algorithm_finalize() {22122213evaluate_triangulation();22142215if (keep_triangulation) {2216is_Computed.set(ConeProperty::Triangulation);2217totalNrSimplices=0;2218auto t=Triangulation.begin();2219detSum=0;2220for(;t!=Triangulation.end();++t){2221totalNrSimplices++;2222t->vol=Generators.submatrix(t->key).vol();2223detSum+=t->vol;2224}2225is_Computed.set(ConeProperty::TriangulationDetSum);2226is_Computed.set(ConeProperty::TriangulationSize);2227}22282229if (do_cone_dec) {2230is_Computed.set(ConeProperty::ConeDecomposition);2231}22322233FreeSimpl.clear();22342235if(verbose) {2236verboseOutput() << "Total number of pyramids = "<< totalNrPyr << ", among them simplicial " << nrSimplicialPyr << endl;2237// cout << "Uni "<< Unimod << " Ht1NonUni " << Ht1NonUni << " NonDecided " << NonDecided << " TotNonDec " << NonDecidedHyp<< endl;2238}22392240}224122422243//---------------------------------------------------------------------------22442245template<typename Number>2246void Full_Cone<Number>::primal_algorithm_set_computed() {22472248extreme_rays_and_deg1_check();2249if(!pointed){2250throw NonpointedException();2251}22522253if (do_triangulation || do_partial_triangulation) {2254is_Computed.set(ConeProperty::TriangulationSize,true);2255if (do_evaluation) {2256is_Computed.set(ConeProperty::TriangulationDetSum,true);2257}2258}2259}226022612262//---------------------------------------------------------------------------2263// Normaliz modes (public)2264//---------------------------------------------------------------------------22652266// check the do_* bools, they must be set in advance2267// this method (de)activate them according to dependencies between them2268template<typename Number>2269void Full_Cone<Number>::do_vars_check(bool with_default) {22702271do_extreme_rays=true; // we always want to do this if compute() is called22722273/* if (do_default_mode && with_default) {2274do_Hilbert_basis = true;2275do_h_vector = true;2276if(!inhomogeneous)2277do_class_group=true;2278}2279*/22802281if (do_integrally_closed) {2282if (do_Hilbert_basis) {2283do_integrally_closed = false; // don't interrupt the computation2284} else {2285do_Hilbert_basis = true;2286}2287}22882289// activate implications2290if (do_module_gens_intcl) do_Hilbert_basis= true;2291if (do_module_gens_intcl) use_bottom_points= false;2292//if (do_hsop) do_Hilbert_basis = true;2293if (do_Stanley_dec) keep_triangulation = true;2294if (do_cone_dec) keep_triangulation = true;2295if (keep_triangulation) do_determinants = true;2296if (do_multiplicity) do_determinants = true;2297if ((do_multiplicity || do_h_vector) && inhomogeneous) do_module_rank = true;2298if (do_determinants) do_triangulation = true;2299if (do_h_vector && (with_default || explicit_h_vector)) do_triangulation = true;2300if (do_deg1_elements) do_partial_triangulation = true;2301if (do_Hilbert_basis) do_partial_triangulation = true;2302// activate2303do_only_multiplicity = do_determinants;2304stop_after_cone_dec = true;2305if(do_cone_dec) do_only_multiplicity=false;23062307if (do_Stanley_dec || do_h_vector || do_deg1_elements2308|| do_Hilbert_basis) {2309do_only_multiplicity = false;2310stop_after_cone_dec = false;2311do_evaluation = true;2312}2313if (do_determinants) do_evaluation = true;23142315// deactivate2316if (do_triangulation) do_partial_triangulation = false;2317if (do_Hilbert_basis) do_deg1_elements = false; // they will be extracted later2318}231923202321// general purpose compute method2322// do_* bools must be set in advance, this method does sanity checks for it2323// if no bool is set it does support hyperplanes and extreme rays2324template<typename Number>2325void Full_Cone<Number>::compute() {23262327if(dim==0){2328set_zero_cone();2329return;2330}233123322333do_vars_check(false);2334explicit_full_triang=do_triangulation; // to distinguish it from do_triangulation via default mode2335if(do_default_mode)2336do_vars_check(true);23372338start_message();23392340if(Support_Hyperplanes.nr_of_rows()==0 && !do_Hilbert_basis && !do_h_vector && !do_multiplicity && !do_deg1_elements2341&& !do_Stanley_dec && !do_triangulation && !do_determinants)2342assert(Generators.max_rank_submatrix_lex().size() == dim);23432344minimize_support_hyperplanes(); // if they are given2345if (inhomogeneous)2346set_levels();23472348if ((!do_triangulation && !do_partial_triangulation)2349|| (Grading.size()>0 && !isComputed(ConeProperty::Grading))){2350// in the second case there are only two possibilities:2351// either nonpointed or bad grading2352do_triangulation=false;2353do_partial_triangulation=false;2354support_hyperplanes();2355}2356else{2357if(isComputed(ConeProperty::IsPointed) && !pointed){2358end_message();2359return;2360}23612362sort_gens_by_degree(true);23632364primal_algorithm();2365}23662367end_message();2368}23692370237123722373// -s2374template<typename Number>2375void Full_Cone<Number>::support_hyperplanes() {2376if(!isComputed(ConeProperty::SupportHyperplanes)){2377sort_gens_by_degree(false); // we do not want to triangulate here2378build_top_cone();2379}2380extreme_rays_and_deg1_check();2381if(inhomogeneous){2382find_level0_dim();2383}2384}23852386//---------------------------------------------------------------------------2387// Checks and auxiliary algorithms2388//---------------------------------------------------------------------------23892390template<typename Number>2391void Full_Cone<Number>::extreme_rays_and_deg1_check() {2392check_pointed();2393if(!pointed){2394throw NonpointedException();2395}2396//cout << "Generators" << endl;2397//Generators.pretty_print(cout);2398//cout << "SupportHyperplanes" << endl;2399//Support_Hyperplanes.pretty_print(cout);2400compute_extreme_rays();2401}24022403//---------------------------------------------------------------------------24042405template<typename Number>2406void Full_Cone<Number>::find_level0_dim(){24072408if(!isComputed(ConeProperty::Generators)){2409throw FatalException("Missing Generators.");2410}24112412Matrix<Number> Help(nr_gen,dim);2413for(size_t i=0; i<nr_gen;++i)2414if(gen_levels[i]==0)2415Help[i]=Generators[i];24162417ProjToLevel0Quot=Help.kernel();24182419level0_dim=dim-ProjToLevel0Quot.nr_of_rows();2420is_Computed.set(ConeProperty::RecessionRank);2421}24222423//---------------------------------------------------------------------------24242425template<typename Number>2426void Full_Cone<Number>::set_levels() {2427if(inhomogeneous && Truncation.size()!=dim){2428throw FatalException("Truncation not defined in inhomogeneous case.");2429}24302431// cout <<"trunc " << Truncation;24322433if(gen_levels.size()!=nr_gen) // now we compute the levels2434{2435gen_levels.resize(nr_gen);2436vector<Number> gen_levels_Number=Generators.MxV(Truncation);2437for (size_t i=0; i<nr_gen; i++) {2438if (gen_levels_Number[i] < 0) {2439throw FatalException("Truncation gives non-positive value "2440+ toString(gen_levels_Number[i]) + " for generator "2441+ toString(i+1) + ".");2442}2443convert(gen_levels[i], gen_levels_Number[i]);2444// cout << "Gen " << Generators[i];2445// cout << "level " << gen_levels[i] << endl << "----------------------" << endl;2446}2447}24482449}24502451//---------------------------------------------------------------------------24522453template<typename Number>2454void Full_Cone<Number>::sort_gens_by_degree(bool triangulate) {2455// if(deg1_extreme_rays) // gen_degrees.size()==0 ||2456// return;24572458if(keep_order)2459return;24602461Matrix<Number> Weights(0,dim);2462vector<bool> absolute;2463if(triangulate){2464Weights.append(vector<Number>(dim,1));2465absolute.push_back(true);2466}24672468vector<key_t> perm=Generators.perm_by_weights(Weights,absolute);2469Generators.order_rows_by_perm(perm);2470order_by_perm(Extreme_Rays_Ind,perm);2471if(inhomogeneous && gen_levels.size()==nr_gen)2472order_by_perm(gen_levels,perm);2473compose_perm_gens(perm);24742475if (verbose) {2476if(triangulate){2477if(isComputed(ConeProperty::Grading)){2478verboseOutput() <<"Generators sorted by degree and lexicographically" << endl;2479verboseOutput() << "Generators per degree:" << endl;2480verboseOutput() << count_in_map<long,long>(gen_degrees);2481}2482else2483verboseOutput() << "Generators sorted by 1-norm and lexicographically" << endl;2484}2485else{2486verboseOutput() << "Generators sorted lexicographically" << endl;2487}2488}2489keep_order=true;2490}24912492//---------------------------------------------------------------------------24932494template<typename Number>2495void Full_Cone<Number>::compose_perm_gens(const vector<key_t>& perm) {2496order_by_perm(PermGens,perm);2497}24982499//---------------------------------------------------------------------------25002501// an alternative to compute() for the basic tasks that need no triangulation2502template<typename Number>2503void Full_Cone<Number>::dualize_cone(bool print_message){25042505if(dim==0){2506set_zero_cone();2507return;2508}25092510// DO NOT CALL do_vars_check!!25112512bool save_tri = do_triangulation;2513bool save_part_tri = do_partial_triangulation;2514do_triangulation = false;2515do_partial_triangulation = false;25162517if(print_message) start_message();25182519sort_gens_by_degree(false);25202521if(!isComputed(ConeProperty::SupportHyperplanes))2522build_top_cone();25232524if(do_pointed)2525check_pointed();25262527if(do_extreme_rays) // in case we have known the support hyperplanes2528compute_extreme_rays();25292530do_triangulation = save_tri;2531do_partial_triangulation = save_part_tri;2532if(print_message) end_message();2533}25342535//---------------------------------------------------------------------------25362537template<typename Number>2538vector<key_t> Full_Cone<Number>::find_start_simplex() const {2539return Generators.max_rank_submatrix_lex();2540}25412542//---------------------------------------------------------------------------25432544template<typename Number>2545Matrix<Number> Full_Cone<Number>::select_matrix_from_list(const list<vector<Number> >& S,2546vector<size_t>& selection){25472548sort(selection.begin(),selection.end());2549assert(selection.back()<S.size());2550size_t i=0,j=0;2551size_t k=selection.size();2552Matrix<Number> M(selection.size(),S.front().size());2553typename list<vector<Number> >::const_iterator ll=S.begin();2554for(;ll!=S.end()&&i<k;++ll){2555if(j==selection[i]){2556M[i]=*ll;2557i++;2558}2559j++;2560}2561return M;2562}25632564//---------------------------------------------------------------------------25652566template<typename Number>25672568void Full_Cone<Number>::minimize_support_hyperplanes(){2569if(Support_Hyperplanes.nr_of_rows() == 0)2570return;2571if(isComputed(ConeProperty::SupportHyperplanes)){2572nrSupport_Hyperplanes=Support_Hyperplanes.nr_of_rows();2573return;2574}2575if (verbose) {2576verboseOutput() << "Minimize the given set of support hyperplanes by "2577<< "computing the extreme rays of the dual cone" << endl;2578}2579Full_Cone<Number> Dual(Support_Hyperplanes);2580Dual.verbose=verbose;2581Dual.Support_Hyperplanes = Generators;2582Dual.is_Computed.set(ConeProperty::SupportHyperplanes);2583Dual.compute_extreme_rays();2584Support_Hyperplanes = Dual.Generators.submatrix(Dual.Extreme_Rays_Ind); //only essential hyperplanes2585is_Computed.set(ConeProperty::SupportHyperplanes);2586nrSupport_Hyperplanes=Support_Hyperplanes.nr_of_rows();2587do_all_hyperplanes=false;2588}258925902591//---------------------------------------------------------------------------25922593template<typename Number>2594void Full_Cone<Number>::compute_extreme_rays(bool use_facets){25952596if (isComputed(ConeProperty::ExtremeRays))2597return;2598// when we do approximation, we do not have the correct hyperplanes2599// and cannot compute the extreme rays2600if (is_approximation)2601return;2602assert(isComputed(ConeProperty::SupportHyperplanes));26032604check_pointed();2605if(!pointed){2606throw NonpointedException();2607}26082609if(dim*Support_Hyperplanes.nr_of_rows() < nr_gen) {2610compute_extreme_rays_rank(use_facets);2611} else {2612compute_extreme_rays_compare(use_facets);2613}2614}26152616//---------------------------------------------------------------------------26172618template<typename Number>2619void Full_Cone<Number>::compute_extreme_rays_rank(bool use_facets){26202621if (verbose) verboseOutput() << "Select extreme rays via rank ... " << flush;26222623size_t i;2624vector<key_t> gen_in_hyperplanes;2625gen_in_hyperplanes.reserve(Support_Hyperplanes.nr_of_rows());2626Matrix<Number> M(Support_Hyperplanes.nr_of_rows(),dim);26272628deque<bool> Ext(nr_gen,false);2629#pragma omp parallel for firstprivate(gen_in_hyperplanes,M)2630for(i=0;i<nr_gen;++i){2631// if (isComputed(ConeProperty::Triangulation) && !in_triang[i])2632// continue;2633gen_in_hyperplanes.clear();2634if(use_facets){2635typename list<FACETDATA>::const_iterator IHV=Facets.begin();2636for (size_t j=0; j<Support_Hyperplanes.nr_of_rows(); ++j, ++IHV){2637if(IHV->GenInHyp.test(i))2638gen_in_hyperplanes.push_back(j);2639}2640}2641else{2642for (size_t j=0; j<Support_Hyperplanes.nr_of_rows(); ++j){2643if(v_scalar_product(Generators[i],Support_Hyperplanes[j])==0)2644gen_in_hyperplanes.push_back(j);2645}2646}2647if (gen_in_hyperplanes.size() < dim-1)2648continue;2649if (M.rank_submatrix(Support_Hyperplanes,gen_in_hyperplanes) >= dim-1)2650Ext[i]=true;2651}2652for(i=0; i<nr_gen;++i)2653Extreme_Rays_Ind[i]=Ext[i];26542655is_Computed.set(ConeProperty::ExtremeRays);2656if (verbose) verboseOutput() << "done." << endl;2657}26582659//---------------------------------------------------------------------------26602661template<typename Number>2662void Full_Cone<Number>::compute_extreme_rays_compare(bool use_facets){26632664if (verbose) verboseOutput() << "Select extreme rays via comparison ... " << flush;26652666size_t i,j,k;2667// Matrix<Number> SH=getSupportHyperplanes().transpose();2668// Matrix<Number> Val=Generators.multiplication(SH);2669size_t nc=Support_Hyperplanes.nr_of_rows();26702671vector<vector<bool> > Val(nr_gen);2672for (i=0;i<nr_gen;++i)2673Val[i].resize(nc);26742675// In this routine Val[i][j]==1, i.e. true, indicates that2676// the i-th generator is contained in the j-th support hyperplane26772678vector<key_t> Zero(nc);2679vector<key_t> nr_ones(nr_gen);26802681for (i = 0; i <nr_gen; i++) {2682k=0;2683Extreme_Rays_Ind[i]=true;2684if(use_facets){2685typename list<FACETDATA>::const_iterator IHV=Facets.begin();2686for (j=0; j<Support_Hyperplanes.nr_of_rows(); ++j, ++IHV){2687if(IHV->GenInHyp.test(i)){2688k++;2689Val[i][j]=true;2690}2691else2692Val[i][j]=false;2693}2694}2695else{2696for (j = 0; j <nc; ++j) {2697if (v_scalar_product(Generators[i],Support_Hyperplanes[j])==0) {2698k++;2699Val[i][j]=true;2700}2701else2702Val[i][j]=false;2703}2704}2705nr_ones[i]=k;2706if (k<dim-1||k==nc) // not contained in enough facets or in all (0 as generator)2707Extreme_Rays_Ind[i]=false;2708}27092710maximal_subsets(Val,Extreme_Rays_Ind);27112712is_Computed.set(ConeProperty::ExtremeRays);2713if (verbose) verboseOutput() << "done." << endl;2714}27152716//---------------------------------------------------------------------------27172718template<typename Number>2719bool Full_Cone<Number>::contains(const vector<Number>& v) {2720for (size_t i=0; i<Support_Hyperplanes.nr_of_rows(); ++i)2721if (v_scalar_product(Support_Hyperplanes[i],v) < 0)2722return false;2723return true;2724}2725//---------------------------------------------------------------------------27262727template<typename Number>2728bool Full_Cone<Number>::contains(const Full_Cone& C) {2729for(size_t i=0;i<C.nr_gen;++i)2730if(!contains(C.Generators[i])){2731cerr << "Missing generator " << C.Generators[i] << endl;2732return(false);2733}2734return(true);2735}2736//---------------------------------------------------------------------------27372738template<typename Number>2739void Full_Cone<Number>::check_pointed() {2740if (isComputed(ConeProperty::IsPointed))2741return;2742assert(isComputed(ConeProperty::SupportHyperplanes));2743if (verbose) verboseOutput() << "Checking pointedness ... " << flush;27442745pointed = (Support_Hyperplanes.max_rank_submatrix_lex().size() == dim);2746is_Computed.set(ConeProperty::IsPointed);2747if (verbose) verboseOutput() << "done." << endl;2748}274927502751//---------------------------------------------------------------------------2752template<typename Number>2753void Full_Cone<Number>::disable_grading_dep_comp() {27542755if (do_multiplicity || do_deg1_elements || do_h_vector) {2756if (do_default_mode) {2757// if (verbose)2758// verboseOutput() << "No grading specified and cannot find one. "2759// << "Disabling some computations!" << endl;2760do_deg1_elements = false;2761do_h_vector = false;2762if(!explicit_full_triang){2763do_triangulation=false;2764do_partial_triangulation=true;2765}2766} else {2767throw BadInputException("No grading specified and cannot find one. Cannot compute some requested properties!");2768}2769}2770}27712772//---------------------------------------------------------------------------27732774/* computes a degree function, s.t. every generator has value >0 */2775template<typename Number>2776vector<Number> Full_Cone<Number>::compute_degree_function() const {2777size_t i;2778vector<Number> degree_function(dim,0);2779// add hyperplanes to get a degree function2780if(verbose) {2781verboseOutput()<<"computing degree function... "<<flush;2782}2783size_t h;2784for (h=0; h<Support_Hyperplanes.nr_of_rows(); ++h) {2785for (i=0; i<dim; i++) {2786degree_function[i] += Support_Hyperplanes.get_elem(h,i);2787}2788}2789v_simplify(degree_function);2790if(verbose) {2791verboseOutput()<<"done."<<endl;2792}2793return degree_function;2794}27952796//---------------------------------------------------------------------------2797// Constructors2798//---------------------------------------------------------------------------27992800template<typename Number>2801void Full_Cone<Number>::reset_tasks(){2802do_triangulation = false;2803do_partial_triangulation = false;2804do_determinants = false;2805do_multiplicity=false;2806do_integrally_closed = false;2807do_Hilbert_basis = false;2808do_deg1_elements = false;2809keep_triangulation = false;2810do_Stanley_dec=false;2811do_h_vector=false;2812do_hsop = false;2813do_excluded_faces=false;2814do_approximation=false;2815do_default_mode=false;2816do_class_group = false;2817do_module_gens_intcl = false;2818do_module_rank = false;2819do_cone_dec=false;2820stop_after_cone_dec=false;28212822do_extreme_rays=false;2823do_pointed=false;28242825do_evaluation = false;2826do_only_multiplicity=false;28272828use_bottom_points = true;28292830nrSimplicialPyr=0;2831totalNrPyr=0;2832is_pyramid = false;2833triangulation_is_nested = false;2834triangulation_is_partial = false;2835}283628372838//---------------------------------------------------------------------------28392840template<typename Number>2841Full_Cone<Number>::Full_Cone(const Matrix<Number>& M, bool do_make_prime){ // constructor of the top cone2842// do_make_prime left for syntax reasons, irrelevantant28432844dim=M.nr_of_columns();2845if(dim>0)2846Generators=M;2847// M.pretty_print(cout);2848// assert(M.row_echelon()== dim); rank check now done later28492850/*index=1; // not used at present2851for(size_t i=0;i<dim;++i)2852index*=M[i][i];2853index=Iabs(index); */28542855//make the generators coprime, remove 0 rows and duplicates2856has_generator_with_common_divisor = false; // irrelevant28572858Generators.simplify_rows();28592860Generators.remove_duplicate_and_zero_rows();2861nr_gen = Generators.nr_of_rows();28622863if (nr_gen != static_cast<size_t>(static_cast<key_t>(nr_gen))) {2864throw FatalException("Too many generators to fit in range of key_t!");2865}28662867// multiplicity = 0;2868is_Computed = bitset<ConeProperty::EnumSize>(); //initialized to false2869is_Computed.set(ConeProperty::Generators);2870pointed = false;2871is_simplicial = nr_gen == dim;2872deg1_extreme_rays = false;2873deg1_generated = false;2874deg1_generated_computed = false;2875deg1_hilbert_basis = false;28762877reset_tasks();28782879Extreme_Rays_Ind = vector<bool>(nr_gen,false);2880in_triang = vector<bool> (nr_gen,false);2881deg1_triangulation = true;2882if(dim==0){ //correction needed to include the 0 cone;2883is_Computed.set(ConeProperty::Triangulation);2884}2885pyr_level=-1;2886Top_Cone=this;2887Top_Key.resize(nr_gen);2888for(size_t i=0;i<nr_gen;i++)2889Top_Key[i]=i;2890totalNrSimplices=0;2891TriangulationBufferSize=0;28922893detSum = 0;2894shift = 0;28952896FS.resize(omp_get_max_threads());28972898Pyramids.resize(20); // prepare storage for pyramids2899nrPyramids.resize(20,0);29002901recursion_allowed=true;29022903do_all_hyperplanes=true;2904// multithreaded_pyramid=true; now in build_cone where it is defined dynamically290529062907nextGen=0;2908store_level=0;29092910Comparisons.reserve(nr_gen);2911nrTotalComparisons=0;29122913inhomogeneous=false;29142915level0_dim=dim; // must always be defined29162917use_existing_facets=false;2918start_from=0;2919old_nr_supp_hyps=0;29202921verbose=false;29222923RankTest = vector< Matrix<Number> >(omp_get_max_threads(), Matrix<Number>(0,dim));29242925do_bottom_dec=false;2926suppress_bottom_dec=false;2927keep_order=false;29282929approx_level = 1;2930is_approximation=false;29312932PermGens.resize(nr_gen);2933for(size_t i=0;i<nr_gen;++i)2934PermGens[i]=i;2935}29362937//---------------------------------------------------------------------------29382939/* constructor for pyramids */2940template<typename Number>2941Full_Cone<Number>::Full_Cone(Full_Cone<Number>& C, const vector<key_t>& Key) {29422943Generators = C.Generators.submatrix(Key);2944dim = Generators.nr_of_columns();2945nr_gen = Generators.nr_of_rows();2946has_generator_with_common_divisor = C.has_generator_with_common_divisor;2947is_simplicial = nr_gen == dim;29482949Top_Cone=C.Top_Cone; // relate to top cone2950Top_Key.resize(nr_gen);2951for(size_t i=0;i<nr_gen;i++)2952Top_Key[i]=C.Top_Key[Key[i]];29532954// multiplicity = 0;29552956Extreme_Rays_Ind = vector<bool>(nr_gen,false);2957is_Computed.set(ConeProperty::ExtremeRays, C.isComputed(ConeProperty::ExtremeRays));2958if(isComputed(ConeProperty::ExtremeRays))2959for(size_t i=0;i<nr_gen;i++)2960Extreme_Rays_Ind[i]=C.Extreme_Rays_Ind[Key[i]];2961in_triang = vector<bool> (nr_gen,false);2962deg1_triangulation = true;29632964// not used in a pyramid, but set precaution2965deg1_extreme_rays = false;2966deg1_generated = false;2967deg1_generated_computed = false;2968deg1_hilbert_basis = false;29692970Grading=C.Grading;2971is_Computed.set(ConeProperty::Grading, C.isComputed(ConeProperty::Grading));2972Order_Vector=C.Order_Vector;29732974do_extreme_rays=false;2975do_triangulation=C.do_triangulation;2976do_partial_triangulation=C.do_partial_triangulation;2977do_determinants=C.do_determinants;2978do_multiplicity=C.do_multiplicity;2979do_deg1_elements=C.do_deg1_elements;2980do_h_vector=C.do_h_vector;2981do_Hilbert_basis=C.do_Hilbert_basis;2982keep_triangulation=C.keep_triangulation;2983do_only_multiplicity=C.do_only_multiplicity;2984do_evaluation=C.do_evaluation;2985do_Stanley_dec=C.do_Stanley_dec;2986inhomogeneous=C.inhomogeneous; // at present not used in proper pyramids2987is_pyramid=true;29882989pyr_level=C.pyr_level+1;29902991totalNrSimplices=0;2992detSum = 0;2993shift = C.shift;2994if(C.gen_degrees.size()>0){ // now we copy the degrees2995gen_degrees.resize(nr_gen);2996for (size_t i=0; i<nr_gen; i++) {2997gen_degrees[i] = C.gen_degrees[Key[i]];2998}2999}3000if(C.gen_levels.size()>0){ // now we copy the levels3001gen_levels.resize(nr_gen);3002for (size_t i=0; i<nr_gen; i++) {3003gen_levels[i] = C.gen_levels[Key[i]];3004}3005}3006TriangulationBufferSize=0;300730083009recursion_allowed=C.recursion_allowed; // must be reset if necessary3010do_all_hyperplanes=true; // must be reset for non-recursive pyramids3011// multithreaded_pyramid=false; // SEE ABOVE30123013nextGen=0;3014store_level = C.store_level;30153016Comparisons.reserve(nr_gen);3017nrTotalComparisons=0;30183019level0_dim = C.level0_dim; // must always be defined30203021use_existing_facets=false;3022start_from=0;3023old_nr_supp_hyps=0;3024verbose=false;30253026approx_level = C.approx_level;3027is_approximation = C.is_approximation;30283029do_bottom_dec=false;3030suppress_bottom_dec=false;3031keep_order=true;3032}30333034//---------------------------------------------------------------------------30353036template<typename Number>3037void Full_Cone<Number>::set_zero_cone() {30383039assert(dim==0);30403041if (verbose) {3042verboseOutput() << "Zero cone detected!" << endl;3043}30443045// The basis change already is transforming to zero.3046is_Computed.set(ConeProperty::Sublattice);3047is_Computed.set(ConeProperty::Generators);3048is_Computed.set(ConeProperty::ExtremeRays);3049Support_Hyperplanes=Matrix<Number> (0);3050is_Computed.set(ConeProperty::SupportHyperplanes);3051totalNrSimplices = 0;3052is_Computed.set(ConeProperty::TriangulationSize);3053detSum = 0;3054is_Computed.set(ConeProperty::Triangulation);30553056pointed = true;3057is_Computed.set(ConeProperty::IsPointed);30583059deg1_extreme_rays = true;3060is_Computed.set(ConeProperty::IsDeg1ExtremeRays);30613062if (inhomogeneous) { // empty set of solutions3063is_Computed.set(ConeProperty::VerticesOfPolyhedron);3064module_rank = 0;3065is_Computed.set(ConeProperty::ModuleRank);3066is_Computed.set(ConeProperty::ModuleGenerators);3067level0_dim=0;3068is_Computed.set(ConeProperty::RecessionRank);3069}3070}30713072//---------------------------------------------------------------------------30733074template<typename Number>3075bool Full_Cone<Number>::isComputed(ConeProperty::Enum prop) const{3076return is_Computed.test(prop);3077}30783079//---------------------------------------------------------------------------3080// Data access3081//---------------------------------------------------------------------------30823083template<typename Number>3084size_t Full_Cone<Number>::getDimension()const{3085return dim;3086}30873088//---------------------------------------------------------------------------30893090template<typename Number>3091size_t Full_Cone<Number>::getNrGenerators()const{3092return nr_gen;3093}30943095//---------------------------------------------------------------------------30963097template<typename Number>3098bool Full_Cone<Number>::isPointed()const{3099return pointed;3100}31013102//---------------------------------------------------------------------------31033104template<typename Number>3105bool Full_Cone<Number>::isDeg1ExtremeRays() const{3106return deg1_extreme_rays;3107}31083109//---------------------------------------------------------------------------31103111template<typename Number>3112size_t Full_Cone<Number>::getModuleRank()const{3113return module_rank;3114}311531163117//---------------------------------------------------------------------------31183119template<typename Number>3120const Matrix<Number>& Full_Cone<Number>::getGenerators()const{3121return Generators;3122}31233124//---------------------------------------------------------------------------31253126template<typename Number>3127vector<bool> Full_Cone<Number>::getExtremeRays()const{3128return Extreme_Rays_Ind;3129}31303131//---------------------------------------------------------------------------31323133template<typename Number>3134Matrix<Number> Full_Cone<Number>::getSupportHyperplanes()const{3135return Support_Hyperplanes;3136}31373138//---------------------------------------------------------------------------31393140template<typename Number>3141void Full_Cone<Number>::error_msg(string s) const{3142errorOutput() <<"\nFull Cone "<< s<<"\n";3143}31443145//---------------------------------------------------------------------------31463147template<typename Number>3148void Full_Cone<Number>::print()const{3149verboseOutput()<<"\ndim="<<dim<<".\n";3150verboseOutput()<<"\nnr_gen="<<nr_gen<<".\n";3151// verboseOutput()<<"\nhyp_size="<<hyp_size<<".\n";3152verboseOutput()<<"\nGrading is:\n";3153verboseOutput()<< Grading;3154// verboseOutput()<<"\nMultiplicity is "<<multiplicity<<".\n";3155verboseOutput()<<"\nGenerators are:\n";3156Generators.pretty_print(verboseOutput());3157verboseOutput()<<"\nExtreme_rays are:\n";3158verboseOutput()<< Extreme_Rays_Ind;3159verboseOutput()<<"\nSupport Hyperplanes are:\n";3160Support_Hyperplanes.pretty_print(verboseOutput());3161verboseOutput()<<"\nHilbert basis is:\n";3162verboseOutput()<< Hilbert_Basis;3163verboseOutput()<<"\nDeg1 elements are:\n";3164verboseOutput()<< Deg1_Elements;3165}31663167} //end namespace316831693170