Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BooleanMatrix.cs
2using System.Text;
10
12{
16 public sealed class BooleanMatrix : RingElement, IMatrix
17 {
18 private bool[,] values;
19 private IElement[,] matrixElements;
20 private ICollection<IElement> elements;
21 private readonly int rows;
22 private readonly int columns;
23
28 public BooleanMatrix(bool[,] 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 BooleanMatrix(int Rows, int Columns, ICollection<IElement> Elements)
44 {
45 this.values = null;
46 this.elements = Elements;
47 this.matrixElements = null;
48 this.rows = Rows;
49 this.columns = Columns;
50 }
51
55 public bool[,] Values
56 {
57 get
58 {
59 if (this.values is null)
60 {
61 bool[,] v = new bool[this.rows, this.columns];
62 int x = 0;
63 int y = 0;
64
65 if (this.elements is ChunkedList<IElement> Values)
66 {
67 ChunkNode<IElement> Loop = Values.FirstChunk;
68 int i, c;
69
70 while (!(Loop is null))
71 {
72 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
73 {
74 if (!(Loop[i].AssociatedObjectValue is bool b))
75 b = false;
76
77 v[y, x++] = b;
78 if (x >= this.columns)
79 {
80 y++;
81 x = 0;
82 }
83 }
84
85 Loop = Loop.Next;
86 }
87 }
88 else
89 {
90 foreach (IElement Element in this.elements)
91 {
92 if (!(Element.AssociatedObjectValue is bool b))
93 b = false;
94
95 v[y, x++] = b;
96 if (x >= this.columns)
97 {
98 y++;
99 x = 0;
100 }
101 }
102 }
103
104 this.values = v;
105 }
106
107 return this.values;
108 }
109 }
110
114 public ICollection<IElement> Elements
115 {
116 get
117 {
118 if (this.elements is null)
119 {
120 int x, y, i = 0;
121 IElement[] v = new IElement[this.rows * this.columns];
122
123 for (y = 0; y < this.rows; y++)
124 {
125 for (x = 0; x < this.columns; x++)
126 v[i++] = new BooleanValue(this.values[y, x]);
127 }
128
129 this.elements = v;
130 }
131
132 return this.elements;
133 }
134 }
135
140 {
141 get
142 {
143 if (this.matrixElements is null)
144 {
145 IElement[,] v = new IElement[this.rows, this.columns];
146 int x = 0;
147 int y = 0;
148
149 foreach (IElement E in this.Elements)
150 {
151 v[y, x++] = E;
152 if (x >= this.columns)
153 {
154 y++;
155 x = 0;
156 }
157 }
158
159 this.matrixElements = v;
160 }
161
162 return this.matrixElements;
163 }
164 }
165
169 public int Rows => this.rows;
170
174 public int Columns => this.columns;
175
177 public override string ToString()
178 {
179 bool[,] v = this.Values;
180 StringBuilder sb = null;
181 bool First;
182 int x, y;
183
184 for (y = 0; y < this.rows; y++)
185 {
186 if (sb is null)
187 sb = new StringBuilder("[[");
188 else
189 sb.Append(",\r\n [");
190
191 First = true;
192 for (x = 0; x < this.columns; x++)
193 {
194 if (First)
195 First = false;
196 else
197 sb.Append(", ");
198
199 sb.Append(Expression.ToString(v[y, x]));
200 }
201
202 sb.Append(']');
203 }
204
205 if (sb is null)
206 sb = new StringBuilder("[[]]");
207 else
208 sb.Append(']');
209
210 return sb.ToString();
211 }
212
216 public override IRing AssociatedRing
217 {
218 get
219 {
220 if (this.associatedMatrixSpace is null)
221 this.associatedMatrixSpace = new BooleanMatrices(this.rows, this.columns);
222
223 return this.associatedMatrixSpace;
224 }
225 }
226
227 private BooleanMatrices associatedMatrixSpace = null;
228
232 public override object AssociatedObjectValue => this;
233
240 {
241 return this.ToDoubleMatrix().MultiplyLeft(Element);
242 }
243
250 {
251 return this.ToDoubleMatrix().MultiplyRight(Element);
252 }
253
258 public override IRingElement Invert()
259 {
260 if (this.rows != this.columns)
261 return null;
262
263 return this.ToDoubleMatrix().Invert();
264 }
265
277 public IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
278 {
279 return this.ToDoubleMatrix().Reduce(Eliminate, BreakIfZero, out Rank, out Factor);
280 }
281
287 {
288 bool[,] Values = this.Values;
289 double[,] v = new double[this.rows, this.columns];
290 int x, y;
291
292 for (y = 0; y < this.rows; y++)
293 {
294 for (x = 0; x < this.columns; x++)
295 v[y, x] = Values[y, x] ? 1 : 0;
296 }
297
298 return new DoubleMatrix(v);
299 }
300
307 {
308 return this.ToDoubleMatrix().Add(Element);
309 }
310
315 public override IGroupElement Negate()
316 {
317 return this;
318 }
319
325 public override bool Equals(object obj)
326 {
327 if (!(obj is BooleanMatrix Matrix))
328 return false;
329
330 if (this.columns != Matrix.columns || this.rows != Matrix.rows)
331 return false;
332
333 bool[,] V1 = this.Values;
334 bool[,] V2 = Matrix.Values;
335 int x, y;
336
337 for (y = 0; y < this.rows; y++)
338 {
339 for (x = 0; x < this.columns; x++)
340 {
341 if (V1[y, x] != V2[y, x])
342 return false;
343 }
344 }
345
346 return true;
347 }
348
353 public override int GetHashCode()
354 {
355 int Result = 0;
356 int x, y;
357 int i = 0;
358
359 for (y = 0; y < this.rows; y++)
360 {
361 for (x = 0; x < this.columns; x++)
362 {
363 if (this.values[y, x])
364 Result ^= (1 << i);
365
366 i++;
367 i &= 31;
368 }
369 }
370
371 return Result;
372 }
373
377 public override bool IsScalar => false;
378
382 public override ICollection<IElement> ChildElements => this.Elements;
383
391 {
392 return MatrixDefinition.Encapsulate(Elements, this.rows, this.columns, Node);
393 }
394
401 public override IElement Encapsulate(ICollection<IElement> Elements, ScriptNode Node)
402 {
403 return MatrixDefinition.Encapsulate(Elements, this.rows, this.columns, Node);
404 }
405
410 {
411 get
412 {
413 if (this.zero is null)
414 this.zero = new BooleanMatrix(new bool[this.rows, this.columns]);
415
416 return this.zero;
417 }
418 }
419
420 private BooleanMatrix zero = null;
421
425 public int Dimension => this.rows;
426
430 public ICollection<IElement> VectorElements
431 {
432 get
433 {
434 if (!(this.rowVectors is null))
435 return this.rowVectors;
436
437 bool[,] v = this.Values;
439 int x, y;
440 bool[] r;
441
442 for (y = 0; y < this.rows; y++)
443 {
444 r = new bool[this.columns];
445
446 for (x = 0; x < this.columns; x++)
447 r[x] = v[y, x];
448
449 Rows.Add(new BooleanVector(r));
450 }
451
452 this.rowVectors = Rows;
453 return Rows;
454 }
455 }
456
457 private ChunkedList<IElement> rowVectors = null;
458
464 {
465 bool[,] v = new bool[this.columns, this.rows];
466 bool[,] Values = this.Values;
467 int x, y;
468
469 for (y = 0; y < this.rows; y++)
470 {
471 for (x = 0; x < this.columns; x++)
472 v[x, y] = Values[y, x];
473 }
474
475 return new BooleanMatrix(v);
476 }
477
483 {
484 return this.Transpose();
485 }
486
492 public IElement GetElement(int Index)
493 {
494 if (Index < 0 || Index >= this.rows)
495 throw new ScriptException("Index out of bounds.");
496
497 bool[,] M = this.Values;
498 bool[] V = new bool[this.columns];
499 int i;
500
501 for (i = 0; i < this.columns; i++)
502 V[i] = M[Index, i];
503
504 return new BooleanVector(V);
505 }
506
512 public void SetElement(int Index, IElement Value)
513 {
514 if (Index < 0 || Index >= this.rows)
515 throw new ScriptException("Index out of bounds.");
516
517 if (!(Value is BooleanVector V))
518 throw new ScriptException("Row vectors in a boolean matrix are required to be boolean vectors.");
519
520 if (V.Dimension != this.columns)
521 throw new ScriptException("Dimension mismatch.");
522
523 bool[] V2 = V.Values;
524 bool[,] M = this.Values;
525 this.elements = null;
526
527 int i;
528
529 for (i = 0; i < this.columns; i++)
530 M[Index, i] = V2[i];
531 }
532
539 public IElement GetElement(int Column, int Row)
540 {
541 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
542 throw new ScriptException("Index out of bounds.");
543
544 return new BooleanValue(this.Values[Row, Column]);
545 }
546
553 public void SetElement(int Column, int Row, IElement Value)
554 {
555 if (Column < 0 || Column >= this.columns || Row < 0 || Row >= this.rows)
556 throw new ScriptException("Index out of bounds.");
557
558 if (!(Value.AssociatedObjectValue is bool V))
559 throw new ScriptException("Elements in a boolean matrix must be boolean values.");
560
561 bool[,] M = this.Values;
562 this.elements = null;
563
564 M[Row, Column] = V;
565 }
566
572 public IVector GetRow(int Row)
573 {
574 if (Row < 0 || Row >= this.rows)
575 throw new ScriptException("Index out of bounds.");
576
577 bool[,] M = this.Values;
578 bool[] V = new bool[this.columns];
579 int i;
580
581 for (i = 0; i < this.columns; i++)
582 V[i] = M[Row, i];
583
584 return new BooleanVector(V);
585 }
586
592 public IVector GetColumn(int Column)
593 {
594 if (Column < 0 || Column >= this.columns)
595 throw new ScriptException("Index out of bounds.");
596
597 bool[,] M = this.Values;
598 bool[] V = new bool[this.rows];
599 int i;
600
601 for (i = 0; i < this.rows; i++)
602 V[i] = M[i, Column];
603
604 return new BooleanVector(V);
605 }
606
612 public void SetRow(int Row, IVector Vector)
613 {
614 if (Row < 0 || Row >= this.rows)
615 throw new ScriptException("Index out of bounds.");
616
617 if (Vector.Dimension != this.columns)
618 throw new ScriptException("Vector dimension does not match number of columns");
619
620 if (!(Vector is BooleanVector V))
621 throw new ScriptException("Row vectors in a boolean matrix must be boolean vectors.");
622
623 bool[] V2 = V.Values;
624 bool[,] M = this.Values;
625 this.elements = null;
626 int i;
627
628 for (i = 0; i < this.columns; i++)
629 M[Row, i] = V2[i];
630 }
631
637 public void SetColumn(int Column, IVector Vector)
638 {
639 if (Column < 0 || Column >= this.columns)
640 throw new ScriptException("Index out of bounds.");
641
642 if (Vector.Dimension != this.rows)
643 throw new ScriptException("Vector dimension does not match number of rows");
644
645 if (!(Vector is BooleanVector V))
646 throw new ScriptException("Column vectors in a boolean matrix must be boolean vectors.");
647
648 bool[] V2 = V.Values;
649 bool[,] M = this.Values;
650 this.elements = null;
651 int i;
652
653 for (i = 0; i < this.rows; i++)
654 M[i, Column] = V2[i];
655 }
656
665 public bool TryFind(IElement Element, out int Column, out int Row)
666 {
667 return this.TryFind(Element, 0, 0, out Column, out Row);
668 }
669
680 public bool TryFind(IElement Element, int FromColumn, int FromRow, out int Column, out int Row)
681 {
682 if (Element is BooleanValue B)
683 return this.TryFind(B.Value, FromColumn, FromRow, out Column, out Row);
684 else
685 {
686 Column = -1;
687 Row = -1;
688 return false;
689 }
690 }
691
702 public bool TryFind(bool Element, int FromColumn, int FromRow, out int Column, out int Row)
703 {
704 bool[,] Values = this.Values;
705
706 while (FromRow < this.rows)
707 {
708 while (FromColumn < this.columns)
709 {
710 if (Values[FromRow, FromColumn] == Element)
711 {
712 Column = FromColumn;
713 Row = FromRow;
714
715 return true;
716 }
717
718 FromColumn++;
719 }
720
721 FromColumn = 0;
722 FromRow++;
723 }
724
725 Column = -1;
726 Row = -1;
727
728 return false;
729 }
730
739 public bool TryFindLast(IElement Element, out int Column, out int Row)
740 {
741 return this.TryFindLast(Element, this.columns - 1, this.rows - 1, out Column, out Row);
742 }
743
754 public bool TryFindLast(IElement Element, int FromColumn, int FromRow, out int Column, out int Row)
755 {
756 if (Element is BooleanValue B)
757 return this.TryFindLast(B.Value, FromColumn, FromRow, out Column, out Row);
758 else
759 {
760 Column = -1;
761 Row = -1;
762 return false;
763 }
764 }
765
776 public bool TryFindLast(bool Element, int FromColumn, int FromRow, out int Column, out int Row)
777 {
778 bool[,] Values = this.Values;
779
780 while (FromRow >= 0)
781 {
782 while (FromColumn >= 0)
783 {
784 if (Values[FromRow, FromColumn] == Element)
785 {
786 Column = FromColumn;
787 Row = FromRow;
788
789 return true;
790 }
791
792 FromColumn--;
793 }
794
795 FromColumn = this.columns - 1;
796 FromRow--;
797 }
798
799 Column = -1;
800 Row = -1;
801
802 return false;
803 }
804 }
805}
Node referencing a chunk in a ChunkedList<T>
Definition: ChunkNode.cs:11
ChunkNode< T > Next
Next chunk
Definition: ChunkNode.cs:26
int Pos
Index after the last element in chunk.
Definition: ChunkNode.cs:51
int Start
Index of first element in chunk.
Definition: ChunkNode.cs:46
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
Base class for all types of elements.
Definition: Element.cs:14
abstract object AssociatedObjectValue
Associated object value.
Definition: Element.cs:43
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:41
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4760
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
Boolean-valued number.
Definition: BooleanValue.cs:12
Pseudo-ring of Boolean-valued matrices.
IVector GetColumn(int Column)
Gets a column vector from the matrix.
void SetRow(int Row, IVector Vector)
Gets a row vector from the matrix.
override IRingElement Invert()
Inverts the element, if possible.
IMatrix ConjugateTranspose()
Returns a conjugate transposed matrix.
bool TryFind(bool Element, int FromColumn, int FromRow, out int Column, out int Row)
Tries to find an element in the matrix, continuing search from a given position in the matrix....
int Dimension
Dimension of matrix, if seen as a vector of row vectors.
override IRingElement MultiplyLeft(IRingElement Element)
Tries to multiply an element to the current element, from the left.
override IElement Encapsulate(ICollection< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
void SetElement(int Column, int Row, IElement Value)
Sets an element in the matrix.
override IAbelianGroupElement Zero
Returns the zero element of the group.
ICollection< IElement > VectorElements
Vector of row vectors.
IElement[,] MatrixElements
Matrix elements
override int GetHashCode()
Calculates a hash code of the element.
IElement GetElement(int Index)
Gets an element of the vector.
override object AssociatedObjectValue
Associated object value.
bool TryFind(IElement Element, out int Column, out int Row)
Tries to find an element in the matrix. Search is done, left to right, top to bottom.
override bool Equals(object obj)
Compares the element to another.
void SetElement(int Index, IElement Value)
Sets an element in the vector.
bool TryFind(IElement Element, int FromColumn, int FromRow, out int Column, out int Row)
Tries to find an element in the matrix, continuing search from a given position in the matrix....
BooleanMatrix(bool[,] Values)
Boolean-valued matrix.
bool TryFindLast(IElement Element, int FromColumn, int FromRow, out int Column, out int Row)
Tries to find the last element in the matrix, continuing search from a given position in 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.
ICollection< IElement > Elements
Matrix elements.
bool TryFindLast(IElement Element, out int Column, out int Row)
Tries to find the last element in the matrix. Search is done, right to left, bottom to top.
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
DoubleMatrix ToDoubleMatrix()
Converts matrix to a double-valued matrix.
bool[,] Values
Matrix element values.
override IAbelianGroupElement Add(IAbelianGroupElement Element)
Tries to add an element to the current element.
bool TryFindLast(bool Element, int FromColumn, int FromRow, out int Column, out int Row)
Tries to find the last element in the matrix, continuing search from a given position in the matrix....
override bool IsScalar
If the element represents a scalar value.
IVector GetRow(int Row)
Gets a row vector from the matrix.
override IGroupElement Negate()
Negates the element.
override IRing AssociatedRing
Associated Ring.
BooleanMatrix(int Rows, int Columns, ICollection< IElement > Elements)
Boolean-valued vector.
IElement GetElement(int Column, int Row)
Gets an element of the matrix.
IMatrix Transpose()
Returns a transposed matrix.
override IElement Encapsulate(ChunkedList< 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.
IMatrix Reduce(bool Eliminate, bool BreakIfZero, out int Rank, out ICommutativeRingWithIdentityElement Factor)
Reduces a matrix.
override IRingElement MultiplyLeft(IRingElement Element)
Tries to multiply an element to the current element, from the left.
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.
override IAbelianGroupElement Add(IAbelianGroupElement Element)
Tries to add an element to the current element.
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:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
Basic interface for all types of group elements.
Definition: IGroupElement.cs:9
Basic interface for matrices.
Definition: IMatrix.cs:7
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