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: 418425
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
#ifndef MATRIX_HPP
26
#define MATRIX_HPP
27
//---------------------------------------------------------------------------
28
29
30
#include <vector>
31
#include <list>
32
#include <iostream>
33
#include <string>
34
35
#include <libnormaliz/libnormaliz.h>
36
#include <libnormaliz/integer.h>
37
#include <libnormaliz/convert.h>
38
39
//---------------------------------------------------------------------------
40
41
namespace libnormaliz {
42
using std::list;
43
using std::vector;
44
using std::string;
45
46
template<typename Integer> class Matrix {
47
48
template<typename> friend class Matrix;
49
template<typename> friend class Lineare_Transformation;
50
template<typename> friend class Sublattice_Representation;
51
52
// public:
53
54
size_t nr;
55
size_t nc;
56
vector< vector<Integer> > elem;
57
58
//---------------------------------------------------------------------------
59
// Private routines, used in the public routines
60
//---------------------------------------------------------------------------
61
62
//---------------------------------------------------------------------------
63
// Row and column reduction
64
//---------------------------------------------------------------------------
65
// return value false undicates failure because of overflow
66
// for all the routines below
67
68
// reduction via integer division and elemntary transformations
69
bool reduce_row(size_t corner); //reduction by the corner-th row
70
bool reduce_row (size_t row, size_t col); // corner at position (row,col)
71
72
// replaces two columns by linear combinations of them
73
bool linear_comb_columns(const size_t& col,const size_t& j,
74
const Integer& u,const Integer& w,const Integer& v,const Integer& z);
75
76
// column reduction with gcd method
77
bool gcd_reduce_column (size_t corner, Matrix<Integer>& Right);
78
79
//---------------------------------------------------------------------------
80
// Work horses
81
//---------------------------------------------------------------------------
82
83
// takes |product of the diagonal elem|
84
Integer compute_vol(bool& success);
85
86
// Solve system with coefficients and right hand side in one matrix, using elementary transformations
87
// solution replaces right hand side
88
bool solve_destructive_inner(bool ZZinvertible, Integer& denom);
89
90
// asembles the matrix of the system (left side the submatrix of mother given by key
91
// right side from column vectors pointed to by RS
92
// both in a single matrix
93
void solve_system_submatrix_outer(const Matrix<Integer>& mother, const vector<key_t>& key, const vector<vector<Integer>* >& RS,
94
Integer& denom, bool ZZ_invertible, bool transpose, size_t red_col, size_t sign_col,
95
bool compute_denom=true, bool make_sol_prime=false);
96
97
size_t row_echelon_inner_elem(bool& success); // does the work and checks for overflows
98
// size_t row_echelon_inner_bareiss(bool& success, Integer& det);
99
// NOTE: Bareiss cannot be used if z-invertible transformations are needed
100
101
size_t row_echelon(bool& success); // transforms this into row echelon form and returns rank
102
size_t row_echelon(bool& success, Integer& det); // computes also |det|
103
size_t row_echelon(bool& success, bool do_compute_vol, Integer& det); // chooses elem (or bareiss in former time)
104
105
// reduces the rows a matrix in row echelon form upwards, from left to right
106
bool reduce_rows_upwards();
107
size_t row_echelon_reduce(bool& success); // combines row_echelon and reduce_rows_upwards
108
109
// computes rank and index simultaneously, returns rank
110
Integer full_rank_index(bool& success);
111
112
vector<key_t> max_rank_submatrix_lex_inner(bool& success) const;
113
114
// A version of invert that circumvents protection and leaves it to the calling routine
115
Matrix invert_unprotected(Integer& denom, bool& sucess) const;
116
117
bool SmithNormalForm_inner(size_t& rk, Matrix<Integer>& Right);
118
119
vector<Integer> optimal_subdivision_point_inner() const;
120
121
122
//---------------------------------------------------------------------------
123
// Pivots for rows/columns operations
124
//---------------------------------------------------------------------------
125
126
vector<long> pivot(size_t corner); //Find the position of an element x with
127
//0<abs(x)<=abs(y) for all y!=0 in the right-lower submatrix of this
128
//described by an int corner
129
130
long pivot_column(size_t col); //Find the position of an element x with
131
//0<abs(x)<=abs(y) for all y!=0 in the lower half of the column of this
132
//described by an int col
133
134
long pivot_column(size_t row,size_t col); //in column col starting from row
135
136
//---------------------------------------------------------------------------
137
// Helpers for linear systems
138
//---------------------------------------------------------------------------
139
140
Matrix bundle_matrices(const Matrix<Integer>& Right_side)const;
141
Matrix extract_solution() const;
142
vector<vector<Integer>* > row_pointers();
143
void customize_solution(size_t dim, Integer& denom, size_t red_col,
144
size_t sign_col, bool make_sol_prime);
145
146
public:
147
148
size_t row_echelon_inner_bareiss(bool& success, Integer& det);
149
150
vector<vector<Integer>* > submatrix_pointers(const vector<key_t>& key);
151
152
//---------------------------------------------------------------------------
153
// Rows and columns exchange
154
//---------------------------------------------------------------------------
155
156
void exchange_rows(const size_t& row1, const size_t& row2); //row1 is exchanged with row2
157
void exchange_columns(const size_t& col1, const size_t& col2); // col1 is exchanged with col2
158
159
//---------------------------------------------------------------------------
160
161
//---------------------------------------------------------------------------
162
// Construction and destruction
163
//---------------------------------------------------------------------------
164
165
Matrix();
166
Matrix(size_t dim); //constructor of unit matrix
167
Matrix(size_t row, size_t col); //main constructor, all entries 0
168
Matrix(size_t row, size_t col, Integer value); //constructor, all entries set to value
169
Matrix(const vector< vector<Integer> >& elem); //constuctor, elem=elem
170
Matrix(const list< vector<Integer> >& elems);
171
172
//---------------------------------------------------------------------------
173
// Data access
174
//---------------------------------------------------------------------------
175
176
void write_column(size_t col, const vector<Integer>& data); //write a column
177
void print(const string& name, const string& suffix) const; // writes matrix into name.suffix
178
void print_append(const string& name,const string& suffix) const; // the same, but appends matrix
179
void print(std::ostream& out, bool with_format=false) const; // writes matrix to the stream
180
void pretty_print(std::ostream& out, bool with_row_nr=false) const; // writes matrix in a nice format to the stream // read a row
181
size_t nr_of_rows() const; // returns nr
182
size_t nr_of_columns() const; // returns nc
183
void set_nr_of_columns(size_t c);
184
/* generates a pseudo random matrix for tests, entries form 0 to mod-1 */
185
void random(int mod=3);
186
187
void set_zero(); // sets all entries to 0
188
189
/* returns a submatrix with rows corresponding to indices given by
190
* the entries of rows, Numbering from 0 to n-1 ! */
191
Matrix submatrix(const vector<key_t>& rows) const;
192
Matrix submatrix(const vector<int>& rows) const;
193
Matrix submatrix(const vector<bool>& rows) const;
194
195
void swap (Matrix<Integer>& x);
196
197
// returns the permutation created by sorting the rows with a grading function
198
// or by 1-norm if computed is false
199
vector<key_t> perm_sort_by_degree(const vector<key_t>& key, const vector<Integer>& grading, bool computed) const;
200
vector<key_t> perm_by_weights(const Matrix<Integer>& Weights, vector<bool> absolute);
201
202
void select_submatrix(const Matrix<Integer>& mother, const vector<key_t>& rows);
203
void select_submatrix_trans(const Matrix<Integer>& mother, const vector<key_t>& rows);
204
205
Matrix& remove_zero_rows(); // remove zero rows, modifies this
206
207
// resizes the matrix to the given number of rows/columns
208
// if the size shrinks it will keep all its allocated memory
209
// useful when the size varies
210
void resize(size_t nr_rows);
211
void resize(size_t nr_rows, size_t nr_cols);
212
void resize_columns(size_t nr_cols);
213
void Shrink_nr_rows(size_t new_nr_rows);
214
215
vector<Integer> diagonal() const; //returns the diagonale of this
216
//this should be a quadratic matrix
217
size_t maximal_decimal_length() const; //return the maximal number of decimals
218
//needed to write an entry
219
220
vector<size_t> maximal_decimal_length_columnwise() const; // the same per column
221
222
void append(const Matrix& M); // appends the rows of M to this
223
void append(const vector<vector<Integer> >& M); // the same, but for another type of matrix
224
void append(const vector<Integer>& v); // append the row v to this
225
void append_column(const vector<Integer>& v); // append the column v to this
226
void remove_row(const vector<Integer>& row); // removes all appearances of this row, not very efficient!
227
void remove_row(const size_t index);
228
vector<size_t> remove_duplicate_and_zero_rows();
229
void remove_duplicate(const Matrix& M);
230
231
232
inline const Integer& get_elem(size_t row, size_t col) const {
233
return elem[row][col];
234
}
235
inline const vector< vector<Integer> >& get_elements() const {
236
return elem;
237
}
238
inline vector<Integer> const& operator[] (size_t row) const {
239
return elem[row];
240
}
241
inline vector<Integer>& operator[] (size_t row) {
242
return elem[row];
243
}
244
void set_nc(size_t col){
245
nc=col;
246
}
247
void set_nr(size_t rows){
248
nc=rows;
249
}
250
251
//---------------------------------------------------------------------------
252
// Basic matrices operations
253
//---------------------------------------------------------------------------
254
255
Matrix add(const Matrix& A) const; // returns this+A
256
Matrix multiplication(const Matrix& A) const; // returns this*A
257
Matrix multiplication(const Matrix& A, long m) const;// returns this*A (mod m)
258
bool equal(const Matrix& A) const; // returns this==A
259
bool equal(const Matrix& A, long m) const; // returns this==A (mod m)
260
Matrix transpose() const; // returns the transpose of this
261
262
bool is_diagonal() const;
263
264
//---------------------------------------------------------------------------
265
// Scalar operations
266
//---------------------------------------------------------------------------
267
268
void scalar_multiplication(const Integer& scalar); //this=this*scalar
269
void scalar_division(const Integer& scalar);
270
//this=this div scalar, all the elem of this must be divisible with the scalar
271
void reduction_modulo(const Integer& modulo); //this=this mod scalar
272
Integer matrix_gcd() const; //returns the gcd of all elem
273
vector<Integer> make_prime(); //each row of this is reduced by its gcd,
274
// vector of gcds returned
275
void make_cols_prime(size_t from_col, size_t to_col);
276
// the columns of this in the specified range are reduced by their gcd
277
278
Matrix multiply_rows(const vector<Integer>& m) const; //returns matrix were row i is multiplied by m[i]
279
280
//---------------------------------------------------------------------------
281
// Vector operations
282
//---------------------------------------------------------------------------
283
284
void MxV(vector<Integer>& result, const vector<Integer>& v) const;//result = this*V
285
vector<Integer> MxV(const vector<Integer>& v) const;//returns this*V
286
vector<Integer> VxM(const vector<Integer>& v) const;//returns V*this
287
vector<Integer> VxM_div(const vector<Integer>& v, const Integer& divisor,bool& success) const; // additionally divides by divisor
288
289
//---------------------------------------------------------------------------
290
// Matrix operations
291
// --- these are more complicated algorithms ---
292
//---------------------------------------------------------------------------
293
294
// Normal forms
295
296
// converts this to row echelon form over ZZ and returns rank, GMP protected, uses only elementary transformations over ZZ
297
size_t row_echelon();
298
299
// public version of row_echelon_reduce, GMP protected, uses only elementary transformations over ZZ
300
size_t row_echelon_reduce();
301
302
// transforms matrix into lower triangular form via column transformations
303
// assumes that rk is the rank and that the matrix is zero after the first rk rows
304
// Right = Right*(column transformation of this call)
305
bool column_trigonalize(size_t rk, Matrix<Integer>& Right);
306
307
// combines row_echelon_reduce and column_trigonalize
308
// returns column transformation matrix
309
Matrix<Integer> row_column_trigonalize(size_t& rk, bool& success);
310
311
// rank and determinant
312
313
size_t rank() const; //returns rank
314
Integer full_rank_index() const; // returns index of full rank sublattice
315
size_t rank_submatrix(const vector<key_t>& key) const; //returns rank of submarix defined by key
316
317
// returns rank of submatrix of mother. "this" is used as work space
318
size_t rank_submatrix(const Matrix<Integer>& mother, const vector<key_t>& key);
319
320
// vol stands for |det|
321
Integer vol() const;
322
Integer vol_submatrix(const vector<key_t>& key) const;
323
Integer vol_submatrix(const Matrix<Integer>& mother, const vector<key_t>& key);
324
325
// find linearly indepenpendent submatrix of maximal rank
326
327
vector<key_t> max_rank_submatrix_lex() const; //returns a vector with entries
328
//the indices of the first rows in lexicographic order of this forming
329
//a submatrix of maximal rank.
330
331
// Solution of linear systems with square matrix
332
333
// In the following routines, denom is the absolute value of the determinant of the
334
// left side matrix.
335
// If the diagonal is asked for, ZZ-invertible transformations are used.
336
// Otherwise ther is no restriction on the used algorithm
337
338
//The diagonal of left hand side after transformation into an upper triangular matrix
339
//is saved in diagonal, denom is |determinant|.
340
341
// System with "this" as left side
342
Matrix solve(const Matrix& Right_side, Integer& denom) const;
343
Matrix solve(const Matrix& Right_side, vector< Integer >& diagonal, Integer& denom) const;
344
// solve the system this*Solution=denom*Right_side.
345
346
// system is defined by submatrix of mother given by key (left side) and column vectors pointed to by RS (right side)
347
// NOTE: this is used as the matrix for the work
348
void solve_system_submatrix(const Matrix& mother, const vector<key_t>& key, const vector<vector<Integer>* >& RS,
349
vector< Integer >& diagonal, Integer& denom, size_t red_col, size_t sign_col);
350
void solve_system_submatrix(const Matrix& mother, const vector<key_t>& key, const vector<vector<Integer>* >& RS,
351
Integer& denom, size_t red_col, size_t sign_col, bool compute_denom=true, bool make_sol_prime=false);
352
// the left side gets transposed
353
void solve_system_submatrix_trans(const Matrix& mother, const vector<key_t>& key, const vector<vector<Integer>* >& RS,
354
Integer& denom, size_t red_col, size_t sign_col);
355
356
357
// For non-square matrices
358
359
// The next two solve routines do not require the matrix to be square.
360
// However, we want rank = number of columns, ensuring unique solvability
361
362
vector<Integer> solve_rectangular(const vector<Integer>& v, Integer& denom) const;
363
// computes solution vector for right side v, solution over the rationals
364
// matrix needs not be quadratic, but must have rank = number of columns
365
// with denominator denom.
366
// gcd of denom and solution is extracted !!!!!
367
368
vector<Integer> solve_ZZ(const vector<Integer>& v) const;
369
// computes solution vector for right side v
370
// insists on integrality of the solution
371
372
// homogenous linear systems
373
374
Matrix<Integer> kernel () const;
375
// computes a ZZ-basis of the solutions of (*this)x=0
376
// the basis is formed by the ROWS of the returned matrix
377
378
// inverse matrix
379
380
//this*Solution=denom*I. "this" should be a quadratic matrix with nonzero determinant.
381
Matrix invert(Integer& denom) const;
382
383
void invert_submatrix(const vector<key_t>& key, Integer& denom, Matrix<Integer>& Inv,
384
bool compute_denom=true, bool make_sol_prime=false) const;
385
386
// find linear form that is constant on the rows
387
388
vector<Integer> find_linear_form () const;
389
// Tries to find a linear form which gives the same value an all rows of this
390
// this should be a m x n matrix (m>=n) of maxinal rank
391
// returns an empty vector if there does not exist such a linear form
392
393
vector<Integer> find_linear_form_low_dim () const;
394
//same as find_linear_form but also works with not maximal rank
395
//uses a linear transformation to get a full rank matrix
396
397
// normal forms
398
399
Matrix AlmostHermite(size_t& rk);
400
// Converts "this" into lower trigonal column Hermite normal form, returns column
401
// transformation matrix
402
// Almost: elements left of diagonal are not reduced mod diagonal
403
404
// Computes Smith normal form and returns column transformation matrix
405
Matrix SmithNormalForm(size_t& rk);
406
407
//for simplicial subcones
408
409
// computes support hyperplanes and volume
410
void simplex_data(const vector<key_t>& key, Matrix<Integer>& Supp, Integer& vol, bool compute_vol) const;
411
// finds subdivision points
412
vector<Integer> optimal_subdivision_point() const;
413
414
// Sorting of rows
415
416
Matrix& sort_by_weights(const Matrix<Integer>& Weights, vector<bool> absolute);
417
Matrix& sort_lex();
418
void order_rows_by_perm(const vector<key_t>& perm);
419
420
// solve homogeneous congruences
421
422
Matrix<Integer> solve_congruences(bool& zero_modulus) const;
423
424
// saturate sublattice
425
426
void saturate();
427
428
// find the indices of the rows in which the linear form L takes its max and min values
429
430
vector<key_t> max_and_min(const vector<Integer>& L, const vector<Integer>& norm) const;
431
432
// try to sort the rows in such a way that the extreme points of the polytope spanned by the rows come first
433
434
size_t extreme_points_first(const vector<Integer> norm=vector<Integer>(0));
435
436
// find an inner point in the cone spanned by the rows of the matrix
437
438
vector<Integer> find_inner_point();
439
};
440
//class end *****************************************************************
441
442
//---------------------------------------------------------------------------
443
// Utilities
444
//---------------------------------------------------------------------------
445
446
template<typename Integer> class order_helper {
447
448
public:
449
450
vector<Integer> weight;
451
key_t index;
452
vector<Integer>* v;
453
};
454
455
template<typename T>
456
vector<vector<T> > to_matrix(const vector<T>& v){
457
458
vector<vector<T> > mat(1);
459
mat[0]=v;
460
return mat;
461
}
462
463
template<typename Integer>
464
Matrix<Integer> readMatrix(const string project);
465
466
//---------------------------------------------------------------------------
467
// Conversion between integer types
468
//---------------------------------------------------------------------------
469
470
template<typename ToType, typename FromType>
471
void convert(Matrix<ToType>& to_mat, const Matrix<FromType>& from_mat);
472
473
template<typename Integer>
474
void mat_to_mpz(const Matrix<Integer>& mat, Matrix<mpz_class>& mpz_mat);
475
476
template<typename Integer>
477
void mat_to_Int(const Matrix<mpz_class>& mpz_mat, Matrix<Integer>& mat);
478
479
template<typename Integer>
480
void mpz_submatrix(Matrix<mpz_class>& sub, const Matrix<Integer>& mother, const vector<key_t>& selection);
481
482
template<typename Integer>
483
void mpz_submatrix_trans(Matrix<mpz_class>& sub, const Matrix<Integer>& mother, const vector<key_t>& selection);
484
485
} // namespace
486
487
//---------------------------------------------------------------------------
488
#endif
489
//---------------------------------------------------------------------------
490
491