├── MANIFEST.in ├── README.md ├── docs └── index.rst ├── examples ├── 2DNoisyXORDemo.py ├── 2DNoisyXORTestData.txt ├── 2DNoisyXORTrainingData.txt ├── BreastCancerDemo.py ├── FashionMNISTDemo2DConvolutionWeightedClauses.py ├── IMDbTextCategorizationDemo.py ├── InterpretabilityDemo.py ├── MNISTDemo.py ├── MNISTDemo2DConvolutionWeightedClauses.py ├── MNISTDemoWeightedClauses.py ├── NoisyXORDemo.py ├── NoisyXORTestData.txt ├── NoisyXORTrainingData.txt └── RegressionDemo.py ├── pyTsetlinMachineParallel ├── ConvolutionalTsetlinMachine.c ├── ConvolutionalTsetlinMachine.h ├── MultiClassConvolutionalTsetlinMachine.c ├── MultiClassConvolutionalTsetlinMachine.h ├── Tools.c ├── Tools.h ├── __init__.py ├── fast_rand.h ├── makefile ├── tm.py └── tools.py └── setup.py /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include pyTsetlinMachineParallel/Tools.h 2 | include pyTsetlinMachineParallel/ConvolutionalTsetlinMachine.h 3 | include pyTsetlinMachineParallel/MultiClassConvolutionalTsetlinMachine.h 4 | include pyTsetlinMachineParallel/fast_rand.h 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyTsetlinMachineParallel 2 | ![License](https://img.shields.io/github/license/microsoft/interpret.svg?style=flat-square) ![Python Version](https://img.shields.io/pypi/pyversions/interpret.svg?style=flat-square) ![Maintenance](https://img.shields.io/maintenance/yes/2023?style=flat-square) 3 | 4 | Multi-threaded implementation of the Tsetlin Machine (https://arxiv.org/abs/1804.01508), Convolutional Tsetlin Machine (https://arxiv.org/abs/1905.09688), Regression Tsetlin Machine (https://arxiv.org/abs/1905.04206, https://royalsocietypublishing.org/doi/full/10.1098/rsta.2019.0165, https://link.springer.com/chapter/10.1007/978-3-030-30244-3_23), and Weighted Tsetlin Machines (https://arxiv.org/abs/1911.12607, https://ieeexplore.ieee.org/document/9316190, https://arxiv.org/abs/2002.01245), with support for continuous features (https://arxiv.org/abs/1905.04199, https://link.springer.com/chapter/10.1007%2F978-3-030-22999-3_49) and multigranular clauses (https://arxiv.org/abs/1909.07310, https://link.springer.com/chapter/10.1007/978-3-030-34885-4_11). 5 | 6 |

7 | 8 |

9 | 10 | ## Contents 11 | 12 | - [Installation](#installation) 13 | - [Documentation](#documentation) 14 | - [Tutorials](#tutorials) 15 | - [Examples](#examples) 16 | - [Multiclass Demo](#multiclass-demo) 17 | - [Interpretability Demo](#interpretability-demo) 18 | - [2D Convolution Demo](#2d-convolution-demo) 19 | - [Continuous Input Demo](#continuous-input-demo) 20 | - [MNIST Demo](#mnist-demo) 21 | - [MNIST Demo w/Weighted Clauses](#mnist-demo-wweighted-clauses) 22 | - [MNIST 2D Convolution Demo w/Weighted Clauses](#mnist-2d-convolution-demo-wweighted-clauses) 23 | - [Fashion MNIST 2D Convolution Demo w/Weighted Clauses](#fashion-mnist-2d-convolution-demo-wweighted-clauses) 24 | - [IMDb Text Categorization Demo](#imdb-text-categorization-demo) 25 | - [Regression Demo](#regression-demo) 26 | - [Further Work](#further-work) 27 | - [Requirements](#requirements) 28 | - [Acknowledgements](#acknowledgements) 29 | - [Tsetlin Machine Papers](#tsetlin-machine-papers) 30 | - [Licence](#licence) 31 | 32 | ## Installation 33 | 34 | ```bash 35 | pip install pyTsetlinMachineParallel 36 | 37 | export OMP_NUM_THREADS=10 38 | ``` 39 | 40 | ## Documentation 41 | 42 | Documentation coming soon at https://pytsetlinmachineparallel.readthedocs.io/en/latest/ 43 | 44 | ## Tutorials 45 | 46 | Convolutional Tsetlin Machine tutorial, https://github.com/cair/convolutional-tsetlin-machine-tutorial 47 | 48 | ## Examples 49 | 50 | ### Multiclass Demo 51 | 52 | #### Code: NoisyXORDemo.py 53 | 54 | ```python 55 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 56 | import numpy as np 57 | 58 | train_data = np.loadtxt("NoisyXORTrainingData.txt") 59 | X_train = train_data[:,0:-1] 60 | Y_train = train_data[:,-1] 61 | 62 | test_data = np.loadtxt("NoisyXORTestData.txt") 63 | X_test = test_data[:,0:-1] 64 | Y_test = test_data[:,-1] 65 | 66 | tm = MultiClassTsetlinMachine(10, 15, 3.9, boost_true_positive_feedback=0) 67 | 68 | tm.fit(X_train, Y_train, epochs=200) 69 | 70 | print("Accuracy:", 100*(tm.predict(X_test) == Y_test).mean()) 71 | 72 | print("Prediction: x1 = 1, x2 = 0, ... -> y = %d" % (tm.predict(np.array([[1,0,1,0,1,0,1,1,1,1,0,0]])))) 73 | print("Prediction: x1 = 0, x2 = 1, ... -> y = %d" % (tm.predict(np.array([[0,1,1,0,1,0,1,1,1,1,0,0]])))) 74 | print("Prediction: x1 = 0, x2 = 0, ... -> y = %d" % (tm.predict(np.array([[0,0,1,0,1,0,1,1,1,1,0,0]])))) 75 | print("Prediction: x1 = 1, x2 = 1, ... -> y = %d" % (tm.predict(np.array([[1,1,1,0,1,0,1,1,1,1,0,0]])))) 76 | ``` 77 | 78 | #### Output 79 | 80 | ```bash 81 | python3 ./NoisyXORDemo.py 82 | 83 | Accuracy: 100.00% 84 | 85 | Prediction: x1 = 1, x2 = 0, ... -> y = 1 86 | Prediction: x1 = 0, x2 = 1, ... -> y = 1 87 | Prediction: x1 = 0, x2 = 0, ... -> y = 0 88 | Prediction: x1 = 1, x2 = 1, ... -> y = 0 89 | ``` 90 | 91 | ### Interpretability Demo 92 | 93 | #### Code: InterpretabilityDemo.py 94 | 95 | ```python 96 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 97 | import numpy as np 98 | 99 | number_of_features = 20 100 | noise = 0.1 101 | 102 | X_train = np.random.randint(0, 2, size=(5000, number_of_features), dtype=np.uint32) 103 | Y_train = np.logical_xor(X_train[:,0], X_train[:,1]).astype(dtype=np.uint32) 104 | Y_train = np.where(np.random.rand(5000) <= noise, 1-Y_train, Y_train) # Adds noise 105 | 106 | X_test = np.random.randint(0, 2, size=(5000, number_of_features), dtype=np.uint32) 107 | Y_test = np.logical_xor(X_test[:,0], X_test[:,1]).astype(dtype=np.uint32) 108 | 109 | tm = MultiClassTsetlinMachine(10, 15, 3.0, boost_true_positive_feedback=0) 110 | 111 | tm.fit(X_train, Y_train, epochs=200) 112 | 113 | print("Accuracy:", 100*(tm.predict(X_test) == Y_test).mean()) 114 | 115 | print("\nClass 0 Positive Clauses:\n") 116 | for j in range(0, 10, 2): 117 | print("Clause #%d: " % (j), end=' ') 118 | l = [] 119 | for k in range(number_of_features*2): 120 | if tm.ta_action(0, j, k) == 1: 121 | if k < number_of_features: 122 | l.append(" x%d" % (k)) 123 | else: 124 | l.append("¬x%d" % (k-number_of_features)) 125 | print(" ∧ ".join(l)) 126 | 127 | print("\nClass 0 Negative Clauses:\n") 128 | for j in range(1, 10, 2): 129 | print("Clause #%d: " % (j), end=' ') 130 | l = [] 131 | for k in range(number_of_features*2): 132 | if tm.ta_action(0, j, k) == 1: 133 | if k < number_of_features: 134 | l.append(" x%d" % (k)) 135 | else: 136 | l.append("¬x%d" % (k-number_of_features)) 137 | print(" ∧ ".join(l)) 138 | 139 | print("\nClass 1 Positive Clauses:\n") 140 | for j in range(0, 10, 2): 141 | print("Clause #%d: " % (j), end=' ') 142 | l = [] 143 | for k in range(number_of_features*2): 144 | if tm.ta_action(1, j, k) == 1: 145 | if k < number_of_features: 146 | l.append(" x%d" % (k)) 147 | else: 148 | l.append("¬x%d" % (k-number_of_features)) 149 | print(" ∧ ".join(l)) 150 | 151 | print("\nClass 1 Negative Clauses:\n") 152 | for j in range(1, 10, 2): 153 | print("Clause #%d: " % (j), end=' ') 154 | l = [] 155 | for k in range(number_of_features*2): 156 | if tm.ta_action(1, j, k) == 1: 157 | if k < number_of_features: 158 | l.append(" x%d" % (k)) 159 | else: 160 | l.append("¬x%d" % (k-number_of_features)) 161 | print(" ∧ ".join(l)) 162 | ``` 163 | 164 | #### Output 165 | 166 | ```bash 167 | python3 ./InterpretabilityDemo.py 168 | 169 | Accuracy: 100.0 170 | 171 | Class 0 Positive Clauses: 172 | 173 | Clause #0: ¬x0 ∧ ¬x1 174 | Clause #2: x0 ∧ x1 175 | Clause #4: x0 ∧ x1 176 | Clause #6: ¬x0 ∧ ¬x1 177 | Clause #8: ¬x0 ∧ ¬x1 178 | 179 | Class 0 Negative Clauses: 180 | 181 | Clause #1: x0 ∧ ¬x1 182 | Clause #3: x0 ∧ ¬x1 183 | Clause #5: x1 ∧ ¬x0 184 | Clause #7: x1 ∧ ¬x0 185 | Clause #9: x0 ∧ ¬x1 186 | 187 | Class 1 Positive Clauses: 188 | 189 | Clause #0: x1 ∧ ¬x0 190 | Clause #2: x1 ∧ ¬x0 191 | Clause #4: x0 ∧ ¬x1 192 | Clause #6: x0 ∧ ¬x1 193 | Clause #8: x0 ∧ ¬x1 194 | 195 | Class 1 Negative Clauses: 196 | 197 | Clause #1: x0 ∧ x1 198 | Clause #3: ¬x0 ∧ ¬x1 199 | Clause #5: ¬x0 ∧ ¬x1 200 | Clause #7: ¬x0 ∧ ¬x1 201 | Clause #9: x0 ∧ x1 202 | ``` 203 | 204 | ### 2D Convolution Demo 205 | 206 | #### Code: 2DNoisyXORDemo.py 207 | 208 | ```python 209 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 210 | import numpy as np 211 | 212 | train_data = np.loadtxt("2DNoisyXORTrainingData.txt") 213 | X_train = train_data[:,0:-1].reshape(train_data.shape[0], 4, 4) 214 | Y_train = train_data[:,-1] 215 | 216 | test_data = np.loadtxt("2DNoisyXORTestData.txt") 217 | X_test = test_data[:,0:-1].reshape(test_data.shape[0], 4, 4) 218 | Y_test = test_data[:,-1] 219 | 220 | ctm = MultiClassConvolutionalTsetlinMachine2D(40, 60, 3.9, (2, 2), boost_true_positive_feedback=0) 221 | 222 | ctm.fit(X_train, Y_train, epochs=5000) 223 | 224 | print("Accuracy:", 100*(ctm.predict(X_test) == Y_test).mean()) 225 | 226 | Xi = np.array([[[0,1,1,0], 227 | [1,1,0,1], 228 | [1,0,1,1], 229 | [0,0,0,1]]]) 230 | 231 | print("\nInput Image:\n") 232 | print(Xi) 233 | print("\nPrediction: %d" % (ctm.predict(Xi))) 234 | ``` 235 | 236 | #### Output 237 | 238 | ```bash 239 | python3 ./2DNoisyXORDemo.py 240 | 241 | Accuracy: 99.71% 242 | 243 | Input Image: 244 | 245 | [[0 1 1 0] 246 | [1 1 0 1] 247 | [1 0 1 1] 248 | [0 0 0 1]] 249 | 250 | Prediction: 1 251 | ``` 252 | 253 | ### Continuous Input Demo 254 | 255 | #### Code: BreastCancerDemo.py 256 | 257 | ```python 258 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 259 | from pyTsetlinMachineParallel.tools import Binarizer 260 | import numpy as np 261 | 262 | from sklearn import datasets 263 | from sklearn.model_selection import train_test_split 264 | 265 | breast_cancer = datasets.load_breast_cancer() 266 | X = breast_cancer.data 267 | Y = breast_cancer.target 268 | 269 | b = Binarizer(max_bits_per_feature = 10) 270 | b.fit(X) 271 | X_transformed = b.transform(X) 272 | 273 | tm = MultiClassTsetlinMachine(800, 40, 5.0) 274 | 275 | print("\nMean accuracy over 100 runs:\n") 276 | tm_results = np.empty(0) 277 | for i in range(100): 278 | X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y, test_size=0.2) 279 | 280 | tm.fit(X_train, Y_train, epochs=25) 281 | tm_results = np.append(tm_results, np.array(100*(tm.predict(X_test) == Y_test).mean())) 282 | print("#%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1))) 283 | ``` 284 | #### Output 285 | 286 | ```bash 287 | python3 ./BreastCancerDemo.py 288 | 289 | Mean accuracy over 100 runs: 290 | 291 | #1 Average Accuracy: 97.37% +/- 0.00 292 | #2 Average Accuracy: 97.37% +/- 0.00 293 | ... 294 | #99 Average Accuracy: 97.52% +/- 0.29 295 | #100 Average Accuracy: 97.54% +/- 0.29 296 | ``` 297 | 298 | ### MNIST Demo 299 | 300 | #### Code: MNISTDemo.py 301 | 302 | ```python 303 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 304 | import numpy as np 305 | from time import time 306 | 307 | from keras.datasets import mnist 308 | 309 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 310 | 311 | X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) 312 | X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) 313 | 314 | tm = MultiClassTsetlinMachine(2000, 50, 10.0) 315 | 316 | print("\nAccuracy over 250 epochs:\n") 317 | for i in range(250): 318 | start_training = time() 319 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 320 | stop_training = time() 321 | 322 | start_testing = time() 323 | result = 100*(tm.predict(X_test) == Y_test).mean() 324 | stop_testing = time() 325 | 326 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 327 | ``` 328 | 329 | #### Output 330 | 331 | ```bash 332 | python3 ./MNISTDemo.py 333 | 334 | Accuracy over 250 epochs: 335 | 336 | #1 Accuracy: 94.91% Training: 4.43s Testing: 1.02s 337 | #2 Accuracy: 96.06% Training: 3.66s Testing: 1.03s 338 | #3 Accuracy: 96.46% Training: 3.24s Testing: 1.07s 339 | ... 340 | 341 | #248 Accuracy: 98.19% Training: 1.77s Testing: 1.06s 342 | #249 Accuracy: 98.19% Training: 1.90s Testing: 1.05s 343 | #250 Accuracy: 98.21% Training: 1.70s Testing: 1.06s 344 | ``` 345 | ### MNIST Demo w/Weighted Clauses 346 | 347 | #### Code: MNISTDemoWeightedClauses.py 348 | 349 | ```python 350 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 351 | import numpy as np 352 | from time import time 353 | 354 | from keras.datasets import mnist 355 | 356 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 357 | 358 | X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) 359 | X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) 360 | 361 | tm = MultiClassTsetlinMachine(2000, 50*100, 10.0, weighted_clauses=True) 362 | 363 | print("\nAccuracy over 100 epochs:\n") 364 | for i in range(100): 365 | start_training = time() 366 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 367 | stop_training = time() 368 | 369 | start_testing = time() 370 | result = 100*(tm.predict(X_test) == Y_test).mean() 371 | stop_testing = time() 372 | 373 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 374 | ``` 375 | 376 | #### Output 377 | 378 | ```bash 379 | python3 ./MNISTDemoWeightedClauses.py 380 | 381 | Accuracy over 100 epochs: 382 | 383 | #1 Accuracy: 93.58% Training: 6.01s Testing: 1.53s 384 | #2 Accuracy: 95.22% Training: 3.09s Testing: 1.44s 385 | #3 Accuracy: 95.98% Training: 3.02s Testing: 1.08s 386 | ... 387 | 388 | #98 Accuracy: 98.05% Training: 1.78s Testing: 1.06s 389 | #99 Accuracy: 98.16% Training: 1.67s Testing: 1.06s 390 | #100 Accuracy: 98.14% Training: 1.70s Testing: 1.08s 391 | ``` 392 | 393 | ### MNIST 2D Convolution Demo w/Weighted Clauses 394 | 395 | #### Code: MNISTDemo2DConvolutionWeightedClauses.py 396 | 397 | ```python 398 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 399 | import numpy as np 400 | from time import time 401 | 402 | from keras.datasets import mnist 403 | 404 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 405 | 406 | X_train = np.where(X_train >= 75, 1, 0) 407 | X_test = np.where(X_test >= 75, 1, 0) 408 | 409 | tm = MultiClassConvolutionalTsetlinMachine2D(2000, 50*100, 5.0, (10, 10), weighted_clauses=True) 410 | 411 | print("\nAccuracy over 30 epochs:\n") 412 | for i in range(30): 413 | start = time() 414 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 415 | stop = time() 416 | 417 | result = 100*(tm.predict(X_test) == Y_test).mean() 418 | 419 | print("#%d Accuracy: %.2f%% (%.2fs)" % (i+1, result, stop-start)) 420 | ``` 421 | 422 | #### Output 423 | 424 | ```bash 425 | python3 ./MNISTDemo2DConvolutionWeightedClauses.py 426 | 427 | Accuracy over 30 epochs: 428 | 429 | #1 Accuracy: 97.78% (26.13s) 430 | #2 Accuracy: 98.05% (26.81s) 431 | #3 Accuracy: 98.25% (27.27s) 432 | ... 433 | 434 | #28 Accuracy: 99.07% (30.84s) 435 | #29 Accuracy: 99.09% (30.21s) 436 | #30 Accuracy: 99.12% (29.52s) 437 | ``` 438 | ### Fashion MNIST 2D Convolution Demo w/Weighted Clauses 439 | 440 | #### Code: FashionMNISTDemo2DConvolutionWeightedClauses.py 441 | 442 | ```python 443 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 444 | import numpy as np 445 | from time import time 446 | import cv2 447 | from keras.datasets import fashion_mnist 448 | 449 | (X_train, Y_train), (X_test, Y_test) = fashion_mnist.load_data() 450 | X_train = np.copy(X_train) 451 | X_test = np.copy(X_test) 452 | 453 | for i in range(X_train.shape[0]): 454 | X_train[i,:] = cv2.adaptiveThreshold(X_train[i], 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 455 | 456 | for i in range(X_test.shape[0]): 457 | X_test[i,:] = cv2.adaptiveThreshold(X_test[i], 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 458 | 459 | tm = MultiClassConvolutionalTsetlinMachine2D(8000, 100*100, 10.0, (10, 10), weighted_clauses=True) 460 | 461 | print("\nAccuracy over 20 epochs:\n") 462 | for i in range(20): 463 | start = time() 464 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 465 | stop = time() 466 | 467 | result = 100*(tm.predict(X_test) == Y_test).mean() 468 | 469 | print("#%d Accuracy: %.2f%% (%.2fs)" % (i+1, result, stop-start)) 470 | ``` 471 | 472 | #### Output 473 | 474 | ```bash 475 | python3 ./FashionMNISTDemo2DConvolutionWeightedClauses.py 476 | 477 | Accuracy over 20 epochs: 478 | 479 | #1 Accuracy: 84.98% (72.75s) 480 | #2 Accuracy: 86.76% (67.73s) 481 | #3 Accuracy: 87.74% (69.19s) 482 | ... 483 | 484 | #18 Accuracy: 90.50% (63.15s) 485 | #19 Accuracy: 90.59% (76.57s) 486 | #20 Accuracy: 90.77% (69.71s) 487 | ``` 488 | 489 | ### IMDb Text Categorization Demo 490 | 491 | #### Code: IMDbTextCategorizationDemo.py 492 | 493 | ```python 494 | import numpy as np 495 | import keras 496 | from sklearn.feature_selection import SelectKBest 497 | from sklearn.feature_selection import chi2 498 | from keras.datasets import imdb 499 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 500 | from time import time 501 | 502 | MAX_NGRAM = 2 503 | 504 | NUM_WORDS=5000 505 | INDEX_FROM=2 506 | 507 | FEATURES=5000 508 | 509 | print("Downloading dataset...") 510 | 511 | train,test = keras.datasets.imdb.load_data(num_words=NUM_WORDS, index_from=INDEX_FROM) 512 | 513 | train_x,train_y = train 514 | test_x,test_y = test 515 | 516 | word_to_id = keras.datasets.imdb.get_word_index() 517 | word_to_id = {k:(v+INDEX_FROM) for k,v in word_to_id.items()} 518 | word_to_id[""] = 0 519 | word_to_id[""] = 1 520 | word_to_id[""] = 2 521 | 522 | print("Producing bit representation...") 523 | 524 | # Produce N-grams 525 | 526 | id_to_word = {value:key for key,value in word_to_id.items()} 527 | 528 | vocabulary = {} 529 | for i in range(train_y.shape[0]): 530 | terms = [] 531 | for word_id in train_x[i]: 532 | terms.append(id_to_word[word_id]) 533 | 534 | for N in range(1,MAX_NGRAM+1): 535 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 536 | for gram in grams: 537 | phrase = " ".join(gram) 538 | 539 | if phrase in vocabulary: 540 | vocabulary[phrase] += 1 541 | else: 542 | vocabulary[phrase] = 1 543 | 544 | # Assign a bit position to each N-gram (minimum frequency 10) 545 | 546 | phrase_bit_nr = {} 547 | bit_nr_phrase = {} 548 | bit_nr = 0 549 | for phrase in vocabulary.keys(): 550 | if vocabulary[phrase] < 10: 551 | continue 552 | 553 | phrase_bit_nr[phrase] = bit_nr 554 | bit_nr_phrase[bit_nr] = phrase 555 | bit_nr += 1 556 | 557 | # Create bit representation 558 | 559 | X_train = np.zeros((train_y.shape[0], len(phrase_bit_nr)), dtype=np.uint32) 560 | Y_train = np.zeros(train_y.shape[0], dtype=np.uint32) 561 | for i in range(train_y.shape[0]): 562 | terms = [] 563 | for word_id in train_x[i]: 564 | terms.append(id_to_word[word_id]) 565 | 566 | for N in range(1,MAX_NGRAM+1): 567 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 568 | for gram in grams: 569 | phrase = " ".join(gram) 570 | if phrase in phrase_bit_nr: 571 | X_train[i,phrase_bit_nr[phrase]] = 1 572 | 573 | Y_train[i] = train_y[i] 574 | 575 | X_test = np.zeros((test_y.shape[0], len(phrase_bit_nr)), dtype=np.uint32) 576 | Y_test = np.zeros(test_y.shape[0], dtype=np.uint32) 577 | 578 | for i in range(test_y.shape[0]): 579 | terms = [] 580 | for word_id in test_x[i]: 581 | terms.append(id_to_word[word_id]) 582 | 583 | for N in range(1,MAX_NGRAM+1): 584 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 585 | for gram in grams: 586 | phrase = " ".join(gram) 587 | if phrase in phrase_bit_nr: 588 | X_test[i,phrase_bit_nr[phrase]] = 1 589 | 590 | Y_test[i] = test_y[i] 591 | 592 | print("Selecting features...") 593 | 594 | SKB = SelectKBest(chi2, k=FEATURES) 595 | SKB.fit(X_train, Y_train) 596 | 597 | selected_features = SKB.get_support(indices=True) 598 | X_train = SKB.transform(X_train) 599 | X_test = SKB.transform(X_test) 600 | 601 | tm = MultiClassTsetlinMachine(10000, 80*100, 10.0, weighted_clauses=True) 602 | 603 | print("\nAccuracy over 30 epochs:\n") 604 | for i in range(30): 605 | start_training = time() 606 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 607 | stop_training = time() 608 | 609 | start_testing = time() 610 | result = 100*(tm.predict(X_test) == Y_test).mean() 611 | stop_testing = time() 612 | 613 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 614 | ``` 615 | 616 | #### Output: 617 | 618 | ```bash 619 | python ./IMDbTextCategorizationDemo.py 620 | 621 | Downloading dataset... 622 | Producing bit representation... 623 | Selecting features... 624 | 625 | Accuracy over 30 epochs: 626 | 627 | #1 Accuracy: 85.61% Training: 86.99s Testing: 21.02s 628 | #2 Accuracy: 86.92% Training: 76.44s Testing: 20.19s 629 | #3 Accuracy: 86.53% Training: 68.72s Testing: 22.44s 630 | ... 631 | 632 | #28 Accuracy: 89.12% Training: 40.38s Testing: 27.77s 633 | #29 Accuracy: 89.04% Training: 42.99s Testing: 26.28s 634 | #30 Accuracy: 89.08% Training: 39.81s Testing: 26.38s 635 | ``` 636 | 637 | ### Regression Demo 638 | 639 | #### Code: RegressionDemo.py 640 | 641 | ```python 642 | from pyTsetlinMachineParallel.tm import RegressionTsetlinMachine 643 | from pyTsetlinMachineParallel.tools import Binarizer 644 | import numpy as np 645 | from time import time 646 | 647 | from sklearn import datasets 648 | from sklearn.model_selection import train_test_split 649 | 650 | california_housing = datasets.fetch_california_housing() 651 | X = california_housing.data 652 | Y = california_housing.target 653 | 654 | b = Binarizer(max_bits_per_feature = 10) 655 | b.fit(X) 656 | X_transformed = b.transform(X) 657 | 658 | tm = RegressionTsetlinMachine(1000, 500*10, 2.75, weighted_clauses=True) 659 | 660 | print("\nRMSD over 25 runs:\n") 661 | tm_results = np.empty(0) 662 | for i in range(25): 663 | X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y) 664 | 665 | start = time() 666 | tm.fit(X_train, Y_train, epochs=30) 667 | stop = time() 668 | tm_results = np.append(tm_results, np.sqrt(((tm.predict(X_test) - Y_test)**2).mean())) 669 | 670 | print("#%d RMSD: %.2f +/- %.2f (%.2fs)" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1), stop-start)) 671 | ``` 672 | 673 | #### Output 674 | 675 | ```bash 676 | python3 ./RegressionDemo.py 677 | 678 | RMSD over 25 runs: 679 | 680 | #1 RMSD: 0.61 +/- 0.00 (1.16s) 681 | #2 RMSD: 0.62 +/- 0.01 (0.99s) 682 | #3 RMSD: 0.61 +/- 0.01 (0.96s) 683 | ... 684 | 685 | #23 RMSD: 0.61 +/- 0.00 (0.93s) 686 | #24 RMSD: 0.61 +/- 0.00 (1.06s) 687 | #25 RMSD: 0.61 +/- 0.00 (1.02s) 688 | ``` 689 | 690 | ## Further Work 691 | 692 | * Multilayer Tsetlin Machine 693 | * Recurrent Tsetlin Machine 694 | * GPU support 695 | * Optimize convolution code 696 | * More extensive hyper-parameter search for the demos 697 | 698 | ## Requirements 699 | 700 | - Python 3.7.x, https://www.python.org/downloads/ 701 | - Numpy, http://www.numpy.org/ 702 | - OpenMP 5.0, https://www.openmp.org/ 703 | - Ubuntu or macOS 704 | 705 | ## Acknowledgements 706 | 707 | I thank my colleagues from the Centre for Artificial Intelligence Research (CAIR), Lei Jiao, Xuan Zhang, Geir Thore Berge, Darshana Abeyrathna, Saeed Rahimi Gorji, Sondre Glimsdal, Rupsa Saha, Bimal Bhattarai, Rohan K. Yadav, Bernt Viggo Matheussen, Morten Goodwin, Christian Omlin, Vladimir Zadorozhny (University of Pittsburgh), Jivitesh Sharma, and Ahmed Abouzeid, for their contributions to the development of the Tsetlin machine family of techniques. I would also like to thank our House of CAIR partners, Alex Yakovlev, Rishad Shafik, Adrian Wheeldon, Jie Lei, Tousif Rahman (Newcastle University), Jonny Edwards (Temporal Computing), Marco Wiering (University of Groningen), Christian D. Blakely (PwC Switzerland), Adrian Phoulady, Anders Refsdal Olsen, Halvor Smørvik, and Erik Mathisen for their many contributions. 708 | 709 | ## Tsetlin Machine Papers 710 | 711 | ```bash 712 | @InProceedings{wheeldon2021self, 713 | title="{Self-Timed Reinforcement Learning using Tsetlin Machine}", 714 | author={Adrian Wheeldon and Alex Yakovlev and Rishad Shafik}, 715 | booktitle={27th IEEE International Symposium on Asynchronous Circuits and Systems (ASYNC 2021)}, 716 | year={2021}, 717 | organization={IEEE}, 718 | url={https://arxiv.org/abs/2109.00846} 719 | } 720 | ``` 721 | 722 | ```bash 723 | @article{glimsdal2021coalesced, 724 | title={Coalesced Multi-Output Tsetlin Machines with Clause Sharing}, 725 | author={Sondre Glimsdal and Ole-Christoffer Granmo}, 726 | journal = {arXiv preprint arXiv:2108.07594}, year = {2021}, 727 | url = {https://arxiv.org/abs/2108.07594} 728 | } 729 | ``` 730 | 731 | ```bash 732 | @article{Abeyrathna2021adaptivesparse, 733 | title="{Adaptive Sparse Representation of Continuous Input for Tsetlin Machines Based on Stochastic Searching on the Line}", 734 | volume={10}, 735 | ISSN={2079-9292}, 736 | url={http://dx.doi.org/10.3390/electronics10172107}, 737 | DOI={10.3390/electronics10172107}, 738 | number={17}, 739 | journal={Electronics}, 740 | publisher={MDPI AG}, 741 | author={Abeyrathna, Kuruge Darshana and Granmo, Ole-Christoffer and Goodwin, Morten}, 742 | year={2021}, 743 | month={Aug}, 744 | pages={2107}} 745 | ``` 746 | 747 | ```bash 748 | @article{zhang2021convergence, 749 | title = {On the {{Convergence}} of {{Tsetlin Machines}} for the {{IDENTITY}}- and {{NOT Operators}}}, 750 | author = {Zhang, Xuan and Jiao, Lei and Granmo, Ole-Christoffer and Goodwin, Morten}, 751 | year = {2021}, 752 | journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence} 753 | } 754 | ``` 755 | 756 | ```bash 757 | @InProceedings{abeyrathna2021parallel, 758 | title="{Massively Parallel and Asynchronous Tsetlin Machine Architecture Supporting Almost Constant-Time Scaling}", 759 | author={K. Darshana Abeyrathna and Bimal Bhattarai and Morten Goodwin and Saeed Gorji and Ole-Christoffer Granmo and Lei Jiao and Rupsa Saha and Rohan K. Yadav}, 760 | booktitle={The Thirty-eighth International Conference on Machine Learning (ICML 2021)}, 761 | year={2021}, 762 | organization={ICML} 763 | } 764 | ``` 765 | 766 | ```bash 767 | @article{sharma2021dropclause, 768 | title="{Human Interpretable AI: Enhancing Tsetlin Machine Stochasticity with Drop Clause}", 769 | author={Jivitesh Sharma and Rohan Yadav and Ole-Christoffer Granmo and Lei Jiao}, 770 | journal = {arXiv preprint arXiv:2105.14506}, year = {2021}, 771 | url = {https://arxiv.org/abs/2105.14506} 772 | } 773 | ``` 774 | 775 | ```bash 776 | @article{bhattarai2021fakenews, 777 | title="{Explainable Tsetlin Machine framework for fake news detection with credibility score assessment}", 778 | author={Bimal Bhattarai and Ole-Christoffer Granmo and Lei Jiao}, 779 | journal = {arXiv preprint arXiv:2105.09114}, year = {2021}, 780 | url = {https://arxiv.org/abs/2105.09114} 781 | } 782 | ``` 783 | 784 | ```bash 785 | @article{bhattarai2021wordlevel, 786 | title="{Word-level Human Interpretable Scoring Mechanism for Novel Text Detection Using Tsetlin Machines}", 787 | author={Bimal Bhattarai and Ole-Christoffer Granmo and Lei Jiao}, 788 | journal = {arXiv preprint arXiv:2105.04708}, year = {2021}, 789 | url = {https://arxiv.org/abs/2105.04708} 790 | } 791 | ``` 792 | 793 | ```bash 794 | @article{yadav2021dwr, 795 | title="{Distributed Word Representation in Tsetlin Machine}", 796 | author={Rohan Kumar Yadav and Lei Jiao and Ole-Christoffer Granmo and Morten Goodwin}, 797 | journal = {arXiv preprint arXiv:2104.06901}, year = {2021}, 798 | url = {https://arxiv.org/abs/2104.06901} 799 | } 800 | ``` 801 | 802 | ```bash 803 | @article{lei2021kws, 804 | title="{Low-Power Audio Keyword Spotting Using Tsetlin Machines}", 805 | author={Jie Lei and Tousif Rahman and Rishad Shafik and Adrian Wheeldon and Alex Yakovlev and Ole-Christoffer Granmo and Fahim Kawsar and Akhil Mathur}, 806 | journal = {Journal of Low Power Electronics and Applications}, year = {2021}, 807 | volume=11, 808 | issue=18, 809 | url = {https://www.mdpi.com/2079-9268/11/2/18}, 810 | organization={MDPI} 811 | } 812 | ``` 813 | 814 | ```bash 815 | @InProceedings{blakely2021closed, 816 | title="{Closed-Form Expressions for Global and Local Interpretation of Tsetlin Machines}", 817 | author={Christian D. {Blakely} and Ole-Christoffer {Granmo}}, 818 | booktitle={34th International Conference on Industrial, Engineering and Other Applications of Applied Intelligent Systems (IEA/AIE 2021)}, 819 | year={2021}, 820 | organization={Springer} 821 | } 822 | ``` 823 | 824 | ```bash 825 | @InProceedings{gorji2021rl, 826 | title="{Explainable Reinforcement Learning with the Tsetlin Machine}", 827 | author={Saeed {Gorji} and Ole Christoffer {Granmo} and Marco {Wiering}}, 828 | booktitle={34th International Conference on Industrial, Engineering and Other Applications of Applied Intelligent Systems (IEA/AIE 2021)}, 829 | year={2021}, 830 | organization={Springer} 831 | } 832 | ``` 833 | 834 | ```bash 835 | @InProceedings{yadav2021sentiment, 836 | title="{Human-Level Interpretable Learning for Aspect-Based Sentiment Analysis}", 837 | author={Rohan Kumar {Yadav} and Lei {Jiao} and Ole-Christoffer {Granmo} and Morten {Goodwin}}, 838 | booktitle={The Thirty-Fifth AAAI Conference on Artificial Intelligence (AAAI-21)}, 839 | year={2021}, 840 | organization={AAAI} 841 | } 842 | ``` 843 | 844 | ```bash 845 | @InProceedings{nicolae2021question, 846 | title="{Question Classification using Interpretable Tsetlin Machine}", 847 | author={Dragos Constantin {Nicolae}}, 848 | booktitle={The 1st International Workshop on Machine Reasoning (MRC 2021)}, 849 | year={2021} 850 | } 851 | ``` 852 | 853 | ```bash 854 | @article{saha2021relational, 855 | title="{A Relational Tsetlin Machine with Applications to Natural Language Understanding}", 856 | author={Rupsa Saha and Ole-Christoffer Granmo and Vladimir I. Zadorozhny and Morten Goodwin}, 857 | journal = {arXiv preprint arXiv:2102.10952}, year = {2021}, 858 | url = {https://arxiv.org/abs/2102.10952} 859 | } 860 | ``` 861 | 862 | ```bash 863 | @InProceedings{yadav2021wordsense, 864 | title="{Interpretability in Word Sense Disambiguation using Tsetlin Machine}", 865 | author={Rohan Kumar {Yadav} and Lei {Jiao} and Ole-Christoffer {Granmo} and Morten {Goodwin}}, 866 | booktitle={13th International Conference on Agents and Artificial Intelligence (ICAART 2021)}, 867 | year={2021}, 868 | organization={INSTICC} 869 | } 870 | ``` 871 | 872 | ```bash 873 | @InProceedings{bhattarai2021novelty, 874 | title="{Measuring the Novelty of Natural Language Text Using the Conjunctive Clauses of a Tsetlin Machine Text Classifier}", 875 | author={Bimal Bhattarai and Lei Jiao and Ole-Christoffer Granmo}, 876 | booktitle={13th International Conference on Agents and Artificial Intelligence (ICAART 2021)}, 877 | year={2021}, 878 | organization={INSTICC} 879 | } 880 | ``` 881 | 882 | ```bash 883 | @InProceedings{abeyrathna2021convreg, 884 | title="{Convolutional Regression Tsetlin Machine}", 885 | author={Abeyrathna, Kuruge Darshana and Granmo, Ole-Christoffer and Goodwin, Morten}, 886 | booktitle={6th International Conference on Machine Learning Technologies (ICMLT 2021)}, 887 | year={2021}, 888 | organization={ACM} 889 | } 890 | ``` 891 | 892 | ```bash 893 | @article{abeyrathna2021integer, 894 | author = {Abeyrathna, Kuruge Darshana and Granmo, Ole-Christoffer and Goodwin, Morten}, 895 | title = "{Extending the Tsetlin Machine With Integer-Weighted Clauses for Increased Interpretability}", 896 | journal = {IEEE Access}, 897 | volume = 9, 898 | year = {2021} 899 | } 900 | ``` 901 | 902 | ```bash 903 | @article{jiao2021xor, 904 | title="{On the Convergence of Tsetlin Machines for the XOR Operator}", 905 | author={Lei Jiao and Xuan Zhang and Ole-Christoffer Granmo and K. Darshana Abeyrathna}, 906 | journal = {arXiv preprint arXiv:2101.02547}, year = {2021}, 907 | url = {https://arxiv.org/abs/2101.02547} 908 | } 909 | ``` 910 | 911 | ```bash 912 | @InProceedings{wheeldon2021low, 913 | title="{Low-Latency Asynchronous Logic Design for Inference at the Edge}", 914 | author={Adrian Wheeldon and Alex Yakovlev and Rishad Shafik and Jordan Morris}, 915 | booktitle={2021 Design, Automation and Test in Europe Conference (DATE21)}, 916 | year={2021}, 917 | pages="370-373" 918 | } 919 | ``` 920 | 921 | ```bash 922 | @InProceedings{lei2020arithmetic, 923 | title="{From Arithmetic to Logic Based AI: A Comparative Analysis of Neural Networks and Tsetlin Machine}", 924 | author={Jie {Lei} and Adrian {Wheeldon} and Rishad {Shafik} and Alex {Yakovlev} and Ole-Christoffer {Granmo}}, 925 | booktitle={27th IEEE International Conference on Electronics Circuits and Systems (ICECS2020)}, 926 | year={2020}, 927 | organization={IEEE} 928 | } 929 | ``` 930 | 931 | ```bash 932 | @InProceedings{abeyrathna2020auc, 933 | title="{On Obtaining Classification Confidence, Ranked Predictions and AUC with Tsetlin Machines}", 934 | author={K. Darshana Abeyrathna and Ole-Christoffer Granmo and Morten Goodwin}, 935 | booktitle={2020 IEEE Symposium Series on Computational Intelligence (SSCI)}, 936 | year={2020}, 937 | organization={IEEE} 938 | } 939 | ``` 940 | 941 | ```bash 942 | @InProceedings{abeyrathna2020intrusion, 943 | title="{Intrusion Detection with Interpretable Rules Generated Using the Tsetlin Machine}", 944 | author={K. Darshana Abeyrathna and Harsha S. Gardiyawasam Pussewalage and Sasanka N. Ranasinghea and Vladimir A. Oleshchuk and Ole-Christoffer Granmo}, 945 | booktitle={2020 IEEE Symposium Series on Computational Intelligence (SSCI)}, 946 | year={2020}, 947 | organization={IEEE} 948 | } 949 | ``` 950 | 951 | ```bash 952 | @InProceedings{abeyrathna2020adaptive, 953 | title="{Adaptive Continuous Feature Binarization for Tsetlin Machines Applied to Forecasting Dengue Incidences in the Philippines}", 954 | author={K. Darshana Abeyrathna and Ole-Christoffer Granmo and Xuan Zhang and Morten Goodwin}, 955 | booktitle={2020 IEEE Symposium Series on Computational Intelligence (SSCI)}, 956 | year={2020}, 957 | organization={IEEE} 958 | } 959 | ``` 960 | 961 | ```bash 962 | @InProceedings{saha2020causal, 963 | author = {Rupsa {Saha} and Ole-Christoffer {Granmo} and Morten {Goodwin}}, 964 | title = "{Mining Interpretable Rules for Sentiment and Semantic Relation Analysis using Tsetlin Machines}", 965 | booktitle="Lecture Notes in Computer Science: Proceedings of the 40th International Conference on Innovative Techniques and Applications of Artificial Intelligence (SGAI-2020)", year="2020", 966 | publisher="Springer International Publishing" 967 | } 968 | ``` 969 | 970 | ```bash 971 | @InProceedings{abeyrathna2020deterministic, 972 | title="{A Novel Multi-Step Finite-State Automaton for Arbitrarily Deterministic Tsetlin Machine Learning}", 973 | author={K. Darshana Abeyrathna and Ole-Christoffer Granmo and Rishad Shafik and Alex Yakovlev and Adrian Wheeldon and Jie Lei and Morten Goodwin}, 974 | booktitle="Lecture Notes in Computer Science: Proceedings of the 40th International Conference on Innovative Techniques and Applications of Artificial Intelligence (SGAI-2020)", year="2020", 975 | publisher="Springer International Publishing" 976 | } 977 | ``` 978 | 979 | ```bash 980 | @article{wheeldon2020learning, 981 | author={Adrian {Wheeldon} and Rishad {Shafik} and Tousif {Rahman} and Jie {Lei} and Alex {Yakovlev} and Ole-Christoffer {Granmo}}, 982 | journal={Philosophical Transactions of the Royal Society A}, 983 | title="{Learning Automata based Energy-efficient AI Hardware Design for IoT}", 984 | year={2020} 985 | } 986 | ``` 987 | 988 | ```bash 989 | @InProceedings{shafik2020explainability, 990 | title="{Explainability and Dependability Analysis of Learning Automata based AI Hardware}", 991 | author={Rishad {Shafik} and Adrian {Wheeldon} and Alex {Yakovlev}}, 992 | booktitle={IEEE 26th International Symposium on On-Line Testing and Robust System Design (IOLTS)}, 993 | year={2020}, 994 | organization={IEEE} 995 | } 996 | ``` 997 | 998 | ```bash 999 | @article{lavrova2020, 1000 | author = {D. S. {Lavrova} and N. N. {Eliseev}}, 1001 | title = "{Network Attacks Detection based on Tsetlin Machine}", 1002 | pages = {17-23}, 1003 | journal = {Information Security Problems. Computer Systems.}, year = {2020} 1004 | } 1005 | ``` 1006 | 1007 | ```bash 1008 | @InProceedings{gorji2020indexing, 1009 | title="{Increasing the Inference and Learning Speed of Tsetlin Machines with Clause Indexing}", 1010 | author={Saeed {Gorji} and Ole Christoffer {Granmo} and Sondre {Glimsdal} and Jonathan {Edwards} and Morten {Goodwin}}, 1011 | booktitle={33rd International Conference on Industrial, Engineering and Other Applications of Applied Intelligent Systems (IEA/AIE 2020)}, 1012 | year={2020}, 1013 | organization={Springer} 1014 | } 1015 | ``` 1016 | 1017 | ```bash 1018 | @InProceedings{abeyrathna2020integerregression, 1019 | title="{A Regression Tsetlin Machine with Integer Weighted Clauses for Compact Pattern Representation}", 1020 | author={Abeyrathna, Kuruge Darshana and Granmo, Ole-Christoffer and Goodwin, Morten}, 1021 | booktitle={33rd International Conference on Industrial, Engineering and Other Applications of Applied Intelligent Systems (IEA/AIE 2020)}, 1022 | year={2020}, 1023 | organization={Springer} 1024 | } 1025 | ``` 1026 | 1027 | ```bash 1028 | @InProceedings{phoulady2020weighted, 1029 | author={Adrian {Phoulady} and Ole-Christoffer {Granmo} and Saeed Rahimi {Gorji} and Hady Ahmady {Phoulady}}, 1030 | booktitle={Proceedings of the Ninth International Workshop on Statistical Relational AI (StarAI 2020)}, 1031 | title="{The Weighted Tsetlin Machine: Compressed Representations with Clause Weighting}", 1032 | year={2020} 1033 | } 1034 | ``` 1035 | 1036 | ```bash 1037 | @InProceedings{wheeldon2020pervasive, 1038 | author={Adrian {Wheeldon} and Rishad {Shafik} and Alex {Yakovlev} and Jonathan {Edwards} and Ibrahim {Haddadi} and Ole-Christoffer {Granmo}}, 1039 | booktitle={SCONA Workshop at Design, Automation and Test in Europe (DATE 2020)}, 1040 | title="{Tsetlin Machine: A New Paradigm for Pervasive AI}", 1041 | year={2020} 1042 | } 1043 | ``` 1044 | 1045 | ```bash 1046 | @article{abeyrathna2020nonlinear, 1047 | author={K. Darshana {Abeyrathna} and Ole-Christoffer {Granmo} and Xuan {Zhang} and Lei {Jiao} and Morten {Goodwin}}, 1048 | journal={Philosophical Transactions of the Royal Society A}, 1049 | title="{The Regression Tsetlin Machine - A Novel Approach to Interpretable Non-Linear Regression}", 1050 | volume={378}, issue={2164}, 1051 | year={2020} 1052 | } 1053 | ``` 1054 | 1055 | ```bash 1056 | @InProceedings{gorji2019multigranular, 1057 | author = {Saeed Rahimi {Gorji} and Ole-Christoffer {Granmo} and Adrian {Phoulady} and Morten {Goodwin}}, 1058 | title = "{A Tsetlin Machine with Multigranular Clauses}", 1059 | booktitle="Lecture Notes in Computer Science: Proceedings of the Thirty-ninth International Conference on Innovative Techniques and Applications of Artificial Intelligence (SGAI-2019)", year="2019", 1060 | volume = {11927}, 1061 | publisher="Springer International Publishing" 1062 | } 1063 | ``` 1064 | 1065 | ```bash 1066 | @article{berge2019text, 1067 | author={Geir Thore {Berge} and Ole-Christoffer {Granmo} and Tor Oddbjørn {Tveit} and Morten {Goodwin} and Lei {Jiao} and Bernt Viggo {Matheussen}}, 1068 | journal={IEEE Access}, 1069 | title="{Using the Tsetlin Machine to Learn Human-Interpretable Rules for High-Accuracy Text Categorization with Medical Applications}", 1070 | volume={7}, 1071 | pages={115134-115146}, 1072 | year={2019}, 1073 | doi={10.1109/ACCESS.2019.2935416}, 1074 | ISSN={2169-3536} 1075 | } 1076 | ``` 1077 | 1078 | ```bash 1079 | @article{granmo2019convtsetlin, 1080 | author = {{Granmo}, Ole-Christoffer and {Glimsdal}, Sondre and {Jiao}, Lei and {Goodwin}, Morten and {Omlin}, Christian W. and {Berge}, Geir Thore}, 1081 | title = "{The Convolutional Tsetlin Machine}", 1082 | journal = {arXiv preprint arXiv:1905.09688}, year = {2019}, 1083 | url={https://arxiv.org/abs/1905.09688} 1084 | } 1085 | ``` 1086 | 1087 | ```bash 1088 | @InProceedings{abeyrathna2019regressiontsetlin, 1089 | author = {{Abeyrathna}, Kuruge Darshana and {Granmo}, Ole-Christoffer and {Jiao}, Lei and {Goodwin}, Morten}, 1090 | title = "{The Regression Tsetlin Machine: A Tsetlin Machine for Continuous Output Problems}", 1091 | editor="Moura Oliveira, Paulo and Novais, Paulo and Reis, Lu{\'i}s Paulo ", 1092 | booktitle="Progress in Artificial Intelligence", year="2019", 1093 | publisher="Springer International Publishing", 1094 | pages="268--280" 1095 | } 1096 | ``` 1097 | 1098 | ```bash 1099 | @InProceedings{abeyrathna2019continuousinput, 1100 | author = {{Abeyrathna}, Kuruge Darshana and {Granmo}, Ole-Christoffer and {Zhang}, Xuan and {Goodwin}, Morten}, 1101 | title = "{A Scheme for Continuous Input to the Tsetlin Machine with Applications to Forecasting Disease Outbreaks}", 1102 | booktitle = "{Advances and Trends in Artificial Intelligence. From Theory to Practice}", year = "2019", 1103 | editor = "Wotawa, Franz and Friedrich, Gerhard and Pill, Ingo and Koitz-Hristov, Roxane and Ali, Moonis", 1104 | publisher = "Springer International Publishing", 1105 | pages = "564--578" 1106 | } 1107 | ``` 1108 | 1109 | ```bash 1110 | @article{granmo2018tsetlin, 1111 | author = {{Granmo}, Ole-Christoffer}, 1112 | title = "{The Tsetlin Machine - A Game Theoretic Bandit Driven Approach to Optimal Pattern Recognition with Propositional Logic}", 1113 | journal = {arXiv preprint arXiv:1804.01508}, year = {2018}, 1114 | url={https://arxiv.org/abs/1804.01508} 1115 | } 1116 | ``` 1117 | 1118 | ## Licence 1119 | 1120 | Copyright (c) 2021 Ole-Christoffer Granmo 1121 | 1122 | Permission is hereby granted, free of charge, to any person obtaining a copy 1123 | of this software and associated documentation files (the "Software"), to deal 1124 | in the Software without restriction, including without limitation the rights 1125 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1126 | copies of the Software, and to permit persons to whom the Software is 1127 | furnished to do so, subject to the following conditions: 1128 | 1129 | The above copyright notice and this permission notice shall be included in all 1130 | copies or substantial portions of the Software. 1131 | 1132 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1133 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1134 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1135 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1136 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1137 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1138 | SOFTWARE. 1139 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. pyTsetlinMachineParallel documentation master file, created by 2 | sphinx-quickstart on Wed Dec 13 09:28:23 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to the pyTsetlinMachineParallel documentation 7 | ==================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Content 12 | 13 | Indices and tables 14 | ================== 15 | 16 | * :ref:`genindex` 17 | * :ref:`modindex` 18 | * :ref:`search` 19 | -------------------------------------------------------------------------------- /examples/2DNoisyXORDemo.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python3 2 | 3 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 4 | import numpy as np 5 | 6 | train_data = np.loadtxt("2DNoisyXORTrainingData.txt") 7 | X_train = train_data[:,0:-1].reshape(train_data.shape[0], 4, 4) 8 | Y_train = train_data[:,-1] 9 | 10 | test_data = np.loadtxt("2DNoisyXORTestData.txt") 11 | X_test = test_data[:,0:-1].reshape(test_data.shape[0], 4, 4) 12 | Y_test = test_data[:,-1] 13 | 14 | ctm = MultiClassConvolutionalTsetlinMachine2D(40, 60, 3.9, (2, 2), boost_true_positive_feedback=0) 15 | 16 | ctm.fit(X_train, Y_train, epochs=5000) 17 | 18 | print("Accuracy:", 100*(ctm.predict(X_test) == Y_test).mean()) 19 | 20 | Xi = np.array([[[0,1,1,0], 21 | [1,1,0,1], 22 | [1,0,1,1], 23 | [0,0,0,1]]]) 24 | 25 | print("\nInput Image:\n") 26 | print(Xi) 27 | print("\nPrediction: %d" % (ctm.predict(Xi))) 28 | -------------------------------------------------------------------------------- /examples/2DNoisyXORTrainingData.txt: -------------------------------------------------------------------------------- 1 | 0 1 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 2 | 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 1 3 | 1 1 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 4 | 0 1 1 0 0 0 0 0 0 0 0 1 1 1 0 1 0 5 | 1 1 0 1 0 0 1 0 1 0 0 1 0 0 1 1 1 6 | 0 1 0 1 1 0 1 0 1 1 1 1 0 1 1 1 0 7 | 0 1 0 1 0 1 0 0 1 0 0 0 0 0 1 0 0 8 | 1 1 0 1 0 0 1 1 0 1 1 1 1 0 0 1 0 9 | 1 1 0 0 0 1 0 0 0 1 0 0 0 1 1 1 0 10 | 1 1 1 1 1 0 0 1 0 0 1 1 0 1 1 1 0 11 | 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 1 12 | 1 1 1 1 1 0 0 1 1 0 0 0 0 1 0 0 1 13 | 0 0 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 14 | 0 1 0 0 1 0 1 0 1 1 1 1 0 1 1 0 1 15 | 1 0 0 1 1 1 1 0 1 1 1 1 0 0 0 0 0 16 | 1 0 1 1 0 1 0 1 1 1 1 0 0 0 1 0 0 17 | 0 0 1 1 1 0 1 1 1 0 0 0 0 0 1 1 0 18 | 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 1 1 19 | 0 1 0 1 1 0 1 0 0 0 1 1 1 1 1 1 1 20 | 1 0 1 1 1 1 0 1 1 0 0 1 1 1 1 1 1 21 | 1 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 1 22 | 0 0 0 1 1 1 1 1 0 1 0 1 0 1 1 1 0 23 | 0 0 1 0 1 1 0 1 0 0 0 1 0 0 0 0 0 24 | 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 25 | 0 1 0 0 1 1 0 0 1 0 0 1 1 1 1 1 1 26 | 1 0 1 1 0 1 0 0 0 0 1 1 0 0 0 1 0 27 | 0 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 0 28 | 0 1 0 1 0 0 1 1 1 1 0 0 0 0 1 1 0 29 | 1 0 1 1 0 1 0 0 1 1 0 1 1 1 0 1 1 30 | 1 0 1 0 0 1 0 0 1 1 0 0 0 1 0 1 1 31 | 0 0 0 0 1 1 1 0 1 1 0 1 1 1 0 1 1 32 | 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 33 | 0 1 0 1 1 0 1 0 1 1 0 0 1 0 0 0 1 34 | 1 1 0 1 1 0 1 0 0 0 0 1 0 1 1 0 1 35 | 0 1 1 0 1 0 0 1 0 0 1 1 0 0 1 1 1 36 | 1 0 1 0 1 1 0 0 0 1 0 1 0 0 0 1 1 37 | 1 1 0 1 0 0 1 1 0 0 1 0 0 1 0 1 1 38 | 0 1 1 1 0 0 0 0 0 1 0 1 0 1 0 1 0 39 | 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 40 | 1 1 0 0 1 0 1 0 1 1 0 0 1 0 1 0 1 41 | 1 0 0 1 0 1 1 1 0 0 0 0 1 1 0 0 0 42 | 0 0 0 1 0 1 1 1 0 0 1 1 0 0 1 1 1 43 | 1 0 1 0 0 0 1 1 1 1 1 1 0 0 1 0 1 44 | 1 1 0 1 0 0 1 1 0 0 1 0 0 1 0 0 1 45 | 0 1 1 0 0 0 0 1 1 1 1 1 0 1 0 1 0 46 | 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0 47 | 0 0 1 1 0 1 0 1 0 0 0 1 1 0 0 0 1 48 | 1 0 1 1 0 0 1 1 1 0 1 0 1 0 1 0 0 49 | 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 50 | 0 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 0 51 | 0 1 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 52 | 0 0 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 53 | 1 0 1 1 1 1 0 0 0 0 0 0 1 0 1 0 1 54 | 0 1 1 0 1 0 0 1 1 1 1 0 1 1 1 0 0 55 | 1 0 1 0 0 0 1 0 0 0 0 1 1 0 0 1 0 56 | 0 1 0 1 1 0 1 1 1 0 0 1 0 0 1 0 1 57 | 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 58 | 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 59 | 1 0 1 1 1 0 1 1 1 1 0 1 1 0 0 1 0 60 | 0 0 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 61 | 1 0 1 1 1 0 1 1 0 0 1 0 0 0 1 0 1 62 | 1 1 0 0 1 0 1 1 0 1 1 0 1 1 1 0 1 63 | 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 1 0 64 | 1 0 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 65 | 1 0 1 1 1 0 1 1 1 1 1 0 0 0 0 0 1 66 | 0 1 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1 67 | 0 0 1 0 1 1 0 0 1 1 0 0 1 1 0 1 0 68 | 1 1 0 0 0 0 1 0 0 0 0 1 0 1 1 1 1 69 | 0 0 0 0 0 1 1 0 0 0 1 1 1 0 1 1 1 70 | 1 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 71 | 0 0 1 0 1 1 0 1 1 1 1 1 0 1 0 0 0 72 | 1 1 0 1 0 1 0 1 1 0 1 1 0 0 1 0 1 73 | 1 0 1 1 1 1 0 1 1 1 0 1 1 1 1 1 0 74 | 0 0 0 0 0 1 1 0 1 1 0 1 0 1 1 1 1 75 | 0 0 1 1 1 0 1 0 1 1 0 0 0 1 0 1 1 76 | 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 0 0 77 | 0 1 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 78 | 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 1 79 | 1 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 0 80 | 1 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 81 | 1 1 0 0 1 1 0 1 0 0 1 1 1 1 0 1 0 82 | 1 0 1 0 0 0 1 0 1 0 0 1 1 1 0 0 1 83 | 0 1 0 0 0 0 1 0 1 0 1 1 0 0 1 1 0 84 | 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 1 0 85 | 1 0 0 1 0 1 1 1 1 0 0 1 0 1 0 1 0 86 | 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 1 87 | 0 0 1 0 1 1 0 0 1 0 0 1 0 1 1 0 1 88 | 1 0 0 0 1 1 1 1 0 1 0 0 1 0 1 0 0 89 | 0 0 0 1 1 1 1 0 1 0 1 0 1 0 1 1 0 90 | 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 91 | 0 0 1 1 0 1 0 1 0 0 1 0 0 0 0 0 1 92 | 0 1 1 0 0 0 0 1 1 1 1 1 0 1 1 1 1 93 | 0 1 0 1 0 1 0 0 0 1 0 1 1 0 1 1 1 94 | 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 95 | 1 0 1 0 0 1 0 1 0 1 0 1 1 0 0 0 1 96 | 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 1 1 97 | 0 1 0 1 1 0 1 0 1 0 1 1 0 1 1 0 1 98 | 0 0 1 1 0 0 1 0 0 1 1 1 1 0 0 1 0 99 | 0 1 0 0 0 0 1 1 0 0 1 0 0 0 1 0 1 100 | 0 0 1 0 1 1 0 1 0 1 1 1 1 0 1 1 1 101 | 0 0 1 1 1 1 0 1 1 1 0 0 0 1 0 1 0 102 | 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 103 | 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1 0 1 104 | 1 1 0 1 0 0 1 1 1 0 0 0 0 1 0 0 1 105 | 0 0 1 1 0 1 0 0 1 1 0 1 0 0 0 1 1 106 | 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 1 107 | 1 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1 1 108 | 0 1 0 1 0 1 0 1 1 1 0 1 1 1 0 0 0 109 | 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 110 | 0 1 0 0 1 0 1 1 1 1 0 1 0 0 0 1 0 111 | 1 0 0 1 0 1 1 1 0 0 0 1 0 1 0 1 0 112 | 1 1 0 1 1 1 0 1 1 0 0 0 0 0 1 0 0 113 | 0 1 0 1 1 0 1 1 0 1 1 1 0 1 0 0 1 114 | 0 0 1 1 0 0 1 1 1 0 0 0 0 0 0 1 1 115 | 0 1 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 116 | 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1 117 | 1 0 0 0 0 1 1 1 1 0 0 1 0 1 0 1 1 118 | 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 119 | 1 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 120 | 1 1 0 1 1 0 1 1 0 1 1 1 1 0 0 1 0 121 | 1 1 0 1 0 1 0 0 1 0 0 0 1 1 0 0 0 122 | 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 123 | 1 0 1 0 0 0 1 0 1 1 1 0 1 1 1 0 0 124 | 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 125 | 1 0 1 1 1 1 0 1 0 0 0 0 0 1 1 1 1 126 | 1 1 0 0 0 0 1 1 1 0 0 1 1 0 1 0 0 127 | 1 1 1 1 1 0 0 0 1 1 0 1 1 0 0 1 1 128 | 1 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 129 | 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 1 130 | 1 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 1 131 | 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 0 1 132 | 1 0 1 1 1 0 1 1 1 1 0 1 1 0 0 1 0 133 | 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 0 0 134 | 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 135 | 0 0 1 1 1 0 1 0 0 1 0 0 0 0 1 1 0 136 | 0 1 1 1 0 0 0 0 1 0 0 0 1 1 0 1 0 137 | 1 0 0 1 0 1 1 1 0 0 0 1 0 1 0 0 0 138 | 0 1 0 0 0 1 0 0 1 1 1 1 0 0 0 1 1 139 | 1 1 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 140 | 1 0 1 1 1 0 1 1 1 1 1 1 0 0 1 0 0 141 | 0 0 1 1 1 0 1 0 1 1 0 0 0 1 1 1 0 142 | 0 0 1 0 0 1 0 1 0 1 0 1 1 0 0 0 1 143 | 1 0 0 0 0 1 1 1 0 1 1 0 1 0 1 1 1 144 | 1 0 0 0 0 1 1 1 1 1 1 1 1 0 1 0 0 145 | 1 0 1 1 0 0 1 0 0 0 0 1 1 1 1 1 0 146 | 0 0 1 1 0 1 0 1 1 0 0 1 1 1 0 1 1 147 | 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 1 0 148 | 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 0 1 149 | 1 0 1 0 1 1 0 1 1 1 0 1 0 0 1 0 1 150 | 0 1 0 1 1 0 1 1 0 1 1 0 1 0 0 0 1 151 | 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 0 0 152 | 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 153 | 0 1 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 154 | 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 1 0 155 | 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 156 | 0 0 1 0 0 0 1 0 1 1 0 1 0 0 0 0 0 157 | 1 0 0 1 1 1 1 0 0 1 0 1 0 1 0 1 1 158 | 0 1 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 159 | 1 1 0 1 0 0 1 1 1 1 0 0 0 0 0 1 1 160 | 1 0 0 1 0 1 1 0 0 1 1 1 1 0 1 0 1 161 | 0 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 1 162 | 1 1 0 1 0 0 1 1 1 0 0 1 0 0 1 0 0 163 | 0 1 0 0 1 0 1 1 1 0 0 0 1 1 1 0 0 164 | 0 1 0 1 0 0 1 0 1 0 0 1 1 1 1 1 1 165 | 1 1 0 1 1 1 0 1 1 1 0 0 1 1 1 0 0 166 | 1 0 1 1 1 0 1 0 1 1 1 0 1 1 0 0 1 167 | 0 1 0 0 0 0 1 1 0 1 0 1 1 0 1 1 1 168 | 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 0 1 169 | 0 0 1 0 1 0 1 1 1 0 0 1 0 0 0 0 0 170 | 1 0 1 0 0 1 0 0 0 1 1 0 0 1 1 0 1 171 | 0 0 1 0 1 0 1 0 0 1 1 1 1 1 0 1 0 172 | 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 0 173 | 1 1 0 0 1 1 0 0 1 0 0 0 1 0 1 1 0 174 | 1 1 0 1 1 1 0 1 0 1 1 1 0 0 0 1 0 175 | 1 0 1 0 0 1 0 1 1 0 1 0 0 1 1 0 0 176 | 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 177 | 0 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 178 | 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 179 | 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 180 | 1 1 0 0 0 0 1 0 1 0 0 1 1 0 1 1 1 181 | 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 1 182 | 0 0 1 1 1 1 0 1 1 0 1 1 0 1 0 1 1 183 | 0 0 0 0 0 1 1 1 1 1 1 1 0 1 0 1 1 184 | 1 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1 1 185 | 1 1 0 1 0 0 1 1 0 1 1 1 0 0 0 1 0 186 | 1 0 1 1 1 0 1 1 1 0 0 1 1 0 1 1 0 187 | 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 188 | 1 1 0 0 0 0 1 1 0 1 1 1 0 1 1 1 0 189 | 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 190 | 0 1 0 0 0 0 1 1 0 1 1 1 0 1 1 0 1 191 | 1 0 1 1 0 1 0 0 0 1 1 0 0 1 1 1 0 192 | 1 0 1 0 0 1 0 0 1 1 1 0 0 1 0 0 0 193 | 1 1 0 0 1 1 0 1 1 1 0 1 1 0 1 0 1 194 | 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 195 | 0 0 1 1 1 0 1 0 0 0 1 0 0 1 0 1 0 196 | 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 1 0 197 | 1 1 0 1 0 1 0 1 1 0 1 1 1 1 1 1 0 198 | 0 0 1 1 1 1 0 0 1 0 1 0 1 0 1 1 1 199 | 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 200 | 1 1 0 0 0 1 0 0 1 1 0 0 1 1 1 1 0 201 | 0 1 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 202 | 1 0 1 0 0 0 1 0 0 1 1 1 0 0 0 1 0 203 | 0 1 1 0 1 0 0 1 1 0 0 1 0 0 0 0 0 204 | 1 0 1 0 0 1 0 0 1 0 0 1 0 1 1 0 0 205 | 1 0 0 0 0 1 1 1 1 1 0 1 1 1 0 1 1 206 | 1 1 0 1 0 1 0 1 1 0 0 0 0 1 1 1 0 207 | 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1 1 208 | 1 1 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 209 | 1 1 0 0 0 0 1 1 0 1 1 0 1 0 1 0 1 210 | 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 1 0 211 | 0 0 0 0 1 1 1 1 1 1 1 0 1 1 0 1 0 212 | 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 0 0 213 | 0 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 1 214 | 0 0 1 1 0 1 0 0 0 0 1 0 0 0 1 1 0 215 | 0 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 216 | 1 0 0 1 0 1 1 1 0 0 1 1 1 0 0 1 1 217 | 1 1 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 218 | 0 1 1 0 1 0 0 0 1 1 0 0 1 0 1 0 1 219 | 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 220 | 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 1 221 | 1 0 1 1 0 0 1 1 0 0 1 0 0 1 1 1 0 222 | 1 1 0 0 1 1 0 1 1 0 0 0 0 0 0 1 0 223 | 1 0 1 0 0 0 1 1 1 0 0 1 0 1 1 0 0 224 | 1 1 0 0 0 1 0 0 1 0 1 0 1 0 1 1 1 225 | 1 1 0 1 1 1 0 1 1 0 1 0 0 0 0 0 0 226 | 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 227 | 1 1 0 1 1 0 1 1 0 0 1 1 0 0 0 0 1 228 | 1 1 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 229 | 0 0 1 1 0 1 0 1 0 0 1 1 1 0 0 0 1 230 | 1 0 1 1 0 0 1 1 0 0 0 1 0 1 1 1 1 231 | 0 1 0 1 1 0 1 1 0 0 1 0 0 0 1 1 0 232 | 1 0 1 0 0 1 0 1 1 0 1 0 0 1 1 0 1 233 | 0 0 0 1 1 1 1 1 1 1 1 0 1 1 0 1 0 234 | 1 1 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 235 | 1 0 0 1 1 1 1 0 0 1 1 0 0 0 0 0 1 236 | 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 1 0 237 | 1 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 238 | 1 0 1 1 0 0 1 0 1 1 0 1 1 1 1 1 1 239 | 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 240 | 1 0 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 241 | 1 0 1 1 0 0 1 0 1 1 1 0 0 1 1 0 1 242 | 1 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 243 | 0 0 0 1 1 1 1 1 1 0 0 1 1 0 0 0 0 244 | 1 0 1 1 0 0 1 0 1 0 1 0 1 0 1 1 0 245 | 0 0 1 1 1 0 1 1 0 1 0 0 1 1 0 0 1 246 | 0 0 0 0 1 1 1 0 0 0 1 1 1 1 0 0 0 247 | 1 0 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 248 | 1 1 0 1 0 0 1 0 1 0 0 0 0 0 1 0 0 249 | 0 1 1 1 0 0 0 0 1 0 1 1 1 1 1 0 0 250 | 0 0 1 1 0 1 0 1 1 1 0 1 0 0 0 0 1 251 | 1 1 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 252 | 1 1 0 1 1 0 1 0 0 0 1 0 1 0 1 1 1 253 | 0 1 1 0 1 0 0 0 1 1 0 0 0 1 1 0 1 254 | 1 0 1 1 1 0 1 0 0 0 1 1 0 0 1 0 1 255 | 0 1 0 1 1 1 0 0 1 0 0 0 1 1 0 1 0 256 | 1 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 257 | 1 1 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 258 | 0 0 1 0 0 0 1 1 1 0 0 1 1 1 0 1 0 259 | 0 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 260 | 0 1 1 1 1 0 0 0 0 1 0 0 1 1 1 0 0 261 | 1 1 1 0 1 0 0 0 0 1 1 1 1 0 0 0 0 262 | 1 0 0 0 1 1 1 1 0 0 1 0 1 0 1 1 0 263 | 0 0 1 1 1 0 1 1 0 0 1 0 1 0 0 0 1 264 | 0 0 0 1 0 1 1 1 0 0 1 1 0 0 0 0 1 265 | 1 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0 266 | 0 1 0 0 0 0 1 1 1 1 0 1 0 1 0 1 1 267 | 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 0 1 268 | 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 1 1 269 | 0 0 1 0 1 1 0 1 0 0 1 1 1 1 0 1 1 270 | 1 1 1 0 1 0 0 1 1 1 0 0 0 0 0 0 1 271 | 0 0 1 0 0 1 0 0 0 0 1 0 1 0 1 0 1 272 | 0 0 1 1 0 1 0 1 0 0 0 0 1 1 1 0 1 273 | 1 0 1 0 0 1 0 1 0 0 0 1 1 1 1 1 0 274 | 0 0 1 0 0 1 0 1 0 0 0 1 1 1 0 1 1 275 | 1 1 0 1 0 0 1 0 1 0 1 0 0 1 1 0 1 276 | 1 0 1 1 0 1 0 0 1 1 1 1 0 0 1 0 1 277 | 1 1 0 0 1 1 0 1 1 1 1 1 0 0 0 0 0 278 | 1 1 1 1 0 0 0 0 0 0 0 1 0 1 0 1 1 279 | 1 0 1 0 0 1 0 1 1 1 0 0 0 0 0 1 0 280 | 0 1 1 0 1 0 0 0 1 1 0 1 0 1 1 0 1 281 | 1 1 0 1 1 0 1 1 0 1 1 0 1 0 1 0 1 282 | 1 0 0 0 0 1 1 1 0 1 1 1 1 1 1 0 0 283 | 1 1 0 1 1 0 1 0 0 1 0 1 1 1 1 0 1 284 | 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1 0 285 | 0 1 0 1 1 0 1 0 0 0 0 1 0 1 0 0 0 286 | 0 0 1 0 0 1 0 0 0 0 1 1 1 1 1 0 1 287 | 0 1 0 1 1 0 1 1 1 0 1 1 0 1 0 1 0 288 | 0 1 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 289 | 0 0 1 0 1 1 0 1 0 1 0 0 0 1 1 0 0 290 | 1 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 291 | 1 1 0 1 1 0 1 0 1 0 1 1 1 0 0 1 0 292 | 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 1 1 293 | 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 1 294 | 1 0 1 1 1 1 0 1 0 1 1 1 0 1 0 1 1 295 | 1 0 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 296 | 0 0 0 1 0 1 1 1 0 0 1 0 0 1 1 1 1 297 | 0 0 1 1 1 1 0 1 0 0 1 0 0 0 1 0 0 298 | 1 0 1 0 0 1 0 1 0 1 1 0 1 0 0 0 0 299 | 1 1 1 0 0 0 0 0 1 0 1 1 0 0 0 1 1 300 | 0 1 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 301 | 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 302 | 1 1 0 1 0 0 1 1 1 1 1 1 0 0 0 1 1 303 | 0 0 1 1 1 0 1 1 1 1 0 0 1 0 0 0 0 304 | 1 1 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 305 | 0 0 1 0 1 0 1 0 1 0 0 1 0 1 0 0 0 306 | 1 0 1 0 0 1 0 0 1 1 1 0 1 1 1 0 0 307 | 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1 1 1 308 | 0 1 1 1 0 0 0 0 0 0 1 1 1 0 1 0 0 309 | 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1 0 310 | 1 0 1 1 1 0 1 0 1 0 0 1 1 1 1 0 0 311 | 1 0 1 0 0 0 1 1 0 0 1 1 1 1 0 0 0 312 | 1 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 313 | 1 0 1 0 1 1 0 1 0 0 0 1 0 1 0 1 1 314 | 1 0 1 0 0 1 0 0 1 1 1 0 1 0 0 0 1 315 | 0 0 1 1 0 0 1 1 1 0 1 0 1 1 0 1 0 316 | 0 0 1 1 1 1 0 1 1 0 1 1 0 1 1 0 1 317 | 1 0 1 1 0 1 0 0 0 0 0 0 0 0 1 1 1 318 | 1 1 0 0 0 0 1 0 1 0 0 1 0 1 1 1 1 319 | 1 0 1 0 1 1 0 0 0 0 0 1 0 1 0 0 1 320 | 1 1 0 1 1 0 1 1 0 1 0 1 1 1 1 0 0 321 | 0 0 1 0 0 1 0 0 1 1 0 0 0 0 1 0 1 322 | 0 1 0 1 0 0 1 1 1 1 1 0 0 1 0 0 0 323 | 1 1 1 0 0 0 0 1 0 0 1 1 0 1 0 1 1 324 | 0 1 0 1 0 0 1 1 0 1 1 0 1 1 1 1 0 325 | 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 1 326 | 1 0 1 0 0 1 0 0 0 1 0 0 0 1 1 0 1 327 | 1 1 0 1 0 1 0 0 0 1 1 1 1 1 0 1 0 328 | 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 1 0 329 | 1 1 1 0 1 0 0 1 1 0 1 1 0 0 0 1 0 330 | 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 0 0 331 | 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 1 332 | 1 0 1 1 1 1 0 0 1 0 1 1 1 1 0 0 1 333 | 0 1 0 0 0 0 1 0 1 1 1 1 1 0 0 1 1 334 | 0 0 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 335 | 1 1 0 1 1 1 0 0 1 1 1 1 0 0 0 0 0 336 | 0 0 1 1 1 1 0 1 1 0 1 0 0 0 0 1 1 337 | 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 338 | 1 1 1 1 0 0 0 1 1 1 0 0 0 0 1 0 0 339 | 0 1 0 1 0 0 1 0 0 1 0 1 1 1 0 0 1 340 | 0 0 1 0 1 1 0 0 0 0 0 1 1 1 0 1 1 341 | 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 1 1 342 | 1 0 1 1 1 0 1 1 0 0 1 1 1 1 0 1 0 343 | 0 0 0 1 1 1 1 1 0 0 1 1 0 0 0 0 0 344 | 0 1 0 1 0 0 1 0 1 1 1 1 0 1 0 0 0 345 | 1 1 0 1 0 0 1 1 0 0 0 0 1 0 0 1 1 346 | 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0 1 0 347 | 0 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 348 | 1 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 0 349 | 1 0 1 0 1 1 0 1 0 1 0 1 0 0 0 1 1 350 | 0 0 1 0 1 1 0 1 0 1 1 1 1 1 1 1 1 351 | 0 0 1 0 0 1 0 0 1 1 0 0 1 1 1 1 1 352 | 0 1 0 0 1 0 1 1 1 1 1 0 1 1 0 0 1 353 | 1 1 0 0 1 0 1 0 0 1 1 1 0 1 1 1 0 354 | 1 0 1 1 1 0 1 0 1 0 1 1 1 1 0 1 0 355 | 1 1 0 1 0 0 1 1 0 1 1 0 1 0 1 0 1 356 | 1 0 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0 357 | 1 0 1 1 1 0 1 1 1 0 0 0 0 1 0 1 1 358 | 0 1 1 0 1 0 0 0 1 1 0 1 1 0 0 0 1 359 | 1 0 1 1 0 0 1 0 1 1 1 1 1 1 0 1 1 360 | 1 1 0 0 1 1 0 0 1 1 1 0 1 0 1 1 1 361 | 0 0 1 0 1 1 0 1 1 0 0 0 1 1 0 1 1 362 | 1 1 1 1 0 0 0 0 0 1 1 1 0 1 0 0 1 363 | 0 1 0 0 1 0 1 0 1 1 1 0 0 1 0 0 0 364 | 1 1 0 0 0 0 1 1 0 1 1 0 0 1 0 0 0 365 | 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 366 | 0 0 1 1 1 1 0 0 1 0 0 0 1 1 0 1 1 367 | 0 0 0 1 0 1 1 0 0 1 0 1 1 0 0 1 1 368 | 1 1 0 1 0 0 1 0 0 0 0 1 1 1 1 1 1 369 | 0 1 0 0 1 1 0 1 1 1 1 1 0 1 1 0 1 370 | 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 371 | 0 1 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 372 | 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 1 373 | 0 0 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 374 | 0 0 1 0 1 0 1 0 1 1 1 1 1 1 1 0 1 375 | 1 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 376 | 1 1 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 377 | 1 1 0 1 0 0 1 1 1 1 1 1 0 0 1 1 0 378 | 0 1 1 1 1 0 0 0 0 0 1 0 0 1 1 0 1 379 | 0 0 0 0 0 1 1 1 1 0 1 1 1 0 1 1 1 380 | 1 1 0 1 1 1 0 0 1 1 0 0 0 1 0 1 0 381 | 0 0 1 1 0 0 1 1 0 0 1 0 1 1 0 1 0 382 | 1 1 0 1 0 0 1 1 0 1 1 0 1 0 0 1 1 383 | 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 0 0 384 | 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 385 | 0 0 1 1 0 0 1 1 1 0 1 1 0 1 0 0 0 386 | 1 1 0 0 0 0 1 1 1 0 1 1 0 0 1 0 1 387 | 0 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 0 388 | 1 1 0 1 0 1 0 0 0 0 1 1 0 0 1 0 1 389 | 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 1 390 | 0 0 0 0 1 1 1 0 1 1 0 1 0 1 1 1 0 391 | 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 1 392 | 0 1 1 1 0 0 0 0 1 0 0 0 0 0 1 0 0 393 | 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 1 394 | 1 1 0 1 1 1 0 1 0 1 1 0 1 0 1 0 0 395 | 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 0 396 | 1 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 397 | 1 0 1 1 1 1 0 1 1 1 1 0 1 0 1 0 1 398 | 0 0 1 1 1 1 0 0 0 0 1 0 1 1 0 0 1 399 | 0 1 0 1 0 0 1 1 0 1 1 1 0 1 0 0 1 400 | 1 1 1 1 0 0 0 1 1 0 1 1 1 0 1 1 1 401 | 0 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 402 | 0 1 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0 403 | 1 1 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 404 | 1 1 0 1 1 0 1 0 1 1 0 1 0 0 1 1 1 405 | 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 0 1 406 | 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 1 407 | 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 0 408 | 0 0 1 0 0 1 0 1 0 1 1 0 0 1 1 1 1 409 | 1 1 0 0 1 0 1 1 1 0 1 0 0 0 0 1 1 410 | 0 0 1 1 1 0 1 0 0 0 0 0 0 1 0 1 1 411 | 1 1 0 0 1 0 1 1 1 1 1 1 0 1 0 1 1 412 | 0 0 1 1 0 1 0 0 1 1 1 0 1 1 0 0 0 413 | 0 1 0 0 1 1 0 0 1 0 0 1 0 1 1 0 0 414 | 0 1 1 0 0 0 0 1 0 0 1 0 1 0 1 0 1 415 | 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 1 0 416 | 1 1 1 1 1 0 0 1 0 0 1 0 1 1 1 0 0 417 | 1 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 0 418 | 0 1 0 0 0 0 1 0 0 1 1 0 1 0 0 1 1 419 | 0 1 0 0 1 0 1 0 1 0 1 1 0 0 1 0 0 420 | 1 1 1 0 1 0 0 1 1 0 0 0 0 1 0 1 1 421 | 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 422 | 1 1 1 1 0 0 0 1 0 0 0 1 0 1 1 0 0 423 | 0 1 0 1 1 0 1 0 0 1 1 1 0 0 0 1 0 424 | 1 1 0 1 1 0 1 1 0 1 0 0 0 1 1 0 1 425 | 0 0 1 0 0 0 1 0 1 1 0 1 0 1 0 1 0 426 | 1 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1 0 427 | 1 1 0 1 0 1 0 1 1 0 0 0 0 0 0 1 0 428 | 0 0 1 1 1 0 1 0 1 0 0 1 0 1 0 0 0 429 | 0 1 1 1 0 0 0 1 1 0 1 1 0 1 1 0 1 430 | 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 1 431 | 1 0 1 0 0 0 1 0 0 1 1 1 0 0 0 1 0 432 | 1 0 1 0 0 1 0 0 1 1 1 1 1 1 0 1 1 433 | 0 0 1 0 1 1 0 0 1 0 0 0 0 1 1 0 0 434 | 0 1 0 1 0 1 0 1 1 1 1 0 1 0 0 0 1 435 | 0 1 0 0 0 0 1 0 1 1 1 0 1 0 1 0 0 436 | 0 0 0 1 0 1 1 0 0 0 1 1 1 0 0 1 0 437 | 1 1 0 1 0 0 1 1 0 1 1 1 1 1 1 1 1 438 | 0 0 1 1 0 1 0 1 0 1 0 0 1 1 0 1 0 439 | 1 0 1 1 1 1 0 1 0 1 0 0 0 1 1 1 0 440 | 1 1 0 1 0 0 1 0 0 1 1 0 1 1 0 1 1 441 | 0 0 1 0 1 1 0 0 0 0 0 1 0 0 1 0 0 442 | 1 0 0 0 0 1 1 0 1 1 1 1 0 1 1 0 1 443 | 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 0 444 | 1 1 0 0 0 1 0 1 0 1 1 0 1 0 1 1 1 445 | 1 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 0 446 | 0 1 0 0 1 0 1 0 0 0 0 1 1 1 1 1 0 447 | 0 1 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 448 | 0 1 0 0 1 1 0 0 1 0 0 0 1 1 1 0 0 449 | 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 1 450 | 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 1 0 451 | 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 452 | 0 0 0 1 1 1 1 0 1 1 0 1 0 0 0 0 1 453 | 1 0 1 0 1 1 0 1 1 0 1 1 0 0 0 1 0 454 | 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 0 1 455 | 0 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 456 | 1 1 1 0 0 0 0 0 1 1 0 0 1 1 0 1 0 457 | 1 0 1 1 0 0 1 1 1 0 0 0 0 0 1 0 0 458 | 0 1 0 1 0 0 1 0 0 1 1 1 1 1 0 0 1 459 | 1 0 0 1 1 1 1 0 0 1 0 1 1 1 1 1 0 460 | 1 1 0 0 1 0 1 1 1 1 0 0 0 0 1 1 0 461 | 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 1 462 | 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0 1 0 463 | 1 1 1 0 0 0 0 1 0 1 1 0 1 1 0 1 0 464 | 1 1 0 1 0 0 1 1 0 1 1 1 0 1 0 1 0 465 | 0 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 466 | 0 1 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 467 | 0 1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 0 468 | 0 0 1 0 1 1 0 0 1 1 0 0 1 0 0 1 0 469 | 1 1 1 1 1 0 0 0 0 1 0 1 1 0 0 1 1 470 | 1 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 0 471 | 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 472 | 1 0 1 1 0 0 1 1 1 0 1 1 0 0 0 0 1 473 | 1 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 474 | 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 0 1 475 | 1 1 0 1 1 0 1 0 0 1 1 1 0 0 1 0 1 476 | 0 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 1 477 | 0 0 1 1 0 0 1 1 0 1 0 1 1 1 1 0 1 478 | 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1 1 0 479 | 1 1 0 1 0 0 1 0 1 0 1 0 1 1 0 0 0 480 | 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 1 1 481 | 1 1 0 1 0 0 1 1 0 0 0 0 1 1 0 1 1 482 | 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 1 0 483 | 0 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 1 484 | 1 1 0 1 0 0 1 1 1 1 1 1 0 0 0 0 1 485 | 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 486 | 0 1 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1 487 | 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 488 | 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 489 | 1 1 0 0 0 1 0 1 0 0 1 0 1 0 1 1 1 490 | 1 1 0 0 1 0 1 1 0 0 1 0 0 1 1 1 1 491 | 1 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 1 492 | 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 493 | 1 1 0 1 0 0 1 0 1 0 0 1 1 1 1 1 1 494 | 0 0 1 1 0 1 0 0 0 1 1 0 0 1 1 0 0 495 | 1 0 0 0 1 1 1 1 0 1 0 0 1 0 1 0 1 496 | 1 1 0 1 0 0 1 1 1 0 0 0 1 1 0 1 0 497 | 1 0 1 0 1 1 0 1 1 0 0 1 1 0 1 0 0 498 | 1 1 0 1 0 1 0 1 0 0 0 0 1 0 0 1 1 499 | 0 0 1 0 0 1 0 1 0 0 1 0 1 1 1 1 1 500 | 1 0 1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 501 | 1 1 0 0 1 0 1 1 1 0 1 0 0 1 0 1 1 502 | 1 0 0 0 0 1 1 1 0 1 1 1 0 1 1 0 0 503 | 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 1 0 504 | 0 0 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 505 | 1 0 1 0 0 0 1 0 0 1 0 1 1 1 0 1 0 506 | 1 0 0 0 1 1 1 0 1 0 1 0 1 0 0 1 0 507 | 1 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 1 508 | 1 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 0 509 | 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 0 510 | 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 0 511 | 0 0 0 0 0 1 1 0 0 0 1 1 0 1 1 1 0 512 | 0 1 0 1 1 0 1 1 0 1 1 0 0 0 1 1 1 513 | 0 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 514 | 0 0 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 515 | 0 0 1 0 0 0 1 1 0 0 1 1 0 1 0 0 1 516 | 0 0 1 1 0 1 0 0 0 1 1 1 0 0 1 1 1 517 | 1 1 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 518 | 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0 1 1 519 | 1 1 0 0 0 1 0 0 1 1 0 0 0 1 1 1 1 520 | 0 1 0 1 0 0 1 0 1 1 0 0 0 0 0 1 1 521 | 1 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 522 | 0 0 1 1 0 0 1 1 0 1 0 1 0 0 0 0 0 523 | 0 1 1 0 1 0 0 1 0 0 0 1 1 0 1 0 0 524 | 1 1 1 1 1 0 0 0 1 0 0 1 0 0 1 0 0 525 | 1 1 0 0 1 1 0 0 1 1 1 0 1 1 0 1 1 526 | 1 0 0 1 1 1 1 0 1 0 0 0 0 1 1 1 1 527 | 1 1 0 1 1 0 1 0 1 0 1 1 0 0 1 0 1 528 | 0 1 0 1 1 0 1 1 1 1 0 1 0 1 0 1 0 529 | 0 0 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 530 | 1 1 0 0 0 1 0 1 1 1 0 1 0 1 0 1 0 531 | 1 1 0 0 0 0 1 0 0 1 0 1 1 0 1 1 1 532 | 1 0 1 0 1 0 1 1 0 0 1 1 1 0 0 1 1 533 | 1 0 0 1 1 1 1 1 0 0 0 0 0 1 1 0 0 534 | 0 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 0 535 | 0 0 1 1 1 0 1 1 1 1 0 1 1 0 0 1 1 536 | 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 1 537 | 1 1 0 1 1 0 1 1 0 1 1 1 0 0 0 0 0 538 | 1 1 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 539 | 1 0 1 0 1 1 0 1 0 1 1 0 1 1 0 1 1 540 | 1 1 0 0 1 0 1 1 0 1 0 1 0 0 0 1 1 541 | 1 1 0 1 0 0 1 0 1 0 1 1 0 1 1 0 0 542 | 0 1 0 1 1 0 1 1 0 1 1 1 0 1 1 1 0 543 | 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 1 544 | 0 1 0 0 0 0 1 0 1 1 0 0 1 0 1 1 1 545 | 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 0 546 | 0 1 1 1 0 0 0 1 0 0 1 1 1 1 0 0 0 547 | 1 1 0 1 1 1 0 1 0 1 0 1 1 0 0 1 0 548 | 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 549 | 1 0 1 0 0 1 0 1 0 1 0 0 1 1 1 0 1 550 | 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 551 | 1 0 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 552 | 1 0 1 0 0 1 0 0 0 0 0 0 1 1 1 1 0 553 | 0 1 0 1 1 0 1 1 1 0 1 1 1 0 1 1 1 554 | 0 0 0 1 0 1 1 0 0 0 1 1 1 1 0 1 1 555 | 0 1 0 1 1 0 1 1 1 1 0 1 0 1 0 0 0 556 | 1 0 1 1 0 0 1 1 1 0 0 1 0 1 0 1 1 557 | 1 0 1 1 0 0 1 1 0 0 1 1 1 0 1 1 1 558 | 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 1 0 559 | 0 1 0 1 1 0 1 1 0 1 0 0 1 0 1 0 1 560 | 0 1 0 1 0 0 1 1 1 1 0 1 1 1 0 1 1 561 | 0 0 0 0 0 1 1 1 0 0 1 0 0 1 1 1 0 562 | 0 1 0 0 0 0 1 1 1 1 0 1 0 0 1 0 0 563 | 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 0 1 564 | 0 1 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 565 | 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 0 566 | 0 1 0 0 0 0 1 1 0 1 0 1 0 0 1 1 0 567 | 0 1 0 1 0 0 1 0 1 0 0 1 0 1 1 0 0 568 | 1 1 1 1 1 0 0 0 1 1 1 0 1 1 1 1 0 569 | 0 0 1 0 1 0 1 1 1 1 1 0 1 0 1 0 1 570 | 0 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 571 | 0 1 0 0 0 1 0 0 1 1 0 1 0 0 1 0 1 572 | 1 0 1 0 0 1 0 0 0 1 0 1 0 1 1 0 1 573 | 1 0 1 0 0 1 0 1 0 0 1 1 0 1 1 1 1 574 | 1 0 1 0 1 1 0 1 1 0 0 1 1 1 1 1 1 575 | 0 1 1 1 0 0 0 1 0 0 1 1 1 0 1 0 1 576 | 0 1 1 0 1 0 0 1 1 0 1 1 1 0 0 0 1 577 | 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1 1 1 578 | 1 1 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 579 | 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 1 0 580 | 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 1 0 581 | 0 0 1 0 0 0 1 1 1 1 0 1 0 0 1 1 0 582 | 1 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 0 583 | 1 1 0 0 1 1 0 1 0 0 1 1 1 1 1 0 1 584 | 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 0 1 585 | 0 1 0 0 1 0 1 0 1 1 1 0 1 1 1 1 1 586 | 0 0 0 0 1 1 1 0 0 0 0 1 0 1 0 0 1 587 | 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 588 | 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 1 589 | 1 0 1 0 0 1 0 1 1 0 0 1 0 0 1 1 0 590 | 1 1 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 591 | 1 0 0 0 1 1 1 1 0 1 1 0 1 0 0 1 1 592 | 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 593 | 1 0 1 1 0 1 0 1 0 1 1 0 0 1 1 1 1 594 | 1 1 0 0 0 0 1 0 1 0 0 1 1 0 0 0 0 595 | 1 1 0 1 1 0 1 1 1 1 1 0 0 0 1 1 0 596 | 0 1 0 0 1 0 1 1 0 0 1 1 0 0 0 0 1 597 | 1 0 1 1 0 0 1 1 0 0 0 0 1 0 0 1 1 598 | 0 0 0 0 1 1 1 1 1 1 0 1 1 0 0 0 0 599 | 0 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 1 600 | 0 1 1 0 1 0 0 0 1 1 0 1 1 1 0 0 0 601 | 1 0 1 1 1 1 0 1 0 1 0 1 1 0 0 1 1 602 | 1 0 1 0 1 0 1 1 0 0 0 1 0 1 1 0 1 603 | 0 0 1 0 0 1 0 0 1 1 0 1 0 0 0 0 1 604 | 0 0 1 0 0 0 1 1 0 1 0 0 0 0 0 1 0 605 | 0 0 1 1 1 1 0 0 1 0 0 1 0 1 1 0 1 606 | 1 0 1 1 1 1 0 1 1 0 1 0 1 0 1 1 0 607 | 0 1 0 0 1 0 1 1 1 0 0 0 1 1 0 0 0 608 | 1 1 0 0 1 0 1 0 1 1 1 1 0 1 1 0 1 609 | 0 0 0 1 0 1 1 1 1 1 0 1 0 1 1 1 0 610 | 0 0 1 1 0 1 0 1 0 1 0 1 1 1 0 1 1 611 | 1 1 0 1 1 1 0 1 1 0 1 1 0 0 1 0 1 612 | 0 1 0 0 1 1 0 1 1 1 0 0 0 0 1 0 1 613 | 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 614 | 0 1 0 0 1 0 1 1 0 0 1 0 0 0 1 1 0 615 | 1 1 0 0 1 1 0 1 0 1 0 0 1 0 0 1 1 616 | 1 0 1 1 0 1 0 1 0 0 0 0 0 1 1 1 0 617 | 1 0 1 1 0 1 0 0 1 1 0 0 0 1 1 1 0 618 | 0 1 0 1 0 0 1 1 0 0 1 1 1 0 1 0 1 619 | 1 1 0 1 0 1 0 1 0 0 0 0 0 1 1 1 0 620 | 0 1 1 0 0 0 0 1 1 0 0 1 0 0 0 1 0 621 | 0 0 1 0 1 1 0 0 0 0 0 0 1 0 1 0 1 622 | 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1 623 | 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 624 | 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 1 0 625 | 0 0 1 1 1 0 1 1 1 1 1 0 0 1 0 0 1 626 | 1 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 1 627 | 0 1 0 1 1 0 1 1 1 1 1 1 0 0 1 0 1 628 | 0 0 1 1 1 1 0 1 1 0 0 1 0 0 0 1 0 629 | 0 0 0 1 1 1 1 1 1 0 1 0 1 0 0 0 0 630 | 0 0 0 0 1 1 1 1 0 1 1 0 1 1 1 0 1 631 | 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 0 0 632 | 1 1 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 633 | 1 0 1 1 1 0 1 1 0 0 1 0 1 0 0 1 0 634 | 0 0 1 1 1 1 0 1 0 0 0 0 0 1 1 1 0 635 | 0 1 0 1 0 0 1 0 0 1 0 1 1 1 0 0 0 636 | 0 1 1 1 1 0 0 1 1 0 0 1 1 1 1 1 0 637 | 0 1 1 0 1 0 0 1 0 0 0 1 1 0 1 0 0 638 | 0 0 1 1 1 1 0 1 0 1 1 0 0 1 1 0 0 639 | 0 0 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 640 | 1 0 1 1 1 0 1 0 0 0 1 1 1 1 1 0 0 641 | 1 0 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 642 | 1 1 0 0 1 0 1 1 0 1 0 1 1 0 1 0 1 643 | 1 0 0 1 0 1 1 1 1 0 1 1 1 0 1 1 0 644 | 0 1 0 0 1 1 0 0 1 0 1 0 1 1 0 0 0 645 | 1 1 0 1 0 1 0 0 0 1 1 1 1 0 0 0 1 646 | 1 0 1 1 0 1 0 0 1 0 0 1 1 1 1 0 1 647 | 1 1 0 0 1 0 1 1 0 0 0 1 0 1 1 0 1 648 | 0 1 1 1 1 0 0 0 1 1 0 0 0 0 1 1 0 649 | 1 0 1 1 0 1 0 0 0 1 1 0 1 1 1 0 0 650 | 0 1 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 651 | 1 1 0 1 0 1 0 0 1 0 1 1 0 0 0 0 0 652 | 1 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 653 | 0 0 1 0 1 1 0 1 0 0 1 1 0 0 1 0 1 654 | 1 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 1 655 | 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1 0 0 656 | 0 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 0 657 | 0 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 0 658 | 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 0 0 659 | 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 1 1 660 | 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 1 1 661 | 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 662 | 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 1 0 663 | 1 0 1 1 0 1 0 0 0 1 1 1 0 1 1 0 0 664 | 1 1 0 0 0 0 1 1 0 1 1 1 1 1 1 1 0 665 | 1 0 1 1 0 1 0 0 1 1 1 1 1 0 1 1 0 666 | 1 1 0 0 1 1 0 1 1 0 0 0 1 0 1 0 0 667 | 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 1 0 668 | 0 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 669 | 0 1 1 0 1 0 0 0 1 1 0 0 1 1 0 0 0 670 | 1 1 0 1 0 0 1 0 0 1 1 1 0 0 0 0 0 671 | 0 1 0 0 0 0 1 0 0 1 0 1 0 0 1 1 0 672 | 0 1 0 1 1 1 0 1 1 0 0 0 0 1 1 1 0 673 | 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 674 | 0 1 1 0 1 0 0 1 0 1 1 0 0 0 1 1 0 675 | 1 1 1 0 1 0 0 0 0 0 0 1 0 1 1 1 1 676 | 0 1 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 677 | 1 0 0 1 1 1 1 1 1 0 1 0 0 1 1 0 1 678 | 0 0 1 0 1 1 0 1 0 1 1 1 0 1 1 0 1 679 | 1 0 0 1 1 1 1 1 0 0 0 1 1 1 0 1 0 680 | 0 0 1 1 1 0 1 1 1 1 0 0 1 0 0 0 0 681 | 0 1 0 1 0 0 1 1 0 0 1 0 1 0 1 1 0 682 | 1 0 1 1 1 1 0 0 1 0 0 1 1 1 0 0 0 683 | 0 1 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 684 | 0 0 1 1 0 1 0 1 0 0 0 0 0 1 1 0 0 685 | 0 1 0 0 0 0 1 1 1 0 1 1 1 1 1 1 1 686 | 1 1 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 687 | 0 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 1 688 | 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 0 689 | 0 1 1 1 0 0 0 0 1 1 1 1 1 1 0 1 1 690 | 0 1 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 691 | 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 0 692 | 0 0 1 1 0 0 1 1 0 1 1 1 0 1 1 0 0 693 | 0 0 1 1 0 1 0 1 0 1 1 0 0 1 0 1 1 694 | 0 1 0 1 1 1 0 1 0 0 1 0 0 1 0 0 1 695 | 0 1 1 0 0 0 0 1 1 1 1 0 0 1 0 1 1 696 | 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 1 1 697 | 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 698 | 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 0 1 699 | 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 700 | 0 1 0 1 1 0 1 1 1 1 1 0 1 0 0 1 1 701 | 0 0 0 0 1 1 1 0 0 1 0 1 0 1 0 1 1 702 | 0 0 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 703 | 1 1 0 0 0 0 1 1 0 1 1 0 1 1 1 1 0 704 | 0 1 0 0 1 0 1 1 0 0 1 1 1 1 0 0 1 705 | 0 1 0 0 1 0 1 1 0 0 1 0 0 1 1 0 0 706 | 1 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 1 707 | 1 0 1 0 1 1 0 1 1 0 1 1 1 0 0 1 0 708 | 1 0 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 709 | 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 0 0 710 | 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 0 1 711 | 0 1 1 1 1 0 0 0 1 0 1 0 1 1 0 1 0 712 | 1 1 0 0 1 1 0 1 0 1 1 0 1 1 0 1 1 713 | 0 0 1 0 1 0 1 1 1 0 1 1 1 1 0 1 1 714 | 1 1 0 1 1 0 1 0 0 1 0 1 0 0 1 0 1 715 | 1 0 1 1 0 0 1 0 0 1 0 1 1 1 1 1 1 716 | 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 1 0 717 | 0 0 1 0 0 1 0 0 0 0 0 1 1 0 1 1 0 718 | 0 0 1 1 0 1 0 1 1 0 1 0 1 1 1 0 0 719 | 0 0 1 1 1 1 0 0 0 0 0 1 1 0 1 0 1 720 | 1 1 0 0 0 1 0 0 0 1 0 0 1 1 1 0 0 721 | 0 1 0 1 1 1 0 0 0 0 1 1 0 1 1 1 1 722 | 0 0 1 1 1 1 0 1 0 1 0 1 0 0 0 1 1 723 | 0 0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 1 724 | 1 0 0 1 1 1 1 1 0 0 1 1 0 0 1 0 0 725 | 1 1 1 1 0 0 0 1 0 1 0 0 0 1 1 1 1 726 | 1 1 1 0 1 0 0 1 0 1 1 0 0 0 1 1 1 727 | 0 1 1 1 0 0 0 0 0 1 1 1 0 0 1 1 1 728 | 0 0 1 0 0 0 1 1 1 0 1 1 1 0 0 0 0 729 | 1 0 1 1 0 0 1 0 0 0 0 0 0 1 0 1 0 730 | 0 0 1 0 1 1 0 1 1 0 1 1 1 0 1 0 1 731 | 1 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 1 732 | 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 733 | 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 1 1 734 | 0 1 0 1 0 0 1 1 0 0 1 0 0 0 0 1 1 735 | 0 1 1 1 1 0 0 0 1 1 0 1 0 1 1 0 0 736 | 0 1 0 0 1 1 0 0 1 0 1 1 1 1 0 1 1 737 | 1 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 738 | 0 1 1 0 1 0 0 0 0 1 1 1 1 1 0 1 0 739 | 1 0 1 0 0 1 0 1 0 0 0 1 1 1 1 0 1 740 | 1 0 1 0 0 1 0 0 1 1 1 0 0 0 0 0 1 741 | 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 1 742 | 1 0 0 1 1 1 1 1 0 1 1 1 0 1 1 0 0 743 | 0 1 0 0 0 0 1 1 0 0 1 1 0 1 0 0 0 744 | 0 1 0 1 0 0 1 1 1 1 0 0 1 1 1 0 1 745 | 0 1 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 746 | 0 1 0 1 0 1 0 1 1 1 0 0 0 1 1 0 0 747 | 1 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 748 | 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 749 | 1 0 1 0 0 1 0 1 0 1 0 1 0 0 0 0 1 750 | 0 1 0 1 1 0 1 0 1 1 1 1 1 1 0 0 1 751 | 0 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 752 | 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 753 | 0 0 1 1 1 1 0 1 0 0 1 0 1 1 1 0 0 754 | 1 0 1 0 1 0 1 1 0 1 1 0 0 1 1 1 0 755 | 1 1 0 0 0 0 1 0 1 0 0 1 0 1 1 0 1 756 | 0 0 1 1 1 1 0 1 1 0 0 1 0 1 0 0 1 757 | 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 758 | 1 1 1 0 0 0 0 0 1 1 0 1 0 1 0 1 0 759 | 1 0 1 1 1 1 0 1 0 0 0 0 1 1 0 0 1 760 | 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 761 | 1 1 0 0 1 0 1 0 0 1 1 1 0 0 0 0 1 762 | 0 0 1 0 1 1 0 1 0 0 1 1 0 0 0 1 1 763 | 0 0 1 1 1 1 0 1 1 0 1 1 1 0 0 0 0 764 | 0 1 0 1 0 1 0 1 1 1 0 1 1 1 1 1 1 765 | 0 1 0 1 0 1 0 0 1 0 0 1 1 0 1 0 1 766 | 1 0 0 0 1 1 1 1 0 0 1 1 0 0 0 1 1 767 | 1 0 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 768 | 1 0 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 769 | 1 0 1 1 1 1 0 1 1 0 1 0 0 0 0 1 1 770 | 1 1 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1 771 | 1 0 1 0 0 1 0 1 1 0 0 1 1 0 0 0 0 772 | 0 0 0 1 0 1 1 0 1 0 1 1 1 0 1 1 0 773 | 1 0 1 0 1 1 0 0 0 0 0 0 1 1 1 1 0 774 | 1 1 0 1 0 0 1 1 0 0 0 0 0 0 1 1 1 775 | 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 1 0 776 | 0 1 1 0 0 0 0 1 1 1 1 0 1 0 1 0 1 777 | 0 0 1 1 0 1 0 0 1 0 0 0 1 1 1 0 0 778 | 1 0 1 0 1 1 0 0 1 0 1 1 0 0 1 0 1 779 | 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 780 | 1 1 0 0 0 0 1 1 1 1 1 0 0 1 0 0 1 781 | 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 0 0 782 | 0 0 0 1 1 1 1 1 0 1 1 0 0 1 0 0 1 783 | 0 1 0 0 0 1 0 0 1 0 1 1 1 0 1 1 0 784 | 1 1 0 0 1 0 1 0 1 1 0 0 1 0 1 0 0 785 | 1 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 0 786 | 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 1 0 787 | 1 1 0 1 1 0 1 0 1 1 1 1 0 0 1 0 0 788 | 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 789 | 1 1 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 790 | 0 1 1 0 1 0 0 1 0 0 1 0 1 1 1 0 0 791 | 1 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 792 | 0 0 1 0 1 0 1 1 0 1 1 0 1 1 0 0 1 793 | 1 0 1 1 1 1 0 1 1 1 1 1 0 0 1 0 1 794 | 1 0 1 1 1 1 0 0 1 0 0 0 0 1 0 0 0 795 | 1 0 1 1 0 1 0 0 1 1 1 0 1 0 0 1 0 796 | 1 1 0 0 1 0 1 1 1 1 1 0 0 1 1 1 0 797 | 1 0 0 0 1 1 1 1 0 0 0 0 1 1 0 0 1 798 | 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 799 | 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 0 0 800 | 1 1 0 0 1 0 1 1 1 0 0 0 0 1 0 0 1 801 | 1 0 1 1 1 0 1 1 0 0 1 1 0 0 1 0 1 802 | 0 0 1 1 1 1 0 0 1 1 1 0 1 0 0 1 1 803 | 1 0 0 0 1 1 1 1 0 1 1 0 1 1 1 1 0 804 | 0 1 0 1 0 0 1 0 1 1 0 0 1 0 1 0 1 805 | 0 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1 1 806 | 0 0 0 1 1 1 1 0 1 0 0 0 1 1 1 0 0 807 | 1 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1 0 808 | 0 1 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0 809 | 1 0 1 1 1 0 1 0 0 0 0 0 1 1 1 1 1 810 | 1 0 1 1 0 1 0 1 0 0 0 1 1 1 1 0 0 811 | 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 812 | 1 1 0 0 1 0 1 1 1 1 0 0 0 1 1 0 0 813 | 1 0 0 0 1 1 1 1 0 0 1 1 1 0 1 1 1 814 | 0 0 1 1 1 0 1 1 1 0 0 0 0 0 1 1 1 815 | 0 0 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0 816 | 0 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 817 | 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0 1 1 818 | 0 1 1 1 1 0 0 0 1 0 1 1 1 0 0 1 0 819 | 0 1 1 1 0 0 0 0 0 0 1 0 1 0 1 0 0 820 | 0 0 0 1 1 1 1 1 1 0 1 0 1 1 0 0 1 821 | 1 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 1 822 | 0 1 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 823 | 0 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 824 | 1 1 0 1 1 0 1 1 0 1 0 1 0 1 0 0 0 825 | 0 1 1 0 0 0 0 1 1 0 1 0 1 1 0 1 0 826 | 0 0 1 1 1 0 1 0 1 1 1 1 1 1 1 1 1 827 | 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 828 | 0 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 829 | 1 1 0 0 1 0 1 0 1 1 0 0 0 0 1 1 1 830 | 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 1 831 | 1 0 1 1 0 1 0 0 0 0 0 1 1 1 1 1 1 832 | 0 1 1 0 1 0 0 1 0 0 0 1 1 0 1 0 0 833 | 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 834 | 0 0 1 0 0 1 0 1 1 0 0 0 0 1 1 1 0 835 | 1 1 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 836 | 1 0 1 1 0 1 0 0 0 1 1 1 1 0 0 0 1 837 | 1 0 1 1 0 1 0 0 0 0 1 1 0 1 1 1 0 838 | 0 0 1 1 0 1 0 1 0 1 1 1 1 1 1 0 0 839 | 0 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 840 | 0 0 1 1 1 1 0 0 1 0 0 0 0 1 1 1 1 841 | 1 0 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0 842 | 1 0 1 1 0 1 0 1 0 0 1 1 0 1 0 0 0 843 | 1 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 0 844 | 0 1 0 1 1 0 1 1 0 0 0 1 0 1 1 0 0 845 | 1 0 1 0 0 0 1 1 0 1 0 0 1 0 1 1 0 846 | 0 0 1 1 0 1 0 0 0 0 1 0 1 0 1 1 1 847 | 1 1 1 0 0 0 0 1 1 1 0 1 1 0 1 0 0 848 | 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 1 849 | 1 1 0 1 0 0 1 0 1 1 0 1 1 0 0 0 1 850 | 0 0 1 1 1 1 0 1 1 1 0 0 0 0 0 1 1 851 | 1 1 0 1 0 0 1 1 0 1 1 1 0 1 1 1 0 852 | 0 1 1 0 1 0 0 0 1 0 0 1 1 1 1 1 1 853 | 1 0 1 1 1 0 1 0 1 1 0 1 1 0 0 0 1 854 | 1 1 0 0 0 1 0 1 1 0 1 0 1 0 1 1 1 855 | 1 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 856 | 1 0 1 0 0 1 0 0 0 1 0 1 1 1 1 0 1 857 | 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 858 | 1 1 0 1 0 0 1 1 0 1 0 1 1 0 1 1 1 859 | 1 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 1 860 | 0 1 0 1 0 0 1 0 1 0 1 0 0 0 1 1 0 861 | 0 0 1 0 1 1 0 1 1 0 1 1 0 1 1 0 0 862 | 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 1 863 | 1 1 1 0 0 0 0 0 1 0 1 0 1 1 1 0 0 864 | 1 0 1 1 1 1 0 0 1 0 0 0 1 1 0 1 0 865 | 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 1 1 866 | 0 0 0 1 0 1 1 1 1 0 0 1 0 0 0 1 0 867 | 0 0 1 1 0 0 1 1 0 0 0 0 0 0 1 1 0 868 | 1 0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0 869 | 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 1 1 870 | 1 1 0 1 1 0 1 1 1 1 0 1 0 0 0 1 1 871 | 1 0 1 1 1 0 1 1 1 0 0 1 1 0 0 0 1 872 | 1 0 1 0 1 1 0 1 1 0 0 1 1 1 1 1 1 873 | 1 1 0 1 1 1 0 1 1 0 1 0 1 1 1 0 0 874 | 0 0 1 1 0 1 0 0 1 1 1 1 0 1 0 0 1 875 | 1 0 1 1 0 1 0 0 0 0 0 1 0 0 1 0 1 876 | 1 1 1 0 1 0 0 0 0 0 1 1 0 1 0 1 0 877 | 0 0 1 0 1 1 0 1 0 0 1 0 1 0 0 0 1 878 | 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 879 | 0 1 0 1 1 0 1 0 0 0 1 1 1 0 1 0 0 880 | 1 0 0 0 0 1 1 0 0 1 1 1 1 1 0 0 0 881 | 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 0 1 882 | 1 1 0 0 1 0 1 0 0 0 1 1 1 0 0 0 0 883 | 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 0 884 | 1 0 1 0 0 0 1 0 0 0 1 0 0 1 1 0 0 885 | 1 1 0 1 1 1 0 0 1 0 0 0 0 0 0 1 0 886 | 1 0 1 0 0 1 0 1 1 0 0 0 1 1 0 1 1 887 | 1 1 0 1 0 0 1 1 0 1 0 0 1 0 1 0 0 888 | 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 889 | 0 1 0 0 1 0 1 1 0 1 0 0 0 0 1 0 1 890 | 0 0 1 0 0 1 0 1 1 1 1 0 1 0 0 0 0 891 | 0 1 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 892 | 0 0 1 0 1 1 0 0 0 0 0 0 1 0 0 1 1 893 | 0 0 1 1 1 0 1 1 1 0 0 1 0 1 0 1 0 894 | 1 0 0 1 0 1 1 1 0 0 0 1 1 0 0 0 1 895 | 0 1 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 896 | 1 0 1 0 1 0 1 1 1 1 1 0 0 1 1 1 0 897 | 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 898 | 0 0 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 899 | 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0 0 0 900 | 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0 1 901 | 0 1 0 1 1 0 1 0 0 1 0 0 0 0 0 1 0 902 | 1 0 0 1 0 1 1 0 1 1 0 0 1 1 0 1 1 903 | 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 1 904 | 0 0 1 0 1 1 0 1 0 0 0 1 1 1 1 0 1 905 | 0 0 1 0 1 1 0 0 0 1 1 1 0 1 0 1 1 906 | 0 1 0 1 1 1 0 1 0 0 1 0 0 1 0 0 0 907 | 0 0 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 908 | 0 1 0 0 0 0 1 1 1 1 1 1 0 1 1 0 1 909 | 1 0 1 1 0 0 1 1 0 1 0 0 0 1 1 0 1 910 | 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 0 911 | 1 1 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 912 | 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 1 0 913 | 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 914 | 0 1 1 1 0 0 0 1 0 0 1 1 0 1 1 1 1 915 | 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 1 916 | 1 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 917 | 0 1 0 1 1 0 1 0 1 1 0 1 0 1 1 0 1 918 | 1 0 0 0 0 1 1 0 1 1 1 0 1 0 0 1 1 919 | 0 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 920 | 1 0 1 1 1 1 0 1 1 0 0 1 1 0 0 1 0 921 | 0 1 0 1 1 0 1 0 0 1 0 0 1 0 1 0 1 922 | 0 1 0 0 1 0 1 0 0 1 0 0 1 1 1 0 0 923 | 1 1 0 0 1 0 1 0 1 1 0 1 0 0 0 1 1 924 | 0 1 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 925 | 1 0 0 0 1 1 1 1 1 0 1 0 1 0 0 1 0 926 | 1 0 1 1 0 1 0 1 0 1 0 0 0 1 1 0 0 927 | 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 1 928 | 1 1 0 1 0 0 1 0 1 1 1 0 0 1 0 1 1 929 | 1 0 1 1 1 1 0 1 0 1 1 0 1 0 0 1 1 930 | 1 1 0 0 1 0 1 1 0 0 1 0 0 1 1 1 0 931 | 1 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 1 932 | 1 0 1 1 0 1 0 0 1 1 0 0 0 1 0 0 1 933 | 1 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 934 | 0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 0 935 | 0 0 0 1 1 1 1 1 0 1 0 0 1 1 0 0 0 936 | 1 1 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 937 | 1 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 938 | 1 1 0 0 1 0 1 1 1 0 1 1 0 0 1 1 1 939 | 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 940 | 0 1 0 1 0 0 1 0 1 1 1 0 0 1 0 1 0 941 | 1 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 942 | 1 1 0 0 1 0 1 0 1 1 0 1 1 1 1 1 1 943 | 0 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 944 | 0 0 0 0 1 1 1 0 0 1 1 1 0 1 0 0 1 945 | 0 1 0 1 0 1 0 0 1 0 0 0 1 1 0 0 1 946 | 1 1 1 0 0 0 0 1 1 0 0 0 1 0 1 1 0 947 | 1 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 0 948 | 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 0 949 | 0 0 1 0 1 1 0 1 0 0 1 0 1 0 1 1 0 950 | 0 0 1 1 1 1 0 0 1 0 0 1 0 0 0 0 0 951 | 1 0 1 0 1 1 0 1 1 1 1 1 0 0 1 1 1 952 | 0 1 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1 953 | 0 0 1 1 0 0 1 1 1 1 0 0 0 0 1 0 1 954 | 0 0 0 1 0 1 1 1 1 1 0 1 1 0 1 0 1 955 | 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 1 956 | 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0 1 0 957 | 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 0 0 958 | 1 1 1 1 0 0 0 0 1 0 0 1 0 1 0 0 0 959 | 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 0 960 | 0 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 0 961 | 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 962 | 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 1 1 963 | 1 0 1 0 0 0 1 1 1 1 0 0 0 0 1 0 0 964 | 1 1 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 965 | 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 966 | 1 0 1 1 0 0 1 0 1 0 0 1 0 1 0 0 1 967 | 1 0 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 968 | 0 1 0 1 0 0 1 1 1 0 0 1 1 0 0 1 0 969 | 1 0 1 0 0 1 0 1 1 0 1 1 0 1 0 0 1 970 | 0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1 971 | 1 0 0 1 1 1 1 1 0 1 1 0 0 0 1 0 0 972 | 1 0 1 0 0 1 0 0 1 1 1 1 0 1 1 1 1 973 | 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 0 0 974 | 0 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 1 975 | 0 1 0 1 0 1 0 1 0 0 0 1 0 0 0 0 1 976 | 1 0 1 1 1 0 1 1 1 1 1 1 1 1 0 0 0 977 | 0 1 0 1 0 0 1 1 1 0 1 0 0 1 1 1 1 978 | 1 0 1 1 1 0 1 0 0 1 0 1 1 0 0 1 0 979 | 1 1 0 0 0 0 1 1 1 1 0 0 0 1 0 1 1 980 | 0 1 0 0 1 1 0 1 1 1 1 0 0 1 0 1 1 981 | 1 0 1 0 1 1 0 0 0 1 0 1 1 0 1 1 1 982 | 1 0 1 1 0 0 1 0 0 0 0 1 1 0 0 0 0 983 | 1 0 1 0 0 0 1 1 0 1 0 0 1 1 1 1 0 984 | 1 1 0 1 0 0 1 0 0 0 0 0 1 0 0 1 1 985 | 1 1 0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 986 | 0 0 1 0 1 1 0 1 0 1 0 0 0 1 0 0 1 987 | 0 0 0 1 0 1 1 1 1 0 0 0 0 1 0 0 0 988 | 1 0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 989 | 0 1 1 0 0 0 0 1 0 1 1 1 0 1 0 1 0 990 | 1 0 1 0 0 0 1 0 1 1 0 0 1 0 0 1 1 991 | 1 1 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1 992 | 1 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 1 993 | 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 1 994 | 1 1 0 1 1 1 0 1 0 1 0 0 1 1 1 0 1 995 | 0 1 0 1 0 0 1 0 0 1 1 0 1 1 1 0 0 996 | 0 0 1 1 0 0 1 1 1 1 0 1 1 1 0 1 0 997 | 1 0 0 0 0 1 1 0 0 0 1 1 1 1 0 1 0 998 | 0 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 0 999 | 0 0 1 1 0 1 0 1 0 0 0 1 0 0 0 1 0 1000 | 1 1 0 0 1 0 1 1 0 1 1 1 1 0 1 0 0 1001 | 1 1 0 0 1 0 1 1 0 1 1 1 0 1 0 0 1 1002 | 0 1 1 0 1 0 0 1 1 0 1 0 1 0 0 1 1 1003 | 0 0 1 0 1 0 1 1 0 1 1 0 0 0 0 1 1 1004 | 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1005 | 1 1 0 1 1 0 1 0 1 1 0 0 1 1 1 1 1 1006 | 0 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 1007 | 1 1 1 1 0 0 0 0 0 1 0 1 1 1 1 1 0 1008 | 1 0 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 1009 | 0 0 1 0 1 0 1 1 0 1 0 0 0 1 1 1 0 1010 | 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 1011 | 0 1 1 1 0 0 0 0 0 0 0 1 0 1 1 0 0 1012 | 0 0 1 0 0 0 1 0 1 0 1 1 0 1 1 0 0 1013 | 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1014 | 0 1 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1015 | 0 0 1 1 1 1 0 0 1 0 1 0 0 0 1 1 1 1016 | 0 0 1 1 0 1 0 0 1 1 1 0 0 1 1 0 1 1017 | 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 1 1018 | 1 0 1 0 0 1 0 1 0 1 0 1 0 0 0 0 1 1019 | 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 1 1020 | 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 0 1021 | 0 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 0 1022 | 0 1 1 1 1 0 0 0 1 0 1 1 1 0 1 1 0 1023 | 0 0 1 0 1 0 1 0 1 1 1 0 1 1 0 1 0 1024 | 1 0 1 1 1 1 0 0 1 0 0 1 0 1 1 1 1 1025 | 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 0 1 1026 | 0 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 1 1027 | 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1028 | 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 1 1 1029 | 1 0 0 1 1 1 1 0 0 0 1 0 0 1 0 1 0 1030 | 0 1 0 0 0 0 1 1 0 0 0 1 0 0 1 1 1 1031 | 1 0 1 0 1 1 0 0 0 1 0 0 1 0 0 1 1 1032 | 1 0 0 1 1 1 1 1 1 1 1 0 1 0 0 1 1 1033 | 0 1 1 0 1 0 0 0 0 1 0 0 1 1 1 0 0 1034 | 0 1 0 1 0 1 0 1 1 0 1 1 1 0 1 0 1 1035 | 0 0 1 0 1 1 0 1 1 0 1 1 0 0 0 0 1 1036 | 1 0 1 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1037 | 0 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 1038 | 0 1 0 1 0 0 1 1 0 1 1 0 0 1 1 0 1 1039 | 0 1 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 1040 | 0 0 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 1041 | 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1042 | 1 1 0 0 1 0 1 1 0 0 1 0 1 1 1 0 0 1043 | 1 1 0 0 1 1 0 0 0 1 1 1 0 0 1 0 0 1044 | 0 1 0 1 0 0 1 1 1 1 1 1 0 0 0 0 1 1045 | 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 0 1 1046 | 1 0 1 1 0 1 0 1 0 0 0 0 0 1 0 1 1 1047 | 0 1 0 1 1 0 1 1 1 0 1 0 1 1 1 1 1 1048 | 1 0 0 1 1 1 1 0 0 1 1 0 1 1 0 1 0 1049 | 0 1 0 1 0 1 0 0 1 1 1 1 1 0 0 0 0 1050 | 1 0 1 1 1 1 0 0 1 0 0 1 0 0 1 1 1 1051 | 0 1 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 1052 | 0 1 0 1 0 0 1 0 1 0 1 1 1 0 1 0 1 1053 | 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1 1054 | 1 1 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 1055 | 0 1 0 1 1 1 0 1 1 1 0 0 1 0 0 0 0 1056 | 0 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 1057 | 0 1 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0 1058 | 0 0 1 1 0 1 0 1 1 1 1 1 1 0 1 1 0 1059 | 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 1 1 1060 | 1 1 0 1 0 1 0 0 1 1 0 1 0 0 1 1 0 1061 | 0 1 0 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1062 | 1 0 1 0 0 1 0 1 1 0 1 1 0 0 1 1 1 1063 | 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 1 0 1064 | 1 0 1 0 1 1 0 0 1 1 1 0 0 1 0 0 1 1065 | 0 0 1 1 0 0 1 0 1 0 1 1 0 0 0 1 0 1066 | 1 0 1 0 0 0 1 0 1 0 0 0 0 0 1 1 0 1067 | 1 0 1 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1068 | 1 1 0 1 0 1 0 1 1 1 1 1 0 0 1 1 0 1069 | 1 0 1 1 0 1 0 0 0 0 0 1 0 1 0 1 0 1070 | 0 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1071 | 0 1 0 1 1 1 0 1 1 1 0 1 0 1 1 1 1 1072 | 1 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1073 | 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 1 0 1074 | 1 0 1 1 1 1 0 0 0 0 0 1 0 0 0 1 1 1075 | 1 0 1 1 1 1 0 0 1 1 0 0 0 0 0 0 1 1076 | 0 1 0 0 0 1 0 1 0 1 0 1 0 1 1 1 1 1077 | 1 1 0 0 1 0 1 0 1 1 1 0 1 0 0 1 0 1078 | 0 0 0 0 1 1 1 1 1 0 0 0 1 1 0 1 0 1079 | 0 0 0 0 0 1 1 0 1 0 0 0 1 1 1 0 0 1080 | 0 1 0 1 1 1 0 0 1 0 1 1 1 0 1 1 0 1081 | 1 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1 1 1082 | 1 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 1 1083 | 0 1 0 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1084 | 1 0 0 1 0 1 1 0 0 1 1 1 0 1 0 0 0 1085 | 0 0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 0 1086 | 0 1 0 0 0 0 1 1 0 0 1 1 0 1 1 0 0 1087 | 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 0 1 1088 | 0 0 1 0 0 1 0 1 1 1 0 0 1 0 1 1 1 1089 | 1 0 1 1 1 1 0 1 0 0 1 0 0 1 0 1 1 1090 | 1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 1 0 1091 | 0 0 1 1 0 1 0 0 1 0 0 0 1 1 0 1 1 1092 | 1 1 1 1 1 0 0 1 0 0 0 1 1 1 0 0 0 1093 | 0 1 0 1 1 0 1 1 1 0 1 0 0 0 0 1 1 1094 | 1 0 1 0 1 1 0 1 1 1 1 0 0 1 0 0 1 1095 | 1 1 0 1 1 1 0 0 1 0 0 1 1 1 0 1 0 1096 | 0 0 1 0 0 0 1 0 0 1 1 0 1 0 0 0 0 1097 | 0 0 0 1 0 1 1 1 1 1 0 0 0 0 1 0 1 1098 | 0 0 1 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1099 | 0 1 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1100 | 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 1 1 1101 | 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 1102 | 1 0 1 0 0 1 0 1 0 0 1 1 0 0 1 0 1 1103 | 0 0 1 1 1 0 1 0 1 0 0 1 0 0 0 0 1 1104 | 1 0 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1105 | 1 0 1 0 1 1 0 0 0 0 1 0 1 1 1 1 1 1106 | 0 1 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 1107 | 0 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 1108 | 0 1 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1109 | 1 0 0 1 1 1 1 0 0 0 1 0 0 1 0 1 1 1110 | 0 1 0 1 1 0 1 1 1 1 0 1 1 0 0 0 0 1111 | 1 1 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1112 | 1 0 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1113 | 0 0 1 1 1 0 1 1 0 1 1 1 0 0 1 0 0 1114 | 0 1 0 1 0 1 0 1 1 0 0 0 0 0 1 0 0 1115 | 1 0 0 0 1 1 1 1 0 1 0 1 0 1 0 0 0 1116 | 1 0 1 0 1 1 0 1 0 1 1 1 0 1 0 0 1 1117 | 1 0 1 0 0 1 0 1 0 1 0 1 0 1 1 1 1 1118 | 1 1 0 0 1 1 0 1 1 0 1 0 0 1 0 1 1 1119 | 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 1 1 1120 | 1 0 0 0 0 1 1 1 1 1 1 0 0 1 1 0 0 1121 | 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 1 1122 | 1 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1123 | 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 0 1124 | 1 0 1 1 1 0 1 0 0 0 0 0 1 1 0 0 0 1125 | 0 0 1 1 1 1 0 0 1 0 1 0 1 0 1 0 1 1126 | 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1127 | 0 0 1 1 0 1 0 1 1 0 0 1 0 1 1 1 1 1128 | 1 0 0 1 1 1 1 0 0 0 0 0 1 0 1 0 0 1129 | 1 1 1 1 1 0 0 1 0 1 0 0 1 1 0 0 0 1130 | 0 0 1 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1131 | 1 0 1 0 0 1 0 0 1 0 1 0 1 1 1 1 0 1132 | 1 0 1 1 0 1 0 1 0 0 1 1 1 1 1 0 0 1133 | 1 1 0 0 0 1 0 1 1 0 0 1 1 0 1 1 0 1134 | 1 0 1 0 0 0 1 1 1 0 0 0 0 1 0 1 0 1135 | 1 0 1 0 1 1 0 0 0 1 1 1 0 0 1 1 0 1136 | 1 0 1 0 1 1 0 1 0 0 1 1 0 1 1 0 1 1137 | 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 0 1138 | 0 0 0 0 1 1 1 1 0 1 1 1 1 0 1 0 0 1139 | 0 0 1 0 1 0 1 1 0 1 0 1 1 0 1 0 0 1140 | 1 1 0 0 0 0 1 1 0 1 1 1 1 1 1 1 1 1141 | 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 1 1 1142 | 1 1 1 1 1 0 0 0 0 1 1 0 0 1 1 0 0 1143 | 1 0 1 0 1 1 0 0 1 1 0 1 1 0 0 1 1 1144 | 1 1 0 0 0 1 0 1 1 1 0 1 0 0 1 0 0 1145 | 1 1 0 1 1 0 1 1 0 0 0 0 0 1 1 1 1 1146 | 0 1 0 1 0 1 0 1 1 1 1 0 0 1 0 1 0 1147 | 0 0 1 1 1 0 1 1 1 0 1 0 1 1 1 1 1 1148 | 1 0 0 1 1 1 1 1 0 0 0 1 1 0 1 0 1 1149 | 0 0 1 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1150 | 1 1 0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 1151 | 1 1 0 0 0 0 1 1 1 0 1 0 1 0 0 0 0 1152 | 0 1 0 0 0 0 1 0 1 0 0 0 1 1 0 1 1 1153 | 1 0 1 0 1 0 1 1 1 0 0 0 0 1 0 1 1 1154 | 1 0 1 1 0 0 1 0 0 0 1 0 1 0 0 1 0 1155 | 0 1 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 1156 | 0 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1157 | 1 1 0 0 1 1 0 0 0 0 0 1 0 1 1 0 1 1158 | 0 0 1 1 0 0 1 1 0 1 1 0 0 1 1 1 0 1159 | 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 1160 | 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 0 1161 | 1 0 1 0 1 0 1 0 1 1 1 1 1 0 0 1 0 1162 | 1 0 1 1 0 0 1 0 0 0 0 1 1 1 0 1 0 1163 | 0 1 0 1 0 0 1 1 0 1 0 0 1 1 0 1 1 1164 | 1 0 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 1165 | 0 1 1 0 0 0 0 0 1 1 0 0 1 0 0 0 0 1166 | 0 1 0 1 0 0 1 1 1 1 0 1 1 1 1 0 1 1167 | 1 1 0 1 0 0 1 1 0 1 1 1 1 1 0 0 1 1168 | 0 0 1 1 0 1 0 0 1 0 0 1 0 1 1 1 1 1169 | 0 1 0 0 0 0 1 0 1 1 1 0 1 1 1 0 0 1170 | 0 0 1 1 1 1 0 1 1 0 0 0 0 1 1 0 1 1171 | 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 1 1172 | 0 0 0 1 0 1 1 1 1 1 1 0 0 0 0 0 0 1173 | 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1174 | 1 0 1 1 0 1 0 1 1 0 0 1 1 0 0 0 1 1175 | 0 1 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1176 | 1 1 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 1177 | 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1178 | 1 1 0 0 0 0 1 1 1 1 1 1 1 0 1 1 0 1179 | 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 1180 | 1 1 0 1 1 0 1 1 0 0 1 1 1 0 1 1 1 1181 | 0 0 1 0 0 1 0 0 1 0 1 1 1 0 1 0 1 1182 | 1 0 1 1 1 1 0 0 1 0 1 1 1 1 0 1 0 1183 | 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 1 0 1184 | 1 1 0 0 1 0 1 0 1 0 1 1 1 0 1 1 0 1185 | 1 0 1 0 0 1 0 1 1 0 1 1 1 1 0 1 1 1186 | 0 0 0 1 1 1 1 0 1 1 1 1 1 1 0 0 0 1187 | 0 0 1 1 1 1 0 1 0 1 1 0 0 1 0 0 1 1188 | 1 0 1 0 1 0 1 1 0 1 0 1 0 1 1 1 0 1189 | 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0 1 0 1190 | 0 0 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1191 | 1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 0 1 1192 | 1 0 0 1 1 1 1 0 1 1 0 1 1 1 1 0 1 1193 | 1 0 1 1 1 1 0 1 1 1 1 0 1 1 0 0 0 1194 | 1 1 0 1 1 0 1 0 1 0 0 1 1 0 0 1 1 1195 | 0 1 1 0 1 0 0 1 0 1 0 1 0 1 1 0 0 1196 | 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0 1 0 1197 | 1 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 1198 | 0 0 1 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1199 | 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 1 0 1200 | 1 0 1 1 1 1 0 0 0 1 1 0 1 1 1 0 0 1201 | 0 1 1 1 1 0 0 0 0 0 0 1 0 0 1 0 0 1202 | 0 0 1 0 0 0 1 0 1 0 0 1 1 0 1 1 0 1203 | 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1204 | 1 0 1 1 0 0 1 0 0 0 1 0 1 1 0 0 0 1205 | 0 0 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 1206 | 0 1 1 1 1 0 0 1 0 1 0 1 0 0 0 1 0 1207 | 0 1 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 1208 | 0 0 1 1 0 1 0 1 0 1 1 0 0 1 0 0 1 1209 | 1 0 1 0 1 0 1 1 1 0 1 1 0 0 1 0 1 1210 | 1 0 1 0 1 1 0 0 0 0 0 1 1 0 1 0 1 1211 | 1 1 0 0 0 0 1 1 0 1 1 0 0 1 1 0 1 1212 | 0 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 1 1213 | 0 1 1 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1214 | 0 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 1 1215 | 1 0 0 1 0 1 1 0 1 0 1 1 0 0 0 1 1 1216 | 1 0 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1217 | 0 1 0 0 0 0 1 0 1 1 1 1 0 0 1 1 1 1218 | 0 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 0 1219 | 1 1 0 0 1 1 0 0 0 0 1 0 0 1 1 0 1 1220 | 1 0 0 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1221 | 1 0 1 0 0 1 0 0 0 1 1 0 0 1 0 1 1 1222 | 0 1 0 1 1 0 1 0 0 0 1 0 1 1 0 0 0 1223 | 1 1 0 1 1 0 1 1 0 1 1 0 0 0 1 0 1 1224 | 0 0 1 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1225 | 1 1 1 0 0 0 0 0 1 0 1 1 1 0 1 0 0 1226 | 1 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 1 1227 | 0 1 1 1 0 0 0 0 1 0 1 1 0 0 0 0 0 1228 | 1 1 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 1229 | 1 1 0 0 1 0 1 1 1 0 0 0 1 1 0 0 1 1230 | 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 1231 | 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1232 | 0 1 0 1 0 1 0 1 0 1 1 1 0 1 1 0 1 1233 | 0 0 1 0 0 0 1 0 1 1 1 1 0 1 0 1 0 1234 | 1 0 0 1 1 1 1 1 1 0 0 1 0 1 0 1 1 1235 | 0 1 0 0 1 1 0 1 1 1 1 0 0 0 0 1 0 1236 | 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1237 | 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 0 1 1238 | 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 1 0 1239 | 1 1 0 0 1 0 1 1 1 0 0 0 0 0 0 1 1 1240 | 1 1 0 1 1 0 1 1 0 1 1 1 1 0 0 1 1 1241 | 1 0 1 0 1 1 0 1 0 1 0 1 1 1 1 1 1 1242 | 0 1 0 1 1 0 1 1 1 0 1 0 0 1 1 1 1 1243 | 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 0 0 1244 | 1 0 1 1 1 0 1 1 0 1 1 0 0 1 0 1 1 1245 | 1 0 1 1 1 1 0 1 1 1 0 1 0 1 1 0 1 1246 | 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 1247 | 1 1 1 0 0 0 0 1 1 0 1 0 0 1 0 1 1 1248 | 0 0 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 1249 | 1 1 1 0 0 0 0 1 1 1 1 0 1 0 1 1 1 1250 | 0 0 1 0 0 1 0 0 1 0 0 1 0 1 1 0 1 1251 | 1 1 0 1 1 1 0 1 1 0 1 0 1 0 1 0 0 1252 | 0 0 1 0 0 1 0 0 1 1 1 1 0 0 0 0 1 1253 | 1 0 0 0 0 1 1 0 1 1 0 1 1 0 1 0 0 1254 | 0 1 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 1255 | 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1256 | 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1257 | 0 1 0 1 0 1 0 1 1 1 0 1 1 1 1 0 0 1258 | 1 1 0 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1259 | 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1 1 0 1260 | 0 0 1 1 0 1 0 0 1 1 0 0 1 1 1 0 0 1261 | 1 1 1 0 1 0 0 0 0 1 1 1 1 1 0 0 0 1262 | 0 0 1 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1263 | 1 1 0 1 1 0 1 1 1 0 1 0 0 0 0 0 1 1264 | 0 1 1 0 1 0 0 0 1 0 1 0 0 0 1 1 1 1265 | 0 0 1 1 0 1 0 0 1 0 1 1 0 0 0 0 1 1266 | 1 1 1 1 1 0 0 0 1 0 1 0 1 0 0 0 0 1267 | 0 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 1 1268 | 0 0 0 1 0 1 1 0 0 1 1 1 1 1 0 1 1 1269 | 1 0 1 1 1 0 1 1 0 0 0 0 0 0 1 1 1 1270 | 0 1 0 0 0 1 0 1 0 1 0 1 0 0 1 0 0 1271 | 1 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1272 | 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 0 1 1273 | 1 0 1 1 1 1 0 1 0 0 1 0 0 0 1 0 0 1274 | 0 0 1 1 0 1 0 0 1 0 0 0 1 1 0 1 0 1275 | 1 1 0 0 1 0 1 0 0 0 1 1 1 1 0 1 1 1276 | 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 0 1277 | 1 1 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 1278 | 1 1 0 0 0 0 1 0 1 0 1 1 0 0 1 1 0 1279 | 1 1 1 1 1 0 0 1 1 0 1 0 0 1 0 0 0 1280 | 0 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1281 | 1 1 0 1 0 1 0 1 1 1 0 0 0 1 0 1 1 1282 | 0 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1283 | 1 0 1 0 1 0 1 0 1 1 0 1 0 0 1 1 0 1284 | 0 1 0 0 1 0 1 1 1 1 0 0 0 1 1 1 1 1285 | 1 0 1 1 1 0 1 1 1 0 0 0 1 0 1 1 0 1286 | 1 1 1 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1287 | 0 0 1 1 1 0 1 1 1 0 0 1 1 0 0 1 1 1288 | 0 0 0 1 1 1 1 1 1 1 0 1 0 0 1 1 0 1289 | 1 1 1 1 1 0 0 0 0 0 1 0 1 1 0 1 0 1290 | 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 1 1291 | 0 1 0 1 1 0 1 1 1 1 0 1 0 0 0 0 1 1292 | 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1293 | 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 1 1294 | 0 1 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 1295 | 1 0 1 0 0 1 0 1 1 1 1 0 0 1 0 0 0 1296 | 1 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 0 1297 | 1 1 0 0 0 0 1 1 0 0 0 0 0 1 1 0 1 1298 | 1 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 0 1299 | 1 1 0 0 1 0 1 0 0 1 1 0 0 1 0 1 1 1300 | 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1301 | 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1 1302 | 0 0 0 1 0 1 1 0 1 0 0 1 1 1 1 0 1 1303 | 0 0 1 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1304 | 0 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1 1 1305 | 1 0 0 1 1 1 1 1 0 0 0 1 0 1 1 0 0 1306 | 1 1 0 0 1 0 1 0 1 0 1 0 0 1 0 0 1 1307 | 0 0 0 1 1 1 1 1 0 0 0 0 0 1 0 1 1 1308 | 1 1 0 0 0 1 0 1 0 1 0 1 1 0 1 1 0 1309 | 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 1 1 1310 | 0 0 1 1 1 0 1 0 1 0 0 1 1 0 0 0 1 1311 | 1 0 0 1 1 1 1 1 1 1 0 1 0 0 0 0 0 1312 | 0 1 1 1 0 0 0 0 1 1 1 0 0 1 0 0 1 1313 | 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 1314 | 1 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1315 | 1 1 0 1 1 0 1 0 1 1 0 0 0 1 1 0 1 1316 | 1 0 1 0 0 1 0 1 0 0 0 0 1 1 0 1 1 1317 | 1 0 1 0 0 1 0 0 0 1 0 0 1 1 0 1 1 1318 | 1 0 1 0 0 1 0 0 1 1 0 0 1 1 1 1 1 1319 | 0 1 1 1 0 0 0 0 1 0 1 0 0 1 1 1 0 1320 | 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1 0 0 1321 | 0 1 0 1 1 0 1 1 0 1 1 0 0 1 1 1 1 1322 | 1 1 0 1 1 0 1 1 0 1 0 0 1 0 0 1 1 1323 | 0 0 1 1 1 0 1 1 1 0 1 0 0 0 0 1 1 1324 | 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 1325 | 1 1 0 0 1 1 0 0 0 0 0 1 0 0 0 1 0 1326 | 1 0 0 1 0 1 1 0 0 1 1 1 1 1 0 1 1 1327 | 1 1 0 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1328 | 1 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 1329 | 1 0 1 0 1 1 0 1 1 1 1 0 1 1 0 1 1 1330 | 0 1 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1331 | 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 1 1332 | 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 1 1 1333 | 0 1 0 1 1 0 1 1 1 0 1 0 0 1 1 0 1 1334 | 1 1 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1335 | 0 1 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 1336 | 1 0 1 1 0 1 0 1 0 0 0 1 1 0 0 0 1 1337 | 1 0 1 0 0 1 0 1 0 1 1 0 1 0 1 1 0 1338 | 1 0 1 1 1 0 1 0 1 1 1 0 0 0 1 0 1 1339 | 0 1 0 1 0 0 1 0 1 0 1 0 0 1 1 0 1 1340 | 0 1 1 0 1 0 0 1 1 1 1 0 1 0 1 1 0 1341 | 1 1 0 1 0 0 1 0 0 1 1 1 1 1 1 0 1 1342 | 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 1343 | 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1344 | 0 0 0 1 1 1 1 1 0 0 1 1 1 0 0 0 1 1345 | 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 1346 | 1 1 0 0 1 0 1 0 0 0 0 1 1 0 1 1 1 1347 | 1 1 0 0 0 0 1 0 0 1 1 0 1 1 0 1 1 1348 | 1 1 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1349 | 1 1 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0 1350 | 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 0 0 1351 | 0 0 1 1 0 1 0 1 1 0 1 0 0 0 0 1 0 1352 | 1 1 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 1353 | 0 0 1 1 0 0 1 0 0 0 0 1 1 1 1 1 0 1354 | 1 0 0 1 1 1 1 0 1 1 1 1 0 0 0 0 1 1355 | 1 0 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 1356 | 0 0 0 0 1 1 1 0 1 1 0 1 1 0 0 0 1 1357 | 0 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1358 | 1 0 1 1 0 0 1 1 1 1 1 0 1 1 0 1 0 1359 | 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 1 1360 | 1 1 1 1 1 0 0 0 1 0 0 0 1 1 1 0 0 1361 | 1 1 1 1 0 0 0 1 1 0 0 0 1 0 0 0 0 1362 | 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 1363 | 0 1 1 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1364 | 0 1 0 0 1 0 1 0 0 1 1 1 1 0 0 0 1 1365 | 1 1 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1366 | 1 1 0 0 0 0 1 0 0 1 0 0 1 0 1 0 1 1367 | 1 0 1 0 0 0 1 1 0 1 1 0 0 1 0 0 0 1368 | 1 1 0 0 0 0 1 1 0 1 1 0 0 1 0 1 1 1369 | 1 1 0 0 0 0 1 0 1 1 1 0 1 1 0 0 0 1370 | 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 1 1371 | 1 1 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1372 | 0 1 0 1 0 1 0 0 1 0 0 1 1 1 1 0 0 1373 | 0 0 1 1 0 1 0 1 1 1 1 0 0 0 1 0 1 1374 | 1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 1375 | 1 0 1 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1376 | 0 0 1 1 0 1 0 0 1 0 1 0 0 0 0 1 0 1377 | 1 0 1 1 0 1 0 1 0 0 0 1 0 0 1 1 1 1378 | 1 0 1 0 0 1 0 0 0 0 1 0 1 1 1 1 1 1379 | 1 1 0 1 0 0 1 1 1 0 1 0 0 1 1 0 1 1380 | 1 1 0 1 0 0 1 1 1 1 1 1 0 1 0 1 1 1381 | 1 0 0 0 0 1 1 0 0 0 0 0 1 0 1 1 0 1382 | 1 1 0 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1383 | 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 1 0 1384 | 1 0 1 1 0 0 1 1 1 1 0 1 0 0 0 1 1 1385 | 0 0 1 0 1 1 0 0 1 1 0 0 1 0 1 0 1 1386 | 1 0 1 1 0 0 1 1 1 1 0 1 1 1 1 0 0 1387 | 1 1 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 1388 | 0 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 0 1389 | 1 0 0 0 1 1 1 0 0 0 1 1 1 0 1 1 0 1390 | 1 0 0 0 1 1 1 0 1 1 1 1 0 0 1 1 0 1391 | 0 0 0 1 0 1 1 0 1 0 1 1 0 1 0 0 1 1392 | 1 1 0 1 1 0 1 1 1 0 0 0 1 1 1 0 0 1393 | 1 0 1 1 1 1 0 0 1 0 1 1 0 0 1 1 0 1394 | 1 0 1 0 1 1 0 1 1 1 1 1 1 1 0 1 1 1395 | 0 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1396 | 1 0 1 0 1 1 0 1 1 0 0 1 0 0 0 1 1 1397 | 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 1 1 1398 | 0 0 1 0 1 1 0 0 0 0 0 1 0 1 1 1 1 1399 | 0 1 0 0 0 1 0 0 1 0 1 1 0 1 1 0 0 1400 | 1 1 1 1 0 0 0 0 1 1 1 0 0 0 1 0 0 1401 | 1 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0 1 1402 | 0 1 1 0 1 0 0 1 1 0 1 0 0 0 1 1 1 1403 | 1 0 1 1 0 1 0 1 0 0 0 1 1 1 0 1 0 1404 | 1 0 1 0 0 1 0 0 1 0 1 0 1 1 1 0 0 1405 | 0 1 0 0 0 1 0 1 1 1 1 1 1 0 0 0 0 1406 | 1 1 0 1 1 0 1 1 1 0 1 0 0 1 0 0 0 1407 | 1 0 1 1 1 1 0 0 1 0 1 1 1 1 1 0 1 1408 | 0 1 0 1 0 0 1 1 1 1 0 1 0 1 0 0 1 1409 | 0 0 1 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1410 | 0 0 1 1 1 0 1 1 0 0 0 0 1 1 0 1 1 1411 | 1 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 1412 | 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1413 | 1 0 1 1 1 0 1 1 1 0 1 0 1 0 0 1 1 1414 | 0 1 1 0 1 0 0 1 0 0 0 1 0 0 1 1 0 1415 | 0 1 0 0 1 0 1 0 1 1 1 0 0 1 0 1 1 1416 | 0 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 0 1417 | 1 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 1418 | 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 0 1419 | 1 1 0 0 1 0 1 1 1 0 1 0 0 0 0 1 1 1420 | 1 0 1 1 1 1 0 0 1 0 1 1 0 1 1 0 1 1421 | 1 0 1 0 0 1 0 1 1 1 1 1 0 1 0 0 1 1422 | 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 1423 | 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 1424 | 1 1 0 0 1 1 0 0 0 0 1 1 1 0 0 1 0 1425 | 1 0 1 1 1 0 1 0 1 0 1 0 0 0 1 0 1 1426 | 1 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 1427 | 0 0 1 1 0 1 0 0 1 1 0 0 0 0 0 0 1 1428 | 1 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 1 1429 | 1 0 1 0 1 1 0 1 0 1 0 0 1 1 1 1 1 1430 | 1 0 1 1 1 1 0 1 0 0 1 1 1 0 0 0 1 1431 | 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1432 | 1 1 0 1 1 0 1 0 1 1 0 0 0 1 0 0 0 1433 | 0 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 0 1434 | 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 1 1 1435 | 1 1 0 0 1 1 0 0 1 0 0 0 1 1 1 0 0 1436 | 0 1 0 0 1 0 1 0 0 1 0 0 1 1 1 0 1 1437 | 1 1 1 0 1 0 0 1 0 0 1 0 1 0 1 1 0 1438 | 1 0 1 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1439 | 0 0 1 1 0 1 0 0 0 1 0 0 1 1 0 1 0 1440 | 1 1 0 1 1 0 1 1 1 0 1 0 0 0 1 0 1 1441 | 0 0 1 1 1 0 1 0 0 0 0 1 0 1 0 0 0 1442 | 0 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 1 1443 | 1 1 0 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1444 | 1 0 1 0 1 1 0 1 1 1 0 0 1 1 0 0 1 1445 | 1 0 1 0 0 1 0 1 1 0 0 0 1 0 1 1 0 1446 | 0 1 0 1 1 0 1 0 0 1 0 0 0 0 0 1 1 1447 | 1 1 0 1 0 1 0 0 0 1 1 1 1 0 0 0 1 1448 | 1 0 1 1 1 0 1 1 0 0 1 0 1 1 0 0 0 1449 | 1 1 0 0 0 0 1 1 1 0 1 1 0 1 0 0 0 1450 | 1 0 1 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1451 | 0 0 0 1 1 1 1 1 1 0 1 0 0 1 0 1 1 1452 | 1 0 0 0 0 1 1 0 0 0 0 1 0 1 1 1 0 1453 | 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1454 | 1 0 0 0 1 1 1 0 1 0 0 1 1 0 0 0 1 1455 | 1 0 0 0 1 1 1 0 0 1 1 1 1 1 0 1 1 1456 | 0 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 0 1457 | 1 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1458 | 0 1 0 0 1 0 1 0 1 1 0 1 0 0 1 0 0 1459 | 0 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 0 1460 | 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1461 | 1 0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 0 1462 | 1 0 1 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1463 | 1 0 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0 1464 | 1 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 1 1465 | 0 1 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 1466 | 1 1 0 0 1 0 1 1 1 1 1 1 1 0 1 1 0 1467 | 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 1 0 1468 | 1 1 0 0 1 0 1 1 0 1 1 0 0 0 0 0 1 1469 | 1 1 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 1470 | 1 1 0 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1471 | 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 1 1472 | 1 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 1 1473 | 1 1 0 0 1 0 1 1 1 1 0 0 0 1 1 1 0 1474 | 0 1 0 0 0 0 1 0 0 1 1 1 0 0 1 1 0 1475 | 1 1 0 1 1 0 1 1 0 0 1 1 0 1 1 0 1 1476 | 1 1 0 0 1 0 1 1 0 0 1 0 1 0 0 0 0 1477 | 1 1 0 0 0 0 1 0 1 0 1 0 0 1 1 0 0 1478 | 1 0 1 0 0 0 1 0 0 1 1 1 1 0 1 0 0 1479 | 1 0 1 0 0 1 0 1 1 0 1 1 1 1 1 1 1 1480 | 1 1 0 0 1 0 1 1 1 0 0 1 0 0 0 0 1 1481 | 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 1 1482 | 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 1 1 1483 | 1 0 1 1 0 1 0 0 0 0 0 1 0 1 0 1 0 1484 | 1 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1485 | 0 1 0 0 0 0 1 1 1 1 0 1 1 1 1 0 1 1486 | 1 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1 0 1487 | 1 0 0 0 0 1 1 0 0 1 1 1 1 1 0 0 1 1488 | 1 1 0 1 0 0 1 1 0 1 1 1 1 0 0 0 0 1489 | 1 1 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1490 | 1 0 1 1 1 1 0 0 0 1 1 1 0 1 1 0 1 1491 | 0 0 0 1 0 1 1 1 1 0 0 1 1 1 0 1 1 1492 | 1 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 0 1493 | 1 0 1 1 1 1 0 1 0 0 0 0 1 0 1 1 1 1494 | 1 1 0 1 0 1 0 0 0 0 1 0 0 1 1 1 1 1495 | 1 1 0 0 1 1 0 1 1 0 0 1 0 0 0 1 1 1496 | 1 0 1 0 0 0 1 0 0 1 1 1 1 0 0 1 1 1497 | 1 0 1 1 0 1 0 0 0 0 0 0 1 1 1 1 0 1498 | 0 1 0 1 1 0 1 1 0 1 1 0 1 0 1 1 0 1499 | 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 1500 | 0 1 0 0 0 1 0 0 1 1 1 0 1 0 0 0 0 1501 | 0 0 1 0 0 1 0 0 0 1 1 1 0 0 1 0 0 1502 | 0 0 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1503 | 1 1 0 1 1 1 0 0 1 0 1 1 0 1 0 0 0 1504 | 1 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1505 | 0 0 1 0 0 1 0 1 0 1 0 0 0 1 0 0 1 1506 | 0 0 1 1 0 0 1 0 0 0 0 1 1 0 0 0 0 1507 | 1 1 0 1 1 0 1 1 0 0 0 0 1 1 0 1 1 1508 | 1 1 0 1 0 0 1 1 1 1 0 0 1 1 1 1 1 1509 | 1 0 0 0 1 1 1 0 0 0 0 1 0 1 0 1 0 1510 | 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 1 0 1511 | 0 0 1 0 1 1 0 1 1 0 1 0 0 0 0 0 1 1512 | 1 1 1 0 0 0 0 0 1 1 1 0 1 1 1 0 1 1513 | 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 1 1514 | 0 1 0 1 1 1 0 1 1 0 0 0 1 0 0 0 1 1515 | 0 0 1 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1516 | 1 0 1 0 0 1 0 1 0 1 0 0 1 1 0 1 0 1517 | 0 1 0 1 0 0 1 0 0 1 1 1 1 1 1 1 1 1518 | 1 0 1 1 1 1 0 0 1 1 0 1 1 0 1 1 0 1519 | 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 1520 | 0 1 1 1 1 0 0 1 0 1 0 1 1 0 1 0 1 1521 | 1 1 0 1 1 0 1 1 1 0 0 0 0 1 0 1 1 1522 | 1 1 0 1 1 0 1 0 0 1 0 1 1 1 0 0 0 1523 | 0 1 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 1524 | 1 1 0 0 1 0 1 1 0 1 1 1 0 0 0 0 0 1525 | 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1526 | 0 1 0 0 0 0 1 1 0 0 0 0 1 0 0 1 0 1527 | 1 1 0 0 1 0 1 0 0 0 1 0 1 1 1 0 1 1528 | 0 0 1 0 0 0 1 1 1 0 1 0 1 0 1 0 0 1529 | 1 1 1 0 1 0 0 1 1 1 1 0 0 1 0 1 0 1530 | 0 1 0 1 1 0 1 0 0 0 1 1 0 1 0 0 0 1531 | 1 1 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 1532 | 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1533 | 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1534 | 1 1 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1535 | 1 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1536 | 1 1 0 0 1 1 0 1 0 0 0 1 0 0 1 1 1 1537 | 1 1 0 1 0 1 0 1 0 0 1 0 1 1 1 1 0 1538 | 0 1 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1539 | 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 1 0 1540 | 0 0 1 1 0 0 1 1 0 1 0 0 0 0 1 1 0 1541 | 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 0 0 1542 | 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 1 1543 | 1 0 0 0 0 1 1 1 0 1 0 0 0 0 1 1 0 1544 | 1 0 1 1 0 0 1 0 0 1 1 0 0 0 0 0 1 1545 | 1 1 0 1 0 0 1 1 0 1 0 0 1 0 1 0 0 1546 | 0 1 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 1547 | 0 1 0 1 0 0 1 1 1 1 0 0 1 1 0 0 0 1548 | 0 1 0 1 1 1 0 0 0 1 0 1 1 0 1 0 0 1549 | 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1550 | 0 1 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 1551 | 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 1 0 1552 | 1 0 1 0 1 1 0 1 0 1 0 0 0 1 0 1 1 1553 | 0 1 0 0 0 0 1 0 1 0 1 1 0 1 1 0 1 1554 | 0 0 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 1555 | 0 0 1 0 0 1 0 1 1 0 0 0 1 1 1 1 1 1556 | 1 1 0 1 0 0 1 1 1 1 0 1 1 0 1 1 0 1557 | 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 1558 | 0 1 0 0 0 0 1 1 0 1 1 0 0 1 1 0 1 1559 | 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 1 0 1560 | 0 1 0 1 1 0 1 0 1 1 1 1 0 0 0 1 1 1561 | 1 1 0 1 1 0 1 1 1 1 0 0 0 1 1 0 1 1562 | 1 1 1 0 0 0 0 0 0 1 0 0 1 0 1 0 1 1563 | 1 0 1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1564 | 0 0 1 0 0 1 0 0 0 0 1 0 1 1 0 0 0 1565 | 0 0 1 1 0 1 0 0 0 1 1 0 1 0 1 0 0 1566 | 0 0 1 1 1 1 0 0 1 1 1 0 0 1 0 0 1 1567 | 0 1 0 0 0 1 0 1 1 0 1 0 1 1 1 1 0 1568 | 1 0 0 1 0 1 1 1 0 1 0 0 0 0 0 1 0 1569 | 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1570 | 1 0 1 0 1 0 1 0 0 0 1 1 0 1 0 1 1 1571 | 1 1 0 1 0 0 1 1 1 1 0 0 0 1 1 1 0 1572 | 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 1 0 1573 | 0 1 1 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1574 | 0 1 0 1 0 0 1 0 0 0 1 1 0 1 0 1 0 1575 | 0 0 1 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1576 | 1 0 1 0 1 1 0 0 0 1 1 0 1 0 0 0 1 1577 | 1 0 1 1 1 1 0 0 0 0 1 1 0 0 0 0 0 1578 | 0 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1579 | 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1580 | 1 1 0 1 0 0 1 0 0 1 1 0 1 0 1 1 1 1581 | 0 1 0 0 0 0 1 0 0 1 1 1 1 0 1 1 1 1582 | 0 1 0 1 0 1 0 0 1 1 0 0 1 0 0 1 0 1583 | 1 1 0 1 0 0 1 0 0 0 1 0 1 1 0 0 1 1584 | 1 0 1 0 1 1 0 0 1 0 0 0 0 1 1 0 0 1585 | 0 1 0 1 1 0 1 0 1 0 0 0 1 1 1 0 0 1586 | 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1 1 1587 | 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1588 | 0 0 1 0 0 1 0 1 1 0 1 0 1 1 0 0 1 1589 | 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1590 | 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1591 | 1 0 0 0 0 1 1 1 0 1 1 1 1 1 0 0 1 1592 | 1 1 0 1 1 0 1 0 0 1 0 0 1 1 0 0 1 1593 | 0 0 1 0 0 0 1 1 1 0 1 1 1 1 0 1 0 1594 | 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1595 | 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 1 1596 | 0 1 0 1 1 1 0 1 1 0 1 1 1 0 0 0 0 1597 | 0 0 1 1 0 1 0 1 1 0 1 1 0 1 1 1 0 1598 | 0 1 0 0 1 0 1 0 0 0 1 0 1 1 0 0 1 1599 | 1 0 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 1600 | 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1601 | 0 0 1 0 0 0 1 0 1 0 1 1 0 1 1 1 0 1602 | 1 1 0 0 0 0 1 1 0 1 1 1 1 1 1 1 1 1603 | 0 0 0 0 0 1 1 1 0 1 1 0 0 1 1 0 0 1604 | 0 1 1 1 1 0 0 0 1 1 1 1 0 1 0 0 0 1605 | 0 0 1 0 0 0 1 0 1 1 1 0 0 1 0 1 1 1606 | 1 1 0 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1607 | 1 0 1 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1608 | 1 0 1 0 0 1 0 0 1 1 0 1 1 1 1 1 1 1609 | 1 0 1 0 1 0 1 1 1 1 0 1 1 1 1 0 0 1610 | 0 0 1 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1611 | 1 0 1 1 0 1 0 0 1 0 1 0 1 1 1 1 0 1612 | 0 0 1 0 0 1 0 1 0 1 1 1 0 1 1 1 0 1613 | 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 1614 | 1 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 0 1615 | 1 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 1 1616 | 1 0 1 0 0 1 0 1 1 0 1 1 0 1 0 0 1 1617 | 1 1 0 1 0 0 1 1 0 0 1 1 0 1 1 0 1 1618 | 1 1 0 1 1 1 0 1 1 1 1 0 1 0 0 1 0 1619 | 0 0 1 1 1 0 1 0 1 0 1 1 0 0 1 1 0 1620 | 0 0 1 1 0 1 0 0 0 0 0 0 1 1 1 1 1 1621 | 1 0 1 0 0 1 0 0 1 1 0 1 0 1 0 0 0 1622 | 0 0 1 0 1 1 0 0 1 0 1 1 1 1 1 1 1 1623 | 1 0 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 1624 | 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 1 0 1625 | 0 0 1 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1626 | 0 1 0 0 0 1 0 0 1 0 1 1 0 0 0 1 0 1627 | 1 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 1 1628 | 0 1 0 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1629 | 1 0 1 0 0 1 0 0 1 0 1 1 0 0 0 1 0 1630 | 1 0 0 0 1 1 1 1 1 1 0 1 0 0 1 0 1 1631 | 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1632 | 0 0 1 1 0 0 1 1 1 1 0 0 1 0 1 1 0 1633 | 0 0 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 1634 | 1 1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1635 | 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1636 | 0 0 1 1 0 0 1 1 0 1 1 0 0 1 0 0 0 1637 | 0 0 1 0 1 1 0 0 1 1 1 0 1 1 0 0 1 1638 | 0 1 0 0 1 1 0 0 1 1 0 1 0 0 0 1 0 1639 | 0 0 0 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1640 | 0 1 0 1 1 0 1 1 1 1 0 1 1 1 1 0 1 1641 | 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 0 1642 | 0 1 1 1 0 0 0 1 1 0 1 1 0 1 0 0 0 1643 | 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 1 1 1644 | 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 1 1 1645 | 0 0 1 1 1 1 0 1 0 0 0 1 1 0 1 1 1 1646 | 0 0 0 0 0 1 1 1 1 0 1 0 0 0 1 1 0 1647 | 1 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1648 | 1 0 1 1 0 1 0 0 0 1 0 0 1 1 0 1 1 1649 | 0 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1650 | 1 0 1 0 1 1 0 0 1 1 0 0 0 1 1 1 0 1651 | 0 1 0 0 1 0 1 1 1 1 0 0 0 1 1 1 1 1652 | 1 0 0 1 0 1 1 1 0 1 0 1 1 1 1 0 1 1653 | 1 1 1 1 0 0 0 0 1 0 0 1 0 1 0 0 1 1654 | 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 1 1655 | 0 0 1 1 0 1 0 0 1 1 0 1 0 1 1 1 1 1656 | 1 0 1 1 0 1 0 0 1 1 0 1 0 0 0 0 0 1657 | 1 0 1 0 0 0 1 0 1 0 0 1 1 1 0 1 0 1658 | 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 1 0 1659 | 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 1 1 1660 | 1 0 1 0 1 1 0 0 0 0 1 1 1 0 1 1 1 1661 | 0 0 1 1 1 1 0 1 0 0 1 1 0 1 1 0 0 1662 | 0 0 0 1 1 1 1 1 0 0 0 0 0 1 0 1 0 1663 | 0 1 1 1 1 0 0 1 0 1 1 1 0 1 1 1 1 1664 | 1 0 0 0 1 1 1 1 0 1 0 0 0 0 0 1 1 1665 | 0 1 0 0 0 0 1 1 0 1 0 0 0 0 1 0 1 1666 | 1 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1667 | 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1668 | 1 0 0 0 1 1 1 0 1 0 1 1 1 1 0 0 0 1669 | 0 0 1 1 1 0 1 0 0 0 0 0 0 1 1 0 0 1670 | 1 0 0 0 1 1 1 0 1 1 1 0 0 1 1 0 0 1671 | 1 0 1 0 1 1 0 0 1 0 1 0 0 0 1 1 0 1672 | 1 0 0 0 1 1 1 1 0 1 0 0 0 1 1 1 1 1673 | 0 1 0 1 1 0 1 1 0 0 0 1 0 0 0 1 0 1674 | 0 0 1 1 0 1 0 0 0 1 1 0 0 0 1 1 1 1675 | 1 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1676 | 0 1 0 1 0 0 1 0 0 0 1 0 1 0 0 0 1 1677 | 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0 0 1678 | 0 1 0 1 1 0 1 1 1 0 1 1 0 1 0 0 0 1679 | 0 0 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 1680 | 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 0 1681 | 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 1682 | 1 0 1 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1683 | 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 1 0 1684 | 1 1 0 1 0 1 0 1 0 0 1 0 1 1 0 1 1 1685 | 0 0 1 0 1 1 0 1 0 0 0 0 1 1 1 0 0 1686 | 1 1 1 0 0 0 0 1 0 1 1 0 0 0 0 1 1 1687 | 0 0 1 0 1 1 0 1 0 1 0 0 0 1 1 1 0 1688 | 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 1689 | 0 0 0 0 1 1 1 1 0 1 1 1 1 0 0 0 0 1690 | 1 0 1 0 0 1 0 0 1 1 0 1 0 0 1 1 0 1691 | 1 1 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 1692 | 0 1 0 1 0 1 0 1 0 1 0 0 1 1 0 1 0 1693 | 0 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 1 1694 | 0 0 1 0 1 1 0 1 1 0 0 0 0 0 0 0 0 1695 | 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0 1 1 1696 | 0 0 1 0 0 1 0 0 0 0 1 0 1 1 1 0 1 1697 | 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1698 | 1 1 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 1699 | 1 1 0 0 1 0 1 0 0 1 0 1 1 0 1 0 1 1700 | 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1701 | 0 1 1 1 0 0 0 1 0 0 1 0 1 0 1 1 0 1702 | 0 1 0 1 0 1 0 1 0 1 0 0 0 1 1 0 1 1703 | 0 0 1 1 1 0 1 0 1 0 1 1 0 0 1 1 1 1704 | 1 0 1 1 1 0 1 1 1 0 1 1 0 1 0 1 1 1705 | 0 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1706 | 1 1 1 0 1 0 0 0 1 1 0 1 1 0 1 0 1 1707 | 1 0 1 1 0 1 0 0 0 1 0 1 0 1 1 1 1 1708 | 0 0 1 1 0 1 0 1 0 1 1 1 0 0 1 1 0 1709 | 0 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 0 1710 | 0 1 1 1 0 0 0 0 0 1 1 1 0 1 0 0 0 1711 | 1 1 1 1 1 0 0 0 1 1 1 0 1 0 1 1 0 1712 | 0 1 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1713 | 1 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1714 | 1 1 1 1 1 0 0 1 1 0 1 0 1 0 1 1 1 1715 | 0 1 0 0 1 1 0 1 1 1 1 0 1 0 0 1 1 1716 | 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 1 1717 | 1 0 0 0 1 1 1 1 1 1 0 0 1 0 1 0 0 1718 | 0 1 1 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1719 | 0 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 1 1720 | 1 1 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 1721 | 0 0 0 1 0 1 1 1 1 0 0 0 0 1 0 1 0 1722 | 1 1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 1 1723 | 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1724 | 1 1 0 0 1 0 1 0 0 1 1 1 1 1 0 1 1 1725 | 1 1 0 0 0 0 1 1 0 0 1 0 1 0 1 0 0 1726 | 1 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 1 1727 | 0 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 1 1728 | 0 0 0 1 1 1 1 0 0 0 1 0 0 1 1 0 1 1729 | 1 1 0 1 1 1 0 1 1 0 0 1 1 1 0 1 0 1730 | 0 1 0 1 1 0 1 0 0 1 1 1 1 0 0 0 0 1731 | 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 0 1732 | 1 0 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 1733 | 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1734 | 1 0 1 1 1 1 0 1 0 1 1 1 0 1 1 1 0 1735 | 1 0 0 1 1 1 1 0 1 0 1 0 0 1 1 1 0 1736 | 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 1 0 1737 | 0 1 0 1 0 0 1 1 0 1 0 0 1 0 1 1 1 1738 | 0 0 1 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1739 | 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1740 | 0 1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 0 1741 | 1 1 1 0 1 0 0 1 1 0 1 1 1 0 0 1 0 1742 | 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 1 0 1743 | 0 1 0 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1744 | 1 1 0 1 1 0 1 1 1 0 0 1 0 1 0 1 1 1745 | 1 1 0 1 0 0 1 0 1 0 1 1 1 0 1 1 1 1746 | 0 1 0 0 0 0 1 1 0 0 1 1 1 1 0 1 1 1747 | 0 0 1 1 1 1 0 1 1 0 1 1 0 0 1 1 1 1748 | 1 1 0 0 0 0 1 1 1 0 1 0 1 0 1 0 1 1749 | 1 1 0 1 1 0 1 1 1 0 1 1 0 0 1 0 1 1750 | 0 1 0 0 0 1 0 1 1 0 1 1 0 1 1 0 0 1751 | 1 0 1 0 0 0 1 0 1 1 1 1 1 0 1 1 0 1752 | 0 0 0 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1753 | 0 0 0 0 0 1 1 1 1 1 0 0 1 1 1 1 0 1754 | 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 1755 | 0 0 1 0 0 1 0 0 0 1 0 1 1 0 0 1 0 1756 | 1 1 0 0 0 0 1 1 1 1 0 1 1 0 0 0 0 1757 | 0 0 1 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1758 | 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 1 0 1759 | 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 0 0 1760 | 0 1 0 1 1 0 1 0 1 1 0 0 0 1 0 1 1 1761 | 0 0 0 0 0 1 1 0 0 1 0 1 1 0 0 0 1 1762 | 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1763 | 1 0 1 1 0 0 1 1 0 0 0 0 0 1 1 0 1 1764 | 0 1 0 1 0 0 1 1 1 0 0 1 0 0 1 0 1 1765 | 1 0 1 0 0 1 0 0 0 0 1 0 1 0 0 1 1 1766 | 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0 1 1 1767 | 1 0 0 1 0 1 1 0 1 0 1 0 1 0 1 1 0 1768 | 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1769 | 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 1 1770 | 1 1 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 1771 | 0 0 1 1 0 1 0 1 0 1 1 1 0 0 1 0 0 1772 | 0 0 1 0 1 1 0 0 1 0 1 1 1 1 0 1 0 1773 | 1 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 1 1774 | 1 0 0 0 1 1 1 1 0 0 1 0 0 1 1 0 0 1775 | 1 1 0 1 0 0 1 1 0 0 0 0 1 1 1 0 1 1776 | 1 0 1 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1777 | 1 0 1 0 1 1 0 1 0 1 1 1 1 0 0 0 1 1778 | 1 1 0 1 0 0 1 0 1 0 1 0 0 1 1 1 0 1779 | 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 1780 | 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1781 | 1 0 0 1 0 1 1 1 0 0 1 0 1 0 1 0 1 1782 | 0 1 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 1783 | 1 1 1 0 1 0 0 1 1 0 1 0 1 1 1 0 1 1784 | 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 0 0 1785 | 0 1 0 0 0 1 0 1 0 1 0 0 0 0 0 0 1 1786 | 0 1 0 0 0 0 1 1 0 1 1 0 1 0 1 0 1 1787 | 0 0 1 0 0 1 0 1 1 1 0 1 0 0 1 0 0 1788 | 0 0 1 0 0 0 1 0 0 0 0 0 1 0 1 1 0 1789 | 1 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0 1790 | 0 0 1 1 1 1 0 1 0 0 1 0 1 0 0 1 1 1791 | 1 0 1 0 0 1 0 0 0 1 0 1 1 0 0 1 0 1792 | 1 0 1 0 1 0 1 1 0 1 1 0 0 1 0 0 0 1793 | 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 1 1794 | 0 1 1 1 0 0 0 0 1 0 1 0 0 0 0 1 1 1795 | 1 1 0 1 1 1 0 1 1 0 1 0 1 0 0 0 1 1796 | 1 0 0 0 0 1 1 1 0 0 0 1 0 1 1 0 1 1797 | 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1798 | 1 0 1 1 1 0 1 0 1 1 1 1 0 1 1 0 0 1799 | 0 0 0 1 1 1 1 1 0 0 1 1 1 0 1 0 1 1800 | 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 1 0 1801 | 1 1 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 1802 | 1 0 1 0 1 1 0 1 0 1 1 1 0 1 0 1 1 1803 | 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 0 1804 | 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 1 1805 | 1 1 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 1806 | 1 0 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 1807 | 1 1 0 1 1 0 1 1 0 0 1 1 0 0 1 1 1 1808 | 1 0 1 0 1 1 0 1 0 0 1 1 0 0 1 1 1 1809 | 1 0 1 1 1 0 1 0 1 0 1 1 1 1 0 1 0 1810 | 0 1 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1811 | 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1812 | 1 0 0 0 1 1 1 1 0 0 1 0 1 1 0 0 0 1813 | 0 0 1 0 1 0 1 1 1 1 1 1 0 0 0 0 1 1814 | 1 1 0 0 1 0 1 1 1 1 1 1 0 0 1 1 0 1815 | 0 0 1 0 0 1 0 1 1 1 1 1 1 1 1 0 1 1816 | 0 1 0 1 1 0 1 0 0 1 1 0 1 1 0 0 0 1817 | 0 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 1818 | 1 0 1 1 1 0 1 0 1 0 0 1 1 1 0 0 1 1819 | 0 1 0 1 0 1 0 1 1 1 1 0 0 0 1 0 1 1820 | 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 0 0 1821 | 1 0 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 1822 | 1 0 0 0 1 1 1 0 0 1 1 1 1 0 0 0 0 1823 | 0 0 0 1 1 1 1 1 1 0 1 1 0 1 0 1 0 1824 | 0 0 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1825 | 0 0 1 0 1 0 1 1 1 1 1 0 0 0 1 1 0 1826 | 0 0 1 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1827 | 0 1 1 0 0 0 0 1 0 1 1 0 1 0 1 0 0 1828 | 1 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 0 1829 | 0 1 1 1 0 0 0 1 0 0 0 0 0 0 1 1 0 1830 | 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 0 1 1831 | 0 1 0 0 0 0 1 0 1 1 1 1 0 1 0 1 0 1832 | 0 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1833 | 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 0 0 1834 | 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 1 1 1835 | 0 0 0 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1836 | 1 0 1 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1837 | 0 1 0 0 0 0 1 0 0 1 0 0 1 0 1 0 1 1838 | 0 0 1 1 1 1 0 0 0 1 1 0 1 1 0 1 1 1839 | 0 1 0 0 0 1 0 1 0 0 1 0 0 1 1 1 0 1840 | 0 1 0 1 0 1 0 0 1 0 1 0 1 1 1 0 0 1841 | 1 1 1 0 1 0 0 1 0 1 1 1 1 0 1 0 0 1842 | 0 1 1 0 0 0 0 1 1 1 1 1 0 1 1 0 0 1843 | 1 1 0 0 0 1 0 1 0 1 0 1 0 0 0 1 0 1844 | 0 0 0 1 0 1 1 0 0 1 1 0 0 1 1 1 0 1845 | 1 0 1 0 1 0 1 1 0 0 1 0 0 1 0 1 0 1846 | 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1847 | 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 1 1848 | 0 0 1 0 1 0 1 1 0 0 1 0 0 1 0 1 0 1849 | 0 0 1 0 1 1 0 1 1 1 1 0 1 1 0 0 1 1850 | 0 0 1 1 0 0 1 1 0 1 1 0 1 1 1 1 0 1851 | 0 0 0 1 1 1 1 0 1 0 1 0 0 1 1 0 0 1852 | 1 1 0 1 0 0 1 1 0 1 1 1 0 0 1 0 1 1853 | 1 1 1 0 1 0 0 0 0 1 1 1 0 0 0 0 0 1854 | 1 1 0 0 1 0 1 1 0 1 1 0 0 0 0 0 0 1855 | 1 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1856 | 0 0 0 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1857 | 0 1 0 0 1 0 1 0 0 1 0 1 1 0 0 1 0 1858 | 0 0 1 1 0 1 0 1 1 0 1 0 1 1 0 0 0 1859 | 1 0 1 1 1 1 0 1 1 0 1 0 0 1 0 1 0 1860 | 1 0 1 1 1 1 0 1 0 0 0 0 0 0 1 0 0 1861 | 0 0 0 0 1 1 1 0 0 1 0 1 1 0 0 0 0 1862 | 1 0 0 1 0 1 1 1 0 1 1 1 1 1 0 1 0 1863 | 1 1 0 1 1 0 1 0 0 1 0 1 0 0 0 0 0 1864 | 0 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 1 1865 | 1 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 0 1866 | 0 0 1 1 1 1 0 1 1 0 1 0 1 1 1 1 0 1867 | 0 0 1 0 1 0 1 0 1 0 1 0 0 1 1 1 0 1868 | 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 1869 | 0 1 0 0 1 0 1 0 1 1 0 1 0 0 1 0 1 1870 | 0 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 1 1871 | 1 0 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1872 | 0 1 0 1 1 0 1 0 0 0 0 0 0 1 1 0 0 1873 | 0 1 0 1 1 1 0 1 1 0 1 0 1 1 1 0 1 1874 | 0 0 1 1 1 1 0 1 1 1 0 0 0 0 0 1 0 1875 | 0 1 1 1 0 0 0 1 0 0 0 1 1 0 0 1 0 1876 | 1 1 1 1 1 0 0 0 1 0 1 0 0 0 0 1 1 1877 | 1 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 0 1878 | 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 0 1 1879 | 0 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 1880 | 1 1 0 1 0 0 1 1 1 0 0 0 0 1 0 1 0 1881 | 1 1 0 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1882 | 0 1 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 1883 | 1 0 1 1 1 1 0 0 1 1 0 1 0 1 1 0 1 1884 | 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1 0 1 1885 | 1 1 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1 1886 | 1 1 0 0 1 0 1 1 0 1 0 0 1 0 0 1 1 1887 | 0 1 0 1 1 1 0 0 0 0 0 1 0 0 0 1 0 1888 | 1 1 0 1 0 1 0 1 0 0 0 1 1 0 1 0 1 1889 | 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 0 1890 | 0 0 1 0 1 0 1 1 1 0 0 0 0 1 1 1 1 1891 | 1 0 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1892 | 1 1 0 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1893 | 1 0 1 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1894 | 1 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 1895 | 1 1 0 0 1 1 0 0 1 1 0 1 1 1 0 0 0 1896 | 1 1 0 0 0 0 1 0 0 1 0 1 0 1 0 1 0 1897 | 0 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 1 1898 | 1 0 1 1 1 0 1 1 1 0 0 0 0 1 1 0 1 1899 | 0 1 0 1 1 0 1 0 1 0 0 1 0 0 1 1 1 1900 | 0 1 0 0 1 0 1 1 0 1 0 1 0 1 1 0 1 1901 | 0 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 1902 | 0 1 0 0 0 0 1 1 0 1 0 0 0 1 1 0 0 1903 | 1 0 1 0 1 1 0 1 0 1 1 0 1 0 0 1 1 1904 | 0 0 0 0 0 1 1 0 1 1 1 1 0 0 1 0 1 1905 | 0 0 1 0 0 1 0 1 1 0 0 1 1 0 0 1 0 1906 | 1 0 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 1907 | 0 1 0 0 0 0 1 0 0 0 1 0 1 1 1 0 0 1908 | 0 1 0 1 1 0 1 1 0 0 0 0 0 0 0 1 1 1909 | 0 1 0 0 1 0 1 1 0 0 1 0 0 1 1 1 1 1910 | 1 0 1 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1911 | 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 1912 | 1 1 0 0 0 1 0 1 0 1 1 0 1 0 1 1 0 1913 | 0 0 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 1914 | 1 0 1 1 1 1 0 1 0 1 1 0 0 1 0 1 1 1915 | 1 0 1 0 0 0 1 1 0 0 1 1 0 1 0 1 1 1916 | 1 0 1 1 1 0 1 1 0 0 0 1 1 0 0 1 0 1917 | 0 0 1 1 0 1 0 0 0 1 0 0 1 1 0 1 1 1918 | 1 1 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0 1919 | 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1920 | 0 1 0 1 0 1 0 0 1 1 0 1 1 0 0 0 1 1921 | 1 1 0 1 1 0 1 1 0 1 1 0 0 1 0 0 0 1922 | 0 0 1 1 0 0 1 0 1 0 0 1 1 1 0 1 0 1923 | 1 0 1 1 0 1 0 0 1 0 1 1 0 1 1 0 1 1924 | 0 1 1 0 1 0 0 0 1 0 1 1 0 1 1 0 1 1925 | 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0 1926 | 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 1 0 1927 | 1 1 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1928 | 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 0 0 1929 | 1 0 1 1 0 1 0 0 0 1 0 0 1 0 0 0 0 1930 | 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0 1931 | 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 0 1 1932 | 1 1 0 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1933 | 0 0 1 1 0 1 0 0 0 0 1 0 1 1 1 1 0 1934 | 1 0 1 0 0 1 0 0 1 0 1 0 0 0 0 0 1 1935 | 0 0 1 1 1 0 1 1 1 0 1 0 0 0 0 1 0 1936 | 1 0 1 1 0 1 0 1 1 1 0 1 0 0 0 1 0 1937 | 1 0 0 1 0 1 1 1 0 1 0 0 0 0 1 1 1 1938 | 1 1 0 0 1 1 0 0 1 0 1 1 1 0 0 0 0 1939 | 1 0 0 1 1 1 1 1 0 0 0 1 0 1 0 0 1 1940 | 0 0 1 1 0 1 0 0 0 1 1 0 0 1 0 0 0 1941 | 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1942 | 0 0 1 1 1 0 1 1 0 1 1 1 1 1 0 1 0 1943 | 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 1 0 1944 | 1 1 0 0 1 0 1 0 0 0 1 1 1 1 0 0 1 1945 | 1 0 1 0 0 0 1 1 0 1 1 0 0 0 0 1 0 1946 | 0 0 1 1 1 0 1 1 1 0 0 0 1 0 0 0 1 1947 | 0 0 1 1 1 1 0 1 0 0 1 0 0 1 0 1 1 1948 | 0 1 1 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1949 | 1 0 0 0 1 1 1 0 1 1 0 1 1 0 0 1 1 1950 | 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1951 | 1 0 1 1 0 0 1 0 1 0 1 0 1 1 0 0 1 1952 | 1 1 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 1953 | 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1954 | 1 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 0 1955 | 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 1956 | 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 0 0 1957 | 1 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 1 1958 | 0 0 1 1 0 1 0 1 1 1 0 1 0 1 1 0 1 1959 | 0 1 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1960 | 1 1 0 0 1 1 0 1 0 1 0 0 1 0 0 0 1 1961 | 1 1 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1 1962 | 0 0 0 1 0 1 1 0 1 1 0 1 1 1 0 0 0 1963 | 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1964 | 0 0 0 0 0 1 1 0 0 0 0 1 1 0 1 1 0 1965 | 1 0 0 0 1 1 1 0 0 0 0 1 1 0 1 0 1 1966 | 0 1 0 1 0 0 1 0 1 1 1 0 0 0 1 0 0 1967 | 0 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 0 1968 | 0 0 1 0 1 0 1 1 1 1 1 0 0 0 1 1 0 1969 | 0 0 1 0 0 0 1 0 0 1 0 1 1 0 0 0 0 1970 | 1 0 1 1 1 1 0 1 1 1 0 0 0 0 0 1 0 1971 | 1 1 1 1 0 0 0 1 1 0 0 0 0 1 0 1 0 1972 | 1 0 1 1 1 1 0 0 1 0 0 0 0 1 1 0 0 1973 | 1 1 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1974 | 0 0 1 1 0 1 0 0 1 0 1 0 1 0 0 0 0 1975 | 0 0 0 0 0 1 1 1 0 0 1 1 0 1 1 0 1 1976 | 0 1 0 0 1 1 0 1 0 1 1 1 1 1 1 0 0 1977 | 0 1 0 1 0 1 0 1 0 1 1 1 1 0 0 1 0 1978 | 1 0 1 1 0 1 0 1 0 1 1 0 0 0 1 0 1 1979 | 1 0 1 1 0 1 0 0 1 0 0 1 0 0 0 0 1 1980 | 1 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 0 1981 | 1 0 1 1 1 1 0 0 1 0 0 0 0 0 1 1 1 1982 | 0 0 0 1 0 1 1 1 1 1 1 1 1 0 1 0 1 1983 | 0 0 1 1 0 0 1 1 0 0 1 0 0 0 0 0 1 1984 | 0 1 0 1 0 1 0 1 1 1 1 0 1 1 0 0 1 1985 | 1 1 0 1 1 1 0 1 1 0 1 1 1 0 0 1 1 1986 | 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 0 1 1987 | 0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 1988 | 0 1 0 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1989 | 1 0 0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1990 | 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 1 1 1991 | 1 0 1 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1992 | 0 0 1 0 0 1 0 1 0 1 1 1 0 0 0 1 1 1993 | 1 0 1 1 1 1 0 1 0 0 0 1 0 0 0 0 1 1994 | 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 1 1995 | 0 1 1 0 0 0 0 0 1 0 1 1 1 0 0 0 1 1996 | 0 0 0 0 0 1 1 1 1 1 1 0 1 1 1 0 0 1997 | 0 0 0 0 0 1 1 1 0 1 0 1 1 1 0 1 0 1998 | 1 1 0 0 0 1 0 0 0 1 0 1 1 0 1 1 0 1999 | 0 1 1 0 1 0 0 1 1 1 1 1 1 0 1 0 0 2000 | 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 0 2001 | 1 0 1 1 1 0 1 1 0 1 0 1 0 0 0 0 1 2002 | 0 1 0 1 0 0 1 1 0 0 0 0 0 0 1 0 1 2003 | 0 0 1 0 1 1 0 0 0 1 1 1 0 0 1 0 0 2004 | 1 0 1 1 1 0 1 0 0 0 1 0 1 0 0 1 0 2005 | 1 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 2006 | 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1 1 0 2007 | 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 2008 | 0 0 1 0 1 1 0 0 1 1 1 0 0 1 0 1 0 2009 | 0 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 2010 | 0 0 1 0 0 1 0 1 0 1 0 1 1 1 1 1 1 2011 | 0 0 1 0 0 0 1 0 0 1 1 1 1 0 1 1 0 2012 | 1 0 1 1 0 1 0 1 1 0 1 1 0 0 1 0 1 2013 | 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 0 2014 | 0 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 0 2015 | 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 1 0 2016 | 1 1 0 1 1 1 0 1 1 1 0 1 0 0 1 1 0 2017 | 0 0 0 1 0 1 1 1 1 1 1 0 0 1 0 0 0 2018 | 0 1 0 1 0 0 1 1 1 0 1 1 1 0 0 1 1 2019 | 0 1 0 0 1 0 1 1 1 1 1 0 1 0 1 0 0 2020 | 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 0 2021 | 0 0 1 1 1 1 0 1 1 0 1 1 0 0 1 0 1 2022 | 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 1 2023 | 0 0 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0 2024 | 0 0 0 0 0 1 1 0 1 0 0 0 0 1 1 1 0 2025 | 1 1 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 2026 | 1 0 1 0 1 0 1 1 0 0 1 0 1 0 0 0 1 2027 | 1 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 1 2028 | 0 1 1 1 1 0 0 0 0 1 0 1 1 1 1 1 1 2029 | 0 1 1 0 1 0 0 1 1 0 0 1 1 1 0 1 0 2030 | 0 0 1 1 1 1 0 0 0 0 0 0 1 0 0 1 0 2031 | 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 2032 | 0 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 1 2033 | 0 1 1 1 0 0 0 0 1 1 0 1 1 1 0 1 0 2034 | 1 1 0 1 0 0 1 1 0 1 1 0 1 0 1 0 0 2035 | 1 0 0 0 0 1 1 1 1 1 0 1 0 1 1 1 0 2036 | 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 2037 | 1 0 1 1 1 0 1 0 0 1 1 1 1 0 1 1 1 2038 | 0 0 1 0 0 0 1 0 1 1 0 0 1 0 0 0 0 2039 | 0 1 0 1 0 0 1 0 1 1 1 1 1 1 0 1 0 2040 | 1 0 0 1 0 1 1 0 1 1 1 0 1 1 1 1 0 2041 | 0 1 0 1 1 1 0 0 1 0 1 1 1 1 1 0 0 2042 | 1 0 1 0 1 1 0 0 1 1 1 1 0 1 0 1 0 2043 | 0 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 2044 | 0 0 0 0 0 1 1 1 1 1 0 1 0 0 1 1 0 2045 | 1 0 1 1 0 0 1 0 0 1 1 1 0 1 1 1 0 2046 | 1 1 1 0 0 0 0 0 1 1 1 1 1 0 1 0 0 2047 | 0 0 1 0 1 1 0 0 0 0 0 0 1 0 0 1 1 2048 | 0 0 1 1 0 1 0 0 0 0 1 1 1 1 1 1 0 2049 | 1 0 1 0 1 1 0 1 0 1 1 0 0 0 0 0 1 2050 | 0 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 2051 | 0 1 1 0 1 0 0 1 1 1 0 0 0 0 0 0 0 2052 | 0 1 0 1 0 0 1 1 0 1 0 0 0 0 1 0 0 2053 | 1 1 1 1 1 0 0 1 1 0 1 1 0 1 0 0 0 2054 | 0 0 1 1 0 1 0 0 1 0 1 1 0 1 0 1 0 2055 | 0 0 1 0 1 0 1 1 1 0 0 0 1 0 0 1 0 2056 | 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 2057 | 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 2058 | 1 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 1 2059 | 1 1 0 1 1 0 1 1 0 1 0 0 0 1 0 0 1 2060 | 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 1 2061 | 0 1 0 0 0 1 0 1 0 1 0 1 1 1 1 1 0 2062 | 1 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 2063 | 0 1 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 2064 | 1 1 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 2065 | 1 0 1 1 1 1 0 1 0 1 1 0 1 0 0 0 0 2066 | 0 1 0 1 0 0 1 1 0 1 1 0 1 1 0 1 1 2067 | 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 2068 | 0 1 0 1 1 1 0 1 1 1 1 1 0 1 0 0 1 2069 | 1 1 0 1 1 1 0 0 1 0 0 0 0 1 1 0 0 2070 | 0 1 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 2071 | 1 0 1 0 0 1 0 1 0 1 0 1 1 1 1 1 0 2072 | 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1 1 0 2073 | 1 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 2074 | 1 0 1 0 0 1 0 1 0 1 0 1 1 0 0 0 1 2075 | 0 1 1 1 0 0 0 0 0 1 0 1 1 0 0 1 1 2076 | 0 1 0 1 1 0 1 1 0 0 1 1 0 0 1 0 0 2077 | 0 0 1 1 0 1 0 1 0 0 1 1 1 1 1 0 1 2078 | 1 1 1 0 1 0 0 1 0 0 1 1 1 1 0 1 1 2079 | 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 2080 | 0 0 0 1 1 1 1 1 0 0 1 1 1 0 1 0 1 2081 | 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 1 1 2082 | 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 0 1 2083 | 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 2084 | 0 1 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 2085 | 1 1 0 0 0 0 1 0 0 1 1 1 1 0 1 1 1 2086 | 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 1 1 2087 | 0 1 1 1 1 0 0 0 1 1 0 0 1 0 1 0 0 2088 | 1 1 1 1 1 0 0 0 1 0 1 1 1 1 0 1 1 2089 | 0 0 0 0 1 1 1 0 1 0 0 0 0 0 0 1 0 2090 | 0 1 0 1 0 0 1 0 1 1 1 0 0 0 1 1 0 2091 | 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 0 2092 | 0 0 1 1 0 0 1 1 0 1 0 1 0 0 0 0 0 2093 | 1 1 0 1 0 1 0 0 0 0 1 0 1 1 1 0 1 2094 | 1 0 0 1 0 1 1 1 0 1 1 0 1 1 1 1 0 2095 | 0 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 1 2096 | 0 1 1 1 1 0 0 1 0 0 1 1 0 0 0 0 1 2097 | 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 0 1 2098 | 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 2099 | 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 2100 | 0 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 1 2101 | 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 1 0 2102 | 1 1 0 0 1 0 1 1 0 1 1 0 0 1 0 1 1 2103 | 1 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 1 2104 | 1 0 1 1 1 0 1 1 1 1 1 1 0 1 0 1 0 2105 | 1 0 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 2106 | 1 1 0 0 1 0 1 1 1 1 1 1 1 1 0 1 0 2107 | 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 2108 | 1 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 2109 | 0 0 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 2110 | 0 1 0 1 1 1 0 1 1 1 1 1 1 0 1 1 0 2111 | 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 2112 | 0 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1 2113 | 0 0 0 0 1 1 1 0 0 1 0 0 1 0 1 0 1 2114 | 1 0 1 1 0 0 1 0 0 0 1 0 1 1 0 0 1 2115 | 0 1 0 1 0 0 1 0 0 0 1 1 0 0 1 1 1 2116 | 1 0 1 1 1 1 0 0 0 0 0 0 1 0 0 1 1 2117 | 0 1 0 0 1 1 0 1 0 0 0 1 1 0 1 0 0 2118 | 1 0 0 1 0 1 1 1 0 0 1 0 0 1 1 0 1 2119 | 1 0 1 0 1 1 0 1 0 0 0 1 0 0 0 1 1 2120 | 1 1 0 1 0 0 1 0 1 0 0 1 1 0 1 0 1 2121 | 0 1 1 0 1 0 0 0 0 0 0 1 0 1 1 1 1 2122 | 1 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 2123 | 0 0 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1 2124 | 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 0 2125 | 0 1 1 1 1 0 0 1 0 0 0 0 0 1 1 1 1 2126 | 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 2127 | 1 0 1 0 0 1 0 1 0 0 1 1 1 1 0 1 1 2128 | 1 0 0 1 1 1 1 0 0 1 0 0 1 0 0 1 0 2129 | 0 0 1 0 1 0 1 0 0 0 1 1 1 0 1 1 0 2130 | 0 1 0 0 1 0 1 0 1 0 1 1 1 1 0 1 1 2131 | 1 1 0 0 0 0 1 1 0 0 1 0 1 0 1 1 1 2132 | 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 2133 | 1 0 1 1 0 1 0 0 0 1 1 0 0 0 1 0 0 2134 | 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 2135 | 1 1 0 0 0 0 1 0 1 0 1 1 1 1 1 0 1 2136 | 1 1 0 1 1 0 1 1 1 1 0 0 0 1 1 1 1 2137 | 1 0 0 0 0 1 1 1 0 1 0 1 1 1 0 1 1 2138 | 1 1 0 1 0 1 0 1 1 0 1 1 1 0 1 0 0 2139 | 0 1 0 1 0 0 1 1 1 0 0 1 1 0 1 1 0 2140 | 1 0 0 1 1 1 1 1 0 0 0 1 0 1 1 0 0 2141 | 0 1 0 1 0 0 1 1 0 1 1 1 0 1 1 1 1 2142 | 0 1 0 0 1 1 0 0 0 0 1 1 1 1 1 0 1 2143 | 0 0 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 2144 | 1 1 1 1 1 0 0 0 1 1 1 0 1 0 1 0 0 2145 | 0 0 0 0 0 1 1 0 0 0 0 1 0 0 1 1 1 2146 | 1 1 0 0 1 0 1 0 0 0 0 1 1 0 1 0 0 2147 | 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 0 1 2148 | 1 0 1 0 1 1 0 0 1 0 0 0 0 0 1 0 0 2149 | 1 0 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 2150 | 0 0 1 0 0 0 1 0 0 1 1 0 1 0 0 0 0 2151 | 1 1 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 2152 | 0 0 0 1 1 1 1 1 0 0 0 0 1 1 0 0 0 2153 | 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 2154 | 1 0 0 1 0 1 1 1 1 0 1 1 0 1 0 0 1 2155 | 1 1 0 0 1 1 0 1 1 0 0 1 1 0 1 1 0 2156 | 1 1 0 1 1 0 1 1 0 0 1 0 1 1 0 1 0 2157 | 1 1 1 1 1 0 0 0 0 1 1 0 1 1 0 0 0 2158 | 1 0 1 1 1 1 0 0 1 0 0 0 0 0 1 0 1 2159 | 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 1 2160 | 1 0 1 1 1 0 1 1 1 1 1 0 0 1 0 0 0 2161 | 0 0 1 1 0 1 0 0 0 1 0 0 1 1 1 0 0 2162 | 1 1 0 1 0 0 1 0 0 0 1 0 1 0 0 0 0 2163 | 1 1 0 0 1 0 1 0 1 1 0 1 0 0 1 1 1 2164 | 1 0 0 0 1 1 1 1 0 0 1 0 0 1 0 0 0 2165 | 1 1 0 0 0 0 1 0 1 0 1 1 1 0 0 0 0 2166 | 1 0 1 0 1 1 0 1 0 0 0 0 1 1 0 1 1 2167 | 0 0 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 2168 | 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 0 1 2169 | 0 0 0 1 1 1 1 1 0 1 0 0 0 0 1 0 0 2170 | 1 1 0 1 1 0 1 0 1 1 0 0 0 1 0 1 1 2171 | 1 1 0 0 1 1 0 0 1 0 0 1 1 0 1 1 0 2172 | 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 0 2173 | 0 0 0 0 1 1 1 0 0 0 0 1 0 1 0 1 1 2174 | 0 1 0 0 0 1 0 1 0 1 0 0 1 1 0 1 1 2175 | 1 1 0 0 1 0 1 0 1 0 1 0 1 1 0 0 1 2176 | 0 1 1 0 0 0 0 0 1 0 1 1 1 1 1 1 0 2177 | 0 0 1 0 0 1 0 0 1 1 0 0 1 0 1 1 1 2178 | 1 0 1 1 1 1 0 1 1 0 0 0 0 1 1 0 0 2179 | 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 2180 | 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0 0 1 2181 | 1 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 0 2182 | 1 1 1 1 1 0 0 1 0 1 1 1 0 0 1 0 0 2183 | 1 0 1 0 1 0 1 0 0 1 0 0 0 0 1 1 0 2184 | 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 2185 | 0 0 1 1 1 1 0 1 0 0 0 1 0 0 0 0 1 2186 | 1 1 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 2187 | 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0 0 2188 | 0 0 0 1 0 1 1 1 1 0 0 1 0 0 0 1 0 2189 | 0 0 1 0 1 0 1 1 0 0 0 0 0 1 1 1 1 2190 | 1 1 1 0 0 0 0 1 1 1 1 1 0 1 1 1 0 2191 | 0 0 0 1 1 1 1 0 1 1 0 1 1 1 0 1 0 2192 | 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1 1 1 2193 | 0 1 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 2194 | 0 0 1 0 1 0 1 0 1 0 0 1 1 0 1 1 1 2195 | 0 0 1 0 1 0 1 0 0 1 0 0 0 0 0 1 0 2196 | 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 2197 | 1 0 1 0 1 0 1 1 0 0 1 1 1 1 0 1 0 2198 | 1 1 0 1 0 1 0 0 1 1 1 0 0 1 1 1 0 2199 | 0 1 1 0 1 0 0 1 0 0 0 1 1 1 0 0 0 2200 | 1 1 0 1 0 0 1 1 0 1 0 0 1 1 0 0 1 2201 | 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 2202 | 1 1 0 0 1 0 1 1 0 0 1 0 1 0 1 0 1 2203 | 0 0 0 0 1 1 1 0 1 1 0 1 0 0 0 0 1 2204 | 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1 1 0 2205 | 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 2206 | 1 0 1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 2207 | 1 0 0 0 1 1 1 0 0 1 0 1 1 1 1 1 0 2208 | 0 0 1 0 1 0 1 1 0 1 0 0 1 1 1 1 1 2209 | 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 2210 | 0 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 2211 | 0 1 0 0 1 0 1 1 1 1 0 1 1 1 0 0 1 2212 | 0 0 0 1 0 1 1 1 0 1 1 1 1 0 1 0 0 2213 | 0 0 1 0 0 0 1 1 1 0 1 1 0 0 1 0 0 2214 | 1 1 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 2215 | 1 0 1 0 1 1 0 0 1 0 1 1 1 0 1 1 0 2216 | 0 0 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 2217 | 1 1 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 2218 | 1 0 1 1 1 1 0 1 1 1 1 0 0 1 0 0 1 2219 | 1 0 1 1 0 0 1 0 1 1 0 1 1 1 0 1 0 2220 | 1 1 0 0 1 1 0 1 0 1 0 1 1 0 1 1 0 2221 | 0 0 1 1 0 1 0 1 1 0 0 0 0 1 1 1 0 2222 | 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 1 1 2223 | 1 0 1 1 1 1 0 1 0 1 0 0 1 0 0 1 0 2224 | 1 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 1 2225 | 0 0 1 1 0 0 1 1 1 0 1 0 1 0 1 1 0 2226 | 1 0 1 1 1 1 0 0 0 1 1 0 0 1 0 1 0 2227 | 1 1 0 1 1 1 0 1 1 0 0 0 1 0 0 0 1 2228 | 1 0 1 1 1 1 0 1 0 1 0 0 1 0 1 0 1 2229 | 0 0 0 1 1 1 1 1 1 1 0 0 0 1 0 1 0 2230 | 0 1 0 1 0 0 1 1 0 0 1 0 1 0 0 0 1 2231 | 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 0 1 2232 | 0 0 1 0 1 1 0 0 1 0 1 1 0 0 0 0 0 2233 | 1 1 0 1 0 0 1 1 0 1 1 1 0 1 0 1 1 2234 | 1 1 0 1 0 0 1 1 0 1 1 1 1 0 0 0 1 2235 | 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 2236 | 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 2237 | 1 0 1 0 1 1 0 1 1 0 0 0 1 1 0 1 0 2238 | 0 1 0 0 0 0 1 0 1 0 0 1 1 0 1 1 0 2239 | 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 2240 | 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 1 1 2241 | 0 0 0 1 1 1 1 0 0 0 1 0 1 1 1 0 1 2242 | 0 0 1 1 0 1 0 1 1 0 0 1 0 0 0 0 1 2243 | 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 0 1 2244 | 0 0 1 0 0 0 1 0 0 1 1 0 1 0 0 1 0 2245 | 0 0 1 0 0 0 1 1 1 1 0 0 1 1 1 1 0 2246 | 1 1 0 1 1 0 1 1 0 1 0 0 1 0 1 0 1 2247 | 1 0 1 0 1 1 0 0 0 0 0 0 1 0 1 1 1 2248 | 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 2249 | 1 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 2250 | 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 1 1 2251 | 0 1 0 0 1 0 1 0 0 0 0 0 1 1 1 1 0 2252 | 0 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 1 2253 | 1 1 0 0 0 0 1 0 0 1 1 0 0 1 1 1 1 2254 | 0 1 1 0 0 0 0 1 1 1 0 0 1 0 0 1 0 2255 | 0 1 0 0 0 1 0 1 1 0 0 0 0 0 1 1 0 2256 | 0 0 1 1 0 0 1 0 0 1 1 0 1 1 0 1 1 2257 | 1 0 0 0 0 1 1 1 1 1 1 1 0 1 0 1 0 2258 | 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 1 1 2259 | 0 0 0 1 1 1 1 0 1 1 1 1 0 0 0 1 1 2260 | 0 0 0 0 0 1 1 1 0 1 0 1 1 0 0 1 0 2261 | 1 0 1 0 0 1 0 1 0 1 1 0 0 1 1 0 1 2262 | 1 1 1 1 1 0 0 0 0 1 1 0 1 1 1 0 0 2263 | 0 0 1 0 1 1 0 0 1 1 0 1 0 0 0 1 1 2264 | 1 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 2265 | 0 0 1 1 1 0 1 1 1 1 0 1 0 0 0 0 0 2266 | 1 1 0 1 0 0 1 1 1 0 1 0 1 0 0 1 1 2267 | 0 0 1 0 0 1 0 1 1 0 0 0 0 0 0 0 1 2268 | 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 1 0 2269 | 0 0 1 0 1 1 0 1 1 0 0 0 1 0 1 0 0 2270 | 0 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0 0 2271 | 0 0 1 0 1 0 1 1 1 1 0 1 0 1 1 1 0 2272 | 0 0 1 0 1 0 1 1 1 0 0 0 1 0 0 1 0 2273 | 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 2274 | 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 1 1 2275 | 1 1 0 1 1 1 0 0 1 1 1 1 0 1 0 1 0 2276 | 1 0 1 1 1 0 1 1 0 0 1 1 0 1 0 0 0 2277 | 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 0 1 2278 | 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 1 2279 | 1 1 0 0 1 0 1 1 1 1 1 0 1 0 0 1 1 2280 | 0 0 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 2281 | 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 2282 | 1 0 1 0 0 1 0 1 1 1 1 0 0 1 0 0 1 2283 | 0 1 0 0 1 1 0 0 0 1 1 1 0 1 1 1 1 2284 | 0 0 1 1 0 1 0 0 1 0 1 1 1 0 0 0 1 2285 | 1 1 0 1 0 0 1 1 0 1 0 0 1 1 0 1 1 2286 | 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 0 0 2287 | 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 1 0 2288 | 0 0 1 1 1 1 0 0 1 1 1 1 1 0 0 1 1 2289 | 1 0 1 0 0 1 0 0 1 1 0 1 1 0 0 1 0 2290 | 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 2291 | 0 1 0 0 1 0 1 1 0 0 0 0 1 1 0 0 1 2292 | 1 0 1 0 1 1 0 1 1 1 1 1 0 1 0 0 1 2293 | 1 1 0 1 1 0 1 0 1 0 0 1 0 1 1 1 0 2294 | 1 0 1 0 1 1 0 1 0 1 0 1 1 0 1 1 0 2295 | 0 1 0 1 1 0 1 1 0 1 0 0 1 0 0 0 0 2296 | 1 1 0 0 0 1 0 1 0 1 1 0 1 1 1 1 0 2297 | 0 0 1 1 1 0 1 0 1 1 1 0 1 1 0 0 1 2298 | 1 0 1 1 0 0 1 1 0 0 1 0 0 0 1 1 0 2299 | 1 0 1 1 0 1 0 0 1 1 1 1 1 0 1 1 0 2300 | 1 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 2301 | 0 0 1 1 0 0 1 1 1 0 1 1 0 1 0 0 0 2302 | 0 1 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 2303 | 0 0 1 1 1 0 1 1 1 0 0 0 1 1 1 0 0 2304 | 0 1 1 0 0 0 0 0 1 1 0 1 1 0 1 0 0 2305 | 1 0 1 0 1 1 0 0 1 1 1 0 1 1 0 1 1 2306 | 1 0 1 1 1 0 1 1 1 1 0 1 1 0 1 1 0 2307 | 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 1 0 2308 | 1 1 0 1 1 1 0 0 1 1 1 1 0 1 0 0 1 2309 | 1 1 0 1 1 0 1 0 1 1 0 1 0 0 1 0 1 2310 | 1 0 1 1 0 0 1 0 0 0 0 0 1 1 0 0 0 2311 | 1 1 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 2312 | 0 1 0 0 0 0 1 1 1 0 1 0 1 1 0 0 1 2313 | 1 0 1 1 1 1 0 1 0 1 1 0 1 1 1 1 0 2314 | 0 0 0 1 1 1 1 0 0 1 1 1 1 1 0 0 1 2315 | 1 0 1 0 1 1 0 0 1 0 0 0 1 1 1 0 0 2316 | 1 0 0 0 1 1 1 1 0 1 0 0 1 0 1 1 0 2317 | 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 1 1 2318 | 1 1 0 1 0 0 1 1 1 1 0 0 0 1 1 1 0 2319 | 1 1 0 1 0 1 0 0 0 0 1 1 0 1 1 0 0 2320 | 0 1 0 1 1 0 1 0 0 1 1 1 0 1 1 1 1 2321 | 1 1 1 1 0 0 0 1 1 0 0 0 1 1 0 0 0 2322 | 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 0 0 2323 | 1 1 0 0 0 0 1 1 1 0 1 0 0 1 0 1 1 2324 | 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 1 2325 | 0 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0 0 2326 | 0 1 0 0 1 1 0 1 0 0 0 1 0 1 1 0 0 2327 | 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 0 1 2328 | 1 1 1 0 1 0 0 0 0 0 1 0 1 1 1 0 1 2329 | 0 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 1 2330 | 1 0 0 1 1 1 1 0 1 0 0 0 1 0 1 0 0 2331 | 1 0 0 1 0 1 1 1 0 0 1 0 1 0 1 0 0 2332 | 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 2333 | 1 0 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 2334 | 1 1 0 1 1 0 1 0 0 1 1 0 1 1 1 1 1 2335 | 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 0 2336 | 1 1 0 1 1 1 0 0 1 0 1 0 1 1 1 1 0 2337 | 0 0 1 0 1 1 0 1 0 1 1 0 1 0 0 0 1 2338 | 1 0 1 1 1 0 1 1 1 0 1 0 0 0 0 0 1 2339 | 0 0 1 1 1 0 1 1 1 0 1 0 0 0 0 1 0 2340 | 0 0 1 0 0 1 0 0 0 0 1 0 1 0 1 0 0 2341 | 1 1 0 1 0 0 1 0 0 0 1 0 1 1 0 0 0 2342 | 0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 1 0 2343 | 0 0 1 1 0 1 0 0 1 1 1 0 1 1 1 0 0 2344 | 0 1 0 0 1 0 1 0 1 1 1 0 1 0 1 0 0 2345 | 1 1 0 0 1 1 0 0 1 0 0 1 1 1 0 0 1 2346 | 1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 0 0 2347 | 0 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 0 2348 | 1 1 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 2349 | 0 1 0 1 1 0 1 1 0 1 0 0 1 0 0 1 0 2350 | 0 1 0 0 0 1 0 1 0 1 1 1 0 0 1 1 1 2351 | 0 0 1 1 1 0 1 1 1 1 0 1 1 0 0 1 0 2352 | 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 1 1 2353 | 1 0 0 0 0 1 1 0 1 0 1 0 0 0 1 1 0 2354 | 0 1 0 1 1 0 1 1 0 0 1 0 1 1 1 0 0 2355 | 1 0 1 1 0 1 0 1 1 0 0 0 1 0 0 0 0 2356 | 1 1 0 1 1 0 1 1 0 1 0 0 0 0 1 0 0 2357 | 0 1 0 0 1 0 1 1 1 1 1 0 1 1 0 0 0 2358 | 0 0 1 1 0 1 0 0 0 0 1 1 1 0 1 1 0 2359 | 1 0 0 0 1 1 1 0 1 1 0 0 0 0 1 0 0 2360 | 1 1 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 2361 | 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 2362 | 1 0 1 0 0 1 0 1 1 1 1 1 0 1 0 1 1 2363 | 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 2364 | 0 1 0 0 1 1 0 1 1 1 0 0 0 1 0 1 0 2365 | 0 1 1 0 1 0 0 0 1 0 1 0 1 0 0 1 1 2366 | 0 1 0 1 1 1 0 1 0 0 1 1 1 1 0 0 1 2367 | 0 1 0 0 1 0 1 1 0 1 0 1 0 0 0 1 1 2368 | 1 0 1 1 1 1 0 1 1 0 0 0 1 0 0 1 0 2369 | 0 0 1 1 1 1 0 1 0 0 0 0 0 0 1 0 0 2370 | 1 0 1 1 0 0 1 1 1 0 0 1 1 1 0 1 1 2371 | 0 1 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 2372 | 0 0 1 1 0 1 0 1 0 1 1 1 0 0 1 0 0 2373 | 0 1 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 2374 | 0 0 1 0 1 1 0 0 1 1 0 1 0 1 0 1 0 2375 | 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 2376 | 0 1 0 1 0 1 0 1 0 0 1 0 1 1 1 0 0 2377 | 0 1 0 1 1 1 0 0 0 1 1 1 0 1 1 0 0 2378 | 0 1 0 0 1 1 0 0 1 0 1 0 0 1 0 1 1 2379 | 0 1 1 1 1 0 0 0 1 1 0 1 0 0 1 1 0 2380 | 0 0 1 1 1 1 0 0 0 0 1 0 0 1 0 1 1 2381 | 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 1 0 2382 | 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 2383 | 0 1 0 0 0 0 1 0 1 0 0 0 1 1 1 1 1 2384 | 1 0 1 1 1 1 0 1 0 1 0 1 0 1 0 1 1 2385 | 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 0 2386 | 0 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0 1 2387 | 0 0 1 0 1 1 0 0 1 0 1 1 0 0 0 0 0 2388 | 0 1 0 0 0 0 1 1 1 1 0 1 1 1 1 0 0 2389 | 0 1 0 0 1 1 0 0 0 1 0 0 1 1 1 1 1 2390 | 0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 2391 | 1 0 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 2392 | 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 0 1 2393 | 0 1 1 0 0 0 0 0 1 1 0 0 1 0 1 1 0 2394 | 0 1 0 0 1 0 1 1 1 1 0 1 0 0 0 0 1 2395 | 1 1 0 1 1 0 1 1 0 0 1 0 0 1 1 1 1 2396 | 1 0 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 2397 | 0 0 1 1 1 0 1 1 0 0 0 0 1 0 1 1 0 2398 | 0 1 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 2399 | 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 2400 | 0 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 2401 | 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 2402 | 0 1 1 0 0 0 0 0 0 1 1 0 0 1 0 1 0 2403 | 0 1 0 0 1 0 1 1 0 1 1 1 0 0 0 0 1 2404 | 1 1 1 0 1 0 0 0 1 0 1 0 0 0 0 1 0 2405 | 1 1 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 2406 | 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 0 1 2407 | 0 0 1 0 1 1 0 0 0 1 0 0 1 1 1 0 0 2408 | 0 0 1 0 1 0 1 0 0 1 1 0 1 1 1 0 0 2409 | 1 1 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 2410 | 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1 1 0 2411 | 1 1 0 1 1 0 1 1 1 1 1 0 1 0 0 1 0 2412 | 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 2413 | 0 1 0 0 1 0 1 1 0 0 0 0 1 0 1 1 1 2414 | 1 1 0 0 1 0 1 0 1 1 0 1 1 1 1 0 0 2415 | 1 0 1 0 0 0 1 1 0 1 0 1 0 1 0 1 1 2416 | 0 0 1 0 0 1 0 1 1 0 1 1 0 1 1 1 0 2417 | 0 1 0 1 0 0 1 1 1 0 0 0 0 1 0 1 0 2418 | 0 0 0 1 0 1 1 0 0 0 0 1 1 1 1 0 0 2419 | 0 0 1 0 1 1 0 1 1 1 1 0 1 0 0 1 1 2420 | 1 1 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 2421 | 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 2422 | 0 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 0 2423 | 1 0 1 1 0 1 0 0 1 1 0 0 0 0 1 1 1 2424 | 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 1 0 2425 | 1 1 0 0 1 0 1 0 1 0 1 0 1 1 0 0 1 2426 | 0 0 1 1 0 1 0 1 1 0 0 1 0 0 1 0 0 2427 | 1 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 0 2428 | 0 0 1 1 0 1 0 1 1 0 0 0 0 1 1 0 1 2429 | 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 2430 | 0 0 0 1 0 1 1 1 0 1 0 1 1 1 0 0 1 2431 | 0 1 1 0 0 0 0 1 0 1 1 1 0 1 1 1 0 2432 | 1 0 1 1 0 1 0 1 0 0 0 0 0 0 1 1 1 2433 | 1 0 1 1 0 1 0 0 0 1 1 0 0 1 1 1 1 2434 | 0 0 1 0 0 0 1 1 0 0 1 1 0 1 0 0 1 2435 | 0 0 1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 2436 | 1 1 1 0 1 0 0 1 1 1 1 0 1 0 0 1 1 2437 | 1 0 0 1 1 1 1 1 0 0 1 0 0 1 0 1 0 2438 | 0 0 1 1 0 0 1 0 1 0 1 0 0 1 0 0 0 2439 | 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0 2440 | 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 2441 | 1 1 1 0 0 0 0 0 1 0 0 1 1 1 1 0 0 2442 | 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 2443 | 0 1 0 1 0 1 0 0 1 0 0 1 0 0 0 0 0 2444 | 1 0 1 1 0 1 0 0 0 0 0 0 1 1 0 1 0 2445 | 1 1 1 0 0 0 0 1 0 0 0 1 1 1 1 1 1 2446 | 0 0 1 1 1 0 1 1 0 1 0 0 1 0 0 1 1 2447 | 0 0 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 2448 | 0 0 1 0 1 1 0 0 1 0 0 1 0 0 0 1 1 2449 | 0 0 1 1 0 1 0 1 1 1 0 1 1 1 0 1 1 2450 | 1 1 0 0 1 1 0 1 1 1 1 0 1 1 1 1 1 2451 | 1 0 1 1 1 0 1 1 0 0 0 0 0 1 1 0 0 2452 | 0 1 0 0 1 1 0 1 1 0 1 1 0 0 0 0 0 2453 | 1 1 0 1 1 0 1 1 1 1 0 0 0 0 0 1 1 2454 | 0 1 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 2455 | 0 1 0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 2456 | 1 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 2457 | 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 1 1 2458 | 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 0 1 2459 | 1 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 1 2460 | 1 0 1 1 1 1 0 0 1 1 0 1 1 0 1 0 1 2461 | 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 2462 | 1 1 0 1 0 1 0 1 1 1 1 0 1 0 1 1 0 2463 | 1 1 0 1 0 1 0 0 1 1 1 1 1 0 1 1 0 2464 | 1 1 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 2465 | 1 0 1 1 1 1 0 0 1 0 1 1 1 1 1 1 1 2466 | 1 1 0 0 0 0 1 1 0 0 1 1 0 1 1 1 0 2467 | 1 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 0 2468 | 1 1 0 0 1 1 0 0 1 0 0 1 0 1 1 0 0 2469 | 1 1 0 0 1 1 0 1 0 0 1 1 0 1 1 0 0 2470 | 0 1 0 1 0 1 0 0 0 1 1 0 1 1 0 0 0 2471 | 0 1 0 1 0 1 0 1 0 0 1 1 1 1 0 1 1 2472 | 1 0 1 1 0 0 1 0 0 1 1 1 0 1 1 0 1 2473 | 1 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 0 2474 | 1 1 0 1 1 0 1 1 0 1 0 0 1 1 1 0 0 2475 | 1 0 1 1 1 1 0 1 1 0 0 0 1 0 0 1 1 2476 | 0 1 0 1 0 0 1 0 1 0 1 1 1 0 1 0 1 2477 | 1 1 0 1 1 1 0 0 0 0 1 0 0 1 1 1 0 2478 | 1 1 0 0 1 0 1 1 1 1 1 0 1 1 0 1 1 2479 | 1 1 0 1 0 0 1 1 0 1 0 0 1 1 1 0 0 2480 | 0 0 0 0 0 1 1 1 1 0 0 1 1 0 1 0 1 2481 | 0 1 0 1 1 0 1 0 0 0 1 0 1 0 0 1 0 2482 | 1 1 0 1 0 1 0 1 0 0 1 0 1 0 0 0 0 2483 | 1 0 1 0 1 1 0 0 0 1 0 0 0 1 1 1 1 2484 | 1 0 1 0 1 1 0 1 0 0 1 1 0 0 0 1 1 2485 | 1 1 0 1 0 0 1 1 0 1 1 0 1 1 1 1 1 2486 | 1 0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 2487 | 1 0 0 1 0 1 1 0 0 0 1 1 0 1 1 0 0 2488 | 0 0 0 1 0 1 1 0 1 0 1 1 1 0 1 0 1 2489 | 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 0 2490 | 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 1 0 2491 | 0 1 1 0 0 0 0 1 0 0 1 1 1 1 1 0 1 2492 | 0 1 1 1 1 0 0 1 1 1 0 0 0 0 0 1 0 2493 | 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0 0 1 2494 | 0 1 0 1 0 0 1 1 1 0 1 0 1 0 1 1 1 2495 | 1 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 1 2496 | 0 1 0 1 0 1 0 1 1 0 1 1 0 1 1 0 0 2497 | 1 0 0 0 1 1 1 0 0 1 1 1 0 1 0 1 0 2498 | 0 1 0 1 1 0 1 0 1 0 0 1 0 1 1 0 1 2499 | 0 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 1 2500 | 1 1 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 2501 | -------------------------------------------------------------------------------- /examples/BreastCancerDemo.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 2 | from pyTsetlinMachineParallel.tools import Binarizer 3 | import numpy as np 4 | 5 | from sklearn import datasets 6 | from sklearn.model_selection import train_test_split 7 | 8 | breast_cancer = datasets.load_breast_cancer() 9 | X = breast_cancer.data 10 | Y = breast_cancer.target 11 | 12 | b = Binarizer(max_bits_per_feature = 10) 13 | b.fit(X) 14 | X_transformed = b.transform(X) 15 | 16 | tm = MultiClassTsetlinMachine(800, 40, 5.0) 17 | 18 | print("\nMean accuracy over 100 runs:\n") 19 | tm_results = np.empty(0) 20 | for i in range(100): 21 | X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y, test_size=0.2) 22 | 23 | tm.fit(X_train, Y_train, epochs=25) 24 | tm_results = np.append(tm_results, np.array(100*(tm.predict(X_test) == Y_test).mean())) 25 | print("#%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1))) 26 | -------------------------------------------------------------------------------- /examples/FashionMNISTDemo2DConvolutionWeightedClauses.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 2 | import numpy as np 3 | from time import time 4 | import cv2 5 | from keras.datasets import fashion_mnist 6 | 7 | (X_train, Y_train), (X_test, Y_test) = fashion_mnist.load_data() 8 | X_train = np.copy(X_train) 9 | X_test = np.copy(X_test) 10 | 11 | for i in range(X_train.shape[0]): 12 | X_train[i,:] = cv2.adaptiveThreshold(X_train[i], 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 13 | 14 | for i in range(X_test.shape[0]): 15 | X_test[i,:] = cv2.adaptiveThreshold(X_test[i], 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 16 | 17 | tm = MultiClassConvolutionalTsetlinMachine2D(8000, 100*100, 10.0, (10, 10), weighted_clauses=True) 18 | 19 | print("\nAccuracy over 20 epochs:\n") 20 | for i in range(20): 21 | start = time() 22 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 23 | stop = time() 24 | 25 | result = 100*(tm.predict(X_test) == Y_test).mean() 26 | 27 | print("#%d Accuracy: %.2f%% (%.2fs)" % (i+1, result, stop-start)) 28 | -------------------------------------------------------------------------------- /examples/IMDbTextCategorizationDemo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import numpy as np 5 | import keras 6 | from sklearn.feature_selection import SelectKBest 7 | from sklearn.feature_selection import chi2 8 | from keras.datasets import imdb 9 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 10 | from time import time 11 | 12 | MAX_NGRAM = 2 13 | 14 | NUM_WORDS=5000 15 | INDEX_FROM=2 16 | 17 | FEATURES=5000 18 | 19 | print("Downloading dataset...") 20 | 21 | train,test = keras.datasets.imdb.load_data(num_words=NUM_WORDS, index_from=INDEX_FROM) 22 | 23 | train_x,train_y = train 24 | test_x,test_y = test 25 | 26 | word_to_id = keras.datasets.imdb.get_word_index() 27 | word_to_id = {k:(v+INDEX_FROM) for k,v in word_to_id.items()} 28 | word_to_id[""] = 0 29 | word_to_id[""] = 1 30 | word_to_id[""] = 2 31 | 32 | print("Producing bit representation...") 33 | 34 | # Produce N-grams 35 | 36 | id_to_word = {value:key for key,value in word_to_id.items()} 37 | 38 | vocabulary = {} 39 | for i in range(train_y.shape[0]): 40 | terms = [] 41 | for word_id in train_x[i]: 42 | terms.append(id_to_word[word_id]) 43 | 44 | for N in range(1,MAX_NGRAM+1): 45 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 46 | for gram in grams: 47 | phrase = " ".join(gram) 48 | 49 | if phrase in vocabulary: 50 | vocabulary[phrase] += 1 51 | else: 52 | vocabulary[phrase] = 1 53 | 54 | # Assign a bit position to each N-gram (minimum frequency 10) 55 | 56 | phrase_bit_nr = {} 57 | bit_nr_phrase = {} 58 | bit_nr = 0 59 | for phrase in vocabulary.keys(): 60 | if vocabulary[phrase] < 10: 61 | continue 62 | 63 | phrase_bit_nr[phrase] = bit_nr 64 | bit_nr_phrase[bit_nr] = phrase 65 | bit_nr += 1 66 | 67 | # Create bit representation 68 | 69 | X_train = np.zeros((train_y.shape[0], len(phrase_bit_nr)), dtype=np.uint32) 70 | Y_train = np.zeros(train_y.shape[0], dtype=np.uint32) 71 | for i in range(train_y.shape[0]): 72 | terms = [] 73 | for word_id in train_x[i]: 74 | terms.append(id_to_word[word_id]) 75 | 76 | for N in range(1,MAX_NGRAM+1): 77 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 78 | for gram in grams: 79 | phrase = " ".join(gram) 80 | if phrase in phrase_bit_nr: 81 | X_train[i,phrase_bit_nr[phrase]] = 1 82 | 83 | Y_train[i] = train_y[i] 84 | 85 | X_test = np.zeros((test_y.shape[0], len(phrase_bit_nr)), dtype=np.uint32) 86 | Y_test = np.zeros(test_y.shape[0], dtype=np.uint32) 87 | 88 | for i in range(test_y.shape[0]): 89 | terms = [] 90 | for word_id in test_x[i]: 91 | terms.append(id_to_word[word_id]) 92 | 93 | for N in range(1,MAX_NGRAM+1): 94 | grams = [terms[j:j+N] for j in range(len(terms)-N+1)] 95 | for gram in grams: 96 | phrase = " ".join(gram) 97 | if phrase in phrase_bit_nr: 98 | X_test[i,phrase_bit_nr[phrase]] = 1 99 | 100 | Y_test[i] = test_y[i] 101 | 102 | print("Selecting features...") 103 | 104 | SKB = SelectKBest(chi2, k=FEATURES) 105 | SKB.fit(X_train, Y_train) 106 | 107 | selected_features = SKB.get_support(indices=True) 108 | X_train = SKB.transform(X_train) 109 | X_test = SKB.transform(X_test) 110 | 111 | tm = MultiClassTsetlinMachine(10000, 80*100, 10.0, weighted_clauses=True) 112 | 113 | print("\nAccuracy over 30 epochs:\n") 114 | for i in range(30): 115 | start_training = time() 116 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 117 | stop_training = time() 118 | 119 | start_testing = time() 120 | result = 100*(tm.predict(X_test) == Y_test).mean() 121 | stop_testing = time() 122 | 123 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /examples/InterpretabilityDemo.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 2 | import numpy as np 3 | 4 | number_of_features = 20 5 | noise = 0.1 6 | 7 | X_train = np.random.randint(0, 2, size=(5000, number_of_features), dtype=np.uint32) 8 | Y_train = np.logical_xor(X_train[:,0], X_train[:,1]).astype(dtype=np.uint32) 9 | Y_train = np.where(np.random.rand(5000) <= noise, 1-Y_train, Y_train) # Adds noise 10 | 11 | X_test = np.random.randint(0, 2, size=(5000, number_of_features), dtype=np.uint32) 12 | Y_test = np.logical_xor(X_test[:,0], X_test[:,1]).astype(dtype=np.uint32) 13 | 14 | tm = MultiClassTsetlinMachine(10, 15, 3.0, boost_true_positive_feedback=0) 15 | 16 | tm.fit(X_train, Y_train, epochs=200) 17 | 18 | print("Accuracy:", 100*(tm.predict(X_test) == Y_test).mean()) 19 | 20 | print("\nClass 0 Positive Clauses:\n") 21 | for j in range(0, 10, 2): 22 | print("Clause #%d: " % (j), end=' ') 23 | l = [] 24 | for k in range(number_of_features*2): 25 | if tm.ta_action(0, j, k) == 1: 26 | if k < number_of_features: 27 | l.append(" x%d" % (k)) 28 | else: 29 | l.append("¬x%d" % (k-number_of_features)) 30 | print(" ∧ ".join(l)) 31 | 32 | print("\nClass 0 Negative Clauses:\n") 33 | for j in range(1, 10, 2): 34 | print("Clause #%d: " % (j), end=' ') 35 | l = [] 36 | for k in range(number_of_features*2): 37 | if tm.ta_action(0, j, k) == 1: 38 | if k < number_of_features: 39 | l.append(" x%d" % (k)) 40 | else: 41 | l.append("¬x%d" % (k-number_of_features)) 42 | print(" ∧ ".join(l)) 43 | 44 | print("\nClass 1 Positive Clauses:\n") 45 | for j in range(0, 10, 2): 46 | print("Clause #%d: " % (j), end=' ') 47 | l = [] 48 | for k in range(number_of_features*2): 49 | if tm.ta_action(1, j, k) == 1: 50 | if k < number_of_features: 51 | l.append(" x%d" % (k)) 52 | else: 53 | l.append("¬x%d" % (k-number_of_features)) 54 | print(" ∧ ".join(l)) 55 | 56 | print("\nClass 1 Negative Clauses:\n") 57 | for j in range(1, 10, 2): 58 | print("Clause #%d: " % (j), end=' ') 59 | l = [] 60 | for k in range(number_of_features*2): 61 | if tm.ta_action(1, j, k) == 1: 62 | if k < number_of_features: 63 | l.append(" x%d" % (k)) 64 | else: 65 | l.append("¬x%d" % (k-number_of_features)) 66 | print(" ∧ ".join(l)) 67 | -------------------------------------------------------------------------------- /examples/MNISTDemo.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 2 | import numpy as np 3 | from time import time 4 | 5 | from keras.datasets import mnist 6 | 7 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 8 | 9 | X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) 10 | X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) 11 | 12 | tm = MultiClassTsetlinMachine(2000, 50, 10.0) 13 | 14 | print("\nAccuracy over 250 epochs:\n") 15 | for i in range(250): 16 | start_training = time() 17 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 18 | stop_training = time() 19 | 20 | start_testing = time() 21 | result = 100*(tm.predict(X_test) == Y_test).mean() 22 | stop_testing = time() 23 | 24 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 25 | -------------------------------------------------------------------------------- /examples/MNISTDemo2DConvolutionWeightedClauses.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassConvolutionalTsetlinMachine2D 2 | import numpy as np 3 | from time import time 4 | 5 | from keras.datasets import mnist 6 | 7 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 8 | 9 | X_train = np.where(X_train >= 75, 1, 0) 10 | X_test = np.where(X_test >= 75, 1, 0) 11 | 12 | tm = MultiClassConvolutionalTsetlinMachine2D(2000, 50*100, 5.0, (10, 10), weighted_clauses=True) 13 | 14 | print("\nAccuracy over 30 epochs:\n") 15 | for i in range(30): 16 | start = time() 17 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 18 | stop = time() 19 | 20 | result = 100*(tm.predict(X_test) == Y_test).mean() 21 | 22 | print("#%d Accuracy: %.2f%% (%.2fs)" % (i+1, result, stop-start)) 23 | -------------------------------------------------------------------------------- /examples/MNISTDemoWeightedClauses.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 2 | import numpy as np 3 | from time import time 4 | 5 | from keras.datasets import mnist 6 | 7 | (X_train, Y_train), (X_test, Y_test) = mnist.load_data() 8 | 9 | X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) 10 | X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) 11 | 12 | tm = MultiClassTsetlinMachine(2000, 50*100, 10.0, weighted_clauses=True) 13 | 14 | print("\nAccuracy over 100 epochs:\n") 15 | for i in range(100): 16 | start_training = time() 17 | tm.fit(X_train, Y_train, epochs=1, incremental=True) 18 | stop_training = time() 19 | 20 | start_testing = time() 21 | result = 100*(tm.predict(X_test) == Y_test).mean() 22 | stop_testing = time() 23 | 24 | print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) 25 | -------------------------------------------------------------------------------- /examples/NoisyXORDemo.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine 2 | import numpy as np 3 | 4 | train_data = np.loadtxt("NoisyXORTrainingData.txt") 5 | X_train = train_data[:,0:-1] 6 | Y_train = train_data[:,-1] 7 | 8 | test_data = np.loadtxt("NoisyXORTestData.txt") 9 | X_test = test_data[:,0:-1] 10 | Y_test = test_data[:,-1] 11 | 12 | tm = MultiClassTsetlinMachine(10, 15, 3.9, boost_true_positive_feedback=0) 13 | 14 | tm.fit(X_train, Y_train, epochs=200) 15 | 16 | print("Accuracy:", 100*(tm.predict(X_test) == Y_test).mean()) 17 | 18 | print("Prediction: x1 = 1, x2 = 0, ... -> y = %d" % (tm.predict(np.array([[1,0,1,0,1,0,1,1,1,1,0,0]])))) 19 | print("Prediction: x1 = 0, x2 = 1, ... -> y = %d" % (tm.predict(np.array([[0,1,1,0,1,0,1,1,1,1,0,0]])))) 20 | print("Prediction: x1 = 0, x2 = 0, ... -> y = %d" % (tm.predict(np.array([[0,0,1,0,1,0,1,1,1,1,0,0]])))) 21 | print("Prediction: x1 = 1, x2 = 1, ... -> y = %d" % (tm.predict(np.array([[1,1,1,0,1,0,1,1,1,1,0,0]])))) 22 | -------------------------------------------------------------------------------- /examples/RegressionDemo.py: -------------------------------------------------------------------------------- 1 | from pyTsetlinMachineParallel.tm import RegressionTsetlinMachine 2 | from pyTsetlinMachineParallel.tools import Binarizer 3 | import numpy as np 4 | from time import time 5 | 6 | from sklearn import datasets 7 | from sklearn.model_selection import train_test_split 8 | 9 | california_housing = datasets.fetch_california_housing() 10 | X = california_housing.data 11 | Y = california_housing.target 12 | 13 | b = Binarizer(max_bits_per_feature = 10) 14 | b.fit(X) 15 | X_transformed = b.transform(X) 16 | 17 | tm = RegressionTsetlinMachine(1000, 500*10, 2.75, weighted_clauses=True) 18 | 19 | print("\nRMSD over 25 runs:\n") 20 | tm_results = np.empty(0) 21 | for i in range(25): 22 | X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y) 23 | 24 | start = time() 25 | tm.fit(X_train, Y_train, epochs=30) 26 | stop = time() 27 | tm_results = np.append(tm_results, np.sqrt(((tm.predict(X_test) - Y_test)**2).mean())) 28 | 29 | print("#%d RMSD: %.2f +/- %.2f (%.2fs)" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1), stop-start)) 30 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/ConvolutionalTsetlinMachine.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2019 Ole-Christoffer Granmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 24 | https://arxiv.org/abs/1905.09688 25 | 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "fast_rand.h" 36 | 37 | #include "ConvolutionalTsetlinMachine.h" 38 | 39 | struct TsetlinMachine *CreateTsetlinMachine(int number_of_clauses, int number_of_features, int number_of_patches, int number_of_ta_chunks, int number_of_state_bits, int T, double s, double s_range, int boost_true_positive_feedback, int weighted_clauses) 40 | { 41 | /* Set up the Tsetlin Machine structure */ 42 | 43 | struct TsetlinMachine *tm = (void *)malloc(sizeof(struct TsetlinMachine)); 44 | 45 | tm->number_of_clauses = number_of_clauses; 46 | 47 | tm->number_of_features = number_of_features; 48 | 49 | tm->number_of_clause_chunks = (number_of_clauses-1)/32 + 1; 50 | 51 | tm->number_of_patches = number_of_patches; 52 | 53 | tm->clause_output = (unsigned int *)malloc(sizeof(unsigned int) * tm->number_of_clause_chunks); 54 | 55 | tm->output_one_patches = (int *)malloc(sizeof(int) * number_of_patches); 56 | 57 | tm->number_of_ta_chunks = number_of_ta_chunks; 58 | 59 | tm->feedback_to_la = (unsigned int *)malloc(sizeof(unsigned int) * number_of_ta_chunks); 60 | 61 | tm->number_of_state_bits = number_of_state_bits; 62 | 63 | tm->ta_state = (unsigned int *)malloc(sizeof(unsigned int) * number_of_clauses * number_of_ta_chunks * number_of_state_bits); 64 | 65 | tm->T = T; 66 | 67 | tm->s = s; 68 | 69 | tm->s_range = s_range; 70 | 71 | tm->clause_patch = (unsigned int *)malloc(sizeof(unsigned int) * number_of_clauses); 72 | 73 | tm->feedback_to_clauses = (int *)malloc(sizeof(int) * tm->number_of_clause_chunks); 74 | 75 | tm->clause_weights = (unsigned int *)malloc(sizeof(unsigned int) * number_of_clauses); 76 | 77 | if (((number_of_features) % 32) != 0) { 78 | tm->filter = (~(0xffffffff << ((number_of_features) % 32))); 79 | } else { 80 | tm->filter = 0xffffffff; 81 | } 82 | 83 | tm->boost_true_positive_feedback = boost_true_positive_feedback; 84 | 85 | tm->weighted_clauses = weighted_clauses; 86 | 87 | tm_initialize(tm); 88 | 89 | return tm; 90 | } 91 | 92 | void tm_initialize(struct TsetlinMachine *tm) 93 | { 94 | /* Set up the Tsetlin Machine structure */ 95 | 96 | unsigned int pos = 0; 97 | for (int j = 0; j < tm->number_of_clauses; ++j) { 98 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 99 | for (int b = 0; b < tm->number_of_state_bits-1; ++b) { 100 | tm->ta_state[pos] = ~0; 101 | pos++; 102 | } 103 | tm->ta_state[pos] = 0; 104 | pos++; 105 | } 106 | tm->clause_weights[j] = 1; 107 | } 108 | } 109 | 110 | void tm_destroy(struct TsetlinMachine *tm) 111 | { 112 | free(tm->clause_output); 113 | free(tm->output_one_patches); 114 | free(tm->feedback_to_la); 115 | free(tm->ta_state); 116 | free(tm->feedback_to_clauses); 117 | free(tm->clause_weights); 118 | } 119 | 120 | static inline void tm_initialize_random_streams(struct TsetlinMachine *tm, int clause) 121 | { 122 | // Initialize all bits to zero 123 | memset(tm->feedback_to_la, 0, tm->number_of_ta_chunks*sizeof(unsigned int)); 124 | 125 | int n = tm->number_of_features; 126 | double p = 1.0 / (tm->s + 1.0 * clause * (tm->s_range - tm->s) / tm->number_of_clauses); 127 | 128 | int active = normal(n * p, n * p * (1 - p)); 129 | active = active >= n ? n : active; 130 | active = active < 0 ? 0 : active; 131 | while (active--) { 132 | int f = fast_rand() % (tm->number_of_features); 133 | while (tm->feedback_to_la[f / 32] & (1 << (f % 32))) { 134 | f = fast_rand() % (tm->number_of_features); 135 | } 136 | tm->feedback_to_la[f / 32] |= 1 << (f % 32); 137 | } 138 | } 139 | 140 | // Increment the states of each of those 32 Tsetlin Automata flagged in the active bit vector. 141 | static inline void tm_inc(struct TsetlinMachine *tm, int clause, int chunk, unsigned int active) 142 | { 143 | unsigned int carry, carry_next; 144 | 145 | unsigned int *ta_state = &tm->ta_state[clause*tm->number_of_ta_chunks*tm->number_of_state_bits + chunk*tm->number_of_state_bits]; 146 | 147 | carry = active; 148 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 149 | if (carry == 0) 150 | break; 151 | 152 | carry_next = ta_state[b] & carry; // Sets carry bits (overflow) passing on to next bit 153 | ta_state[b] = ta_state[b] ^ carry; // Performs increments with XOR 154 | carry = carry_next; 155 | } 156 | 157 | if (carry > 0) { 158 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 159 | ta_state[b] |= carry; 160 | } 161 | } 162 | } 163 | 164 | // Decrement the states of each of those 32 Tsetlin Automata flagged in the active bit vector. 165 | static inline void tm_dec(struct TsetlinMachine *tm, int clause, int chunk, unsigned int active) 166 | { 167 | unsigned int carry, carry_next; 168 | 169 | unsigned int *ta_state = &tm->ta_state[clause*tm->number_of_ta_chunks*tm->number_of_state_bits + chunk*tm->number_of_state_bits]; 170 | 171 | carry = active; 172 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 173 | if (carry == 0) 174 | break; 175 | 176 | carry_next = (~ta_state[b]) & carry; // Sets carry bits (overflow) passing on to next bit 177 | ta_state[b] = ta_state[b] ^ carry; // Performs increments with XOR 178 | carry = carry_next; 179 | } 180 | 181 | if (carry > 0) { 182 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 183 | ta_state[b] &= ~carry; 184 | } 185 | } 186 | } 187 | 188 | /* Sum up the votes for each class */ 189 | static inline int sum_up_class_votes(struct TsetlinMachine *tm) 190 | { 191 | int class_sum = 0; 192 | 193 | for (int j = 0; j < tm->number_of_clauses; j++) { 194 | int clause_chunk = j / 32; 195 | int clause_pos = j % 32; 196 | 197 | if (j % 2 == 0) { 198 | class_sum += tm->clause_weights[j] * ((tm->clause_output[clause_chunk] & (1 << clause_pos)) > 0); 199 | } else { 200 | class_sum -= tm->clause_weights[j] * ((tm->clause_output[clause_chunk] & (1 << clause_pos)) > 0); 201 | } 202 | } 203 | 204 | class_sum = (class_sum > (tm->T)) ? (tm->T) : class_sum; 205 | class_sum = (class_sum < -(tm->T)) ? -(tm->T) : class_sum; 206 | 207 | return class_sum; 208 | } 209 | 210 | /* Calculate the output of each clause using the actions of each Tsetline Automaton. */ 211 | static inline void tm_calculate_clause_output(struct TsetlinMachine *tm, unsigned int *Xi, int predict) 212 | { 213 | int output_one_patches_count; 214 | 215 | unsigned int *ta_state = tm->ta_state; 216 | 217 | for (int j = 0; j < tm->number_of_clause_chunks; j++) { 218 | tm->clause_output[j] = 0; 219 | } 220 | 221 | for (int j = 0; j < tm->number_of_clauses; j++) { 222 | output_one_patches_count = 0; 223 | 224 | for (int patch = 0; patch < tm->number_of_patches; ++patch) { 225 | unsigned int output = 1; 226 | unsigned int all_exclude = 1; 227 | for (int k = 0; k < tm->number_of_ta_chunks-1; k++) { 228 | unsigned int pos = j*tm->number_of_ta_chunks*tm->number_of_state_bits + k*tm->number_of_state_bits + tm->number_of_state_bits-1; 229 | output = output && (ta_state[pos] & Xi[patch*tm->number_of_ta_chunks + k]) == ta_state[pos]; 230 | 231 | if (!output) { 232 | break; 233 | } 234 | all_exclude = all_exclude && (ta_state[pos] == 0); 235 | } 236 | 237 | unsigned int pos = j*tm->number_of_ta_chunks*tm->number_of_state_bits + (tm->number_of_ta_chunks-1)*tm->number_of_state_bits + tm->number_of_state_bits-1; 238 | output = output && 239 | (ta_state[pos] & Xi[patch*tm->number_of_ta_chunks + tm->number_of_ta_chunks - 1] & tm->filter) == 240 | (ta_state[pos] & tm->filter); 241 | 242 | all_exclude = all_exclude && ((ta_state[pos] & tm->filter) == 0); 243 | 244 | output = output && !(predict == PREDICT && all_exclude == 1); 245 | 246 | if (output) { 247 | tm->output_one_patches[output_one_patches_count] = patch; 248 | output_one_patches_count++; 249 | } 250 | } 251 | 252 | if (output_one_patches_count > 0) { 253 | unsigned int clause_chunk = j / 32; 254 | unsigned int clause_chunk_pos = j % 32; 255 | 256 | tm->clause_output[clause_chunk] |= (1 << clause_chunk_pos); 257 | 258 | int patch_id = fast_rand() % output_one_patches_count; 259 | tm->clause_patch[j] = tm->output_one_patches[patch_id]; 260 | } 261 | } 262 | } 263 | 264 | /******************************************/ 265 | /*** Online Training of Tsetlin Machine ***/ 266 | /******************************************/ 267 | 268 | // The Tsetlin Machine can be trained incrementally, one training example at a time. 269 | // Use this method directly for online and incremental training. 270 | 271 | void tm_update_clauses(struct TsetlinMachine *tm, unsigned int *Xi, int class_sum, int target) 272 | { 273 | unsigned int *ta_state = tm->ta_state; 274 | 275 | for (int j = 0; j < tm->number_of_clause_chunks; j++) { 276 | tm->feedback_to_clauses[j] = 0; 277 | } 278 | 279 | for (int j = 0; j < tm->number_of_clauses; j++) { 280 | unsigned int clause_chunk = j / 32; 281 | unsigned int clause_chunk_pos = j % 32; 282 | 283 | tm->feedback_to_clauses[clause_chunk] |= (((float)fast_rand())/((float)FAST_RAND_MAX) <= (1.0/(tm->T*2))*(tm->T + (1 - 2*target)*class_sum)) << clause_chunk_pos; 284 | } 285 | 286 | for (int j = 0; j < tm->number_of_clauses; j++) { 287 | unsigned int clause_chunk = j / 32; 288 | unsigned int clause_chunk_pos = j % 32; 289 | 290 | if (!(tm->feedback_to_clauses[clause_chunk] & (1 << clause_chunk_pos))) { 291 | continue; 292 | } 293 | 294 | omp_set_lock(&tm->clause_lock[j]); 295 | if ((2*target-1) * (1 - 2 * (j & 1)) == -1) { 296 | if ((tm->clause_output[clause_chunk] & (1 << clause_chunk_pos)) > 0) { 297 | // Type II Feedback 298 | 299 | if (tm->weighted_clauses && tm->clause_weights[j] > 1) { 300 | tm->clause_weights[j]--; 301 | } 302 | 303 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 304 | int patch = tm->clause_patch[j]; 305 | unsigned int pos = j*tm->number_of_ta_chunks*tm->number_of_state_bits + k*tm->number_of_state_bits + tm->number_of_state_bits-1; 306 | 307 | tm_inc(tm, j, k, (~Xi[patch*tm->number_of_ta_chunks + k]) & (~ta_state[pos])); 308 | } 309 | } 310 | } else if ((2*target-1) * (1 - 2 * (j & 1)) == 1) { 311 | // Type I Feedback 312 | 313 | tm_initialize_random_streams(tm, j); 314 | 315 | if ((tm->clause_output[clause_chunk] & (1 << clause_chunk_pos)) > 0) { 316 | // Type Ia Feedback 317 | 318 | if (tm->weighted_clauses) { 319 | tm->clause_weights[j]++; 320 | } 321 | 322 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 323 | int patch = tm->clause_patch[j]; 324 | if (tm->boost_true_positive_feedback == 1) { 325 | tm_inc(tm, j, k, Xi[patch*tm->number_of_ta_chunks + k]); 326 | } else { 327 | tm_inc(tm, j, k, Xi[patch*tm->number_of_ta_chunks + k] & (~tm->feedback_to_la[k])); 328 | } 329 | 330 | tm_dec(tm, j, k, (~Xi[patch*tm->number_of_ta_chunks + k]) & tm->feedback_to_la[k]); 331 | } 332 | } else { 333 | // Type Ib Feedback 334 | 335 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 336 | tm_dec(tm, j, k, tm->feedback_to_la[k]); 337 | } 338 | } 339 | } 340 | omp_unset_lock(&tm->clause_lock[j]); 341 | } 342 | } 343 | 344 | void tm_update(struct TsetlinMachine *tm, unsigned int *Xi, int target) 345 | { 346 | /*******************************/ 347 | /*** Calculate Clause Output ***/ 348 | /*******************************/ 349 | 350 | 351 | tm_calculate_clause_output(tm, Xi, UPDATE); 352 | 353 | /***************************/ 354 | /*** Sum up Clause Votes ***/ 355 | /***************************/ 356 | 357 | int class_sum = sum_up_class_votes(tm); 358 | 359 | /*********************************/ 360 | /*** Train Individual Automata ***/ 361 | /*********************************/ 362 | 363 | tm_update_clauses(tm, Xi, class_sum, target); 364 | } 365 | 366 | int tm_score(struct TsetlinMachine *tm, unsigned int *Xi) { 367 | /*******************************/ 368 | /*** Calculate Clause Output ***/ 369 | /*******************************/ 370 | 371 | tm_calculate_clause_output(tm, Xi, PREDICT); 372 | 373 | /***************************/ 374 | /*** Sum up Clause Votes ***/ 375 | /***************************/ 376 | 377 | return sum_up_class_votes(tm); 378 | } 379 | 380 | int tm_ta_state(struct TsetlinMachine *tm, int clause, int ta) 381 | { 382 | int ta_chunk = ta / 32; 383 | int chunk_pos = ta % 32; 384 | 385 | unsigned int pos = clause * tm->number_of_ta_chunks * tm->number_of_state_bits + ta_chunk * tm->number_of_state_bits; 386 | 387 | int state = 0; 388 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 389 | if (tm->ta_state[pos + b] & (1 << chunk_pos)) { 390 | state |= 1 << b; 391 | } 392 | } 393 | 394 | return state; 395 | } 396 | 397 | int tm_ta_action(struct TsetlinMachine *tm, int clause, int ta) 398 | { 399 | int ta_chunk = ta / 32; 400 | int chunk_pos = ta % 32; 401 | 402 | unsigned int pos = clause * tm->number_of_ta_chunks * tm->number_of_state_bits + ta_chunk * tm->number_of_state_bits + tm->number_of_state_bits-1; 403 | 404 | return (tm->ta_state[pos] & (1 << chunk_pos)) > 0; 405 | } 406 | 407 | /*****************************************************/ 408 | /*** Storing and Loading of Tsetlin Machine State ****/ 409 | /*****************************************************/ 410 | 411 | void tm_get_ta_state(struct TsetlinMachine *tm, unsigned int *ta_state) 412 | { 413 | int pos = 0; 414 | for (int j = 0; j < tm->number_of_clauses; ++j) { 415 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 416 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 417 | ta_state[pos] = tm->ta_state[pos]; 418 | pos++; 419 | } 420 | } 421 | } 422 | } 423 | 424 | void tm_set_ta_state(struct TsetlinMachine *tm, unsigned int *ta_state) 425 | { 426 | int pos = 0; 427 | for (int j = 0; j < tm->number_of_clauses; ++j) { 428 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 429 | for (int b = 0; b < tm->number_of_state_bits; ++b) { 430 | tm->ta_state[pos] = ta_state[pos]; 431 | pos++; 432 | } 433 | } 434 | } 435 | } 436 | 437 | void tm_get_clause_weights(struct TsetlinMachine *tm, unsigned int *clause_weights) 438 | { 439 | for (int j = 0; j < tm->number_of_clauses; ++j) { 440 | clause_weights[j] = tm->clause_weights[j]; 441 | } 442 | } 443 | 444 | void tm_set_clause_weights(struct TsetlinMachine *tm, unsigned int *clause_weights) 445 | { 446 | for (int j = 0; j < tm->number_of_clauses; ++j) { 447 | tm->clause_weights[j] = clause_weights[j]; 448 | } 449 | } 450 | 451 | /**************************************/ 452 | /*** The Regression Tsetlin Machine ***/ 453 | /**************************************/ 454 | 455 | /* Sum up the votes for each class */ 456 | static inline int sum_up_class_votes_regression(struct TsetlinMachine *tm) 457 | { 458 | int class_sum = 0; 459 | 460 | for (int j = 0; j < tm->number_of_clauses; j++) { 461 | int clause_chunk = j / 32; 462 | int clause_pos = j % 32; 463 | 464 | class_sum += tm->clause_weights[j] * ((tm->clause_output[clause_chunk] & (1 << clause_pos)) > 0); 465 | 466 | } 467 | class_sum = (class_sum > (tm->T)) ? (tm->T) : class_sum; 468 | 469 | return class_sum; 470 | } 471 | 472 | // The Tsetlin Machine can be trained incrementally, one training example at a time. 473 | // Use this method directly for online and incremental training. 474 | 475 | void tm_update_regression(struct TsetlinMachine *tm, unsigned int *Xi, int target) 476 | { 477 | unsigned int *ta_state = tm->ta_state; 478 | 479 | /*******************************/ 480 | /*** Calculate Clause Output ***/ 481 | /*******************************/ 482 | 483 | tm_calculate_clause_output(tm, Xi, UPDATE); 484 | 485 | /***************************/ 486 | /*** Sum up Clause Votes ***/ 487 | /***************************/ 488 | 489 | int class_sum = sum_up_class_votes_regression(tm); 490 | 491 | /*********************************/ 492 | /*** Train Individual Automata ***/ 493 | /*********************************/ 494 | 495 | // Calculate feedback to clauses 496 | 497 | int prediction_error = class_sum - target; 498 | 499 | for (int j = 0; j < tm->number_of_clause_chunks; j++) { 500 | tm->feedback_to_clauses[j] = 0; 501 | } 502 | 503 | for (int j = 0; j < tm->number_of_clauses; j++) { 504 | unsigned int clause_chunk = j / 32; 505 | unsigned int clause_chunk_pos = j % 32; 506 | 507 | tm->feedback_to_clauses[clause_chunk] |= (((float)fast_rand())/((float)FAST_RAND_MAX) <= pow(1.0*prediction_error/tm->T, 2)) << clause_chunk_pos; 508 | } 509 | 510 | for (int j = 0; j < tm->number_of_clauses; j++) { 511 | unsigned int clause_chunk = j / 32; 512 | unsigned int clause_chunk_pos = j % 32; 513 | 514 | if (!(tm->feedback_to_clauses[clause_chunk] & (1 << clause_chunk_pos))) { 515 | continue; 516 | } 517 | 518 | if (prediction_error > 0) { 519 | if ((tm->clause_output[clause_chunk] & (1 << clause_chunk_pos)) > 0) { 520 | // Type II Feedback 521 | 522 | if (tm->weighted_clauses && tm->clause_weights[j] > 1) { 523 | tm->clause_weights[j]--; 524 | } 525 | 526 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 527 | int patch = tm->clause_patch[j]; 528 | unsigned int pos = j*tm->number_of_ta_chunks*tm->number_of_state_bits + k*tm->number_of_state_bits + tm->number_of_state_bits-1; 529 | 530 | tm_inc(tm, j, k, (~Xi[patch*tm->number_of_ta_chunks + k]) & (~ta_state[pos])); 531 | } 532 | } 533 | } else if (prediction_error < 0) { 534 | // Type I Feedback 535 | 536 | tm_initialize_random_streams(tm, j); 537 | 538 | if ((tm->clause_output[clause_chunk] & (1 << clause_chunk_pos)) > 0) { 539 | // Type Ia Feedback 540 | 541 | if (tm->weighted_clauses) { 542 | tm->clause_weights[j]++; 543 | } 544 | 545 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 546 | int patch = tm->clause_patch[j]; 547 | if (tm->boost_true_positive_feedback == 1) { 548 | tm_inc(tm, j, k, Xi[patch*tm->number_of_ta_chunks + k]); 549 | } else { 550 | tm_inc(tm, j, k, Xi[patch*tm->number_of_ta_chunks + k] & (~tm->feedback_to_la[k])); 551 | } 552 | 553 | tm_dec(tm, j, k, (~Xi[patch*tm->number_of_ta_chunks + k]) & tm->feedback_to_la[k]); 554 | } 555 | } else { 556 | // Type Ib Feedback 557 | 558 | for (int k = 0; k < tm->number_of_ta_chunks; ++k) { 559 | tm_dec(tm, j, k, tm->feedback_to_la[k]); 560 | } 561 | } 562 | } 563 | } 564 | } 565 | 566 | void tm_fit_regression(struct TsetlinMachine *tm, unsigned int *X, int *y, int number_of_examples, int epochs) 567 | { 568 | unsigned int step_size = tm->number_of_patches * tm->number_of_ta_chunks; 569 | 570 | int max_threads = omp_get_max_threads(); 571 | struct TsetlinMachine **tm_thread = (void *)malloc(sizeof(struct TsetlinMachine *) * max_threads); 572 | 573 | tm->clause_lock = (omp_lock_t *)malloc(sizeof(omp_lock_t) * tm->number_of_clauses); 574 | for (int j = 0; j < tm->number_of_clauses; ++j) { 575 | omp_init_lock(&tm->clause_lock[j]); 576 | } 577 | 578 | for (int t = 0; t < max_threads; t++) { 579 | tm_thread[t] = CreateTsetlinMachine(tm->number_of_clauses, tm->number_of_features, tm->number_of_patches, tm->number_of_ta_chunks, tm->number_of_state_bits, tm->T, tm->s, tm->s_range, tm->boost_true_positive_feedback, tm->weighted_clauses); 580 | free(tm_thread[t]->ta_state); 581 | tm_thread[t]->ta_state = tm->ta_state; 582 | free(tm_thread[t]->clause_weights); 583 | tm_thread[t]->clause_weights = tm->clause_weights; 584 | tm_thread[t]->clause_lock = tm->clause_lock; 585 | } 586 | 587 | for (int epoch = 0; epoch < epochs; epoch++) { 588 | // Add shuffling here... 589 | 590 | #pragma omp parallel for 591 | for (int l = 0; l < number_of_examples; l++) { 592 | int thread_id = omp_get_thread_num(); 593 | unsigned int pos = l*step_size; 594 | 595 | tm_update_regression(tm_thread[thread_id], &X[pos], y[l]); 596 | } 597 | } 598 | 599 | for (int t = 0; t < max_threads; t++) { 600 | free(tm_thread[t]->clause_output); 601 | free(tm_thread[t]->output_one_patches); 602 | free(tm_thread[t]->feedback_to_la); 603 | free(tm_thread[t]->feedback_to_clauses); 604 | free(tm_thread[t]); 605 | } 606 | 607 | for (int j = 0; j < tm->number_of_clauses; ++j) { 608 | omp_destroy_lock(&tm->clause_lock[j]); 609 | } 610 | 611 | free(tm->clause_lock); 612 | free(tm_thread); 613 | } 614 | 615 | int tm_score_regression(struct TsetlinMachine *tm, unsigned int *Xi) { 616 | /*******************************/ 617 | /*** Calculate Clause Output ***/ 618 | /*******************************/ 619 | 620 | tm_calculate_clause_output(tm, Xi, PREDICT); 621 | 622 | /***************************/ 623 | /*** Sum up Clause Votes ***/ 624 | /***************************/ 625 | 626 | return sum_up_class_votes_regression(tm); 627 | } 628 | 629 | /******************************/ 630 | /*** Predict y for inputs X ***/ 631 | /******************************/ 632 | 633 | void tm_predict_regression(struct TsetlinMachine *tm, unsigned int *X, int *y, int number_of_examples) 634 | { 635 | unsigned int step_size = tm->number_of_patches * tm->number_of_ta_chunks; 636 | 637 | int max_threads = omp_get_max_threads(); 638 | struct TsetlinMachine **tm_thread = (void *)malloc(sizeof(struct TsetlinMachine *) * max_threads); 639 | 640 | for (int t = 0; t < max_threads; t++) { 641 | tm_thread[t] = CreateTsetlinMachine(tm->number_of_clauses, tm->number_of_features, tm->number_of_patches, tm->number_of_ta_chunks, tm->number_of_state_bits, tm->T, tm->s, tm->s_range, tm->boost_true_positive_feedback, tm->weighted_clauses); 642 | free(tm_thread[t]->ta_state); 643 | tm_thread[t]->ta_state = tm->ta_state; 644 | free(tm_thread[t]->clause_weights); 645 | tm_thread[t]->clause_weights = tm->clause_weights; 646 | } 647 | 648 | #pragma omp parallel for 649 | for (int l = 0; l < number_of_examples; l++) { 650 | int thread_id = omp_get_thread_num(); 651 | unsigned int pos = l*step_size; 652 | 653 | y[l] = tm_score_regression(tm_thread[thread_id], &X[pos]); 654 | } 655 | 656 | for (int t = 0; t < max_threads; t++) { 657 | free(tm_thread[t]->clause_output); 658 | free(tm_thread[t]->output_one_patches); 659 | free(tm_thread[t]->feedback_to_la); 660 | free(tm_thread[t]->feedback_to_clauses); 661 | free(tm_thread[t]); 662 | } 663 | 664 | free(tm_thread); 665 | 666 | return; 667 | } 668 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/ConvolutionalTsetlinMachine.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2019 Ole-Christoffer Granmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 24 | https://arxiv.org/abs/1905.09688 25 | 26 | */ 27 | 28 | #include 29 | 30 | #define PREDICT 1 31 | #define UPDATE 0 32 | 33 | struct TsetlinMachine { 34 | int number_of_clauses; 35 | 36 | int number_of_features; 37 | 38 | int number_of_clause_chunks; 39 | 40 | omp_lock_t *clause_lock; 41 | 42 | unsigned int *ta_state; 43 | unsigned int *clause_output; 44 | unsigned int *feedback_to_la; 45 | int *feedback_to_clauses; 46 | unsigned int *clause_patch; 47 | 48 | int *output_one_patches; 49 | 50 | unsigned int *clause_weights; 51 | 52 | int number_of_patches; 53 | int number_of_ta_chunks; 54 | int number_of_state_bits; 55 | 56 | int T; 57 | 58 | double s; 59 | 60 | double s_range; 61 | 62 | unsigned int filter; 63 | 64 | int boost_true_positive_feedback; 65 | 66 | int weighted_clauses; 67 | }; 68 | 69 | struct TsetlinMachine *CreateTsetlinMachine(int number_of_clauses, int number_of_features, int number_of_patches, int number_of_ta_chunks, int number_of_state_bits, int T, double s, double s_range, int boost_true_positive_feedback, int weighted_clauses); 70 | 71 | void tm_initialize(struct TsetlinMachine *tm); 72 | 73 | void tm_destroy(struct TsetlinMachine *tm); 74 | 75 | void tm_update_clauses(struct TsetlinMachine *tm, unsigned int *Xi, int class_sum, int target); 76 | 77 | void tm_update(struct TsetlinMachine *tm, unsigned int *Xi, int target); 78 | 79 | int tm_score(struct TsetlinMachine *tm, unsigned int *Xi); 80 | 81 | int tm_ta_state(struct TsetlinMachine *tm, int clause, int ta); 82 | 83 | int tm_ta_action(struct TsetlinMachine *tm, int clause, int ta); 84 | 85 | void tm_update_regression(struct TsetlinMachine *tm, unsigned int *Xi, int target); 86 | 87 | void tm_fit_regression(struct TsetlinMachine *tm, unsigned int *X, int *y, int number_of_examples, int epochs); 88 | 89 | int tm_score_regression(struct TsetlinMachine *tm, unsigned int *Xi); 90 | 91 | void tm_predict_regression(struct TsetlinMachine *tm, unsigned int *X, int *y, int number_of_examples); 92 | 93 | void tm_get_ta_state(struct TsetlinMachine *tm, unsigned int *ta_state); 94 | 95 | void tm_set_ta_state(struct TsetlinMachine *tm, unsigned int *ta_state); 96 | 97 | void tm_get_clause_weights(struct TsetlinMachine *tm, unsigned int *clause_weights); 98 | 99 | void tm_set_clause_weights(struct TsetlinMachine *tm, unsigned int *clause_weights); 100 | 101 | 102 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/MultiClassConvolutionalTsetlinMachine.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2019 Ole-Christoffer Granmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 24 | https://arxiv.org/abs/1905.09688 25 | 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "MultiClassConvolutionalTsetlinMachine.h" 33 | 34 | /**************************************/ 35 | /*** The Convolutional Tsetlin Machine ***/ 36 | /**************************************/ 37 | 38 | /*** Initialize Tsetlin Machine ***/ 39 | struct MultiClassTsetlinMachine *CreateMultiClassTsetlinMachine(int number_of_classes, int number_of_clauses, int number_of_features, int number_of_patches, int number_of_ta_chunks, int number_of_state_bits, int T, double s, double s_range, int boost_true_positive_feedback, int weighted_clauses) 40 | { 41 | 42 | struct MultiClassTsetlinMachine *mc_tm = NULL; 43 | 44 | mc_tm = (void *)malloc(sizeof(struct MultiClassTsetlinMachine)); 45 | 46 | mc_tm->number_of_classes = number_of_classes; 47 | mc_tm->tsetlin_machines = (void *)malloc(sizeof(struct TsetlinMachine *)* number_of_classes); 48 | for (int i = 0; i < number_of_classes; i++) { 49 | mc_tm->tsetlin_machines[i] = CreateTsetlinMachine(number_of_clauses, number_of_features, number_of_patches, number_of_ta_chunks, number_of_state_bits, T, s, s_range, boost_true_positive_feedback, weighted_clauses); 50 | } 51 | 52 | mc_tm->number_of_patches = number_of_patches; 53 | 54 | mc_tm->number_of_ta_chunks = number_of_ta_chunks; 55 | 56 | mc_tm->number_of_state_bits = number_of_state_bits; 57 | 58 | return mc_tm; 59 | } 60 | 61 | void mc_tm_initialize(struct MultiClassTsetlinMachine *mc_tm) 62 | { 63 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 64 | tm_initialize(mc_tm->tsetlin_machines[i]); 65 | } 66 | } 67 | 68 | void mc_tm_destroy(struct MultiClassTsetlinMachine *mc_tm) 69 | { 70 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 71 | tm_destroy(mc_tm->tsetlin_machines[i]); 72 | 73 | free(mc_tm->tsetlin_machines[i]); 74 | } 75 | free(mc_tm->tsetlin_machines); 76 | } 77 | 78 | /***********************************/ 79 | /*** Predict classes of inputs X ***/ 80 | /***********************************/ 81 | 82 | void mc_tm_predict(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, int *y, int number_of_examples) 83 | { 84 | 85 | unsigned int step_size = mc_tm->number_of_patches * mc_tm->number_of_ta_chunks; 86 | 87 | int max_threads = omp_get_max_threads(); 88 | struct MultiClassTsetlinMachine **mc_tm_thread = (void *)malloc(sizeof(struct MultiClassTsetlinMachine *) * max_threads); 89 | struct TsetlinMachine *tm = mc_tm->tsetlin_machines[0]; 90 | for (int t = 0; t < max_threads; t++) { 91 | mc_tm_thread[t] = CreateMultiClassTsetlinMachine(mc_tm->number_of_classes, tm->number_of_clauses, tm->number_of_features, tm->number_of_patches, tm->number_of_ta_chunks, tm->number_of_state_bits, tm->T, tm->s, tm->s_range, tm->boost_true_positive_feedback, tm->weighted_clauses); 92 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 93 | free(mc_tm_thread[t]->tsetlin_machines[i]->ta_state); 94 | mc_tm_thread[t]->tsetlin_machines[i]->ta_state = mc_tm->tsetlin_machines[i]->ta_state; 95 | free(mc_tm_thread[t]->tsetlin_machines[i]->clause_weights); 96 | mc_tm_thread[t]->tsetlin_machines[i]->clause_weights = mc_tm->tsetlin_machines[i]->clause_weights; 97 | } 98 | } 99 | 100 | #pragma omp parallel for 101 | for (int l = 0; l < number_of_examples; l++) { 102 | int thread_id = omp_get_thread_num(); 103 | 104 | unsigned int pos = l*step_size; 105 | // Identify class with largest output 106 | int max_class_sum = tm_score(mc_tm_thread[thread_id]->tsetlin_machines[0], &X[pos]); 107 | int max_class = 0; 108 | for (int i = 1; i < mc_tm_thread[thread_id]->number_of_classes; i++) { 109 | int class_sum = tm_score(mc_tm_thread[thread_id]->tsetlin_machines[i], &X[pos]); 110 | if (max_class_sum < class_sum) { 111 | max_class_sum = class_sum; 112 | max_class = i; 113 | } 114 | } 115 | 116 | y[l] = max_class; 117 | } 118 | 119 | for (int t = 0; t < max_threads; t++) { 120 | for (int i = 0; i < mc_tm_thread[t]->number_of_classes; i++) { 121 | 122 | struct TsetlinMachine *tm_thread = mc_tm_thread[t]->tsetlin_machines[i]; 123 | 124 | free(tm_thread->clause_output); 125 | free(tm_thread->output_one_patches); 126 | free(tm_thread->feedback_to_la); 127 | free(tm_thread->feedback_to_clauses); 128 | free(tm_thread); 129 | } 130 | } 131 | 132 | free(mc_tm_thread); 133 | 134 | return; 135 | } 136 | 137 | /******************************************/ 138 | /*** Online Training of Tsetlin Machine ***/ 139 | /******************************************/ 140 | 141 | // The Tsetlin Machine can be trained incrementally, one training example at a time. 142 | // Use this method directly for online and incremental training. 143 | 144 | void mc_tm_update(struct MultiClassTsetlinMachine *mc_tm, unsigned int *Xi, int target_class) 145 | { 146 | tm_update(mc_tm->tsetlin_machines[target_class], Xi, 1); 147 | 148 | // Randomly pick one of the other classes, for pairwise learning of class output 149 | unsigned int negative_target_class = (unsigned int)mc_tm->number_of_classes * 1.0*rand()/((unsigned int)RAND_MAX + 1); 150 | while (negative_target_class == target_class) { 151 | negative_target_class = (unsigned int)mc_tm->number_of_classes * 1.0*rand()/((unsigned int)RAND_MAX + 1); 152 | } 153 | tm_update(mc_tm->tsetlin_machines[negative_target_class], Xi, 0); 154 | } 155 | 156 | /**********************************************/ 157 | /*** Batch Mode Training of Tsetlin Machine ***/ 158 | /**********************************************/ 159 | 160 | void mc_tm_fit(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, int *y, int number_of_examples, int epochs) 161 | { 162 | unsigned int step_size = mc_tm->number_of_patches * mc_tm->number_of_ta_chunks; 163 | 164 | int max_threads = omp_get_max_threads(); 165 | struct MultiClassTsetlinMachine **mc_tm_thread = (void *)malloc(sizeof(struct MultiClassTsetlinMachine *) * max_threads); 166 | struct TsetlinMachine *tm = mc_tm->tsetlin_machines[0]; 167 | 168 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 169 | mc_tm->tsetlin_machines[i]->clause_lock = (omp_lock_t *)malloc(sizeof(omp_lock_t) * tm->number_of_clauses); 170 | for (int j = 0; j < tm->number_of_clauses; ++j) { 171 | omp_init_lock(&mc_tm->tsetlin_machines[i]->clause_lock[j]); 172 | } 173 | } 174 | 175 | for (int t = 0; t < max_threads; t++) { 176 | mc_tm_thread[t] = CreateMultiClassTsetlinMachine(mc_tm->number_of_classes, tm->number_of_clauses, tm->number_of_features, tm->number_of_patches, tm->number_of_ta_chunks, tm->number_of_state_bits, tm->T, tm->s, tm->s_range, tm->boost_true_positive_feedback, tm->weighted_clauses); 177 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 178 | free(mc_tm_thread[t]->tsetlin_machines[i]->ta_state); 179 | mc_tm_thread[t]->tsetlin_machines[i]->ta_state = mc_tm->tsetlin_machines[i]->ta_state; 180 | free(mc_tm_thread[t]->tsetlin_machines[i]->clause_weights); 181 | mc_tm_thread[t]->tsetlin_machines[i]->clause_weights = mc_tm->tsetlin_machines[i]->clause_weights; 182 | 183 | mc_tm_thread[t]->tsetlin_machines[i]->clause_lock = mc_tm->tsetlin_machines[i]->clause_lock; 184 | } 185 | } 186 | 187 | for (int epoch = 0; epoch < epochs; epoch++) { 188 | #pragma omp parallel for 189 | for (int l = 0; l < number_of_examples; l++) { 190 | int thread_id = omp_get_thread_num(); 191 | unsigned int pos = l*step_size; 192 | 193 | mc_tm_update(mc_tm_thread[thread_id], &X[pos], y[l]); 194 | } 195 | } 196 | 197 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 198 | for (int j = 0; j < tm->number_of_clauses; ++j) { 199 | omp_destroy_lock(&mc_tm->tsetlin_machines[i]->clause_lock[j]); 200 | } 201 | } 202 | 203 | for (int t = 0; t < max_threads; t++) { 204 | for (int i = 0; i < mc_tm_thread[t]->number_of_classes; i++) { 205 | 206 | struct TsetlinMachine *tm_thread = mc_tm_thread[t]->tsetlin_machines[i]; 207 | 208 | free(tm_thread->clause_output); 209 | free(tm_thread->output_one_patches); 210 | free(tm_thread->feedback_to_la); 211 | free(tm_thread->feedback_to_clauses); 212 | free(tm_thread); 213 | } 214 | } 215 | 216 | free(tm->clause_lock); 217 | free(mc_tm_thread); 218 | } 219 | 220 | int mc_tm_ta_state(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, int ta) 221 | { 222 | return tm_ta_state(mc_tm->tsetlin_machines[class], clause, ta); 223 | } 224 | 225 | int mc_tm_ta_action(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, int ta) 226 | { 227 | return tm_ta_action(mc_tm->tsetlin_machines[class], clause, ta); 228 | } 229 | 230 | void mc_tm_clause_configuration(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, unsigned int *clause_configuration) 231 | { 232 | for (int k = 0; k < mc_tm->tsetlin_machines[class]->number_of_features; ++k) { 233 | clause_configuration[k] = tm_ta_action(mc_tm->tsetlin_machines[class], clause, k); 234 | } 235 | 236 | return; 237 | } 238 | 239 | int mc_tm_clause_weight(struct MultiClassTsetlinMachine *mc_tm, int class, int clause) 240 | { 241 | return(mc_tm->tsetlin_machines[class]->clause_weights[clause]); 242 | } 243 | 244 | /*****************************************************/ 245 | /*** Storing and Loading of Tsetlin Machine State ****/ 246 | /*****************************************************/ 247 | 248 | void mc_tm_get_state(struct MultiClassTsetlinMachine *mc_tm, int class, unsigned int *clause_weights, unsigned int *ta_state) 249 | { 250 | tm_get_ta_state(mc_tm->tsetlin_machines[class], ta_state); 251 | tm_get_clause_weights(mc_tm->tsetlin_machines[class], clause_weights); 252 | 253 | return; 254 | } 255 | 256 | void mc_tm_set_state(struct MultiClassTsetlinMachine *mc_tm, int class, unsigned int *clause_weights, unsigned int *ta_state) 257 | { 258 | tm_set_ta_state(mc_tm->tsetlin_machines[class], ta_state); 259 | tm_set_clause_weights(mc_tm->tsetlin_machines[class], clause_weights); 260 | 261 | return; 262 | } 263 | 264 | /******************************************************************************/ 265 | /*** Clause Based Transformation of Input Examples for Multi-layer Learning ***/ 266 | /******************************************************************************/ 267 | 268 | void mc_tm_transform(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, unsigned int *X_transformed, int invert, int number_of_examples) 269 | { 270 | unsigned int step_size = mc_tm->number_of_patches * mc_tm->number_of_ta_chunks; 271 | 272 | int max_threads = omp_get_max_threads(); 273 | struct MultiClassTsetlinMachine **mc_tm_thread = (void *)malloc(sizeof(struct MultiClassTsetlinMachine *) * max_threads); 274 | struct TsetlinMachine *tm = mc_tm->tsetlin_machines[0]; 275 | for (int t = 0; t < max_threads; t++) { 276 | mc_tm_thread[t] = CreateMultiClassTsetlinMachine(mc_tm->number_of_classes, tm->number_of_clauses, tm->number_of_features, tm->number_of_patches, tm->number_of_ta_chunks, tm->number_of_state_bits, tm->T, tm->s, tm->s_range, tm->boost_true_positive_feedback, tm->weighted_clauses); 277 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 278 | free(mc_tm_thread[t]->tsetlin_machines[i]->ta_state); 279 | mc_tm_thread[t]->tsetlin_machines[i]->ta_state = mc_tm->tsetlin_machines[i]->ta_state; 280 | free(mc_tm_thread[t]->tsetlin_machines[i]->clause_weights); 281 | mc_tm_thread[t]->tsetlin_machines[i]->clause_weights = mc_tm->tsetlin_machines[i]->clause_weights; 282 | } 283 | } 284 | 285 | #pragma omp parallel for 286 | for (int l = 0; l < number_of_examples; l++) { 287 | int thread_id = omp_get_thread_num(); 288 | unsigned int pos = l*step_size; 289 | 290 | for (int i = 0; i < mc_tm->number_of_classes; i++) { 291 | tm_score(mc_tm_thread[thread_id]->tsetlin_machines[i], &X[pos]); 292 | 293 | for (int j = 0; j < mc_tm->tsetlin_machines[i]->number_of_clauses; ++j) { 294 | unsigned long transformed_feature = l*mc_tm->number_of_classes*mc_tm->tsetlin_machines[i]->number_of_clauses + i*mc_tm->tsetlin_machines[i]->number_of_clauses + j; 295 | 296 | int clause_chunk = j / 32; 297 | int clause_pos = j % 32; 298 | 299 | int clause_output = (mc_tm_thread[thread_id]->tsetlin_machines[i]->clause_output[clause_chunk] & (1 << clause_pos)) > 0; 300 | 301 | if (clause_output && !invert) { 302 | X_transformed[transformed_feature] = 1; 303 | } else if (!clause_output && invert) { 304 | X_transformed[transformed_feature] = 1; 305 | } else { 306 | X_transformed[transformed_feature] = 0; 307 | } 308 | } 309 | } 310 | } 311 | 312 | return; 313 | } 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/MultiClassConvolutionalTsetlinMachine.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2019 Ole-Christoffer Granmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 24 | https://arxiv.org/abs/1905.09688 25 | 26 | */ 27 | 28 | #include "ConvolutionalTsetlinMachine.h" 29 | 30 | struct MultiClassTsetlinMachine { 31 | int number_of_classes; 32 | struct TsetlinMachine **tsetlin_machines; 33 | 34 | int number_of_patches; 35 | int number_of_ta_chunks; 36 | int number_of_state_bits; 37 | }; 38 | 39 | struct MultiClassTsetlinMachine *CreateMultiClassTsetlinMachine(int number_of_classes, int number_of_clauses, int number_of_features, int number_of_patches, int number_of_ta_chunks, int number_of_state_bits, int T, double s, double s_range, int boost_true_positive_feedback, int weighted_clauses); 40 | 41 | void mc_tm_initialize(struct MultiClassTsetlinMachine *mc_tm); 42 | 43 | void mc_tm_destroy(struct MultiClassTsetlinMachine *mc_tm); 44 | 45 | void mc_tm_initialize_random_streams(struct MultiClassTsetlinMachine *mc_tm, float s); 46 | 47 | void mc_tm_predict(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, int *y, int number_of_examples); 48 | 49 | void mc_tm_fit(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, int y[], int number_of_examples, int epochs); 50 | 51 | void mc_tm_get_state(struct MultiClassTsetlinMachine *mc_tm, int class, unsigned int *clause_weights, unsigned int *ta_state); 52 | 53 | void mc_tm_set_state(struct MultiClassTsetlinMachine *mc_tm, int class, unsigned int *clause_weights, unsigned int *ta_state); 54 | 55 | int mc_tm_ta_state(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, int ta); 56 | 57 | int mc_tm_ta_action(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, int ta); 58 | 59 | int mc_tm_clause_weight(struct MultiClassTsetlinMachine *mc_tm, int class, int clause); 60 | 61 | void mc_tm_transform(struct MultiClassTsetlinMachine *mc_tm, unsigned int *X, unsigned int *X_transformed, int invert, int number_of_examples); 62 | 63 | void mc_tm_clause_configuration(struct MultiClassTsetlinMachine *mc_tm, int class, int clause, unsigned int *clause_configuration); 64 | 65 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/Tools.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2019 Ole-Christoffer Granmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 24 | https://arxiv.org/abs/1905.09688 25 | 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | void tm_encode(unsigned int *X, unsigned int *encoded_X, int number_of_examples, int dim_x, int dim_y, int dim_z, int patch_dim_x, int patch_dim_y, int append_negated) 32 | { 33 | int global_number_of_features = dim_x * dim_y * dim_z; 34 | int number_of_features = patch_dim_x * patch_dim_y * dim_z + (dim_x - patch_dim_x) + (dim_y - patch_dim_y); 35 | int number_of_patches = (dim_x - patch_dim_x + 1) * (dim_y - patch_dim_y + 1); 36 | 37 | int number_of_ta_chunks; 38 | if (append_negated) { 39 | number_of_ta_chunks= (((2*number_of_features-1)/32 + 1)); 40 | } else { 41 | number_of_ta_chunks= (((number_of_features-1)/32 + 1)); 42 | } 43 | 44 | unsigned int *Xi; 45 | unsigned int *encoded_Xi; 46 | 47 | unsigned int input_pos = 0; 48 | unsigned int input_step_size = global_number_of_features; 49 | 50 | // Fill encoded_X with zeros 51 | 52 | memset(encoded_X, 0, number_of_examples * number_of_patches * number_of_ta_chunks * sizeof(unsigned int)); 53 | 54 | unsigned int encoded_pos = 0; 55 | for (int i = 0; i < number_of_examples; ++i) { 56 | int patch_nr = 0; 57 | // Produce the patches of the current image 58 | for (int y = 0; y < dim_y - patch_dim_y + 1; ++y) { 59 | for (int x = 0; x < dim_x - patch_dim_x + 1; ++x) { 60 | Xi = &X[input_pos]; 61 | encoded_Xi = &encoded_X[encoded_pos]; 62 | 63 | // Encode y coordinate of patch into feature vector 64 | for (int y_threshold = 0; y_threshold < dim_y - patch_dim_y; ++y_threshold) { 65 | int patch_pos = y_threshold; 66 | 67 | if (y > y_threshold) { 68 | int chunk_nr = patch_pos / 32; 69 | int chunk_pos = patch_pos % 32; 70 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 71 | } else if (append_negated) { 72 | int chunk_nr = (patch_pos + number_of_features) / 32; 73 | int chunk_pos = (patch_pos + number_of_features) % 32; 74 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 75 | } 76 | } 77 | 78 | // Encode x coordinate of patch into feature vector 79 | for (int x_threshold = 0; x_threshold < dim_x - patch_dim_x; ++x_threshold) { 80 | int patch_pos = (dim_y - patch_dim_y) + x_threshold; 81 | 82 | if (x > x_threshold) { 83 | int chunk_nr = patch_pos / 32; 84 | int chunk_pos = patch_pos % 32; 85 | 86 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 87 | } else if (append_negated) { 88 | int chunk_nr = (patch_pos + number_of_features) / 32; 89 | int chunk_pos = (patch_pos + number_of_features) % 32; 90 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 91 | } 92 | } 93 | 94 | // Encode patch content into feature vector 95 | for (int p_y = 0; p_y < patch_dim_y; ++p_y) { 96 | for (int p_x = 0; p_x < patch_dim_x; ++p_x) { 97 | for (int z = 0; z < dim_z; ++z) { 98 | int image_pos = (y + p_y)*dim_x*dim_z + (x + p_x)*dim_z + z; 99 | int patch_pos = (dim_y - patch_dim_y) + (dim_x - patch_dim_x) + p_y * patch_dim_x * dim_z + p_x * dim_z + z; 100 | 101 | if (Xi[image_pos] == 1) { 102 | int chunk_nr = patch_pos / 32; 103 | int chunk_pos = patch_pos % 32; 104 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 105 | } else if (append_negated) { 106 | int chunk_nr = (patch_pos + number_of_features) / 32; 107 | int chunk_pos = (patch_pos + number_of_features) % 32; 108 | encoded_Xi[chunk_nr] |= (1 << chunk_pos); 109 | } 110 | } 111 | } 112 | } 113 | encoded_pos += number_of_ta_chunks; 114 | patch_nr++; 115 | } 116 | } 117 | input_pos += input_step_size; 118 | } 119 | } -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/Tools.h: -------------------------------------------------------------------------------- 1 | void tm_encode(unsigned int *X, unsigned int *encoded_X, int number_of_examples, int dim_x, int dim_y, int dim_z, int patch_dim_x, int patch_dim_y, int append_negated); 2 | 3 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/fast_rand.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Yasser Phoulady on 2019-04-01. 3 | // 4 | 5 | #ifndef C_BITWISE_TSETLIN_MACHINE_FAST_RAND_H 6 | #define C_BITWISE_TSETLIN_MACHINE_FAST_RAND_H 7 | 8 | #include 9 | 10 | static uint64_t const multiplier = 6364136223846793005u; 11 | static uint64_t mcg_state = 0xcafef00dd15ea5e5u; 12 | 13 | inline static uint32_t pcg32_fast() { 14 | uint64_t x = mcg_state; 15 | unsigned int count = (unsigned int) (x >> 61); // 61 = 64 - 3 16 | 17 | mcg_state = x * multiplier; 18 | return (uint32_t) ((x ^ x >> 22) >> (22 + count)); // 22 = 32 - 3 - 7 19 | } 20 | 21 | //static void pcg32_fast_init(uint64_t seed) { 22 | // mcg_state = 2 * seed + 1; 23 | // pcg32_fast(); 24 | //} 25 | 26 | #define FAST_RAND_MAX UINT32_MAX 27 | #define fast_rand() pcg32_fast() 28 | 29 | // Box–Muller transform 30 | inline static int normal(double mean, double variance) { 31 | double u1 = (double) (fast_rand() + 1) / ((double) FAST_RAND_MAX + 1), u2 = (double) fast_rand() / FAST_RAND_MAX; // u1 in (0, 1] and u2 in [0, 1] 32 | double n1 = sqrt(-2 * log(u1)) * sin(8 * atan(1) * u2); 33 | return (int) round(mean + sqrt(variance) * n1); 34 | } 35 | 36 | inline static int binomial(int n, double p) { 37 | return normal(n * p, n * p * (1 - p)); 38 | } 39 | 40 | // Knuth's random Poisson-distributed number 41 | inline static int poisson(double lambda) { 42 | int k = 0; 43 | double l = exp(-lambda), p = 1; 44 | while (p > l) { 45 | ++k; 46 | p *= (double) fast_rand() / FAST_RAND_MAX; 47 | } 48 | return k - 1; 49 | } 50 | 51 | #endif //C_BITWISE_TSETLIN_MACHINE_FAST_RAND_H 52 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/makefile: -------------------------------------------------------------------------------- 1 | libTM: MultiClassConvolutionalTsetlinMachine.c MultiClassConvolutionalTsetlinMachine.h ConvolutionalTsetlinMachine.c ConvolutionalTsetlinMachine.h Tools.c Tools.h 2 | gcc -O3 -fopenmp -ffast-math -c -Wall -Werror -fpic MultiClassConvolutionalTsetlinMachine.c ConvolutionalTsetlinMachine.c Tools.c 3 | gcc -shared -O3 -fopenmp -ffast-math -o libTM.so MultiClassConvolutionalTsetlinMachine.o ConvolutionalTsetlinMachine.o Tools.o 4 | 5 | clean: 6 | rm *.o libTM.so 7 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/tm.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Ole-Christoffer Granmo 2 | 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | # This code implements the Convolutional Tsetlin Machine from paper arXiv:1905.09688 22 | # https://arxiv.org/abs/1905.09688 23 | 24 | import numpy as np 25 | import ctypes as C 26 | import os 27 | 28 | this_dir, this_filename = os.path.split(__file__) 29 | _lib = np.ctypeslib.load_library('libTM', os.path.join(this_dir, "..")) 30 | 31 | class CMultiClassConvolutionalTsetlinMachine(C.Structure): 32 | None 33 | 34 | class CConvolutionalTsetlinMachine(C.Structure): 35 | None 36 | 37 | mc_ctm_pointer = C.POINTER(CMultiClassConvolutionalTsetlinMachine) 38 | 39 | ctm_pointer = C.POINTER(CConvolutionalTsetlinMachine) 40 | 41 | array_1d_uint = np.ctypeslib.ndpointer( 42 | dtype=np.uint32, 43 | ndim=1, 44 | flags='CONTIGUOUS') 45 | 46 | array_1d_int = np.ctypeslib.ndpointer( 47 | dtype=np.int32, 48 | ndim=1, 49 | flags='CONTIGUOUS') 50 | 51 | 52 | # Multiclass Tsetlin Machine 53 | 54 | _lib.CreateMultiClassTsetlinMachine.restype = mc_ctm_pointer 55 | _lib.CreateMultiClassTsetlinMachine.argtypes = [C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_double, C.c_double, C.c_int, C.c_int] 56 | 57 | _lib.mc_tm_destroy.restype = None 58 | _lib.mc_tm_destroy.argtypes = [mc_ctm_pointer] 59 | 60 | _lib.mc_tm_fit.restype = None 61 | _lib.mc_tm_fit.argtypes = [mc_ctm_pointer, array_1d_uint, array_1d_uint, C.c_int, C.c_int] 62 | 63 | _lib.mc_tm_initialize.restype = None 64 | _lib.mc_tm_initialize.argtypes = [mc_ctm_pointer] 65 | 66 | _lib.mc_tm_predict.restype = None 67 | _lib.mc_tm_predict.argtypes = [mc_ctm_pointer, array_1d_uint, array_1d_uint, C.c_int] 68 | 69 | _lib.mc_tm_ta_state.restype = C.c_int 70 | _lib.mc_tm_ta_state.argtypes = [mc_ctm_pointer, C.c_int, C.c_int, C.c_int] 71 | 72 | _lib.mc_tm_ta_action.restype = C.c_int 73 | _lib.mc_tm_ta_action.argtypes = [mc_ctm_pointer, C.c_int, C.c_int, C.c_int] 74 | 75 | _lib.mc_tm_set_state.restype = None 76 | _lib.mc_tm_set_state.argtypes = [mc_ctm_pointer, C.c_int, array_1d_uint, array_1d_uint] 77 | 78 | _lib.mc_tm_get_state.restype = None 79 | _lib.mc_tm_get_state.argtypes = [mc_ctm_pointer, C.c_int, array_1d_uint, array_1d_uint] 80 | 81 | _lib.mc_tm_transform.restype = None 82 | _lib.mc_tm_transform.argtypes = [mc_ctm_pointer, array_1d_uint, array_1d_uint, C.c_int, C.c_int] 83 | 84 | _lib.mc_tm_clause_configuration.restype = None 85 | _lib.mc_tm_clause_configuration.argtypes = [mc_ctm_pointer, C.c_int, C.c_int, array_1d_uint] 86 | 87 | # Tsetlin Machine 88 | 89 | _lib.CreateTsetlinMachine.restype = ctm_pointer 90 | _lib.CreateTsetlinMachine.argtypes = [C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_double, C.c_double, C.c_int, C.c_int] 91 | 92 | _lib.tm_fit_regression.restype = None 93 | _lib.tm_fit_regression.argtypes = [ctm_pointer, array_1d_uint, array_1d_int, C.c_int, C.c_int] 94 | 95 | _lib.tm_predict_regression.restype = None 96 | _lib.tm_predict_regression.argtypes = [ctm_pointer, array_1d_uint, array_1d_int, C.c_int] 97 | 98 | # Tools 99 | 100 | _lib.tm_encode.restype = None 101 | _lib.tm_encode.argtypes = [array_1d_uint, array_1d_uint, C.c_int, C.c_int, C.c_int, C.c_int, C.c_int, C.c_int] 102 | 103 | class MultiClassConvolutionalTsetlinMachine2D(): 104 | def __init__(self, number_of_clauses, T, s, patch_dim, boost_true_positive_feedback=1, number_of_state_bits=8, append_negated=True, weighted_clauses=False, s_range=False): 105 | self.number_of_clauses = number_of_clauses 106 | self.number_of_clause_chunks = (number_of_clauses-1)/32 + 1 107 | self.number_of_state_bits = number_of_state_bits 108 | self.patch_dim = patch_dim 109 | self.T = int(T) 110 | self.s = s 111 | self.boost_true_positive_feedback = boost_true_positive_feedback 112 | self.mc_ctm = None 113 | self.append_negated = append_negated 114 | self.weighted_clauses = weighted_clauses 115 | if s_range: 116 | self.s_range = s_range 117 | else: 118 | self.s_range = s 119 | 120 | def __getstate__(self): 121 | state = self.__dict__.copy() 122 | state['mc_ctm_state'] = self.get_state() 123 | del state['mc_ctm'] 124 | if 'encoded_X' in state: 125 | del state['encoded_X'] 126 | return state 127 | 128 | def __setstate__(self, state): 129 | self.__dict__.update(state) 130 | self.mc_ctm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, self.number_of_patches, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 131 | self.set_state(state['mc_ctm_state']) 132 | 133 | def __del__(self): 134 | if self.mc_ctm != None: 135 | _lib.mc_tm_destroy(self.mc_ctm) 136 | 137 | def fit(self, X, Y, epochs=100, incremental=False): 138 | number_of_examples = X.shape[0] 139 | 140 | if self.mc_ctm == None: 141 | self.number_of_classes = int(np.max(Y) + 1) 142 | self.dim_x = X.shape[1] 143 | self.dim_y = X.shape[2] 144 | 145 | if len(X.shape) == 3: 146 | self.dim_z = 1 147 | elif len(X.shape) == 4: 148 | self.dim_z = X.shape[3] 149 | 150 | if self.append_negated: 151 | self.number_of_features = int(self.patch_dim[0]*self.patch_dim[1]*self.dim_z + (self.dim_x - self.patch_dim[0]) + (self.dim_y - self.patch_dim[1]))*2 152 | else: 153 | self.number_of_features = int(self.patch_dim[0]*self.patch_dim[1]*self.dim_z + (self.dim_x - self.patch_dim[0]) + (self.dim_y - self.patch_dim[1])) 154 | 155 | self.number_of_patches = int((self.dim_x - self.patch_dim[0] + 1)*(self.dim_y - self.patch_dim[1] + 1)) 156 | self.number_of_ta_chunks = int((self.number_of_features-1)/32 + 1) 157 | self.mc_ctm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, self.number_of_patches, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 158 | elif incremental == False: 159 | _lib.mc_tm_destroy(self.mc_ctm) 160 | self.mc_ctm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, self.number_of_patches, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 161 | 162 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 163 | 164 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 165 | Ym = np.ascontiguousarray(Y).astype(np.uint32) 166 | 167 | if self.append_negated: 168 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 1) 169 | else: 170 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 0) 171 | 172 | _lib.mc_tm_fit(self.mc_ctm, self.encoded_X, Ym, number_of_examples, epochs) 173 | 174 | return 175 | 176 | def predict(self, X): 177 | number_of_examples = X.shape[0] 178 | 179 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 180 | 181 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 182 | 183 | if self.append_negated: 184 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 1) 185 | else: 186 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 0) 187 | 188 | Y = np.ascontiguousarray(np.zeros(number_of_examples, dtype=np.uint32)) 189 | 190 | _lib.mc_tm_predict(self.mc_ctm, self.encoded_X, Y, number_of_examples) 191 | 192 | return Y 193 | 194 | def ta_state(self, mc_tm_class, clause, ta): 195 | return _lib.mc_tm_ta_state(self.mc_ctm, mc_tm_class, clause, ta) 196 | 197 | def ta_action(self, mc_tm_class, clause, ta): 198 | return _lib.mc_tm_ta_action(self.mc_ctm, mc_tm_class, clause, ta) 199 | 200 | def get_state(self): 201 | state_list = [] 202 | for i in range(self.number_of_classes): 203 | ta_states = np.ascontiguousarray(np.empty(self.number_of_clauses * self.number_of_ta_chunks * self.number_of_state_bits, dtype=np.uint32)) 204 | clause_weights = np.ascontiguousarray(np.empty(self.number_of_clauses, dtype=np.uint32)) 205 | _lib.mc_tm_get_state(self.mc_ctm, i, clause_weights, ta_states) 206 | state_list.append((clause_weights, ta_states)) 207 | 208 | return state_list 209 | 210 | def set_state(self, state_list): 211 | for i in range(self.number_of_classes): 212 | _lib.mc_tm_set_state(self.mc_ctm, i, state_list[i][0], state_list[i][1]) 213 | 214 | return 215 | 216 | def transform(self, X, inverted=True): 217 | number_of_examples = X.shape[0] 218 | 219 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 220 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 221 | 222 | if self.append_negated: 223 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 1) 224 | else: 225 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.dim_x, self.dim_y, self.dim_z, self.patch_dim[0], self.patch_dim[1], 0) 226 | 227 | X_transformed = np.ascontiguousarray(np.empty(number_of_examples*self.number_of_classes*self.number_of_clauses, dtype=np.uint32)) 228 | 229 | if (inverted): 230 | _lib.mc_tm_transform(self.mc_ctm, self.encoded_X, X_transformed, 1, number_of_examples) 231 | else: 232 | _lib.mc_tm_transform(self.mc_ctm, self.encoded_X, X_transformed, 0, number_of_examples) 233 | 234 | return X_transformed.reshape((number_of_examples, self.number_of_classes*self.number_of_clauses)) 235 | 236 | class MultiClassTsetlinMachine(): 237 | def __init__(self, number_of_clauses, T, s, boost_true_positive_feedback=1, number_of_state_bits=8, append_negated=True, weighted_clauses=False, s_range=False): 238 | self.number_of_clauses = number_of_clauses 239 | self.number_of_clause_chunks = (number_of_clauses-1)/32 + 1 240 | self.number_of_state_bits = number_of_state_bits 241 | self.T = int(T) 242 | self.s = s 243 | self.boost_true_positive_feedback = boost_true_positive_feedback 244 | self.mc_tm = None 245 | self.itm = None 246 | self.append_negated = append_negated 247 | self.weighted_clauses = weighted_clauses 248 | if s_range: 249 | self.s_range = s_range 250 | else: 251 | self.s_range = s 252 | 253 | def __getstate__(self): 254 | state = self.__dict__.copy() 255 | state['mc_tm_state'] = self.get_state() 256 | del state['mc_tm'] 257 | if 'encoded_X' in state: 258 | del state['encoded_X'] 259 | return state 260 | 261 | def __setstate__(self, state): 262 | self.__dict__.update(state) 263 | self.mc_tm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 264 | self.set_state(state['mc_tm_state']) 265 | 266 | def __del__(self): 267 | if self.mc_tm != None: 268 | _lib.mc_tm_destroy(self.mc_tm) 269 | 270 | if self.itm != None: 271 | _lib.itm_destroy(self.itm) 272 | 273 | def fit(self, X, Y, epochs=100, incremental=False): 274 | number_of_examples = X.shape[0] 275 | 276 | self.number_of_classes = int(np.max(Y) + 1) 277 | 278 | if self.mc_tm == None: 279 | if self.append_negated: 280 | self.number_of_features = X.shape[1]*2 281 | else: 282 | self.number_of_features = X.shape[1] 283 | 284 | self.number_of_patches = 1 285 | self.number_of_ta_chunks = int((self.number_of_features-1)/32 + 1) 286 | self.mc_tm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 287 | elif incremental == False: 288 | _lib.mc_tm_destroy(self.mc_tm) 289 | self.mc_tm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 290 | 291 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_ta_chunks), dtype=np.uint32)) 292 | 293 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 294 | Ym = np.ascontiguousarray(Y).astype(np.uint32) 295 | 296 | if self.append_negated: 297 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features//2, 1, 1, self.number_of_features//2, 1, 1) 298 | else: 299 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features, 1, 1, self.number_of_features, 1, 0) 300 | 301 | _lib.mc_tm_fit(self.mc_tm, self.encoded_X, Ym, number_of_examples, epochs) 302 | 303 | return 304 | 305 | def predict(self, X): 306 | number_of_examples = X.shape[0] 307 | 308 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 309 | 310 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 311 | 312 | if self.append_negated: 313 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features//2, 1, 1, self.number_of_features//2, 1, 1) 314 | else: 315 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features, 1, 1, self.number_of_features, 1, 0) 316 | 317 | Y = np.ascontiguousarray(np.zeros(number_of_examples, dtype=np.uint32)) 318 | 319 | _lib.mc_tm_predict(self.mc_tm, self.encoded_X, Y, number_of_examples) 320 | 321 | return Y 322 | 323 | def ta_state(self, mc_tm_class, clause, ta): 324 | return _lib.mc_tm_ta_state(self.mc_tm, mc_tm_class, clause, ta) 325 | 326 | def ta_action(self, mc_tm_class, clause, ta): 327 | return _lib.mc_tm_ta_action(self.mc_tm, mc_tm_class, clause, ta) 328 | 329 | def get_state(self): 330 | state_list = [] 331 | for i in range(self.number_of_classes): 332 | ta_states = np.ascontiguousarray(np.empty(self.number_of_clauses * self.number_of_ta_chunks * self.number_of_state_bits, dtype=np.uint32)) 333 | clause_weights = np.ascontiguousarray(np.empty(self.number_of_clauses, dtype=np.uint32)) 334 | _lib.mc_tm_get_state(self.mc_tm, i, clause_weights, ta_states) 335 | state_list.append((clause_weights, ta_states)) 336 | 337 | return state_list 338 | 339 | def set_state(self, state_list): 340 | for i in range(self.number_of_classes): 341 | _lib.mc_tm_set_state(self.mc_tm, i, state_list[i][0], state_list[i][1]) 342 | 343 | return 344 | 345 | def transform(self, X, inverted=True): 346 | number_of_examples = X.shape[0] 347 | 348 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 349 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 350 | 351 | if self.append_negated: 352 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features//2, 1, 1, self.number_of_features//2, 1, 1) 353 | else: 354 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features, 1, 1, self.number_of_features, 1, 0) 355 | 356 | X_transformed = np.ascontiguousarray(np.empty(number_of_examples*self.number_of_classes*self.number_of_clauses, dtype=np.uint32)) 357 | 358 | _lib.mc_tm_transform(self.mc_tm, self.encoded_X, X_transformed, inverted, number_of_examples) 359 | 360 | return X_transformed.reshape((number_of_examples, self.number_of_classes*self.number_of_clauses)) 361 | 362 | class RegressionTsetlinMachine(): 363 | def __init__(self, number_of_clauses, T, s, boost_true_positive_feedback=1, number_of_state_bits=8, weighted_clauses=False, s_range=False): 364 | self.number_of_clauses = number_of_clauses 365 | self.number_of_clause_chunks = (number_of_clauses-1)/32 + 1 366 | self.number_of_state_bits = number_of_state_bits 367 | self.T = int(T) 368 | self.s = s 369 | self.boost_true_positive_feedback = boost_true_positive_feedback 370 | self.rtm = None 371 | self.weighted_clauses = weighted_clauses 372 | if s_range: 373 | self.s_range = s_range 374 | else: 375 | self.s_range = s 376 | 377 | def __getstate__(self): 378 | state = self.__dict__.copy() 379 | state['rtm_state'] = self.get_state() 380 | del state['rtm'] 381 | if 'encoded_X' in state: 382 | del state['encoded_X'] 383 | return state 384 | 385 | def __setstate__(self, state): 386 | self.__dict__.update(state) 387 | self.rtm = _lib.CreateTsetlinMachine(self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 388 | self.set_state(state['rtm_state']) 389 | 390 | def __del__(self): 391 | if self.rtm != None: 392 | _lib.tm_destroy(self.rtm) 393 | 394 | def fit(self, X, Y, epochs=100, incremental=False): 395 | number_of_examples = X.shape[0] 396 | 397 | self.max_y = np.max(Y) 398 | self.min_y = np.min(Y) 399 | 400 | if self.rtm == None: 401 | self.number_of_features = X.shape[1]*2 402 | self.number_of_patches = 1 403 | self.number_of_ta_chunks = int((self.number_of_features-1)/32 + 1) 404 | self.rtm = _lib.CreateTsetlinMachine(self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 405 | elif incremental == False: 406 | _lib.tm_destroy(self.rtm) 407 | self.rtm = _lib.CreateTsetlinMachine(self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses) 408 | 409 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_ta_chunks), dtype=np.uint32)) 410 | 411 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 412 | Ym = np.ascontiguousarray((Y - self.min_y)/(self.max_y - self.min_y)*self.T).astype(np.int32) 413 | 414 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features//2, 1, 1, self.number_of_features//2, 1, 1) 415 | 416 | _lib.tm_fit_regression(self.rtm, self.encoded_X, Ym, number_of_examples, epochs) 417 | 418 | return 419 | 420 | def predict(self, X): 421 | number_of_examples = X.shape[0] 422 | 423 | self.encoded_X = np.ascontiguousarray(np.empty(int(number_of_examples * self.number_of_patches * self.number_of_ta_chunks), dtype=np.uint32)) 424 | 425 | Xm = np.ascontiguousarray(X.flatten()).astype(np.uint32) 426 | _lib.tm_encode(Xm, self.encoded_X, number_of_examples, self.number_of_features//2, 1, 1, self.number_of_features//2, 1, 1) 427 | 428 | Y = np.zeros(number_of_examples, dtype=np.int32) 429 | 430 | _lib.tm_predict_regression(self.rtm, self.encoded_X, Y, number_of_examples) 431 | 432 | return 1.0*(Y)*(self.max_y - self.min_y)/(self.T) + self.min_y 433 | -------------------------------------------------------------------------------- /pyTsetlinMachineParallel/tools.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Binarizer: 4 | def __init__(self, max_bits_per_feature = 25): 5 | self.max_bits_per_feature = max_bits_per_feature 6 | return 7 | 8 | def fit(self, X): 9 | self.number_of_features = 0 10 | self.unique_values = [] 11 | for i in range(X.shape[1]): 12 | uv = np.unique(X[:,i])[1:] 13 | if uv.size > self.max_bits_per_feature: 14 | unique_values = np.empty(0) 15 | 16 | step_size = 1.0*uv.size/self.max_bits_per_feature 17 | pos = 0.0 18 | while int(pos) < uv.size and unique_values.size < self.max_bits_per_feature: 19 | unique_values = np.append(unique_values, np.array(uv[int(pos)])) 20 | pos += step_size 21 | else: 22 | unique_values = uv 23 | 24 | self.unique_values.append(unique_values) 25 | self.number_of_features += self.unique_values[-1].size 26 | return 27 | 28 | def transform(self, X): 29 | X_transformed = np.zeros((X.shape[0], self.number_of_features)) 30 | 31 | pos = 0 32 | for i in range(X.shape[1]): 33 | for j in range(self.unique_values[i].size): 34 | X_transformed[:,pos] = (X[:,i] >= self.unique_values[i][j]) 35 | pos += 1 36 | 37 | return X_transformed -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import * 2 | 3 | libTM = Extension('libTM', 4 | sources = ['pyTsetlinMachineParallel/ConvolutionalTsetlinMachine.c', 'pyTsetlinMachineParallel/MultiClassConvolutionalTsetlinMachine.c', 'pyTsetlinMachineParallel/Tools.c'], 5 | include_dirs=['pyTsetlinMachineParallel'], 6 | extra_compile_args=['-fopenmp'], 7 | extra_link_args=['-lgomp']) 8 | 9 | setup( 10 | name='pyTsetlinMachineParallel', 11 | version='0.2.1', 12 | author='Ole-Christoffer Granmo', 13 | author_email='ole.granmo@uia.no', 14 | url='https://github.com/cair/pyTsetlinMachineParallel/', 15 | license='MIT', 16 | description='Multi-threaded implementation of the Tsetlin Machine, Convolutional Tsetlin Machine, Regression Tsetlin Machine, and Weighted Tsetlin Machine, with support for continuous features and multigranularity.', 17 | long_description='Multi-threaded implementation of the Tsetlin Machine, Convolutional Tsetlin Machine, Regression Tsetlin Machine, and Weighted Tsetlin Machine, with support for continuous features and multigranularity.', 18 | ext_modules = [libTM], 19 | keywords ='pattern-recognition machine-learning interpretable-machine-learning rule-based-machine-learning propositional-logic tsetlin-machine regression convolution', 20 | packages=['pyTsetlinMachineParallel'] 21 | ) 22 | --------------------------------------------------------------------------------