1 /* 2 Copyright Kazuya Takahashi 2016-2018. 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 do 88 { 89 BCV!n v; 90 v[k] = true; 91 return v; 92 } 93 } 94 95 unittest 96 { 97 immutable a = BSM!3([ 98 [true, false, true], [true, true, false], [false, false, true] 99 ]); 100 immutable b = BSM!3([ 101 [false, true, true], [true, false, false], [false, false, true] 102 ]); 103 immutable c = BSM!3([ 104 [false, true, true], [true, true, true], [false, false, true] 105 ]); 106 107 assert(a * b == c); 108 } 109 110 unittest 111 { 112 immutable a = BSM!3([ 113 [true, false, true], [true, true, false], [false, false, true] 114 ]); 115 immutable b = BCV!3([true, false, false]); 116 immutable c = BCV!3([true, true, false]); 117 118 assert(a * b == c); 119 } 120 121 unittest 122 { 123 immutable a = BCV!3([false, true, false]); 124 125 assert(BCV!3.e(1) == a); 126 } 127 128 import std.traits : isInstanceOf; 129 130 auto transpose(M)(in M a) pure if (isInstanceOf!(BSM, M)) 131 { 132 import std.traits : TemplateArgsOf; 133 134 BSM!(TemplateArgsOf!M) ta; 135 foreach (i, row; a) 136 { 137 foreach (j, e; row) 138 { 139 ta[j][i] = e; 140 } 141 } 142 return ta; 143 } 144 145 unittest 146 { 147 immutable a = BSM!3([ 148 [false, true, false], [false, true, true], [true, false, false] 149 ]); 150 immutable b = BSM!3([ 151 [false, false, true], [true, true, false], [false, true, false] 152 ]); 153 154 assert(transpose(a) == b); 155 } 156 157 auto isBijective(M)(in M a) pure if (isInstanceOf!(BSM, M)) 158 { 159 foreach (i, ref row; a) 160 { 161 size_t k; 162 163 foreach (j, e; row) 164 { 165 if (e) 166 { 167 if (++k == 2) 168 { 169 return false; 170 } 171 else 172 { 173 foreach (ref row2; a[i + 1 .. $]) 174 { 175 if (row2[j]) 176 { 177 return false; 178 } 179 } 180 } 181 } 182 } 183 184 if (k == 0) 185 { 186 return false; 187 } 188 } 189 190 return true; 191 } 192 193 unittest 194 { 195 immutable a = BSM!3([ 196 [true, false, false], [false, false, true], [false, true, false] 197 ]); 198 immutable b = BSM!3([ 199 [false, false, true], [false, false, true], [true, true, false] 200 ]); 201 immutable c = BSM!3([ 202 [true, false, true], [false, true, false], [false, false, false] 203 ]); 204 immutable d = BSM!3([ 205 [false, false, false], [false, true, false], [false, false, false] 206 ]); 207 208 assert(isBijective(a)); 209 assert(!isBijective(b)); 210 assert(!isBijective(c)); 211 assert(!isBijective(d)); 212 } 213 214 auto isIrreflexive(M)(in M a) pure if (isInstanceOf!(BSM, M)) 215 { 216 foreach (i, ref row; a) 217 { 218 if (row[i]) 219 { 220 return false; 221 } 222 } 223 224 return true; 225 } 226 227 unittest 228 { 229 immutable a = BSM!3([ 230 [false, false, true], [false, false, true], [true, true, false] 231 ]); 232 immutable b = BSM!3([ 233 [true, false, true], [false, false, true], [true, false, false] 234 ]); 235 236 assert(isIrreflexive(a)); 237 assert(!isIrreflexive(b)); 238 } 239 240 auto isSymmetric(M)(in M a) pure if (isInstanceOf!(BSM, M)) 241 { 242 foreach (i, ref row; a[0 .. $ - 1]) 243 { 244 foreach (j, e; row[i + 1 .. $]) 245 { 246 if (a[i + j + 1][i] != e) 247 { 248 return false; 249 } 250 } 251 } 252 253 return true; 254 } 255 256 unittest 257 { 258 immutable a = BSM!3([ 259 [true, false, true], [false, false, true], [true, true, false] 260 ]); 261 immutable b = BSM!3([ 262 [true, false, true], [false, false, true], [true, false, false] 263 ]); 264 265 assert(isSymmetric(a)); 266 assert(!isSymmetric(b)); 267 }