Matrix-Algebra
/
main.cpp
568 строк · 14.5 Кб
1#include <iostream>
2#include <iomanip>
3#include <cmath>
4
5using namespace std;
6
7class MatrixException : public exception {
8private:
9char *message;
10
11public:
12MatrixException(char *msg) : message(msg) {}
13
14char *what() {
15return message;
16}
17};
18
19
20class Matrix {
21protected:
22unsigned int n;
23unsigned int m;
24double **data;
25
26public:
27Matrix(int cols, int rows) {
28n = cols;
29m = rows;
30
31data = new double *[cols];
32for (int i = 0; i < cols; i++) {
33data[i] = new double[rows];
34for (int j = 0; j < rows; j++) {
35data[i][j] = 0;
36}
37}
38}
39
40
41int getN() {
42return n;
43}
44
45int getM() {
46return m;
47}
48
49
50void setValue(int i, int j, double value) {
51data[i][j] = value;
52}
53
54double getValue(int i, int j) {
55return data[i][j];
56}
57
58// double *getRow(int i) {
59// double ans[n];
60// for (int k = 0; k < n; k++) {
61// ans[k] = data[i][k];
62// }
63//
64// return ans;
65// }
66
67Matrix getCopy() {
68Matrix ans = Matrix(getN(), getM());
69for (int i = 0; i < getN(); i++) {
70for (int j = 0; j < getM(); j++) {
71ans.setValue(i, j, getValue(i, j));
72}
73}
74return ans;
75}
76
77Matrix operator+(Matrix const secondMatrix) const {
78if (n != secondMatrix.n || m != secondMatrix.m) {
79throw MatrixException((char *) "Error: the dimensional problem occurred");
80}
81Matrix answer = Matrix(n, m);
82for (int i = 0; i < n; i++) {
83for (int j = 0; j < m; j++) {
84answer.data[i][j] = data[i][j] + secondMatrix.data[i][j];
85}
86}
87return answer;
88}
89
90Matrix operator-(Matrix const secondMatrix) const {
91if (n != secondMatrix.n || m != secondMatrix.m) {
92throw MatrixException((char *) "Error: the dimensional problem occurred");
93}
94Matrix answer = Matrix(n, m);
95for (int i = 0; i < n; i++) {
96for (int j = 0; j < m; j++) {
97answer.data[i][j] = data[i][j] - secondMatrix.data[i][j];
98}
99}
100return answer;
101}
102
103Matrix operator*(Matrix const secondMatrix) const {
104if (m != secondMatrix.n) {
105throw MatrixException((char *) "Error: the dimensional problem occurred");
106}
107Matrix answer = Matrix(n, secondMatrix.m);
108
109for (int i = 0; i < n; i++) {
110for (int j = 0; j < secondMatrix.m; j++) {
111
112for (int k = 0; k < secondMatrix.n; k++) {
113answer.setValue(i, j, answer.data[i][j] + data[i][k] * secondMatrix.data[k][j]);
114}
115}
116
117}
118
119return answer;
120}
121
122Matrix getTranspose() {
123
124Matrix answer = Matrix(m, n);
125
126for (int i = 0; i < n; i++) {
127for (int j = 0; j < m; j++) {
128answer.setValue(j, i, data[i][j]);
129}
130}
131
132return answer;
133
134}
135
136Matrix &operator=(Matrix const &otherMatrix) {
137data = otherMatrix.data;
138n = otherMatrix.n;
139m = otherMatrix.m;
140return *this;
141}
142
143friend istream &operator>>(istream &is, Matrix &matrix) {
144for (int i = 0; i < matrix.n; i++) {
145for (int j = 0; j < matrix.m; j++) {
146double t;
147is >> t;
148matrix.setValue(i, j, t);
149}
150}
151return is;
152}
153
154friend ostream &operator<<(ostream &os, Matrix &matrix) {
155for (int i = 0; i < matrix.n; i++) {
156for (int j = 0; j < matrix.m; j++) {
157double num = matrix.getValue(i, j);
158if (abs(num) < 0.005) {
159os << setprecision(4) << fixed << abs(matrix.getValue(i, j));
160} else {
161os << setprecision(4) << fixed << matrix.getValue(i, j);
162}
163if (j != matrix.m - 1) {
164cout << " ";
165}
166
167
168}
169os << endl;
170}
171return os;
172}
173
174double getDeterminant();
175
176Matrix getInverse();
177
178Matrix solveGaussianEquation(Matrix b);
179
180Matrix solveJacobianEquation(Matrix b, long double epsilon);
181
182Matrix solveSeidelEquation(Matrix b, long double epsilon);
183
184
185static void printAugmented(Matrix left, Matrix right) {
186
187for (int i = 0; i < left.getN(); i++) {
188for (int j = 0; j < left.getM(); j++) {
189cout << setprecision(2) << fixed << left.getValue(i, j) << " ";
190}
191for (int j = 0; j < right.getM(); j++) {
192cout << setprecision(2) << fixed << right.getValue(i, j) << " ";
193}
194cout << endl;
195}
196}
197
198};
199
200class ColumnVector : public Matrix {
201public:
202ColumnVector(int n) : Matrix(n, 1) {
203
204}
205
206};
207
208class SquareMatrix : public Matrix {
209public:
210SquareMatrix(int n) : Matrix(n, n) {
211
212}
213};
214
215class IdentityMatrix : public SquareMatrix {
216public:
217IdentityMatrix(int n) : SquareMatrix(n) {
218for (int i = 0; i < n; i++) {
219for (int j = 0; j < n; j++) {
220if (i == j) {
221setValue(i, j, 1);
222}
223}
224}
225}
226
227IdentityMatrix(Matrix matrix) : SquareMatrix(max(matrix.getN(), matrix.getM())) {
228int maxSize = max(matrix.getN(), matrix.getM());
229int minSize = min(matrix.getN(), matrix.getM());
230for (int i = 0; i < maxSize; i++) {
231for (int j = 0; j < maxSize; j++) {
232if (i == j && i < minSize) {
233setValue(i, j, 1);
234}
235}
236}
237}
238};
239
240class EliminationMatrix : public IdentityMatrix {
241public:
242EliminationMatrix(Matrix matrix, int i, int j) : IdentityMatrix(matrix.getN()) {
243i--;
244j--;
245double e = -matrix.getValue(i, j) / matrix.getValue(j, j);
246setValue(i, j, e);
247}
248};
249
250class PermutationMatrix : public IdentityMatrix {
251public:
252PermutationMatrix(Matrix matrix, int i, int j) : IdentityMatrix(matrix.getN()) {
253i--;
254j--;
255setValue(i, i, 0);
256setValue(j, j, 0);
257setValue(i, j, 1);
258setValue(j, i, 1);
259}
260};
261
262double Matrix::getDeterminant() {
263Matrix result = getCopy();
264int steps = 1;
265
266for (int j = 0; j < getM(); j++) {
267if (j != result.getM() - 1) {
268double pivot = result.getValue(j, j);
269int pivot_i = j;
270for (int i = j; i < getN(); i++) {
271if (abs(result.getValue(i, j)) > abs(pivot)) {
272pivot = result.getValue(i, j);
273pivot_i = i;
274}
275}
276if (pivot_i != j) {
277Matrix p = PermutationMatrix(result, pivot_i + 1, j + 1);
278result = p * result;
279cout << "step #" << steps << ": permutation" << endl;
280cout << result;
281steps++;
282}
283}
284for (int i = j + 1; i < getN(); i++) {
285if (result.getValue(i, j) != 0) {
286Matrix e = EliminationMatrix(result, i + 1, j + 1);
287result = e * result;
288cout << "step #" << steps << ": elimination" << endl;
289cout << result;
290steps++;
291}
292}
293}
294
295double det = 1;
296for (int i = 0; i < n; i++) {
297det *= result.getValue(i, i);
298}
299cout << "result:" << endl << setprecision(2) << fixed << det << endl;
300return det;
301}
302
303Matrix Matrix::getInverse() {
304if (getN() != getM()) {
305throw MatrixException((char *) "Error: the dimensional problem occurred");
306}
307Matrix left = getCopy();
308Matrix right = IdentityMatrix(getN());
309
310for (int j = 0; j < getM(); j++) {
311if (j != left.getM() - 1) {
312double pivot = left.getValue(j, j);
313int pivot_i = j;
314for (int i = j; i < getN(); i++) {
315if (abs(left.getValue(i, j)) > abs(pivot)) {
316pivot = left.getValue(i, j);
317pivot_i = i;
318}
319}
320if (pivot_i != j) {
321Matrix p = PermutationMatrix(left, pivot_i + 1, j + 1);
322left = p * left;
323right = p * right;
324}
325}
326for (int i = j + 1; i < getN(); i++) {
327if (left.getValue(i, j) != 0) {
328Matrix e = EliminationMatrix(left, i + 1, j + 1);
329left = e * left;
330right = e * right;
331}
332}
333}
334
335for (int j = getM() - 1; j >= 0; j--) {
336
337for (int i = j - 1; i >= 0; i--) {
338if (left.getValue(i, j) != 0) {
339Matrix e = EliminationMatrix(left, i + 1, j + 1);
340left = e * left;
341right = e * right;
342}
343}
344}
345
346for (int i = 0; i < getN(); i++) {
347double value = 1 / left.getValue(i, i);
348left.setValue(i, i, left.getValue(i, i) * value);
349
350for (int j = 0; j < getN(); j++) {
351right.setValue(i, j, right.getValue(i, j) * value);
352}
353}
354
355
356return right;
357}
358
359Matrix Matrix::solveGaussianEquation(Matrix b) {
360if (b.getM() != 1) {
361if (getN() != getM()) {
362throw MatrixException((char *) "Error: the dimensional problem occurred");
363}
364}
365Matrix left = getCopy();
366Matrix right = b.getCopy();
367
368
369for (int j = 0; j < getM(); j++) {
370if (j != left.getM() - 1) {
371double pivot = left.getValue(j, j);
372int pivot_i = j;
373for (int i = j; i < getN(); i++) {
374if (abs(left.getValue(i, j)) > abs(pivot)) {
375pivot = left.getValue(i, j);
376pivot_i = i;
377}
378}
379if (pivot_i != j) {
380Matrix p = PermutationMatrix(left, pivot_i + 1, j + 1);
381left = p * left;
382right = p * right;
383}
384}
385for (int i = j + 1; i < getN(); i++) {
386if (left.getValue(i, j) != 0) {
387Matrix e = EliminationMatrix(left, i + 1, j + 1);
388left = e * left;
389right = e * right;
390}
391}
392}
393for (int j = getM() - 1; j >= 0; j--) {
394for (int i = j - 1; i >= 0; i--) {
395if (left.getValue(i, j) != 0) {
396Matrix e = EliminationMatrix(left, i + 1, j + 1);
397left = e * left;
398right = e * right;
399}
400}
401}
402
403for (int i = 0; i < getN(); i++) {
404double value = 1 / left.getValue(i, i);
405
406left.setValue(i, i, left.getValue(i, i) * value);
407right.setValue(i, 0, right.getValue(i, 0) * value);
408}
409
410return right;
411}
412
413Matrix Matrix::solveJacobianEquation(Matrix b, long double epsilon) {
414if (getM() != b.getN()) {
415throw MatrixException("The method is not applicable!");
416}
417for (int i = 0; i < getN(); i++) {
418if (getValue(i, i) == 0) {
419throw MatrixException("The method is not applicable!");
420}
421long double sum = 0;
422for (int j = 0; j < getM(); j++) {
423if (i != j) {
424sum += getValue(i, j);
425}
426}
427if (getValue(i, i) < sum) {
428throw MatrixException("The method is not applicable!");
429}
430}
431Matrix aD = SquareMatrix(n);
432for (int i = 0; i < getN(); i++) {
433aD.setValue(i, i, getValue(i, i));
434}
435Matrix aDInverse = aD.getInverse();
436
437Matrix alpha = aDInverse * (aD - *this);
438cout << "alpha:" << endl << alpha;
439
440Matrix beta = aDInverse * b;
441cout << "beta:" << endl << beta;
442
443Matrix x = beta.getCopy();
444Matrix newx = IdentityMatrix(beta);
445cout << "x(0):" << endl << x;
446int steps = 1;
447
448while (true) {
449newx = alpha * x + beta;
450Matrix delta = newx - x;
451long double error = 0;
452for (int i = 0; i < delta.getN(); i++) {
453error += powl(delta.getValue(i, 0), 2);
454}
455error = ::sqrt(error);
456cout << "e: " << error << endl;
457
458
459cout << "x(" << steps++ << "):" << endl << newx;
460
461if (error <= epsilon) {
462return x;
463}
464
465x = newx;
466}
467}
468
469Matrix Matrix::solveSeidelEquation(Matrix b, long double epsilon) {
470if (getM() != b.getN()) {
471throw MatrixException("The method is not applicable!");
472}
473for (int i = 0; i < getN(); i++) {
474if (getValue(i, i) == 0) {
475throw MatrixException("The method is not applicable!");
476}
477long double sum = 0;
478for (int j = 0; j < getM(); j++) {
479if (i != j) {
480sum += fabs(getValue(i, j));
481}
482}
483if (fabs(getValue(i, i)) < sum) {
484throw MatrixException("The method is not applicable!");
485}
486}
487
488Matrix aD = SquareMatrix(n);
489for (int i = 0; i < getN(); i++) {
490aD.setValue(i, i, getValue(i, i));
491}
492
493Matrix aDInverse = aD.getInverse();
494
495Matrix alpha = aDInverse * (aD - *this);
496Matrix beta = aDInverse * b;
497
498Matrix aL = SquareMatrix(n);
499for (int j = 0; j < getM(); j++){
500for (int i = j + 1; i < getN(); i++){
501aL.setValue(i, j, alpha.getValue(i, j));
502}
503}
504
505Matrix aU = SquareMatrix(n);
506for (int j = getM() - 1; j >= 0; j--) {
507for (int i = j - 1; i >= 0; i--){
508aU.setValue(i, j, alpha.getValue(i, j));
509}
510}
511
512Matrix IminusB = IdentityMatrix(aL) - aL;
513Matrix IminusBInverse = IminusB.getInverse();
514
515cout << "beta:" << endl << beta;
516cout << "alpha:" << endl << alpha;
517cout << "B:" << endl << aL;
518cout << "C:" << endl << aU;
519cout << "I-B:" << endl << IminusB;
520cout << "(I-B)_-1:" << endl << IminusBInverse;
521cout << "x(0):" << endl << beta;
522
523Matrix x = beta.getCopy();
524int steps = 1;
525while (true){
526Matrix newx = IminusBInverse * (aU * x + beta);
527
528Matrix delta = newx - x;
529long double error = 0;
530for (int i = 0; i < delta.getN(); i++) {
531error += powl(delta.getValue(i, 0), 2);
532}
533error = ::sqrt(error);
534cout << "e: " << error << endl;
535
536cout << "x(" << steps++ << "):" << endl << newx;
537
538if (error <= epsilon) {
539return x;
540}
541
542x = newx;
543}
544}
545
546int main() {
547int n;
548cin >> n;
549
550Matrix a = SquareMatrix(n);
551cin >> a;
552
553cin >> n;
554Matrix b = ColumnVector(n);
555cin >> b;
556
557double epsilon;
558cin >> epsilon;
559
560try {
561a.solveSeidelEquation(b, epsilon);
562}
563catch (MatrixException e) {
564cout << e.what() << endl;
565}
566return 0;
567
568}
569
570
571
572