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 static enum I = { 47 BSM!n id; 48 foreach (i, ref row; id) 49 { 50 row[i] = true; 51 } 52 return id; 53 }(); 54 } 55 56 // boolean column vector 57 struct BCV(size_t n) if (n > 0) 58 { 59 bool[n] c_vec; 60 alias c_vec this; 61 62 static auto e(size_t k) pure 63 in 64 { 65 assert(k < n); 66 } 67 body 68 { 69 BCV!n v; 70 v[k] = true; 71 return v; 72 } 73 } 74 75 unittest 76 { 77 immutable a = BSM!3([[true, false, true], [true, true, false], 78 [false, false, true]]); 79 immutable b = BSM!3([[false, true, true], [true, false, false], 80 [false, false, true]]); 81 immutable c = BSM!3([[false, true, true], [true, true, true], 82 [false, false, true]]); 83 84 assert(a * b == c); 85 } 86 87 unittest 88 { 89 immutable a = BSM!3([[true, false, true], [true, true, false], 90 [false, false, true]]); 91 immutable b = BCV!3([true, false, false]); 92 immutable c = BCV!3([true, true, false]); 93 94 assert(a * b == c); 95 } 96 97 import std.traits : TemplateArgsOf, TemplateOf; 98 99 auto transpose(M)(in M a) pure if (__traits(isSame, TemplateOf!M, BSM)) 100 { 101 BSM!(TemplateArgsOf!M) ta; 102 foreach (i, row; a) 103 { 104 foreach (j, e; row) 105 { 106 ta[j][i] = e; 107 } 108 } 109 return ta; 110 } 111 112 auto isBijective(M)(in M a) pure if (__traits(isSame, TemplateOf!M, BSM)) 113 { 114 import std.algorithm.searching : all, count; 115 return a[].all!(row => row[].count!"a" == 1); 116 } 117 118 auto isIrreflexive(M)(in M a) pure if (__traits(isSame, TemplateOf!M, BSM)) 119 { 120 foreach (i, row; a) 121 { 122 if (row[i]) 123 { 124 return false; 125 } 126 } 127 128 return true; 129 } 130 131 auto isSymmetric(M)(in M a) pure if (__traits(isSame, TemplateOf!M, BSM)) 132 { 133 foreach (i, row; a[0 .. $-1]) 134 { 135 foreach (j, e; row[1 .. $]) 136 { 137 if (row[j+1] != e) 138 { 139 return false; 140 } 141 } 142 } 143 144 return true; 145 } 146 147 auto lowerRotator(size_t n)(size_t shift) @property pure 148 { 149 BSM!n r; 150 if (shift % n == 0) 151 { 152 r = BSM!n.I; 153 } 154 else 155 { 156 foreach (i, ref e; r) 157 { 158 e[(i + n - (shift % n)) % n] = true; 159 } 160 } 161 return r; 162 } 163 164 auto upperRotator(size_t n)(size_t shift) @property pure 165 { 166 BSM!n r; 167 if (shift % n == 0) 168 { 169 r = BSM!n.I; 170 } 171 else 172 { 173 foreach (i, ref e; r) 174 { 175 e[(i + (shift % n)) % n] = true; 176 } 177 } 178 return r; 179 } 180 181 auto permutation(size_t N)(in size_t[] substitution) 182 in 183 { 184 import std.algorithm.comparison : isPermutation; 185 import std.range : iota; 186 187 assert(N.iota.isPermutation(substitution)); 188 } 189 body 190 { 191 BSM!N p; 192 foreach (i, s; substitution) 193 { 194 p[s][i] = true; 195 } 196 return p; 197 }