1 /*
2 Copyright electrolysis 2016.
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 */
6 
7 module boolean_matrix;
8 
9 // boolean square matrix
10 struct BSM(size_t n) if (n > 0)
11 {
12     bool[n][n] s_mat;
13     alias s_mat this;
14 
15     auto opMul()(in auto ref BSM!n matrix) const pure
16     {
17         import std.range : iota, transversal, zip;
18         import std.algorithm.searching : canFind;
19         import std.algorithm.mutation : copy;
20         import std.algorithm.iteration : map;
21 
22         BSM!n r;
23         foreach (i, ref row; r)
24         {
25             n.iota.map!(j => zip(s_mat[i][], matrix[].transversal(j))
26                 .canFind!"a[0]&&a[1]").copy(row[]);
27         }
28 
29         return r;
30     }
31 
32     auto opMul()(in auto ref BCV!n vector) const pure
33     {
34         import std.range : zip;
35         import std.algorithm.searching : canFind;
36         import std.algorithm.mutation : copy;
37         import std.algorithm.iteration : map;
38 
39         BCV!n r;
40         s_mat[].map!(row => zip(row[], vector[]).canFind!"a[0]&&a[1]")
41             .copy(r[]);
42 
43         return r;
44     }
45 }
46 
47 // boolean column vector
48 struct BCV(size_t n) if (n > 0)
49 {
50     bool[n] c_vec;
51     alias c_vec this;
52 }
53 
54 unittest
55 {
56     immutable a = BSM!3([[true, false, true], [true, true, false],
57         [false, false, true]]);
58     immutable b = BSM!3([[false, true, true], [true, false, false],
59         [false, false, true]]);
60     immutable c = BSM!3([[false, true, true], [true, true, true],
61         [false, false, true]]);
62 
63     assert(a * b == c);
64 }
65 
66 unittest
67 {
68     immutable a = BSM!3([[true, false, true], [true, true, false],
69         [false, false, true]]);
70     immutable b = BCV!3([true, false, false]);
71     immutable c = BCV!3([true, true, false]);
72 
73     assert(a * b == c);
74 }
75 
76 enum Identity(size_t n) = {
77     BSM!n id;
78     foreach (i; 0 .. n)
79     {
80         id[i][i] = true;
81     }
82     return id;
83 }();
84 
85 import std.traits : TemplateArgsOf, TemplateOf;
86 
87 auto transpose(M)(in M a) pure if (__traits(isSame, TemplateOf!M, BSM))
88 {
89     BSM!(TemplateArgsOf!M) ta;
90     foreach (i, row; a)
91     {
92         foreach (j, e; row)
93         {
94             ta[j][i] = e;
95         }
96     }
97     return ta;
98 }
99 
100 auto lowerRotator(size_t n)(size_t shift) @property pure
101 {
102     BSM!n r;
103     if (shift % n == 0)
104     {
105         r = Identity!n;
106     }
107     else
108     {
109         foreach (i, ref e; r)
110         {
111             e[(i + n - (shift % n)) % n] = true;
112         }
113     }
114     return r;
115 }
116 
117 auto upperRotator(size_t n)(size_t shift) @property pure
118 {
119     BSM!n r;
120     if (shift % n == 0)
121     {
122         r = Identity!n;
123     }
124     else
125     {
126         foreach (i, ref e; r)
127         {
128             e[(i + (shift % n)) % n] = true;
129         }
130     }
131     return r;
132 }
133 
134 auto permutation(size_t N)(in size_t[] substitution)
135 in
136 {
137     import std.algorithm.comparison : isPermutation;
138     import std.range : iota;
139 
140     assert(N.iota.isPermutation(substitution));
141 }
142 body
143 {
144     BSM!N p;
145     foreach (i, s; substitution)
146     {
147         p[s][i] = true;
148     }
149     return p;
150 }