GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/*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#include <stdlib.h>24#include <list>25#include <sys/stat.h>26#include <sys/types.h>2728#include "libnormaliz/vector_operations.h"29#include "libnormaliz/map_operations.h"30#include "libnormaliz/convert.h"31#include "libnormaliz/cone.h"32#include "libnormaliz/full_cone.h"33#include "libnormaliz/my_omp.h"3435namespace libnormaliz {36using namespace std;3738// adds the signs inequalities given by Signs to Inequalities39template<typename Integer>40Matrix<Integer> sign_inequalities(const vector< vector<Integer> >& Signs) {41if (Signs.size() != 1) {42throw BadInputException("ERROR: Bad signs matrix, has "43+ toString(Signs.size()) + " rows (should be 1)!");44}45size_t dim = Signs[0].size();46Matrix<Integer> Inequ(0,dim);47vector<Integer> ineq(dim,0);48for (size_t i=0; i<dim; i++) {49Integer sign = Signs[0][i];50if (sign == 1 || sign == -1) {51ineq[i] = sign;52Inequ.append(ineq);53ineq[i] = 0;54} else if (sign != 0) {55throw BadInputException("Bad signs matrix, has entry "56+ toString(sign) + " (should be -1, 1 or 0)!");57}58}59return Inequ;60}6162template<typename Integer>63Matrix<Integer> strict_sign_inequalities(const vector< vector<Integer> >& Signs) {64if (Signs.size() != 1) {65throw BadInputException("ERROR: Bad signs matrix, has "66+ toString(Signs.size()) + " rows (should be 1)!");67}68size_t dim = Signs[0].size();69Matrix<Integer> Inequ(0,dim);70vector<Integer> ineq(dim,0);71ineq[dim-1]=-1;72for (size_t i=0; i<dim-1; i++) { // last component of strict_signs always 073Integer sign = Signs[0][i];74if (sign == 1 || sign == -1) {75ineq[i] = sign;76Inequ.append(ineq);77ineq[i] = 0;78} else if (sign != 0) {79throw BadInputException("Bad signs matrix, has entry "80+ toString(sign) + " (should be -1, 1 or 0)!");81}82}83return Inequ;84}8586template<typename Integer>87vector<vector<Integer> > find_input_matrix(const map< InputType, vector< vector<Integer> > >& multi_input_data,88const InputType type){8990typename map< InputType , vector< vector<Integer> > >::const_iterator it;91it = multi_input_data.find(type);92if (it != multi_input_data.end())93return(it->second);9495vector< vector<Integer> > dummy;96return(dummy);97}9899template<typename Integer>100void insert_column(vector< vector<Integer> >& mat, size_t col, Integer entry){101102if(mat.size()==0)103return;104vector<Integer> help(mat[0].size()+1);105for(size_t i=0;i<mat.size();++i){106for(size_t j=0;j<col;++j)107help[j]=mat[i][j];108help[col]=entry;109for(size_t j=col;j<mat[i].size();++j)110help[j+1]=mat[i][j];111mat[i]=help;112}113}114115template<typename Integer>116void insert_zero_column(vector< vector<Integer> >& mat, size_t col){117// Integer entry=0;118insert_column<Integer>(mat,col,0);119}120121template<typename Integer>122void Cone<Integer>::homogenize_input(map< InputType, vector< vector<Integer> > >& multi_input_data){123124typename map< InputType , vector< vector<Integer> > >::iterator it;125it = multi_input_data.begin();126for(;it!=multi_input_data.end();++it){127switch(it->first){128case Type::dehomogenization:129throw BadInputException("Type dehomogenization not allowed with inhomogeneous input!");130break;131case Type::inhom_inequalities: // nothing to do132case Type::inhom_equations:133case Type::inhom_congruences:134case Type::polyhedron:135case Type::vertices:136case Type::support_hyperplanes:137case Type::open_facets:138case Type::grading: // already taken care of139break;140case Type::strict_inequalities:141insert_column<Integer>(it->second,dim-1,-1);142break;143case Type::offset:144insert_column<Integer>(it->second,dim-1,1);145break;146default: // is correct for signs and strict_signs !147insert_zero_column<Integer>(it->second,dim-1);148break;149}150}151}152153bool denominator_allowed(InputType input_type){154155switch(input_type){156157case Type::congruences:158case Type::inhom_congruences:159case Type::grading:160case Type::dehomogenization:161case Type::lattice:162case Type::normalization:163case Type::cone_and_lattice:164case Type::offset:165case Type::rees_algebra:166case Type::lattice_ideal:167case Type::signs:168case Type::strict_signs:169// case Type::open_facets:170return false;171break;172default:173return true;174break;175}176}177178//---------------------------------------------------------------------------179180template<typename Integer>181Cone<Integer>::Cone(){182}183184template<typename Integer>185Cone<Integer>::Cone(InputType input_type, const vector< vector<Integer> >& Input) {186// convert to a map187map< InputType, vector< vector<Integer> > > multi_input_data;188multi_input_data[input_type] = Input;189process_multi_input(multi_input_data);190}191192template<typename Integer>193Cone<Integer>::Cone(InputType type1, const vector< vector<Integer> >& Input1,194InputType type2, const vector< vector<Integer> >& Input2) {195if (type1 == type2) {196throw BadInputException("Input types must pairwise different!");197}198// convert to a map199map< InputType, vector< vector<Integer> > > multi_input_data;200multi_input_data[type1] = Input1;201multi_input_data[type2] = Input2;202process_multi_input(multi_input_data);203}204205template<typename Integer>206Cone<Integer>::Cone(InputType type1, const vector< vector<Integer> >& Input1,207InputType type2, const vector< vector<Integer> >& Input2,208InputType type3, const vector< vector<Integer> >& Input3) {209if (type1 == type2 || type1 == type3 || type2 == type3) {210throw BadInputException("Input types must be pairwise different!");211}212// convert to a map213map< InputType, vector< vector<Integer> > > multi_input_data;214multi_input_data[type1] = Input1;215multi_input_data[type2] = Input2;216multi_input_data[type3] = Input3;217process_multi_input(multi_input_data);218}219220template<typename Integer>221Cone<Integer>::Cone(const map< InputType, vector< vector<Integer> > >& multi_input_data) {222process_multi_input(multi_input_data);223}224225// now with mpq_class input226227template<typename Integer>228Cone<Integer>::Cone(InputType input_type, const vector< vector<mpq_class> >& Input) {229// convert to a map230map< InputType, vector< vector<mpq_class> > > multi_input_data;231multi_input_data[input_type] = Input;232process_multi_input(multi_input_data);233}234235template<typename Integer>236Cone<Integer>::Cone(InputType type1, const vector< vector<mpq_class> >& Input1,237InputType type2, const vector< vector<mpq_class> >& Input2) {238if (type1 == type2) {239throw BadInputException("Input types must pairwise different!");240}241// convert to a map242map< InputType, vector< vector<mpq_class> > > multi_input_data;243multi_input_data[type1] = Input1;244multi_input_data[type2] = Input2;245process_multi_input(multi_input_data);246}247248template<typename Integer>249Cone<Integer>::Cone(InputType type1, const vector< vector<mpq_class> >& Input1,250InputType type2, const vector< vector<mpq_class> >& Input2,251InputType type3, const vector< vector<mpq_class> >& Input3) {252if (type1 == type2 || type1 == type3 || type2 == type3) {253throw BadInputException("Input types must be pairwise different!");254}255// convert to a map256map< InputType, vector< vector<mpq_class> > > multi_input_data;257multi_input_data[type1] = Input1;258multi_input_data[type2] = Input2;259multi_input_data[type3] = Input3;260process_multi_input(multi_input_data);261}262263template<typename Integer>264Cone<Integer>::Cone(const map< InputType, vector< vector<mpq_class> > >& multi_input_data) {265process_multi_input(multi_input_data);266}267268// now with nmz_float input269270template<typename Integer>271Cone<Integer>::Cone(InputType input_type, const vector< vector<nmz_float> >& Input) {272// convert to a map273map< InputType, vector< vector<nmz_float> > > multi_input_data;274multi_input_data[input_type] = Input;275process_multi_input(multi_input_data);276}277278template<typename Integer>279Cone<Integer>::Cone(InputType type1, const vector< vector<nmz_float> >& Input1,280InputType type2, const vector< vector<nmz_float> >& Input2) {281if (type1 == type2) {282throw BadInputException("Input types must pairwise different!");283}284// convert to a map285map< InputType, vector< vector<nmz_float> > > multi_input_data;286multi_input_data[type1] = Input1;287multi_input_data[type2] = Input2;288process_multi_input(multi_input_data);289}290291template<typename Integer>292Cone<Integer>::Cone(InputType type1, const vector< vector<nmz_float> >& Input1,293InputType type2, const vector< vector<nmz_float> >& Input2,294InputType type3, const vector< vector<nmz_float> >& Input3) {295if (type1 == type2 || type1 == type3 || type2 == type3) {296throw BadInputException("Input types must be pairwise different!");297}298// convert to a map299map< InputType, vector< vector<nmz_float> > > multi_input_data;300multi_input_data[type1] = Input1;301multi_input_data[type2] = Input2;302multi_input_data[type3] = Input3;303process_multi_input(multi_input_data);304}305306template<typename Integer>307Cone<Integer>::Cone(const map< InputType, vector< vector<nmz_float> > >& multi_input_data) {308process_multi_input(multi_input_data);309}310311//---------------------------------------------------------------------------312// now with Matrix313//---------------------------------------------------------------------------314315template<typename Integer>316Cone<Integer>::Cone(InputType input_type, const Matrix<Integer>& Input) {317// convert to a map318map< InputType, vector< vector<Integer> > >multi_input_data;319multi_input_data[input_type] = Input.get_elements();320process_multi_input(multi_input_data);321}322323template<typename Integer>324Cone<Integer>::Cone(InputType type1, const Matrix<Integer>& Input1,325InputType type2, const Matrix<Integer>& Input2) {326if (type1 == type2) {327throw BadInputException("Input types must pairwise different!");328}329// convert to a map330map< InputType, vector< vector<Integer> > > multi_input_data;331multi_input_data[type1] = Input1.get_elements();332multi_input_data[type2] = Input2.get_elements();333process_multi_input(multi_input_data);334}335336template<typename Integer>337Cone<Integer>::Cone(InputType type1, const Matrix<Integer>& Input1,338InputType type2, const Matrix<Integer>& Input2,339InputType type3, const Matrix<Integer>& Input3) {340if (type1 == type2 || type1 == type3 || type2 == type3) {341throw BadInputException("Input types must be pairwise different!");342}343// convert to a map344map< InputType, vector< vector<Integer> > > multi_input_data;345multi_input_data[type1] = Input1.get_elements();346multi_input_data[type2] = Input2.get_elements();347multi_input_data[type3] = Input3.get_elements();348process_multi_input(multi_input_data);349}350351template<typename Integer>352Cone<Integer>::Cone(const map< InputType, Matrix<Integer> >& multi_input_data_Matrix){353map< InputType, vector< vector<Integer> > > multi_input_data;354auto it = multi_input_data_Matrix.begin();355for(; it != multi_input_data_Matrix.end(); ++it){356multi_input_data[it->first]=it->second.get_elements();357}358process_multi_input(multi_input_data);359}360361//---------------------------------------------------------------------------362// now with Matrix and mpq_class363364template<typename Integer>365Cone<Integer>::Cone(InputType input_type, const Matrix<mpq_class>& Input) {366// convert to a map367map< InputType, vector< vector<mpq_class> > >multi_input_data;368multi_input_data[input_type] = Input.get_elements();369process_multi_input(multi_input_data);370}371372template<typename Integer>373Cone<Integer>::Cone(InputType type1, const Matrix<mpq_class>& Input1,374InputType type2, const Matrix<mpq_class>& Input2) {375if (type1 == type2) {376throw BadInputException("Input types must pairwise different!");377}378// convert to a map379map< InputType, vector< vector<mpq_class> > > multi_input_data;380multi_input_data[type1] = Input1.get_elements();381multi_input_data[type2] = Input2.get_elements();382process_multi_input(multi_input_data);383}384385template<typename Integer>386Cone<Integer>::Cone(InputType type1, const Matrix<mpq_class>& Input1,387InputType type2, const Matrix<mpq_class>& Input2,388InputType type3, const Matrix<mpq_class>& Input3) {389if (type1 == type2 || type1 == type3 || type2 == type3) {390throw BadInputException("Input types must be pairwise different!");391}392// convert to a map393map< InputType, vector< vector<mpq_class> > > multi_input_data;394multi_input_data[type1] = Input1.get_elements();395multi_input_data[type2] = Input2.get_elements();396multi_input_data[type3] = Input3.get_elements();397process_multi_input(multi_input_data);398}399400template<typename Integer>401Cone<Integer>::Cone(const map< InputType, Matrix<mpq_class> >& multi_input_data_Matrix){402map< InputType, vector< vector<mpq_class> > > multi_input_data;403auto it = multi_input_data_Matrix.begin();404for(; it != multi_input_data_Matrix.end(); ++it){405multi_input_data[it->first]=it->second.get_elements();406}407process_multi_input(multi_input_data);408}409410//---------------------------------------------------------------------------411// now with Matrix and nmz_float412413template<typename Integer>414Cone<Integer>::Cone(InputType input_type, const Matrix<nmz_float>& Input) {415// convert to a map416map< InputType, vector< vector<nmz_float> > >multi_input_data;417multi_input_data[input_type] = Input.get_elements();418process_multi_input(multi_input_data);419}420421template<typename Integer>422Cone<Integer>::Cone(InputType type1, const Matrix<nmz_float>& Input1,423InputType type2, const Matrix<nmz_float>& Input2) {424if (type1 == type2) {425throw BadInputException("Input types must pairwise different!");426}427// convert to a map428map< InputType, vector< vector<nmz_float> > > multi_input_data;429multi_input_data[type1] = Input1.get_elements();430multi_input_data[type2] = Input2.get_elements();431process_multi_input(multi_input_data);432}433434template<typename Integer>435Cone<Integer>::Cone(InputType type1, const Matrix<nmz_float>& Input1,436InputType type2, const Matrix<nmz_float>& Input2,437InputType type3, const Matrix<nmz_float>& Input3) {438if (type1 == type2 || type1 == type3 || type2 == type3) {439throw BadInputException("Input types must be pairwise different!");440}441// convert to a map442map< InputType, vector< vector<nmz_float> > > multi_input_data;443multi_input_data[type1] = Input1.get_elements();444multi_input_data[type2] = Input2.get_elements();445multi_input_data[type3] = Input3.get_elements();446process_multi_input(multi_input_data);447}448449template<typename Integer>450Cone<Integer>::Cone(const map< InputType, Matrix<nmz_float> >& multi_input_data_Matrix){451map< InputType, vector< vector<nmz_float> > > multi_input_data;452auto it = multi_input_data_Matrix.begin();453for(; it != multi_input_data_Matrix.end(); ++it){454multi_input_data[it->first]=it->second.get_elements();455}456process_multi_input(multi_input_data);457}458459//---------------------------------------------------------------------------460461template<typename Integer>462Cone<Integer>::~Cone() {463if(IntHullCone!=NULL)464delete IntHullCone;465if(IntHullCone!=NULL)466delete SymmCone;467}468469//---------------------------------------------------------------------------470471template<typename Integer>472void Cone<Integer>::process_multi_input(const map< InputType, vector< vector<mpq_class> > >& multi_input_data_const) {473474map< InputType, vector< vector<mpq_class> > > multi_input_data(multi_input_data_const);475// since polytope will be comverted to cone, we must do some checks here476if(exists_element(multi_input_data,Type::grading) && exists_element(multi_input_data,Type::polytope)){477throw BadInputException("No explicit grading allowed with polytope!");478}479if(exists_element(multi_input_data,Type::cone) && exists_element(multi_input_data,Type::polytope)){480throw BadInputException("Illegal combination of cone generator types!");481}482483map< InputType, vector< vector<Integer> > > multi_input_data_ZZ;484485// special treatment of polytope. We convert it o cone486if(exists_element(multi_input_data,Type::polytope)){487size_t dim;488if(multi_input_data[Type::polytope].size()>0){489dim=multi_input_data[Type::polytope][0].size()+1;490vector<vector<Integer> > grading;491grading.push_back(vector<Integer>(dim));492grading[0][dim-1]=1;493multi_input_data_ZZ[Type::grading]=grading;494}495multi_input_data[Type::cone]=multi_input_data[Type::polytope];496multi_input_data.erase(Type::polytope);497for(size_t i=0;i<multi_input_data[Type::cone].size();++i){498multi_input_data[Type::cone][i].resize(dim);499multi_input_data[Type::cone][i][dim-1]=1;500}501}502503// now we clear denominators504auto it = multi_input_data.begin();505for(; it != multi_input_data.end(); ++it) {506for(size_t i=0;i < it->second.size();++i){507mpz_class common_denom=1;508for(size_t j=0;j<it->second[i].size();++j){509it->second[i][j].canonicalize();510common_denom=libnormaliz::lcm(common_denom,it->second[i][j].get_den());511}512if(common_denom>1 && !denominator_allowed(it->first))513throw BadInputException("Proper fraction not allowed in certain input types");514vector<Integer> transfer(it->second[i].size());515for(size_t j=0;j<it->second[i].size();++j){516it->second[i][j]*=common_denom;517convert(transfer[j],it->second[i][j].get_num());518}519multi_input_data_ZZ[it->first].push_back(transfer);520}521}522523process_multi_input_inner(multi_input_data_ZZ);524}525526template<typename Integer>527void Cone<Integer>::process_multi_input(const map< InputType, vector< vector<nmz_float> > >& multi_input_data) {528529map< InputType, vector< vector<mpq_class> > > multi_input_data_QQ;530auto it = multi_input_data.begin();531for(; it != multi_input_data.end(); ++it) {532vector<vector<mpq_class> > Transfer;533vector<mpq_class> vt;534for(size_t j=0;j<it->second.size();++j){535for(size_t k=0;k<it->second[j].size();++k)536vt.push_back(mpq_class(it->second[j][k]));537Transfer.push_back(vt);538}539multi_input_data_QQ[it->first]=Transfer;540}541process_multi_input(multi_input_data_QQ);542}543544template<typename Integer>545void Cone<Integer>::process_multi_input(const map< InputType, vector< vector<Integer> > >& multi_input_data_const) {546initialize();547map< InputType, vector< vector<Integer> > > multi_input_data(multi_input_data_const);548process_multi_input_inner(multi_input_data);549}550551template<typename Integer>552void Cone<Integer>::process_multi_input_inner(map< InputType, vector< vector<Integer> > >& multi_input_data) {553initialize();554// find basic input type555lattice_ideal_input=false;556nr_latt_gen=0, nr_cone_gen=0;557bool inhom_input=false;558559inequalities_present=false; //control choice of positive orthant560561// NEW: Empty matrix have syntactical influence562auto it = multi_input_data.begin();563for(; it != multi_input_data.end(); ++it) {564switch (it->first) {565case Type::inhom_inequalities:566case Type::inhom_equations:567case Type::inhom_congruences:568case Type::strict_inequalities:569case Type::strict_signs:570case Type::open_facets:571inhom_input=true;572case Type::signs:573case Type::inequalities:574case Type::equations:575case Type::congruences:576break;577case Type::lattice_ideal:578lattice_ideal_input=true;579break;580case Type::polyhedron:581inhom_input=true;582case Type::integral_closure:583case Type::rees_algebra:584case Type::polytope:585case Type::cone:586case Type::subspace:587nr_cone_gen++;588break;589case Type::normalization:590case Type::cone_and_lattice:591nr_cone_gen++;592case Type::lattice:593case Type::saturation:594nr_latt_gen++;595break;596case Type::vertices:597case Type::offset:598inhom_input=true;599default:600break;601}602603switch (it->first) { // chceck existence of inrqualities604case Type::inhom_inequalities:605case Type::strict_inequalities:606case Type::strict_signs:607case Type::signs:608case Type::inequalities:609case Type::excluded_faces:610case Type::support_hyperplanes:611inequalities_present=true;612default:613break;614}615616}617618bool gen_error=false;619if(nr_cone_gen>2)620gen_error=true;621622if(nr_cone_gen==2 && (!exists_element(multi_input_data,Type::subspace)623|| !(exists_element(multi_input_data,Type::cone)624|| exists_element(multi_input_data,Type::cone_and_lattice)625|| exists_element(multi_input_data,Type::integral_closure)626|| exists_element(multi_input_data,Type::normalization) ) )627)628gen_error=true;629630if(gen_error){631throw BadInputException("Illegal combination of cone generator types!");632}633634635if(nr_latt_gen>1){636throw BadInputException("Only one matrix of lattice generators allowed!");637}638if(lattice_ideal_input){639if(multi_input_data.size() > 2 || (multi_input_data.size()==2 && !exists_element(multi_input_data,Type::grading))){640throw BadInputException("Only grading allowed with lattice_ideal!");641}642}643if(exists_element(multi_input_data,Type::open_facets)){644size_t allowed=0;645auto it = multi_input_data.begin();646for(; it != multi_input_data.end(); ++it) {647switch (it->first) {648case Type::open_facets:649case Type::cone:650case Type::grading:651case Type::vertices:652allowed++;653break;654default:655break;656}657}658if(allowed!=multi_input_data.size())659throw BadInputException("Illegal combination of input types with open_facets!");660if(exists_element(multi_input_data,Type::vertices)){661if(multi_input_data[Type::vertices].size()>1)662throw BadInputException("At most one vertex allowed with open_facets!");663}664665}666if(inhom_input){667if(exists_element(multi_input_data,Type::dehomogenization) || exists_element(multi_input_data,Type::support_hyperplanes)){668throw BadInputException("Types dehomogenization and support_hyperplanes not allowed with inhomogeneous input!");669}670}671if(inhom_input || exists_element(multi_input_data,Type::dehomogenization)){672if(exists_element(multi_input_data,Type::rees_algebra) || exists_element(multi_input_data,Type::polytope)){673throw BadInputException("Types polytope and rees_algebra not allowed with inhomogeneous input or dehomogenization!");674}675if(exists_element(multi_input_data,Type::excluded_faces)){676throw BadInputException("Type excluded_faces not allowed with inhomogeneous input or dehomogenization!");677}678}679if(exists_element(multi_input_data,Type::grading) && exists_element(multi_input_data,Type::polytope)){680throw BadInputException("No explicit grading allowed with polytope!");681}682683// remove empty matrices684it = multi_input_data.begin();685for(; it != multi_input_data.end();) {686if (it->second.size() == 0)687multi_input_data.erase(it++);688else689++it;690}691692if(multi_input_data.size()==0){693throw BadInputException("All input matrices empty!");694}695696//determine dimension697it = multi_input_data.begin();698size_t inhom_corr = 0; // correction in the inhom_input case699if (inhom_input) inhom_corr = 1;700dim = it->second.front().size() - type_nr_columns_correction(it->first) + inhom_corr;701702// We now process input types that are independent of generators, constraints, lattice_ideal703// check for excluded faces704705ExcludedFaces = find_input_matrix(multi_input_data,Type::excluded_faces);706if(ExcludedFaces.nr_of_rows()==0)707ExcludedFaces=Matrix<Integer>(0,dim); // we may need the correct number of columns708PreComputedSupportHyperplanes = find_input_matrix(multi_input_data,Type::support_hyperplanes);709710// check for a grading711vector< vector<Integer> > lf = find_input_matrix(multi_input_data,Type::grading);712if (lf.size() > 1) {713throw BadInputException("Bad grading, has "714+ toString(lf.size()) + " rows (should be 1)!");715}716if(lf.size()==1){717if(inhom_input)718lf[0].push_back(0); // first we extend grading trivially to have the right dimension719setGrading (lf[0]); // will eventually be set in full_cone.cpp720721}722723// cout << "Dim " << dim <<endl;724725// check consistence of dimension726it = multi_input_data.begin();727size_t test_dim;728for (; it != multi_input_data.end(); ++it) {729test_dim = it->second.front().size() - type_nr_columns_correction(it->first) + inhom_corr;730if (test_dim != dim) {731throw BadInputException("Inconsistent dimensions in input!");732}733}734735if(inhom_input)736homogenize_input(multi_input_data);737738// check for dehomogenization739lf = find_input_matrix(multi_input_data,Type::dehomogenization);740if (lf.size() > 1) {741throw BadInputException("Bad dehomogenization, has "742+ toString(lf.size()) + " rows (should be 1)!");743}744if(lf.size()==1){745setDehomogenization(lf[0]);746}747748// now we can unify implicit and explicit truncation749// Note: implicit and explicit truncation have already been excluded750if (inhom_input) {751Dehomogenization.resize(dim,0),752Dehomogenization[dim-1]=1;753is_Computed.set(ConeProperty::Dehomogenization);754}755if(isComputed(ConeProperty::Dehomogenization))756inhomogeneous=true;757758if(lattice_ideal_input){759prepare_input_lattice_ideal(multi_input_data);760}761762Matrix<Integer> LatticeGenerators(0,dim);763prepare_input_generators(multi_input_data, LatticeGenerators);764765prepare_input_constraints(multi_input_data); // sets Equations,Congruences,Inequalities766767// set default values if necessary768if(inhom_input && LatticeGenerators.nr_of_rows()!=0 && !exists_element(multi_input_data,Type::offset)){769vector<Integer> offset(dim);770offset[dim-1]=1;771LatticeGenerators.append(offset);772}773if(inhom_input && Generators.nr_of_rows()!=0 && !exists_element(multi_input_data,Type::vertices)774&& !exists_element(multi_input_data,Type::polyhedron)){775vector<Integer> vertex(dim);776vertex[dim-1]=1;777Generators.append(vertex);778}779780if(Inequalities.nr_of_rows()>0 && Generators.nr_of_rows()>0){ // eliminate superfluous inequalities781vector<key_t> essential;782for(size_t i=0;i<Inequalities.nr_of_rows();++i){783for (size_t j=0;j<Generators.nr_of_rows();++j){784if(v_scalar_product(Inequalities[i],Generators[j])<0){785essential.push_back(i);786break;787}788}789}790if(essential.size()<Inequalities.nr_of_rows())791Inequalities=Inequalities.submatrix(essential);792}793794// cout << "Ineq " << Inequalities.nr_of_rows() << endl;795796process_lattice_data(LatticeGenerators,Congruences,Equations);797798bool cone_sat_eq=no_lattice_restriction;799bool cone_sat_cong=no_lattice_restriction;800801// cout << "nolatrest " << no_lattice_restriction << endl;802803if(Inequalities.nr_of_rows()==0 && Generators.nr_of_rows()!=0){804if(!no_lattice_restriction){805cone_sat_eq=true;806for(size_t i=0;i<Generators.nr_of_rows() && cone_sat_eq;++i)807for(size_t j=0;j<Equations.nr_of_rows() && cone_sat_eq ;++j)808if(v_scalar_product(Generators[i],Equations[j])!=0){809cone_sat_eq=false;810}811}812if(!no_lattice_restriction){813cone_sat_cong=true;814for(size_t i=0;i<Generators.nr_of_rows() && cone_sat_cong;++i){815vector<Integer> test=Generators[i];816test.resize(dim+1);817for(size_t j=0;j<Congruences.nr_of_rows() && cone_sat_cong ;++j)818if(v_scalar_product(test,Congruences[j]) % Congruences[j][dim] !=0)819cone_sat_cong=false;820}821}822823if(cone_sat_eq && cone_sat_cong){824set_original_monoid_generators(Generators);825}826827if(cone_sat_eq && !cone_sat_cong){ // multiply generators by anniullator mod sublattice828for(size_t i=0;i<Generators.nr_of_rows();++i)829v_scalar_multiplication(Generators[i],BasisChange.getAnnihilator());830cone_sat_cong=true;831}832}833834if((Inequalities.nr_of_rows()!=0 || !cone_sat_eq) && Generators.nr_of_rows()!=0){835Sublattice_Representation<Integer> ConeLatt(Generators,true);836Full_Cone<Integer> TmpCone(ConeLatt.to_sublattice(Generators));837TmpCone.dualize_cone();838Inequalities.append(ConeLatt.from_sublattice_dual(TmpCone.Support_Hyperplanes));839Generators=Matrix<Integer>(0,dim); // Generators now converted into inequalities840}841842if(exists_element(multi_input_data,Type::open_facets)){843// read manual for the computation that follows844if(!isComputed(ConeProperty::OriginalMonoidGenerators)) // practically impossible, but better to check845throw BadInputException("Error in connection with open_facets");846if(Generators.nr_of_rows()!=BasisChange.getRank())847throw BadInputException("Cone for open_facets not simplicial!");848Matrix<Integer> TransformedGen=BasisChange.to_sublattice(Generators);849vector<key_t> key(TransformedGen.nr_of_rows());850for(size_t j=0;j<TransformedGen.nr_of_rows();++j)851key[j]=j;852Matrix<Integer> TransformedSupps;853Integer dummy;854TransformedGen.simplex_data(key,TransformedSupps,dummy,false);855Matrix<Integer> NewSupps=BasisChange.from_sublattice_dual(TransformedSupps);856NewSupps.remove_row(NewSupps.nr_of_rows()-1); // must remove the inequality for the homogenizing variable857for(size_t j=0;j<NewSupps.nr_of_rows();++j){858if(!(multi_input_data[Type::open_facets][0][j]==0 || multi_input_data[Type::open_facets][0][j]==1))859throw BadInputException("Illegal entry in open_facets");860NewSupps[j][dim-1]-=multi_input_data[Type::open_facets][0][j];861}862NewSupps.append(BasisChange.getEquationsMatrix());863Matrix<Integer> Ker=NewSupps.kernel(); // gives the new verterx864// Ker.pretty_print(cout);865assert(Ker.nr_of_rows()==1);866Generators[Generators.nr_of_rows()-1]=Ker[0];867}868869assert(Inequalities.nr_of_rows()==0 || Generators.nr_of_rows()==0);870871if(Generators.nr_of_rows()==0)872prepare_input_type_4(Inequalities); // inserts default inequalties if necessary873else{874is_Computed.set(ConeProperty::Generators);875is_Computed.set(ConeProperty::Sublattice);876}877878checkGrading();879checkDehomogenization();880881if(isComputed(ConeProperty::Grading)) {// cone known to be pointed882is_Computed.set(ConeProperty::MaximalSubspace);883pointed=true;884is_Computed.set(ConeProperty::IsPointed);885}886887setWeights(); // make matrix of weights for sorting888889if(PreComputedSupportHyperplanes.nr_of_rows()>0){890check_precomputed_support_hyperplanes();891SupportHyperplanes=PreComputedSupportHyperplanes;892is_Computed.set(ConeProperty::SupportHyperplanes);893}894895BasisChangePointed=BasisChange;896897is_Computed.set(ConeProperty::IsInhomogeneous);898is_Computed.set(ConeProperty::EmbeddingDim);899900/* if(ExcludedFaces.nr_of_rows()>0){ // Nothing to check anymore901check_excluded_faces();902} */903904/*905cout <<"-----------------------" << endl;906cout << "Gen " << endl;907Generators.pretty_print(cout);908cout << "Supp " << endl;909SupportHyperplanes.pretty_print(cout);910cout << "A" << endl;911BasisChange.get_A().pretty_print(cout);912cout << "B" << endl;913BasisChange.get_B().pretty_print(cout);914cout <<"-----------------------" << endl;915*/916}917918919//---------------------------------------------------------------------------920921template<typename Integer>922void Cone<Integer>::prepare_input_constraints(const map< InputType, vector< vector<Integer> > >& multi_input_data) {923924Matrix<Integer> Signs(0,dim), StrictSigns(0,dim);925926SupportHyperplanes=Matrix<Integer>(0,dim);927Inequalities=Matrix<Integer>(0,dim);928Equations=Matrix<Integer>(0,dim);929Congruences=Matrix<Integer>(0,dim+1);930931typename map< InputType , vector< vector<Integer> > >::const_iterator it=multi_input_data.begin();932933it = multi_input_data.begin();934for (; it != multi_input_data.end(); ++it) {935936switch (it->first) {937case Type::strict_inequalities:938case Type::inequalities:939case Type::inhom_inequalities:940case Type::excluded_faces:941Inequalities.append(it->second);942break;943case Type::equations:944case Type::inhom_equations:945Equations.append(it->second);946break;947case Type::congruences:948case Type::inhom_congruences:949Congruences.append(it->second);950break;951case Type::signs:952Signs = sign_inequalities(it->second);953break;954case Type::strict_signs:955StrictSigns = strict_sign_inequalities(it->second);956break;957default:958break;959}960}961if(!BC_set) compose_basis_change(Sublattice_Representation<Integer>(dim));962Matrix<Integer> Help(Signs); // signs first !!963Help.append(StrictSigns); // then strict signs964Help.append(Inequalities);965Inequalities=Help;966}967968//---------------------------------------------------------------------------969template<typename Integer>970void Cone<Integer>::prepare_input_generators(map< InputType, vector< vector<Integer> > >& multi_input_data, Matrix<Integer>& LatticeGenerators) {971972if(exists_element(multi_input_data,Type::vertices)){973for(size_t i=0;i<multi_input_data[Type::vertices].size();++i)974if(multi_input_data[Type::vertices][i][dim-1] <= 0) {975throw BadInputException("Vertex has non-positive denominator!");976}977}978979if(exists_element(multi_input_data,Type::polyhedron)){980for(size_t i=0;i<multi_input_data[Type::polyhedron].size();++i)981if(multi_input_data[Type::polyhedron][i][dim-1] < 0) {982throw BadInputException("Polyhedron vertex has negative denominator!");983}984}985986typename map< InputType , vector< vector<Integer> > >::const_iterator it=multi_input_data.begin();987// find specific generator type -- there is only one, as checked already988989normalization=false;990991// check for subspace992BasisMaxSubspace = find_input_matrix(multi_input_data,Type::subspace);993if(BasisMaxSubspace.nr_of_rows()==0)994BasisMaxSubspace=Matrix<Integer>(0,dim);995996vector<Integer> neg_sum_subspace(dim,0);997for(size_t i=0;i<BasisMaxSubspace.nr_of_rows();++i)998neg_sum_subspace=v_add(neg_sum_subspace,BasisMaxSubspace[i]);999v_scalar_multiplication<Integer>(neg_sum_subspace,-1);100010011002Generators=Matrix<Integer>(0,dim);1003for(; it != multi_input_data.end(); ++it) {1004switch (it->first) {1005case Type::normalization:1006case Type::cone_and_lattice:1007normalization=true;1008LatticeGenerators.append(it->second);1009if(BasisMaxSubspace.nr_of_rows()>0)1010LatticeGenerators.append(BasisMaxSubspace);1011case Type::vertices:1012case Type::polyhedron:1013case Type::cone:1014case Type::integral_closure:1015Generators.append(it->second);1016break;1017case Type::subspace:1018Generators.append(it->second);1019Generators.append(neg_sum_subspace);1020break;1021case Type::polytope:1022Generators.append(prepare_input_type_2(it->second));1023break;1024case Type::rees_algebra:1025Generators.append(prepare_input_type_3(it->second));1026break;1027case Type::lattice:1028LatticeGenerators.append(it->second);1029break;1030case Type::saturation:1031LatticeGenerators.append(it->second);1032LatticeGenerators.saturate();1033break;1034case Type::offset:1035if(it->second.size()>1){1036throw BadInputException("Only one offset allowed!");1037}1038LatticeGenerators.append(it->second);1039break;1040default: break;1041}1042}1043}10441045//---------------------------------------------------------------------------10461047template<typename Integer>1048void Cone<Integer>::process_lattice_data(const Matrix<Integer>& LatticeGenerators, Matrix<Integer>& Congruences, Matrix<Integer>& Equations) {10491050if(!BC_set)1051compose_basis_change(Sublattice_Representation<Integer>(dim));10521053bool no_constraints=(Congruences.nr_of_rows()==0) && (Equations.nr_of_rows()==0);1054bool only_cone_gen=(Generators.nr_of_rows()!=0) && no_constraints && (LatticeGenerators.nr_of_rows()==0);10551056no_lattice_restriction=true;10571058if(only_cone_gen){1059Sublattice_Representation<Integer> Basis_Change(Generators,true);1060compose_basis_change(Basis_Change);1061return;1062}10631064if(normalization && no_constraints){1065Sublattice_Representation<Integer> Basis_Change(Generators,false);1066compose_basis_change(Basis_Change);1067return;1068}10691070no_lattice_restriction=false;10711072if(Generators.nr_of_rows()!=0){1073Equations.append(Generators.kernel());1074}10751076if(LatticeGenerators.nr_of_rows()!=0){1077Sublattice_Representation<Integer> GenSublattice(LatticeGenerators,false);1078if((Equations.nr_of_rows()==0) && (Congruences.nr_of_rows()==0)){1079compose_basis_change(GenSublattice);1080return;1081}1082Congruences.append(GenSublattice.getCongruencesMatrix());1083Equations.append(GenSublattice.getEquationsMatrix());1084}10851086if (Congruences.nr_of_rows() > 0) {1087bool zero_modulus;1088Matrix<Integer> Ker_Basis=Congruences.solve_congruences(zero_modulus);1089if(zero_modulus) {1090throw BadInputException("Modulus 0 in congruence!");1091}1092Sublattice_Representation<Integer> Basis_Change(Ker_Basis,false);1093compose_basis_change(Basis_Change);1094}10951096if (Equations.nr_of_rows()>0) {1097Matrix<Integer> Ker_Basis=BasisChange.to_sublattice_dual(Equations).kernel();1098Sublattice_Representation<Integer> Basis_Change(Ker_Basis,true);1099compose_basis_change(Basis_Change);1100}1101}11021103//---------------------------------------------------------------------------11041105template<typename Integer>1106void Cone<Integer>::prepare_input_type_4(Matrix<Integer>& Inequalities) {11071108if (!inequalities_present) {1109if (verbose) {1110verboseOutput() << "No inequalities specified in constraint mode, using non-negative orthant." << endl;1111}1112if(inhomogeneous){1113vector<Integer> test(dim);1114test[dim-1]=1;1115size_t matsize=dim;1116if(test==Dehomogenization) // in this case "last coordinate >= 0" will come in through the dehomogenization1117matsize=dim-1; // we don't check for any other coincidence1118Inequalities= Matrix<Integer>(matsize,dim);1119for(size_t j=0;j<matsize;++j)1120Inequalities[j][j]=1;1121}1122else1123Inequalities = Matrix<Integer>(dim);1124}1125if(inhomogeneous)1126SupportHyperplanes.append(Dehomogenization);1127SupportHyperplanes.append(Inequalities);1128}112911301131//---------------------------------------------------------------------------11321133/* polytope input */1134template<typename Integer>1135Matrix<Integer> Cone<Integer>::prepare_input_type_2(const vector< vector<Integer> >& Input) {1136size_t j;1137size_t nr = Input.size();1138//append a column of 11139Matrix<Integer> Generators(nr, dim);1140for (size_t i=0; i<nr; i++) {1141for (j=0; j<dim-1; j++)1142Generators[i][j] = Input[i][j];1143Generators[i][dim-1]=1;1144}1145// use the added last component as grading1146Grading = vector<Integer>(dim,0);1147Grading[dim-1] = 1;1148is_Computed.set(ConeProperty::Grading);1149GradingDenom=1;1150is_Computed.set(ConeProperty::GradingDenom);1151return Generators;1152}11531154//---------------------------------------------------------------------------11551156/* rees input */1157template<typename Integer>1158Matrix<Integer> Cone<Integer>::prepare_input_type_3(const vector< vector<Integer> >& InputV) {1159Matrix<Integer> Input(InputV);1160int i,j,k,nr_rows=Input.nr_of_rows(), nr_columns=Input.nr_of_columns();1161// create cone generator matrix1162Matrix<Integer> Full_Cone_Generators(nr_rows+nr_columns,nr_columns+1,0);1163for (i = 0; i < nr_columns; i++) {1164Full_Cone_Generators[i][i]=1;1165}1166for(i=0; i<nr_rows; i++){1167Full_Cone_Generators[i+nr_columns][nr_columns]=1;1168for(j=0; j<nr_columns; j++) {1169Full_Cone_Generators[i+nr_columns][j]=Input[i][j];1170}1171}1172// primarity test1173vector<bool> Prim_Test(nr_columns,false);1174for (i=0; i<nr_rows; i++) {1175k=0;1176size_t v=0;1177for(j=0; j<nr_columns; j++)1178if (Input[i][j]!=0 ){1179k++;1180v=j;1181}1182if(k==1)1183Prim_Test[v]=true;1184}1185rees_primary=true;1186for(i=0; i<nr_columns; i++)1187if(!Prim_Test[i])1188rees_primary=false;11891190is_Computed.set(ConeProperty::IsReesPrimary);1191return Full_Cone_Generators;1192}119311941195//---------------------------------------------------------------------------11961197template<typename Integer>1198void Cone<Integer>::prepare_input_lattice_ideal(map< InputType, vector< vector<Integer> > >& multi_input_data) {11991200Matrix<Integer> Binomials(find_input_matrix(multi_input_data,Type::lattice_ideal));12011202if (Grading.size()>0) {1203//check if binomials are homogeneous1204vector<Integer> degrees = Binomials.MxV(Grading);1205for (size_t i=0; i<degrees.size(); ++i) {1206if (degrees[i]!=0) {1207throw BadInputException("Grading gives non-zero value "1208+ toString(degrees[i]) + " for binomial "1209+ toString(i+1) + "!");1210}1211if (Grading[i] <0) {1212throw BadInputException("Grading gives negative value "1213+ toString(Grading[i]) + " for generator "1214+ toString(i+1) + "!");1215}1216}1217}12181219Matrix<Integer> Gens=Binomials.kernel().transpose();1220Full_Cone<Integer> FC(Gens);1221FC.verbose=verbose;1222if (verbose) verboseOutput() << "Computing a positive embedding..." << endl;12231224FC.dualize_cone();1225Matrix<Integer> Supp_Hyp=FC.getSupportHyperplanes().sort_lex();1226Matrix<Integer> Selected_Supp_Hyp_Trans=(Supp_Hyp.submatrix(Supp_Hyp.max_rank_submatrix_lex())).transpose();1227Matrix<Integer> Positive_Embedded_Generators=Gens.multiplication(Selected_Supp_Hyp_Trans);1228// GeneratorsOfToricRing = Positive_Embedded_Generators;1229// is_Computed.set(ConeProperty::GeneratorsOfToricRing);1230dim = Positive_Embedded_Generators.nr_of_columns();1231multi_input_data.insert(make_pair(Type::normalization,Positive_Embedded_Generators.get_elements())); // this is the cone defined by the binomials12321233if (Grading.size()>0) {1234// solve GeneratorsOfToricRing * grading = old_grading1235Integer dummyDenom;1236// Grading must be set directly since map entry has been processed already1237Grading = Positive_Embedded_Generators.solve_rectangular(Grading,dummyDenom);1238if (Grading.size() != dim) {1239errorOutput() << "Grading could not be transferred!"<<endl;1240is_Computed.set(ConeProperty::Grading, false);1241}1242}1243}12441245/* only used by the constructors */1246template<typename Integer>1247void Cone<Integer>::initialize() {1248BC_set=false;1249is_Computed = bitset<ConeProperty::EnumSize>(); //initialized to false1250dim = 0;1251unit_group_index = 1;1252inhomogeneous=false;1253rees_primary = false;1254triangulation_is_nested = false;1255triangulation_is_partial = false;1256is_approximation=false;1257verbose = libnormaliz::verbose; //take the global default1258if (using_GMP<Integer>()) {1259change_integer_type = true;1260} else {1261change_integer_type = false;1262}1263IntHullCone=NULL;1264SymmCone=NULL;12651266already_in_compute=false;12671268set_parallelization();1269nmz_interrupted=0;1270nmz_scip=false;12711272}12731274template<typename Integer>1275void Cone<Integer>::set_parallelization() {12761277omp_set_nested(0);12781279if(thread_limit<0)1280throw BadInputException("Invalid thread limit");12811282if(parallelization_set){1283if(thread_limit!=0)1284omp_set_num_threads(thread_limit);1285}1286else{1287if(std::getenv("OMP_NUM_THREADS") == NULL){1288long old=omp_get_max_threads();1289if(old>default_thread_limit)1290set_thread_limit(default_thread_limit);1291omp_set_num_threads(thread_limit);1292}1293}1294}12951296//---------------------------------------------------------------------------12971298template<typename Integer>1299void Cone<Integer>::compose_basis_change(const Sublattice_Representation<Integer>& BC) {1300if (BC_set) {1301BasisChange.compose(BC);1302} else {1303BasisChange = BC;1304BC_set = true;1305}1306}1307//---------------------------------------------------------------------------1308template<typename Integer>1309void Cone<Integer>::check_precomputed_support_hyperplanes(){13101311if (isComputed(ConeProperty::Generators)) {1312// check if the inequalities are at least valid1313// if (PreComputedSupportHyperplanes.nr_of_rows() != 0) {1314Integer sp;1315for (size_t i = 0; i < Generators.nr_of_rows(); ++i) {1316for (size_t j = 0; j < PreComputedSupportHyperplanes.nr_of_rows(); ++j) {1317if ((sp = v_scalar_product(Generators[i], PreComputedSupportHyperplanes[j])) < 0) {1318throw BadInputException("Precomputed inequality " + toString(j)1319+ " is not valid for generator " + toString(i)1320+ " (value " + toString(sp) + ")");1321}1322}1323}1324// }1325}1326}13271328//---------------------------------------------------------------------------1329template<typename Integer>1330void Cone<Integer>::check_excluded_faces(){13311332if (isComputed(ConeProperty::Generators)) {1333// check if the inequalities are at least valid1334// if (ExcludedFaces.nr_of_rows() != 0) {1335Integer sp;1336for (size_t i = 0; i < Generators.nr_of_rows(); ++i) {1337for (size_t j = 0; j < ExcludedFaces.nr_of_rows(); ++j) {1338if ((sp = v_scalar_product(Generators[i], ExcludedFaces[j])) < 0) {1339throw BadInputException("Excluded face " + toString(j)1340+ " is not valid for generator " + toString(i)1341+ " (value " + toString(sp) + ")");1342}1343}1344}1345// }1346}1347}134813491350//---------------------------------------------------------------------------13511352template<typename Integer>1353bool Cone<Integer>::setVerbose (bool v) {1354//we want to return the old value1355bool old = verbose;1356verbose = v;1357return old;1358}1359//---------------------------------------------------------------------------13601361template<typename Integer>1362void Cone<Integer>::deactivateChangeOfPrecision() {1363change_integer_type = false;1364}13651366//---------------------------------------------------------------------------13671368template<typename Integer>1369void Cone<Integer>::checkGrading () {13701371if (isComputed(ConeProperty::Grading) || Grading.size()==0) {1372return;1373}13741375bool positively_graded=true;1376bool nonnegative=true;1377size_t neg_index=0;1378Integer neg_value;1379if (Generators.nr_of_rows() > 0) {1380vector<Integer> degrees = Generators.MxV(Grading);1381for (size_t i=0; i<degrees.size(); ++i) {1382if (degrees[i]<=0 && (!inhomogeneous || v_scalar_product(Generators[i],Dehomogenization)==0)) {1383// in the inhomogeneous case: test only generators of tail cone1384positively_graded=false;;1385if(degrees[i]<0){1386nonnegative=false;1387neg_index=i;1388neg_value=degrees[i];1389}1390}1391}1392if(positively_graded){1393vector<Integer> test_grading=BasisChange.to_sublattice_dual_no_div(Grading);1394GradingDenom=v_make_prime(test_grading);1395}1396else1397GradingDenom = 1;1398} else {1399GradingDenom = 1;1400}14011402if (isComputed(ConeProperty::Generators)){1403if(!nonnegative){1404throw BadInputException("Grading gives negative value "1405+ toString(neg_value) + " for generator "1406+ toString(neg_index+1) + "!");1407}1408if(positively_graded){1409is_Computed.set(ConeProperty::Grading);1410is_Computed.set(ConeProperty::GradingDenom);1411}1412}14131414}14151416//---------------------------------------------------------------------------14171418template<typename Integer>1419void Cone<Integer>::checkDehomogenization () {1420if(Dehomogenization.size()>0){1421vector<Integer> test=Generators.MxV(Dehomogenization);1422for(size_t i=0;i<test.size();++i)1423if(test[i]<0){1424throw BadInputException(1425"Dehomogenization has has negative value on generator "1426+ toString(Generators[i]));1427}1428}1429}1430//---------------------------------------------------------------------------14311432template<typename Integer>1433void Cone<Integer>::setGrading (const vector<Integer>& lf) {14341435if (isComputed(ConeProperty::Grading) && Grading == lf) {1436return;1437}14381439if (lf.size() != dim) {1440throw BadInputException("Grading linear form has wrong dimension "1441+ toString(lf.size()) + " (should be " + toString(dim) + ")");1442}14431444Grading = lf;1445checkGrading();1446}14471448//---------------------------------------------------------------------------14491450template<typename Integer>1451void Cone<Integer>::setWeights () {14521453if(WeightsGrad.nr_of_columns()!=dim){1454WeightsGrad=Matrix<Integer> (0,dim); // weight matrix for ordering1455}1456if(Grading.size()>0 && WeightsGrad.nr_of_rows()==0)1457WeightsGrad.append(Grading);1458GradAbs=vector<bool>(WeightsGrad.nr_of_rows(),false);1459}1460//---------------------------------------------------------------------------14611462template<typename Integer>1463void Cone<Integer>::setDehomogenization (const vector<Integer>& lf) {1464if (lf.size() != dim) {1465throw BadInputException("Dehomogenizing linear form has wrong dimension "1466+ toString(lf.size()) + " (should be " + toString(dim) + ")");1467}1468Dehomogenization=lf;1469is_Computed.set(ConeProperty::Dehomogenization);1470}14711472//---------------------------------------------------------------------------14731474/* check what is computed */1475template<typename Integer>1476bool Cone<Integer>::isComputed(ConeProperty::Enum prop) const {1477return is_Computed.test(prop);1478}14791480template<typename Integer>1481bool Cone<Integer>::isComputed(ConeProperties CheckComputed) const {1482return CheckComputed.reset(is_Computed).any();1483}14841485template<typename Integer>1486void Cone<Integer>::resetComputed(ConeProperty::Enum prop){1487is_Computed.reset(prop);1488}148914901491/* getter */14921493template<typename Integer>1494Cone<Integer>& Cone<Integer>::getIntegerHullCone() const {1495return *IntHullCone;1496}14971498template<typename Integer>1499Cone<Integer>& Cone<Integer>::getSymmetrizedCone() const {1500return *SymmCone;1501}15021503template<typename Integer>1504size_t Cone<Integer>::getRank() {1505compute(ConeProperty::Sublattice);1506return BasisChange.getRank();1507}15081509template<typename Integer> // computation depends on OriginalMonoidGenerators1510Integer Cone<Integer>::getIndex() {1511compute(ConeProperty::OriginalMonoidGenerators);1512return index;1513}15141515template<typename Integer> // computation depends on OriginalMonoidGenerators1516Integer Cone<Integer>::getInternalIndex() {1517return getIndex();1518}15191520template<typename Integer>1521Integer Cone<Integer>::getUnitGroupIndex() {1522compute(ConeProperty::OriginalMonoidGenerators,ConeProperty::IsIntegrallyClosed);1523return unit_group_index;1524}15251526template<typename Integer>1527size_t Cone<Integer>::getRecessionRank() {1528compute(ConeProperty::RecessionRank);1529return recession_rank;1530}15311532template<typename Integer>1533long Cone<Integer>::getAffineDim() {1534compute(ConeProperty::AffineDim);1535return affine_dim;1536}15371538template<typename Integer>1539const Sublattice_Representation<Integer>& Cone<Integer>::getSublattice() {1540compute(ConeProperty::Sublattice);1541return BasisChange;1542}15431544template<typename Integer>1545const Matrix<Integer>& Cone<Integer>::getOriginalMonoidGeneratorsMatrix() {1546compute(ConeProperty::OriginalMonoidGenerators);1547return OriginalMonoidGenerators;1548}1549template<typename Integer>1550const vector< vector<Integer> >& Cone<Integer>::getOriginalMonoidGenerators() {1551compute(ConeProperty::OriginalMonoidGenerators);1552return OriginalMonoidGenerators.get_elements();1553}1554template<typename Integer>1555size_t Cone<Integer>::getNrOriginalMonoidGenerators() {1556compute(ConeProperty::OriginalMonoidGenerators);1557return OriginalMonoidGenerators.nr_of_rows();1558}15591560template<typename Integer>1561const vector< vector<Integer> >& Cone<Integer>::getMaximalSubspace() {1562compute(ConeProperty::MaximalSubspace);1563return BasisMaxSubspace.get_elements();1564}1565template<typename Integer>1566const Matrix<Integer>& Cone<Integer>::getMaximalSubspaceMatrix() {1567compute(ConeProperty::MaximalSubspace);1568return BasisMaxSubspace;1569}1570template<typename Integer>1571size_t Cone<Integer>::getDimMaximalSubspace() {1572compute(ConeProperty::MaximalSubspace);1573return BasisMaxSubspace.nr_of_rows();1574}15751576template<typename Integer>1577const Matrix<Integer>& Cone<Integer>::getGeneratorsMatrix() {1578compute(ConeProperty::Generators);1579return Generators;1580}15811582template<typename Integer>1583const vector< vector<Integer> >& Cone<Integer>::getGenerators() {1584compute(ConeProperty::Generators);1585return Generators.get_elements();1586}15871588template<typename Integer>1589size_t Cone<Integer>::getNrGenerators() {1590compute(ConeProperty::Generators);1591return Generators.nr_of_rows();1592}15931594template<typename Integer>1595const Matrix<Integer>& Cone<Integer>::getExtremeRaysMatrix() {1596compute(ConeProperty::ExtremeRays);1597return ExtremeRays;1598}1599template<typename Integer>1600const vector< vector<Integer> >& Cone<Integer>::getExtremeRays() {1601compute(ConeProperty::ExtremeRays);1602return ExtremeRays.get_elements();1603}1604template<typename Integer>1605size_t Cone<Integer>::getNrExtremeRays() {1606compute(ConeProperty::ExtremeRays);1607return ExtremeRays.nr_of_rows();1608}16091610template<typename Integer>1611const Matrix<nmz_float>& Cone<Integer>::getVerticesFloatMatrix() {1612compute(ConeProperty::VerticesFloat);1613return VerticesFloat;1614}1615template<typename Integer>1616const vector< vector<nmz_float> >& Cone<Integer>::getVerticesFloat() {1617compute(ConeProperty::VerticesFloat);1618return VerticesFloat.get_elements();1619}1620template<typename Integer>1621size_t Cone<Integer>::getNrVerticesFloat() {1622compute(ConeProperty::VerticesFloat);1623return VerticesFloat.nr_of_rows();1624}16251626template<typename Integer>1627const Matrix<Integer>& Cone<Integer>::getVerticesOfPolyhedronMatrix() {1628compute(ConeProperty::VerticesOfPolyhedron);1629return VerticesOfPolyhedron;1630}1631template<typename Integer>1632const vector< vector<Integer> >& Cone<Integer>::getVerticesOfPolyhedron() {1633compute(ConeProperty::VerticesOfPolyhedron);1634return VerticesOfPolyhedron.get_elements();1635}1636template<typename Integer>1637size_t Cone<Integer>::getNrVerticesOfPolyhedron() {1638compute(ConeProperty::VerticesOfPolyhedron);1639return VerticesOfPolyhedron.nr_of_rows();1640}16411642template<typename Integer>1643const Matrix<Integer>& Cone<Integer>::getSupportHyperplanesMatrix() {1644compute(ConeProperty::SupportHyperplanes);1645return SupportHyperplanes;1646}1647template<typename Integer>1648const vector< vector<Integer> >& Cone<Integer>::getSupportHyperplanes() {1649compute(ConeProperty::SupportHyperplanes);1650return SupportHyperplanes.get_elements();1651}1652template<typename Integer>1653size_t Cone<Integer>::getNrSupportHyperplanes() {1654compute(ConeProperty::SupportHyperplanes);1655return SupportHyperplanes.nr_of_rows();1656}16571658template<typename Integer>1659map< InputType , vector< vector<Integer> > > Cone<Integer>::getConstraints () {1660compute(ConeProperty::Sublattice, ConeProperty::SupportHyperplanes);1661map<InputType, vector< vector<Integer> > > c;1662c[Type::inequalities] = SupportHyperplanes.get_elements();1663c[Type::equations] = BasisChange.getEquations();1664c[Type::congruences] = BasisChange.getCongruences();1665return c;1666}16671668template<typename Integer>1669const Matrix<Integer>& Cone<Integer>::getExcludedFacesMatrix() {1670compute(ConeProperty::ExcludedFaces);1671return ExcludedFaces;1672}1673template<typename Integer>1674const vector< vector<Integer> >& Cone<Integer>::getExcludedFaces() {1675compute(ConeProperty::ExcludedFaces);1676return ExcludedFaces.get_elements();1677}1678template<typename Integer>1679size_t Cone<Integer>::getNrExcludedFaces() {1680compute(ConeProperty::ExcludedFaces);1681return ExcludedFaces.nr_of_rows();1682}16831684template<typename Integer>1685const vector< pair<vector<key_t>,Integer> >& Cone<Integer>::getTriangulation() {1686compute(ConeProperty::Triangulation);1687return Triangulation;1688}16891690template<typename Integer>1691const vector<vector<bool> >& Cone<Integer>::getOpenFacets() {1692compute(ConeProperty::ConeDecomposition);1693return OpenFacets;1694}16951696template<typename Integer>1697const vector< pair<vector<key_t>,long> >& Cone<Integer>::getInclusionExclusionData() {1698compute(ConeProperty::InclusionExclusionData);1699return InExData;1700}17011702template<typename Integer>1703void Cone<Integer>::make_StanleyDec_export() {1704if(!StanleyDec_export.empty())1705return;1706assert(isComputed(ConeProperty::StanleyDec));1707auto SD=StanleyDec.begin();1708for(;SD!=StanleyDec.end();++SD){1709STANLEYDATA<Integer> NewSt;1710NewSt.key=SD->key;1711convert(NewSt.offsets,SD->offsets);1712StanleyDec_export.push_back(NewSt);1713}1714}17151716template<typename Integer>1717const list< STANLEYDATA<Integer> >& Cone<Integer>::getStanleyDec() {1718compute(ConeProperty::StanleyDec);1719make_StanleyDec_export();1720return StanleyDec_export;1721}17221723template<typename Integer>1724list< STANLEYDATA_int >& Cone<Integer>::getStanleyDec_mutable() {1725assert(isComputed(ConeProperty::StanleyDec));1726return StanleyDec;1727}17281729template<typename Integer>1730size_t Cone<Integer>::getTriangulationSize() {1731compute(ConeProperty::TriangulationSize);1732return TriangulationSize;1733}17341735template<typename Integer>1736Integer Cone<Integer>::getTriangulationDetSum() {1737compute(ConeProperty::TriangulationDetSum);1738return TriangulationDetSum;1739}17401741template<typename Integer>1742vector<Integer> Cone<Integer>::getWitnessNotIntegrallyClosed() {1743compute(ConeProperty::WitnessNotIntegrallyClosed);1744return WitnessNotIntegrallyClosed;1745}17461747template<typename Integer>1748vector<Integer> Cone<Integer>::getGeneratorOfInterior() {1749compute(ConeProperty::GeneratorOfInterior);1750return GeneratorOfInterior;1751}17521753template<typename Integer>1754const Matrix<Integer>& Cone<Integer>::getHilbertBasisMatrix() {1755compute(ConeProperty::HilbertBasis);1756return HilbertBasis;1757}1758template<typename Integer>1759const vector< vector<Integer> >& Cone<Integer>::getHilbertBasis() {1760compute(ConeProperty::HilbertBasis);1761return HilbertBasis.get_elements();1762}1763template<typename Integer>1764size_t Cone<Integer>::getNrHilbertBasis() {1765compute(ConeProperty::HilbertBasis);1766return HilbertBasis.nr_of_rows();1767}17681769template<typename Integer>1770const Matrix<Integer>& Cone<Integer>::getModuleGeneratorsOverOriginalMonoidMatrix() {1771compute(ConeProperty::ModuleGeneratorsOverOriginalMonoid);1772return ModuleGeneratorsOverOriginalMonoid;1773}1774template<typename Integer>1775const vector< vector<Integer> >& Cone<Integer>::getModuleGeneratorsOverOriginalMonoid() {1776compute(ConeProperty::ModuleGeneratorsOverOriginalMonoid);1777return ModuleGeneratorsOverOriginalMonoid.get_elements();1778}1779template<typename Integer>1780size_t Cone<Integer>::getNrModuleGeneratorsOverOriginalMonoid() {1781compute(ConeProperty::ModuleGeneratorsOverOriginalMonoid);1782return ModuleGeneratorsOverOriginalMonoid.nr_of_rows();1783}17841785template<typename Integer>1786const Matrix<Integer>& Cone<Integer>::getModuleGeneratorsMatrix() {1787compute(ConeProperty::ModuleGenerators);1788return ModuleGenerators;1789}1790template<typename Integer>1791const vector< vector<Integer> >& Cone<Integer>::getModuleGenerators() {1792compute(ConeProperty::ModuleGenerators);1793return ModuleGenerators.get_elements();1794}1795template<typename Integer>1796size_t Cone<Integer>::getNrModuleGenerators() {1797compute(ConeProperty::ModuleGenerators);1798return ModuleGenerators.nr_of_rows();1799}18001801template<typename Integer>1802const Matrix<Integer>& Cone<Integer>::getDeg1ElementsMatrix() {1803compute(ConeProperty::Deg1Elements);1804return Deg1Elements;1805}1806template<typename Integer>1807const vector< vector<Integer> >& Cone<Integer>::getDeg1Elements() {1808compute(ConeProperty::Deg1Elements);1809return Deg1Elements.get_elements();1810}1811template<typename Integer>1812size_t Cone<Integer>::getNrDeg1Elements() {1813compute(ConeProperty::Deg1Elements);1814return Deg1Elements.nr_of_rows();1815}18161817template<typename Integer>1818const HilbertSeries& Cone<Integer>::getHilbertSeries() {1819compute(ConeProperty::HilbertSeries);1820return HSeries;1821}18221823template<typename Integer>1824vector<Integer> Cone<Integer>::getGrading() {1825compute(ConeProperty::Grading);1826return Grading;1827}18281829template<typename Integer>1830Integer Cone<Integer>::getGradingDenom() {1831compute(ConeProperty::Grading);1832return GradingDenom;1833}18341835template<typename Integer>1836vector<Integer> Cone<Integer>::getDehomogenization() {1837compute(ConeProperty::Dehomogenization);1838return Dehomogenization;1839}18401841template<typename Integer>1842mpq_class Cone<Integer>::getMultiplicity() {1843compute(ConeProperty::Multiplicity);1844return multiplicity;1845}18461847template<typename Integer>1848mpq_class Cone<Integer>::getVirtualMultiplicity() {1849if(!isComputed(ConeProperty::VirtualMultiplicity)) // in order not to compute the triangulation1850compute(ConeProperty::VirtualMultiplicity); // which is deleted if not asked for explicitly1851return IntData.getVirtualMultiplicity();1852}18531854template<typename Integer>1855const pair<HilbertSeries, mpz_class>& Cone<Integer>::getWeightedEhrhartSeries(){1856if(!isComputed(ConeProperty::WeightedEhrhartSeries)) // see above1857compute(ConeProperty::WeightedEhrhartSeries);1858return getIntData().getWeightedEhrhartSeries();1859}18601861template<typename Integer>1862IntegrationData& Cone<Integer>::getIntData(){1863return IntData;1864}18651866template<typename Integer>1867mpq_class Cone<Integer>::getIntegral() {1868if(!isComputed(ConeProperty::Integral)) // see above1869compute(ConeProperty::Integral);1870return IntData.getIntegral();1871}18721873template<typename Integer>1874bool Cone<Integer>::isPointed() {1875compute(ConeProperty::IsPointed);1876return pointed;1877}18781879template<typename Integer>1880bool Cone<Integer>::isInhomogeneous() {1881return inhomogeneous;1882}18831884template<typename Integer>1885bool Cone<Integer>::isDeg1ExtremeRays() {1886compute(ConeProperty::IsDeg1ExtremeRays);1887return deg1_extreme_rays;1888}18891890template<typename Integer>1891bool Cone<Integer>::isGorenstein() {1892compute(ConeProperty::IsGorenstein);1893return Gorenstein;1894}18951896template<typename Integer>1897bool Cone<Integer>::isDeg1HilbertBasis() {1898compute(ConeProperty::IsDeg1HilbertBasis);1899return deg1_hilbert_basis;1900}19011902template<typename Integer>1903bool Cone<Integer>::isIntegrallyClosed() {1904compute(ConeProperty::IsIntegrallyClosed);1905return integrally_closed;1906}19071908template<typename Integer>1909bool Cone<Integer>::isReesPrimary() {1910compute(ConeProperty::IsReesPrimary);1911return rees_primary;1912}19131914template<typename Integer>1915Integer Cone<Integer>::getReesPrimaryMultiplicity() {1916compute(ConeProperty::ReesPrimaryMultiplicity);1917return ReesPrimaryMultiplicity;1918}19191920// the information about the triangulation will just be returned1921// if no triangulation was computed so far they return false1922template<typename Integer>1923bool Cone<Integer>::isTriangulationNested() {1924return triangulation_is_nested;1925}1926template<typename Integer>1927bool Cone<Integer>::isTriangulationPartial() {1928return triangulation_is_partial;1929}19301931template<typename Integer>1932size_t Cone<Integer>::getModuleRank() {1933compute(ConeProperty::ModuleRank);1934return module_rank;1935}19361937template<typename Integer>1938vector<Integer> Cone<Integer>::getClassGroup() {1939compute(ConeProperty::ClassGroup);1940return ClassGroup;1941}19421943//---------------------------------------------------------------------------19441945template<typename Integer>1946ConeProperties Cone<Integer>::compute(ConeProperty::Enum cp) {1947if (isComputed(cp)) return ConeProperties();1948return compute(ConeProperties(cp));1949}19501951template<typename Integer>1952ConeProperties Cone<Integer>::compute(ConeProperty::Enum cp1, ConeProperty::Enum cp2) {1953return compute(ConeProperties(cp1,cp2));1954}19551956template<typename Integer>1957ConeProperties Cone<Integer>::compute(ConeProperty::Enum cp1, ConeProperty::Enum cp2,1958ConeProperty::Enum cp3) {1959return compute(ConeProperties(cp1,cp2,cp3));1960}19611962//---------------------------------------------------------------------------19631964template<typename Integer>1965void Cone<Integer>::set_implicit_dual_mode(ConeProperties& ToCompute) {19661967if(ToCompute.test(ConeProperty::DualMode) || ToCompute.test(ConeProperty::PrimalMode)1968|| ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid)1969|| ToCompute.test(ConeProperty::Approximate)1970|| ToCompute.test(ConeProperty::Projection)1971|| nr_cone_gen>0 || nr_latt_gen>0 || SupportHyperplanes.nr_of_rows() > 2*dim1972|| SupportHyperplanes.nr_of_rows()1973<= BasisChangePointed.getRank()+ 50/(BasisChangePointed.getRank()+1))1974return;1975if(ToCompute.test(ConeProperty::HilbertBasis))1976ToCompute.set(ConeProperty::DualMode);1977if(ToCompute.test(ConeProperty::Deg1Elements)1978&& !(ToCompute.test(ConeProperty::HilbertSeries) || ToCompute.test(ConeProperty::Multiplicity)))1979ToCompute.set(ConeProperty::DualMode);1980return;1981}19821983//---------------------------------------------------------------------------19841985// this wrapper allows us to save and restore class data that depend on ToCompute1986// and may therefore be destroyed if compute() is called by itself1987template<typename Integer>1988ConeProperties Cone<Integer>::recursive_compute(ConeProperties ToCompute) {19891990bool save_explicit_HilbertSeries=explicit_HilbertSeries;1991bool save_naked_dual= naked_dual;1992bool save_default_mode= default_mode;1993already_in_compute=false;1994ToCompute=compute_inner(ToCompute);1995explicit_HilbertSeries=save_explicit_HilbertSeries;1996naked_dual=save_naked_dual;1997default_mode= save_default_mode;1998return ToCompute;1999}20002001//---------------------------------------------------------------------------20022003template<typename Integer>2004ConeProperties Cone<Integer>::compute(ConeProperties ToCompute) {2005already_in_compute=false;2006set_parallelization();2007nmz_interrupted=0;2008if(ToCompute.test(ConeProperty::SCIP)){2009#ifdef NMZ_SCIP2010nmz_scip=true;2011ToCompute.set(ConeProperty::SCIP);2012#else2013throw BadInputException("Option SCIP only allowed if Normaliz was built with Scip");2014#endif // NMZ_SCIP2015}2016return compute_inner(ToCompute);2017}20182019//---------------------------------------------------------------------------20202021template<typename Integer>2022ConeProperties Cone<Integer>::compute_inner(ConeProperties ToCompute) {20232024assert(!already_in_compute);2025already_in_compute=true;20262027if(ToCompute.test(ConeProperty::NoPeriodBound)){2028HSeries.set_period_bounded(false);2029IntData.getWeightedEhrhartSeries().first.set_period_bounded(false);2030}203120322033#ifndef NMZ_COCOA2034if(ToCompute.test(ConeProperty::VirtualMultiplicity) || ToCompute.test(ConeProperty::Integral)2035|| ToCompute.test(ConeProperty::WeightedEhrhartSeries))2036throw BadInputException("Integral, VirtualMultiplicity, WeightedEhrhartSeries only computable with CoCoALib");2037#endif20382039default_mode=ToCompute.test(ConeProperty::DefaultMode);20402041if(ToCompute.test(ConeProperty::BigInt)){2042if(!using_GMP<Integer>())2043throw BadInputException("BigInt can only be set for cones of Integer type GMP");2044change_integer_type=false;2045}20462047if(ToCompute.test(ConeProperty::KeepOrder) && !isComputed(ConeProperty::OriginalMonoidGenerators))2048throw BadInputException("KeepOrder can only be set if OriginalMonoidGenerators are defined");20492050INTERRUPT_COMPUTATION_BY_EXCEPTION20512052if(BasisMaxSubspace.nr_of_rows()>0 && !isComputed(ConeProperty::MaximalSubspace)){2053BasisMaxSubspace=Matrix<Integer>(0,dim);2054recursive_compute(ConeProperty::MaximalSubspace);2055}20562057explicit_HilbertSeries=ToCompute.test(ConeProperty::HilbertSeries) || ToCompute.test(ConeProperty::HSOP);2058// must distiguish it from being set through DefaultMode;2059naked_dual=ToCompute.test(ConeProperty::DualMode)2060&& !(ToCompute.test(ConeProperty::HilbertBasis) || ToCompute.test(ConeProperty::Deg1Elements));2061// to control the computation of rational solutions in the inhomogeneous case20622063ToCompute.reset(is_Computed);2064ToCompute.check_conflicting_variants();2065ToCompute.set_preconditions(inhomogeneous);2066ToCompute.prepare_compute_options(inhomogeneous);2067ToCompute.check_sanity(inhomogeneous);2068if (!isComputed(ConeProperty::OriginalMonoidGenerators)) {2069if (ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid)) {2070errorOutput() << "ERROR: Module generators over original monoid only computable if original monoid is defined!"2071<< endl;2072throw NotComputableException(ConeProperty::ModuleGeneratorsOverOriginalMonoid);2073}2074if (ToCompute.test(ConeProperty::IsIntegrallyClosed)) {2075errorOutput() << "ERROR: Original monoid is not defined, cannot check it for being integrally closed."2076<< endl;2077throw NotComputableException(ConeProperty::IsIntegrallyClosed);2078}2079}20802081try_symmetrization(ToCompute);2082ToCompute.reset(is_Computed);2083if (ToCompute.none()) {2084already_in_compute=false; return ToCompute;2085}20862087INTERRUPT_COMPUTATION_BY_EXCEPTION208820892090set_implicit_dual_mode(ToCompute);20912092if (ToCompute.test(ConeProperty::DualMode)) {2093compute_dual(ToCompute);2094}20952096if (ToCompute.test(ConeProperty::WitnessNotIntegrallyClosed)) {2097find_witness();2098}20992100ToCompute.reset(is_Computed);2101if (ToCompute.none()) {2102already_in_compute=false; return ToCompute;2103}21042105INTERRUPT_COMPUTATION_BY_EXCEPTION21062107try_approximation_or_projection(ToCompute);21082109ToCompute.reset(is_Computed); // already computed2110if (ToCompute.none()) {2111already_in_compute=false; return ToCompute;2112}21132114/* preparation: get generators if necessary */2115compute_generators();21162117if (!isComputed(ConeProperty::Generators)) {2118throw FatalException("Could not get Generators.");2119}21202121if (rees_primary && (ToCompute.test(ConeProperty::ReesPrimaryMultiplicity)2122|| ToCompute.test(ConeProperty::Multiplicity)2123|| ToCompute.test(ConeProperty::HilbertSeries)2124|| ToCompute.test(ConeProperty::DefaultMode) ) ) {2125ReesPrimaryMultiplicity = compute_primary_multiplicity();2126is_Computed.set(ConeProperty::ReesPrimaryMultiplicity);2127}21282129ToCompute.reset(is_Computed); // already computed2130if (ToCompute.none()) {2131already_in_compute=false; return ToCompute;2132}21332134// the computation of the full cone2135if (change_integer_type) {2136try {2137compute_full_cone<MachineInteger>(ToCompute);2138} catch(const ArithmeticException& e) {2139if (verbose) {2140verboseOutput() << e.what() << endl;2141verboseOutput() << "Restarting with a bigger type." << endl;2142}2143change_integer_type = false;2144}2145}21462147if (!change_integer_type) {2148compute_full_cone<Integer>(ToCompute);2149}21502151check_Gorenstein(ToCompute);21522153if(ToCompute.test(ConeProperty::IntegerHull)) {2154compute_integer_hull();2155}21562157INTERRUPT_COMPUTATION_BY_EXCEPTION21582159complete_HilbertSeries_comp(ToCompute);21602161complete_sublattice_comp(ToCompute);21622163compute_vertices_float(ToCompute);21642165if(ToCompute.test(ConeProperty::WeightedEhrhartSeries))2166compute_weighted_Ehrhart(ToCompute);2167ToCompute.reset(is_Computed);21682169if(ToCompute.test(ConeProperty::Integral))2170compute_integral(ToCompute);2171ToCompute.reset(is_Computed);21722173if(ToCompute.test(ConeProperty::VirtualMultiplicity))2174compute_virt_mult(ToCompute);2175ToCompute.reset(is_Computed);21762177/* check if everything is computed */2178ToCompute.reset(is_Computed); //remove what is now computed2179if (ToCompute.test(ConeProperty::Deg1Elements) && isComputed(ConeProperty::Grading)) {2180// this can happen when we were looking for a witness earlier2181recursive_compute(ToCompute);2182}2183if (!ToCompute.test(ConeProperty::DefaultMode) && ToCompute.goals().any()) {2184throw NotComputableException(ToCompute.goals());2185}2186ToCompute.reset_compute_options();2187already_in_compute=false; return ToCompute;2188}21892190template<typename Integer>2191void Cone<Integer>::compute_integer_hull() {21922193if(verbose){2194verboseOutput() << "Computing integer hull" << endl;2195}21962197Matrix<Integer> IntHullGen;2198bool IntHullComputable=true;2199size_t nr_extr=0;2200if(inhomogeneous){2201if(!isComputed(ConeProperty::HilbertBasis))2202IntHullComputable=false;2203IntHullGen=HilbertBasis;2204IntHullGen.append(ModuleGenerators);2205}2206else{2207if(!isComputed(ConeProperty::Deg1Elements))2208IntHullComputable=false;2209IntHullGen=Deg1Elements;2210}2211ConeProperties IntHullCompute;2212IntHullCompute.set(ConeProperty::SupportHyperplanes);2213if(!IntHullComputable){2214errorOutput() << "Integer hull not computable: no integer points available." << endl;2215throw NotComputableException(IntHullCompute);2216}22172218if(IntHullGen.nr_of_rows()==0){2219IntHullGen.append(vector<Integer>(dim,0)); // we need a non-empty input matrix2220}22212222INTERRUPT_COMPUTATION_BY_EXCEPTION22232224if(!inhomogeneous || HilbertBasis.nr_of_rows()==0){2225nr_extr=IntHullGen.extreme_points_first();2226if(verbose){2227verboseOutput() << nr_extr << " extreme points found" << endl;2228}2229}2230else{ // now an unbounded polyhedron2231if(isComputed(ConeProperty::Grading)){2232nr_extr=IntHullGen.extreme_points_first(Grading);2233}2234else{2235if(isComputed(ConeProperty::SupportHyperplanes)){2236vector<Integer> aux_grading=SupportHyperplanes.find_inner_point();2237nr_extr=IntHullGen.extreme_points_first(aux_grading);2238}2239}2240}22412242// IntHullGen.pretty_print(cout);2243IntHullCone=new Cone<Integer>(InputType::cone_and_lattice,IntHullGen.get_elements(), Type::subspace,BasisMaxSubspace);2244if(nr_extr!=0) // we suppress the ordering in full_cone only if we have found few extreme rays2245IntHullCompute.set(ConeProperty::KeepOrder);22462247IntHullCone->inhomogeneous=true; // inhomogeneous;2248if(inhomogeneous)2249IntHullCone->Dehomogenization=Dehomogenization;2250else2251IntHullCone->Dehomogenization=Grading;2252IntHullCone->verbose=verbose;2253try{2254IntHullCone->compute(IntHullCompute);2255if(IntHullCone->isComputed(ConeProperty::SupportHyperplanes))2256is_Computed.set(ConeProperty::IntegerHull);2257if(verbose){2258verboseOutput() << "Integer hull finished" << endl;2259}2260}2261catch (const NotComputableException& ){2262errorOutput() << "Error in computation of integer hull" << endl;2263}2264}22652266template<typename Integer>2267void Cone<Integer>::check_vanishing_of_grading_and_dehom(){2268if(Grading.size()>0){2269vector<Integer> test=BasisMaxSubspace.MxV(Grading);2270if(test!=vector<Integer>(test.size())){2271throw BadInputException("Grading does not vanish on maximal subspace.");2272}2273}2274if(Dehomogenization.size()>0){2275vector<Integer> test=BasisMaxSubspace.MxV(Dehomogenization);2276if(test!=vector<Integer>(test.size())){2277throw BadInputException("Dehomogenization does not vanish on maximal subspace.");2278}2279}2280}22812282template<typename Integer>2283template<typename IntegerFC>2284void Cone<Integer>::compute_full_cone(ConeProperties& ToCompute) {22852286if(ToCompute.test(ConeProperty::IsPointed) && Grading.size()==0){2287if (verbose) {2288verboseOutput()<< "Checking pointedness first"<< endl;2289}2290ConeProperties Dualize;2291Dualize.set(ConeProperty::SupportHyperplanes);2292Dualize.set(ConeProperty::ExtremeRays);2293recursive_compute(Dualize);2294}22952296Matrix<IntegerFC> FC_Gens;22972298BasisChangePointed.convert_to_sublattice(FC_Gens, Generators);2299Full_Cone<IntegerFC> FC(FC_Gens,!ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid));2300// !ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid) blocks make_prime in full_cone.cpp23012302/* activate bools in FC */23032304FC.verbose=verbose;23052306FC.inhomogeneous=inhomogeneous;2307FC.explicit_h_vector=explicit_HilbertSeries;23082309if (ToCompute.test(ConeProperty::HilbertSeries)) {2310FC.do_h_vector = true;2311}2312if (ToCompute.test(ConeProperty::HilbertBasis)) {2313FC.do_Hilbert_basis = true;2314}2315if (ToCompute.test(ConeProperty::IsIntegrallyClosed)) {2316FC.do_integrally_closed = true;2317}2318if (ToCompute.test(ConeProperty::Triangulation)) {2319FC.keep_triangulation = true;2320}2321if (ToCompute.test(ConeProperty::ConeDecomposition)) {2322FC.do_cone_dec = true;2323}2324if (ToCompute.test(ConeProperty::Multiplicity) ) {2325FC.do_multiplicity = true;2326}2327if (ToCompute.test(ConeProperty::TriangulationDetSum) ) {2328FC.do_determinants = true;2329}2330if (ToCompute.test(ConeProperty::TriangulationSize)) {2331FC.do_triangulation = true;2332}2333if (ToCompute.test(ConeProperty::NoSubdivision)) {2334FC.use_bottom_points = false;2335}2336if (ToCompute.test(ConeProperty::Deg1Elements)) {2337FC.do_deg1_elements = true;2338}2339if (ToCompute.test(ConeProperty::StanleyDec)) {2340FC.do_Stanley_dec = true;2341}2342if (ToCompute.test(ConeProperty::Approximate)2343&& ToCompute.test(ConeProperty::Deg1Elements)) {2344FC.do_approximation = true;2345FC.do_deg1_elements = true;2346}2347if (ToCompute.test(ConeProperty::DefaultMode)) {2348FC.do_default_mode = true;2349}2350if (ToCompute.test(ConeProperty::BottomDecomposition)) {2351FC.do_bottom_dec = true;2352}2353if (ToCompute.test(ConeProperty::NoBottomDec)) {2354FC.suppress_bottom_dec = true;2355}2356if (ToCompute.test(ConeProperty::KeepOrder)) {2357FC.keep_order = true;2358}2359if (ToCompute.test(ConeProperty::ClassGroup)) {2360FC.do_class_group=true;2361}2362if (ToCompute.test(ConeProperty::ModuleRank)) {2363FC.do_module_rank=true;2364}23652366if (ToCompute.test(ConeProperty::HSOP)) {2367FC.do_hsop=true;2368}23692370/* Give extra data to FC */2371if ( isComputed(ConeProperty::ExtremeRays) ) {2372FC.Extreme_Rays_Ind = ExtremeRaysIndicator;2373FC.is_Computed.set(ConeProperty::ExtremeRays);2374}23752376/* if(isComputed(ConeProperty::Deg1Elements)){2377Matrix<IntegerFC> Deg1Converted;2378BasisChangePointed.convert_to_sublattice(Deg1Converted, Deg1Elements);2379for(size_t i=0;i<Deg1Elements.nr_of_rows();++i)2380FC.Deg1_Elements.push_back(Deg1Converted[i]);2381FC.is_Computed.set(ConeProperty::Deg1Elements);2382}23832384if(isComputed(ConeProperty::HilbertBasis)){2385Matrix<IntegerFC> HBConverted;2386BasisChangePointed.convert_to_sublattice(HBConverted, HilbertBasis);2387for(size_t i=0;i<HilbertBasis.nr_of_rows();++i)2388FC.Deg1_Elements.push_back(HBConverted[i]);2389FC.is_Computed.set(ConeProperty::HilbertBasis);2390}*/23912392if (ExcludedFaces.nr_of_rows()!=0) {2393BasisChangePointed.convert_to_sublattice_dual(FC.ExcludedFaces, ExcludedFaces);2394}2395if (isComputed(ConeProperty::ExcludedFaces)) {2396FC.is_Computed.set(ConeProperty::ExcludedFaces);2397}23982399if (inhomogeneous){2400BasisChangePointed.convert_to_sublattice_dual_no_div(FC.Truncation, Dehomogenization);2401}2402if ( Grading.size()>0 ) { // IMPORTANT: Truncation must be set before Grading2403BasisChangePointed.convert_to_sublattice_dual(FC.Grading, Grading);2404if(isComputed(ConeProperty::Grading) ){ // is grading positive?2405FC.is_Computed.set(ConeProperty::Grading);2406/*if (inhomogeneous)2407FC.find_grading_inhom();2408FC.set_degrees();*/2409}2410}24112412if (SupportHyperplanes.nr_of_rows()!=0) {2413BasisChangePointed.convert_to_sublattice_dual(FC.Support_Hyperplanes, SupportHyperplanes);2414}2415if (isComputed(ConeProperty::SupportHyperplanes)){2416FC.is_Computed.set(ConeProperty::SupportHyperplanes);2417FC.do_all_hyperplanes = false;2418}24192420if(ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid)){2421FC.do_module_gens_intcl=true;2422}24232424if(is_approximation)2425give_data_of_approximated_cone_to(FC);24262427/* do the computation */24282429try {2430try {2431FC.compute();2432} catch (const NotIntegrallyClosedException& ) {2433}2434is_Computed.set(ConeProperty::Sublattice);2435// make sure we minimize the excluded faces if requested2436if(ToCompute.test(ConeProperty::ExcludedFaces) || ToCompute.test(ConeProperty::SupportHyperplanes)) {2437FC.prepare_inclusion_exclusion();2438}2439extract_data(FC);2440if(isComputed(ConeProperty::IsPointed) && pointed)2441is_Computed.set(ConeProperty::MaximalSubspace);2442} catch(const NonpointedException& ) {2443is_Computed.set(ConeProperty::Sublattice);2444extract_data(FC);2445if(verbose){2446verboseOutput() << "Cone not pointed. Restarting computation." << endl;2447}2448FC=Full_Cone<IntegerFC>(Matrix<IntegerFC>(1)); // to kill the old FC (almost)2449Matrix<Integer> Dual_Gen;2450Dual_Gen=BasisChangePointed.to_sublattice_dual(SupportHyperplanes);2451Sublattice_Representation<Integer> Pointed(Dual_Gen,true); // sublattice of the dual lattice2452BasisMaxSubspace = BasisChangePointed.from_sublattice(Pointed.getEquationsMatrix());2453check_vanishing_of_grading_and_dehom();2454BasisChangePointed.compose_dual(Pointed);2455is_Computed.set(ConeProperty::MaximalSubspace);2456// now we get the basis of the maximal subspace2457pointed = (BasisMaxSubspace.nr_of_rows() == 0);2458is_Computed.set(ConeProperty::IsPointed);2459compute_full_cone<IntegerFC>(ToCompute);2460}2461}246224632464template<typename Integer>2465void Cone<Integer>::compute_generators() {2466//create Generators from SupportHyperplanes2467if (!isComputed(ConeProperty::Generators) && (SupportHyperplanes.nr_of_rows()!=0 ||inhomogeneous)) {2468if (verbose) {2469verboseOutput() << "Computing extreme rays as support hyperplanes of the dual cone:" << endl;2470}2471if (change_integer_type) {2472try {2473compute_generators_inner<MachineInteger>();2474} catch(const ArithmeticException& e) {2475if (verbose) {2476verboseOutput() << e.what() << endl;2477verboseOutput() << "Restarting with a bigger type." << endl;2478}2479compute_generators_inner<Integer>();2480}2481} else {2482compute_generators_inner<Integer>();2483}2484}2485assert(isComputed(ConeProperty::Generators));2486}24872488template<typename Integer>2489template<typename IntegerFC>2490void Cone<Integer>::compute_generators_inner() {24912492Matrix<Integer> Dual_Gen;2493Dual_Gen=BasisChangePointed.to_sublattice_dual(SupportHyperplanes);2494// first we take the quotient of the efficient sublattice modulo the maximal subspace2495Sublattice_Representation<Integer> Pointed(Dual_Gen,true); // sublattice of the dual space24962497// now we get the basis of the maximal subspace2498if(!isComputed(ConeProperty::MaximalSubspace)){2499BasisMaxSubspace = BasisChangePointed.from_sublattice(Pointed.getEquationsMatrix());2500check_vanishing_of_grading_and_dehom();2501is_Computed.set(ConeProperty::MaximalSubspace);2502}2503if(!isComputed(ConeProperty::IsPointed)){2504pointed = (BasisMaxSubspace.nr_of_rows() == 0);2505is_Computed.set(ConeProperty::IsPointed);2506}2507BasisChangePointed.compose_dual(Pointed); // primal cone now pointed, may not yet be full dimensional25082509// restrict the supphyps to efficient sublattice and push to quotient mod subspace2510Matrix<IntegerFC> Dual_Gen_Pointed;2511BasisChangePointed.convert_to_sublattice_dual(Dual_Gen_Pointed, SupportHyperplanes);2512Full_Cone<IntegerFC> Dual_Cone(Dual_Gen_Pointed);2513Dual_Cone.verbose=verbose;2514Dual_Cone.do_extreme_rays=true; // we try to find them, need not exist2515try {2516Dual_Cone.dualize_cone();2517} catch(const NonpointedException& ){}; // we don't mind if the dual cone is not pointed25182519if (Dual_Cone.isComputed(ConeProperty::SupportHyperplanes)) {2520//get the extreme rays of the primal cone2521BasisChangePointed.convert_from_sublattice(Generators,2522Dual_Cone.getSupportHyperplanes());2523is_Computed.set(ConeProperty::Generators);25242525//get minmal set of support_hyperplanes if possible2526if (Dual_Cone.isComputed(ConeProperty::ExtremeRays)) {2527Matrix<IntegerFC> Supp_Hyp = Dual_Cone.getGenerators().submatrix(Dual_Cone.getExtremeRays());2528BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, Supp_Hyp);2529SupportHyperplanes.sort_lex();2530is_Computed.set(ConeProperty::SupportHyperplanes);2531}25322533// now the final transformations2534// only necessary if the basis changes computed so far do not make the cone full-dimensional2535// this is equaivalent to the dual cone bot being pointed2536if(!(Dual_Cone.isComputed(ConeProperty::IsPointed) && Dual_Cone.isPointed())){2537// first to full-dimensional pointed2538Matrix<Integer> Help;2539Help=BasisChangePointed.to_sublattice(Generators); // sublattice of the primal space2540Sublattice_Representation<Integer> PointedHelp(Help,true);2541BasisChangePointed.compose(PointedHelp);2542// second to efficient sublattice2543if(BasisMaxSubspace.nr_of_rows()==0){ // primal cone is pointed and we can copy2544BasisChange=BasisChangePointed;2545}2546else{2547Help=BasisChange.to_sublattice(Generators);2548Help.append(BasisChange.to_sublattice(BasisMaxSubspace));2549Sublattice_Representation<Integer> EmbHelp(Help,true); // sublattice of the primal space2550compose_basis_change(EmbHelp);2551}2552}2553is_Computed.set(ConeProperty::Sublattice); // will not be changed anymore25542555checkGrading();2556// compute grading, so that it is also known if nothing else is done afterwards2557if (!isComputed(ConeProperty::Grading) && !inhomogeneous) {2558// Generators = ExtremeRays2559vector<Integer> lf = BasisChangePointed.to_sublattice(Generators).find_linear_form();2560if (lf.size() == BasisChange.getRank()) {2561vector<Integer> test_lf=BasisChange.from_sublattice_dual(lf);2562if(Generators.nr_of_rows()==0 || v_scalar_product(Generators[0],test_lf)==1)2563setGrading(test_lf);2564}2565}2566setWeights();2567set_extreme_rays(vector<bool>(Generators.nr_of_rows(),true)); // here since they get sorted2568is_Computed.set(ConeProperty::ExtremeRays);2569}2570}257125722573template<typename Integer>2574void Cone<Integer>::compute_dual(ConeProperties& ToCompute) {25752576ToCompute.reset(is_Computed);2577if (ToCompute.none() || !( ToCompute.test(ConeProperty::Deg1Elements)2578|| ToCompute.test(ConeProperty::HilbertBasis))) {2579return;2580}25812582if (change_integer_type) {2583try {2584compute_dual_inner<MachineInteger>(ToCompute);2585} catch(const ArithmeticException& e) {2586if (verbose) {2587verboseOutput() << e.what() << endl;2588verboseOutput() << "Restarting with a bigger type." << endl;2589}2590change_integer_type = false;2591}2592}2593if (!change_integer_type) {2594compute_dual_inner<Integer>(ToCompute);2595}2596ToCompute.reset(ConeProperty::DualMode);2597ToCompute.reset(is_Computed);2598// if (ToCompute.test(ConeProperty::DefaultMode) && ToCompute.goals().none()) {2599// ToCompute.reset(ConeProperty::DefaultMode);2600// }2601}26022603template<typename Integer>2604vector<Sublattice_Representation<Integer> > MakeSubAndQuot(const Matrix<Integer>& Gen,2605const Matrix<Integer>& Ker){2606vector<Sublattice_Representation<Integer> > Result;2607Matrix<Integer> Help=Gen;2608Help.append(Ker);2609Sublattice_Representation<Integer> Sub(Help,true);2610Sublattice_Representation<Integer> Quot=Sub;2611if(Ker.nr_of_rows()>0){2612Matrix<Integer> HelpQuot=Sub.to_sublattice(Ker).kernel(); // kernel here to be interpreted as subspace of the dual2613// namely the linear forms vanishing on Ker2614Sublattice_Representation<Integer> SubToQuot(HelpQuot,true); // sublattice of the dual2615Quot.compose_dual(SubToQuot);2616}2617Result.push_back(Sub);2618Result.push_back(Quot);26192620return Result;2621}26222623template<typename Integer>2624template<typename IntegerFC>2625void Cone<Integer>::compute_dual_inner(ConeProperties& ToCompute) {26262627bool do_only_Deg1_Elements = ToCompute.test(ConeProperty::Deg1Elements)2628&& !ToCompute.test(ConeProperty::HilbertBasis);26292630if(isComputed(ConeProperty::Generators) && SupportHyperplanes.nr_of_rows()==0){2631if (verbose) {2632verboseOutput()<< "Computing support hyperplanes for the dual mode:"<< endl;2633}2634ConeProperties Dualize;2635Dualize.set(ConeProperty::SupportHyperplanes);2636Dualize.set(ConeProperty::ExtremeRays);2637recursive_compute(Dualize);2638}26392640bool do_extreme_rays_first = false;2641if (!isComputed(ConeProperty::ExtremeRays)) {2642if (do_only_Deg1_Elements && Grading.size()==0)2643do_extreme_rays_first = true;2644else if ( (do_only_Deg1_Elements || inhomogeneous) &&2645( naked_dual2646|| ToCompute.test(ConeProperty::ExtremeRays)2647|| ToCompute.test(ConeProperty::SupportHyperplanes)2648|| ToCompute.test(ConeProperty::Sublattice) ) )2649do_extreme_rays_first = true;2650}26512652if (do_extreme_rays_first) {2653if (verbose) {2654verboseOutput() << "Computing extreme rays for the dual mode:"<< endl;2655}2656compute_generators(); // computes extreme rays, but does not find grading !2657}26582659if(do_only_Deg1_Elements && Grading.size()==0){2660vector<Integer> lf= Generators.submatrix(ExtremeRaysIndicator).find_linear_form_low_dim();2661if(Generators.nr_of_rows()==0 || (lf.size()==dim && v_scalar_product(Generators[0],lf)==1))2662setGrading(lf);2663else{2664throw BadInputException("Need grading to compute degree 1 elements and cannot find one.");2665}2666}26672668if (SupportHyperplanes.nr_of_rows()==0 && !isComputed(ConeProperty::SupportHyperplanes)) {2669throw FatalException("Could not get SupportHyperplanes.");2670}26712672Matrix<IntegerFC> Inequ_on_Ker;2673BasisChangePointed.convert_to_sublattice_dual(Inequ_on_Ker,SupportHyperplanes);26742675vector<IntegerFC> Truncation;2676if(inhomogeneous){2677BasisChangePointed.convert_to_sublattice_dual_no_div(Truncation, Dehomogenization);2678}2679if (do_only_Deg1_Elements) {2680// in this case the grading acts as truncation and it is a NEW inequality2681BasisChangePointed.convert_to_sublattice_dual(Truncation, Grading);2682}26832684Cone_Dual_Mode<IntegerFC> ConeDM(Inequ_on_Ker, Truncation); // Inequ_on_Ker is NOT const2685Inequ_on_Ker=Matrix<IntegerFC>(0,0); // destroy it2686ConeDM.verbose=verbose;2687ConeDM.inhomogeneous=inhomogeneous;2688ConeDM.do_only_Deg1_Elements=do_only_Deg1_Elements;2689if(isComputed(ConeProperty::Generators))2690BasisChangePointed.convert_to_sublattice(ConeDM.Generators, Generators);2691if(isComputed(ConeProperty::ExtremeRays))2692ConeDM.ExtremeRaysInd=ExtremeRaysIndicator;2693ConeDM.hilbert_basis_dual();26942695if(!isComputed(ConeProperty::MaximalSubspace)){2696BasisChangePointed.convert_from_sublattice(BasisMaxSubspace,ConeDM.BasisMaxSubspace);2697check_vanishing_of_grading_and_dehom(); // all this must be done here because to_sublattice may kill it2698}26992700if (!isComputed(ConeProperty::Sublattice) || !isComputed(ConeProperty::MaximalSubspace)){2701if(!(do_only_Deg1_Elements || inhomogeneous)) {2702// At this point we still have BasisChange==BasisChangePointed2703// now we can pass to a pointed full-dimensional cone27042705vector<Sublattice_Representation<IntegerFC> > BothRepFC=MakeSubAndQuot2706(ConeDM.Generators,ConeDM.BasisMaxSubspace);2707if(!BothRepFC[0].IsIdentity())2708BasisChange.compose(Sublattice_Representation<Integer>(BothRepFC[0]));2709is_Computed.set(ConeProperty::Sublattice);2710if(!BothRepFC[1].IsIdentity())2711BasisChangePointed.compose(Sublattice_Representation<Integer>(BothRepFC[1]));2712ConeDM.to_sublattice(BothRepFC[1]);2713}2714}27152716is_Computed.set(ConeProperty::MaximalSubspace); // NOT EARLIER !!!!271727182719// create a Full_Cone out of ConeDM2720Full_Cone<IntegerFC> FC(ConeDM);2721FC.verbose=verbose;2722// Give extra data to FC2723if (Grading.size()>0) {2724BasisChangePointed.convert_to_sublattice_dual(FC.Grading, Grading);2725if(isComputed(ConeProperty::Grading))2726FC.is_Computed.set(ConeProperty::Grading);2727}2728if(inhomogeneous)2729BasisChangePointed.convert_to_sublattice_dual_no_div(FC.Truncation, Dehomogenization);2730FC.do_class_group=ToCompute.test(ConeProperty::ClassGroup);2731FC.dual_mode();2732extract_data(FC);2733}27342735//---------------------------------------------------------------------------27362737template<typename Integer>2738Integer Cone<Integer>::compute_primary_multiplicity() {2739if (change_integer_type) {2740try {2741return compute_primary_multiplicity_inner<MachineInteger>();2742} catch(const ArithmeticException& e) {2743if (verbose) {2744verboseOutput() << e.what() << endl;2745verboseOutput() << "Restarting with a bigger type." << endl;2746}2747change_integer_type = false;2748}2749}2750return compute_primary_multiplicity_inner<Integer>();2751}27522753//---------------------------------------------------------------------------27542755template<typename Integer>2756template<typename IntegerFC>2757Integer Cone<Integer>::compute_primary_multiplicity_inner() {2758Matrix<IntegerFC> Ideal(0,dim-1);2759vector<IntegerFC> help(dim-1);2760for(size_t i=0;i<Generators.nr_of_rows();++i){ // select ideal generators2761if(Generators[i][dim-1]==1){2762for(size_t j=0;j<dim-1;++j)2763convert(help[j],Generators[i][j]);2764Ideal.append(help);2765}2766}2767Full_Cone<IntegerFC> IdCone(Ideal,false);2768IdCone.do_bottom_dec=true;2769IdCone.do_determinants=true;2770IdCone.compute();2771return convertTo<Integer>(IdCone.detSum);2772}27732774//---------------------------------------------------------------------------27752776template<typename Integer>2777template<typename IntegerFC>2778void Cone<Integer>::extract_data(Full_Cone<IntegerFC>& FC) {2779//this function extracts ALL available data from the Full_Cone2780//even if it was in Cone already <- this may change2781//it is possible to delete the data in Full_Cone after extracting it27822783if(verbose) {2784verboseOutput() << "transforming data..."<<flush;2785}27862787if (FC.isComputed(ConeProperty::Generators)) {2788BasisChangePointed.convert_from_sublattice(Generators,FC.getGenerators());2789is_Computed.set(ConeProperty::Generators);2790}27912792if (FC.isComputed(ConeProperty::IsPointed) && !isComputed(ConeProperty::IsPointed)) {2793pointed = FC.isPointed();2794if(pointed)2795is_Computed.set(ConeProperty::MaximalSubspace);2796is_Computed.set(ConeProperty::IsPointed);2797}27982799if (FC.isComputed(ConeProperty::Grading)) {2800if (Grading.size()==0) {2801BasisChangePointed.convert_from_sublattice_dual(Grading, FC.getGrading());2802}2803is_Computed.set(ConeProperty::Grading);2804setWeights();2805//compute denominator of Grading2806if(BasisChangePointed.getRank()!=0){2807vector<Integer> test_grading = BasisChangePointed.to_sublattice_dual_no_div(Grading);2808GradingDenom=v_make_prime(test_grading);2809}2810else2811GradingDenom=1;2812is_Computed.set(ConeProperty::GradingDenom);2813}28142815if (FC.isComputed(ConeProperty::ModuleGeneratorsOverOriginalMonoid)) { // must precede extreme rays2816BasisChangePointed.convert_from_sublattice(ModuleGeneratorsOverOriginalMonoid, FC.getModuleGeneratorsOverOriginalMonoid());2817ModuleGeneratorsOverOriginalMonoid.sort_by_weights(WeightsGrad,GradAbs);2818is_Computed.set(ConeProperty::ModuleGeneratorsOverOriginalMonoid);2819}28202821if (FC.isComputed(ConeProperty::ExtremeRays)) {2822set_extreme_rays(FC.getExtremeRays());2823}2824if (FC.isComputed(ConeProperty::SupportHyperplanes)) {2825/* if (inhomogeneous) {2826// remove irrelevant support hyperplane 0 ... 0 12827vector<IntegerFC> irr_hyp_subl;2828BasisChangePointed.convert_to_sublattice_dual(irr_hyp_subl, Dehomogenization);2829FC.Support_Hyperplanes.remove_row(irr_hyp_subl);2830} */2831// BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, FC.getSupportHyperplanes());2832extract_supphyps(FC);2833if(inhomogeneous && FC.dim<dim){ // make inequality for the inhomogeneous variable appear as dehomogenization2834vector<Integer> dehom_restricted=BasisChangePointed.to_sublattice_dual(Dehomogenization);2835for(size_t i=0;i<SupportHyperplanes.nr_of_rows();++i){2836if(dehom_restricted==BasisChangePointed.to_sublattice_dual(SupportHyperplanes[i])){2837SupportHyperplanes[i]=Dehomogenization;2838break;2839}2840}2841}2842SupportHyperplanes.sort_lex();2843is_Computed.set(ConeProperty::SupportHyperplanes);2844}2845if (FC.isComputed(ConeProperty::TriangulationSize)) {2846TriangulationSize = FC.totalNrSimplices;2847triangulation_is_nested = FC.triangulation_is_nested;2848triangulation_is_partial= FC.triangulation_is_partial;2849is_Computed.set(ConeProperty::TriangulationSize);2850is_Computed.set(ConeProperty::IsTriangulationPartial);2851is_Computed.set(ConeProperty::IsTriangulationNested);2852is_Computed.reset(ConeProperty::Triangulation);2853Triangulation.clear(); // to get rid of a previously computed triangulation2854}2855if (FC.isComputed(ConeProperty::TriangulationDetSum)) {2856convert(TriangulationDetSum, FC.detSum);2857is_Computed.set(ConeProperty::TriangulationDetSum);2858}28592860if (FC.isComputed(ConeProperty::Triangulation)) {2861size_t tri_size = FC.Triangulation.size();2862FC.Triangulation.sort(compareKeys<IntegerFC>); // necessary to make triangulation unique2863Triangulation = vector< pair<vector<key_t>, Integer> >(tri_size);2864if(FC.isComputed(ConeProperty::ConeDecomposition))2865OpenFacets.resize(tri_size);2866SHORTSIMPLEX<IntegerFC> simp;2867for (size_t i = 0; i<tri_size; ++i) {2868simp = FC.Triangulation.front();2869Triangulation[i].first.swap(simp.key);2870/* sort(Triangulation[i].first.begin(), Triangulation[i].first.end()); -- no longer allowed here because of ConeDecomposition. Done in full_cone.cpp, transfer_triangulation_to top */2871if (FC.isComputed(ConeProperty::TriangulationDetSum))2872convert(Triangulation[i].second, simp.vol);2873else2874Triangulation[i].second = 0;2875if(FC.isComputed(ConeProperty::ConeDecomposition))2876OpenFacets[i].swap(simp.Excluded);2877FC.Triangulation.pop_front();2878}2879if(FC.isComputed(ConeProperty::ConeDecomposition))2880is_Computed.set(ConeProperty::ConeDecomposition);2881is_Computed.set(ConeProperty::Triangulation);2882}28832884if (FC.isComputed(ConeProperty::StanleyDec)) {2885StanleyDec.clear();2886StanleyDec.splice(StanleyDec.begin(),FC.StanleyDec);2887// At present, StanleyDec not sorted here2888is_Computed.set(ConeProperty::StanleyDec);2889}28902891if (FC.isComputed(ConeProperty::InclusionExclusionData)) {2892InExData.clear();2893InExData.reserve(FC.InExCollect.size());2894map<boost::dynamic_bitset<>, long>::iterator F;2895vector<key_t> key;2896for (F=FC.InExCollect.begin(); F!=FC.InExCollect.end(); ++F) {2897key.clear();2898for (size_t i=0;i<FC.nr_gen;++i) {2899if (F->first.test(i)) {2900key.push_back(i);2901}2902}2903InExData.push_back(make_pair(key,F->second));2904}2905is_Computed.set(ConeProperty::InclusionExclusionData);2906}2907if (FC.isComputed(ConeProperty::RecessionRank) && isComputed(ConeProperty::MaximalSubspace)) {2908recession_rank = FC.level0_dim+BasisMaxSubspace.nr_of_rows();2909is_Computed.set(ConeProperty::RecessionRank);2910if (getRank() == recession_rank) {2911affine_dim = -1;2912} else {2913affine_dim = getRank()-1;2914}2915is_Computed.set(ConeProperty::AffineDim);2916}2917if (FC.isComputed(ConeProperty::ModuleRank)) {2918module_rank = FC.getModuleRank();2919is_Computed.set(ConeProperty::ModuleRank);2920}2921if (FC.isComputed(ConeProperty::Multiplicity)) {2922if(!inhomogeneous) {2923multiplicity = FC.getMultiplicity();2924is_Computed.set(ConeProperty::Multiplicity);2925} else if (isComputed(ConeProperty::ModuleRank)) {2926multiplicity = FC.getMultiplicity()*module_rank;2927is_Computed.set(ConeProperty::Multiplicity);2928}2929}2930if (FC.isComputed(ConeProperty::WitnessNotIntegrallyClosed)) {2931BasisChangePointed.convert_from_sublattice(WitnessNotIntegrallyClosed,FC.Witness);2932is_Computed.set(ConeProperty::WitnessNotIntegrallyClosed);2933integrally_closed = false;2934is_Computed.set(ConeProperty::IsIntegrallyClosed);2935}2936if (FC.isComputed(ConeProperty::HilbertBasis)) {2937if (inhomogeneous) {2938// separate (capped) Hilbert basis to the Hilbert basis of the level 0 cone2939// and the module generators in level 12940HilbertBasis = Matrix<Integer>(0,dim);2941ModuleGenerators = Matrix<Integer>(0,dim);2942typename list< vector<IntegerFC> >::const_iterator FCHB(FC.Hilbert_Basis.begin());2943vector<Integer> tmp;2944for (; FCHB != FC.Hilbert_Basis.end(); ++FCHB) {29452946INTERRUPT_COMPUTATION_BY_EXCEPTION29472948BasisChangePointed.convert_from_sublattice(tmp,*FCHB);2949if (v_scalar_product(tmp,Dehomogenization) == 0) { // Hilbert basis element of the cone at level 02950HilbertBasis.append(tmp);2951} else { // module generator2952ModuleGenerators.append(tmp);2953}2954}2955ModuleGenerators.sort_by_weights(WeightsGrad,GradAbs);2956is_Computed.set(ConeProperty::ModuleGenerators);2957} else { // homogeneous2958HilbertBasis = Matrix<Integer>(0,dim);2959typename list< vector<IntegerFC> >::const_iterator FCHB(FC.Hilbert_Basis.begin());2960vector<Integer> tmp;2961for (; FCHB != FC.Hilbert_Basis.end(); ++FCHB) {2962BasisChangePointed.convert_from_sublattice(tmp,*FCHB);2963HilbertBasis.append(tmp);2964}2965}2966HilbertBasis.sort_by_weights(WeightsGrad,GradAbs);2967is_Computed.set(ConeProperty::HilbertBasis);2968}2969if (FC.isComputed(ConeProperty::Deg1Elements)) {2970Deg1Elements = Matrix<Integer>(0,dim);2971typename list< vector<IntegerFC> >::const_iterator DFC(FC.Deg1_Elements.begin());2972vector<Integer> tmp;2973for (; DFC != FC.Deg1_Elements.end(); ++DFC) {29742975INTERRUPT_COMPUTATION_BY_EXCEPTION29762977BasisChangePointed.convert_from_sublattice(tmp,*DFC);2978Deg1Elements.append(tmp);2979}2980Deg1Elements.sort_by_weights(WeightsGrad,GradAbs);2981is_Computed.set(ConeProperty::Deg1Elements);2982}2983if (FC.isComputed(ConeProperty::HilbertSeries)) {2984long save_nr_coeff_quasipol=HSeries.get_nr_coeff_quasipol(); // Full_Cone does not compute the quasipolynomial2985HSeries = FC.Hilbert_Series;2986HSeries.set_nr_coeff_quasipol(save_nr_coeff_quasipol);2987is_Computed.set(ConeProperty::HilbertSeries);2988}2989if (FC.isComputed(ConeProperty::HSOP)) {2990is_Computed.set(ConeProperty::HSOP);2991}2992if (FC.isComputed(ConeProperty::IsDeg1ExtremeRays)) {2993deg1_extreme_rays = FC.isDeg1ExtremeRays();2994is_Computed.set(ConeProperty::IsDeg1ExtremeRays);2995}2996if (FC.isComputed(ConeProperty::ExcludedFaces)) {2997BasisChangePointed.convert_from_sublattice_dual(ExcludedFaces, FC.getExcludedFaces());2998ExcludedFaces.sort_lex();2999is_Computed.set(ConeProperty::ExcludedFaces);3000}30013002if (FC.isComputed(ConeProperty::IsDeg1HilbertBasis)) {3003deg1_hilbert_basis = FC.isDeg1HilbertBasis();3004is_Computed.set(ConeProperty::IsDeg1HilbertBasis);3005}3006if (FC.isComputed(ConeProperty::ClassGroup)) {3007convert(ClassGroup, FC.ClassGroup);3008is_Computed.set(ConeProperty::ClassGroup);3009}30103011/* if (FC.isComputed(ConeProperty::MaximalSubspace) &&3012!isComputed(ConeProperty::MaximalSubspace)) {3013BasisChangePointed.convert_from_sublattice(BasisMaxSubspace, FC.Basis_Max_Subspace);3014check_vanishing_of_grading_and_dehom();3015is_Computed.set(ConeProperty::MaximalSubspace);3016}*/30173018check_integrally_closed();30193020if (verbose) {3021verboseOutput() << " done." <<endl;3022}3023}30243025//---------------------------------------------------------------------------3026template<typename Integer>3027template<typename IntegerFC>3028void Cone<Integer>::extract_supphyps(Full_Cone<IntegerFC>& FC) {3029BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, FC.getSupportHyperplanes());3030}30313032template<typename Integer>3033void Cone<Integer>::extract_supphyps(Full_Cone<Integer>& FC) {3034if(BasisChangePointed.IsIdentity())3035swap(SupportHyperplanes,FC.Support_Hyperplanes);3036else3037SupportHyperplanes=BasisChangePointed.from_sublattice_dual(FC.getSupportHyperplanes());3038}303930403041//---------------------------------------------------------------------------30423043template<typename Integer>3044void Cone<Integer>::check_integrally_closed() {3045if (!isComputed(ConeProperty::OriginalMonoidGenerators)3046|| isComputed(ConeProperty::IsIntegrallyClosed)3047|| !isComputed(ConeProperty::HilbertBasis) || inhomogeneous)3048return;30493050unit_group_index=1;3051if(BasisMaxSubspace.nr_of_rows()>0)3052compute_unit_group_index();3053is_Computed.set(ConeProperty::UnitGroupIndex);3054if (index > 1 || HilbertBasis.nr_of_rows() > OriginalMonoidGenerators.nr_of_rows()3055|| unit_group_index>1) {3056integrally_closed = false;3057is_Computed.set(ConeProperty::IsIntegrallyClosed);3058return;3059}3060find_witness();3061}30623063//---------------------------------------------------------------------------30643065template<typename Integer>3066void Cone<Integer>::compute_unit_group_index() {3067assert(isComputed(ConeProperty::MaximalSubspace));3068// we want to compute in the maximal linear subspace3069Sublattice_Representation<Integer> Sub(BasisMaxSubspace,true);3070Matrix<Integer> origens_in_subspace(0,dim);30713072// we must collect all original generetors that lie in the maximal subspace30733074for(size_t i=0;i<OriginalMonoidGenerators.nr_of_rows();++i){3075size_t j;3076for(j=0;j<SupportHyperplanes.nr_of_rows();++j){3077if(v_scalar_product(OriginalMonoidGenerators[i],SupportHyperplanes[j])!=0)3078break;3079}3080if(j==SupportHyperplanes.nr_of_rows())3081origens_in_subspace.append(OriginalMonoidGenerators[i]);3082}3083Matrix<Integer> M=Sub.to_sublattice(origens_in_subspace);3084unit_group_index= M.full_rank_index();3085// cout << "Unit group index " << unit_group_index;3086}30873088//---------------------------------------------------------------------------30893090template<typename Integer>3091void Cone<Integer>::find_witness() {3092if (!isComputed(ConeProperty::OriginalMonoidGenerators)3093|| inhomogeneous) {3094// no original monoid defined3095throw NotComputableException(ConeProperties(ConeProperty::WitnessNotIntegrallyClosed));3096}3097if (isComputed(ConeProperty::IsIntegrallyClosed) && integrally_closed) {3098// original monoid is integrally closed3099throw NotComputableException(ConeProperties(ConeProperty::WitnessNotIntegrallyClosed));3100}3101if (isComputed(ConeProperty::WitnessNotIntegrallyClosed)3102|| !isComputed(ConeProperty::HilbertBasis) )3103return;31043105long nr_gens = OriginalMonoidGenerators.nr_of_rows();3106long nr_hilb = HilbertBasis.nr_of_rows();3107// if the cone is not pointed, we have to check it on the quotion3108Matrix<Integer> gens_quot;3109Matrix<Integer> hilb_quot;3110if (!pointed) {3111gens_quot = BasisChangePointed.to_sublattice(OriginalMonoidGenerators);3112hilb_quot = BasisChangePointed.to_sublattice(HilbertBasis);3113}3114Matrix<Integer>& gens = pointed ? OriginalMonoidGenerators : gens_quot;3115Matrix<Integer>& hilb = pointed ? HilbertBasis : hilb_quot;3116integrally_closed = true;3117typename list< vector<Integer> >::iterator h;3118for (long h = 0; h < nr_hilb; ++h) {3119integrally_closed = false;3120for (long i = 0; i < nr_gens; ++i) {3121if (hilb[h] == gens[i]) {3122integrally_closed = true;3123break;3124}3125}3126if (!integrally_closed) {3127WitnessNotIntegrallyClosed = HilbertBasis[h];3128is_Computed.set(ConeProperty::WitnessNotIntegrallyClosed);3129break;3130}3131}3132is_Computed.set(ConeProperty::IsIntegrallyClosed);3133}31343135//---------------------------------------------------------------------------31363137template<typename Integer>3138void Cone<Integer>::set_original_monoid_generators(const Matrix<Integer>& Input) {3139if (!isComputed(ConeProperty::OriginalMonoidGenerators)) {3140OriginalMonoidGenerators = Input;3141is_Computed.set(ConeProperty::OriginalMonoidGenerators);3142}3143// Generators = Input;3144// is_Computed.set(ConeProperty::Generators);3145Matrix<Integer> M=BasisChange.to_sublattice(Input);3146index=M.full_rank_index();3147is_Computed.set(ConeProperty::InternalIndex);3148}31493150//---------------------------------------------------------------------------31513152template<typename Integer>3153void Cone<Integer>::set_extreme_rays(const vector<bool>& ext) {3154assert(ext.size() == Generators.nr_of_rows());3155ExtremeRaysIndicator=ext;3156vector<bool> choice=ext;3157if (inhomogeneous) {3158// separate extreme rays to rays of the level 0 cone3159// and the verticies of the polyhedron, which are in level >=13160size_t nr_gen = Generators.nr_of_rows();3161vector<bool> VOP(nr_gen);3162for (size_t i=0; i<nr_gen; i++) {3163if (ext[i] && v_scalar_product(Generators[i],Dehomogenization) != 0) {3164VOP[i] = true;3165choice[i]=false;3166}3167}3168VerticesOfPolyhedron=Generators.submatrix(VOP).sort_by_weights(WeightsGrad,GradAbs);3169is_Computed.set(ConeProperty::VerticesOfPolyhedron);3170}3171ExtremeRays=Generators.submatrix(choice);3172if(inhomogeneous && !isComputed(ConeProperty::AffineDim) && isComputed(ConeProperty::MaximalSubspace)){3173size_t level0_dim=ExtremeRays.max_rank_submatrix_lex().size();3174recession_rank = level0_dim+BasisMaxSubspace.nr_of_rows();3175is_Computed.set(ConeProperty::RecessionRank);3176if (getRank() == recession_rank) {3177affine_dim = -1;3178} else {3179affine_dim = getRank()-1;3180}3181is_Computed.set(ConeProperty::AffineDim);31823183}3184if(isComputed(ConeProperty::ModuleGeneratorsOverOriginalMonoid)){ // not possible in inhomogeneous case3185Matrix<Integer> ExteEmbedded=BasisChangePointed.to_sublattice(ExtremeRays);3186for(size_t i=0;i<ExteEmbedded.nr_of_rows();++i)3187v_make_prime(ExteEmbedded[i]);3188ExteEmbedded.remove_duplicate_and_zero_rows();3189ExtremeRays=BasisChangePointed.from_sublattice(ExteEmbedded);3190}3191ExtremeRays.sort_by_weights(WeightsGrad,GradAbs);3192is_Computed.set(ConeProperty::ExtremeRays);3193}31943195//---------------------------------------------------------------------------31963197template<typename Integer>3198void Cone<Integer>::compute_vertices_float(ConeProperties& ToCompute) {3199if(!ToCompute.test(ConeProperty::VerticesFloat) || isComputed(ConeProperty::VerticesFloat))3200return;3201if(!isComputed(ConeProperty::ExtremeRays))3202throw NotComputableException("VerticesFloat not computable without extreme rays");3203if(inhomogeneous && !isComputed(ConeProperty::VerticesOfPolyhedron))3204throw NotComputableException("VerticesFloat not computable in the inhomogeneous case without vertices");3205if(!inhomogeneous && !isComputed(ConeProperty::Grading))3206throw NotComputableException("VerticesFloat not computable in the homogeneous case without a grading");3207if(inhomogeneous)3208convert(VerticesFloat, VerticesOfPolyhedron);3209else3210convert(VerticesFloat, ExtremeRays);3211vector<nmz_float> norm;3212if(inhomogeneous)3213convert(norm,Dehomogenization);3214else{3215convert( norm,Grading);3216nmz_float GD=1.0/convertTo<double>(GradingDenom);3217v_scalar_multiplication(norm,GD);3218}3219for(size_t i=0;i<VerticesFloat.nr_of_rows();++i){3220nmz_float den=1.0/v_scalar_product(VerticesFloat[i],norm);3221v_scalar_multiplication(VerticesFloat[i],den);3222}3223is_Computed.set(ConeProperty::VerticesFloat);3224}32253226//---------------------------------------------------------------------------32273228template<typename Integer>3229void Cone<Integer>::complete_sublattice_comp(ConeProperties& ToCompute) {32303231if(!isComputed(ConeProperty::Sublattice))3232return;3233is_Computed.set(ConeProperty::Rank);3234if(ToCompute.test(ConeProperty::Equations)){3235BasisChange.getEquationsMatrix(); // just to force computation, ditto below3236is_Computed.set(ConeProperty::Equations);3237}3238if(ToCompute.test(ConeProperty::Congruences) || ToCompute.test(ConeProperty::ExternalIndex)){3239BasisChange.getCongruencesMatrix();3240BasisChange.getExternalIndex();3241is_Computed.set(ConeProperty::Congruences);3242is_Computed.set(ConeProperty::ExternalIndex);3243}3244}32453246template<typename Integer>3247void Cone<Integer>::complete_HilbertSeries_comp(ConeProperties& ToCompute) {3248if(!isComputed(ConeProperty::HilbertSeries))3249return;3250if(ToCompute.test(ConeProperty::HilbertQuasiPolynomial))3251HSeries.computeHilbertQuasiPolynomial();3252if(HSeries.isHilbertQuasiPolynomialComputed())3253is_Computed.set(ConeProperty::HilbertQuasiPolynomial);32543255// in the case that HS was computed but not HSOP, we need to compute hsop3256if(ToCompute.test(ConeProperty::HSOP) && !isComputed(ConeProperty::HSOP)){3257// we need generators and support hyperplanes to compute hsop3258Matrix<Integer> FC_gens;3259Matrix<Integer> FC_hyps;3260BasisChangePointed.convert_to_sublattice(FC_gens,Generators);3261Full_Cone<Integer> FC(FC_gens);3262FC.Extreme_Rays_Ind = ExtremeRaysIndicator;3263FC.Grading = Grading;3264FC.inhomogeneous = inhomogeneous;3265// TRUNCATION?3266BasisChangePointed.convert_to_sublattice_dual(FC.Support_Hyperplanes,SupportHyperplanes);3267FC.compute_hsop();3268HSeries.setHSOPDenom(FC.Hilbert_Series.getHSOPDenom());3269HSeries.compute_hsop_num();3270}3271}32723273//---------------------------------------------------------------------------3274template<typename Integer>3275void Cone<Integer>::set_project(string name){3276project=name;3277}32783279template<typename Integer>3280void Cone<Integer>::set_output_dir(string name){3281output_dir=name;3282}32833284template<typename Integer>3285void Cone<Integer>::set_nmz_call(const string& path){3286nmz_call=path;3287}32883289template<typename Integer>3290void Cone<Integer>::setPolynomial(string poly){3291IntData=IntegrationData(poly);3292}32933294template<typename Integer>3295void Cone<Integer>::setNrCoeffQuasiPol(long nr_coeff){3296IntData.set_nr_coeff_quasipol(nr_coeff);3297HSeries.set_nr_coeff_quasipol(nr_coeff);3298}32993300bool executable(string command){3301//n check whether "command --version" cam be executed33023303command +=" --version";3304string dev0= " > /dev/null";3305#ifdef _WIN32 //for 32 and 64 bit windows3306dev0=" > NUL:";3307#endif3308command+=dev0;3309if(system(command.c_str())==0)3310return true;3311else3312return false;3313}33143315string command(const string& original_call, const string& to_replace, const string& by_this){3316// in the original call we replace the program name to_replace by by_this3317// we try variants with and without "lt-" preceding the names of executables3318// since libtools may have inserted "lt-" before the original name33193320string copy=original_call;3321// cout << "CALL " << original_call << endl;3322string search_lt="lt-"+to_replace;3323long length=to_replace.size();3324size_t found;3325found = copy.rfind(search_lt);3326if (found==std::string::npos) {3327found = copy.rfind(to_replace);3328if (found==std::string::npos){3329throw FatalException("Call "+ copy +" of " +to_replace+" does not contain " +to_replace);3330}3331}3332else{3333length+=3; //name includes lt-3334}3335string test_path=copy.replace (found,length,by_this);3336// cout << "TEST " << test_path << endl;3337if(executable(test_path)) // first without lt-3338return test_path;3339copy=original_call;3340string by_this_with_lt="lt-"+by_this; /// now with lt-3341test_path=copy.replace (found,length,by_this_with_lt);3342// cout << "TEST " << test_path << endl;3343if(executable(test_path))3344return test_path;3345return ""; // no executable found3346}33473348//---------------------------------------------------------------------------3349template<typename Integer>3350void Cone<Integer>::try_symmetrization(ConeProperties& ToCompute) {33513352if(ToCompute.test(ConeProperty::NoSymmetrization))3353return;33543355if(!(ToCompute.test(ConeProperty::Symmetrize) || ToCompute.test(ConeProperty::HilbertSeries) ||3356ToCompute.test(ConeProperty::Multiplicity)))3357return;33583359if(inhomogeneous || nr_latt_gen>0|| nr_cone_gen>0 || lattice_ideal_input || Grading.size() < dim){3360if(ToCompute.test(ConeProperty::Symmetrize))3361throw BadInputException("Symmetrization not posible with the given input");3362else3363return;3364}33653366#ifndef NMZ_COCOA3367if(project==""){3368if(ToCompute.test(ConeProperty::Symmetrize)){3369throw BadInputException("Symmetrization via libnormaliz not possible without CoCoALib");3370}3371else3372return;3373}3374#endif33753376Matrix<Integer> AllConst=ExcludedFaces;3377size_t nr_excl = AllConst.nr_of_rows();3378AllConst. append(Equations);3379size_t nr_equ=AllConst.nr_of_rows()-nr_excl;3380vector<bool> unit_vector(dim,false);3381for(size_t i=0;i<Inequalities.nr_of_rows();++i){3382size_t nr_nonzero=0;3383size_t nonzero_coord;3384bool is_unit_vector=true;3385for(size_t j=0;j<dim;++j){3386if(Inequalities[i][j]==0)3387continue;3388if(nr_nonzero>0 || Inequalities[i][j]!=1){ // not a sign inequality3389is_unit_vector=false;3390break;3391}3392nr_nonzero++;3393nonzero_coord=j;3394}3395if(!is_unit_vector)3396AllConst.append(Inequalities[i]);3397else3398unit_vector[nonzero_coord]=true;3399}34003401size_t nr_inequ=AllConst.nr_of_rows()-nr_equ-nr_excl;34023403for(size_t i=0;i<dim;++i)3404if(!unit_vector[i]){3405if(ToCompute.test(ConeProperty::Symmetrize))3406throw BadInputException("Symmetrization not possible: Not all sign inequalities in input");3407else3408return;3409}34103411for(size_t i=0;i<Congruences.nr_of_rows();++i){3412vector<Integer> help=Congruences[i];3413help.resize(dim);3414AllConst.append(help);3415}3416// now we have collected all constraints and cehcked the existence of the sign inequalities341734183419AllConst.append(Grading);34203421/* AllConst.pretty_print(cout);3422cout << "----------------------" << endl;3423cout << nr_excl << " " << nr_equ << " " << nr_inequ << endl; */34243425AllConst=AllConst.transpose();34263427map< vector<Integer>, size_t > classes;3428typename map< vector<Integer>, size_t >::iterator C;34293430for(size_t j=0;j<AllConst.nr_of_rows();++j){3431C=classes.find(AllConst[j]);3432if(C!=classes.end())3433C->second++;3434else3435classes.insert(pair<vector<Integer>, size_t>(AllConst[j],1));3436}34373438vector<size_t> multiplicities;3439Matrix<Integer> SymmConst(0,AllConst.nr_of_columns());34403441for(C=classes.begin();C!=classes.end();++C){3442multiplicities.push_back(C->second);3443SymmConst.append(C->first);3444}3445SymmConst=SymmConst.transpose();34463447vector<Integer> SymmGrad=SymmConst[SymmConst.nr_of_rows()-1];34483449if(verbose){3450verboseOutput() << "Embedding dimension of symmetrized cone = " << SymmGrad.size() << endl;3451}34523453if(SymmGrad.size() > 2*dim/3){3454if(!ToCompute.test(ConeProperty::Symmetrize)){3455return;3456}3457}34583459/* compute_generators(); // we must protect against the zero cone3460if(getRank()==0)3461return; */34623463Matrix<Integer> SymmInequ(0,SymmConst.nr_of_columns());3464Matrix<Integer> SymmEqu(0,SymmConst.nr_of_columns());3465Matrix<Integer> SymmCong(0,SymmConst.nr_of_columns());3466Matrix<Integer> SymmExcl(0,SymmConst.nr_of_columns());34673468for(size_t i=0;i<nr_excl;++i)3469SymmExcl.append(SymmConst[i]);3470for(size_t i=nr_excl;i<nr_excl+nr_equ;++i)3471SymmEqu.append(SymmConst[i]);3472for(size_t i=nr_excl+nr_equ;i<nr_excl+nr_equ+nr_inequ;++i)3473SymmInequ.append(SymmConst[i]);3474for(size_t i=nr_excl+nr_equ+nr_inequ;i<SymmConst.nr_of_rows()-1;++i){3475SymmCong.append(SymmConst[i]);3476SymmCong[SymmCong.nr_of_rows()-1].push_back(Congruences[i-(nr_inequ+nr_equ)][dim]); // restore modulus3477}34783479string polynomial;34803481for(size_t i=0;i<multiplicities.size();++i){3482for(size_t j=1;j<multiplicities[i];++j)3483polynomial+="(x["+to_string((unsigned long long) i+1)+"]+"+to_string((unsigned long long)j)+")*";34843485}3486polynomial+="1";3487mpz_class fact=1;3488for(size_t i=0;i<multiplicities.size();++i){3489for(size_t j=1;j<multiplicities[i];++j)3490fact*=j;3491}3492polynomial+="/"+fact.get_str()+";";34933494#ifdef NMZ_COCOA34953496map< InputType, Matrix<Integer> > SymmInput;3497SymmInput[InputType::inequalities]=SymmInequ;3498SymmInput[InputType::equations]=SymmEqu;3499SymmInput[InputType::congruences]=SymmCong;3500SymmInput[InputType::excluded_faces]=SymmExcl;3501Matrix<Integer> GradMat(0,SymmGrad.size());3502GradMat.append(SymmGrad);3503SymmInput[InputType::grading]=GradMat;3504Matrix<Integer> SymmNonNeg(0,SymmGrad.size());3505vector<Integer> NonNeg(SymmGrad.size(),1);3506SymmNonNeg.append(NonNeg);3507SymmInput[InputType::signs]=SymmNonNeg;3508SymmCone=new Cone<Integer>(SymmInput);3509SymmCone->setPolynomial(polynomial);3510SymmCone->setNrCoeffQuasiPol(HSeries.get_nr_coeff_quasipol());3511SymmCone->HSeries.set_period_bounded(HSeries.get_period_bounded());3512SymmCone->setVerbose(verbose);3513ConeProperties SymmToCompute;3514SymmToCompute.set(ConeProperty::SupportHyperplanes);3515SymmToCompute.set(ConeProperty::WeightedEhrhartSeries,ToCompute.test(ConeProperty::HilbertSeries));3516SymmToCompute.set(ConeProperty::VirtualMultiplicity,ToCompute.test(ConeProperty::Multiplicity));3517SymmToCompute.set(ConeProperty::BottomDecomposition,ToCompute.test(ConeProperty::BottomDecomposition));3518SymmCone->compute(SymmToCompute);3519if(SymmCone->isComputed(ConeProperty::WeightedEhrhartSeries)){3520HSeries=SymmCone->getWeightedEhrhartSeries().first;3521is_Computed.set(ConeProperty::HilbertSeries);3522}3523if(SymmCone->isComputed(ConeProperty::VirtualMultiplicity)){3524multiplicity=SymmCone->getVirtualMultiplicity();3525is_Computed.set(ConeProperty::Multiplicity);3526}3527is_Computed.set(ConeProperty::Symmetrize);3528return;35293530#endif35313532}3533353435353536template<typename Integer>3537void integrate(Cone<Integer>& C, const bool do_virt_mult);35383539template<typename Integer>3540void generalizedEhrhartSeries(Cone<Integer>& C);35413542template<typename Integer>3543void Cone<Integer>::compute_integral (ConeProperties& ToCompute){3544if(isComputed(ConeProperty::Integral) || !ToCompute.test(ConeProperty::Integral))3545return;3546if(IntData.getPolynomial()=="")3547throw BadInputException("Polynomial weight missing");3548#ifdef NMZ_COCOA3549if(getRank()==0)3550getIntData().setIntegral(0);3551else3552integrate<Integer>(*this,false);3553is_Computed.set(ConeProperty::Integral);3554#endif3555}35563557template<typename Integer>3558void Cone<Integer>::compute_virt_mult(ConeProperties& ToCompute){3559if(isComputed(ConeProperty::VirtualMultiplicity) || !ToCompute.test(ConeProperty::VirtualMultiplicity))3560return;3561if(IntData.getPolynomial()=="")3562throw BadInputException("Polynomial weight missing");3563#ifdef NMZ_COCOA3564if(getRank()==0)3565getIntData().setVirtualMultiplicity(0);3566else3567integrate<Integer>(*this,true);3568is_Computed.set(ConeProperty::VirtualMultiplicity);3569#endif3570}35713572template<typename Integer>3573void Cone<Integer>::compute_weighted_Ehrhart(ConeProperties& ToCompute){3574if(isComputed(ConeProperty::WeightedEhrhartSeries) || !ToCompute.test(ConeProperty::WeightedEhrhartSeries))3575return;3576if(IntData.getPolynomial()=="")3577throw BadInputException("Polynomial weight missing");3578/* if(getRank()==0)3579throw NotComputableException("WeightedEhrhartSeries not computed in dimenison 0");*/3580#ifdef NMZ_COCOA3581generalizedEhrhartSeries(*this);3582is_Computed.set(ConeProperty::WeightedEhrhartSeries);3583if(getIntData().isWeightedEhrhartQuasiPolynomialComputed()){3584is_Computed.set(ConeProperty::WeightedEhrhartQuasiPolynomial);3585is_Computed.set(ConeProperty::VirtualMultiplicity);3586}3587#endif3588}3589//---------------------------------------------------------------------------3590template<typename Integer>3591bool Cone<Integer>::get_verbose (){3592return verbose;3593}35943595//---------------------------------------------------------------------------3596template<typename Integer>3597void Cone<Integer>::NotComputable (string message){3598if(!default_mode)3599throw NotComputableException(message);3600}36013602//---------------------------------------------------------------------------3603template<typename Integer>3604void Cone<Integer>::check_Gorenstein(ConeProperties& ToCompute){36053606if(!ToCompute.test(ConeProperty::IsGorenstein) || isComputed(ConeProperty::IsGorenstein))3607return;3608if(!isComputed(ConeProperty::SupportHyperplanes))3609recursive_compute(ConeProperty::SupportHyperplanes);3610if(!isComputed(ConeProperty::MaximalSubspace))3611recursive_compute(ConeProperty::MaximalSubspace);36123613if(dim==0){3614Gorenstein=true;3615is_Computed.set(ConeProperty::IsGorenstein);3616GeneratorOfInterior=vector<Integer> (dim,0);3617is_Computed.set(ConeProperty::GeneratorOfInterior);3618return;3619}3620Matrix<Integer> TransfSupps=BasisChangePointed.to_sublattice_dual(SupportHyperplanes);3621assert(TransfSupps.nr_of_rows()>0);3622Gorenstein=false;3623vector<Integer> TransfIntGen = TransfSupps.find_linear_form();3624if(TransfIntGen.size()!=0 && v_scalar_product(TransfIntGen,TransfSupps[0])==1){3625Gorenstein=true;3626GeneratorOfInterior=BasisChangePointed.from_sublattice(TransfIntGen);3627is_Computed.set(ConeProperty::GeneratorOfInterior);3628}3629is_Computed.set(ConeProperty::IsGorenstein);3630}36313632//---------------------------------------------------------------------------3633template<typename Integer>3634template<typename IntegerFC>3635void Cone<Integer>::give_data_of_approximated_cone_to(Full_Cone<IntegerFC>& FC){36363637// *this is the approximatING cone. The support hyperplanes and equations of the approximatED3638// cone are given to the Full_Cone produced from *this so that the superfluous points can3639// bre sorted out as early as possible.36403641assert(is_approximation);3642assert(ApproximatedCone->inhomogeneous || ApproximatedCone->getGradingDenom()==1); // in case we generalize later36433644FC.is_global_approximation=true;3645// FC.is_approximation=true; At present not allowed. Only used for approximation within Full_Cone36463647// We must distinguish zwo cases: Approximated->Grading_Is_Coordinate or it is not36483649// If it is not:3650// The first coordinate in *this is the degree given by the grading3651// in ApproximatedCone. We disregard it by setting the first coordinate3652// of the grading, inequalities and equations to 0, and then have 0 followed3653// by the grading, equations and inequalities resp. of ApproximatedCone.36543655vector<Integer> help_g;3656if(ApproximatedCone->inhomogeneous)3657help_g=ApproximatedCone->Dehomogenization;3658else3659help_g=ApproximatedCone->Grading;36603661if(ApproximatedCone->Grading_Is_Coordinate){3662swap(help_g[0],help_g[ApproximatedCone->GradingCoordinate]);3663BasisChangePointed.convert_to_sublattice_dual_no_div(FC.Subcone_Grading,help_g);3664}3665else{3666vector<Integer> help(help_g.size()+1);3667help[0]=0;3668for(size_t j=0;j<help_g.size();++j)3669help[j+1]=help_g[j];3670BasisChangePointed.convert_to_sublattice_dual_no_div(FC.Subcone_Grading,help);3671}36723673Matrix<Integer> Eq=ApproximatedCone->BasisChangePointed.getEquationsMatrix();3674FC.Subcone_Equations=Matrix<IntegerFC>(Eq.nr_of_rows(),BasisChangePointed.getRank());3675if(ApproximatedCone->Grading_Is_Coordinate){3676Eq.exchange_columns(0,ApproximatedCone->GradingCoordinate);3677BasisChangePointed.convert_to_sublattice_dual(FC.Subcone_Equations,Eq);3678}3679else{3680for(size_t i=0;i<Eq.nr_of_rows();++i){3681vector<Integer> help(Eq.nr_of_columns()+1,0);3682for(size_t j=0;j<Eq.nr_of_columns();++j)3683help[j+1]=Eq[i][j];3684BasisChangePointed.convert_to_sublattice_dual(FC.Subcone_Equations[i], help);3685}3686}36873688Matrix<Integer> Supp=ApproximatedCone->SupportHyperplanes;3689FC.Subcone_Support_Hyperplanes=Matrix<IntegerFC>(Supp.nr_of_rows(),BasisChangePointed.getRank());36903691if(ApproximatedCone->Grading_Is_Coordinate){3692Supp.exchange_columns(0,ApproximatedCone->GradingCoordinate);3693BasisChangePointed.convert_to_sublattice_dual(FC.Subcone_Support_Hyperplanes,Supp);3694}3695else{3696for(size_t i=0;i<Supp.nr_of_rows();++i){3697vector<Integer> help(Supp.nr_of_columns()+1,0);3698for(size_t j=0;j<Supp.nr_of_columns();++j)3699help[j+1]=Supp[i][j];3700BasisChangePointed.convert_to_sublattice_dual(FC.Subcone_Support_Hyperplanes[i], help);3701}3702}3703}37043705//---------------------------------------------------------------------------3706template<typename Integer>3707void Cone<Integer>::try_approximation_or_projection(ConeProperties& ToCompute){37083709if((ToCompute.test(ConeProperty::NoProjection) && !ToCompute.test(ConeProperty::Approximate))3710|| ToCompute.test(ConeProperty::DualMode) || ToCompute.test(ConeProperty::PrimalMode)3711)3712return;37133714if(ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid))3715return;37163717if(!inhomogeneous && ( !ToCompute.test(ConeProperty::Deg1Elements)3718|| ToCompute.test(ConeProperty::HilbertBasis)3719|| ToCompute.test(ConeProperty::HilbertSeries)3720)3721)3722return;37233724if(inhomogeneous && !ToCompute.test(ConeProperty::HilbertBasis) )3725return;37263727bool is_parallelotope=false;3728if(!ToCompute.test(ConeProperty::Approximate))3729is_parallelotope=check_parallelotope();3730if(verbose && is_parallelotope)3731verboseOutput() << "Polyhedron is parallelotope" << endl;37323733if(is_parallelotope){3734SupportHyperplanes.remove_row(Dehomogenization);3735is_Computed.set(ConeProperty::SupportHyperplanes);3736is_Computed.set(ConeProperty::MaximalSubspace);3737is_Computed.set(ConeProperty::Sublattice);3738pointed=true;3739is_Computed.set(ConeProperty::IsPointed);3740}37413742ConeProperties NeededHere;3743NeededHere.set(ConeProperty::SupportHyperplanes);3744NeededHere.set(ConeProperty::Sublattice);3745NeededHere.set(ConeProperty::MaximalSubspace);3746if(!inhomogeneous)3747NeededHere.set(ConeProperty::Grading);3748recursive_compute(NeededHere);37493750if(!is_parallelotope && !ToCompute.test(ConeProperty::Approximate)){ // we try again3751is_parallelotope=check_parallelotope();3752if(is_parallelotope){3753SupportHyperplanes.remove_row(Dehomogenization);3754is_Computed.set(ConeProperty::SupportHyperplanes);3755is_Computed.set(ConeProperty::MaximalSubspace);3756is_Computed.set(ConeProperty::Sublattice);3757pointed=true;3758is_Computed.set(ConeProperty::IsPointed);3759}3760}37613762// cout << "PPPPP " << is_parallelotope << endl;37633764if(!inhomogeneous && !isComputed(ConeProperty::Grading))3765return;37663767if(!inhomogeneous && ToCompute.test(ConeProperty::Approximate) && GradingDenom!=1)3768return;37693770if(!pointed || BasisChangePointed.getRank()==0)3771return;37723773if(inhomogeneous){3774for(size_t i=0;i<Generators.nr_of_rows();++i){3775if(v_scalar_product(Generators[i],Dehomogenization)==0){3776if(ToCompute.test(ConeProperty::Approximate) || ToCompute.test(ConeProperty::Projection))3777throw NotComputableException("Approximation or Projection not applicable to unbounded polyhedra");3778else3779return;3780}3781}3782}37833784if(inhomogeneous){ // exclude that dehoogenization has a gcd > 13785vector<Integer> test_dehom=BasisChange.to_sublattice_dual_no_div(Dehomogenization);3786if(v_make_prime(test_dehom)!=1)3787return;3788}37893790// ****************************************************************3791//3792// NOTE: THE FIRST COORDINATE IS (OR WILL BE MADE) THE GRADING !!!!3793//3794// ****************************************************************37953796vector<Integer> GradForApprox;3797if(!inhomogeneous)3798GradForApprox=Grading;3799else{3800GradForApprox=Dehomogenization;3801GradingDenom=1;3802}38033804Grading_Is_Coordinate=false;3805size_t nr_nonzero=0;3806for(size_t i=0;i<dim;++i){3807if(GradForApprox[i]!=0){3808nr_nonzero++;3809GradingCoordinate=i;3810}3811}3812if(nr_nonzero==1){3813if(GradForApprox[GradingCoordinate]==1)3814Grading_Is_Coordinate=true;3815}38163817Matrix<Integer> GradGen;3818if(Grading_Is_Coordinate){3819if(!ToCompute.test(ConeProperty::Approximate)){3820GradGen=Generators;3821GradGen.exchange_columns(0,GradingCoordinate); // we swap it into the first coordinate3822}3823else{ // we swap the grading into the first coordinate and approximate3824GradGen.resize(0,dim);3825for(size_t i=0;i<Generators.nr_of_rows();++i){3826vector<Integer> gg=Generators[i];3827swap(gg[0],gg[GradingCoordinate]);3828list<vector<Integer> > approx;3829approx_simplex(gg,approx,1);3830GradGen.append(Matrix<Integer>(approx));3831}3832}3833}3834else{ // to avoid coordinate trabnsformations, we prepend the degree as the first coordinate3835GradGen.resize(0,dim+1);3836for(size_t i=0;i<Generators.nr_of_rows();++i){3837vector<Integer> gg(dim+1);3838for(size_t j=0;j<dim;++j)3839gg[j+1]=Generators[i][j];3840gg[0]=v_scalar_product(Generators[i],GradForApprox);3841// cout << gg;3842if(ToCompute.test(ConeProperty::Approximate)){3843list<vector<Integer> > approx;3844approx_simplex(gg,approx,1);3845GradGen.append(Matrix<Integer>(approx));3846}3847else3848GradGen.append(gg);3849}3850}38513852Matrix<Integer> Raw(0,GradGen.nr_of_columns()); // result is returned in this matrix38533854if(ToCompute.test(ConeProperty::Approximate)){3855if(verbose)3856verboseOutput() << "Computing lattice points by approximation" << endl;3857Cone<Integer> HelperCone(InputType::cone,GradGen);3858HelperCone. ApproximatedCone=&(*this); // we will pass this infornation to the Full_Cone that computes the lattice points.3859HelperCone.is_approximation=true; // It allows us to discard points outside *this as quickly as possible3860HelperCone.compute(ConeProperty::Deg1Elements,ConeProperty::PrimalMode);3861Raw=HelperCone.getDeg1ElementsMatrix();3862}3863else{3864if(verbose)3865verboseOutput() << "Computing lattice points by project-and-lift" << endl;3866Matrix<Integer> Supps, Equs;3867if(Grading_Is_Coordinate){3868Supps=getSupportHyperplanesMatrix();3869Supps.exchange_columns(0,GradingCoordinate);3870Equs=BasisChange.getEquationsMatrix();3871Equs.exchange_columns(0,GradingCoordinate);3872}3873else{3874vector<vector<Integer> > SuppHelp=getSupportHyperplanes();3875insert_column<Integer>(SuppHelp,0,0);3876Supps=Matrix<Integer>(SuppHelp);3877vector<vector<Integer> > EqusHelp=BasisChange.getEquations();3878if(EqusHelp.size()>0){3879insert_column<Integer>(EqusHelp,0,0);3880Equs=Matrix<Integer>(EqusHelp);3881}3882else3883Equs.resize(0,dim+1);3884vector<Integer> ExtraEqu(Equs.nr_of_columns());3885ExtraEqu[0]=-1;3886for(size_t i=0;i<Grading.size();++i)3887ExtraEqu[i+1]=Grading[i];3888Equs.append(ExtraEqu);3889}3890Supps.append(Equs); // we must add the equations as pairs of inequalities3891Equs.scalar_multiplication(-1);3892Supps.append(Equs);3893project_and_lift(Raw, GradGen,Supps,ToCompute.test(ConeProperty::ProjectionFloat));3894}38953896HilbertBasis=Matrix<Integer>(0,dim);3897Deg1Elements=Matrix<Integer>(0,dim);3898ModuleGenerators=Matrix<Integer>(0,dim);38993900if(Grading_Is_Coordinate)3901Raw.exchange_columns(0,GradingCoordinate);39023903Matrix<Integer> Cong=BasisChange.getCongruences();39043905if(Grading_Is_Coordinate && Cong.nr_of_rows()==0){3906if(inhomogeneous)3907ModuleGenerators.swap(Raw);3908else3909Deg1Elements.swap(Raw);3910}3911else{3912for(size_t i=0;i<Raw.nr_of_rows();++i){3913vector<Integer> rr;3914if(Grading_Is_Coordinate){3915swap(rr,Raw[i]);3916}3917else{3918rr.resize(dim); // remove the prepended grading3919for(size_t j=0;j<dim;++j)3920rr[j]=Raw[i][j+1];3921}3922bool not_in=false;3923for(size_t k=0;k<Cong.nr_of_rows();++k) {3924if(v_scalar_product_vectors_unequal_lungth(rr,Cong[k]) % Cong[k][dim] !=0) // not in original lattice3925not_in=true;3926break;3927}3928if(not_in)3929continue;3930if(inhomogeneous){3931ModuleGenerators.append(rr);3932}3933else3934Deg1Elements.append(rr);3935}3936}39373938setWeights();3939if(inhomogeneous)3940ModuleGenerators.sort_by_weights(WeightsGrad,GradAbs);3941else3942Deg1Elements.sort_by_weights(WeightsGrad,GradAbs);39433944if(inhomogeneous){3945is_Computed.set(ConeProperty::HilbertBasis);3946is_Computed.set(ConeProperty::ModuleGenerators);3947module_rank= ModuleGenerators.nr_of_rows();3948is_Computed.set(ConeProperty::ModuleRank);3949recession_rank=0;3950is_Computed.set(ConeProperty::RecessionRank);3951if(isComputed(ConeProperty::Grading) && module_rank>0){3952multiplicity=module_rank; // of the recession cone;3953is_Computed.set(ConeProperty::Multiplicity);3954if(ToCompute.test(ConeProperty::HilbertSeries)){3955vector<num_t> hv(1);3956long raw_shift=convertTo<long>(v_scalar_product(Grading,ModuleGenerators[0]));3957for(size_t i=0;i<ModuleGenerators.nr_of_rows();++i){3958long deg = convertTo<long>(v_scalar_product(Grading,ModuleGenerators[i]));3959raw_shift=min(raw_shift,deg);3960}3961for(size_t i=0;i<ModuleGenerators.nr_of_rows();++i){3962size_t deg = convertTo<long>(v_scalar_product(Grading,ModuleGenerators[i]))-raw_shift;3963if(deg+1>hv.size())3964hv.resize(deg+1);3965hv[deg]++;3966}3967HSeries.add(hv,vector<denom_t>());3968HSeries.setShift(raw_shift);3969HSeries.adjustShift();3970HSeries.simplify();3971is_Computed.set(ConeProperty::HilbertSeries);3972}3973}39743975}3976else3977is_Computed.set(ConeProperty::Deg1Elements);39783979is_Computed.set(ConeProperty::Approximate);39803981return;3982}39833984//---------------------------------------------------------------------------3985template<typename Integer>3986void Cone<Integer>::project_and_lift(Matrix<Integer>& Deg1, const Matrix<Integer>& Gens, Matrix<Integer>& Supps, bool float_projection){39873988// if(verbose)3989// verboseOutput() << "Starting projection" << endl;39903991// vector<boost::dynamic_bitset<> > Pair;3992// vector<boost::dynamic_bitset<> > ParaInPair;3993bool is_parallelotope=(Pair.size()>0);39943995vector< boost::dynamic_bitset<> > Ind;39963997if(!is_parallelotope){3998Ind=vector< boost::dynamic_bitset<> > (Supps.nr_of_rows(), boost::dynamic_bitset<> (Gens.nr_of_rows()));3999for(size_t i=0;i<Supps.nr_of_rows();++i)4000for(size_t j=0;j<Gens.nr_of_rows();++j)4001if(v_scalar_product(Supps[i],Gens[j])==0)4002Ind[i][j]=true;4003}40044005size_t rank=BasisChangePointed.getRank();40064007if(float_projection){4008// Matrix<nmz_float> GensFloat;4009// convert(GensFloat,Gens);4010Matrix<nmz_float> SuppsFloat;4011convert(SuppsFloat,Supps);4012vector<Integer> Dummy;4013// project_and_lift_inner<nmz_float,Integer>(Deg1, SuppsFloat,Ind, GradingDenom,rank,verbose,true,Dummy);4014ProjectAndLift<nmz_float,Integer> PL;4015if(!is_parallelotope)4016PL=ProjectAndLift<nmz_float,Integer>(SuppsFloat,Ind,rank);4017else4018PL=ProjectAndLift<nmz_float,Integer>(SuppsFloat,Pair,ParaInPair,rank);4019PL.set_grading_denom(GradingDenom);4020PL.set_verbose(verbose);4021PL.compute();4022PL.put_eg1Points_into(Deg1);4023}4024else{4025if (change_integer_type) {4026Matrix<MachineInteger> Deg1MI(0,Deg1.nr_of_columns());4027// Matrix<MachineInteger> GensMI;4028Matrix<MachineInteger> SuppsMI;4029try {4030// convert(GensMI,Gens);4031convert(SuppsMI,Supps);4032MachineInteger GDMI=convertTo<MachineInteger>(GradingDenom);4033vector<MachineInteger> Dummy;4034// project_and_lift_inner<MachineInteger>(Deg1MI,SuppsMI,Ind, GDMI,rank,verbose,true,Dummy);4035ProjectAndLift<MachineInteger,MachineInteger> PL;4036if(!is_parallelotope)4037PL=ProjectAndLift<MachineInteger,MachineInteger>(SuppsMI,Ind,rank);4038else4039PL=ProjectAndLift<MachineInteger,MachineInteger>(SuppsMI,Pair,ParaInPair,rank);4040PL.set_grading_denom(GDMI);4041PL.set_verbose(verbose);4042PL.compute();4043PL.put_eg1Points_into(Deg1MI);4044} catch(const ArithmeticException& e) {4045if (verbose) {4046verboseOutput() << e.what() << endl;4047verboseOutput() << "Restarting with a bigger type." << endl;4048}4049change_integer_type = false;4050}4051if(change_integer_type){4052convert(Deg1,Deg1MI);4053}4054}40554056if (!change_integer_type) {4057vector<Integer> Dummy;4058// project_and_lift_inner<Integer>(Deg1,Supps,Ind,GradingDenom,rank,verbose,true,Dummy);4059ProjectAndLift<Integer,Integer> PL;4060if(!is_parallelotope)4061PL=ProjectAndLift<Integer,Integer>(Supps,Ind,rank);4062else4063PL=ProjectAndLift<Integer,Integer>(Supps,Pair,ParaInPair,rank);4064PL.set_grading_denom(GradingDenom);4065PL.set_verbose(verbose);4066PL.compute();4067PL.put_eg1Points_into(Deg1);4068}4069}40704071is_Computed.set(ConeProperty::Projection);4072if(float_projection)4073is_Computed.set(ConeProperty::ProjectionFloat);40744075if(verbose)4076verboseOutput() << "Project-and-lift complete" << endl <<4077"------------------------------------------------------------" << endl;40784079}40804081//---------------------------------------------------------------------------4082template<typename Integer>4083bool Cone<Integer>::check_parallelotope(){40844085vector<Integer> Grad; // copy of Grading or Dehomogenization40864087if(inhomogeneous){4088Grad=Dehomogenization;4089}4090else{4091if(!isComputed(ConeProperty::Grading))4092return false;4093Grad=Grading;4094}40954096Grading_Is_Coordinate=false;4097size_t nr_nonzero=0;4098for(size_t i=0;i<Grad.size();++i){4099if(Grad[i]!=0){4100nr_nonzero++;4101GradingCoordinate=i;4102}4103}4104if(nr_nonzero==1){4105if(Grad[GradingCoordinate]==1)4106Grading_Is_Coordinate=true;4107}4108if(!Grading_Is_Coordinate)4109return false;41104111Matrix<Integer> Supps(SupportHyperplanes);4112if(inhomogeneous)4113Supps.remove_row(Grad);41144115size_t dim=Supps.nr_of_columns()-1; //affine dimension4116if(Supps.nr_of_rows()!=2*dim)4117return false;4118Pair.resize(2*dim);4119ParaInPair.resize(2*dim);4120for(size_t i=0;i<2*dim;++i){4121Pair[i].resize(dim);4122Pair[i].reset();4123ParaInPair[i].resize(dim);4124ParaInPair[i].reset();4125}41264127vector<bool> done(2*dim);4128Matrix<Integer> M2(2,dim+1), M3(3,dim+1);4129M3[2]=Grad;4130size_t pair_counter=0;41314132vector<key_t> Supp_1; // to find antipodal vertices4133vector<key_t> Supp_2;41344135for(size_t i=0;i<2*dim;++i){4136if(done[i])4137continue;4138bool parallel_found=false;4139M2[0]=Supps[i];4140M3[0]=Supps[i];4141size_t j=i+1;4142for(;j<2*dim;++j){4143if(done[j]) continue;4144M2[1]=Supps[j];4145if(M2.rank()<2)4146continue;4147M3[1]=Supps[j];4148if(M3.rank()==3)4149continue;4150else{4151parallel_found=true;4152done[j]=true;4153break;4154}4155}4156if(!parallel_found)4157return false;4158Supp_1.push_back(i);4159Supp_2.push_back(j);4160Pair[i][pair_counter]=true;4161Pair[j][pair_counter]=true;4162ParaInPair[j][pair_counter]=true;4163pair_counter++;4164}41654166Matrix<Integer> v1=Supps.submatrix(Supp_1).kernel(); // opposite vertices4167Matrix<Integer> v2=Supps.submatrix(Supp_2).kernel();4168Integer MinusOne=-1;4169if(v_scalar_product(v1[0],Grad)==0)4170return false;4171if(v_scalar_product(v2[0],Grad)==0)4172return false;4173if(v_scalar_product(v1[0],Grad)<0)4174v_scalar_multiplication(v1[0],MinusOne);4175if(v_scalar_product(v2[0],Grad)<0)4176v_scalar_multiplication(v2[0],MinusOne);41774178/* cout << Supp_1;4179cout << Supp_2;4180v1.pretty_print(cout);4181v2.pretty_print(cout);4182cout << "==============" << endl;4183Supps.pretty_print(cout);4184cout << "==============" << endl;*/4185if(v1.nr_of_rows()!=1 || v2.nr_of_rows()!=1)4186return false;4187for(size_t i=0;i<Supp_1.size();++i){4188// cout << "i " << i << " " << v_scalar_product(Supps[Supp_1[i]],v2[0]) << endl;4189if(!v_scalar_product_positive(Supps[Supp_1[i]],v2[0]))4190return false;4191}4192for(size_t i=0;i<Supp_2.size();++i){4193// cout << "i " << i << " " << v_scalar_product(Supps[Supp_2[i]],v1[0]) << endl;4194if(!v_scalar_product_positive(Supps[Supp_2[i]],v1[0]))4195return false;4196}41974198// we have found opposite vertices41994200return true;4201}4202420342044205} // end namespace libnormaliz420642074208