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
//---------------------------------------------------------------------------
25
#include<set>
26
27
#include "libnormaliz/matrix.h"
28
#include "libnormaliz/nmz_nauty.h"
29
#include "libnormaliz/cone.h"
30
#include "libnormaliz/full_cone.h"
31
32
namespace libnormaliz {
33
using namespace std;
34
35
template<typename Integer>
36
const Matrix<Integer>& Automorphism_Group<Integer>::getGens() const {
37
return Gens;
38
}
39
40
template<typename Integer>
41
const Matrix<Integer>& Automorphism_Group<Integer>::getLinForms() const{
42
return LinForms;
43
}
44
45
template<typename Integer>
46
const Matrix<Integer>& Automorphism_Group<Integer>::getSpecialLinForms() const{
47
return SpecialLinForms;
48
}
49
50
template<typename Integer>
51
vector<vector<key_t> > Automorphism_Group<Integer>::getGenPerms() const{
52
return GenPerms;
53
}
54
55
template<typename Integer>
56
mpz_class Automorphism_Group<Integer>::getOrder() const{
57
return order;
58
}
59
60
template<typename Integer>
61
vector<vector<key_t> > Automorphism_Group<Integer>::getLinFormPerms() const{
62
return LinFormPerms;
63
}
64
65
template<typename Integer>
66
vector<vector<key_t> > Automorphism_Group<Integer>::getGenOrbits() const{
67
return GenOrbits;
68
}
69
70
template<typename Integer>
71
vector<vector<key_t> > Automorphism_Group<Integer>::getLinFormOrbits() const{
72
return LinFormOrbits;
73
}
74
75
template<typename Integer>
76
vector<Matrix<Integer> > Automorphism_Group<Integer>::getLinMaps() const{
77
return LinMaps;
78
}
79
80
template<typename Integer>
81
vector<key_t> Automorphism_Group<Integer>::getCanLabellingGens() const{
82
return CanLabellingGens;
83
}
84
85
template<typename Integer>
86
bool Automorphism_Group<Integer>::isFromAmbientSpace() const{
87
return from_ambient_space;
88
}
89
90
template<typename Integer>
91
bool Automorphism_Group<Integer>::isFromHB() const{
92
return from_HB;
93
}
94
95
template<typename Integer>
96
bool Automorphism_Group<Integer>::isLinMapsComputed() const{
97
return LinMaps_computed;
98
}
99
100
template<typename Integer>
101
bool Automorphism_Group<Integer>::isGraded() const{
102
return graded;
103
}
104
105
template<typename Integer>
106
bool Automorphism_Group<Integer>::isInhomogeneous() const{
107
return inhomogeneous;
108
}
109
110
template<typename Integer>
111
void Automorphism_Group<Integer>::setInhomogeneous(bool on_off){
112
inhomogeneous=on_off;
113
}
114
115
template<typename Integer>
116
void Automorphism_Group<Integer>::reset(){
117
LinMaps_computed=false;
118
from_ambient_space=false;
119
graded=false;
120
inhomogeneous=false;
121
from_HB=false;
122
}
123
124
template<typename Integer>
125
Automorphism_Group<Integer>::Automorphism_Group(){
126
reset();
127
}
128
129
template<typename Integer>
130
bool Automorphism_Group<Integer>::make_linear_maps_primal(const Matrix<Integer>& GivenGens,const vector<vector<key_t> >& ComputedGenPerms){
131
132
LinMaps.clear();
133
vector<key_t> PreKey=GivenGens.max_rank_submatrix_lex();
134
vector<key_t> ImKey(PreKey.size());
135
for(size_t i=0;i<ComputedGenPerms.size();++i){
136
for(size_t j=0;j<ImKey.size();++j)
137
ImKey[j]=ComputedGenPerms[i][PreKey[j]];
138
Matrix<Integer> Pre=GivenGens.submatrix(PreKey);
139
Matrix<Integer> Im=GivenGens.submatrix(ImKey);
140
Integer denom,g;
141
Matrix<Integer> Map=Pre.solve(Im,denom);
142
g=Map.matrix_gcd();
143
if(g%denom !=0)
144
return false;
145
Map.scalar_division(denom);
146
if(Map.vol()!=1)
147
return false;
148
LinMaps.push_back(Map.transpose());
149
//Map.pretty_print(cout);
150
// cout << "--------------------------------------" << endl;
151
}
152
LinMaps_computed=true;
153
return true;
154
}
155
156
template<typename Integer>
157
bool Automorphism_Group<Integer>::compute(const Matrix<Integer>& ExtRays,const Matrix<Integer>& GivenGens, bool given_gens_are_extrays,
158
const Matrix<Integer>& SuppHyps,const Matrix<Integer>& GivenLinForms, bool given_lf_are_supps,
159
size_t nr_special_gens, const size_t nr_special_linforms){
160
Gens=ExtRays;
161
LinForms=SuppHyps;
162
SpecialLinForms=Matrix<Integer>(0,ExtRays[0].size());
163
for(size_t i=GivenLinForms.nr_of_rows()-nr_special_linforms;i<GivenLinForms.nr_of_rows();++i){
164
SpecialLinForms.append(GivenLinForms[i]);
165
}
166
167
from_HB=!given_gens_are_extrays;
168
from_ambient_space=!given_lf_are_supps;
169
170
vector<vector<long> > result=compute_automs(GivenGens,nr_special_gens, GivenLinForms,nr_special_linforms,order,CanType);
171
size_t nr_automs=(result.size()-3)/2; // the last 3 have special information
172
173
vector<vector<key_t> > ComputedGenPerms, ComputedLFPerms;
174
for(size_t i=0;i<nr_automs;++i){ // decode results
175
vector<key_t> dummy(result[0].size());
176
for(size_t j=0;j<dummy.size();++j)
177
dummy[j]=result[i][j];
178
ComputedGenPerms.push_back(dummy);
179
vector<key_t> dummy_too(result[nr_automs].size());
180
for(size_t j=0;j<dummy_too.size();++j)
181
dummy_too[j]=result[i+nr_automs][j];
182
LinFormPerms.push_back(dummy_too);
183
ComputedLFPerms.push_back(dummy_too);
184
}
185
186
if(!make_linear_maps_primal(GivenGens,ComputedGenPerms))
187
return false;
188
189
if(given_gens_are_extrays){
190
GenPerms=ComputedGenPerms;
191
GenOrbits=convert_to_orbits(result[result.size()-3]);
192
}
193
else{
194
gen_data_via_lin_maps();
195
}
196
197
if(given_lf_are_supps){
198
LinFormPerms=ComputedLFPerms;
199
LinFormOrbits=convert_to_orbits(result[result.size()-2]);
200
}
201
else{
202
linform_data_via_lin_maps();
203
}
204
205
CanLabellingGens.clear();
206
if(given_gens_are_extrays){
207
CanLabellingGens.resize(result[result.size()-1].size());
208
for(size_t i=0;i<CanLabellingGens.size();++i)
209
CanLabellingGens[i]=result[result.size()-1][i];
210
}
211
212
return true;
213
}
214
215
template<typename Integer>
216
void Automorphism_Group<Integer>::gen_data_via_lin_maps(){
217
218
GenPerms.clear();
219
map<vector<Integer>,key_t> S;
220
for(key_t k=0;k<Gens.nr_of_rows();++k)
221
S[Gens[k]]=k;
222
for(size_t i=0; i<LinMaps.size();++i){
223
vector<key_t> Perm(Gens.nr_of_rows());
224
for(key_t j=0;j<Perm.size();++j){
225
vector<Integer> Im=LinMaps[i].MxV(Gens[j]);
226
assert(S.find(Im)!=S.end()); // for safety
227
Perm[j]=S[Im];
228
}
229
GenPerms.push_back(Perm);
230
}
231
GenOrbits=orbits(GenPerms,Gens.nr_of_rows());
232
}
233
234
template<typename Integer>
235
void Automorphism_Group<Integer>::linform_data_via_lin_maps(){
236
237
LinFormPerms.clear();
238
map<vector<Integer>,key_t> S;
239
for(key_t k=0;k<LinForms.nr_of_rows();++k)
240
S[LinForms[k]]=k;
241
for(size_t i=0; i<LinMaps.size();++i){
242
vector<key_t> Perm(LinForms.nr_of_rows());
243
Integer dummy;
244
Matrix<Integer> LM=LinMaps[i].invert(dummy).transpose();
245
for(key_t j=0;j<Perm.size();++j){
246
vector<Integer> Im=LM.MxV(LinForms[j]);
247
assert(S.find(Im)!=S.end()); // for safety
248
Perm[j]=S[Im];
249
}
250
LinFormPerms.push_back(Perm);
251
}
252
LinFormOrbits=orbits(LinFormPerms,LinForms.nr_of_rows());
253
}
254
255
template<typename Integer>
256
void Automorphism_Group<Integer>::add_images_to_orbit(const vector<Integer>& v,set<vector<Integer> >& orbit) const{
257
258
for(size_t i=0;i<LinMaps.size();++i){
259
vector<Integer> w=LinMaps[i].MxV(v);
260
typename set<vector<Integer> >::iterator f;
261
f=orbit.find(w);
262
if(f!=orbit.end())
263
continue;
264
else{
265
orbit.insert(w);
266
add_images_to_orbit(w,orbit);
267
}
268
}
269
}
270
271
template<typename Integer>
272
list<vector<Integer> > Automorphism_Group<Integer>::orbit_primal(const vector<Integer>& v) const{
273
274
set<vector<Integer> > orbit;
275
add_images_to_orbit(v,orbit);
276
list<vector<Integer> > orbit_list;
277
for(auto c=orbit.begin();c!=orbit.end();++c)
278
orbit_list.push_back(*c);
279
return orbit_list;
280
}
281
282
/* MUCH TO DO
283
template<typename Integer>
284
IsoType<Integer>::IsoType(Full_Cone<Integer>& C, bool with_Hilbert_basis){
285
286
dim=C.getDim();
287
if(dim=0)
288
return;
289
290
if(with_Hilbert_basis){
291
if(!C.isComputed(ConeProperty::HilbertBasis)){
292
C.do_Hilbert_basis=true;
293
C.compute();
294
}
295
HilbertBasis=Matrix<Integer>(C.Hilbert_Basis);
296
}
297
298
if(!C.isComputed(ConeProperty::ExtremeRays)){
299
C.get_supphyps_from_copy(true);
300
C.get_supphyps_from_copy(true,true);
301
}
302
303
ExtremeRays=C.Generators.submatrix(C.Extreme_Rays_ind);
304
SupportHyperplanes=C.Support_Hyperplanes;
305
306
if(C.isComputed(ConeProperty::Multiplicity))
307
Multiplicity=C.multiplicity;
308
309
}*/
310
311
template<typename Integer>
312
IsoType<Integer>::IsoType(){ // constructs a dummy object
313
rank=0;
314
nrExtremeRays=1; // impossible
315
}
316
317
template<typename Integer>
318
IsoType<Integer>::IsoType(const Full_Cone<Integer>& C, bool& success){
319
320
success=false;
321
assert(C.isComputed(ConeProperty::AutomorphismGroup));
322
323
// we don't want the zero cone here. It should have been filtered out.
324
assert(C.dim>0);
325
// We insist that cones arriving here are have their extreme rays as generators
326
nrExtremeRays=C.getNrExtremeRays();
327
assert(nrExtremeRays==C.nr_gen);
328
329
if(C.isComputed(ConeProperty::Grading))
330
Grading=C.Grading;
331
if(C.inhomogeneous)
332
Truncation=C.Truncation;
333
334
if(C.Automs.isFromHB()) // not yet useful
335
return;
336
CanType=C.Automs.CanType;
337
CanLabellingGens=C.Automs.getCanLabellingGens();
338
rank=C.dim;
339
nrSupportHyperplanes=C.nrSupport_Hyperplanes;
340
if(C.isComputed(ConeProperty::Multiplicity))
341
Multiplicity=C.multiplicity;
342
343
if(C.isComputed(ConeProperty::HilbertBasis)){
344
HilbertBasis=Matrix<Integer>(0,rank);
345
ExtremeRays=C.Generators;
346
// we compute the coordinate transformation to the first max linearly indepndent
347
// of extreme rays in canonical order
348
CanBasisKey=ExtremeRays.max_rank_submatrix_lex(CanLabellingGens);
349
CanTransform=ExtremeRays.submatrix(CanBasisKey).invert(CanDenom);
350
351
// now we remove the extreme rays from the stored Hilbert CanBasisKey
352
// since the isomorphic copy knows its own extreme rays
353
if(C.Hilbert_Basis.size()>nrExtremeRays){ // otherwise nothing to do
354
set<vector<Integer> > ERSet;
355
typename set<vector<Integer> >::iterator e;
356
for(size_t i=0;i<nrExtremeRays;++i)
357
ERSet.insert(ExtremeRays[i]);
358
for(auto h=C.Hilbert_Basis.begin();h!=C.Hilbert_Basis.end();++h){
359
e=ERSet.find(*h);
360
if(e==ERSet.end())
361
HilbertBasis.append(*h);
362
}
363
}
364
}
365
success=true;
366
}
367
368
template<typename Integer>
369
const Matrix<Integer>& IsoType<Integer>::getHilbertBasis() const{
370
return HilbertBasis;
371
}
372
373
template<typename Integer>
374
const Matrix<Integer>& IsoType<Integer>::getCanTransform() const{
375
return CanTransform;
376
}
377
378
template<typename Integer>
379
Integer IsoType<Integer>::getCanDenom() const{
380
return CanDenom;
381
}
382
383
template<typename Integer>
384
bool IsoType<Integer>::isOfType(const Full_Cone<Integer>& C) const{
385
386
if(C.dim!=rank || C.nrSupport_Hyperplanes!=nrSupportHyperplanes
387
|| nrExtremeRays!=C.getNrExtremeRays())
388
return false;
389
if(!CanType.equal(C.Automs.CanType))
390
return false;
391
return true;
392
}
393
394
template<typename Integer>
395
mpq_class IsoType<Integer>::getMultiplicity() const{
396
return Multiplicity;
397
}
398
399
template<typename Integer>
400
Isomorphism_Classes<Integer>::Isomorphism_Classes(){
401
402
Classes.push_back(IsoType<Integer>());
403
}
404
405
template<typename Integer>
406
void Isomorphism_Classes<Integer>::add_type(Full_Cone<Integer>& C, bool& success){
407
408
Classes.push_back(IsoType<Integer>(C,success));
409
if(!success)
410
Classes.pop_back();
411
}
412
413
size_t NOT_FOUND=0;
414
size_t FOUND=0;
415
416
template<typename Integer>
417
const IsoType<Integer>& Isomorphism_Classes<Integer>::find_type(Full_Cone<Integer>& C, bool& found) const{
418
419
assert(C.getNrExtremeRays()==C.nr_gen);
420
found=false;
421
if(C.Automs.from_HB)
422
return *Classes.begin();
423
auto it=Classes.begin();
424
++it;
425
for(;it!=Classes.end();++it){
426
if(it->isOfType(C)){
427
found=true;
428
FOUND++;
429
return *it;
430
}
431
}
432
NOT_FOUND++;
433
return *Classes.begin();
434
}
435
436
list<boost::dynamic_bitset<> > partition(size_t n, const vector<vector<key_t> >& Orbits){
437
// produces a list of bitsets, namely the indicator vectors of the key vectors in Orbits
438
439
list<boost::dynamic_bitset<> > Part;
440
for(size_t i=0;i<Orbits.size();++i){
441
boost::dynamic_bitset<> p(n);
442
for(size_t j=0;j<Orbits[i].size();++j)
443
p.set(Orbits[i][j],true);
444
Part.push_back(p);
445
}
446
return Part;
447
}
448
449
vector<vector<key_t> > keys(const list<boost::dynamic_bitset<> >& Partition){
450
// inverse operation of partition
451
vector<vector<key_t> > Keys;
452
auto p=Partition.begin();
453
for(;p!=Partition.end();++p){
454
vector<key_t> key;
455
for(size_t j=0;j< p->size();++j)
456
if(p->test(j))
457
key.push_back(j);
458
Keys.push_back(key);
459
}
460
return Keys;
461
}
462
463
464
list<boost::dynamic_bitset<> > join_partitions(const list<boost::dynamic_bitset<> >& P1,
465
const list<boost::dynamic_bitset<> >& P2){
466
// computes the join of two partitions given as lusts of indicator vectors
467
list<boost::dynamic_bitset<> > J=P1; // work copy pf P1
468
auto p2=P2.begin();
469
for(;p2!=P2.end();++p2){
470
auto p1=J.begin();
471
for(;p1!=J.end();++p1){ // search the first member of J that intersects p1
472
if((*p2).intersects(*p1))
473
break;
474
}
475
if((*p2).is_subset_of(*p1)) // is contained in that member, nothing to do
476
continue;
477
// now we join the members of J that intersect p2
478
assert(p1!=J.end()); // to be on the safe side
479
auto p3=p1;
480
p3++;
481
while(p3!=J.end()){
482
if((*p2).intersects(*p3)){
483
*p1= *p1 | *p3; //the union
484
p3=J.erase(p3);
485
}else
486
p3++;
487
}
488
}
489
return J;
490
}
491
492
vector<vector<key_t> > orbits(const vector<vector<key_t> >& Perms, size_t N){
493
// Perms is a list of permutations of 0,...,N-1
494
495
vector<vector<key_t> > Orbits;
496
if(Perms.size()==0){ //each element is its own orbit
497
Orbits.reserve(N);
498
for(size_t i=0;i<N;++i)
499
Orbits.push_back(vector<key_t>(1,i));
500
return Orbits;
501
}
502
vector<bool> InOrbit(N,false);
503
for(size_t i=0;i<N;++i){
504
if(InOrbit[i])
505
continue;
506
vector<key_t> NewOrbit;
507
NewOrbit.push_back(i);
508
InOrbit[i]=true;
509
for(size_t j=0;j<NewOrbit.size();++j){
510
for(size_t k=0;k<Perms.size();++k){
511
key_t im=Perms[k][NewOrbit[j]];
512
if(InOrbit[im])
513
continue;
514
NewOrbit.push_back(im);
515
InOrbit[im]=true;
516
}
517
}
518
sort(NewOrbit.begin(),NewOrbit.end());
519
Orbits.push_back(NewOrbit);
520
}
521
522
return Orbits;
523
}
524
525
526
/*
527
*/
528
529
/*
530
vector<vector<key_t> > orbits(const vector<vector<key_t> >& Perms, size_t N){
531
532
vector<vector<key_t> > Orbits;
533
if(Perms.size()==0){ //each element is its own orbit
534
Orbits.reserve(N);
535
for(size_t i=0;i<N;++i)
536
Orbits.push_back(vector<key_t>(1,i));
537
return Orbits;
538
}
539
Orbits=cycle_decomposition(Perms[0],true); // with fixed points!
540
list<boost::dynamic_bitset<> > P1=partition(Perms[0].size(),Orbits);
541
for(size_t i=1;i<Perms.size();++i){
542
vector<vector<key_t> > Orbits_1=cycle_decomposition(Perms[i]);
543
list<boost::dynamic_bitset<> > P2=partition(Perms[0].size(),Orbits_1);
544
P1=join_partitions(P1,P2);
545
}
546
return keys(P1);
547
}
548
*/
549
550
vector<vector<key_t> > convert_to_orbits(const vector<long>& raw_orbits){
551
552
vector<key_t> key(raw_orbits.size());
553
vector<vector<key_t> > orbits;
554
for(key_t i=0;i<raw_orbits.size();++i){
555
if(raw_orbits[i]==(long) i){
556
orbits.push_back(vector<key_t>(1,i));
557
key[i]=orbits.size()-1;
558
}
559
else{
560
orbits[key[raw_orbits[i]]].push_back(i);
561
}
562
}
563
return orbits;
564
}
565
566
567
vector<vector<key_t> > cycle_decomposition(vector<key_t> perm, bool with_fixed_points){
568
// computes the cacle decomposition of a permutation with or wothout fixed points
569
570
vector<vector<key_t> > dec;
571
vector<bool> in_cycle(perm.size(),false);
572
for (size_t i=0;i<perm.size();++i){
573
if(in_cycle[i])
574
continue;
575
if(perm[i]==i){
576
if(!with_fixed_points)
577
continue;
578
vector<key_t> cycle(1,i);
579
in_cycle[i]=true;
580
dec.push_back(cycle);
581
continue;
582
}
583
in_cycle[i]=true;
584
key_t next=i;
585
vector<key_t> cycle(1,i);
586
while(true){
587
next=perm[next];
588
if(next==i)
589
break;
590
cycle.push_back(next);
591
in_cycle[next]=true;
592
}
593
dec.push_back(cycle);
594
}
595
return dec;
596
}
597
598
void pretty_print_cycle_dec(const vector<vector<key_t> >& dec, ostream& out){
599
600
for(size_t i=0;i<dec.size();++i){
601
out << "(";
602
for(size_t j=0;j<dec[i].size();++j){
603
out << dec[i][j];
604
if(j!=dec[i].size()-1)
605
out << " ";
606
}
607
out << ") ";
608
609
}
610
out << "--" << endl;
611
}
612
613
template<typename Integer>
614
vector<vector<long> > compute_automs(const Matrix<Integer>& Gens, const size_t nr_special_gens, const Matrix<Integer>& LinForms,
615
const size_t nr_special_linforms, mpz_class& group_order, BinaryMatrix<Integer>& CanType){
616
617
vector<vector<long> > Automs=compute_automs_by_nauty(Gens.get_elements(), nr_special_gens, LinForms.get_elements(),
618
nr_special_linforms, group_order, CanType);
619
return Automs;
620
}
621
622
} // namespace
623
624