GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#ifdef NMZ_COCOA1/*2* nmzIntegrate3* Copyright (C) 2012-2014 Winfried Bruns, Christof Soeger4* This program is free software: you can redistribute it and/or modify5* it under the terms of the GNU General Public License as published by6* the Free Software Foundation, either version 3 of the License, or7* (at your option) any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU General Public License for more details.13*14* You should have received a copy of the GNU General Public License15* along with this program. If not, see <http://www.gnu.org/licenses/>.16*17* As an exception, when this program is distributed through (i) the App Store18* by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or (iii) Google Play19* by Google Inc., then that store may impose any digital rights management,20* device limits and/or redistribution restrictions that are required by its21* terms of service.22*/2324#include <fstream>25#include <sstream>26#include<string>2728#include "libnormaliz/nmz_integrate.h"29#include "libnormaliz/cone.h"30#include "libnormaliz/vector_operations.h"31#include "libnormaliz/map_operations.h"3233using namespace CoCoA;3435#include <boost/dynamic_bitset.hpp>3637#include "../libnormaliz/my_omp.h"3839namespace libnormaliz {404142BigRat IntegralUnitSimpl(const RingElem& F, const SparsePolyRing& P, const vector<BigInt>& Factorial,43const vector<BigInt>& factQuot, const long& rank){4445// SparsePolyRing P=owner(F);46long dim=NumIndets(P);47vector<long> v(dim);4849SparsePolyIter mon=BeginIter(F); // go over the given polynomial50map<vector<long>,RingElem> orderedMons; // will take the ordered exponent vectors51map<vector<long>,RingElem>::iterator ord_mon;5253for (; !IsEnded(mon); ++mon){54exponents(v,PP(mon)); // this function gives the exponent vector back as v55sort(v.begin()+1,v.begin()+rank+1);56ord_mon=orderedMons.find(v); // insert into map or add coefficient57if(ord_mon!=orderedMons.end()){58ord_mon->second+=coeff(mon);59}60else{61orderedMons.insert(pair<vector<long>,RingElem>(v,coeff(mon)));62}63}646566long deg;67BigInt facProd,I;68I=0;69for(ord_mon=orderedMons.begin();ord_mon!=orderedMons.end();++ord_mon){70deg=0;71v=ord_mon->first;72IsInteger(facProd,ord_mon->second); // start with coefficient and multipliy by Factorials73for(long i=1;i<=rank;++i){74deg+=v[i];75facProd*=Factorial[v[i]];76}77I+=facProd*factQuot[deg+rank-1];// maxFact/Factorial[deg+rank-1];78}7980BigRat Irat;81Irat=I;82return(Irat/Factorial[Factorial.size()-1]);83}8485BigRat substituteAndIntegrate(const ourFactorization& FF,const vector<vector<long> >& A,86const vector<long>& degrees, const SparsePolyRing& R, const vector<BigInt>& Factorial,87const vector<BigInt>& factQuot,const BigInt& lcmDegs){88// we need F to define the ring89// applies linar substitution y --> y*(lcmDegs*A/degrees) to all factors in FF90// where row A[i] is divided by degrees[i]91// After substitution the polynomial is integrated over the unit simplex92// and the integral is returned939495size_t i;96size_t m=A.size();97long rank=(long) m; // we prefer rank to be of type long98vector<RingElem> v(m,zero(R));99100BigInt quot;101for(i=0;i<m;i++){102quot=lcmDegs/degrees[i];103v[i]=indets(R)[i+1]*quot;104}105vector<RingElem> w=VxM(v,A);106vector<RingElem> w1(w.size()+1,zero(R));107w1[0]=RingElem(R,lcmDegs);108for(i=1;i<w1.size();++i) // we have to shift w since the (i+1)st variable109w1[i]=w[i-1]; // corresponds to coordinate i (counted from 0)110111112// RingHom phi=PolyAlgebraHom(R,R,w1);113114RingElem G1(zero(R));115list<RingElem> sortedFactors;116for(i=0;i<FF.myFactors.size();++i){117// G1=phi(FF.myFactors[i]);118G1=mySubstitution(FF.myFactors[i],w1);119for(int nn=0;nn<FF.myMultiplicities[i];++nn)120sortedFactors.push_back(G1);121}122123list<RingElem>::iterator sf;124sortedFactors.sort(compareLength);125126RingElem G(one(R));127128for(sf=sortedFactors.begin();sf!=sortedFactors.end();++sf)129G*=*sf;130131// verboseOutput() << "Evaluating integral over unit simplex" << endl;132// boost::dynamic_bitset<> dummyInd;133// vector<long> dummyDeg(degrees.size(),1);134return(IntegralUnitSimpl(G,R,Factorial,factQuot,rank)); // orderExpos(G,dummyDeg,dummyInd,false)135}136137template<typename Integer>138void readGens(Cone<Integer>& C, vector<vector<long> >& gens, const vector<long>& grading, bool check_ascending){139// get from C for nmz_integrate functions140141size_t i,j;142size_t nrows, ncols;143nrows=C.getNrGenerators();144ncols=C.getEmbeddingDim();145gens.resize(nrows);146for(i=0;i<nrows;++i)147gens[i].resize(ncols);148149for(i=0; i<nrows; i++){150for(j=0; j<ncols; j++) {151convert(gens[i],C.getGenerators()[i]);152}153if(check_ascending){154long degree,prevDegree=1;155degree=v_scalar_product(gens[i],grading);156if(degree<prevDegree){157throw FatalException( " Degrees of generators not weakly ascending!");158}159prevDegree=degree;160}161}162}163164bool exists_file(string name_in){165//n check whether file name_in exists166167//b string name_in="nmzIntegrate";168const char* file_in=name_in.c_str();169170struct stat fileStat;171if(stat(file_in,&fileStat) < 0){172return(false);173}174return(true);175}176177void testPolynomial(const string& poly_as_string,long dim){178179GlobalManager CoCoAFoundations;180181string dummy=poly_as_string;182SparsePolyRing R=NewPolyRing_DMPI(RingQQ(),dim+1,lex);183RingElem the_only_factor= ReadExpr(R, dummy); // there is only one184// verboseOutput() << "PPPPPPPPPPPPP " << the_only_factor << endl;185vector<RingElem> V=homogComps(the_only_factor);186187}188189190template<typename Integer>191void integrate(Cone<Integer>& C, const bool do_virt_mult) {192GlobalManager CoCoAFoundations;193194try{195196#ifndef NCATCH197std::exception_ptr tmp_exception;198#endif199200long dim=C.getEmbeddingDim();201// testPolynomial(C.getIntData().getPolynomial(),dim);202203bool verbose_INTsave=verbose_INT;204verbose_INT=C.get_verbose();205206long i;207208if (verbose_INT) {209verboseOutput() << "==========================================================" << endl;210verboseOutput() << "Integration" << endl;211verboseOutput() << "==========================================================" << endl << endl;212}213214vector<long> grading;215convert(grading,C.getGrading());216long gradingDenom;217convert(gradingDenom,C.getGradingDenom());218long rank=C.getRank();219220vector<vector<long> > gens;221readGens(C,gens,grading,false);222if(verbose_INT)223verboseOutput() << "Generators read" << endl;224225BigInt lcmDegs(1);226for(size_t i=0;i<gens.size();++i){227long deg=v_scalar_product(gens[i],grading);228lcmDegs=lcm(lcmDegs,deg);229}230231232SparsePolyRing R=NewPolyRing_DMPI(RingQQ(),dim+1,lex);233SparsePolyRing RZZ=NewPolyRing_DMPI(RingZZ(),PPM(R)); // same indets and ordering as R234vector<RingElem> primeFactors;235vector<RingElem> primeFactorsNonhom;236vector<long> multiplicities;237RingElem remainingFactor(one(R));238239INTERRUPT_COMPUTATION_BY_EXCEPTION240241bool homogeneous;242RingElem F=processInputPolynomial(C.getIntData().getPolynomial(),R,RZZ,primeFactors, primeFactorsNonhom,243multiplicities,remainingFactor,homogeneous,do_virt_mult);244245C.getIntData().setDegreeOfPolynomial(deg(F));246247vector<BigInt> Factorial(deg(F)+dim); // precomputed values248for(i=0;i<deg(F)+dim;++i)249Factorial[i]=factorial(i);250251vector<BigInt> factQuot(deg(F)+dim); // precomputed values252for(i=0;i<deg(F)+dim;++i)253factQuot[i]=Factorial[Factorial.size()-1]/Factorial[i];254255ourFactorization FF(primeFactors,multiplicities,remainingFactor); // assembels the data256ourFactorization FFNonhom(primeFactorsNonhom,multiplicities,remainingFactor); // for output257258long nf=FF.myFactors.size();259if(verbose_INT){260verboseOutput() <<"Factorization" << endl; // we show the factorization so that the user can check261for(i=0;i<nf;++i)262verboseOutput() << FFNonhom.myFactors[i] << " mult " << FF.myMultiplicities[i] << endl;263verboseOutput() << "Remaining factor " << FF.myRemainingFactor << endl << endl;264}265266size_t tri_size=C.getTriangulation().size();267size_t k_start=0, k_end=tri_size;268269bool pseudo_par=false;270size_t block_nr;271if(false){ // exists_file("block.nr")272size_t block_size=2000000;273pseudo_par=true;274string name_in="block.nr";275const char* file_in=name_in.c_str();276ifstream in;277in.open(file_in,ifstream::in);278in >> block_nr;279if(in.fail())280throw FatalException("File block.nr corrupted");281in.close();282k_start=(block_nr-1)*block_size;283k_end=min(k_start+block_size,tri_size);284285for(size_t k=1;k<tri_size;++k)286if(!(C.getTriangulation()[k-1].first<C.getTriangulation()[k].first))287throw FatalException("Triangulation not ordered");288}289290for(size_t k=0;k<tri_size;++k)291for(size_t j=1;j<C.getTriangulation()[k].first.size();++j)292if(!(C.getTriangulation()[k].first[j-1]<C.getTriangulation()[k].first[j]))293throw FatalException("Key in triangulation not ordered");294295if(verbose_INT)296verboseOutput() << "Triangulation is ordered" << endl;297298size_t eval_size;299if(k_start>=k_end)300eval_size=0;301else302eval_size=k_end-k_start;303304if(verbose_INT){305if(pseudo_par){306verboseOutput() << "********************************************" << endl;307verboseOutput() << "Parallel block " << block_nr << endl;308}309verboseOutput() << "********************************************" << endl;310verboseOutput() << eval_size <<" simplicial cones to be evaluated" << endl;311verboseOutput() << "********************************************" << endl;312}313314size_t progress_step=10;315if(tri_size >= 1000000)316progress_step=100;317318size_t nrSimplDone=0;319320vector<BigRat> I_thread(omp_get_max_threads());321for(size_t i=0; i< I_thread.size();++i)322I_thread[i]=0;323324bool skip_remaining=false;325326#pragma omp parallel private(i)327{328329long det, rank=C.getTriangulation()[0].first.size();330vector<long> degrees(rank);331vector<vector<long> > A(rank);332BigRat ISimpl; // integral over a simplex333BigInt prodDeg; // product of the degrees of the generators334RingElem h(zero(R));335336#pragma omp for schedule(dynamic)337for(size_t k=k_start;k<k_end;++k){338339if(skip_remaining)340continue;341342#ifndef NCATCH343try {344#endif345346INTERRUPT_COMPUTATION_BY_EXCEPTION347348convert(det,C.getTriangulation()[k].second);349for(i=0;i<rank;++i) // select submatrix defined by key350A[i]=gens[C.getTriangulation()[k].first[i]];351352degrees=MxV(A,grading);353prodDeg=1;354for(i=0;i<rank;++i){355degrees[i]/=gradingDenom;356prodDeg*=degrees[i];357}358359// h=homogeneousLinearSubstitutionFL(FF,A,degrees,F);360ISimpl=(det*substituteAndIntegrate(FF,A,degrees,RZZ,Factorial,factQuot,lcmDegs))/prodDeg;361I_thread[omp_get_thread_num()]+=ISimpl;362363// a little bit of progress report364if ((++nrSimplDone)%progress_step==0 && verbose_INT)365#pragma omp critical(PROGRESS)366verboseOutput() << nrSimplDone << " simplicial cones done" << endl;367368#ifndef NCATCH369} catch(const std::exception& ) {370tmp_exception = std::current_exception();371skip_remaining = true;372#pragma omp flush(skip_remaining)373}374#endif375376} // triang377378} // parallel379#ifndef NCATCH380if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);381#endif382383BigRat I; // accumulates the integral384I=0;385for(size_t i=0; i< I_thread.size();++i)386I+=I_thread[i];387388389I/=power(lcmDegs,deg(F));390BigRat RFrat;391IsRational(RFrat,remainingFactor); // from RingQQ to BigRat392I*=RFrat;393394string result="Integral";395if(do_virt_mult)396result="Virtual multiplicity";397398BigRat VM=I;399400if(do_virt_mult){401VM*=factorial(deg(F)+rank-1);402C.getIntData().setVirtualMultiplicity(mpq(VM));403}404else405C.getIntData().setIntegral(mpq(I));406407if(verbose_INT){408verboseOutput() << "********************************************" << endl;409verboseOutput() << result << " is " << endl << VM << endl;410verboseOutput() << "********************************************" << endl;411}412413if(pseudo_par){414string name_out="block.nr";415const char* file=name_out.c_str();416ofstream out(file);417out << block_nr+1 << endl;418out.close();419420name_out="block_"+to_string((size_t) block_nr)+".mult";421file=name_out.c_str();422ofstream out_1(file);423out_1 << block_nr << ", "<< VM << "," << endl;424out_1.close();425426/* string chmod="chmod a+w "+name_out;427const char* exec=chmod.c_str();428system(exec);429430string mail_str="mail [email protected] < "+name_out;431exec=name_out.c_str();432system(exec);*/433434/*mail_str="mail [email protected] < "+name_out;435exec=name_out.c_str();436system(exec);*/437}438439verbose_INT=verbose_INTsave;440} // try441catch (const CoCoA::ErrorInfo& err)442{443cerr << "***ERROR*** UNCAUGHT CoCoA error";444ANNOUNCE(cerr, err);445446throw NmzCoCoAException("");447}448}449450CyclRatFunct evaluateFaceClasses(const vector<vector<CyclRatFunct> >& GFP,451map<vector<long>,RingElem>& faceClasses){452// computes the generating rational functions453// for the denominator classes collected from proper faces and returns the sum454455SparsePolyRing R=owner(faceClasses.begin()->second);456CyclRatFunct H(zero(R));457// vector<CyclRatFunct> h(omp_get_max_threads(),CyclRatFunct(zero(R)));458// vector<CyclRatFunct> h(1,CyclRatFunct(zero(R)));459460long mapsize=faceClasses.size();461if(verbose_INT){462verboseOutput() << "--------------------------------------------" << endl;463verboseOutput() << "Evaluating " << mapsize <<" face classes" << endl;464verboseOutput() << "--------------------------------------------" << endl;465}466#pragma omp parallel467{468469map<vector<long>,RingElem>::iterator den=faceClasses.begin();470long mpos=0;471CyclRatFunct h(zero(R));472473#pragma omp for schedule(dynamic)474for(long dc=0;dc<mapsize;++dc){475for(;mpos<dc;++mpos,++den);476for(;mpos>dc;--mpos,--den);477// verboseOutput() << "mpos " << mpos << endl;478479h = genFunct(GFP,den->second,den->first);480h.simplifyCRF();481if(verbose_INT){482#pragma omp critical(VERBOSE)483{484verboseOutput() << "Class ";485for(size_t i=0;i<den->first.size();++i)486verboseOutput() << den->first[i] << " ";487verboseOutput() << "NumTerms " << NumTerms(den->second) << endl;488489// verboseOutput() << "input " << den->second << endl;490}491}492493// h.showCoprimeCRF();494#pragma omp critical(ADDCLASSES)495H.addCRF(h);496}497498} // parallel499faceClasses.clear();500H.simplifyCRF();501return(H);502}503504struct denomClassData{505vector<long> degrees;506size_t simplDue;507size_t simplDone;508};509510CyclRatFunct evaluateDenomClass(const vector<vector<CyclRatFunct> >& GFP,511pair<denomClassData,vector<RingElem> >& denomClass){512// computes the generating rational function513// for a denominator class and returns it514515SparsePolyRing R=owner(denomClass.second[0]);516517if(verbose_INT){518#pragma omp critical(PROGRESS)519{520verboseOutput() << "--------------------------------------------" << endl;521verboseOutput() << "Evaluating denom class ";522for(size_t i=0;i<denomClass.first.degrees.size();++i)523verboseOutput() << denomClass.first.degrees[i] << " ";524verboseOutput() << "NumTerms " << NumTerms(denomClass.second[0]) << endl;525// verboseOutput() << denomClass.second << endl;526verboseOutput() << "--------------------------------------------" << endl;527}528}529530CyclRatFunct h(zero(R));531h = genFunct(GFP,denomClass.second[0],denomClass.first.degrees);532533denomClass.second[0]=0; // to save memory534h.simplifyCRF();535return(h);536}537538void transferFacePolys(deque<pair<vector<long>,RingElem> >& facePolysThread,539map<vector<long>,RingElem>& faceClasses){540541542// verboseOutput() << "In Transfer " << facePolysThread.size() << endl;543map<vector<long>,RingElem>::iterator den_found;544for(size_t i=0;i<facePolysThread.size();++i){545den_found=faceClasses.find(facePolysThread[i].first);546if(den_found!=faceClasses.end()){547den_found->second+=facePolysThread[i].second;548}549else{550faceClasses.insert(facePolysThread[i]);551if(verbose_INT){552#pragma omp critical(VERBOSE)553{554verboseOutput() << "New face class " << faceClasses.size() << " degrees ";555for(size_t j=0;j<facePolysThread[i].first.size();++j)556verboseOutput() << facePolysThread[i].first[j] << " ";557verboseOutput() << endl << flush;558}559}560} // else561}562facePolysThread.clear();563}564565libnormaliz::HilbertSeries nmzHilbertSeries(const CyclRatFunct& H, mpz_class& commonDen)566{567568size_t i;569vector<RingElem> HCoeff0=ourCoeffs(H.num,0); // we must convert the coefficients570BigInt commonDenBI(1); // and find the common denominator571vector<BigRat> HCoeff1(HCoeff0.size());572for(i=0;i<HCoeff0.size();++i){573IsRational(HCoeff1[i],HCoeff0[i]); // to BigRat574commonDenBI=lcm(den(HCoeff1[i]),commonDenBI);575}576577commonDen=mpz(commonDenBI); // convert it to mpz_class578579BigInt HC2;580vector<mpz_class> HCoeff3(HCoeff0.size());581for(i=0;i<HCoeff1.size();++i){582HC2=num(HCoeff1[i]*commonDenBI); // to BigInt583HCoeff3[i]=mpz(HC2); // to mpz_class584}585586vector<long> denomDeg=denom2degrees(H.denom);587libnormaliz::HilbertSeries HS(HCoeff3,count_in_map<long, long>(denomDeg));588HS.simplify();589return(HS);590}591592bool compareDegrees(const STANLEYDATA_int& A, const STANLEYDATA_int& B){593594return(A.degrees < B.degrees);595}596597bool compareFaces(const SIMPLINEXDATA_INT& A, const SIMPLINEXDATA_INT& B){598599return(A.card > B.card);600}601602void prepare_inclusion_exclusion_simpl(const STANLEYDATA_int& S,603const vector<pair<boost::dynamic_bitset<>, long> >& inExCollect,604vector<SIMPLINEXDATA_INT>& inExSimplData) {605606size_t dim=S.key.size();607vector<key_type> key=S.key;608for(size_t i=0;i<dim;++i)609key[i];610611boost::dynamic_bitset<> intersection(dim), Excluded(dim);612613Excluded.set();614for(size_t j=0;j<dim;++j) // enough to test the first offset (coming from the zero vector)615if(S.offsets[0][j]==0)616Excluded.reset(j);617618vector<pair<boost::dynamic_bitset<>, long> >::const_iterator F;619map<boost::dynamic_bitset<>, long> inExSimpl; // local version of nExCollect620map<boost::dynamic_bitset<>, long>::iterator G;621622for(F=inExCollect.begin();F!=inExCollect.end();++F){623// verboseOutput() << "F " << F->first << endl;624bool still_active=true;625for(size_t i=0;i<dim;++i)626if(Excluded[i] && !F->first.test(key[i])){627still_active=false;628break;629}630if(!still_active)631continue;632intersection.reset();633for(size_t i=0;i<dim;++i){634if(F->first.test(key[i]))635intersection.set(i);636}637G=inExSimpl.find(intersection);638if(G!=inExSimpl.end())639G->second+=F->second;640else641inExSimpl.insert(pair<boost::dynamic_bitset<> , long>(intersection,F->second));642}643644SIMPLINEXDATA_INT HilbData;645inExSimplData.clear();646vector<long> degrees;647648for(G=inExSimpl.begin();G!=inExSimpl.end();++G){649if(G->second!=0){650HilbData.GenInFace=G->first;651HilbData.mult=G->second;652HilbData.card=G->first.count();653degrees.clear();654for(size_t j=0;j<dim;++j)655if(G->first.test(j))656degrees.push_back(S.degrees[j]);657HilbData.degrees=degrees;658HilbData.denom=degrees2denom(degrees);659inExSimplData.push_back(HilbData);660}661}662663sort(inExSimplData.begin(),inExSimplData.end(),compareFaces);664665/* for(size_t i=0;i<inExSimplData.size();++i)666verboseOutput() << inExSimplData[i].GenInFace << " ** " << inExSimplData[i].card << " || " << inExSimplData[i].mult << " ++ "<< inExSimplData[i].denom << endl;667verboseOutput() << "InEx prepared" << endl; */668669}670671template<typename Integer>672void readInEx(Cone<Integer>& C, vector<pair<boost::dynamic_bitset<>, long> >& inExCollect, const size_t nrGen){673674size_t inExSize=C.getInclusionExclusionData().size(), keySize;675long mult;676boost::dynamic_bitset<> indicator(nrGen);677for(size_t i=0;i<inExSize;++i){678keySize=C.getInclusionExclusionData()[i].first.size();679indicator.reset();680for(size_t j=0;j<keySize;++j){681indicator.set(C.getInclusionExclusionData()[i].first[j]);682}683mult=C.getInclusionExclusionData()[i].second;684inExCollect.push_back(pair<boost::dynamic_bitset<>, long>(indicator,mult));685}686}687688template<typename Integer>689void readDecInEx(Cone<Integer>& C, const long& dim, /* list<STANLEYDATA_int_INT>& StanleyDec, */690vector<pair<boost::dynamic_bitset<>, long> >& inExCollect, const size_t nrGen){691// rads Stanley decomposition and InExSata from C692693if(C.isComputed(ConeProperty::InclusionExclusionData)){694readInEx(C, inExCollect,nrGen);695}696697// STANLEYDATA_int_INT newSimpl;698// ong i=0;699// newSimpl.key.resize(dim);700701long test;702703auto SD=C.getStanleyDec_mutable().begin();704auto SD_end=C.getStanleyDec_mutable().end();705706for(;SD!=SD_end;++SD){707708// swap(newSimpl.key,SD->key);709test=-1;710for(long i=0;i<dim;++i){711if(SD->key[i]<=test){712throw FatalException("Key of simplicial cone not ascending or out of range");713}714test=SD->key[i];715}716717/* swap(newSimpl.offsets,SD->offsets);718StanleyDec.push_back(newSimpl);719SD=C.getStanleyDec_mutable().erase(SD);*/720}721// C.resetStanleyDec();722}723724template<typename Integer>725void generalizedEhrhartSeries(Cone<Integer>& C){726GlobalManager CoCoAFoundations;727728try{729730bool verbose_INTsave=verbose_INT;731verbose_INT=C.get_verbose();732733if(verbose_INT){734verboseOutput() << "==========================================================" << endl;735verboseOutput() << "Weighted Ehrhart series " << endl;736verboseOutput() << "==========================================================" << endl << endl;737}738739long i,j;740741vector<long> grading;742convert(grading,C.getGrading());743long gradingDenom;744convert(gradingDenom,C.getGradingDenom());745long rank=C.getRank();746long dim=C.getEmbeddingDim();747748// processing the input polynomial749750SparsePolyRing R=NewPolyRing_DMPI(RingQQ(),dim+1,lex);751SparsePolyRing RZZ=NewPolyRing_DMPI(RingZZ(),PPM(R)); // same indets and ordering as R752const RingElem& t=indets(RZZ)[0];753vector<RingElem> primeFactors;754vector<RingElem> primeFactorsNonhom;755vector<long> multiplicities;756RingElem remainingFactor(one(R));757758INTERRUPT_COMPUTATION_BY_EXCEPTION759760bool homogeneous;761RingElem F=processInputPolynomial(C.getIntData().getPolynomial(),R,RZZ,primeFactors, primeFactorsNonhom,762multiplicities,remainingFactor,homogeneous,false);763764C.getIntData().setDegreeOfPolynomial(deg(F));765766vector<BigInt> Factorial(deg(F)+dim); // precomputed values767for(i=0;i<deg(F)+dim;++i)768Factorial[i]=factorial(i);769770ourFactorization FF(primeFactors,multiplicities,remainingFactor); // assembeles the data771ourFactorization FFNonhom(primeFactorsNonhom,multiplicities,remainingFactor); // for output772773long nf=FF.myFactors.size();774if(verbose_INT){775verboseOutput() <<"Factorization" << endl; // we show the factorization so that the user can check776for(i=0;i<nf;++i)777verboseOutput() << FFNonhom.myFactors[i] << " mult " << FF.myMultiplicities[i] << endl;778verboseOutput() << "Remaining factor " << FF.myRemainingFactor << endl << endl;779}780// inputpolynomial processed781782if(rank==0){783vector<RingElem> compsF= homogComps(F);784CyclRatFunct HRat(compsF[0]);785mpz_class commonDen; // common denominator of coefficients of numerator of H786libnormaliz::HilbertSeries HS(nmzHilbertSeries(HRat,commonDen));787C.getIntData().setWeightedEhrhartSeries(make_pair(HS,commonDen));788C.getIntData().computeWeightedEhrhartQuasiPolynomial();789C.getIntData().setVirtualMultiplicity(0);790return;791}792793794vector<vector<long> > gens;795readGens(C,gens,grading,true);796if(verbose_INT)797verboseOutput() << "Generators read" << endl;798long maxDegGen=v_scalar_product(gens[gens.size()-1],grading)/gradingDenom;799800INTERRUPT_COMPUTATION_BY_EXCEPTION801802// list<STANLEYDATA_int_INT> StanleyDec;803vector<pair<boost::dynamic_bitset<>, long> > inExCollect;804readDecInEx(C,rank,inExCollect,gens.size());805if(verbose_INT)806verboseOutput() << "Stanley decomposition (and in/ex data) read" << endl;807808list<STANLEYDATA_int>& StanleyDec=C.getStanleyDec_mutable();809810size_t dec_size=StanleyDec.size();811812// Now we sort the Stanley decomposition by denominator class (= degree class)813814auto S = StanleyDec.begin();815816vector<long> degrees(rank);817vector<vector<long> > A(rank);818819// prepare sorting by computing degrees of generators820821BigInt lcmDets(1); // to become the lcm of all dets of simplicial cones822823for(;S!=StanleyDec.end();++S){824825INTERRUPT_COMPUTATION_BY_EXCEPTION826827for(i=0;i<rank;++i) // select submatrix defined by key828A[i]=gens[S->key[i]];829degrees=MxV(A,grading);830for(i=0;i<rank;++i)831degrees[i]/=gradingDenom; // must be divisible832S->degrees=degrees;833lcmDets=lcm(lcmDets,S->offsets.nr_of_rows());834}835836if(verbose_INT)837verboseOutput() << "lcm(dets)=" << lcmDets << endl;838839StanleyDec.sort(compareDegrees);840841if(verbose_INT)842verboseOutput() << "Stanley decomposition sorted" << endl;843844vector<pair<denomClassData, vector<RingElem> > > denomClasses;845denomClassData denomClass;846vector<RingElem> ZeroVectRingElem;847for(int j=0;j<omp_get_max_threads();++j)848ZeroVectRingElem.push_back(zero(RZZ));849850map<vector<long>,RingElem> faceClasses; // denominator classes for the faces851// contrary to denomClasses these cannot be sorted beforehand852853vector<deque<pair<vector<long>,RingElem> > > facePolys(omp_get_max_threads()); // intermediate storage854bool evaluationActive=false;855856// we now make class 0 to get started857S=StanleyDec.begin();858denomClass.degrees=S->degrees; // put degrees in class859denomClass.simplDone=0;860denomClass.simplDue=1; // already one simplex to be done861denomClasses.push_back(pair<denomClassData,vector<RingElem> >(denomClass,ZeroVectRingElem));862size_t dc=0;863S->classNr=dc; // assignment of class 0 to first simpl in sorted order864865auto prevS = StanleyDec.begin();866867for(++S;S!=StanleyDec.end();++S,++prevS){868if(S->degrees==prevS->degrees){ // compare to predecessor869S->classNr=dc; // assign class to simplex870denomClasses[dc].first.simplDue++; // number of simplices in class ++871}872else{873denomClass.degrees=S->degrees; // make new class874denomClass.simplDone=0;875denomClass.simplDue=1;876denomClasses.push_back(pair<denomClassData,vector<RingElem> >(denomClass,ZeroVectRingElem));877dc++;878S->classNr=dc;879}880}881882if(verbose_INT)883verboseOutput() << denomClasses.size() << " denominator classes built" << endl;884885886vector<vector<CyclRatFunct> > GFP; // we calculate the table of generating functions887vector<CyclRatFunct> DummyCRFVect; // for\sum i^n t^ki vor various values of k and n888CyclRatFunct DummyCRF(zero(RZZ));889for(j=0;j<=deg(F);++j)890DummyCRFVect.push_back(DummyCRF);891for(i=0;i<=maxDegGen;++i){892GFP.push_back(DummyCRFVect);893for(j=0;j<=deg(F);++j)894GFP[i][j]=genFunctPower1(RZZ,i,j);895}896897CyclRatFunct H(zero(RZZ)); // accumulates the series898899if(verbose_INT){900verboseOutput() << "********************************************" << endl;901verboseOutput() << dec_size <<" simplicial cones to be evaluated" << endl;902verboseOutput() << "********************************************" << endl;903}904905size_t progress_step=10;906if(dec_size >= 1000000)907progress_step=100;908909size_t nrSimplDone=0;910911#ifndef NCATCH912std::exception_ptr tmp_exception;913#endif914915bool skip_remaining=false;916int omp_start_level=omp_get_level();917918#pragma omp parallel private(i)919{920921long degree_b;922long det;923bool evaluateClass;924vector<long> degrees;925vector<vector<long> > A(rank);926auto S=StanleyDec.begin();927928RingElem h(zero(RZZ)); // for use in a simplex929CyclRatFunct HClass(zero(RZZ)); // for single class930931size_t s,spos=0;932#pragma omp for schedule(dynamic)933for(s=0;s<dec_size;++s){934935if(skip_remaining)936continue;937938for(;spos<s;++spos,++S);939for(;spos>s;--spos,--S);940941#ifndef NCATCH942try {943#endif944945INTERRUPT_COMPUTATION_BY_EXCEPTION946947int tn;948if(omp_get_level()==omp_start_level)949tn=0;950else951tn = omp_get_ancestor_thread_num(omp_start_level+1);952953det=S->offsets.nr_of_rows();954degrees=S->degrees;955956for(i=0;i<rank;++i) // select submatrix defined by key957A[i]=gens[S->key[i]];958959vector<SIMPLINEXDATA_INT> inExSimplData;960if(inExCollect.size()!=0)961prepare_inclusion_exclusion_simpl(*S,inExCollect,inExSimplData);962963h=0;964long iS=S->offsets.nr_of_rows(); // compute numerator for simplex being processed965for(i=0;i<iS;++i){966degree_b=v_scalar_product(degrees,S->offsets[i]);967degree_b/=det;968h+=power(t,degree_b)*affineLinearSubstitutionFL(FF,A,S->offsets[i],det,RZZ,degrees,lcmDets,969inExSimplData, facePolys[tn]);970}971972evaluateClass=false; // necessary to evaluate class only once973974// #pragma omp critical (ADDTOCLASS)975{976denomClasses[S->classNr].second[tn]+=h;977#pragma omp critical (ADDTOCLASS)978{979denomClasses[S->classNr].first.simplDone++;980981if(denomClasses[S->classNr].first.simplDone==denomClasses[S->classNr].first.simplDue)982evaluateClass=true;983}984}985if(evaluateClass)986{987988for(int j=1;j<omp_get_max_threads();++j){989denomClasses[S->classNr].second[0]+=denomClasses[S->classNr].second[j];990denomClasses[S->classNr].second[j]=0;991}992993// denomClasses[S->classNr].second=0; // <-------------------------------------994HClass=evaluateDenomClass(GFP,denomClasses[S->classNr]);995#pragma omp critical(ACCUMULATE)996{997H.addCRF(HClass);998}9991000}10011002if(!evaluationActive && facePolys[tn].size() >= 20){1003#pragma omp critical(FACEPOLYS)1004{1005evaluationActive=true;1006transferFacePolys(facePolys[tn],faceClasses);1007evaluationActive=false;1008}1009}10101011#pragma omp critical(PROGRESS) // a little bit of progress report1012{1013if((++nrSimplDone)%progress_step==0 && verbose_INT)1014verboseOutput() << nrSimplDone << " simplicial cones done " << endl; // nrActiveFaces-nrActiveFacesOld << " faces done" << endl;1015// nrActiveFacesOld=nrActiveFaces;1016}10171018#ifndef NCATCH1019} catch(const std::exception& ) {1020tmp_exception = std::current_exception();1021skip_remaining=true;1022#pragma omp flush(skip_remaining)1023}1024#endif10251026} // Stanley dec10271028} // parallel10291030#ifndef NCATCH1031if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);1032#endif10331034// collect the contribution of proper fases from inclusion/exclusion as far as not done yet10351036for(int i=0;i<omp_get_max_threads();++i)1037transferFacePolys(facePolys[i],faceClasses);10381039if(!faceClasses.empty())1040H.addCRF(evaluateFaceClasses(GFP,faceClasses));10411042// now we must return to rational coefficients10431044CyclRatFunct HRat(zero(R));1045HRat.denom=H.denom;1046HRat.num=makeQQCoeff(H.num,R);10471048HRat.num*=FF.myRemainingFactor;1049HRat.num/=power(lcmDets,deg(F));10501051HRat.showCoprimeCRF();10521053mpz_class commonDen; // common denominator of coefficients of numerator of H1054libnormaliz::HilbertSeries HS(nmzHilbertSeries(HRat,commonDen));1055HS.set_nr_coeff_quasipol(C.getIntData().getWeightedEhrhartSeries().first.get_nr_coeff_quasipol());1056HS.set_period_bounded(C.getIntData().getWeightedEhrhartSeries().first.get_period_bounded());10571058C.getIntData().setWeightedEhrhartSeries(make_pair(HS,commonDen));10591060C.getIntData().computeWeightedEhrhartQuasiPolynomial();10611062if(C.getIntData().isWeightedEhrhartQuasiPolynomialComputed()){1063mpq_class genMultQ;1064long deg=C.getIntData().getWeightedEhrhartQuasiPolynomial()[0].size()-1;1065long virtDeg=C.getRank()+C.getIntData().getDegreeOfPolynomial()-1;1066if(deg==virtDeg)1067genMultQ=C.getIntData().getWeightedEhrhartQuasiPolynomial()[0][virtDeg];1068genMultQ*=ourFactorial(virtDeg);1069genMultQ/=C.getIntData().getWeightedEhrhartQuasiPolynomialDenom();1070C.getIntData().setVirtualMultiplicity(genMultQ);1071}10721073verbose_INT=verbose_INTsave;10741075return;1076} // try1077catch (const CoCoA::ErrorInfo& err)1078{1079cerr << "***ERROR*** UNCAUGHT CoCoA error";1080ANNOUNCE(cerr, err);10811082throw NmzCoCoAException("");1083}1084}10851086#ifndef NMZ_MIC_OFFLOAD //offload with long is not supported1087template void integrate(Cone<long>& C, const bool do_virt_mult);1088#endif // NMZ_MIC_OFFLOAD1089template void integrate(Cone<long long>& C, const bool do_virt_mult);1090template void integrate(Cone<mpz_class>& C, const bool do_virt_mult);10911092#ifndef NMZ_MIC_OFFLOAD //offload with long is not supported1093template void generalizedEhrhartSeries<long>(Cone<long>& C);1094#endif // NMZ_MIC_OFFLOAD1095template void generalizedEhrhartSeries<long long>(Cone<long long>& C);1096template void generalizedEhrhartSeries<mpz_class>(Cone<mpz_class>& C);1097109810991100} // namespace libnormaliz11011102#endif //NMZ_COCOA110311041105