Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563644 views
1
/*
2
* Normaliz
3
* Copyright (C) 2007-2014 Winfried Bruns, Bogdan Ichim, Christof Soeger
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, either version 3 of the License, or
7
* (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
*
17
* As an exception, when this program is distributed through (i) the App Store
18
* by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or (iii) Google Play
19
* by Google Inc., then that store may impose any digital rights management,
20
* device limits and/or redistribution restrictions that are required by its
21
* terms of service.
22
*/
23
24
#ifdef NMZ_MIC_OFFLOAD
25
#pragma offload_attribute (push, target(mic))
26
#endif
27
28
#include <stdlib.h>
29
#include <math.h>
30
31
#include <iostream>
32
//#include <sstream>
33
#include <algorithm>
34
#include <queue>
35
36
#include "libnormaliz/bottom.h"
37
#include "libnormaliz/libnormaliz.h"
38
#include "libnormaliz/vector_operations.h"
39
#include "libnormaliz/integer.h"
40
//#include "libnormaliz/my_omp.h"
41
#include "libnormaliz/full_cone.h"
42
43
#ifdef NMZ_SCIP
44
#include <scip/scip.h>
45
#include <scip/scipdefplugins.h> //TODO needed?
46
#include <scip/cons_linear.h>
47
#else
48
class SCIP;
49
#endif // NMZ_SCIP
50
51
52
namespace libnormaliz {
53
using namespace std;
54
55
long ScipBound = 1000000;
56
57
template<typename Integer>
58
vector<Integer> opt_sol(SCIP* scip, const Matrix<Integer>& gens, const Matrix<Integer>& SuppHyp,
59
const vector<Integer>& grading);
60
61
template<typename Integer>
62
bool bottom_points_inner(SCIP* scip, Matrix<Integer>& gens, list< vector<Integer> >& local_new_points,
63
vector< Matrix<Integer> >& local_q_gens, size_t& stellar_det_sum);
64
65
// kept here for simplicity:
66
67
double convert_to_double(mpz_class a) {
68
return a.get_d();
69
}
70
71
double convert_to_double(long a) {
72
return a;
73
}
74
75
double convert_to_double(long long a) {
76
return a;
77
}
78
79
template<typename Integer>
80
void bottom_points(list< vector<Integer> >& new_points, const Matrix<Integer>& gens,Integer VolumeBound) {
81
82
/* gens.pretty_print(cout);
83
cout << "=======================" << endl;
84
85
gens.transpose().pretty_print(cout);
86
cout << "=======================" << endl;*/
87
Integer volume;
88
// int dim = gens[0].size();
89
Matrix<Integer> Support_Hyperplanes = gens.invert(volume);
90
91
vector<Integer> grading; // = grading_;
92
if (grading.empty()) grading = gens.find_linear_form();
93
// cout << grading;
94
95
list<vector<Integer> > bottom_candidates;
96
bottom_candidates.splice(bottom_candidates.begin(), new_points);
97
//Matrix<Integer>(bottom_candidates).pretty_print(cout);
98
#ifdef NMZ_SCIP
99
if(verbose && nmz_scip){
100
verboseOutput() << "Computing bottom points using SCIP/projection" << endl;
101
}
102
#else
103
if(verbose){
104
verboseOutput() << "Computing bbottom points using projection " << endl;
105
}
106
#endif
107
108
if (verbose){
109
verboseOutput() << "simplex volume " << volume << endl;
110
}
111
112
//---------------------------- begin stellar subdivision -------------------
113
114
size_t stellar_det_sum = 0;
115
vector< Matrix<Integer> > q_gens; // for successive stellar subdivision
116
q_gens.push_back(gens);
117
int level = 0; // level of subdivision
118
119
#ifndef NCATCH
120
std::exception_ptr tmp_exception;
121
#endif
122
bool skip_remaining = false;
123
#pragma omp parallel // reduction(+:stellar_det_sum)
124
{
125
#ifndef NCATCH
126
try {
127
#endif
128
129
// setup scip enviorenment
130
SCIP* scip = NULL;
131
#ifdef NMZ_SCIP
132
133
SCIPcreate(& scip);
134
SCIPincludeDefaultPlugins(scip);
135
// SCIPsetMessagehdlr(scip,NULL); // deactivate scip output
136
137
SCIPsetIntParam(scip, "display/verblevel", 0);
138
139
// modify timing for better parallelization
140
// SCIPsetBoolParam(scip, "timing/enabled", FALSE);
141
SCIPsetBoolParam(scip, "timing/statistictiming", FALSE);
142
SCIPsetBoolParam(scip, "timing/rareclockcheck", TRUE);
143
144
145
SCIPsetIntParam(scip, "heuristics/shiftandpropagate/freq", -1);
146
SCIPsetIntParam(scip, "branching/pscost/priority", 1000000);
147
// SCIPsetIntParam(scip, "nodeselection/uct/stdpriority", 1000000);
148
#endif // NMZ_SCIP
149
150
vector< Matrix<Integer> > local_q_gens;
151
list< vector<Integer> > local_new_points;
152
153
154
while (!q_gens.empty()) {
155
156
if(skip_remaining) break;
157
if(verbose){
158
#pragma omp single
159
verboseOutput() << q_gens.size() << " simplices on level " << level++ << endl;
160
}
161
162
#pragma omp for schedule(static)
163
for (size_t i = 0; i < q_gens.size(); ++i) {
164
165
if(skip_remaining) continue;
166
167
#ifndef NCATCH
168
try {
169
#endif
170
bottom_points_inner(scip, q_gens[i], local_new_points,local_q_gens,stellar_det_sum);
171
#ifndef NCATCH
172
} catch(const std::exception& ) {
173
tmp_exception = std::current_exception();
174
skip_remaining = true;
175
#pragma omp flush(skip_remaining)
176
}
177
#endif
178
}
179
180
#pragma omp single
181
{
182
q_gens.clear();
183
}
184
#pragma omp critical (LOCALQGENS)
185
{
186
q_gens.insert(q_gens.end(),local_q_gens.begin(),local_q_gens.end());
187
}
188
local_q_gens.clear();
189
#pragma omp barrier
190
}
191
192
#pragma omp critical (LOCALNEWPOINTS)
193
{
194
new_points.splice(new_points.end(), local_new_points, local_new_points.begin(), local_new_points.end());
195
}
196
197
#ifdef NMZ_SCIP
198
SCIPfree(& scip);
199
#endif // NMZ_SCIP
200
201
#ifndef NCATCH
202
} catch(const std::exception& ) {
203
tmp_exception = std::current_exception();
204
skip_remaining = true;
205
#pragma omp flush(skip_remaining)
206
}
207
#endif
208
} // end parallel
209
210
//---------------------------- end stellar subdivision -----------------------
211
212
#ifndef NCATCH
213
if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);
214
#endif
215
216
217
//cout << new_points.size() << " new points accumulated" << endl;
218
new_points.sort();
219
new_points.unique();
220
if(verbose){
221
verboseOutput() << new_points.size() << " bottom points accumulated in total." << endl;
222
verboseOutput() << "The sum of determinants of the stellar subdivision is " << stellar_det_sum << endl;
223
}
224
}
225
226
template<typename Integer>
227
bool bottom_points_inner(SCIP* scip, Matrix<Integer>& gens, list< vector<Integer> >& local_new_points,
228
vector< Matrix<Integer> >& local_q_gens, size_t& stellar_det_sum) {
229
230
INTERRUPT_COMPUTATION_BY_EXCEPTION
231
232
vector<Integer> grading = gens.find_linear_form();
233
Integer volume;
234
int dim = gens[0].size();
235
Matrix<Integer> Support_Hyperplanes = gens.invert(volume);
236
237
if (volume < ScipBound) {
238
#pragma omp atomic
239
stellar_det_sum += convertTo<long long>(volume);
240
return false; // not subdivided
241
}
242
243
// try st4ellar subdivision
244
Support_Hyperplanes = Support_Hyperplanes.transpose();
245
Support_Hyperplanes.make_prime();
246
vector<Integer> new_point;
247
248
#ifdef NMZ_SCIP
249
// set time limit according to volume
250
if(nmz_scip){
251
double time_limit = pow(log10(convert_to_double(volume)),2);
252
SCIPsetRealParam(scip, "limits/time", time_limit);
253
// call scip
254
new_point = opt_sol(scip, gens, Support_Hyperplanes, grading);
255
if(new_point.empty() && verbose)
256
verboseOutput() << "No bottom point found by SCIP. Trying projection." << endl;
257
}
258
#endif // NMZ_SCIP
259
260
if(new_point.empty()){
261
list<vector<Integer> > Dummy;
262
new_point = gens.optimal_subdivision_point(); // projection method
263
}
264
265
if ( !new_point.empty() ){
266
267
//if (find(local_new_points.begin(), local_new_points.end(),new_point) == local_new_points.end())
268
local_new_points.push_back(new_point);
269
Matrix<Integer> stellar_gens(gens);
270
271
int nr_hyps = 0;
272
for (int i=0; i<dim; ++i) {
273
if (v_scalar_product(Support_Hyperplanes[i], new_point) != 0) {
274
stellar_gens[i] = new_point;
275
local_q_gens.push_back(stellar_gens);
276
277
stellar_gens[i] = gens[i];
278
}
279
else nr_hyps++;
280
}
281
//#pragma omp critical(VERBOSE)
282
//cout << new_point << " liegt in " << nr_hyps <<" hyperebenen" << endl;
283
return true; // subdivided
284
}
285
else{ // could not subdivided
286
#pragma omp atomic
287
stellar_det_sum += convertTo<long long>(volume);
288
return false;
289
}
290
}
291
292
// returns -1 if maximum is negative
293
template<typename Integer>
294
double max_in_col(const Matrix<Integer>& M, size_t j) {
295
Integer max = -1;
296
for (size_t i=0; i<M.nr_of_rows(); ++i) {
297
if (M[i][j] > max) max = M[i][j];
298
}
299
return convert_to_double(max);
300
}
301
302
303
// returns 1 if minimum is positive
304
template<typename Integer>
305
double min_in_col(const Matrix<Integer>& M, size_t j) {
306
Integer min = 1;
307
for (size_t i=0; i<M.nr_of_rows(); ++i) {
308
if (M[i][j] < min) min = M[i][j];
309
}
310
return convert_to_double(min);
311
}
312
313
314
#ifdef NMZ_SCIP
315
template<typename Integer>
316
vector<Integer> opt_sol(SCIP* scip,
317
const Matrix<Integer>& gens, const Matrix<Integer>& SuppHyp,
318
const vector<Integer>& grading) {
319
320
INTERRUPT_COMPUTATION_BY_EXCEPTION
321
322
double upper_bound = convert_to_double(v_scalar_product(grading,gens[0]))-0.5;
323
// TODO make the test more strict
324
long dim = grading.size();
325
// create variables
326
SCIP_VAR** x = new SCIP_VAR*[dim];
327
char name[SCIP_MAXSTRLEN];
328
SCIPcreateProbBasic(scip, "extra_points");
329
for (long i=0; i<dim; i++) {
330
(void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "x_%d", i);
331
// SCIPcreateVarBasic(scip, &x[i], name, -SCIPinfinity(scip), SCIPinfinity(scip),
332
// convert_to_double(grading[i]), SCIP_VARTYPE_INTEGER);
333
334
// min_in_col and max_in_col already give good bounds if all signs are positive or negative
335
// no constraint needed
336
SCIPcreateVarBasic(scip, &x[i], name, min_in_col(gens,i), max_in_col(gens, i),
337
convert_to_double(grading[i]), SCIP_VARTYPE_INTEGER);
338
SCIPaddVar(scip, x[i]);
339
}
340
341
// create constraints
342
// vector< vector<Integer> > SuppHyp(MyCone.getSupportHyperplanes());
343
double* ineq = new double[dim];
344
long nrSuppHyp = SuppHyp.nr_of_rows();
345
for( long i = 0; i < nrSuppHyp; ++i )
346
{
347
SCIP_CONS* cons;
348
for (long j=0; j<dim; j++)
349
ineq[j] = convert_to_double(SuppHyp[i][j]);
350
(void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ineq_%d", i);
351
SCIPcreateConsBasicLinear(scip, &cons, name, dim, x, ineq, 0.0, SCIPinfinity(scip));
352
SCIPaddCons(scip, cons);
353
SCIPreleaseCons(scip, &cons);
354
}
355
356
SCIP_CONS* cons;
357
// setup non-zero constraints
358
// if all extreme rays have the same sign in one dimension, add the x_i>=1 or x_i<=-1 constraint
359
360
for (long i=0; i<dim; i++){
361
double min = min_in_col(gens,i);
362
double max = max_in_col(gens,i);
363
if (min*max>0){
364
break;
365
}
366
if (i==dim-1){
367
//cout << "no same sign. using bound disjunction" << endl;
368
// set bound disjunction
369
370
SCIP_VAR** double_x = new SCIP_VAR*[2*dim];
371
SCIP_BOUNDTYPE* boundtypes = new SCIP_BOUNDTYPE[2*dim];
372
SCIP_Real* bounds = new SCIP_Real[2*dim];
373
for (long i=0; i<dim;i++) {
374
double_x[2*i] = x[i];
375
double_x[2*i+1] = x[i];
376
boundtypes[2*i]= SCIP_BOUNDTYPE_LOWER;
377
boundtypes[2*i+1] = SCIP_BOUNDTYPE_UPPER;
378
bounds[2*i] = 1.0;
379
bounds[2*i+1] = -1.0;
380
}
381
SCIPcreateConsBasicBounddisjunction (scip, &cons,"non_zero",2*dim,double_x,boundtypes,bounds);
382
SCIPaddCons(scip, cons);
383
SCIPreleaseCons(scip, &cons);
384
385
/*
386
// this type of constraints procedures numerical problems:
387
for (long j=0; j<dim; j++)
388
ineq[j] = convert_to_double(grading[j]);
389
SCIPcreateConsBasicLinear(scip, &cons, "non_zero", dim, x, ineq, 1.0, SCIPinfinity(scip));
390
*/
391
}
392
}
393
394
// set objective limit, feasible solution has to have a better objective value
395
SCIPsetObjlimit(scip,upper_bound);
396
397
398
// give original generators as hints to scip
399
SCIP_SOL* input_sol;
400
SCIP_Bool stored;
401
SCIPcreateOrigSol(scip, &input_sol, NULL);
402
for (long i=0; i<dim; i++) {
403
for (long j=0; j<dim; j++) {
404
SCIPsetSolVal(scip, input_sol, x[j], convert_to_double(gens[i][j]));
405
}
406
//SCIPprintSol(scip, input_sol, NULL, TRUE);
407
SCIPaddSol(scip, input_sol, &stored);
408
}
409
SCIPfreeSol(scip, &input_sol);
410
411
//SCIPinfoMessage(scip, NULL, "Original problem:\n");
412
//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);
413
//SCIPinfoMessage(scip, NULL, "\nSolving...\n");
414
415
//#ifndef NDEBUG_BLA
416
//FILE* file = fopen("mostrecent.lp","w");
417
//assert (file != NULL);
418
//SCIPprintOrigProblem(scip, file, "lp", FALSE);
419
//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);
420
//fclose(file);
421
//#endif
422
423
// set numerics
424
Integer maxabs = v_max_abs(grading);
425
double epsilon = max(1e-20,min(1/(convert_to_double(maxabs)*10),1e-10));
426
//cout << "epsilon is in region " << log10(epsilon) << endl;
427
double feastol = max(1e-17,epsilon*10);
428
SCIPsetRealParam(scip, "numerics/epsilon", epsilon);
429
SCIPsetRealParam(scip, "numerics/feastol", feastol);
430
431
SCIPsolve(scip);
432
//SCIPprintStatistics(scip, NULL);
433
vector<Integer> sol_vec(dim);
434
if(SCIPgetStatus(scip) == SCIP_STATUS_TIMELIMIT && verbose) verboseOutput() << "time limit reached!" << endl;
435
if( SCIPgetNLimSolsFound(scip) > 0 ) // solutions respecting objective limit (ie not our input solutions)
436
{
437
SCIP_SOL* sol = SCIPgetBestSol(scip);
438
//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);
439
//SCIPprintSol(scip, sol, NULL, FALSE) ;
440
441
for (int i=0;i<dim;i++) {
442
convert(sol_vec[i], SCIPconvertRealToLongint(scip,SCIPgetSolVal(scip,sol,x[i])));
443
}
444
445
446
if(v_scalar_product(grading,sol_vec)>upper_bound){
447
//Integer sc = v_scalar_product(sol_vec,grading);
448
if(verbose){
449
#pragma omp critical(VERBOSE)
450
{
451
verboseOutput() << "Solution does not respect upper bound!" << endl;
452
//cout << "upper bound: " << upper_bound << endl;
453
//cout << "grading: " << grading;
454
//cout << "hyperplanes:" << endl;
455
//SuppHyp.pretty_print(cout);
456
//cout << "generators:" << endl;
457
//gens.pretty_print(cout);
458
//cout << sc << " | solution " << sol_vec;
459
//cout << "epsilon: " << epsilon << endl;
460
//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);
461
//SCIPprintSol(scip, sol, NULL, FALSE) ;
462
//cout << "write files... " << endl;
463
//FILE* file = fopen("mostrecent.lp","w");
464
//assert (file != NULL);
465
//SCIPprintOrigProblem(scip, file, "lp", FALSE);
466
//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);
467
//fclose(file);
468
//assert(v_scalar_product(grading,sol_vec)<=upper_bound);
469
470
}
471
}
472
return vector<Integer>();
473
}
474
475
476
for (int i=0;i<nrSuppHyp;i++) {
477
if((v_scalar_product(SuppHyp[i],sol_vec))<0) {
478
//Integer sc = v_scalar_product(sol_vec,grading);
479
if(verbose){
480
#pragma omp critical(VERBOSE)
481
{
482
verboseOutput() << "Solution does not respect hyperplanes!" << endl;
483
//cout << "the hyperplane: " << SuppHyp[i];
484
//cout << "grading: " << grading;
485
//cout << "hyperplanes:" << endl;
486
//SuppHyp.pretty_print(cout);
487
//cout << "generators:" << endl;
488
//gens.pretty_print(cout);
489
//cout << sc << " | solution " << sol_vec;
490
//cout << "epsilon: " << epsilon << endl;
491
//SCIPprintOrigProblem(scip, NULL, NULL, FALSE);
492
//SCIPprintSol(scip, sol, NULL, FALSE) ;
493
//cout << "write files... " << endl;
494
//FILE* file = fopen("mostrecent.lp","w");
495
//assert (file != NULL);
496
//SCIPprintOrigProblem(scip, file, "lp", FALSE);
497
//SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);
498
//fclose(file);
499
//assert((v_scalar_product(SuppHyp[i],sol_vec))>=0);
500
501
}
502
}
503
return vector<Integer>();
504
}
505
}
506
if((v_scalar_product(grading,sol_vec))<1) {
507
//Integer sc = v_scalar_product(sol_vec,grading);
508
if (verbose){
509
#pragma omp critical(VERBOSE)
510
{
511
verboseOutput() << "Solution does not respect the nonzero condition!" << endl;
512
/*cout << "grading: " << grading;
513
cout << "hyperplanes:" << endl;
514
SuppHyp.pretty_print(cout);
515
cout << "generators:" << endl;
516
gens.pretty_print(cout);
517
cout << sc << " | solution " << sol_vec;
518
cout << "epsilon: " << epsilon << endl;
519
SCIPprintOrigProblem(scip, NULL, NULL, FALSE);
520
SCIPprintSol(scip, sol, NULL, FALSE) ;
521
cout << "write files... " << endl;
522
FILE* file = fopen("mostrecent.lp","w");
523
assert (file != NULL);
524
SCIPprintOrigProblem(scip, file, "lp", FALSE);
525
SCIPwriteParams(scip, "mostrecent.set", TRUE, TRUE);
526
fclose(file);
527
assert((v_scalar_product(grading,sol_vec))>=1);*/
528
529
}
530
}
531
return vector<Integer>();
532
}
533
/*assert(v_scalar_product(grading,sol_vec)<=upper_bound);
534
for (int i=0;i<nrSuppHyp;i++) assert((v_scalar_product(SuppHyp[i],sol_vec))>=0);
535
assert((v_scalar_product(grading,sol_vec))>=1);*/
536
//Integer sc = v_scalar_product(sol_vec,grading);
537
//#pragma omp critical(VERBOSE)
538
//cout << sc << " | solution " << sol_vec;
539
540
} else {
541
return vector<Integer>();
542
}
543
544
for (int j=0;j<dim;j++) SCIPreleaseVar(scip, &x[j]);
545
SCIPfreeProb(scip);
546
return sol_vec;
547
}
548
#endif // NMZ_SCIP
549
550
#ifndef NMZ_MIC_OFFLOAD //offload with long is not supported
551
template void bottom_points(list< vector<long> >& new_points, const Matrix<long>& gens,
552
long VolumeBound);
553
#endif // NMZ_MIC_OFFLOAD
554
template void bottom_points(list< vector<long long> >& new_points, const Matrix<long long>& gens,
555
long long VolumeBound);
556
template void bottom_points(list< vector<mpz_class> >& new_points, const Matrix<mpz_class>& gens,
557
mpz_class VolumeBound);
558
559
} // namespace
560
561
#ifdef NMZ_MIC_OFFLOAD
562
#pragma offload_attribute (pop)
563
#endif
564