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

563624 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 "libnormaliz/cone_helper.h"
29
#include "libnormaliz/vector_operations.h"
30
#include "libnormaliz/my_omp.h"
31
32
namespace libnormaliz {
33
using std::vector;
34
35
//---------------------------------------------------------------------------
36
37
// determines the maximal subsets in a vector of subsets given by their indicator vectors
38
// result returned in is_max_subset -- must be initialized outside
39
// only set to false in this routine
40
// if a set occurs more than once, only the last instance is recognized as maximal
41
void maximal_subsets(const vector<vector<bool> >& ind, vector<bool>& is_max_subset) {
42
43
if(ind.size()==0)
44
return;
45
46
size_t nr_sets=ind.size();
47
size_t card=ind[0].size();
48
vector<key_t> elem(card);
49
50
for (size_t i = 0; i <nr_sets; i++) {
51
if(!is_max_subset[i]) // already known to be non-maximal
52
continue;
53
54
size_t k=0; // counts the number of elements in set with index i
55
for (size_t j = 0; j <card; j++) {
56
if (ind[i][j]) {
57
elem[k]=j;
58
k++;
59
}
60
}
61
62
for (size_t j = 0; j <nr_sets; j++) {
63
if (i==j || !is_max_subset[j] ) // don't compare with itself or something known not to be maximal
64
continue;
65
size_t t;
66
for (t = 0; t<k; t++) {
67
if (!ind[j][elem[t]])
68
break; // not a superset
69
}
70
if (t==k) { // found a superset
71
is_max_subset[i]=false;
72
break; // the loop over j
73
}
74
}
75
}
76
}
77
78
//---------------------------------------------------------------------------
79
// computes c1*v1-c2*v2
80
template<typename Integer>
81
vector<Integer> FM_comb(Integer c1, const vector<Integer>& v1,Integer c2, const vector<Integer>& v2, bool& is_zero){
82
83
size_t dim=v1.size();
84
vector<Integer> new_supp(dim);
85
is_zero=false;
86
size_t k=0;
87
for(;k<dim;++k){
88
new_supp[k]=c1*v1[k]-c2*v2[k];
89
if(!check_range(new_supp[k]))
90
break;
91
}
92
Integer g=0;
93
if(k==dim)
94
g=v_make_prime(new_supp);
95
else{ // redo in GMP if necessary
96
#pragma omp atomic
97
GMP_hyp++;
98
vector<mpz_class> mpz_neg(dim), mpz_pos(dim), mpz_sum(dim);
99
convert(mpz_neg, v1);
100
convert(mpz_pos, v2);
101
for (k = 0; k <dim; k++)
102
mpz_sum[k]=convertTo<mpz_class>(c1)*mpz_neg[k]-
103
convertTo<mpz_class>(c2)*mpz_pos[k];
104
mpz_class GG=v_make_prime(mpz_sum);
105
convert(new_supp, mpz_sum);
106
convert(g,GG);
107
}
108
if(g==0)
109
is_zero=true;
110
return new_supp;
111
}
112
113
template<typename IntegerPL, typename IntegerRet>
114
vector<size_t> ProjectAndLift<IntegerPL,IntegerRet>::order_supps(const Matrix<IntegerPL>& Supps){
115
116
assert(Supps.nr_of_rows()>0);
117
size_t dim=Supps.nr_of_columns();
118
119
vector<pair<IntegerPL,size_t> > NewPos,NewNeg; // to record the order of the support haperplanes
120
for(size_t i=0;i<Supps.nr_of_rows();++i){
121
if(Supps[i][dim-1] >= 0)
122
NewPos.push_back(make_pair(-Supps[i][dim-1],i));
123
else
124
NewNeg.push_back(make_pair(Supps[i][dim-1],i));
125
}
126
sort(NewPos.begin(),NewPos.end());
127
sort(NewNeg.begin(),NewNeg.end());
128
129
size_t min_length=NewNeg.size();
130
if(NewPos.size()<min_length)
131
min_length=NewPos.size();
132
133
vector<size_t> Order;
134
135
for(size_t i=0;i<min_length;++i){
136
Order.push_back(NewPos[i].second);
137
Order.push_back(NewNeg[i].second);
138
}
139
for(size_t i=min_length;i<NewPos.size();++i)
140
Order.push_back(NewPos[i].second);
141
for(size_t i=min_length;i<NewNeg.size();++i)
142
Order.push_back(NewNeg[i].second);
143
144
assert(Order.size()==Supps.nr_of_rows());
145
146
/* for(size_t i=0;i<Order.size();++i)
147
cout << Supps[Order[i]][dim-1] << " ";
148
cout << endl;*/
149
150
return Order;
151
}
152
//---------------------------------------------------------------------------
153
template<typename IntegerPL, typename IntegerRet>
154
void ProjectAndLift<IntegerPL,IntegerRet>::compute_projections(size_t dim, vector< boost::dynamic_bitset<> >& Ind,
155
vector< boost::dynamic_bitset<> >& Pair, vector< boost::dynamic_bitset<> >& ParaInPair,
156
size_t rank){
157
158
INTERRUPT_COMPUTATION_BY_EXCEPTION
159
160
if(dim==1)
161
return;
162
163
const Matrix<IntegerPL> & Supps=AllSupps[dim];
164
size_t dim1=dim-1;
165
166
if(verbose)
167
verboseOutput() << "embdim " << dim << " inequalities " << Supps.nr_of_rows() << endl;
168
169
// cout << "SSS" << Ind.size() << " " << Ind;
170
171
// We now augment the given cone by the last basis vector and its negative
172
// Afterwards we project modulo the subspace spanned by them
173
174
vector<key_t> Neg, Pos; // for the Fourier-Motzkin elimination of inequalities
175
Matrix<IntegerPL> SuppsProj(0,dim); // for the support hyperplanes of the projection
176
Matrix<IntegerPL> EqusProj(0,dim); // for the equations (both later minimized)
177
178
// First we make incidence vectors with the given generators
179
vector< boost::dynamic_bitset<> > NewInd; // for the incidence vectors of the new hyperplanes
180
vector< boost::dynamic_bitset<> > NewPair; // for the incidence vectors of the new hyperplanes
181
vector< boost::dynamic_bitset<> > NewParaInPair; // for the incidence vectors of the new hyperplanes
182
183
boost::dynamic_bitset<> TRUE;
184
if(!is_parallelotope){
185
TRUE.resize(Ind[0].size());
186
TRUE.set();
187
}
188
189
vector<bool> IsEquation(Supps.nr_of_rows());
190
191
bool rank_goes_up=false; // if we add the last unit vector
192
size_t PosEquAt=0; // we memorize the positions of pos/neg equations if rank goes up
193
size_t NegEquAt=0;
194
195
for(size_t i=0;i<Supps.nr_of_rows();++i){
196
if(!is_parallelotope && Ind[i]==TRUE)
197
IsEquation[i]=true;
198
199
if(Supps[i][dim1]==0){ // already independent of last coordinate
200
no_crunch=false;
201
if(IsEquation[i])
202
EqusProj.append(Supps[i]); // is equation
203
else{
204
SuppsProj.append(Supps[i]); // neutral support hyperplane
205
if(!is_parallelotope)
206
NewInd.push_back(Ind[i]);
207
else{
208
NewPair.push_back(Pair[i]);
209
NewParaInPair.push_back(ParaInPair[i]);
210
}
211
}
212
continue;
213
}
214
if(IsEquation[i])
215
rank_goes_up=true;
216
if(Supps[i][dim1]>0){
217
if(IsEquation[i])
218
PosEquAt=i;
219
Pos.push_back(i);
220
continue;
221
}
222
Neg.push_back(i);
223
if(IsEquation[i])
224
NegEquAt=i;
225
}
226
227
// cout << "Nach Pos/Neg " << EqusProj.nr_of_rows() << " " << Pos.size() << " " << Neg.size() << endl;
228
229
// now the elimination, matching Pos and Neg
230
231
// cout << "rank_goes_up " << rank_goes_up << endl;
232
233
bool skip_remaining;
234
#ifndef NCATCH
235
std::exception_ptr tmp_exception;
236
#endif
237
238
if(rank_goes_up){
239
240
assert(!is_parallelotope);
241
242
for(size_t i=0;i<Pos.size();++i){ // match pos and neg equations
243
size_t p=Pos[i];
244
if(!IsEquation[p])
245
continue;
246
IntegerPL PosVal=Supps[p][dim1];
247
for(size_t j=0;j<Neg.size();++j){
248
size_t n=Neg[j];
249
if(!IsEquation[n])
250
continue;
251
IntegerPL NegVal=Supps[n][dim1];
252
bool is_zero;
253
// cout << Supps[p];
254
// cout << Supps[n];
255
vector<IntegerPL> new_equ=FM_comb(PosVal,Supps[n],NegVal,Supps[p],is_zero);
256
// cout << "zero " << is_zero << endl;
257
// cout << "=====================" << endl;
258
if(is_zero)
259
continue;
260
EqusProj.append(new_equ);
261
}
262
}
263
264
for(size_t i=0;i<Pos.size();++i){ // match pos inequalities with a negative equation
265
size_t p=Pos[i];
266
if(IsEquation[p])
267
continue;
268
IntegerPL PosVal=Supps[p][dim1];
269
IntegerPL NegVal=Supps[NegEquAt][dim1];
270
vector<IntegerPL> new_supp(dim);
271
bool is_zero;
272
new_supp=FM_comb(PosVal,Supps[NegEquAt],NegVal,Supps[p],is_zero);
273
/* cout << Supps[NegEquAt];
274
cout << Supps[p];
275
cout << new_supp;
276
cout << "zero " << is_zero << endl;
277
cout << "+++++++++++++++++++++" << endl; */
278
if(is_zero) // cannot happen, but included for analogy
279
continue;
280
SuppsProj.append(new_supp);
281
NewInd.push_back(Ind[p]);
282
}
283
284
for(size_t j=0;j<Neg.size();++j){ // match neg inequalities with a posizive equation
285
size_t n=Neg[j];
286
if(IsEquation[n])
287
continue;
288
IntegerPL PosVal=Supps[PosEquAt][dim1];
289
IntegerPL NegVal=Supps[n][dim1];
290
vector<IntegerPL> new_supp(dim);
291
bool is_zero;
292
new_supp=FM_comb(PosVal,Supps[n],NegVal,Supps[PosEquAt],is_zero);
293
/* cout << Supps[PosEquAt];
294
cout << Supps[n];
295
cout << new_supp;
296
cout << "zero " << is_zero << endl;
297
cout << "=====================" << endl;*/
298
299
if(is_zero) // cannot happen, but included for analogy
300
continue;
301
SuppsProj.append(new_supp);
302
NewInd.push_back(Ind[n]);
303
}
304
}
305
306
// cout << "Nach RGU " << EqusProj.nr_of_rows() << " " << SuppsProj.nr_of_rows() << endl;
307
308
if(!rank_goes_up && !is_parallelotope){ // must match pos and neg hyperplanes
309
310
skip_remaining=false;
311
312
size_t min_nr_vertices=rank-2;
313
/*if(rank>=3){
314
min_nr_vertices=1;
315
for(long i=0;i<(long) rank -3;++i)
316
min_nr_vertices*=2;
317
318
}*/
319
320
#pragma omp parallel for schedule(dynamic)
321
for(size_t i=0;i<Pos.size();++i){
322
323
if (skip_remaining) continue;
324
325
#ifndef NCATCH
326
try {
327
#endif
328
329
INTERRUPT_COMPUTATION_BY_EXCEPTION
330
331
size_t p=Pos[i];
332
IntegerPL PosVal=Supps[p][dim1];
333
vector<key_t> PosKey;
334
for(size_t k=0;k<Ind[i].size();++k)
335
if(Ind[p][k])
336
PosKey.push_back(k);
337
338
for(size_t j=0;j<Neg.size();++j){
339
size_t n=Neg[j];
340
// // to give a facet of the extended cone
341
// match incidence vectors
342
boost::dynamic_bitset<> incidence(TRUE.size());
343
size_t nr_match=0;
344
vector<key_t> CommonKey;
345
for(size_t k=0;k<PosKey.size();++k)
346
if(Ind[n][PosKey[k]]){
347
incidence[PosKey[k]]=true;
348
CommonKey.push_back(PosKey[k]);
349
nr_match++;
350
}
351
if(rank>=2 && nr_match<min_nr_vertices) // cannot make subfacet of augmented cone
352
continue;
353
354
bool IsSubfacet=true;
355
for(size_t k=0;k<Supps.nr_of_rows();++k){
356
if(k==p || k==n || IsEquation[k])
357
continue;
358
bool contained=true;
359
for(size_t j=0;j<CommonKey.size();++j){
360
if(!Ind[k][CommonKey[j]]){
361
contained=false;
362
break;
363
}
364
}
365
if(contained){
366
IsSubfacet=false;
367
break;
368
}
369
}
370
if(!IsSubfacet)
371
continue;
372
//}
373
374
IntegerPL NegVal=Supps[n][dim1];
375
vector<IntegerPL> new_supp(dim);
376
bool is_zero;
377
new_supp=FM_comb(PosVal,Supps[n],NegVal,Supps[p],is_zero);
378
if(is_zero) // linear combination is 0
379
continue;
380
381
if(nr_match==TRUE.size()){ // gives an equation
382
#pragma omp critical(NEWEQ)
383
EqusProj.append(new_supp);
384
continue;
385
}
386
#pragma omp critical(NEWSUPP)
387
{
388
SuppsProj.append(new_supp);
389
NewInd.push_back(incidence);
390
}
391
}
392
393
#ifndef NCATCH
394
} catch(const std::exception& ) {
395
tmp_exception = std::current_exception();
396
skip_remaining = true;
397
#pragma omp flush(skip_remaining)
398
}
399
#endif
400
}
401
402
} // !rank_goes_up && !is_parallelotope
403
404
if(!rank_goes_up && is_parallelotope){ // must match pos and neg hyperplanes
405
406
size_t codim=dim1-1; // the minimal codim a face of the original cone must have
407
// in order to project to a subfacet of the current one
408
size_t original_dim=Pair[0].size()+1;
409
size_t max_number_containing_factes=original_dim-codim;
410
411
skip_remaining=false;
412
413
size_t nr_pos=Pos.size();
414
//if(nr_pos>10000)
415
// nr_pos=10000;
416
size_t nr_neg=Neg.size();
417
// if(nr_neg>10000)
418
// nr_neg=10000;
419
420
#pragma omp parallel for schedule(dynamic)
421
for(size_t i=0;i<nr_pos;++i){
422
423
if (skip_remaining) continue;
424
425
#ifndef NCATCH
426
try {
427
#endif
428
429
INTERRUPT_COMPUTATION_BY_EXCEPTION
430
431
size_t p=Pos[i];
432
IntegerPL PosVal=Supps[p][dim1];
433
434
for(size_t j=0;j<nr_neg;++j){
435
size_t n=Neg[j];
436
boost::dynamic_bitset<> IntersectionPair(Pair[p].size());
437
size_t nr_hyp_intersection=0;
438
bool in_parallel_hyperplanes=false;
439
bool codim_too_small=false;
440
441
for(size_t k=0;k<Pair[p].size();++k){ // run over all pairs
442
if(Pair[p][k] || Pair[n][k]){
443
nr_hyp_intersection++;
444
IntersectionPair[k]=true;
445
if(nr_hyp_intersection> max_number_containing_factes){
446
codim_too_small=true;
447
break;
448
}
449
}
450
if(Pair[p][k] && Pair[n][k]){
451
if(ParaInPair[p][k]!=ParaInPair[n][k]){
452
in_parallel_hyperplanes=true;
453
break;
454
}
455
}
456
}
457
if(in_parallel_hyperplanes || codim_too_small)
458
continue;
459
460
boost::dynamic_bitset<> IntersectionParaInPair(Pair[p].size());
461
for(size_t k=0;k<ParaInPair[p].size();++k){
462
if(Pair[p][k])
463
IntersectionParaInPair[k]=ParaInPair[p][k];
464
else
465
if(Pair[n][k])
466
IntersectionParaInPair[k]=ParaInPair[n][k];
467
}
468
469
// we must nevertheless use the comparison test
470
bool IsSubfacet=true;
471
if(!no_crunch){
472
for(size_t k=0;k<Supps.nr_of_rows();++k){
473
if(k==p || k==n || IsEquation[k])
474
continue;
475
bool contained=true;
476
477
for(size_t u=0;u<IntersectionPair.size();++u){
478
if(Pair[k][u] && !IntersectionPair[u]){ // hyperplane k contains facet of Supp
479
contained=false; // not our intersection
480
continue;
481
}
482
if(Pair[k][u] && IntersectionPair[u]){
483
if(ParaInPair[k][u]!=IntersectionParaInPair[u]){ // they are contained in parallel
484
contained=false; // original facets
485
continue;
486
}
487
}
488
}
489
490
if(contained){
491
IsSubfacet=false;
492
break;
493
}
494
}
495
}
496
if(!IsSubfacet)
497
continue;
498
499
IntegerPL NegVal=Supps[n][dim1];
500
bool dummy;
501
vector<IntegerPL> new_supp=FM_comb(PosVal,Supps[n],NegVal,Supps[p],dummy);
502
#pragma omp critical(NEWSUPP)
503
{
504
SuppsProj.append(new_supp);
505
NewPair.push_back(IntersectionPair);
506
NewParaInPair.push_back(IntersectionParaInPair);
507
}
508
}
509
510
#ifndef NCATCH
511
} catch(const std::exception& ) {
512
tmp_exception = std::current_exception();
513
skip_remaining = true;
514
#pragma omp flush(skip_remaining)
515
}
516
#endif
517
}
518
519
#ifndef NCATCH
520
if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);
521
#endif
522
523
} // !rank_goes_up && is_parallelotope
524
525
// cout << "Nach FM " << EqusProj.nr_of_rows() << " " << SuppsProj.nr_of_rows() << endl;
526
527
Ind.clear(); // no longer needed
528
529
EqusProj.resize_columns(dim1); // cut off the trailing 0
530
SuppsProj.resize_columns(dim1); // project hyperplanes
531
532
// Equations have not yet been appended to support hypwerplanes
533
EqusProj.row_echelon(); // reduce equations
534
// cout << "Nach eche " << EqusProj.nr_of_rows() << endl;
535
/* for(size_t i=0;i<EqusProj.nr_of_rows(); ++i)
536
cout << EqusProj[i]; */
537
SuppsProj.append(EqusProj); // append them as pairs of inequalities
538
EqusProj.scalar_multiplication(-1);
539
SuppsProj.append(EqusProj);
540
541
// Now we must make the new indicator matrix
542
// We must add indictor vectors for the equations
543
for(size_t i=0;i<2*EqusProj.nr_of_rows();++i)
544
NewInd.push_back(TRUE);
545
546
if(dim1>1)
547
AllOrders[dim1]=order_supps(SuppsProj);
548
swap(AllSupps[dim1],SuppsProj);
549
550
size_t new_rank=dim1-EqusProj.nr_of_rows();
551
552
compute_projections(dim-1,NewInd, NewPair, NewParaInPair,new_rank);
553
}
554
555
//---------------------------------------------------------------------------
556
template<typename IntegerPL,typename IntegerRet>
557
bool ProjectAndLift<IntegerPL,IntegerRet>::fiber_interval(IntegerRet& MinInterval, IntegerRet& MaxInterval,
558
const vector<IntegerRet>& base_point){
559
size_t dim=base_point.size()+1;
560
Matrix<IntegerPL>& Supps=AllSupps[dim];
561
vector<size_t>& Order=AllOrders[dim];
562
563
bool FirstMin=true, FirstMax=true;
564
vector<IntegerPL> LiftedGen;
565
convert(LiftedGen,base_point);
566
// cout << LiftedGen;
567
size_t check_supps=Supps.nr_of_rows();
568
if(check_supps>1000 && dim<EmbDim)
569
check_supps=1000;
570
for(size_t j=0;j<check_supps;++j){
571
IntegerPL Den=Supps[Order[j]].back();
572
if(Den==0)
573
continue;
574
IntegerPL Num= -v_scalar_product_vectors_unequal_lungth(LiftedGen,Supps[Order[j]]);
575
// cout << "Num " << Num << endl;
576
IntegerRet Quot;
577
bool frac=int_quotient(Quot,Num,Den);
578
IntegerRet Bound=0;
579
//frac=(Num % Den !=0);
580
if(Den>0){ // we must produce a lower bound of the interval
581
if(Num>=0){ // true quot >= 0
582
Bound=Quot;
583
if(frac)
584
Bound++;
585
}
586
else // true quot < 0
587
Bound=-Quot;
588
if(FirstMin || Bound > MinInterval){
589
MinInterval=Bound;
590
FirstMin=false;
591
}
592
}
593
if(Den<0){ // we must produce an upper bound of the interval
594
if(Num >= 0){ // true quot <= 0
595
Bound=-Quot;
596
if(frac)
597
Bound--;
598
}
599
else // true quot > 0
600
Bound=Quot;
601
if(FirstMax || Bound < MaxInterval){
602
MaxInterval=Bound;
603
FirstMax=false;
604
}
605
}
606
if(!FirstMax && !FirstMin && MaxInterval<MinInterval)
607
return false; // interval empty
608
}
609
return true; // interval nonempty
610
}
611
612
///---------------------------------------------------------------------------
613
template<typename IntegerPL,typename IntegerRet>
614
void ProjectAndLift<IntegerPL,IntegerRet>::lift_points_to_this_dim(list<vector<IntegerRet> >& Deg1Lifted,
615
const list<vector<IntegerRet> >& Deg1Proj){
616
617
if(Deg1Proj.empty())
618
return;
619
size_t dim=Deg1Proj.front().size()+1;
620
size_t dim1=dim-1;
621
vector<list<vector<IntegerRet> > > Deg1Thread(omp_get_max_threads());
622
623
bool skip_remaining;
624
#ifndef NCATCH
625
std::exception_ptr tmp_exception;
626
#endif
627
628
skip_remaining=false;
629
int omp_start_level=omp_get_level();
630
631
#pragma omp parallel
632
{
633
int tn;
634
if(omp_get_level()==omp_start_level)
635
tn=0;
636
else
637
tn = omp_get_ancestor_thread_num(omp_start_level+1);
638
639
size_t nr_to_lift=Deg1Proj.size();
640
size_t ppos=0;
641
auto p=Deg1Proj.begin();
642
#pragma omp for schedule(dynamic)
643
for(size_t i=0;i<nr_to_lift;++i){
644
645
if (skip_remaining) continue;
646
647
for(; i > ppos; ++ppos, ++p) ;
648
for(; i < ppos; --ppos, --p) ;
649
650
651
#ifndef NCATCH
652
try {
653
#endif
654
655
IntegerRet MinInterval=0, MaxInterval=0; // the fiber over *p is an interval -- 0 to make gcc happy
656
fiber_interval(MinInterval, MaxInterval, *p);
657
// cout << "Min " << MinInterval << " Max " << MaxInterval << endl;
658
for(IntegerRet k=MinInterval;k<=MaxInterval;++k){
659
660
INTERRUPT_COMPUTATION_BY_EXCEPTION
661
662
vector<IntegerRet> NewPoint(dim);
663
for(size_t j=0;j<dim1;++j)
664
NewPoint[j]=(*p)[j];
665
NewPoint[dim1]=k;
666
Deg1Thread[tn].push_back(NewPoint);
667
}
668
669
#ifndef NCATCH
670
} catch(const std::exception& ) {
671
tmp_exception = std::current_exception();
672
skip_remaining = true;
673
#pragma omp flush(skip_remaining)
674
}
675
#endif
676
677
} // lifting
678
} // pararllel
679
680
#ifndef NCATCH
681
if (!(tmp_exception == 0)) std::rethrow_exception(tmp_exception);
682
#endif
683
684
for(size_t i=0;i<Deg1Thread.size();++i)
685
Deg1Lifted.splice(Deg1Lifted.begin(),Deg1Thread[i]);
686
687
/* Deg1.pretty_print(cout);
688
cout << "*******************" << endl; */
689
}
690
691
///---------------------------------------------------------------------------
692
template<typename IntegerPL,typename IntegerRet>
693
void ProjectAndLift<IntegerPL,IntegerRet>::lift_points_by_generation(){
694
695
assert(EmbDim>=2);
696
697
list<vector<IntegerRet> > Deg1Lifted;
698
list<vector<IntegerRet> > Deg1Proj;
699
vector<IntegerRet> One(1,GD);
700
Deg1Proj.push_back(One);
701
702
for(size_t i=2; i<=EmbDim;++i){
703
assert(Deg1Lifted.empty());
704
lift_points_to_this_dim(Deg1Lifted,Deg1Proj);
705
if(verbose)
706
verboseOutput() << "embdim " << i << " Deg1Elements " << Deg1Lifted.size() << endl;
707
if(i<EmbDim){
708
Deg1Proj.clear();
709
swap(Deg1Lifted,Deg1Proj);
710
}
711
}
712
713
swap(Deg1Points,Deg1Lifted); // final result
714
/* if(verbose)
715
verboseOutput() << "Lifting done" << endl;*/
716
}
717
718
///---------------------------------------------------------------------------
719
template<typename IntegerPL,typename IntegerRet>
720
void ProjectAndLift<IntegerPL,IntegerRet>::lift_point_recursively(vector<IntegerRet>& final_latt_point,
721
const vector<IntegerRet>& latt_point_proj){
722
723
size_t dim1=latt_point_proj.size();
724
size_t dim=dim1+1;
725
size_t final_dim=AllSupps.size()-1;
726
727
IntegerRet MinInterval=0, MaxInterval=0; // the fiber over Deg1Proj[i] is an interval -- 0 to make gcc happy
728
fiber_interval(MinInterval, MaxInterval, latt_point_proj);
729
for(IntegerRet k=MinInterval;k<=MaxInterval;++k){
730
731
INTERRUPT_COMPUTATION_BY_EXCEPTION
732
733
vector<IntegerRet> NewPoint(dim);
734
for(size_t j=0;j<dim1;++j)
735
NewPoint[j]=latt_point_proj[j];
736
NewPoint[dim1]=k;
737
if(dim==final_dim && NewPoint!=excluded_point){
738
final_latt_point=NewPoint;
739
break;
740
}
741
if(dim<final_dim){
742
lift_point_recursively(final_latt_point, NewPoint);
743
if(final_latt_point.size()>0)
744
break;
745
}
746
}
747
}
748
749
///---------------------------------------------------------------------------
750
template<typename IntegerPL,typename IntegerRet>
751
void ProjectAndLift<IntegerPL,IntegerRet>::find_single_point(){
752
753
size_t dim=AllSupps.size()-1;
754
assert(dim>=2);
755
756
vector<IntegerRet> start(1,GD);
757
vector<IntegerRet> final_latt_point;
758
lift_point_recursively(final_latt_point,start);
759
if(final_latt_point.size()>0){
760
SingleDeg1Point=final_latt_point;
761
if(verbose)
762
verboseOutput() << "Found point" << endl;
763
}
764
else{
765
if(verbose)
766
verboseOutput() << "No point found" << endl;
767
}
768
}
769
770
//---------------------------------------------------------------------------
771
template<typename IntegerPL,typename IntegerRet>
772
void ProjectAndLift<IntegerPL,IntegerRet>::initialize(const Matrix<IntegerPL>& Supps,size_t rank){
773
774
EmbDim=Supps.nr_of_columns(); // our embedding dimension
775
AllSupps.resize(EmbDim+1);
776
AllOrders.resize(EmbDim+1);
777
AllSupps[EmbDim]=Supps;
778
AllOrders[EmbDim]=order_supps(Supps);
779
StartRank=rank;
780
GD=1; // the default choice
781
verbose=true;
782
is_parallelotope=false;
783
no_crunch=true;
784
}
785
786
//---------------------------------------------------------------------------
787
template<typename IntegerPL,typename IntegerRet>
788
ProjectAndLift<IntegerPL,IntegerRet>::ProjectAndLift(){
789
790
}
791
//---------------------------------------------------------------------------
792
// General constructor
793
template<typename IntegerPL,typename IntegerRet>
794
ProjectAndLift<IntegerPL,IntegerRet>::ProjectAndLift(const Matrix<IntegerPL>& Supps,
795
const vector<boost::dynamic_bitset<> >& Ind,size_t rank){
796
797
initialize(Supps,rank);
798
StartInd=Ind;
799
}
800
801
//---------------------------------------------------------------------------
802
// Constructor for parallelotopes
803
template<typename IntegerPL,typename IntegerRet>
804
ProjectAndLift<IntegerPL,IntegerRet>::ProjectAndLift(const Matrix<IntegerPL>& Supps,
805
const vector<boost::dynamic_bitset<> >& Pair,
806
const vector<boost::dynamic_bitset<> >& ParaInPair,size_t rank){
807
808
initialize(Supps,rank);
809
is_parallelotope=true;
810
StartPair=Pair;
811
StartParaInPair=ParaInPair;
812
}
813
814
//---------------------------------------------------------------------------
815
template<typename IntegerPL,typename IntegerRet>
816
void ProjectAndLift<IntegerPL,IntegerRet>::set_verbose(bool on_off){
817
verbose=on_off;
818
}
819
820
//---------------------------------------------------------------------------
821
template<typename IntegerPL,typename IntegerRet>
822
void ProjectAndLift<IntegerPL,IntegerRet>::set_grading_denom(const IntegerRet GradingDenom){
823
GD=GradingDenom;
824
}
825
826
//---------------------------------------------------------------------------
827
template<typename IntegerPL,typename IntegerRet>
828
void ProjectAndLift<IntegerPL,IntegerRet>::set_excluded_point(const vector<IntegerRet>& excl_point){
829
excluded_point=excl_point;
830
}
831
832
//---------------------------------------------------------------------------
833
template<typename IntegerPL,typename IntegerRet>
834
void ProjectAndLift<IntegerPL,IntegerRet>::compute(bool all_points){
835
836
// Project-and-lift for lattice points in a polytope.
837
// The first coordinate is homogenizing. Its value for polytope points ism set by GD so that
838
// a grading denominator 1=1 can be accomodated.
839
// We need only the support hyperplanes Supps and the facet-vertex incidence matrix Ind.
840
// Its rows correspond to facets.
841
842
if(verbose)
843
verboseOutput() << "Projection" << endl;
844
compute_projections(EmbDim, StartInd,StartPair,StartParaInPair, StartRank);
845
if(all_points){
846
if(verbose)
847
verboseOutput() << "Lifting" << endl;
848
lift_points_by_generation();
849
}
850
else{
851
if(verbose)
852
verboseOutput() << "Try finding a lattice point" << endl;
853
find_single_point();
854
}
855
}
856
857
//---------------------------------------------------------------------------
858
template<typename IntegerPL,typename IntegerRet>
859
void ProjectAndLift<IntegerPL,IntegerRet>::put_eg1Points_into(Matrix<IntegerRet>& LattPoints){
860
861
while(!Deg1Points.empty()){
862
LattPoints.append(Deg1Points.front());
863
Deg1Points.pop_front();
864
}
865
}
866
867
//---------------------------------------------------------------------------
868
template<typename IntegerPL,typename IntegerRet>
869
void ProjectAndLift<IntegerPL,IntegerRet>::put_single_point_into(vector<IntegerRet>& LattPoint){
870
871
LattPoint=SingleDeg1Point;
872
}
873
//---------------------------------------------------------------------------
874
875
#ifdef NMZ_MIC_OFFLOAD
876
#pragma offload_attribute (pop)
877
#endif
878
879
} //end namespace libnormaliz
880
881