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 opBinary(string op)(in auto ref BSM!n matrix) const pure 16 { 17 static if (op == "*") 18 { 19 BSM!n r; 20 21 foreach (i, ref row; s_mat) 22 { 23 foreach (j, e; row) 24 { 25 if (e) 26 { 27 r[i][] |= matrix[j][]; 28 } 29 } 30 } 31 32 return r; 33 } 34 else 35 { 36 static assert(0, `Operator '` ~ op ~ `' is not implemented.`); 37 } 38 } 39 40 auto opBinary(string op)(in auto ref BCV!n vector) const pure 41 { 42 static if (op == "*") 43 { 44 BCV!n r; 45 46 foreach (i, ref row; s_mat) 47 { 48 foreach (j, e; row) 49 { 50 if (e && vector[j]) 51 { 52 r[i] = true; 53 break; 54 } 55 } 56 } 57 58 return r; 59 } 60 else 61 { 62 static assert(0, `Operator '` ~ op ~ `' is not implemented.`); 63 } 64 } 65 66 static enum I = { 67 BSM!n id; 68 foreach (i, ref row; id) 69 { 70 row[i] = true; 71 } 72 return id; 73 }(); 74 } 75 76 // boolean column vector 77 struct BCV(size_t n) if (n > 0) 78 { 79 bool[n] c_vec; 80 alias c_vec this; 81 82 static auto e(size_t k) pure 83 in 84 { 85 assert(k < n); 86 } 87 body 88 { 89 BCV!n v; 90 v[k] = true; 91 return v; 92 } 93 } 94 95 unittest 96 { 97 immutable a = BSM!3([[true, false, true], [true, true, false], 98 [false, false, true]]); 99 immutable b = BSM!3([[false, true, true], [true, false, false], 100 [false, false, true]]); 101 immutable c = BSM!3([[false, true, true], [true, true, true], 102 [false, false, true]]); 103 104 assert(a * b == c); 105 } 106 107 unittest 108 { 109 immutable a = BSM!3([[true, false, true], [true, true, false], 110 [false, false, true]]); 111 immutable b = BCV!3([true, false, false]); 112 immutable c = BCV!3([true, true, false]); 113 114 assert(a * b == c); 115 } 116 117 import std.traits : isInstanceOf; 118 119 auto transpose(M)(in M a) pure if (isInstanceOf!(BSM, M)) 120 { 121 import std.traits : TemplateArgsOf; 122 123 BSM!(TemplateArgsOf!M) ta; 124 foreach (i, row; a) 125 { 126 foreach (j, e; row) 127 { 128 ta[j][i] = e; 129 } 130 } 131 return ta; 132 } 133 134 auto isBijective(M)(in M a) pure if (isInstanceOf!(BSM, M)) 135 { 136 foreach (i, ref row; a) 137 { 138 size_t k; 139 140 foreach (e; row) 141 { 142 if (e && ++k == 2) 143 { 144 return false; 145 } 146 } 147 148 if (k == 0) 149 { 150 return false; 151 } 152 } 153 154 return true; 155 } 156 157 auto isIrreflexive(M)(in M a) pure if (isInstanceOf!(BSM, M)) 158 { 159 foreach (i, row; a) 160 { 161 if (row[i]) 162 { 163 return false; 164 } 165 } 166 167 return true; 168 } 169 170 auto isSymmetric(M)(in M a) pure if (isInstanceOf!(BSM, M)) 171 { 172 foreach (i, row; a[0 .. $ - 1]) 173 { 174 foreach (j, e; row[1 .. $]) 175 { 176 if (row[j + 1] != e) 177 { 178 return false; 179 } 180 } 181 } 182 183 return true; 184 } 185 186 auto lowerRotator(size_t n)(size_t shift) @property pure 187 { 188 BSM!n r; 189 if (shift % n == 0) 190 { 191 r = BSM!n.I; 192 } 193 else 194 { 195 foreach (i, ref e; r) 196 { 197 e[(i + n - (shift % n)) % n] = true; 198 } 199 } 200 return r; 201 } 202 203 auto upperRotator(size_t n)(size_t shift) @property pure 204 { 205 BSM!n r; 206 if (shift % n == 0) 207 { 208 r = BSM!n.I; 209 } 210 else 211 { 212 foreach (i, ref e; r) 213 { 214 e[(i + (shift % n)) % n] = true; 215 } 216 } 217 return r; 218 } 219 220 auto permutation(size_t N)(in size_t[] substitution) 221 in 222 { 223 import std.algorithm.comparison : isPermutation; 224 import std.range : iota; 225 226 assert(N.iota.isPermutation(substitution)); 227 } 228 body 229 { 230 BSM!N p; 231 foreach (i, s; substitution) 232 { 233 p[s][i] = true; 234 } 235 return p; 236 }