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 <iostream>
25
#include <cctype> // std::isdigit
26
#include <limits> // numeric_limits
27
28
#include "Qoptions.h"
29
#include "libQnormaliz/libQnormaliz.h"
30
#include "libQnormaliz/Qmap_operations.h"
31
#include "libQnormaliz/Qcone_property.h"
32
33
// eats up a comment, stream must start with "/*", eats everything until "*/"
34
void skip_comment(istream& in) {
35
int i = in.get();
36
int j = in.get();
37
if (i != '/' || j != '*') {
38
throw BadInputException("Bad comment start!");
39
}
40
while (in.good()) {
41
in.ignore(numeric_limits<streamsize>::max(), '*'); //ignore everything until next '*'
42
i = in.get();
43
if (in.good() && i == '/') return; // successfully skipped comment
44
}
45
throw BadInputException("Incomplete comment!");
46
}
47
48
template<typename Number>
49
void save_matrix(map<Type::InputType, vector<vector<Number> > >& input_map,
50
InputType input_type, const vector<vector<Number> >& M) {
51
//check if this type already exists
52
if (exists_element(input_map, input_type)) {
53
/*throw BadInputException("Multiple inputs of type \"" + type_string
54
+ "\" are not allowed!");*/
55
input_map[input_type].insert(input_map[input_type].end(),M.begin(),M.end());
56
return;
57
}
58
input_map[input_type] = M;
59
}
60
61
template<typename Number>
62
void save_empty_matrix(map<Type::InputType, vector<vector<Number> > >& input_map,
63
InputType input_type){
64
65
vector<vector<Number> > M;
66
save_matrix(input_map, input_type, M);
67
}
68
69
template <typename Number>
70
vector<vector<Number> > transpose_mat(const vector<vector<Number> >& mat){
71
72
if(mat.size()==0 || mat[0].size()==0)
73
return vector<vector<Number> >(0);
74
size_t m=mat[0].size();
75
size_t n=mat.size();
76
vector<vector<Number> > transpose(m,vector<Number> (n,0));
77
for(size_t i=0;i<m;++i)
78
for(size_t j=0;j<n;++j)
79
transpose[i][j]=mat[j][i];
80
return transpose;
81
}
82
83
template <typename Number>
84
void append_row(const vector<Number> row, map <Type::InputType, vector< vector<Number> > >& input_map,
85
Type::InputType input_type) {
86
87
vector<vector<Number> > one_row(1,row);
88
save_matrix(input_map,input_type,one_row);
89
}
90
91
template <typename Number>
92
void process_constraint(const string& rel, const vector<Number>& left, Number right, const Number modulus,
93
map <Type::InputType, vector< vector<Number> > >& input_map, bool forced_hom) {
94
95
vector<Number> row=left;
96
bool inhomogeneous=false;
97
if(right!=0 || rel=="<" || rel==">")
98
inhomogeneous=true;
99
string modified_rel=rel;
100
bool strict_inequality=false;
101
if(rel=="<"){
102
strict_inequality=true;
103
right-=1;
104
modified_rel="<=";
105
106
}
107
if(rel==">"){
108
strict_inequality=true;
109
right+=1;
110
modified_rel=">=";
111
}
112
if(strict_inequality && forced_hom){
113
throw BadInputException("Strict inequality not allowed in hom_constraints!");
114
}
115
if(inhomogeneous || forced_hom)
116
row.push_back(-right); // rhs --> lhs
117
if(modified_rel=="<="){ // convert <= to >=
118
for(size_t j=0; j<row.size();++j)
119
row[j]=-row[j];
120
modified_rel=">=";
121
}
122
if(rel=="~")
123
row.push_back(modulus);
124
125
if(inhomogeneous && !forced_hom){
126
if(modified_rel=="="){
127
append_row(row,input_map,Type::inhom_equations);
128
return;
129
}
130
if(modified_rel==">="){
131
append_row(row,input_map,Type::inhom_inequalities);
132
return;
133
}
134
if(modified_rel=="~"){
135
append_row(row,input_map,Type::inhom_congruences);
136
return;
137
}
138
}
139
else {
140
if(modified_rel=="="){
141
append_row(row,input_map,Type::equations);
142
return;
143
}
144
if(modified_rel==">="){
145
append_row(row,input_map,Type::inequalities);
146
return;
147
}
148
if(modified_rel=="~"){
149
append_row(row,input_map,Type::congruences);
150
return;
151
}
152
}
153
throw BadInputException("Illegal constrint type "+rel+" !");
154
}
155
156
template <typename Number>
157
bool read_modulus(istream& in, Number& modulus) {
158
159
in >> std::ws; // gobble any leading white space
160
char dummy;
161
in >> dummy;
162
if(dummy != '(')
163
return false;
164
in >> modulus;
165
if(in.fail() || modulus==0)
166
return false;
167
in >> std::ws; // gobble any white space before closing
168
in >> dummy;
169
if(dummy != ')')
170
return false;
171
return true;
172
}
173
174
template <typename Number>
175
void read_constraints(istream& in, long dim, map <Type::InputType, vector< vector<Number> > >& input_map, bool forced_hom) {
176
177
long nr_constraints;
178
in >> nr_constraints;
179
180
if(in.fail() || nr_constraints < 0) {
181
throw BadInputException("Cannot read "
182
+ toString(nr_constraints) + " constraints!");
183
}
184
long hom_correction=0;
185
if(forced_hom)
186
hom_correction=1;
187
for(long i=0;i< nr_constraints; ++i) {
188
vector<Number> left(dim-hom_correction);
189
for(long j=0;j<dim-hom_correction;++j){
190
in >> left[j];
191
}
192
string rel, modulus_str;
193
Number right, modulus=0;
194
in >> rel;
195
in >> right;
196
if(rel=="~") {
197
if(!read_modulus(in,modulus))
198
throw BadInputException("Error while reading modulus of congruence!");
199
}
200
if (in.fail()) {
201
throw BadInputException("Error while reading constraint!");
202
}
203
process_constraint(rel,left,right,modulus,input_map,forced_hom);
204
}
205
}
206
207
template <typename Number>
208
bool read_sparse_vector(istream& in, vector<Number>& input_vec, long length){
209
210
input_vec=vector<Number> (length,0);
211
char dummy;
212
213
while(true){
214
in >> std::ws;
215
int c = in.peek();
216
if(c==';'){
217
in >> dummy; // swallow ;
218
return true;
219
}
220
long pos;
221
in >> pos;
222
if(in.fail())
223
return false;
224
pos--;
225
if(pos<0 or pos>=length)
226
return false;
227
in >> std::ws;
228
c=in.peek();
229
if(c!=':')
230
return false;
231
in >> dummy; // skip :
232
Number value;
233
in >> value;
234
if(in.fail())
235
return false;
236
input_vec[pos]=value;
237
}
238
}
239
240
template <typename Number>
241
bool read_formatted_vector(istream& in, vector<Number>& input_vec) {
242
243
input_vec.clear();
244
in >> std::ws;
245
char dummy;
246
in >> dummy; // read first proper character
247
if(dummy!='[')
248
return false;
249
bool one_more_entry_required=false;
250
while(true){
251
in >> std::ws;
252
if(!one_more_entry_required && in.peek()==']'){
253
in >> dummy;
254
return true;
255
}
256
Number number;
257
in >> number;
258
if(in.fail())
259
return false;
260
input_vec.push_back(number);
261
in >> std::ws;
262
one_more_entry_required=false;
263
if(in.peek()==',' || in.peek()==';'){ // skip potential separator
264
in >> dummy;
265
one_more_entry_required=true;
266
}
267
}
268
}
269
270
template <typename Number>
271
bool read_formatted_matrix(istream& in, vector<vector<Number> >& input_mat, bool transpose) {
272
input_mat.clear();
273
in >> std::ws;
274
char dummy;
275
in >> dummy; // read first proper character
276
if(dummy!='[')
277
return false;
278
bool one_more_entry_required=false;
279
while(true){
280
in >> std::ws;
281
if(!one_more_entry_required && in.peek()==']'){ // closing ] found
282
in >> dummy;
283
if(transpose)
284
input_mat=transpose_mat(input_mat);
285
return true;
286
}
287
vector<Number> input_vec;
288
if(!read_formatted_vector(in,input_vec)){
289
throw BadInputException("Error in reading input vector!");
290
}
291
if(input_mat.size()>0 && input_vec.size()!=input_mat[0].size()){
292
throw BadInputException("Rows of input matrix have unequal lengths!");
293
}
294
input_mat.push_back(input_vec);
295
in >> std::ws;
296
one_more_entry_required=false;
297
if(in.peek()==',' || in.peek()==';'){ // skip potential separator
298
in >> dummy;
299
one_more_entry_required=true;
300
}
301
}
302
}
303
304
305
template <typename Number>
306
map <Type::InputType, vector< vector<Number> > > readNormalizInput (istream& in, OptionsHandler& options) {
307
308
string type_string;
309
long i,j;
310
long nr_rows,nr_columns,nr_rows_or_columns;
311
InputType input_type;
312
Number number;
313
ConeProperty::Enum cp;
314
315
map<Type::InputType, vector< vector<Number> > > input_map;
316
typename map<Type::InputType, vector< vector<Number> > >::iterator it;
317
318
in >> std::ws; // eat up any leading white spaces
319
int c = in.peek();
320
if ( c == EOF ) {
321
throw BadInputException("Empty input file!");
322
}
323
bool new_input_syntax = !std::isdigit(c);
324
325
if (new_input_syntax) {
326
long dim;
327
while (in.peek() == '/') {
328
skip_comment(in);
329
in >> std::ws;
330
}
331
in >> type_string;
332
if (!in.good() || type_string != "amb_space") {
333
throw BadInputException("First entry must be \"amb_space\"!");
334
}
335
bool dim_known=false;
336
in >> std::ws;
337
c=in.peek();
338
if(c=='a'){
339
string dummy;
340
in >> dummy;
341
if(dummy!="auto"){
342
throw BadInputException("Bad amb_space value!");
343
}
344
}
345
else{
346
in >> dim;
347
if (!in.good() || dim <= 0) {
348
throw BadInputException("Bad amb_space value!");
349
}
350
dim_known=true;
351
}
352
while (in.good()) { //main loop
353
354
bool transpose=false;
355
in >> std::ws; // eat up any leading white spaces
356
c = in.peek();
357
if (c == EOF) break;
358
if (c == '/') {
359
skip_comment(in);
360
} else {
361
in >> type_string;
362
if (in.fail()) {
363
throw BadInputException("Could not read type string!");
364
}
365
if (std::isdigit(c)) {
366
throw BadInputException("Unexpected number " + type_string
367
+ " when expecting a type!");
368
}
369
if (isConeProperty(cp, type_string)) {
370
options.activateInputFileConeProperty(cp);
371
continue;
372
}
373
/* if (type_string == "BigInt") {
374
options.activateInputFileBigInt();
375
continue;
376
} */
377
if (type_string == "LongLong") {
378
options.activateInputFileLongLong();
379
continue;
380
}
381
if (type_string == "total_degree") {
382
if(!dim_known){
383
throw BadInputException("Ambient space must be known for "+type_string+"!");
384
}
385
input_type = Type::grading;
386
save_matrix(input_map, input_type, vector< vector<Number> >(1,vector<Number>(dim+type_nr_columns_correction(input_type),1)));
387
continue;
388
}
389
if (type_string == "nonnegative") {
390
if(!dim_known){
391
throw BadInputException("Ambient space must be known for "+type_string+"!");
392
}
393
input_type = Type::signs;
394
save_matrix(input_map, input_type, vector< vector<Number> >(1,vector<Number>(dim+type_nr_columns_correction(input_type),1)));
395
continue;
396
}
397
if(type_string == "constraints") {
398
if(!dim_known){
399
throw BadInputException("Ambient space must be known for "+type_string+"!");
400
}
401
read_constraints(in,dim,input_map,false);
402
continue;
403
}
404
if(type_string == "hom_constraints") {
405
if(!dim_known){
406
throw BadInputException("Ambient space must be known for "+type_string+"!");
407
}
408
read_constraints(in,dim,input_map,true);
409
continue;
410
}
411
412
413
input_type = to_type(type_string);
414
if(dim_known)
415
nr_columns = dim + type_nr_columns_correction(input_type);
416
417
if (type_is_vector(input_type)) {
418
nr_rows_or_columns = nr_rows = 1;
419
in >> std::ws; // eat up any leading white spaces
420
c = in.peek();
421
if (c=='u') { // must be unit vector
422
string vec_kind;
423
in >> vec_kind;
424
if (vec_kind != "unit_vector") {
425
throw BadInputException("Error while reading "
426
+ type_string
427
+ ": unit_vector expected!");
428
}
429
430
long pos = 0;
431
in >> pos;
432
if (in.fail()) {
433
throw BadInputException("Error while reading "
434
+ type_string
435
+ " as a unit_vector!");
436
}
437
438
if(!dim_known){
439
throw BadInputException("Ambient space must be known for unit vector "+type_string+"!");
440
}
441
442
vector< vector<Number> > e_i = vector< vector<Number> >(1,vector<Number>(nr_columns,0));
443
if (pos < 1 || pos > static_cast<long>(e_i[0].size())) {
444
throw BadInputException("Error while reading "
445
+ type_string + " as a unit_vector "
446
+ toString(pos) + "!");
447
}
448
pos--; // in input file counting starts from 1
449
e_i[0].at(pos) = 1;
450
save_matrix(input_map, input_type, e_i);
451
continue;
452
} // end unit vector
453
454
if(c=='s'){ // must be "sparse"
455
string vec_kind;
456
in >> vec_kind;
457
if (vec_kind != "sparse") {
458
throw BadInputException("Error while reading "
459
+ type_string
460
+ ": sparse vector expected!");
461
}
462
463
if(!dim_known){
464
throw BadInputException("Ambient space must be known for sparse vector "+type_string+"!");
465
}
466
467
vector<Number> sparse_vec;
468
nr_columns = dim + type_nr_columns_correction(input_type);
469
bool success = read_sparse_vector(in,sparse_vec,nr_columns);
470
if(!success){
471
throw BadInputException("Error while reading "
472
+ type_string
473
+ " as a sparse vector!");
474
}
475
save_matrix(input_map, input_type, vector<vector<Number> > (1,sparse_vec));
476
continue;
477
}
478
479
if (c == '[') { // must be formatted vector
480
vector<Number> formatted_vec;
481
bool success = read_formatted_vector(in,formatted_vec);
482
if(!dim_known){
483
dim=formatted_vec.size()- type_nr_columns_correction(input_type);
484
dim_known=true;
485
nr_columns = dim + type_nr_columns_correction(input_type);
486
}
487
if(!success || (long) formatted_vec.size()!=nr_columns){
488
throw BadInputException("Error while reading "
489
+ type_string
490
+ " as a formatted vector!");
491
}
492
save_matrix(input_map, input_type, vector<vector<Number> > (1,formatted_vec));
493
continue;
494
} // end formatted vector
495
496
} else { // end vector, it is a matrix. Plain vector read as a one row matrix later on
497
in >> std::ws;
498
c = in.peek();
499
500
if(c!='[' && !std::isdigit(c)){ // must be transpose
501
string transpose_str;
502
in >> transpose_str;
503
if(transpose_str!="transpose"){
504
throw BadInputException("Illegal keyword "+transpose_str+" following matrix type!");
505
}
506
transpose=true;
507
in >> std::ws;
508
c = in.peek();
509
}
510
if(c=='['){ // it is a formatted matrix
511
vector<vector<Number> > formatted_mat;
512
bool success=read_formatted_matrix(in,formatted_mat, transpose);
513
if(!success){
514
throw BadInputException("Error while reading formatted matrix "
515
+ type_string + "!");
516
}
517
if(formatted_mat.size() ==0){ // empty matrix
518
input_type = to_type(type_string);
519
save_empty_matrix(input_map, input_type);
520
continue;
521
}
522
if(!dim_known){
523
dim=formatted_mat[0].size()- type_nr_columns_correction(input_type);
524
dim_known=true;
525
nr_columns = dim + type_nr_columns_correction(input_type);
526
}
527
528
if((long) formatted_mat[0].size()!=nr_columns){
529
throw BadInputException("Error while reading formatted matrix "
530
+ type_string + "!");
531
}
532
533
save_matrix(input_map, input_type, formatted_mat);
534
continue;
535
} // only plain matrix left
536
537
in >> nr_rows_or_columns; // is number of columns if transposed
538
nr_rows=nr_rows_or_columns; // most of the time
539
}
540
541
if(!dim_known){
542
throw BadInputException("Ambient space must be known for plain matrix or vector "+type_string+"!");
543
}
544
545
if(transpose)
546
swap(nr_rows,nr_columns);
547
548
if(in.fail() || nr_rows_or_columns < 0) {
549
throw BadInputException("Error while reading "
550
+ type_string + " (a " + toString(nr_rows)
551
+ "x" + toString(nr_columns)
552
+ " matrix) !");
553
}
554
if(nr_rows==0){
555
input_type = to_type(type_string);
556
save_empty_matrix(input_map, input_type);
557
continue;
558
}
559
560
vector< vector<Number> > M(nr_rows);
561
in >> std::ws;
562
c=in.peek();
563
if(c=='s'){ // must be sparse
564
string sparse_test;
565
in >> sparse_test;
566
if (sparse_test!= "sparse") {
567
throw BadInputException("Error while reading "
568
+ type_string
569
+ ": sparse matrix expected!");
570
}
571
for(long i=0;i<nr_rows;++i){
572
bool success=read_sparse_vector(in,M[i],nr_columns);
573
if(!success){
574
throw BadInputException("Error while reading "
575
+ type_string
576
+ ": corrupted sparse matrix");
577
}
578
579
}
580
} else{ // dense matrix
581
for(i=0; i<nr_rows; i++){
582
M[i].resize(nr_columns);
583
for(j=0; j<nr_columns; j++) {
584
in >> M[i][j];
585
}
586
}
587
}
588
if(transpose)
589
M=transpose_mat(M);
590
save_matrix(input_map, input_type, M);
591
}
592
if (in.fail()) {
593
throw BadInputException("Error while reading " + type_string
594
+ " (a " + toString(nr_rows) + "x"
595
+ toString(nr_columns) + " matrix) !");
596
}
597
}
598
} else {
599
// old input syntax
600
while (in.good()) {
601
in >> nr_rows;
602
if(in.fail())
603
break;
604
in >> nr_columns;
605
if((nr_rows <0) || (nr_columns < 0)){
606
throw BadInputException("Error while reading a "
607
+ toString(nr_rows) + "x" + toString(nr_columns)
608
+ " matrix !");
609
}
610
vector< vector<Number> > M(nr_rows,vector<Number>(nr_columns));
611
for(i=0; i<nr_rows; i++){
612
for(j=0; j<nr_columns; j++) {
613
in >> number;
614
M[i][j] = number;
615
}
616
}
617
618
in >> type_string;
619
620
if ( in.fail() ) {
621
throw BadInputException("Error while reading a "
622
+ toString(nr_rows) + "x" + toString(nr_columns)
623
+ " matrix!");
624
}
625
626
input_type = to_type(type_string);
627
628
//check if this type already exists
629
save_matrix(input_map, input_type, M);
630
}
631
}
632
return input_map;
633
}
634
635