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