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