CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

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

Views: 418386
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
#include <list>
25
26
#include "libQnormaliz/Qvector_operations.h"
27
#include "libQnormaliz/Qmap_operations.h"
28
#include "libQnormaliz/Qconvert.h"
29
#include "libQnormaliz/Qcone.h"
30
#include "libQnormaliz/Qfull_cone.h"
31
32
namespace libQnormaliz {
33
using namespace std;
34
35
// adds the signs inequalities given by Signs to Inequalities
36
template<typename Number>
37
Matrix<Number> sign_inequalities(const vector< vector<Number> >& Signs) {
38
if (Signs.size() != 1) {
39
throw BadInputException("ERROR: Bad signs matrix, has "
40
+ toString(Signs.size()) + " rows (should be 1)!");
41
}
42
size_t dim = Signs[0].size();
43
Matrix<Number> Inequ(0,dim);
44
vector<Number> ineq(dim,0);
45
for (size_t i=0; i<dim; i++) {
46
Number sign = Signs[0][i];
47
if (sign == 1 || sign == -1) {
48
ineq[i] = sign;
49
Inequ.append(ineq);
50
ineq[i] = 0;
51
} else if (sign != 0) {
52
throw BadInputException("Bad signs matrix, has entry "
53
+ toString(sign) + " (should be -1, 1 or 0)!");
54
}
55
}
56
return Inequ;
57
}
58
59
template<typename Number>
60
Matrix<Number> strict_sign_inequalities(const vector< vector<Number> >& Signs) {
61
if (Signs.size() != 1) {
62
throw BadInputException("ERROR: Bad signs matrix, has "
63
+ toString(Signs.size()) + " rows (should be 1)!");
64
}
65
size_t dim = Signs[0].size();
66
Matrix<Number> Inequ(0,dim);
67
vector<Number> ineq(dim,0);
68
ineq[dim-1]=-1;
69
for (size_t i=0; i<dim-1; i++) { // last component of strict_signs always 0
70
Number sign = Signs[0][i];
71
if (sign == 1 || sign == -1) {
72
ineq[i] = sign;
73
Inequ.append(ineq);
74
ineq[i] = 0;
75
} else if (sign != 0) {
76
throw BadInputException("Bad signs matrix, has entry "
77
+ toString(sign) + " (should be -1, 1 or 0)!");
78
}
79
}
80
return Inequ;
81
}
82
83
template<typename Number>
84
vector<vector<Number> > find_input_matrix(const map< InputType, vector< vector<Number> > >& multi_input_data,
85
const InputType type){
86
87
typename map< InputType , vector< vector<Number> > >::const_iterator it;
88
it = multi_input_data.find(type);
89
if (it != multi_input_data.end())
90
return(it->second);
91
92
vector< vector<Number> > dummy;
93
return(dummy);
94
}
95
96
template<typename Number>
97
void insert_column(vector< vector<Number> >& mat, size_t col, Number entry){
98
99
vector<Number> help(mat[0].size()+1);
100
for(size_t i=0;i<mat.size();++i){
101
for(size_t j=0;j<col;++j)
102
help[j]=mat[i][j];
103
help[col]=entry;
104
for(size_t j=col;j<mat[i].size();++j)
105
help[j+1]=mat[i][j];
106
mat[i]=help;
107
}
108
}
109
110
template<typename Number>
111
void insert_zero_column(vector< vector<Number> >& mat, size_t col){
112
// Number entry=0;
113
insert_column<Number>(mat,col,0);
114
}
115
116
template<typename Number>
117
void Cone<Number>::homogenize_input(map< InputType, vector< vector<Number> > >& multi_input_data){
118
119
typename map< InputType , vector< vector<Number> > >::iterator it;
120
it = multi_input_data.begin();
121
for(;it!=multi_input_data.end();++it){
122
switch(it->first){
123
case Type::dehomogenization:
124
throw BadInputException("Type dehomogenization not allowed with inhomogeneous input!");
125
break;
126
case Type::inhom_inequalities: // nothing to do
127
case Type::inhom_equations:
128
case Type::inhom_congruences:
129
case Type::polyhedron:
130
case Type::vertices:
131
case Type::support_hyperplanes:
132
case Type::grading: // already taken care of
133
break;
134
case Type::strict_inequalities:
135
insert_column<Number>(it->second,dim-1,-1);
136
break;
137
case Type::offset:
138
insert_column<Number>(it->second,dim-1,1);
139
break;
140
default: // is correct for signs and strict_signs !
141
insert_zero_column<Number>(it->second,dim-1);
142
break;
143
}
144
}
145
}
146
147
//---------------------------------------------------------------------------
148
149
template<typename Number>
150
Cone<Number>::Cone(InputType input_type, const vector< vector<Number> >& Input) {
151
// convert to a map
152
map< InputType, vector< vector<Number> > > multi_input_data;
153
multi_input_data[input_type] = Input;
154
process_multi_input(multi_input_data);
155
}
156
157
template<typename Number>
158
Cone<Number>::Cone(InputType type1, const vector< vector<Number> >& Input1,
159
InputType type2, const vector< vector<Number> >& Input2) {
160
if (type1 == type2) {
161
throw BadInputException("Input types must pairwise different!");
162
}
163
// convert to a map
164
map< InputType, vector< vector<Number> > > multi_input_data;
165
multi_input_data[type1] = Input1;
166
multi_input_data[type2] = Input2;
167
process_multi_input(multi_input_data);
168
}
169
170
template<typename Number>
171
Cone<Number>::Cone(InputType type1, const vector< vector<Number> >& Input1,
172
InputType type2, const vector< vector<Number> >& Input2,
173
InputType type3, const vector< vector<Number> >& Input3) {
174
if (type1 == type2 || type1 == type3 || type2 == type3) {
175
throw BadInputException("Input types must be pairwise different!");
176
}
177
// convert to a map
178
map< InputType, vector< vector<Number> > > multi_input_data;
179
multi_input_data[type1] = Input1;
180
multi_input_data[type2] = Input2;
181
multi_input_data[type3] = Input3;
182
process_multi_input(multi_input_data);
183
}
184
185
template<typename Number>
186
Cone<Number>::Cone(const map< InputType, vector< vector<Number> > >& multi_input_data) {
187
process_multi_input(multi_input_data);
188
}
189
190
//---------------------------------------------------------------------------
191
192
template<typename Number>
193
Cone<Number>::Cone(InputType input_type, const Matrix<Number>& Input) {
194
// convert to a map
195
map< InputType, vector< vector<Number> > >multi_input_data;
196
multi_input_data[input_type] = Input.get_elements();
197
process_multi_input(multi_input_data);
198
}
199
200
template<typename Number>
201
Cone<Number>::Cone(InputType type1, const Matrix<Number>& Input1,
202
InputType type2, const Matrix<Number>& Input2) {
203
if (type1 == type2) {
204
throw BadInputException("Input types must pairwise different!");
205
}
206
// convert to a map
207
map< InputType, vector< vector<Number> > > multi_input_data;
208
multi_input_data[type1] = Input1.get_elements();
209
multi_input_data[type2] = Input2.get_elements();
210
process_multi_input(multi_input_data);
211
}
212
213
template<typename Number>
214
Cone<Number>::Cone(InputType type1, const Matrix<Number>& Input1,
215
InputType type2, const Matrix<Number>& Input2,
216
InputType type3, const Matrix<Number>& Input3) {
217
if (type1 == type2 || type1 == type3 || type2 == type3) {
218
throw BadInputException("Input types must be pairwise different!");
219
}
220
// convert to a map
221
map< InputType, vector< vector<Number> > > multi_input_data;
222
multi_input_data[type1] = Input1.get_elements();
223
multi_input_data[type2] = Input2.get_elements();
224
multi_input_data[type3] = Input3.get_elements();
225
process_multi_input(multi_input_data);
226
}
227
228
template<typename Number>
229
Cone<Number>::Cone(const map< InputType, Matrix<Number> >& multi_input_data_Matrix){
230
map< InputType, vector< vector<Number> > > multi_input_data;
231
auto it = multi_input_data_Matrix.begin();
232
for(; it != multi_input_data_Matrix.end(); ++it){
233
multi_input_data[it->first]=it->second.get_elements();
234
}
235
process_multi_input(multi_input_data);
236
}
237
238
//---------------------------------------------------------------------------
239
240
241
template<typename Number>
242
void Cone<Number>::process_multi_input(const map< InputType, vector< vector<Number> > >& multi_input_data_const) {
243
initialize();
244
map< InputType, vector< vector<Number> > > multi_input_data(multi_input_data_const);
245
// find basic input type
246
bool lattice_ideal_input=false;
247
bool inhom_input=false;
248
size_t nr_latt_gen=0, nr_cone_gen=0;
249
250
auto it = multi_input_data.begin();
251
for(; it != multi_input_data.end(); ++it)
252
for(size_t i=0;i < it->second.size();++i){
253
for(size_t j=0;j<it->second[i].size();++j)
254
it->second[i][j].canonicalize();
255
v_simplify(it->second[i]);
256
}
257
258
inequalities_present=false; //control choice of positive orthant
259
260
if( exists_element(multi_input_data,Type::lattice)
261
|| exists_element(multi_input_data,Type::cone_and_lattice)
262
|| exists_element(multi_input_data,Type::congruences)
263
|| exists_element(multi_input_data,Type::inhom_congruences)
264
|| exists_element(multi_input_data,Type::dehomogenization)
265
|| exists_element(multi_input_data,Type::offset)
266
|| exists_element(multi_input_data,Type::grading))
267
throw BadInputException("Input types not allowed for field coefficients");
268
269
// NEW: Empty matrix have syntactical influence
270
it = multi_input_data.begin();
271
for(; it != multi_input_data.end(); ++it) {
272
switch (it->first) {
273
case Type::inhom_inequalities:
274
case Type::inhom_equations:
275
case Type::inhom_congruences:
276
case Type::strict_inequalities:
277
case Type::strict_signs:
278
inhom_input=true;
279
case Type::signs:
280
case Type::inequalities:
281
case Type::equations:
282
case Type::congruences:
283
break;
284
case Type::lattice_ideal:
285
lattice_ideal_input=true;
286
break;
287
case Type::polyhedron:
288
inhom_input=true;
289
case Type::integral_closure:
290
case Type::rees_algebra:
291
case Type::polytope:
292
case Type::cone:
293
case Type::subspace:
294
nr_cone_gen++;
295
break;
296
case Type::normalization:
297
case Type::cone_and_lattice:
298
nr_cone_gen++;
299
case Type::lattice:
300
case Type::saturation:
301
nr_latt_gen++;
302
break;
303
case Type::vertices:
304
case Type::offset:
305
inhom_input=true;
306
default:
307
break;
308
}
309
310
switch (it->first) { // chceck existence of inrqualities
311
case Type::inhom_inequalities:
312
case Type::strict_inequalities:
313
case Type::strict_signs:
314
case Type::signs:
315
case Type::inequalities:
316
case Type::excluded_faces:
317
case Type::support_hyperplanes:
318
inequalities_present=true;
319
default:
320
break;
321
}
322
323
}
324
325
bool gen_error=false;
326
if(nr_cone_gen>2)
327
gen_error=true;
328
329
if(nr_cone_gen==2 && (!exists_element(multi_input_data,Type::subspace)
330
|| !(exists_element(multi_input_data,Type::cone)
331
|| exists_element(multi_input_data,Type::cone_and_lattice)
332
|| exists_element(multi_input_data,Type::integral_closure)
333
|| exists_element(multi_input_data,Type::normalization) ) )
334
)
335
gen_error=true;
336
337
if(gen_error){
338
throw BadInputException("Illegal combination of cone generator types!");
339
}
340
341
342
if(nr_latt_gen>1){
343
throw BadInputException("Only one matrix of lattice generators allowed!");
344
}
345
if(lattice_ideal_input){
346
if(multi_input_data.size() > 2 || (multi_input_data.size()==2 && !exists_element(multi_input_data,Type::grading))){
347
throw BadInputException("Only grading allowed with lattice_ideal!");
348
}
349
}
350
if(inhom_input){
351
if(exists_element(multi_input_data,Type::dehomogenization) || exists_element(multi_input_data,Type::support_hyperplanes)){
352
throw BadInputException("Types dehomogenization and support_hyperplanes not allowed with inhomogeneous input!");
353
}
354
}
355
if(inhom_input || exists_element(multi_input_data,Type::dehomogenization)){
356
if(exists_element(multi_input_data,Type::rees_algebra) || exists_element(multi_input_data,Type::polytope)){
357
throw BadInputException("Types polytope and rees_algebra not allowed with inhomogeneous input or hehomogenizaion!");
358
}
359
if(exists_element(multi_input_data,Type::excluded_faces)){
360
throw BadInputException("Type excluded_faces not allowed with inhomogeneous input or dehomogenization!");
361
}
362
}
363
if(exists_element(multi_input_data,Type::grading) && exists_element(multi_input_data,Type::polytope)){
364
throw BadInputException("No explicit grading allowed with polytope!");
365
}
366
367
// remove empty matrices
368
it = multi_input_data.begin();
369
for(; it != multi_input_data.end();) {
370
if (it->second.size() == 0)
371
multi_input_data.erase(it++);
372
else
373
++it;
374
}
375
376
if(multi_input_data.size()==0){
377
throw BadInputException("All input matrices empty!");
378
}
379
380
//determine dimension
381
it = multi_input_data.begin();
382
size_t inhom_corr = 0; // correction in the inhom_input case
383
if (inhom_input) inhom_corr = 1;
384
dim = it->second.front().size() - type_nr_columns_correction(it->first) + inhom_corr;
385
386
// We now process input types that are independent of generators, constraints, lattice_ideal
387
// check for excluded faces
388
ExcludedFaces = find_input_matrix(multi_input_data,Type::excluded_faces);
389
PreComputedSupportHyperplanes = find_input_matrix(multi_input_data,Type::support_hyperplanes);
390
391
// check consistence of dimension
392
it = multi_input_data.begin();
393
size_t test_dim;
394
for (; it != multi_input_data.end(); ++it) {
395
test_dim = it->second.front().size() - type_nr_columns_correction(it->first) + inhom_corr;
396
if (test_dim != dim) {
397
throw BadInputException("Inconsistent dimensions in input!");
398
}
399
}
400
401
if(inhom_input)
402
homogenize_input(multi_input_data);
403
404
// check for dehomogenization
405
vector< vector<Number> > lf = find_input_matrix(multi_input_data,Type::dehomogenization);
406
if (lf.size() > 1) {
407
throw BadInputException("Bad dehomogenization, has "
408
+ toString(lf.size()) + " rows (should be 1)!");
409
}
410
if(lf.size()==1){
411
setDehomogenization(lf[0]);
412
}
413
414
// now we can unify implicit and explicit truncation
415
// Note: implicit and explicit truncation have already been excluded
416
if (inhom_input) {
417
Dehomogenization.resize(dim,0),
418
Dehomogenization[dim-1]=1;
419
is_Computed.set(ConeProperty::Dehomogenization);
420
}
421
if(isComputed(ConeProperty::Dehomogenization))
422
inhomogeneous=true;
423
424
if(lattice_ideal_input){
425
prepare_input_lattice_ideal(multi_input_data);
426
}
427
428
Matrix<Number> LatticeGenerators(0,dim);
429
prepare_input_generators(multi_input_data, LatticeGenerators);
430
431
Matrix<Number> Equations(0,dim), Congruences(0,dim+1);
432
Matrix<Number> Inequalities(0,dim);
433
prepare_input_constraints(multi_input_data,Equations,Congruences,Inequalities);
434
435
// set default values if necessary
436
if(inhom_input && LatticeGenerators.nr_of_rows()!=0 && !exists_element(multi_input_data,Type::offset)){
437
vector<Number> offset(dim);
438
offset[dim-1]=1;
439
LatticeGenerators.append(offset);
440
}
441
if(inhom_input && Generators.nr_of_rows()!=0 && !exists_element(multi_input_data,Type::vertices)
442
&& !exists_element(multi_input_data,Type::polyhedron)){
443
vector<Number> vertex(dim);
444
vertex[dim-1]=1;
445
Generators.append(vertex);
446
}
447
448
if(Inequalities.nr_of_rows()>0 && Generators.nr_of_rows()>0){ // eliminate superfluous inequalities
449
vector<key_t> essential;
450
for(size_t i=0;i<Inequalities.nr_of_rows();++i){
451
for (size_t j=0;j<Generators.nr_of_rows();++j){
452
if(v_scalar_product(Inequalities[i],Generators[j])<0){
453
essential.push_back(i);
454
break;
455
}
456
}
457
}
458
if(essential.size()<Inequalities.nr_of_rows())
459
Inequalities=Inequalities.submatrix(essential);
460
}
461
462
// cout << "Ineq " << Inequalities.nr_of_rows() << endl;
463
464
process_lattice_data(LatticeGenerators,Congruences,Equations);
465
466
bool cone_sat_eq=no_lattice_restriction;
467
bool cone_sat_cong=no_lattice_restriction;
468
469
// cout << "nolatrest " << no_lattice_restriction << endl;
470
471
if(Inequalities.nr_of_rows()==0 && Generators.nr_of_rows()!=0){
472
if(!no_lattice_restriction){
473
cone_sat_eq=true;
474
for(size_t i=0;i<Generators.nr_of_rows() && cone_sat_eq;++i)
475
for(size_t j=0;j<Equations.nr_of_rows() && cone_sat_eq ;++j)
476
if(v_scalar_product(Generators[i],Equations[j])!=0){
477
cone_sat_eq=false;
478
}
479
}
480
481
if(cone_sat_eq && !cone_sat_cong){ // multiply generators by anniullator mod sublattice
482
for(size_t i=0;i<Generators.nr_of_rows();++i)
483
v_scalar_multiplication(Generators[i],BasisChange.getAnnihilator());
484
cone_sat_cong=true;
485
}
486
}
487
488
if((Inequalities.nr_of_rows()!=0 || !cone_sat_eq) && Generators.nr_of_rows()!=0){
489
Sublattice_Representation<Number> ConeLatt(Generators,true);
490
Full_Cone<Number> TmpCone(ConeLatt.to_sublattice(Generators));
491
TmpCone.dualize_cone();
492
Inequalities.append(ConeLatt.from_sublattice_dual(TmpCone.Support_Hyperplanes));
493
Generators=Matrix<Number>(0,dim); // Generators now converted into inequalities
494
}
495
496
assert(Inequalities.nr_of_rows()==0 || Generators.nr_of_rows()==0);
497
498
if(Generators.nr_of_rows()==0)
499
prepare_input_type_4(Inequalities); // inserts default inequalties if necessary
500
else{
501
is_Computed.set(ConeProperty::Generators);
502
is_Computed.set(ConeProperty::Sublattice);
503
}
504
505
checkDehomogenization();
506
507
setWeights(); // make matrix of weights for sorting
508
509
if(PreComputedSupportHyperplanes.nr_of_rows()>0){
510
check_precomputed_support_hyperplanes();
511
SupportHyperplanes=PreComputedSupportHyperplanes;
512
is_Computed.set(ConeProperty::SupportHyperplanes);
513
}
514
515
BasisChangePointed=BasisChange;
516
517
is_Computed.set(ConeProperty::IsInhomogeneous);
518
is_Computed.set(ConeProperty::EmbeddingDim);
519
520
/* if(ExcludedFaces.nr_of_rows()>0){ // Nothing to check anymore
521
check_excluded_faces();
522
} */
523
524
/*
525
cout <<"-----------------------" << endl;
526
cout << "Gen " << endl;
527
Generators.pretty_print(cout);
528
cout << "Supp " << endl;
529
SupportHyperplanes.pretty_print(cout);
530
cout << "A" << endl;
531
BasisChange.get_A().pretty_print(cout);
532
cout << "B" << endl;
533
BasisChange.get_B().pretty_print(cout);
534
cout <<"-----------------------" << endl;
535
*/
536
}
537
538
539
//---------------------------------------------------------------------------
540
541
template<typename Number>
542
void Cone<Number>::prepare_input_constraints(const map< InputType, vector< vector<Number> > >& multi_input_data,
543
Matrix<Number>& Equations, Matrix<Number>& Congruences, Matrix<Number>& Inequalities) {
544
545
Matrix<Number> Signs(0,dim), StrictSigns(0,dim);
546
547
SupportHyperplanes=Matrix<Number>(0,dim);
548
549
typename map< InputType , vector< vector<Number> > >::const_iterator it=multi_input_data.begin();
550
551
it = multi_input_data.begin();
552
for (; it != multi_input_data.end(); ++it) {
553
554
switch (it->first) {
555
case Type::strict_inequalities:
556
case Type::inequalities:
557
case Type::inhom_inequalities:
558
case Type::excluded_faces:
559
Inequalities.append(it->second);
560
break;
561
case Type::equations:
562
case Type::inhom_equations:
563
Equations.append(it->second);
564
break;
565
case Type::congruences:
566
case Type::inhom_congruences:
567
Congruences.append(it->second);
568
break;
569
case Type::signs:
570
Signs = sign_inequalities(it->second);
571
break;
572
case Type::strict_signs:
573
StrictSigns = strict_sign_inequalities(it->second);
574
break;
575
default:
576
break;
577
}
578
}
579
if(!BC_set) compose_basis_change(Sublattice_Representation<Number>(dim));
580
Matrix<Number> Help(Signs); // signs first !!
581
Help.append(StrictSigns); // then strict signs
582
Help.append(Inequalities);
583
Inequalities=Help;
584
}
585
586
//---------------------------------------------------------------------------
587
template<typename Number>
588
void Cone<Number>::prepare_input_generators(map< InputType, vector< vector<Number> > >& multi_input_data, Matrix<Number>& LatticeGenerators) {
589
590
if(exists_element(multi_input_data,Type::vertices)){
591
for(size_t i=0;i<multi_input_data[Type::vertices].size();++i)
592
if(multi_input_data[Type::vertices][i][dim-1] <= 0) {
593
throw BadInputException("Vertex has non-positive denominator!");
594
}
595
}
596
597
if(exists_element(multi_input_data,Type::polyhedron)){
598
for(size_t i=0;i<multi_input_data[Type::polyhedron].size();++i)
599
if(multi_input_data[Type::polyhedron][i][dim-1] < 0) {
600
throw BadInputException("Polyhedron vertex has negative denominator!");
601
}
602
}
603
604
typename map< InputType , vector< vector<Number> > >::const_iterator it=multi_input_data.begin();
605
// find specific generator type -- there is only one, as checked already
606
607
normalization=false;
608
609
// check for subspace
610
BasisMaxSubspace = find_input_matrix(multi_input_data,Type::subspace);
611
if(BasisMaxSubspace.nr_of_rows()==0)
612
BasisMaxSubspace=Matrix<Number>(0,dim);
613
614
vector<Number> neg_sum_subspace(dim,0);
615
for(size_t i=0;i<BasisMaxSubspace.nr_of_rows();++i)
616
neg_sum_subspace=v_add(neg_sum_subspace,BasisMaxSubspace[i]);
617
v_scalar_multiplication<Number>(neg_sum_subspace,-1);
618
619
620
Generators=Matrix<Number>(0,dim);
621
for(; it != multi_input_data.end(); ++it) {
622
switch (it->first) {
623
case Type::normalization:
624
case Type::cone_and_lattice:
625
normalization=true;
626
LatticeGenerators.append(it->second);
627
if(BasisMaxSubspace.nr_of_rows()>0)
628
LatticeGenerators.append(BasisMaxSubspace);
629
case Type::vertices:
630
case Type::polyhedron:
631
case Type::cone:
632
case Type::integral_closure:
633
Generators.append(it->second);
634
break;
635
case Type::subspace:
636
Generators.append(it->second);
637
Generators.append(neg_sum_subspace);
638
break;
639
case Type::polytope:
640
Generators.append(prepare_input_type_2(it->second));
641
break;
642
case Type::rees_algebra:
643
Generators.append(prepare_input_type_3(it->second));
644
break;
645
case Type::lattice:
646
LatticeGenerators.append(it->second);
647
break;
648
case Type::saturation:
649
LatticeGenerators.append(it->second);
650
LatticeGenerators.saturate();
651
break;
652
case Type::offset:
653
if(it->second.size()>1){
654
throw BadInputException("Only one offset allowed!");
655
}
656
LatticeGenerators.append(it->second);
657
break;
658
default: break;
659
}
660
}
661
}
662
663
//---------------------------------------------------------------------------
664
665
template<typename Number>
666
void Cone<Number>::process_lattice_data(const Matrix<Number>& LatticeGenerators, Matrix<Number>& Congruences, Matrix<Number>& Equations) {
667
668
if(!BC_set)
669
compose_basis_change(Sublattice_Representation<Number>(dim));
670
671
bool no_constraints=(Congruences.nr_of_rows()==0) && (Equations.nr_of_rows()==0);
672
bool only_cone_gen=(Generators.nr_of_rows()!=0) && no_constraints && (LatticeGenerators.nr_of_rows()==0);
673
674
no_lattice_restriction=true;
675
676
if(only_cone_gen){
677
Sublattice_Representation<Number> Basis_Change(Generators,true);
678
compose_basis_change(Basis_Change);
679
return;
680
}
681
682
if(normalization && no_constraints){
683
Sublattice_Representation<Number> Basis_Change(Generators,false);
684
compose_basis_change(Basis_Change);
685
return;
686
}
687
688
no_lattice_restriction=false;
689
690
if(Generators.nr_of_rows()!=0){
691
Equations.append(Generators.kernel());
692
}
693
694
if(LatticeGenerators.nr_of_rows()!=0){
695
Sublattice_Representation<Number> GenSublattice(LatticeGenerators,false);
696
if((Equations.nr_of_rows()==0) && (Congruences.nr_of_rows()==0)){
697
compose_basis_change(GenSublattice);
698
return;
699
}
700
// Congruences.append(GenSublattice.getCongruencesMatrix());
701
Equations.append(GenSublattice.getEquationsMatrix());
702
}
703
704
/* if (Congruences.nr_of_rows() > 0) {
705
bool zero_modulus;
706
Matrix<Number> Ker_Basis=Congruences.solve_congruences(zero_modulus);
707
if(zero_modulus) {
708
throw BadInputException("Modulus 0 in congruence!");
709
}
710
Sublattice_Representation<Number> Basis_Change(Ker_Basis,false);
711
compose_basis_change(Basis_Change);
712
}*/
713
714
if (Equations.nr_of_rows()>0) {
715
Matrix<Number> Ker_Basis=BasisChange.to_sublattice_dual(Equations).kernel();
716
Sublattice_Representation<Number> Basis_Change(Ker_Basis,true);
717
compose_basis_change(Basis_Change);
718
}
719
}
720
721
//---------------------------------------------------------------------------
722
723
template<typename Number>
724
void Cone<Number>::prepare_input_type_4(Matrix<Number>& Inequalities) {
725
726
if (!inequalities_present) {
727
if (verbose) {
728
verboseOutput() << "No inequalities specified in constraint mode, using non-negative orthant." << endl;
729
}
730
if(inhomogeneous){
731
vector<Number> test(dim);
732
test[dim-1]=1;
733
size_t matsize=dim;
734
if(test==Dehomogenization) // in this case "last coordinate >= 0" will come in through the dehomogenization
735
matsize=dim-1; // we don't check for any other coincidence
736
Inequalities= Matrix<Number>(matsize,dim);
737
for(size_t j=0;j<matsize;++j)
738
Inequalities[j][j]=1;
739
}
740
else
741
Inequalities = Matrix<Number>(dim);
742
}
743
if(inhomogeneous)
744
SupportHyperplanes.append(Dehomogenization);
745
SupportHyperplanes.append(Inequalities);
746
}
747
748
749
//---------------------------------------------------------------------------
750
751
/* polytope input */
752
template<typename Number>
753
Matrix<Number> Cone<Number>::prepare_input_type_2(const vector< vector<Number> >& Input) {
754
size_t j;
755
size_t nr = Input.size();
756
//append a column of 1
757
Matrix<Number> Generators(nr, dim);
758
for (size_t i=0; i<nr; i++) {
759
for (j=0; j<dim-1; j++)
760
Generators[i][j] = Input[i][j];
761
Generators[i][dim-1]=1;
762
}
763
// use the added last component as grading
764
Grading = vector<Number>(dim,0);
765
Grading[dim-1] = 1;
766
is_Computed.set(ConeProperty::Grading);
767
GradingDenom=1;
768
is_Computed.set(ConeProperty::GradingDenom);
769
return Generators;
770
}
771
772
//---------------------------------------------------------------------------
773
774
/* rees input */
775
template<typename Number>
776
Matrix<Number> Cone<Number>::prepare_input_type_3(const vector< vector<Number> >& InputV) {
777
Matrix<Number> Input(InputV);
778
int i,j,nr_rows=Input.nr_of_rows(), nr_columns=Input.nr_of_columns();
779
// create cone generator matrix
780
Matrix<Number> Full_Cone_Generators(nr_rows+nr_columns,nr_columns+1,0);
781
for (i = 0; i < nr_columns; i++) {
782
Full_Cone_Generators[i][i]=1;
783
}
784
for(i=0; i<nr_rows; i++){
785
Full_Cone_Generators[i+nr_columns][nr_columns]=1;
786
for(j=0; j<nr_columns; j++) {
787
Full_Cone_Generators[i+nr_columns][j]=Input[i][j];
788
}
789
}
790
791
return Full_Cone_Generators;
792
}
793
794
795
//---------------------------------------------------------------------------
796
797
template<typename Number>
798
void Cone<Number>::prepare_input_lattice_ideal(map< InputType, vector< vector<Number> > >& multi_input_data) {
799
800
Matrix<Number> Binomials(find_input_matrix(multi_input_data,Type::lattice_ideal));
801
802
if (Grading.size()>0) {
803
//check if binomials are homogeneous
804
vector<Number> degrees = Binomials.MxV(Grading);
805
for (size_t i=0; i<degrees.size(); ++i) {
806
if (degrees[i]!=0) {
807
throw BadInputException("Grading gives non-zero value "
808
+ toString(degrees[i]) + " for binomial "
809
+ toString(i+1) + "!");
810
}
811
if (Grading[i] <0) {
812
throw BadInputException("Grading gives negative value "
813
+ toString(Grading[i]) + " for generator "
814
+ toString(i+1) + "!");
815
}
816
}
817
}
818
819
Matrix<Number> Gens=Binomials.kernel().transpose();
820
Full_Cone<Number> FC(Gens);
821
FC.verbose=verbose;
822
if (verbose) verboseOutput() << "Computing a positive embedding..." << endl;
823
824
FC.dualize_cone();
825
Matrix<Number> Supp_Hyp=FC.getSupportHyperplanes().sort_lex();
826
Matrix<Number> Selected_Supp_Hyp_Trans=(Supp_Hyp.submatrix(Supp_Hyp.max_rank_submatrix_lex())).transpose();
827
Matrix<Number> Positive_Embedded_Generators=Gens.multiplication(Selected_Supp_Hyp_Trans);
828
// GeneratorsOfToricRing = Positive_Embedded_Generators;
829
// is_Computed.set(ConeProperty::GeneratorsOfToricRing);
830
dim = Positive_Embedded_Generators.nr_of_columns();
831
multi_input_data.insert(make_pair(Type::normalization,Positive_Embedded_Generators.get_elements())); // this is the cone defined by the binomials
832
833
if (Grading.size()>0) {
834
// solve GeneratorsOfToricRing * grading = old_grading
835
Number dummyDenom;
836
// Grading must be set directly since map entry has been processed already
837
Grading = Positive_Embedded_Generators.solve_rectangular(Grading,dummyDenom);
838
if (Grading.size() != dim) {
839
errorOutput() << "Grading could not be transferred!"<<endl;
840
is_Computed.set(ConeProperty::Grading, false);
841
}
842
}
843
}
844
845
/* only used by the constructors */
846
template<typename Number>
847
void Cone<Number>::initialize() {
848
BC_set=false;
849
is_Computed = bitset<ConeProperty::EnumSize>(); //initialized to false
850
dim = 0;
851
unit_group_index = 1;
852
inhomogeneous=false;
853
triangulation_is_nested = false;
854
triangulation_is_partial = false;
855
verbose = libQnormaliz::verbose; //take the global default
856
if (using_GMP<Number>()) {
857
change_integer_type = true;
858
} else {
859
change_integer_type = false;
860
}
861
}
862
863
//---------------------------------------------------------------------------
864
865
template<typename Number>
866
void Cone<Number>::compose_basis_change(const Sublattice_Representation<Number>& BC) {
867
if (BC_set) {
868
BasisChange.compose(BC);
869
} else {
870
BasisChange = BC;
871
BC_set = true;
872
}
873
}
874
//---------------------------------------------------------------------------
875
template<typename Number>
876
void Cone<Number>::check_precomputed_support_hyperplanes(){
877
878
if (isComputed(ConeProperty::Generators)) {
879
// check if the inequalities are at least valid
880
// if (PreComputedSupportHyperplanes.nr_of_rows() != 0) {
881
Number sp;
882
for (size_t i = 0; i < Generators.nr_of_rows(); ++i) {
883
for (size_t j = 0; j < PreComputedSupportHyperplanes.nr_of_rows(); ++j) {
884
if ((sp = v_scalar_product(Generators[i], PreComputedSupportHyperplanes[j])) < 0) {
885
throw BadInputException("Precomputed inequality " + toString(j)
886
+ " is not valid for generator " + toString(i)
887
+ " (value " + toString(sp) + ")");
888
}
889
}
890
}
891
// }
892
}
893
}
894
895
//---------------------------------------------------------------------------
896
897
template<typename Number>
898
bool Cone<Number>::setVerbose (bool v) {
899
//we want to return the old value
900
bool old = verbose;
901
verbose = v;
902
return old;
903
}
904
905
//---------------------------------------------------------------------------
906
907
template<typename Number>
908
void Cone<Number>::checkDehomogenization () {
909
if(Dehomogenization.size()>0){
910
vector<Number> test=Generators.MxV(Dehomogenization);
911
for(size_t i=0;i<test.size();++i)
912
if(test[i]<0){
913
throw BadInputException(
914
"Dehomogenization has has negative value on generator "
915
+ toString(Generators[i]));
916
}
917
}
918
}
919
920
921
//---------------------------------------------------------------------------
922
923
template<typename Number>
924
void Cone<Number>::setWeights () {
925
926
if(WeightsGrad.nr_of_columns()!=dim){
927
WeightsGrad=Matrix<Number> (0,dim); // weight matrix for ordering
928
}
929
if(Grading.size()>0 && WeightsGrad.nr_of_rows()==0)
930
WeightsGrad.append(Grading);
931
GradAbs=vector<bool>(WeightsGrad.nr_of_rows(),false);
932
}
933
//---------------------------------------------------------------------------
934
935
template<typename Number>
936
void Cone<Number>::setDehomogenization (const vector<Number>& lf) {
937
if (lf.size() != dim) {
938
throw BadInputException("Dehomogenizing linear form has wrong dimension "
939
+ toString(lf.size()) + " (should be " + toString(dim) + ")");
940
}
941
Dehomogenization=lf;
942
is_Computed.set(ConeProperty::Dehomogenization);
943
}
944
945
//---------------------------------------------------------------------------
946
947
/* check what is computed */
948
template<typename Number>
949
bool Cone<Number>::isComputed(ConeProperty::Enum prop) const {
950
return is_Computed.test(prop);
951
}
952
953
template<typename Number>
954
bool Cone<Number>::isComputed(ConeProperties CheckComputed) const {
955
return CheckComputed.reset(is_Computed).any();
956
}
957
958
959
/* getter */
960
961
template<typename Number>
962
size_t Cone<Number>::getRank() {
963
compute(ConeProperty::Sublattice);
964
return BasisChange.getRank();
965
}
966
967
968
template<typename Number>
969
size_t Cone<Number>::getRecessionRank() {
970
compute(ConeProperty::RecessionRank);
971
return recession_rank;
972
}
973
974
template<typename Number>
975
long Cone<Number>::getAffineDim() {
976
compute(ConeProperty::AffineDim);
977
return affine_dim;
978
}
979
980
template<typename Number>
981
const Sublattice_Representation<Number>& Cone<Number>::getSublattice() {
982
compute(ConeProperty::Sublattice);
983
return BasisChange;
984
}
985
986
template<typename Number>
987
const vector< vector<Number> >& Cone<Number>::getOriginalMonoidGenerators() {
988
compute(ConeProperty::OriginalMonoidGenerators);
989
return OriginalMonoidGenerators.get_elements();
990
}
991
template<typename Number>
992
size_t Cone<Number>::getNrOriginalMonoidGenerators() {
993
compute(ConeProperty::OriginalMonoidGenerators);
994
return OriginalMonoidGenerators.nr_of_rows();
995
}
996
997
template<typename Number>
998
const vector< vector<Number> >& Cone<Number>::getMaximalSubspace() {
999
compute(ConeProperty::MaximalSubspace);
1000
return BasisMaxSubspace.get_elements();
1001
}
1002
template<typename Number>
1003
const Matrix<Number>& Cone<Number>::getMaximalSubspaceMatrix() {
1004
compute(ConeProperty::MaximalSubspace);
1005
return BasisMaxSubspace;
1006
}
1007
template<typename Number>
1008
size_t Cone<Number>::getDimMaximalSubspace() {
1009
compute(ConeProperty::MaximalSubspace);
1010
return BasisMaxSubspace.nr_of_rows();
1011
}
1012
1013
template<typename Number>
1014
const Matrix<Number>& Cone<Number>::getGeneratorsMatrix() {
1015
compute(ConeProperty::Generators);
1016
return Generators;
1017
}
1018
1019
template<typename Number>
1020
const vector< vector<Number> >& Cone<Number>::getGenerators() {
1021
compute(ConeProperty::Generators);
1022
return Generators.get_elements();
1023
}
1024
1025
template<typename Number>
1026
size_t Cone<Number>::getNrGenerators() {
1027
compute(ConeProperty::Generators);
1028
return Generators.nr_of_rows();
1029
}
1030
1031
template<typename Number>
1032
const Matrix<Number>& Cone<Number>::getExtremeRaysMatrix() {
1033
compute(ConeProperty::ExtremeRays);
1034
return ExtremeRays;
1035
}
1036
template<typename Number>
1037
const vector< vector<Number> >& Cone<Number>::getExtremeRays() {
1038
compute(ConeProperty::ExtremeRays);
1039
return ExtremeRays.get_elements();
1040
}
1041
template<typename Number>
1042
size_t Cone<Number>::getNrExtremeRays() {
1043
compute(ConeProperty::ExtremeRays);
1044
return ExtremeRays.nr_of_rows();
1045
}
1046
1047
template<typename Number>
1048
const Matrix<Number>& Cone<Number>::getVerticesOfPolyhedronMatrix() {
1049
compute(ConeProperty::VerticesOfPolyhedron);
1050
return VerticesOfPolyhedron;
1051
}
1052
template<typename Number>
1053
const vector< vector<Number> >& Cone<Number>::getVerticesOfPolyhedron() {
1054
compute(ConeProperty::VerticesOfPolyhedron);
1055
return VerticesOfPolyhedron.get_elements();
1056
}
1057
template<typename Number>
1058
size_t Cone<Number>::getNrVerticesOfPolyhedron() {
1059
compute(ConeProperty::VerticesOfPolyhedron);
1060
return VerticesOfPolyhedron.nr_of_rows();
1061
}
1062
1063
template<typename Number>
1064
const Matrix<Number>& Cone<Number>::getSupportHyperplanesMatrix() {
1065
compute(ConeProperty::SupportHyperplanes);
1066
return SupportHyperplanes;
1067
}
1068
template<typename Number>
1069
const vector< vector<Number> >& Cone<Number>::getSupportHyperplanes() {
1070
compute(ConeProperty::SupportHyperplanes);
1071
return SupportHyperplanes.get_elements();
1072
}
1073
template<typename Number>
1074
size_t Cone<Number>::getNrSupportHyperplanes() {
1075
compute(ConeProperty::SupportHyperplanes);
1076
return SupportHyperplanes.nr_of_rows();
1077
}
1078
1079
template<typename Number>
1080
map< InputType , vector< vector<Number> > > Cone<Number>::getConstraints () {
1081
compute(ConeProperty::Sublattice, ConeProperty::SupportHyperplanes);
1082
map<InputType, vector< vector<Number> > > c;
1083
c[Type::inequalities] = SupportHyperplanes.get_elements();
1084
c[Type::equations] = BasisChange.getEquations();
1085
// c[Type::congruences] = BasisChange.getCongruences();
1086
return c;
1087
}
1088
1089
template<typename Number>
1090
const vector< pair<vector<key_t>,Number> >& Cone<Number>::getTriangulation() {
1091
compute(ConeProperty::Triangulation);
1092
return Triangulation;
1093
}
1094
1095
template<typename Number>
1096
const vector<vector<bool> >& Cone<Number>::getOpenFacets() {
1097
compute(ConeProperty::ConeDecomposition);
1098
return OpenFacets;
1099
}
1100
1101
template<typename Number>
1102
size_t Cone<Number>::getTriangulationSize() {
1103
compute(ConeProperty::TriangulationSize);
1104
return TriangulationSize;
1105
}
1106
1107
template<typename Number>
1108
Number Cone<Number>::getTriangulationDetSum() {
1109
compute(ConeProperty::TriangulationDetSum);
1110
return TriangulationDetSum;
1111
}
1112
1113
template<typename Number>
1114
vector<Number> Cone<Number>::getDehomogenization() {
1115
compute(ConeProperty::Dehomogenization);
1116
return Dehomogenization;
1117
}
1118
1119
template<typename Number>
1120
bool Cone<Number>::isPointed() {
1121
compute(ConeProperty::IsPointed);
1122
return pointed;
1123
}
1124
1125
template<typename Number>
1126
bool Cone<Number>::isInhomogeneous() {
1127
return inhomogeneous;
1128
}
1129
1130
1131
// the information about the triangulation will just be returned
1132
// if no triangulation was computed so far they return false
1133
template<typename Number>
1134
bool Cone<Number>::isTriangulationNested() {
1135
return triangulation_is_nested;
1136
}
1137
template<typename Number>
1138
bool Cone<Number>::isTriangulationPartial() {
1139
return triangulation_is_partial;
1140
}
1141
1142
//---------------------------------------------------------------------------
1143
1144
template<typename Number>
1145
ConeProperties Cone<Number>::compute(ConeProperty::Enum cp) {
1146
if (isComputed(cp)) return ConeProperties();
1147
return compute(ConeProperties(cp));
1148
}
1149
1150
template<typename Number>
1151
ConeProperties Cone<Number>::compute(ConeProperty::Enum cp1, ConeProperty::Enum cp2) {
1152
return compute(ConeProperties(cp1,cp2));
1153
}
1154
1155
template<typename Number>
1156
ConeProperties Cone<Number>::compute(ConeProperty::Enum cp1, ConeProperty::Enum cp2,
1157
ConeProperty::Enum cp3) {
1158
return compute(ConeProperties(cp1,cp2,cp3));
1159
}
1160
1161
//---------------------------------------------------------------------------
1162
1163
template<typename Number>
1164
void Cone<Number>::set_implicit_dual_mode(ConeProperties& ToCompute) {
1165
1166
if(ToCompute.test(ConeProperty::DualMode) || ToCompute.test(ConeProperty::PrimalMode)
1167
|| ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid)
1168
|| Generators.nr_of_rows()>0 || SupportHyperplanes.nr_of_rows() > 2*dim
1169
|| SupportHyperplanes.nr_of_rows()
1170
<= BasisChangePointed.getRank()+ 50/(BasisChangePointed.getRank()+1))
1171
return;
1172
if(ToCompute.test(ConeProperty::HilbertBasis))
1173
ToCompute.set(ConeProperty::DualMode);
1174
if(ToCompute.test(ConeProperty::Deg1Elements)
1175
&& !(ToCompute.test(ConeProperty::HilbertSeries) || ToCompute.test(ConeProperty::Multiplicity)))
1176
ToCompute.set(ConeProperty::DualMode);
1177
return;
1178
}
1179
1180
//---------------------------------------------------------------------------
1181
1182
// this wrapper allows us to save and restore class data that depend on ToCompute
1183
// and may therefore be destroyed if compute() is called by itself
1184
template<typename Number>
1185
ConeProperties Cone<Number>::recursive_compute(ConeProperties ToCompute) {
1186
1187
bool save_explicit_HilbertSeries=explicit_HilbertSeries;
1188
bool save_naked_dual= naked_dual;
1189
ToCompute=compute(ToCompute);
1190
explicit_HilbertSeries=save_explicit_HilbertSeries;
1191
naked_dual=save_naked_dual;
1192
return ToCompute;
1193
}
1194
1195
//---------------------------------------------------------------------------
1196
1197
template<typename Number>
1198
ConeProperties Cone<Number>::compute(ConeProperties ToCompute) {
1199
1200
ToCompute.check_Q_permissible();
1201
1202
if(ToCompute.test(ConeProperty::DefaultMode))
1203
ToCompute.set(ConeProperty::SupportHyperplanes);
1204
1205
change_integer_type=false;
1206
1207
if(BasisMaxSubspace.nr_of_rows()>0 && !isComputed(ConeProperty::MaximalSubspace)){
1208
BasisMaxSubspace=Matrix<Number>(0,dim);
1209
recursive_compute(ConeProperty::MaximalSubspace);
1210
}
1211
1212
1213
ToCompute.reset(is_Computed);
1214
ToCompute.set_preconditions();
1215
ToCompute.prepare_compute_options(inhomogeneous);
1216
ToCompute.check_sanity(inhomogeneous);
1217
1218
/* preparation: get generators if necessary */
1219
compute_generators();
1220
1221
if (!isComputed(ConeProperty::Generators)) {
1222
throw FatalException("Could not get Generators.");
1223
}
1224
1225
ToCompute.reset(is_Computed); // already computed
1226
if (ToCompute.none()) {
1227
return ToCompute;
1228
}
1229
1230
// the actual computation
1231
1232
if (!change_integer_type) {
1233
compute_inner<Number>(ToCompute);
1234
}
1235
1236
complete_sublattice_comp(ToCompute);
1237
1238
/* check if everything is computed */
1239
ToCompute.reset(is_Computed); //remove what is now computed
1240
if (ToCompute.test(ConeProperty::Deg1Elements) && isComputed(ConeProperty::Grading)) {
1241
// this can happen when we were looking for a witness earlier
1242
recursive_compute(ToCompute);
1243
}
1244
if (!ToCompute.test(ConeProperty::DefaultMode) && ToCompute.goals().any()) {
1245
throw NotComputableException(ToCompute.goals());
1246
}
1247
ToCompute.reset_compute_options();
1248
return ToCompute;
1249
}
1250
1251
template<typename Number>
1252
template<typename NumberFC>
1253
void Cone<Number>::compute_inner(ConeProperties& ToCompute) {
1254
1255
if(ToCompute.test(ConeProperty::IsPointed) && Grading.size()==0){
1256
if (verbose) {
1257
verboseOutput()<< "Checking pointedness first"<< endl;
1258
}
1259
ConeProperties Dualize;
1260
Dualize.set(ConeProperty::SupportHyperplanes);
1261
Dualize.set(ConeProperty::ExtremeRays);
1262
recursive_compute(Dualize);
1263
}
1264
1265
Matrix<NumberFC> FC_Gens;
1266
1267
BasisChangePointed.convert_to_sublattice(FC_Gens, Generators);
1268
Full_Cone<NumberFC> FC(FC_Gens,!ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid));
1269
// !ToCompute.test(ConeProperty::ModuleGeneratorsOverOriginalMonoid) blocks make_prime in full_cone.cpp
1270
1271
/* activate bools in FC */
1272
1273
FC.verbose=verbose;
1274
1275
FC.inhomogeneous=inhomogeneous;
1276
1277
if (ToCompute.test(ConeProperty::Triangulation)) {
1278
FC.keep_triangulation = true;
1279
}
1280
if (ToCompute.test(ConeProperty::ConeDecomposition)) {
1281
FC.do_cone_dec = true;
1282
}
1283
1284
if (ToCompute.test(ConeProperty::TriangulationDetSum) ) {
1285
FC.do_determinants = true;
1286
}
1287
if (ToCompute.test(ConeProperty::TriangulationSize)) {
1288
FC.do_triangulation = true;
1289
}
1290
if (ToCompute.test(ConeProperty::KeepOrder)) {
1291
FC.keep_order = true;
1292
}
1293
1294
/* Give extra data to FC */
1295
if ( isComputed(ConeProperty::ExtremeRays) ) {
1296
FC.Extreme_Rays_Ind = ExtremeRaysIndicator;
1297
FC.is_Computed.set(ConeProperty::ExtremeRays);
1298
}
1299
1300
if (inhomogeneous){
1301
BasisChangePointed.convert_to_sublattice_dual_no_div(FC.Truncation, Dehomogenization);
1302
}
1303
1304
if (SupportHyperplanes.nr_of_rows()!=0) {
1305
BasisChangePointed.convert_to_sublattice_dual(FC.Support_Hyperplanes, SupportHyperplanes);
1306
}
1307
if (isComputed(ConeProperty::SupportHyperplanes)){
1308
FC.is_Computed.set(ConeProperty::SupportHyperplanes);
1309
FC.do_all_hyperplanes = false;
1310
}
1311
1312
1313
/* do the computation */
1314
1315
try {
1316
try {
1317
FC.compute();
1318
} catch (const NotIntegrallyClosedException& ) {
1319
}
1320
is_Computed.set(ConeProperty::Sublattice);
1321
// make sure we minimize the excluded faces if requested
1322
1323
extract_data(FC);
1324
if(isComputed(ConeProperty::IsPointed) && pointed)
1325
is_Computed.set(ConeProperty::MaximalSubspace);
1326
} catch(const NonpointedException& ) {
1327
is_Computed.set(ConeProperty::Sublattice);
1328
extract_data(FC);
1329
if(verbose){
1330
verboseOutput() << "Cone not pointed. Restarting computation." << endl;
1331
}
1332
FC=Full_Cone<NumberFC>(Matrix<NumberFC>(1)); // to kill the old FC (almost)
1333
Matrix<Number> Dual_Gen;
1334
Dual_Gen=BasisChangePointed.to_sublattice_dual(SupportHyperplanes);
1335
Sublattice_Representation<Number> Pointed(Dual_Gen,true); // sublattice of the dual lattice
1336
BasisMaxSubspace = BasisChangePointed.from_sublattice(Pointed.getEquationsMatrix());
1337
BasisMaxSubspace.simplify_rows();
1338
// check_vanishing_of_grading_and_dehom();
1339
BasisChangePointed.compose_dual(Pointed);
1340
is_Computed.set(ConeProperty::MaximalSubspace);
1341
// now we get the basis of the maximal subspace
1342
pointed = (BasisMaxSubspace.nr_of_rows() == 0);
1343
is_Computed.set(ConeProperty::IsPointed);
1344
compute_inner<NumberFC>(ToCompute);
1345
}
1346
}
1347
1348
1349
template<typename Number>
1350
void Cone<Number>::compute_generators() {
1351
//create Generators from SupportHyperplanes
1352
if (!isComputed(ConeProperty::Generators) && (SupportHyperplanes.nr_of_rows()!=0 ||inhomogeneous)) {
1353
if (verbose) {
1354
verboseOutput() << "Computing extreme rays as support hyperplanes of the dual cone:" << endl;
1355
}
1356
1357
compute_generators_inner<Number>();
1358
1359
}
1360
assert(isComputed(ConeProperty::Generators));
1361
}
1362
1363
template<typename Number>
1364
template<typename NumberFC>
1365
void Cone<Number>::compute_generators_inner() {
1366
1367
Matrix<Number> Dual_Gen;
1368
Dual_Gen=BasisChangePointed.to_sublattice_dual(SupportHyperplanes);
1369
// first we take the quotient of the efficient sublattice modulo the maximal subspace
1370
Sublattice_Representation<Number> Pointed(Dual_Gen,true); // sublattice of the dual space
1371
1372
// now we get the basis of the maximal subspace
1373
if(!isComputed(ConeProperty::MaximalSubspace)){
1374
BasisMaxSubspace = BasisChangePointed.from_sublattice(Pointed.getEquationsMatrix());
1375
BasisMaxSubspace.simplify_rows();
1376
// check_vanishing_of_grading_and_dehom();
1377
is_Computed.set(ConeProperty::MaximalSubspace);
1378
}
1379
if(!isComputed(ConeProperty::IsPointed)){
1380
pointed = (BasisMaxSubspace.nr_of_rows() == 0);
1381
is_Computed.set(ConeProperty::IsPointed);
1382
}
1383
BasisChangePointed.compose_dual(Pointed); // primal cone now pointed, may not yet be full dimensional
1384
1385
// restrict the supphyps to efficient sublattice and push to quotient mod subspace
1386
Matrix<NumberFC> Dual_Gen_Pointed;
1387
BasisChangePointed.convert_to_sublattice_dual(Dual_Gen_Pointed, SupportHyperplanes);
1388
Full_Cone<NumberFC> Dual_Cone(Dual_Gen_Pointed);
1389
Dual_Cone.verbose=verbose;
1390
Dual_Cone.do_extreme_rays=true; // we try to find them, need not exist
1391
try {
1392
Dual_Cone.dualize_cone();
1393
} catch(const NonpointedException& ){}; // we don't mind if the dual cone is not pointed
1394
1395
if (Dual_Cone.isComputed(ConeProperty::SupportHyperplanes)) {
1396
//get the extreme rays of the primal cone
1397
BasisChangePointed.convert_from_sublattice(Generators,
1398
Dual_Cone.getSupportHyperplanes());
1399
is_Computed.set(ConeProperty::Generators);
1400
1401
//get minmal set of support_hyperplanes if possible
1402
if (Dual_Cone.isComputed(ConeProperty::ExtremeRays)) {
1403
Matrix<NumberFC> Supp_Hyp = Dual_Cone.getGenerators().submatrix(Dual_Cone.getExtremeRays());
1404
BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, Supp_Hyp);
1405
SupportHyperplanes.sort_lex();
1406
is_Computed.set(ConeProperty::SupportHyperplanes);
1407
}
1408
1409
// now the final transformations
1410
// only necessary if the basis changes computed so far do not make the cone full-dimensional
1411
// this is equaivalent to the dual cone bot being pointed
1412
if(!(Dual_Cone.isComputed(ConeProperty::IsPointed) && Dual_Cone.isPointed())){
1413
// first to full-dimensional pointed
1414
Matrix<Number> Help;
1415
Help=BasisChangePointed.to_sublattice(Generators); // sublattice of the primal space
1416
Sublattice_Representation<Number> PointedHelp(Help,true);
1417
BasisChangePointed.compose(PointedHelp);
1418
// second to efficient sublattice
1419
if(BasisMaxSubspace.nr_of_rows()==0){ // primal cone is pointed and we can copy
1420
BasisChange=BasisChangePointed;
1421
}
1422
else{
1423
Help=BasisChange.to_sublattice(Generators);
1424
Help.append(BasisChange.to_sublattice(BasisMaxSubspace));
1425
Sublattice_Representation<Number> EmbHelp(Help,true); // sublattice of the primal space
1426
compose_basis_change(EmbHelp);
1427
}
1428
}
1429
is_Computed.set(ConeProperty::Sublattice); // will not be changed anymore
1430
1431
setWeights();
1432
set_extreme_rays(vector<bool>(Generators.nr_of_rows(),true)); // here since they get sorted
1433
is_Computed.set(ConeProperty::ExtremeRays);
1434
}
1435
}
1436
1437
template<typename Number>
1438
vector<Sublattice_Representation<Number> > MakeSubAndQuot(const Matrix<Number>& Gen,
1439
const Matrix<Number>& Ker){
1440
vector<Sublattice_Representation<Number> > Result;
1441
Matrix<Number> Help=Gen;
1442
Help.append(Ker);
1443
Sublattice_Representation<Number> Sub(Help,true);
1444
Sublattice_Representation<Number> Quot=Sub;
1445
if(Ker.nr_of_rows()>0){
1446
Matrix<Number> HelpQuot=Sub.to_sublattice(Ker).kernel(); // kernel here to be interpreted as subspace of the dual
1447
// namely the linear forms vanishing on Ker
1448
Sublattice_Representation<Number> SubToQuot(HelpQuot,true); // sublattice of the dual
1449
Quot.compose_dual(SubToQuot);
1450
}
1451
Result.push_back(Sub);
1452
Result.push_back(Quot);
1453
1454
return Result;
1455
}
1456
1457
//---------------------------------------------------------------------------
1458
1459
template<typename Number>
1460
template<typename NumberFC>
1461
void Cone<Number>::extract_data(Full_Cone<NumberFC>& FC) {
1462
//this function extracts ALL available data from the Full_Cone
1463
//even if it was in Cone already <- this may change
1464
//it is possible to delete the data in Full_Cone after extracting it
1465
1466
if(verbose) {
1467
verboseOutput() << "transforming data..."<<flush;
1468
}
1469
1470
if (FC.isComputed(ConeProperty::Generators)) {
1471
BasisChangePointed.convert_from_sublattice(Generators,FC.getGenerators());
1472
is_Computed.set(ConeProperty::Generators);
1473
}
1474
1475
if (FC.isComputed(ConeProperty::IsPointed) && !isComputed(ConeProperty::IsPointed)) {
1476
pointed = FC.isPointed();
1477
if(pointed)
1478
is_Computed.set(ConeProperty::MaximalSubspace);
1479
is_Computed.set(ConeProperty::IsPointed);
1480
}
1481
1482
1483
if (FC.isComputed(ConeProperty::ExtremeRays)) {
1484
set_extreme_rays(FC.getExtremeRays());
1485
}
1486
if (FC.isComputed(ConeProperty::SupportHyperplanes)) {
1487
/* if (inhomogeneous) {
1488
// remove irrelevant support hyperplane 0 ... 0 1
1489
vector<NumberFC> irr_hyp_subl;
1490
BasisChangePointed.convert_to_sublattice_dual(irr_hyp_subl, Dehomogenization);
1491
FC.Support_Hyperplanes.remove_row(irr_hyp_subl);
1492
} */
1493
// BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, FC.getSupportHyperplanes());
1494
extract_supphyps(FC);
1495
if(inhomogeneous && FC.dim<dim){ // make inequality for the inhomogeneous variable appear as dehomogenization
1496
vector<Number> dehom_restricted=BasisChangePointed.to_sublattice_dual(Dehomogenization);
1497
for(size_t i=0;i<SupportHyperplanes.nr_of_rows();++i){
1498
if(dehom_restricted==BasisChangePointed.to_sublattice_dual(SupportHyperplanes[i])){
1499
SupportHyperplanes[i]=Dehomogenization;
1500
break;
1501
}
1502
}
1503
}
1504
SupportHyperplanes.sort_lex();
1505
is_Computed.set(ConeProperty::SupportHyperplanes);
1506
}
1507
if (FC.isComputed(ConeProperty::TriangulationSize)) {
1508
TriangulationSize = FC.totalNrSimplices;
1509
triangulation_is_nested = FC.triangulation_is_nested;
1510
triangulation_is_partial= FC.triangulation_is_partial;
1511
is_Computed.set(ConeProperty::TriangulationSize);
1512
is_Computed.set(ConeProperty::IsTriangulationPartial);
1513
is_Computed.set(ConeProperty::IsTriangulationNested);
1514
is_Computed.reset(ConeProperty::Triangulation);
1515
Triangulation.clear();
1516
}
1517
if (FC.isComputed(ConeProperty::TriangulationDetSum)) {
1518
convert(TriangulationDetSum, FC.detSum);
1519
is_Computed.set(ConeProperty::TriangulationDetSum);
1520
}
1521
1522
if (FC.isComputed(ConeProperty::Triangulation)) {
1523
size_t tri_size = FC.Triangulation.size();
1524
Triangulation = vector< pair<vector<key_t>, Number> >(tri_size);
1525
if(FC.isComputed(ConeProperty::ConeDecomposition))
1526
OpenFacets.resize(tri_size);
1527
SHORTSIMPLEX<NumberFC> simp;
1528
for (size_t i = 0; i<tri_size; ++i) {
1529
simp = FC.Triangulation.front();
1530
Triangulation[i].first.swap(simp.key);
1531
// sort(Triangulation[i].first.begin(), Triangulation[i].first.end());
1532
if (FC.isComputed(ConeProperty::TriangulationDetSum))
1533
convert(Triangulation[i].second, simp.vol);
1534
else
1535
Triangulation[i].second = 0;
1536
if(FC.isComputed(ConeProperty::ConeDecomposition))
1537
OpenFacets[i].swap(simp.Excluded);
1538
FC.Triangulation.pop_front();
1539
}
1540
if(FC.isComputed(ConeProperty::ConeDecomposition))
1541
is_Computed.set(ConeProperty::ConeDecomposition);
1542
is_Computed.set(ConeProperty::Triangulation);
1543
}
1544
1545
if (FC.isComputed(ConeProperty::RecessionRank) && isComputed(ConeProperty::MaximalSubspace)) {
1546
recession_rank = FC.level0_dim+BasisMaxSubspace.nr_of_rows();
1547
is_Computed.set(ConeProperty::RecessionRank);
1548
if (getRank() == recession_rank) {
1549
affine_dim = -1;
1550
} else {
1551
affine_dim = getRank()-1;
1552
}
1553
is_Computed.set(ConeProperty::AffineDim);
1554
}
1555
1556
/* if (FC.isComputed(ConeProperty::MaximalSubspace) &&
1557
!isComputed(ConeProperty::MaximalSubspace)) {
1558
BasisChangePointed.convert_from_sublattice(BasisMaxSubspace, FC.Basis_Max_Subspace);
1559
check_vanishing_of_grading_and_dehom();
1560
is_Computed.set(ConeProperty::MaximalSubspace);
1561
}*/
1562
1563
if (verbose) {
1564
verboseOutput() << " done." <<endl;
1565
}
1566
}
1567
1568
//---------------------------------------------------------------------------
1569
template<typename Number>
1570
template<typename NumberFC>
1571
void Cone<Number>::extract_supphyps(Full_Cone<NumberFC>& FC) {
1572
BasisChangePointed.convert_from_sublattice_dual(SupportHyperplanes, FC.getSupportHyperplanes());
1573
}
1574
1575
template<typename Number>
1576
void Cone<Number>::extract_supphyps(Full_Cone<Number>& FC) {
1577
if(BasisChangePointed.IsIdentity())
1578
swap(SupportHyperplanes,FC.Support_Hyperplanes);
1579
else
1580
SupportHyperplanes=BasisChangePointed.from_sublattice_dual(FC.getSupportHyperplanes());
1581
}
1582
1583
//---------------------------------------------------------------------------
1584
1585
template<typename Number>
1586
void Cone<Number>::set_extreme_rays(const vector<bool>& ext) {
1587
assert(ext.size() == Generators.nr_of_rows());
1588
ExtremeRaysIndicator=ext;
1589
vector<bool> choice=ext;
1590
if (inhomogeneous) {
1591
// separate extreme rays to rays of the level 0 cone
1592
// and the verticies of the polyhedron, which are in level >=1
1593
size_t nr_gen = Generators.nr_of_rows();
1594
vector<bool> VOP(nr_gen);
1595
for (size_t i=0; i<nr_gen; i++) {
1596
if (ext[i] && v_scalar_product(Generators[i],Dehomogenization) != 0) {
1597
VOP[i] = true;
1598
choice[i]=false;
1599
}
1600
}
1601
VerticesOfPolyhedron=Generators.submatrix(VOP);
1602
VerticesOfPolyhedron.simplify_rows();
1603
VerticesOfPolyhedron.sort_by_weights(WeightsGrad,GradAbs);
1604
is_Computed.set(ConeProperty::VerticesOfPolyhedron);
1605
}
1606
ExtremeRays=Generators.submatrix(choice);
1607
ExtremeRays.simplify_rows();
1608
if(inhomogeneous && !isComputed(ConeProperty::AffineDim) && isComputed(ConeProperty::MaximalSubspace)){
1609
size_t level0_dim=ExtremeRays.max_rank_submatrix_lex().size();
1610
recession_rank = level0_dim+BasisMaxSubspace.nr_of_rows();
1611
is_Computed.set(ConeProperty::RecessionRank);
1612
if (getRank() == recession_rank) {
1613
affine_dim = -1;
1614
} else {
1615
affine_dim = getRank()-1;
1616
}
1617
is_Computed.set(ConeProperty::AffineDim);
1618
1619
}
1620
ExtremeRays.sort_by_weights(WeightsGrad,GradAbs);
1621
is_Computed.set(ConeProperty::ExtremeRays);
1622
}
1623
1624
//---------------------------------------------------------------------------
1625
1626
template<typename Number>
1627
void Cone<Number>::complete_sublattice_comp(ConeProperties& ToCompute) {
1628
1629
if(!isComputed(ConeProperty::Sublattice))
1630
return;
1631
is_Computed.set(ConeProperty::Rank);
1632
if(ToCompute.test(ConeProperty::Equations)){
1633
BasisChange.getEquationsMatrix(); // just to force computation, ditto below
1634
is_Computed.set(ConeProperty::Equations);
1635
}
1636
/*
1637
if(ToCompute.test(ConeProperty::Congruences) || ToCompute.test(ConeProperty::ExternalIndex)){
1638
// BasisChange.getCongruencesMatrix();
1639
BasisChange.getExternalIndex();
1640
// is_Computed.set(ConeProperty::Congruences);
1641
// is_Computed.set(ConeProperty::ExternalIndex);
1642
}*/
1643
}
1644
1645
1646
template<typename Number>
1647
Cone<Number>::~Cone() {
1648
}
1649
1650
1651
1652
} // end namespace libQnormaliz
1653
1654