Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ComplexMatrix.cs
1using System;
2using System.Collections.Generic;
3using System.Numerics;
4using System.Text;
11
13{
17 public sealed class ComplexMatrix : RingElement, IMatrix
18 {
19 private Complex[,] values;
20 private IElement[,] matrixElements;
21 private ICollection<IElement> elements;
22 private readonly int rows;
23 private readonly int columns;
24
29 public ComplexMatrix(Complex[,] Values)
30 {
31 this.values = Values;
32 this.elements = null;
33 this.matrixElements = null;
34 this.rows = Values.GetLength(0);
35 this.columns = Values.GetLength(1);
36 }
37
44 public ComplexMatrix(int Rows, int Columns, ICollection<IElement> Elements)
45 {
46 this.values = null;
47 this.elements = Elements;
48 this.matrixElements = null;
49 this.rows = Rows;
50 this.columns = Columns;
51 }
52
56 public Complex[,] Values
57 {
58 get
59 {
60 if (this.values is null)
61 {
62 Complex[,] v = new Complex[this.rows, this.columns];
63 int x = 0;
64 int y = 0;
65
66 foreach (IElement E in this.elements)
67 {
68 if (!(E.AssociatedObjectValue is Complex z))
69 z = 0;
70
71 v[y, x++] = z;
72 if (x >= this.columns)
73 {
74 y++;
75 x = 0;
76 }
77 }
78
79 this.values = v;
80 }
81
82 return this.values;
83 }
84 }
85
89 public ICollection<IElement> Elements
90 {
91 get
92 {
93 if (this.elements is null)
94 {
95 int x, y, i = 0;
96 IElement[] v = new IElement[this.rows * this.columns];
97
98 for (y = 0; y < this.rows; y++)
99 {
100 for (x = 0; x < this.columns; x++)
101 v[i++] = new ComplexNumber(this.values[y, x]);
102 }
103
104 this.elements = v;
105 }
106
107 return this.elements;
108 }
109 }
110
115 {
116 get
117 {
118 if (this.matrixElements is null)
119 {
120 IElement[,] v = new IElement[this.rows, this.columns];
121 int x = 0;
122 int y = 0;
123
124 foreach (IElement E in this.Elements)
125 {
126 v[y, x++] = E;
127 if (x >= this.columns)
128 {
129 y++;
130 x = 0;
131 }
132 }
133
134 this.matrixElements = v;
135 }
136
137 return this.matrixElements;
138 }
139 }
140
144 public int Rows => this.rows;
145
149 public int Columns => this.columns;
150
152 public override string ToString()
153 {
154 Complex[,] v = this.Values;
155 StringBuilder sb = null;
156 bool First;
157 int x, y;
158
159 for (y = 0; y < this.rows; y++)
160 {
161 if (sb is null)
162 sb = new StringBuilder("[[");
163 else
164 sb.Append(",\r\n [");
165
166 First = true;
167 for (x = 0; x < this.columns; x++)
168 {
169 if (First)
170 First = false;
171 else
172 sb.Append(", ");
173
174 sb.Append(Expression.ToString(v[y, x]));
175 }
176
177 sb.Append(']');
178 }
179
180 if (sb is null)
181 sb = new StringBuilder("[[]]");
182 else
183 sb.Append(']');
184
185 return sb.ToString();
186 }
187
191 public override IRing AssociatedRing
192 {
193 get
194 {
195 if (this.associatedMatrixSpace is null)
196 this.associatedMatrixSpace = new ComplexMatrices(this.rows, this.columns);
197
198 return this.associatedMatrixSpace;
199 }
200 }
201
202 private ComplexMatrices associatedMatrixSpace = null;
203
207 public override object AssociatedObjectValue => this;
208
215 {
216 Complex[,] v;
217 int x, y, z;
218
219 if (Element.AssociatedObjectValue is Complex n)
220 {
221 Complex[,] Values = this.Values;
222
223 v = new Complex[this.rows, this.columns];
224
225 for (y = 0; y < this.rows; y++)
226 {
227 for (x = 0; x < this.columns; x++)
228 v[y, x] = n * Values[y, x];
229 }
230
231 return new ComplexMatrix(v);
232 }
233 else if (Element is ComplexMatrix Matrix)
234 {
235 if (Matrix.columns != this.rows)
236 return null;
237
238 Complex[,] Values = this.Values;
239 Complex[,] Values2 = Matrix.Values;
240
241 v = new Complex[Matrix.rows, this.columns];
242 for (y = 0; y < Matrix.rows; y++)
243 {
244 for (x = 0; x < this.columns; x++)
245 {
246 n = 0;
247
248 for (z = 0; z < this.rows; z++)
249 n += Values2[y, z] * Values[z, x];
250
251 v[y, x] = n;
252 }
253 }
254
255 return new ComplexMatrix(v);
256 }
257 else if (Element is IMatrix)
258 return new ObjectMatrix(this.MatrixElements).MultiplyLeft(Element);
259 else
260 return null;
261 }
262
269 {
270 Complex[,] v;
271 int x, y, z;
272
273 if (Element.AssociatedObjectValue is Complex n)
274 {
275 Complex[,] Values = this.Values;
276
277 v = new Complex[this.rows, this.columns];
278
279 for (y = 0; y < this.rows; y++)
280 {
281 for (x = 0; x < this.columns; x++)
282 v[y, x] = n * Values[y, x];
283 }
284
285 return new ComplexMatrix(v);
286 }
287 else if (Element is ComplexMatrix Matrix)
288 {
289 if (this.columns != Matrix.rows)
290 return null;
291
292 Complex[,] Values = this.Values;
293 Complex[,] Values2 = Matrix.Values;
294
295 v = new Complex[this.rows, Matrix.columns];
296 for (y = 0; y < this.rows; y++)
297 {
298 for (x = 0; x < Matrix.columns; x++)
299 {
300 n = 0;
301
302 for (z = 0; z < this.columns; z++)
303 n += Values[y, z] * Values2[z, x];
304
305 v[y, x] = n;
306 }
307 }
308
309 return new ComplexMatrix(v);
310 }
311 else if (Element is IMatrix)
312 return new ObjectMatrix(this.MatrixElements).MultiplyRight(Element);
313 else
314 return null;
315 }
316
321 public override IRingElement Invert()
322 {
323 if (this.rows != this.columns)
324 return null;
325
326 Complex[,] Values = this.Values;
327 int c2 = this.columns << 1;
328 Complex[,] v = new Complex[this.rows, c2];
329 int x, y;
330
331 for (y = 0; y < this.rows; y++)
332 {
333 for (x = 0; x < this.columns; x++)
334 {
335 v[y, x] = Values[y, x];
336 v[y, x + this.columns] = (x == y ? 1 : 0);
337 }
338 }
339
340 if (Reduce(v, true, true, out _) < 0)
341 return null;
342
343 Complex[,] v2 = new Complex[this.rows, this.columns];
344
345 for (y = 0; y < this.rows; y++)
346 {
347 for (x = 0; x < this.columns; x++)
348 v2[y, x] = v[y, x + this.columns];
349 }
350
351 return new ComplexMatrix(v2);
352 }
353
365 public IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
366 {
367 Complex[,] M = (Complex[,])this.Values.Clone();
368 Rank = Reduce(M, Eliminate, BreakIfZero, out Complex c);
369 Factor = new ComplexNumber(c);
370 return new ComplexMatrix(M);
371 }
372
384 public static int Reduce(Complex[,] Matrix, bool Eliminate, bool BreakIfZero,
385 out Complex Factor)
386 {
387 int x, y, u, z;
388 int Rows = Matrix.GetLength(0);
389 int Columns = Matrix.GetLength(1);
390 int MinCount = Math.Min(Rows, Columns);
391 double a, b;
392 Complex w;
393 int Rank = 0;
394
395 Factor = 1;
396
397 for (x = 0; x < MinCount; x++)
398 {
399 a = Matrix[x, x].Magnitude;
400 z = x;
401 for (y = x + 1; y < Rows; y++)
402 {
403 b = Matrix[y, x].Magnitude;
404 if (b > a)
405 {
406 a = b;
407 z = y;
408 }
409 }
410
411 if (z != x)
412 {
413 for (u = x; u < Columns; u++)
414 {
415 w = Matrix[x, u];
416 Matrix[x, u] = Matrix[z, u];
417 Matrix[z, u] = w;
418 }
419
420 Factor = -Factor;
421 }
422
423 w = Matrix[x, x];
424 if (w == 0)
425 {
426 if (BreakIfZero)
427 return -1;
428 }
429 else
430 {
431 Rank++;
432
433 if (w != 1)
434 {
435 for (u = x; u < Columns; u++)
436 Matrix[x, u] /= w;
437
438 Factor *= w;
439 }
440
441 for (y = Eliminate ? 0 : x + 1; y < Rows; y++)
442 {
443 if (y != x && (w = Matrix[y, x]) != 0)
444 {
445 for (u = x; u < Columns; u++)
446 Matrix[y, u] -= w * Matrix[x, u];
447 }
448 }
449 }
450 }
451
452 return Rank;
453 }
454
461 {
462 Complex[,] v;
463 int x, y;
464
465 if (Element.AssociatedObjectValue is Complex n)
466 {
467 Complex[,] Values = this.Values;
468
469 v = new Complex[this.rows, this.columns];
470
471 for (y = 0; y < this.rows; y++)
472 {
473 for (x = 0; x < this.columns; x++)
474 v[y, x] = n + Values[y, x];
475 }
476
477 return new ComplexMatrix(v);
478 }
479 else if (Element is ComplexMatrix Matrix)
480 {
481 if (this.columns != Matrix.columns || this.rows != Matrix.rows)
482 return null;
483
484 Complex[,] Values = this.Values;
485 Complex[,] Values2 = Matrix.Values;
486
487 v = new Complex[this.rows, this.columns];
488 for (y = 0; y < this.rows; y++)
489 {
490 for (x = 0; x < this.columns; x++)
491 v[y, x] = Values[y, x] + Values2[y, x];
492 }
493
494 return new ComplexMatrix(v);
495 }
496 else if (Element is IMatrix)
497 return new ObjectMatrix(this.MatrixElements).Add(Element);
498 else
499 return null;
500 }
501
506 public override IGroupElement Negate()
507 {
508 Complex[,] Values = this.Values;
509 Complex[,] v = new Complex[this.rows, this.columns];
510 int x, y;
511
512 for (y = 0; y < this.rows; y++)
513 {
514 for (x = 0; x < this.columns; x++)
515 v[y, x] = -Values[y, x];
516 }
517
518 return new ComplexMatrix(v);
519 }
520
526 public override bool Equals(object obj)
527 {
528 if (obj is ComplexMatrix Matrix)
529 {
530 if (this.columns != Matrix.columns || this.rows != Matrix.rows)
531 return false;
532
533 Complex[,] V1 = this.Values;
534 Complex[,] V2 = Matrix.Values;
535 int x, y;
536
537 for (y = 0; y < this.rows; y++)
538 {
539 for (x = 0; x < this.columns; x++)
540 {
541 if (V1[y, x] != V2[y, x])
542 return false;
543 }
544 }
545
546 return true;
547 }
548 else if (obj is IMatrix)
549 return new ObjectMatrix(this.MatrixElements).Equals(obj);
550 else
551 return false;
552 }
553
558 public override int GetHashCode()
559 {
560 Complex[,] Values = this.Values;
561 int Result = 0;
562 int x, y;
563
564 for (y = 0; y < this.rows; y++)
565 {
566 for (x = 0; x < this.columns; x++)
567 Result ^= Values[y, x].GetHashCode();
568 }
569
570 return Result;
571 }
572
576 public override bool IsScalar => false;
577
581 public override ICollection<IElement> ChildElements => this.Elements;
582
589 public override IElement Encapsulate(ICollection<IElement> Elements, ScriptNode Node)
590 {
591 return MatrixDefinition.Encapsulate(Elements, this.rows, this.columns, Node);
592 }
593
598 {
599 get
600 {
601 if (this.zero is null)
602 this.zero = new ComplexMatrix(new Complex[this.rows, this.columns]);
603
604 return this.zero;
605 }
606 }
607
608 private ComplexMatrix zero = null;
609
613 public int Dimension => this.rows;
614
618 public ICollection<IElement> VectorElements
619 {
620 get
621 {
622 if (!(this.rowVectors is null))
623 return this.rowVectors;
624
625 Complex[,] v = this.Values;
626 LinkedList<IElement> Rows = new LinkedList<IElement>();
627 int x, y;
628 Complex[] r;
629
630 for (y = 0; y < this.rows; y++)
631 {
632 r = new Complex[this.columns];
633
634 for (x = 0; x < this.columns; x++)
635 r[x] = v[y, x];
636
637 Rows.AddLast(new ComplexVector(r));
638 }
639
640 this.rowVectors = Rows;
641 return Rows;
642 }
643 }
644
645 private LinkedList<IElement> rowVectors = null;
646
652 {
653 Complex[,] v = new Complex[this.columns, this.rows];
654 Complex[,] Values = this.Values;
655 int x, y;
656
657 for (y = 0; y < this.rows; y++)
658 {
659 for (x = 0; x < this.columns; x++)
660 v[x, y] = Values[y, x];
661 }
662
663 return new ComplexMatrix(v);
664 }
665
671 {
672 Complex[,] v = new Complex[this.columns, this.rows];
673 Complex[,] Values = this.Values;
674 int x, y;
675
676 for (y = 0; y < this.rows; y++)
677 {
678 for (x = 0; x < this.columns; x++)
679 v[x, y] = Complex.Conjugate(Values[y, x]);
680 }
681
682 return new ComplexMatrix(v);
683 }
684
690 public IElement GetElement(int Index)
691 {
692 if (Index < 0 || Index >= this.rows)
693 throw new ScriptException("Index out of bounds.");
694
695 Complex[,] M = this.Values;
696 Complex[] V = new Complex[this.columns];
697 int i;
698
699 for (i = 0; i < this.columns; i++)
700 V[i] = M[Index, i];
701
702 return new ComplexVector(V);
703 }
704
710 public void SetElement(int Index, IElement Value)
711 {
712 if (Index < 0 || Index >= this.rows)
713 throw new ScriptException("Index out of bounds.");
714
715 if (!(Value is ComplexVector V))
716 throw new ScriptException("Row vectors in a Complex matrix are required to be Complex vectors.");
717
718 if (V.Dimension != this.columns)
719 throw new ScriptException("Dimension mismatch.");
720
721 Complex[] V2 = V.Values;
722 Complex[,] M = this.Values;
723 this.elements = null;
724
725 int i;
726
727 for (i = 0; i < this.columns; i++)
728 M[Index, i] = V2[i];
729 }
730
737 public IElement GetElement(int Column, int Row)
738 {
739 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
740 throw new ScriptException("Index out of bounds.");
741
742 return new ComplexNumber(this.Values[Row, Column]);
743 }
744
751 public void SetElement(int Column, int Row, IElement Value)
752 {
753 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
754 throw new ScriptException("Index out of bounds.");
755
756 if (!(Value.AssociatedObjectValue is Complex V))
757 throw new ScriptException("Elements in a Complex matrix must be Complex values.");
758
759 Complex[,] M = this.Values;
760 this.elements = null;
761
762 M[Row, Column] = V;
763 }
764
770 public IVector GetRow(int Row)
771 {
772 if (Row < 0 || Row >= this.rows)
773 throw new ScriptException("Index out of bounds.");
774
775 Complex[,] M = this.Values;
776 Complex[] V = new Complex[this.columns];
777 int i;
778
779 for (i = 0; i < this.columns; i++)
780 V[i] = M[Row, i];
781
782 return new ComplexVector(V);
783 }
784
790 public IVector GetColumn(int Column)
791 {
792 if (Column < 0 || Column >= this.columns)
793 throw new ScriptException("Index out of bounds.");
794
795 Complex[,] M = this.Values;
796 Complex[] V = new Complex[this.rows];
797 int i;
798
799 for (i = 0; i < this.rows; i++)
800 V[i] = M[i, Column];
801
802 return new ComplexVector(V);
803 }
804
810 public void SetRow(int Row, IVector Vector)
811 {
812 if (Row < 0 || Row >= this.rows)
813 throw new ScriptException("Index out of bounds.");
814
815 if (Vector.Dimension != this.columns)
816 throw new ScriptException("Vector dimension does not match number of columns");
817
818 if (!(Vector is ComplexVector V))
819 throw new ScriptException("Row vectors in a Complex matrix must be Complex vectors.");
820
821 Complex[] V2 = V.Values;
822 Complex[,] M = this.Values;
823 this.elements = null;
824 int i;
825
826 for (i = 0; i < this.columns; i++)
827 M[Row, i] = V2[i];
828 }
829
835 public void SetColumn(int Column, IVector Vector)
836 {
837 if (Column < 0 || Column >= this.columns)
838 throw new ScriptException("Index out of bounds.");
839
840 if (Vector.Dimension != this.rows)
841 throw new ScriptException("Vector dimension does not match number of rows");
842
843 if (!(Vector is ComplexVector V))
844 throw new ScriptException("Column vectors in a Complex matrix must be Complex vectors.");
845
846 Complex[] V2 = V.Values;
847 Complex[,] M = this.Values;
848 this.elements = null;
849 int i;
850
851 for (i = 0; i < this.rows; i++)
852 M[i, Column] = V2[i];
853 }
854 }
855}
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 Complex-valued matrices.
static int Reduce(Complex[,] Matrix, bool Eliminate, bool BreakIfZero, out Complex Factor)
Reduces a matrix.
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
IElement[,] MatrixElements
Matrix elements
IElement GetElement(int Column, int Row)
Gets an element of the matrix.
IMatrix Transpose()
Returns a transposed matrix.
ICollection< IElement > VectorElements
Vector of row vectors.
void SetRow(int Row, IVector Vector)
Gets a row vector from the matrix.
override IAbelianGroupElement Add(IAbelianGroupElement Element)
Tries to add an element to the current element.
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 IAbelianGroupElement Zero
Returns the zero element of the group.
Complex[,] Values
Matrix element values.
override IRingElement MultiplyRight(IRingElement Element)
Tries to multiply an element to the current element, from the right.
ComplexMatrix(Complex[,] Values)
Complex-valued matrix.
override bool Equals(object obj)
Compares the element to another.
override IRingElement MultiplyLeft(IRingElement Element)
Tries to multiply an element to the current element, from the left.
override IGroupElement Negate()
Negates the element.
override IRingElement Invert()
Inverts the element, if possible.
IMatrix ConjugateTranspose()
Returns a conjugate transposed matrix.
IElement GetElement(int Index)
Gets an element of the vector.
IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
Reduces a matrix.
override bool IsScalar
If the element represents a scalar value.
ICollection< IElement > Elements
Matrix elements.
void SetElement(int Column, int Row, IElement Value)
Sets an element in the matrix.
IVector GetRow(int Row)
Gets a row vector from the matrix.
IVector GetColumn(int Column)
Gets a column vector from the matrix.
int Dimension
Dimension of matrix, if seen as a vector of row vectors.
void SetElement(int Index, IElement Value)
Sets an element in the vector.
override int GetHashCode()
Calculates a hash code of the element.
override object AssociatedObjectValue
Associated object value.
void SetColumn(int Column, IVector Vector)
Gets a column vector from the matrix.
override IRing AssociatedRing
Associated Ring.
ComplexMatrix(int Rows, int Columns, ICollection< IElement > Elements)
Complex-valued vector.
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