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#ifdef NMZ_MIC_OFFLOAD24#pragma offload_attribute (push, target(mic))25#endif2627#include <stdlib.h>28#include <math.h>2930#include <iostream>31//#include <sstream>32#include <algorithm>33#include <queue>3435#include "libnormaliz/bottom.h"36#include "libnormaliz/libnormaliz.h"37#include "libnormaliz/vector_operations.h"38#include "libnormaliz/integer.h"39//#include "libnormaliz/my_omp.h"40#include "libnormaliz/full_cone.h"4142#ifdef NMZ_SCIP43#include <scip/scip.h>44#include <scip/scipdefplugins.h> //TODO needed?45#include <scip/cons_linear.h>46#else47class SCIP;48#endif // NMZ_SCIP495051namespace libnormaliz {52using namespace std;5354long ScipBound = 1000000;5556template<typename Integer>57vector<Integer> opt_sol(SCIP* scip, const Matrix<Integer>& gens, const Matrix<Integer>& SuppHyp,58const vector<Integer>& grading);5960template<typename Integer>61bool bottom_points_inner(SCIP* scip, Matrix<Integer>& gens, list< vector<Integer> >& local_new_points,62vector< Matrix<Integer> >& local_q_gens, size_t& stellar_det_sum);6364// kept here for simplicity:6566double convert_to_double(mpz_class a) {67return a.get_d();68}6970double convert_to_double(long a) {71return a;72}7374double convert_to_double(long long a) {75return a;76}7778template<typename Integer>79void bottom_points(list< vector<Integer> >& new_points, const Matrix<Integer>& gens,Integer VolumeBound) {8081/* gens.pretty_print(cout);82cout << "=======================" << endl;8384gens.transpose().pretty_print(cout);85cout << "=======================" << endl;*/86Integer volume;87// int dim = gens[0].size();88Matrix<Integer> Support_Hyperplanes = gens.invert(volume);8990vector<Integer> grading; // = grading_;91if (grading.empty()) grading = gens.find_linear_form();92// cout << grading;9394list<vector<Integer> > bottom_candidates;95bottom_candidates.splice(bottom_candidates.begin(), new_points);96//Matrix<Integer>(bottom_candidates).pretty_print(cout);97#ifdef NMZ_SCIP98if(verbose && nmz_scip){99verboseOutput() << "Computing bottom points using SCIP/projection" << endl;100}101#else102if(verbose){103verboseOutput() << "Computing bbottom points using projection " << endl;104}105#endif106107if (verbose){108verboseOutput() << "simplex volume " << volume << endl;109}110111//---------------------------- begin stellar subdivision -------------------112113size_t stellar_det_sum = 0;114vector< Matrix<Integer> > q_gens; // for successive stellar subdivision115q_gens.push_back(gens);116int level = 0; // level of subdivision117118#ifndef NCATCH119std::exception_ptr tmp_exception;120#endif121bool skip_remaining = false;122#pragma omp parallel // reduction(+:stellar_det_sum)123{124#ifndef NCATCH125try {126#endif127128// setup scip enviorenment129SCIP* scip = NULL;130#ifdef NMZ_SCIP131132SCIPcreate(& scip);133SCIPincludeDefaultPlugins(scip);134// SCIPsetMessagehdlr(scip,NULL); // deactivate scip output135136SCIPsetIntParam(scip, "display/verblevel", 0);137138// modify timing for better parallelization139// SCIPsetBoolParam(scip, "timing/enabled", FALSE);140SCIPsetBoolParam(scip, "timing/statistictiming", FALSE);141SCIPsetBoolParam(scip, "timing/rareclockcheck", TRUE);142143144SCIPsetIntParam(scip, "heuristics/shiftandpropagate/freq", -1);145SCIPsetIntParam(scip, "branching/pscost/priority", 1000000);146// SCIPsetIntParam(scip, "nodeselection/uct/stdpriority", 1000000);147#endif // NMZ_SCIP148149vector< Matrix<Integer> > local_q_gens;150list< vector<Integer> > local_new_points;151152153while (!q_gens.empty()) {154155if(skip_remaining) break;156if(verbose){157#pragma omp single158verboseOutput() << q_gens.size() << " simplices on level " << level++ << endl;159}160161#pragma omp for schedule(static)162for (size_t i = 0; i < q_gens.size(); ++i) {163164if(skip_remaining) continue;165166#ifndef NCATCH167try {168#endif169bottom_points_inner(scip, q_gens[i], local_new_points,local_q_gens,stellar_det_sum);170#ifndef NCATCH171} catch(const std::exception& ) {172tmp_exception = std::current_exception();173skip_remaining = true;174#pragma omp flush(skip_remaining)175}176#endif177}178179#pragma omp single180{181q_gens.clear();182}183#pragma omp critical (LOCALQGENS)184{185q_gens.insert(q_gens.end(),local_q_gens.begin(),local_q_gens.end());186}187local_q_gens.clear();188#pragma omp barrier189}190191#pragma omp critical (LOCALNEWPOINTS)192{193new_points.splice(new_points.end(), local_new_points, local_new_points.begin(), local_new_points.end());194}195196#ifdef NMZ_SCIP197SCIPfree(& scip);198#endif // NMZ_SCIP199200#ifndef NCATCH201} catch(const std::exception& ) {202tmp_exception = std::current_exception();203skip_remaining = true;204#pragma omp flush(skip_remaining)205}206#endif207} // end parallel208209//---------------------------- end stellar subdivision -----------------------210211#ifndef NCATCH212if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);213#endif214215216//cout << new_points.size() << " new points accumulated" << endl;217new_points.sort();218new_points.unique();219if(verbose){220verboseOutput() << new_points.size() << " bottom points accumulated in total." << endl;221verboseOutput() << "The sum of determinants of the stellar subdivision is " << stellar_det_sum << endl;222}223}224225template<typename Integer>226bool bottom_points_inner(SCIP* scip, Matrix<Integer>& gens, list< vector<Integer> >& local_new_points,227vector< Matrix<Integer> >& local_q_gens, size_t& stellar_det_sum) {228229INTERRUPT_COMPUTATION_BY_EXCEPTION230231vector<Integer> grading = gens.find_linear_form();232Integer volume;233int dim = gens[0].size();234Matrix<Integer> Support_Hyperplanes = gens.invert(volume);235236if (volume < ScipBound) {237#pragma omp atomic238stellar_det_sum += convertTo<long long>(volume);239return false; // not subdivided240}241242// try st4ellar subdivision243Support_Hyperplanes = Support_Hyperplanes.transpose();244Support_Hyperplanes.make_prime();245vector<Integer> new_point;246247#ifdef NMZ_SCIP248// set time limit according to volume249if(nmz_scip){250double time_limit = pow(log10(convert_to_double(volume)),2);251SCIPsetRealParam(scip, "limits/time", time_limit);252// call scip253new_point = opt_sol(scip, gens, Support_Hyperplanes, grading);254if(new_point.empty() && verbose)255verboseOutput() << "No bottom point found by SCIP. Trying projection." << endl;256}257#endif // NMZ_SCIP258259if(new_point.empty()){260list<vector<Integer> > Dummy;261new_point = gens.optimal_subdivision_point(); // projection method262}263264if ( !new_point.empty() ){265266//if (find(local_new_points.begin(), local_new_points.end(),new_point) == local_new_points.end())267local_new_points.push_back(new_point);268Matrix<Integer> stellar_gens(gens);269270int nr_hyps = 0;271for (int i=0; i<dim; ++i) {272if (v_scalar_product(Support_Hyperplanes[i], new_point) != 0) {273stellar_gens[i] = new_point;274local_q_gens.push_back(stellar_gens);275276stellar_gens[i] = gens[i];277}278else nr_hyps++;279}280//#pragma omp critical(VERBOSE)281//cout << new_point << " liegt in " << nr_hyps <<" hyperebenen" << endl;282return true; // subdivided283}284else{ // could not subdivided285#pragma omp atomic286stellar_det_sum += convertTo<long long>(volume);287return false;288}289}290291// returns -1 if maximum is negative292template<typename Integer>293double max_in_col(const Matrix<Integer>& M, size_t j) {294Integer max = -1;295for (size_t i=0; i<M.nr_of_rows(); ++i) {296if (M[i][j] > max) max = M[i][j];297}298return convert_to_double(max);299}300301302// returns 1 if minimum is positive303template<typename Integer>304double min_in_col(const Matrix<Integer>& M, size_t j) {305Integer min = 1;306for (size_t i=0; i<M.nr_of_rows(); ++i) {307if (M[i][j] < min) min = M[i][j];308}309return convert_to_double(min);310}311312313#ifdef NMZ_SCIP314template<typename Integer>315vector<Integer> opt_sol(SCIP* scip,316const Matrix<Integer>& gens, const Matrix<Integer>& SuppHyp,317const vector<Integer>& grading) {318319INTERRUPT_COMPUTATION_BY_EXCEPTION320321double upper_bound = convert_to_double(v_scalar_product(grading,gens[0]))-0.5;322// TODO make the test more strict323long dim = grading.size();324// create variables325SCIP_VAR** x = new SCIP_VAR*[dim];326char name[SCIP_MAXSTRLEN];327SCIPcreateProbBasic(scip, "extra_points");328for (long i=0; i<dim; i++) {329(void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "x_%d", i);330// SCIPcreateVarBasic(scip, &x[i], name, -SCIPinfinity(scip), SCIPinfinity(scip),331// convert_to_double(grading[i]), SCIP_VARTYPE_INTEGER);332333// min_in_col and max_in_col already give good bounds if all signs are positive or negative334// no constraint needed335SCIPcreateVarBasic(scip, &x[i], name, min_in_col(gens,i), max_in_col(gens, i),336convert_to_double(grading[i]), SCIP_VARTYPE_INTEGER);337SCIPaddVar(scip, x[i]);338}339340// create constraints341// vector< vector<Integer> > SuppHyp(MyCone.getSupportHyperplanes());342double* ineq = new double[dim];343long nrSuppHyp = SuppHyp.nr_of_rows();344for( long i = 0; i < nrSuppHyp; ++i )345{346SCIP_CONS* cons;347for (long j=0; j<dim; j++)348ineq[j] = convert_to_double(SuppHyp[i][j]);349(void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ineq_%d", i);350SCIPcreateConsBasicLinear(scip, &cons, name, dim, x, ineq, 0.0, SCIPinfinity(scip));351SCIPaddCons(scip, cons);352SCIPreleaseCons(scip, &cons);353}354355SCIP_CONS* cons;356// setup non-zero constraints357// if all extreme rays have the same sign in one dimension, add the x_i>=1 or x_i<=-1 constraint358359for (long i=0; i<dim; i++){360double min = min_in_col(gens,i);361double max = max_in_col(gens,i);362if (min*max>0){363break;364}365if (i==dim-1){366//cout << "no same sign. using bound disjunction" << endl;367// set bound disjunction368369SCIP_VAR** double_x = new SCIP_VAR*[2*dim];370SCIP_BOUNDTYPE* boundtypes = new SCIP_BOUNDTYPE[2*dim];371SCIP_Real* bounds = new SCIP_Real[2*dim];372for (long i=0; i<dim;i++) {373double_x[2*i] = x[i];374double_x[2*i+1] = x[i];375boundtypes[2*i]= SCIP_BOUNDTYPE_LOWER;376boundtypes[2*i+1] = SCIP_BOUNDTYPE_UPPER;377bounds[2*i] = 1.0;378bounds[2*i+1] = -1.0;379}380SCIPcreateConsBasicBounddisjunction (scip, &cons,"non_zero",2*dim,double_x,boundtypes,bounds);381SCIPaddCons(scip, cons);382SCIPreleaseCons(scip, &cons);383384/*385// this type of constraints procedures numerical problems:386for (long j=0; j<dim; j++)387ineq[j] = convert_to_double(grading[j]);388SCIPcreateConsBasicLinear(scip, &cons, "non_zero", dim, x, ineq, 1.0, SCIPinfinity(scip));389*/390}391}392393// set objective limit, feasible solution has to have a better objective value394SCIPsetObjlimit(scip,upper_bound);395396397// give original generators as hints to scip398SCIP_SOL* input_sol;399SCIP_Bool stored;400SCIPcreateOrigSol(scip, &input_sol, NULL);401for (long i=0; i<dim; i++) {402for (long j=0; j<dim; j++) {403SCIPsetSolVal(scip, input_sol, x[j], convert_to_double(gens[i][j]));404}405//SCIPprintSol(scip, input_sol, NULL, TRUE);406SCIPaddSol(scip, input_sol, &stored);407}408SCIPfreeSol(scip, &input_sol);409410//SCIPinfoMessage(scip, NULL, "Original problem:\n");411//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);412//SCIPinfoMessage(scip, NULL, "\nSolving...\n");413414//#ifndef NDEBUG_BLA415//FILE* file = fopen("mostrecent.lp","w");416//assert (file != NULL);417//SCIPprintOrigProblem(scip, file, "lp", FALSE);418//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);419//fclose(file);420//#endif421422// set numerics423Integer maxabs = v_max_abs(grading);424double epsilon = max(1e-20,min(1/(convert_to_double(maxabs)*10),1e-10));425//cout << "epsilon is in region " << log10(epsilon) << endl;426double feastol = max(1e-17,epsilon*10);427SCIPsetRealParam(scip, "numerics/epsilon", epsilon);428SCIPsetRealParam(scip, "numerics/feastol", feastol);429430SCIPsolve(scip);431//SCIPprintStatistics(scip, NULL);432vector<Integer> sol_vec(dim);433if(SCIPgetStatus(scip) == SCIP_STATUS_TIMELIMIT && verbose) verboseOutput() << "time limit reached!" << endl;434if( SCIPgetNLimSolsFound(scip) > 0 ) // solutions respecting objective limit (ie not our input solutions)435{436SCIP_SOL* sol = SCIPgetBestSol(scip);437//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);438//SCIPprintSol(scip, sol, NULL, FALSE) ;439440for (int i=0;i<dim;i++) {441convert(sol_vec[i], SCIPconvertRealToLongint(scip,SCIPgetSolVal(scip,sol,x[i])));442}443444445if(v_scalar_product(grading,sol_vec)>upper_bound){446//Integer sc = v_scalar_product(sol_vec,grading);447if(verbose){448#pragma omp critical(VERBOSE)449{450verboseOutput() << "Solution does not respect upper bound!" << endl;451//cout << "upper bound: " << upper_bound << endl;452//cout << "grading: " << grading;453//cout << "hyperplanes:" << endl;454//SuppHyp.pretty_print(cout);455//cout << "generators:" << endl;456//gens.pretty_print(cout);457//cout << sc << " | solution " << sol_vec;458//cout << "epsilon: " << epsilon << endl;459//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);460//SCIPprintSol(scip, sol, NULL, FALSE) ;461//cout << "write files... " << endl;462//FILE* file = fopen("mostrecent.lp","w");463//assert (file != NULL);464//SCIPprintOrigProblem(scip, file, "lp", FALSE);465//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);466//fclose(file);467//assert(v_scalar_product(grading,sol_vec)<=upper_bound);468469}470}471return vector<Integer>();472}473474475for (int i=0;i<nrSuppHyp;i++) {476if((v_scalar_product(SuppHyp[i],sol_vec))<0) {477//Integer sc = v_scalar_product(sol_vec,grading);478if(verbose){479#pragma omp critical(VERBOSE)480{481verboseOutput() << "Solution does not respect hyperplanes!" << endl;482//cout << "the hyperplane: " << SuppHyp[i];483//cout << "grading: " << grading;484//cout << "hyperplanes:" << endl;485//SuppHyp.pretty_print(cout);486//cout << "generators:" << endl;487//gens.pretty_print(cout);488//cout << sc << " | solution " << sol_vec;489//cout << "epsilon: " << epsilon << endl;490//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);491//SCIPprintSol(scip, sol, NULL, FALSE) ;492//cout << "write files... " << endl;493//FILE* file = fopen("mostrecent.lp","w");494//assert (file != NULL);495//SCIPprintOrigProblem(scip, file, "lp", FALSE);496//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);497//fclose(file);498//assert((v_scalar_product(SuppHyp[i],sol_vec))>=0);499500}501}502return vector<Integer>();503}504}505if((v_scalar_product(grading,sol_vec))<1) {506//Integer sc = v_scalar_product(sol_vec,grading);507if (verbose){508#pragma omp critical(VERBOSE)509{510verboseOutput() << "Solution does not respect the nonzero condition!" << endl;511/*cout << "grading: " << grading;512cout << "hyperplanes:" << endl;513SuppHyp.pretty_print(cout);514cout << "generators:" << endl;515gens.pretty_print(cout);516cout << sc << " | solution " << sol_vec;517cout << "epsilon: " << epsilon << endl;518SCIPprintOrigProblem(scip, NULL, NULL, FALSE);519SCIPprintSol(scip, sol, NULL, FALSE) ;520cout << "write files... " << endl;521FILE* file = fopen("mostrecent.lp","w");522assert (file != NULL);523SCIPprintOrigProblem(scip, file, "lp", FALSE);524SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);525fclose(file);526assert((v_scalar_product(grading,sol_vec))>=1);*/527528}529}530return vector<Integer>();531}532/*assert(v_scalar_product(grading,sol_vec)<=upper_bound);533for (int i=0;i<nrSuppHyp;i++) assert((v_scalar_product(SuppHyp[i],sol_vec))>=0);534assert((v_scalar_product(grading,sol_vec))>=1);*/535//Integer sc = v_scalar_product(sol_vec,grading);536//#pragma omp critical(VERBOSE)537//cout << sc << " | solution " << sol_vec;538539} else {540return vector<Integer>();541}542543for (int j=0;j<dim;j++) SCIPreleaseVar(scip, &x[j]);544SCIPfreeProb(scip);545return sol_vec;546}547#endif // NMZ_SCIP548549#ifndef NMZ_MIC_OFFLOAD //offload with long is not supported550template void bottom_points(list< vector<long> >& new_points, const Matrix<long>& gens,551long VolumeBound);552#endif // NMZ_MIC_OFFLOAD553template void bottom_points(list< vector<long long> >& new_points, const Matrix<long long>& gens,554long long VolumeBound);555template void bottom_points(list< vector<mpz_class> >& new_points, const Matrix<mpz_class>& gens,556mpz_class VolumeBound);557558} // namespace559560#ifdef NMZ_MIC_OFFLOAD561#pragma offload_attribute (pop)562#endif563564