├── 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 |   
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 |
--------------------------------------------------------------------------------