Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
DoubleMatrix.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
10
12{
16 public sealed class DoubleMatrix : RingElement, IMatrix
17 {
18 private double[,] values;
19 private IElement[,] matrixElements;
20 private ICollection<IElement> elements;
21 private readonly int rows;
22 private readonly int columns;
23
28 public DoubleMatrix(double[,] Values)
29 {
30 this.values = Values;
31 this.elements = null;
32 this.matrixElements = null;
33 this.rows = Values.GetLength(0);
34 this.columns = Values.GetLength(1);
35 }
36
43 public DoubleMatrix(int Rows, int Columns, ICollection<IElement> Elements)
44 {
45 this.values = null;
46 this.matrixElements = null;
47 this.elements = Elements;
48 this.rows = Rows;
49 this.columns = Columns;
50 }
51
55 public double[,] Values
56 {
57 get
58 {
59 if (this.values is null)
60 {
61 double[,] v = new double[this.rows, this.columns];
62 int x = 0;
63 int y = 0;
64
65 foreach (IElement E in this.elements)
66 {
67 if (!(E.AssociatedObjectValue is double d))
68 d = 0;
69
70 v[y, x++] = d;
71 if (x >= this.columns)
72 {
73 y++;
74 x = 0;
75 }
76 }
77
78 this.values = v;
79 }
80
81 return this.values;
82 }
83 }
84
88 public ICollection<IElement> Elements
89 {
90 get
91 {
92 if (this.elements is null)
93 {
94 int x, y, i = 0;
95 IElement[] v = new IElement[this.rows * this.columns];
96
97 for (y = 0; y < this.rows; y++)
98 {
99 for (x = 0; x < this.columns; x++)
100 v[i++] = new DoubleNumber(this.values[y, x]);
101 }
102
103 this.elements = v;
104 }
105
106 return this.elements;
107 }
108 }
109
114 {
115 get
116 {
117 if (this.matrixElements is null)
118 {
119 IElement[,] v = new IElement[this.rows, this.columns];
120 int x = 0;
121 int y = 0;
122
123 foreach (IElement E in this.Elements)
124 {
125 v[y, x++] = E;
126 if (x >= this.columns)
127 {
128 y++;
129 x = 0;
130 }
131 }
132
133 this.matrixElements = v;
134 }
135
136 return this.matrixElements;
137 }
138 }
139
143 public int Rows => this.rows;
144
148 public int Columns => this.columns;
149
151 public override string ToString()
152 {
153 double[,] v = this.Values;
154 StringBuilder sb = null;
155 bool First;
156 int x, y;
157
158 for (y = 0; y < this.rows; y++)
159 {
160 if (sb is null)
161 sb = new StringBuilder("[[");
162 else
163 sb.Append(",\r\n [");
164
165 First = true;
166 for (x = 0; x < this.columns; x++)
167 {
168 if (First)
169 First = false;
170 else
171 sb.Append(", ");
172
173 sb.Append(Expression.ToString(v[y, x]));
174 }
175
176 sb.Append(']');
177 }
178
179 if (sb is null)
180 sb = new StringBuilder("[[]]");
181 else
182 sb.Append(']');
183
184 return sb.ToString();
185 }
186
190 public override IRing AssociatedRing
191 {
192 get
193 {
194 if (this.associatedMatrixSpace is null)
195 this.associatedMatrixSpace = new DoubleMatrices(this.rows, this.columns);
196
197 return this.associatedMatrixSpace;
198 }
199 }
200
201 private DoubleMatrices associatedMatrixSpace = null;
202
206 public override object AssociatedObjectValue => this;
207
214 {
215 double[,] v;
216 int x, y, z;
217
218 if (Element.AssociatedObjectValue is double n)
219 {
220 double[,] Values = this.Values;
221
222 v = new double[this.rows, this.columns];
223
224 for (y = 0; y < this.rows; y++)
225 {
226 for (x = 0; x < this.columns; x++)
227 v[y, x] = n * Values[y, x];
228 }
229
230 return new DoubleMatrix(v);
231 }
232 else if (Element is DoubleMatrix Matrix)
233 {
234 if (Matrix.columns != this.rows)
235 return null;
236
237 double[,] Values = this.Values;
238 double[,] Values2 = Matrix.Values;
239
240 v = new double[Matrix.rows, this.columns];
241 for (y = 0; y < Matrix.rows; y++)
242 {
243 for (x = 0; x < this.columns; x++)
244 {
245 n = 0;
246
247 for (z = 0; z < this.rows; z++)
248 n += Values2[y, z] * Values[z, x];
249
250 v[y, x] = n;
251 }
252 }
253
254 return new DoubleMatrix(v);
255 }
256 else if (Element is IMatrix)
257 return new ObjectMatrix(this.MatrixElements).MultiplyLeft(Element);
258 else
259 return null;
260 }
261
268 {
269 double[,] v;
270 int x, y, z;
271
272 if (Element.AssociatedObjectValue is double n)
273 {
274 double[,] Values = this.Values;
275
276 v = new double[this.rows, this.columns];
277
278 for (y = 0; y < this.rows; y++)
279 {
280 for (x = 0; x < this.columns; x++)
281 v[y, x] = n * Values[y, x];
282 }
283
284 return new DoubleMatrix(v);
285 }
286 else if (Element is DoubleMatrix Matrix)
287 {
288 if (this.columns != Matrix.rows)
289 return null;
290
291 double[,] Values = this.Values;
292 double[,] Values2 = Matrix.Values;
293
294 v = new double[this.rows, Matrix.columns];
295 for (y = 0; y < this.rows; y++)
296 {
297 for (x = 0; x < Matrix.columns; x++)
298 {
299 n = 0;
300
301 for (z = 0; z < this.columns; z++)
302 n += Values[y, z] * Values2[z, x];
303
304 v[y, x] = n;
305 }
306 }
307
308 return new DoubleMatrix(v);
309 }
310 else if (Element is IMatrix)
311 return new ObjectMatrix(this.MatrixElements).MultiplyRight(Element);
312 else
313 return null;
314 }
315
320 public override IRingElement Invert()
321 {
322 if (this.rows != this.columns)
323 return null;
324
325 double[,] Values = this.Values;
326 int c2 = this.columns << 1;
327 double[,] v = new double[this.rows, c2];
328 int x, y;
329
330 for (y = 0; y < this.rows; y++)
331 {
332 for (x = 0; x < this.columns; x++)
333 {
334 v[y, x] = Values[y, x];
335 v[y, x + this.columns] = (x == y ? 1 : 0);
336 }
337 }
338
339 if (Reduce(v, true, true, out _) < 0)
340 return null;
341
342 double[,] v2 = new double[this.rows, this.columns];
343
344 for (y = 0; y < this.rows; y++)
345 {
346 for (x = 0; x < this.columns; x++)
347 v2[y, x] = v[y, x + this.columns];
348 }
349
350 return new DoubleMatrix(v2);
351 }
352
364 public IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
365 {
366 double[,] M = (double[,])this.Values.Clone();
367 Rank = Reduce(M, Eliminate, BreakIfZero, out double c);
368 Factor = new DoubleNumber(c);
369 return new DoubleMatrix(M);
370 }
371
383 public static int Reduce(double[,] Matrix, bool Eliminate, bool BreakIfZero,
384 out double Factor)
385 {
386 int x, y, u, z;
387 int Rows = Matrix.GetLength(0);
388 int Columns = Matrix.GetLength(1);
389 int MinCount = Math.Min(Rows, Columns);
390 double a, b;
391 int Rank = 0;
392
393 Factor = 1;
394
395 for (x = 0; x < MinCount; x++)
396 {
397 a = Math.Abs(Matrix[x, x]);
398 z = x;
399 for (y = x + 1; y < Rows; y++)
400 {
401 b = Math.Abs(Matrix[y, x]);
402 if (b > a)
403 {
404 a = b;
405 z = y;
406 }
407 }
408
409 if (z != x)
410 {
411 for (u = x; u < Columns; u++)
412 {
413 a = Matrix[x, u];
414 Matrix[x, u] = Matrix[z, u];
415 Matrix[z, u] = a;
416 }
417
418 Factor = -Factor;
419 }
420
421 a = Matrix[x, x];
422 if (a == 0)
423 {
424 if (BreakIfZero)
425 return -1;
426 }
427 else
428 {
429 Rank++;
430
431 if (a != 1)
432 {
433 for (u = x; u < Columns; u++)
434 Matrix[x, u] /= a;
435
436 Factor *= a;
437 }
438
439 for (y = Eliminate ? 0 : x + 1; y < Rows; y++)
440 {
441 if (y != x && (a = Matrix[y, x]) != 0)
442 {
443 for (u = x; u < Columns; u++)
444 Matrix[y, u] -= a * Matrix[x, u];
445 }
446 }
447 }
448 }
449
450 return Rank;
451 }
452
459 {
460 double[,] v;
461 int x, y;
462
463 if (Element.AssociatedObjectValue is double d)
464 {
465 double[,] Values = this.Values;
466
467 v = new double[this.rows, this.columns];
468
469 for (y = 0; y < this.rows; y++)
470 {
471 for (x = 0; x < this.columns; x++)
472 v[y, x] = d + Values[y, x];
473 }
474
475 return new DoubleMatrix(v);
476 }
477 else if (Element is DoubleMatrix Matrix)
478 {
479 if (this.columns != Matrix.columns || this.rows != Matrix.rows)
480 return null;
481
482 double[,] Values = this.Values;
483 double[,] Values2 = Matrix.Values;
484
485 v = new double[this.rows, this.columns];
486 for (y = 0; y < this.rows; y++)
487 {
488 for (x = 0; x < this.columns; x++)
489 v[y, x] = Values[y, x] + Values2[y, x];
490 }
491
492 return new DoubleMatrix(v);
493 }
494 else if (Element is IMatrix)
495 return new ObjectMatrix(this.MatrixElements).Add(Element);
496 else
497 return null;
498 }
499
504 public override IGroupElement Negate()
505 {
506 double[,] Values = this.Values;
507 double[,] v = new double[this.rows, this.columns];
508 int x, y;
509
510 for (y = 0; y < this.rows; y++)
511 {
512 for (x = 0; x < this.columns; x++)
513 v[y, x] = -Values[y, x];
514 }
515
516 return new DoubleMatrix(v);
517 }
518
524 public override bool Equals(object obj)
525 {
526 if (obj is DoubleMatrix Matrix)
527 {
528 if (this.columns != Matrix.columns || this.rows != Matrix.rows)
529 return false;
530
531 double[,] V1 = this.Values;
532 double[,] V2 = Matrix.Values;
533 int x, y;
534
535 for (y = 0; y < this.rows; y++)
536 {
537 for (x = 0; x < this.columns; x++)
538 {
539 if (V1[y, x] != V2[y, x])
540 return false;
541 }
542 }
543
544 return true;
545 }
546 else if (obj is IMatrix)
547 return new ObjectMatrix(this.MatrixElements).Equals(obj);
548 else
549 return false;
550 }
551
556 public override int GetHashCode()
557 {
558 double[,] Values = this.Values;
559 int Result = 0;
560 int x, y;
561
562 for (y = 0; y < this.rows; y++)
563 {
564 for (x = 0; x < this.columns; x++)
565 Result ^= Values[y, x].GetHashCode();
566 }
567
568 return Result;
569 }
570
574 public override bool IsScalar => false;
575
579 public override ICollection<IElement> ChildElements => this.Elements;
580
587 public override IElement Encapsulate(ICollection<IElement> Elements, ScriptNode Node)
588 {
589 return MatrixDefinition.Encapsulate(Elements, this.rows, this.columns, Node);
590 }
591
596 {
597 get
598 {
599 if (this.zero is null)
600 this.zero = new DoubleMatrix(new double[this.rows, this.columns]);
601
602 return this.zero;
603 }
604 }
605
606 private DoubleMatrix zero = null;
607
611 public int Dimension => this.rows;
612
616 public ICollection<IElement> VectorElements
617 {
618 get
619 {
620 if (!(this.rowVectors is null))
621 return this.rowVectors;
622
623 double[,] v = this.Values;
624 LinkedList<IElement> Rows = new LinkedList<IElement>();
625 int x, y;
626 double[] r;
627
628 for (y = 0; y < this.rows; y++)
629 {
630 r = new double[this.columns];
631
632 for (x = 0; x < this.columns; x++)
633 r[x] = v[y, x];
634
635 Rows.AddLast(new DoubleVector(r));
636 }
637
638 this.rowVectors = Rows;
639 return Rows;
640 }
641 }
642
643 private LinkedList<IElement> rowVectors = null;
644
650 {
651 double[,] v = new double[this.columns, this.rows];
652 double[,] Values = this.Values;
653 int x, y;
654
655 for (y = 0; y < this.rows; y++)
656 {
657 for (x = 0; x < this.columns; x++)
658 v[x, y] = Values[y, x];
659 }
660
661 return new DoubleMatrix(v);
662 }
663
669 {
670 return this.Transpose();
671 }
672
678 public IElement GetElement(int Index)
679 {
680 if (Index < 0 || Index >= this.rows)
681 throw new ScriptException("Index out of bounds.");
682
683 double[,] M = this.Values;
684 double[] V = new double[this.columns];
685 int i;
686
687 for (i = 0; i < this.columns; i++)
688 V[i] = M[Index, i];
689
690 return new DoubleVector(V);
691 }
692
698 public void SetElement(int Index, IElement Value)
699 {
700 if (Index < 0 || Index >= this.rows)
701 throw new ScriptException("Index out of bounds.");
702
703 if (!(Value is DoubleVector V))
704 throw new ScriptException("Row vectors in a double matrix are required to be double vectors.");
705
706 if (V.Dimension != this.columns)
707 throw new ScriptException("Dimension mismatch.");
708
709 double[] V2 = V.Values;
710 double[,] M = this.Values;
711 this.elements = null;
712
713 int i;
714
715 for (i = 0; i < this.columns; i++)
716 M[Index, i] = V2[i];
717 }
718
725 public IElement GetElement(int Column, int Row)
726 {
727 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
728 throw new ScriptException("Index out of bounds.");
729
730 return new DoubleNumber(this.Values[Row, Column]);
731 }
732
739 public void SetElement(int Column, int Row, IElement Value)
740 {
741 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
742 throw new ScriptException("Index out of bounds.");
743
744 if (!(Value.AssociatedObjectValue is double d))
745 throw new ScriptException("Elements in a double matrix must be double values.");
746
747 double[,] M = this.Values;
748 this.elements = null;
749
750 M[Row, Column] = d;
751 }
752
758 public IVector GetRow(int Row)
759 {
760 if (Row < 0 || Row >= this.rows)
761 throw new ScriptException("Index out of bounds.");
762
763 double[,] M = this.Values;
764 double[] V = new double[this.columns];
765 int i;
766
767 for (i = 0; i < this.columns; i++)
768 V[i] = M[Row, i];
769
770 return new DoubleVector(V);
771 }
772
778 public IVector GetColumn(int Column)
779 {
780 if (Column < 0 || Column >= this.columns)
781 throw new ScriptException("Index out of bounds.");
782
783 double[,] M = this.Values;
784 double[] V = new double[this.rows];
785 int i;
786
787 for (i = 0; i < this.rows; i++)
788 V[i] = M[i, Column];
789
790 return new DoubleVector(V);
791 }
792
798 public void SetRow(int Row, IVector Vector)
799 {
800 if (Row < 0 || Row >= this.rows)
801 throw new ScriptException("Index out of bounds.");
802
803 if (Vector.Dimension != this.columns)
804 throw new ScriptException("Vector dimension does not match number of columns");
805
806 if (!(Vector is DoubleVector V))
807 throw new ScriptException("Row vectors in a double matrix must be double vectors.");
808
809 double[] V2 = V.Values;
810 double[,] M = this.Values;
811 this.elements = null;
812 int i;
813
814 for (i = 0; i < this.columns; i++)
815 M[Row, i] = V2[i];
816 }
817
823 public void SetColumn(int Column, IVector Vector)
824 {
825 if (Column < 0 || Column >= this.columns)
826 throw new ScriptException("Index out of bounds.");
827
828 if (Vector.Dimension != this.rows)
829 throw new ScriptException("Vector dimension does not match number of rows");
830
831 if (!(Vector is DoubleVector V))
832 throw new ScriptException("Column vectors in a double matrix must be double vectors.");
833
834 double[] V2 = V.Values;
835 double[,] M = this.Values;
836 this.elements = null;
837 int i;
838
839 for (i = 0; i < this.rows; i++)
840 M[i, Column] = V2[i];
841 }
842 }
843}
Base class for all types of elements.
Definition: Element.cs:13
abstract object AssociatedObjectValue
Associated object value.
Definition: Element.cs:46
Base class for all types of ring elements.
Definition: RingElement.cs:10
Base class for script exceptions.
Class managing a script expression.
Definition: Expression.cs:39
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4496
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
Pseudo-ring of Double-valued matrices.
IElement GetElement(int Column, int Row)
Gets an element of the matrix.
IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
Reduces a matrix.
void SetColumn(int Column, IVector Vector)
Gets a column vector from the matrix.
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
static int Reduce(double[,] Matrix, bool Eliminate, bool BreakIfZero, out double Factor)
Reduces a matrix.
IElement GetElement(int Index)
Gets an element of the vector.
DoubleMatrix(int Rows, int Columns, ICollection< IElement > Elements)
Double-valued vector.
Definition: DoubleMatrix.cs:43
override IGroupElement Negate()
Negates the element.
override bool IsScalar
If the element represents a scalar value.
void SetElement(int Index, IElement Value)
Sets an element in the vector.
int Dimension
Dimension of matrix, if seen as a vector of row vectors.
IMatrix Transpose()
Returns a transposed matrix.
override bool Equals(object obj)
Compares the element to another.
IElement[,] MatrixElements
Matrix elements
double[,] Values
Matrix element values.
Definition: DoubleMatrix.cs:56
override object AssociatedObjectValue
Associated object value.
IVector GetRow(int Row)
Gets a row vector from the matrix.
void SetElement(int Column, int Row, IElement Value)
Sets an element in the matrix.
override IRing AssociatedRing
Associated Ring.
ICollection< IElement > VectorElements
Vector of row vectors.
DoubleMatrix(double[,] Values)
Double-valued matrix.
Definition: DoubleMatrix.cs:28
override IRingElement MultiplyLeft(IRingElement Element)
Tries to multiply an element to the current element, from the left.
IMatrix ConjugateTranspose()
Returns a conjugate transposed matrix.
override IElement Encapsulate(ICollection< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
override IRingElement MultiplyRight(IRingElement Element)
Tries to multiply an element to the current element, from the right.
override IRingElement Invert()
Inverts the element, if possible.
IVector GetColumn(int Column)
Gets a column vector from the matrix.
void SetRow(int Row, IVector Vector)
Gets a row vector from the matrix.
ICollection< IElement > Elements
Matrix elements.
Definition: DoubleMatrix.cs:89
override IAbelianGroupElement Zero
Returns the zero element of the group.
override int GetHashCode()
Calculates a hash code of the element.
override IAbelianGroupElement Add(IAbelianGroupElement Element)
Tries to add an element to the current element.
override IRingElement MultiplyRight(IRingElement Element)
Tries to multiply an element to the current element, from the right.
override IAbelianGroupElement Add(IAbelianGroupElement Element)
Tries to add an element to the current element.
override IRingElement MultiplyLeft(IRingElement Element)
Tries to multiply an element to the current element, from the left.
override bool Equals(object obj)
Compares the element to another.
static IMatrix Encapsulate(ICollection< IElement > Rows, ScriptNode Node)
Encapsulates the elements of a matrix.
Basic interface for all types of abelian group elements.
Basic interface for all types of commutative ring with identity elements.
Basic interface for all types of elements.
Definition: IElement.cs:20
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:33
Basic interface for all types of group elements.
Definition: IGroupElement.cs:9
Basic interface for matrices.
Definition: IMatrix.cs:9
Basic interface for all types of ring elements.
Definition: IRingElement.cs:10
Basic interface for vectors.
Definition: IVector.cs:9
int Dimension
Dimension of vector.
Definition: IVector.cs:14
Basic interface for all types of rings.
Definition: IRing.cs:10