PyHierarchicalTsetlinMachineCUDA 0.2.7__tar.gz → 0.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (15) hide show
  1. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PKG-INFO +1 -1
  2. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/kernels.py +234 -108
  3. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tm.py +165 -134
  4. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/PKG-INFO +1 -1
  5. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/README.md +2 -2
  6. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.py +1 -1
  7. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/LICENSE +0 -0
  8. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/__init__.py +0 -0
  9. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/tools.py +0 -0
  10. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA/utils.py +0 -0
  11. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/SOURCES.txt +0 -0
  12. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/dependency_links.txt +0 -0
  13. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/requires.txt +0 -0
  14. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/PyHierarchicalTsetlinMachineCUDA.egg-info/top_level.txt +0 -0
  15. {PyHierarchicalTsetlinMachineCUDA-0.2.7 → PyHierarchicalTsetlinMachineCUDA-0.2.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyHierarchicalTsetlinMachineCUDA
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: Hierarchical Tsetlin Machine Architecture.
5
5
  Home-page: https://github.com/cair/PyHierarchicalTsetlinMachineCUDA/
6
6
  Author: Ole-Christoffer Granmo
@@ -21,6 +21,8 @@
21
21
  code_header = """
22
22
  #include <curand_kernel.h>
23
23
 
24
+ #define NEG_INFINITY (-1 * INFINITY)
25
+
24
26
  #define INT_SIZE 32ULL
25
27
 
26
28
  #if (LITERALS_PER_LEAF % 32 != 0)
@@ -82,7 +84,7 @@ code_update = """
82
84
  }
83
85
  }
84
86
 
85
- __device__ inline void update_clause_weight(curandState *localState, int tm_type, int number_of_outputs, int *clause_weight, int clause_output, int y, int class_sum)
87
+ __device__ inline void update_clause_weight(curandState *localState, int tm_type, int number_of_outputs, int *clause_weight, int clause_output, int y, float class_sum)
86
88
  {
87
89
  int target = 1 - 2*(class_sum > y);
88
90
 
@@ -92,7 +94,7 @@ code_update = """
92
94
 
93
95
  int sign = (*clause_weight >= 0) - (*clause_weight < 0);
94
96
 
95
- int absolute_prediction_error = abs(y - class_sum);
97
+ float absolute_prediction_error = fabsf(y - class_sum);
96
98
  if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
97
99
  if (target*sign > 0) {
98
100
  if (clause_output && abs(*clause_weight) < INT_MAX) {
@@ -112,18 +114,17 @@ code_update = """
112
114
  }
113
115
  }
114
116
 
115
- __device__ inline void update_component_hierarchy(curandState *localState, int number_of_outputs, int *clause_weight, unsigned int *ta_state, int component_output, int *X, int y, int class_sum)
117
+ __device__ inline void update_component_hierarchy(curandState *localState, int number_of_outputs, int *clause_weight, unsigned int *ta_state, int component_output, int *X, int y, float class_sum)
116
118
  {
117
119
  int target = 1 - 2*(class_sum > y);
118
-
120
+
119
121
  if (target == -1 && curand_uniform(localState) > 1.0*Q/max(1, number_of_outputs-1)) {
120
122
  return;
121
123
  }
122
-
123
124
 
124
125
  int sign = (*clause_weight >= 0) - (*clause_weight < 0);
125
126
 
126
- int absolute_prediction_error = abs(y - class_sum);
127
+ float absolute_prediction_error = fabsf(y - class_sum);
127
128
  if (curand_uniform(localState) <= 1.0*absolute_prediction_error/(2*THRESHOLD)) {
128
129
  if (target*sign > 0) {
129
130
  // Type I Feedback
@@ -159,7 +160,7 @@ code_update = """
159
160
  }
160
161
 
161
162
  // Evaluate example
162
- __global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights, int *global_component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *X, int example)
163
+ __global__ void evaluate_leaves(unsigned int *global_ta_state, int *component_weights, float *global_component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *X, int example)
163
164
  {
164
165
  int index = blockIdx.x * blockDim.x + threadIdx.x;
165
166
  int stride = blockDim.x * gridDim.x;
@@ -177,42 +178,59 @@ code_update = """
177
178
  int size_feature_chunk_base = 1;
178
179
  int size_ta_chunk_base = 1;
179
180
  for (int d = 0; d < depth-1; ++d) {
180
- int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
181
- component_remainder = component_remainder / hierarchy_structure_factors[d];
181
+ int depth_d_node_index = component_remainder % hierarchy_structure_factors[d]; // Extract local index of node at depth d (the child index)
182
+ component_remainder = component_remainder / hierarchy_structure_factors[d]; // Move up the hierarchy to prepare for finding the local node index at depth d+1
182
183
 
183
- if (hierarchy_structure_type[d] != 1) {
184
- feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
185
- size_feature_chunk_base *= hierarchy_structure_factors[d];
184
+ // Support multiple Tsetlin Automata teams operating on the same feature chunks to create alternatives.
185
+ if ((hierarchy_structure_type[d] != OR_ALTERNATIVES) && (hierarchy_structure_type[d] != AND_ALTERNATIVES)) {
186
+ feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF; // Identify correct part of the sub-hierarchy (through flattening)
187
+ size_feature_chunk_base *= hierarchy_structure_factors[d]; // Identify how many nodes to jump to skip from one child to the next when indexing at the next depth level
186
188
  }
187
189
 
188
- if (hierarchy_structure_type[d] != 2) {
190
+ // Support reuse of the same Tsetlin Automata when doing OR to group different feature chunks
191
+ if (hierarchy_structure_type[d] != OR_GROUP) {
189
192
  ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
190
193
  size_ta_chunk_base *= hierarchy_structure_factors[d];
191
194
  }
192
195
  }
193
196
 
194
197
  // Get state of current ta team component
195
- unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
198
+ unsigned int *ta_state = &global_ta_state[clause*TA_TEAMS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
196
199
 
197
200
  // Evaluate clause component
198
- int component_output = 1;
201
+
202
+ #if LOG_SCALE == 1
203
+ float component_output = 0;
204
+ #else
205
+ float component_output = 1;
206
+ #endif
207
+
199
208
  for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF-1; ++ta_chunk) {
200
209
  // Compare the TA state of the component (leaf) against the corresponding part of the feature vector
201
210
  if ((ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] & Xi[feature_chunk_base + ta_chunk]) != ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1]) {
202
- component_output = 0;
211
+ #if LOG_SCALE == 1
212
+ component_output = NEG_INFINITY;
213
+ #else
214
+ component_output = 0;
215
+ #endif
216
+
203
217
  break;
204
218
  }
205
219
  }
206
220
 
207
221
  if ((ta_state[(TA_CHUNKS_PER_LEAF-1)*STATE_BITS + STATE_BITS - 1] & Xi[feature_chunk_base + TA_CHUNKS_PER_LEAF-1] & FILTER_HIERARCHICAL) != (ta_state[(TA_CHUNKS_PER_LEAF-1)*STATE_BITS + STATE_BITS - 1] & FILTER_HIERARCHICAL)) {
208
- component_output = 0;
222
+ #if LOG_SCALE == 1
223
+ component_output = NEG_INFINITY;
224
+ #else
225
+ component_output = 0;
226
+ #endif
209
227
  }
210
228
 
211
229
  global_component_output[clause_component] = component_output;
212
230
  }
213
231
  }
214
232
 
215
- __global__ void evaluate_or_groups(int *child_input, int *or_group_node_output, int number_of_or_group_nodes, int number_of_or_group_addends)
233
+ __global__ void evaluate_or_groups(float *child_input, float *or_group_node_output, int number_of_or_group_nodes, int number_of_or_group_addends)
216
234
  {
217
235
  int index = blockIdx.x * blockDim.x + threadIdx.x;
218
236
  int stride = blockDim.x * gridDim.x;
@@ -220,7 +238,7 @@ code_update = """
220
238
  // Add up the votes of each OR node child
221
239
  for (int or_group_node = index; or_group_node < CLAUSES*number_of_or_group_nodes; or_group_node += stride) {
222
240
  // Add OR addends
223
- int or_group_vote_sum = 0;
241
+
224
242
  int max_vote_sum = 0;
225
243
 
226
244
  for (int or_addend = 0; or_addend < number_of_or_group_addends; ++or_addend) {
@@ -229,21 +247,13 @@ code_update = """
229
247
  if (child_input[or_group_node*number_of_or_group_addends + or_addend] > max_vote_sum) {
230
248
  max_vote_sum = child_input[or_group_node*number_of_or_group_addends + or_addend];
231
249
  }
232
-
233
- int previous_or_group_vote_sum = or_group_vote_sum;
234
- or_group_vote_sum += child_input[or_group_node*number_of_or_group_addends + or_addend];
235
- if (or_group_vote_sum < 0) {
236
- printf("OR* OVERFLOW %d -> %d\\n", previous_or_group_vote_sum, or_group_vote_sum);
237
- or_group_vote_sum = previous_or_group_vote_sum;
238
- }
239
250
  }
240
251
 
241
- //or_group_node_output[or_group_node] = or_group_vote_sum;
242
252
  or_group_node_output[or_group_node] = max_vote_sum;
243
253
  }
244
254
  }
245
255
 
246
- __global__ void evaluate_and_groups(int *child_input, int *and_group_node_output, int number_of_and_group_nodes, int number_of_and_group_factors)
256
+ __global__ void evaluate_and_groups(float *child_input, float *and_group_node_output, int number_of_and_group_nodes, int number_of_and_group_factors)
247
257
  {
248
258
  int index = blockIdx.x * blockDim.x + threadIdx.x;
249
259
  int stride = blockDim.x * gridDim.x;
@@ -251,48 +261,62 @@ code_update = """
251
261
  // Multiply the votes from the children of each AND node
252
262
  for (int and_group_node = index; and_group_node < CLAUSES*number_of_and_group_nodes; and_group_node += stride) {
253
263
  // Multiply and factors
254
- int and_group_vote_product = 1;
255
- int max_vote_sum = 0;
264
+
265
+ #if LOG_SCALE == 1
266
+ float and_group_vote_product = 0;
267
+ #else
268
+ float and_group_vote_product = 1;
269
+ #endif
270
+
256
271
  for (int and_factor = 0; and_factor < number_of_and_group_factors; ++and_factor) {
257
272
  // Aggregate votes from each child node through multiplication
258
273
 
259
- int previous_and_group_vote_product = and_group_vote_product;
260
- and_group_vote_product *= child_input[and_group_node*number_of_and_group_factors + and_factor];
261
-
262
- if (child_input[and_group_node*number_of_and_group_factors + and_factor] > max_vote_sum) {
263
- max_vote_sum = child_input[and_group_node*number_of_and_group_factors + and_factor];
264
- }
265
-
266
- if (and_group_vote_product < 0) {
267
- printf("AND OVERFLOW %d -> %d\\n", previous_and_group_vote_product, and_group_vote_product);
268
- and_group_vote_product = previous_and_group_vote_product;
269
- }
274
+ #if LOG_SCALE == 1
275
+ and_group_vote_product += child_input[and_group_node*number_of_and_group_factors + and_factor];
276
+ #else
277
+ and_group_vote_product *= child_input[and_group_node*number_of_and_group_factors + and_factor];
278
+ #endif
270
279
  }
271
-
272
- // Store and group product as node output
280
+
273
281
  and_group_node_output[and_group_node] = and_group_vote_product;
274
- //and_group_node_output[and_group_node] = max_vote_sum;
275
282
  }
276
283
  }
277
284
 
278
- __global__ void propagate_and_group_false_truth_values(int *child_input, int *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
285
+ __global__ void propagate_and_group_false_truth_values(float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
286
+ //__global__ void propagate_and_group_false_truth_values_log(int *child_input, int *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
279
287
  {
280
288
  int index = blockIdx.x * blockDim.x + threadIdx.x;
281
289
  int stride = blockDim.x * gridDim.x;
282
290
 
283
291
  // If a group node is false, all children are made false.
284
292
  for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
285
- if (group_node_output[group_node] == 0) {
286
- for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
287
- if (child_input[group_node*number_of_group_node_children + and_factor] > 0) {
288
- child_input[group_node*number_of_group_node_children + and_factor] = 0;
293
+ #if LOG_SCALE == 1
294
+ if (group_node_output[group_node] == NEG_INFINITY) {
295
+ for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
296
+ if (child_input[group_node*number_of_group_node_children + and_factor] >= 0) {
297
+ child_input[group_node*number_of_group_node_children + and_factor] = NEG_INFINITY;
298
+ }
299
+ }
300
+ }
301
+ #else
302
+ if (group_node_output[group_node] == 0) {
303
+ for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
304
+ if (child_input[group_node*number_of_group_node_children + and_factor] > 0) {
305
+ child_input[group_node*number_of_group_node_children + and_factor] = 0;
306
+ }
289
307
  }
290
308
  }
309
+ #endif
310
+
311
+ if (group_node_output[group_node] == -1) {
312
+ for (int and_factor = 0; and_factor < number_of_group_node_children; ++and_factor) {
313
+ child_input[group_node*number_of_group_node_children + and_factor] = -1;
314
+ }
291
315
  }
292
316
  }
293
317
  }
294
318
 
295
- __global__ void propagate_or_group_false_truth_values(curandState *state, int *child_input, int *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
319
+ __global__ void propagate_or_group_false_truth_values(curandState *state, float *child_input, float *group_node_output, int number_of_group_nodes, int number_of_group_node_children)
296
320
  {
297
321
  int index = blockIdx.x * blockDim.x + threadIdx.x;
298
322
  int stride = blockDim.x * gridDim.x;
@@ -306,24 +330,45 @@ code_update = """
306
330
  for (int group_node = index; group_node < CLAUSES*number_of_group_nodes; group_node += stride) {
307
331
  int number_of_non_zero_children = 0;
308
332
 
309
- if (group_node_output[group_node] == -1) {
310
- for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
311
- child_input[group_node*number_of_group_node_children + or_addend] = -1;
312
- }
313
- } else if (group_node_output[group_node] == 0) {
314
- for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
315
- if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
316
- child_input[group_node*number_of_group_node_children + or_addend] = 0;
333
+ #if LOG_SCALE == 1
334
+ if (group_node_output[group_node] == -1) {
335
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
336
+ child_input[group_node*number_of_group_node_children + or_addend] = -1;
337
+ }
338
+ } else if (group_node_output[group_node] == NEG_INFINITY) {
339
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
340
+ if (child_input[group_node*number_of_group_node_children + or_addend] >= 0) {
341
+ child_input[group_node*number_of_group_node_children + or_addend] = NEG_INFINITY;
342
+ }
343
+ }
344
+ } else {
345
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
346
+ if (child_input[group_node*number_of_group_node_children + or_addend] >= 0) {
347
+ non_zero_children[number_of_non_zero_children] = or_addend;
348
+ number_of_non_zero_children++;
349
+ }
317
350
  }
318
351
  }
319
- } else {
320
- for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
321
- if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
322
- non_zero_children[number_of_non_zero_children] = or_addend;
323
- number_of_non_zero_children++;
352
+ #else
353
+ if (group_node_output[group_node] == -1) {
354
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
355
+ child_input[group_node*number_of_group_node_children + or_addend] = -1;
356
+ }
357
+ } else if (group_node_output[group_node] == 0) {
358
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
359
+ if (child_input[group_node*number_of_group_node_children + or_addend] > 0) {
360
+ child_input[group_node*number_of_group_node_children + or_addend] = 0;
361
+ }
362
+ }
363
+ } else {
364
+ for (int or_addend = 0; or_addend < number_of_group_node_children; ++or_addend) {
365
+ if (child_input[group_node*number_of_group_node_children + or_addend] > 0) { // Or pick the largest.... picking randomly when a tie
366
+ non_zero_children[number_of_non_zero_children] = or_addend;
367
+ number_of_non_zero_children++;
368
+ }
324
369
  }
325
370
  }
326
- }
371
+ #endif
327
372
 
328
373
  if (group_node_output[group_node] != -1) {
329
374
  int selected_child;
@@ -344,51 +389,129 @@ code_update = """
344
389
  state[index] = localState;
345
390
  }
346
391
 
347
- __global__ void evaluate_or_alternatives(int *child_input, int *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
392
+ __global__ void evaluate_or_alternatives(float *child_input, float *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
393
+ //__global__ void evaluate_or_alternatives_log(int *child_input, int *or_alternatives_node_output, int number_of_or_alternatives_nodes, int number_of_or_alternatives)
348
394
  {
349
395
  int index = blockIdx.x * blockDim.x + threadIdx.x;
350
396
  int stride = blockDim.x * gridDim.x;
351
397
 
352
398
  // Add up the votes from the children of each OR node
353
399
  for (int or_alternatives_node = index; or_alternatives_node < CLAUSES*number_of_or_alternatives_nodes; or_alternatives_node += stride) {
354
- // Sum up votes from each or alternative
355
- int or_alternatives_vote_sum = 0;
356
- for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
357
- // Aggregate same input or alternatives through summation
358
-
400
+ #if LOG_SCALE == 1
401
+ float or_alternatives_vote_max = NEG_INFINITY;
402
+ for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
403
+ if (child_input[or_alternatives_node * number_of_or_alternatives + or_alternative] > or_alternatives_vote_max) {
404
+ or_alternatives_vote_max = child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
405
+ }
406
+ }
359
407
 
360
- int previous_or_alternatives_vote_sum = or_alternatives_vote_sum;
361
- or_alternatives_vote_sum += child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
408
+ if (or_alternatives_vote_max != NEG_INFINITY) {
409
+ // Sum up votes from each or alternative
410
+ float or_alternatives_vote_sum = 0;
411
+ for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
412
+ // Aggregates or alternatives through summation
413
+
414
+ or_alternatives_vote_sum += exp2f(child_input[or_alternatives_node * number_of_or_alternatives + or_alternative] - or_alternatives_vote_max);
415
+ }
362
416
 
363
- if (or_alternatives_vote_sum < 0) {
364
- printf("OR OVERFLOW %d -> %d\\n", previous_or_alternatives_vote_sum, or_alternatives_vote_sum);
365
- or_alternatives_vote_sum = previous_or_alternatives_vote_sum;
417
+ // Store vote sum as node output
418
+ or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_max + log2f(or_alternatives_vote_sum);
419
+ } else {
420
+ or_alternatives_node_output[or_alternatives_node] = NEG_INFINITY;
421
+ }
422
+ #else
423
+ // Sum up votes from each or alternative
424
+ int or_alternatives_vote_sum = 0;
425
+ for (int or_alternative = 0; or_alternative < number_of_or_alternatives; ++or_alternative) {
426
+ // Aggregate same input or alternatives through summation
427
+ or_alternatives_vote_sum += child_input[or_alternatives_node * number_of_or_alternatives + or_alternative];
366
428
  }
367
- }
368
429
 
369
- // Store vote sum as node output
370
- or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_sum;
430
+ // Store vote sum as node output
431
+ or_alternatives_node_output[or_alternatives_node] = or_alternatives_vote_sum;
432
+ #endif
371
433
  }
372
434
  }
373
435
 
374
- __global__ void evaluate_final(int number_of_outputs, int *child_input, int *clause_weights, int *class_sum)
436
+ __global__ void max_clause_output(int number_of_outputs, float *clause_output, float *clause_output_max)
375
437
  {
376
438
  int index = blockIdx.x * blockDim.x + threadIdx.x;
377
439
  int stride = blockDim.x * gridDim.x;
378
440
 
379
441
  // Add up the votes from each clause
380
442
  for (int clause = index; clause < CLAUSES; clause += stride) {
381
- if (child_input[clause]) {
382
- for (int class_id = 0; class_id < number_of_outputs; ++class_id) {
383
- int clause_weight = clause_weights[class_id*CLAUSES + clause];
384
- atomicAdd(&class_sum[class_id], clause_weight * child_input[clause]);
443
+ atomicMax((int *)&clause_output_max[0], __float_as_int(clause_output[clause]));
444
+ }
445
+ }
446
+
447
+ __global__ void evaluate_final(int number_of_outputs, float *clause_output, int *clause_weights, float *class_sum)
448
+ {
449
+ int index = blockIdx.x * blockDim.x + threadIdx.x;
450
+ int stride = blockDim.x * gridDim.x;
451
+
452
+ // Add up the votes from each clause
453
+ #if LOG_SCALE == 1
454
+ // Add up the votes from each clause
455
+ for (int class_id = index; class_id < number_of_outputs; class_id += stride) {
456
+ float clause_output_max = NEG_INFINITY;
457
+ for (int clause = 0; clause < CLAUSES; ++clause) {
458
+ if (clause_output[clause] > clause_output_max) {
459
+ clause_output_max = clause_output[clause];
460
+ }
461
+ }
462
+
463
+ if (clause_output_max != NEG_INFINITY) {
464
+ float weighted_clause_output_sum = 0;
465
+ for (int clause = 0; clause < CLAUSES; ++clause) {
466
+ weighted_clause_output_sum += clause_weights[class_id*CLAUSES + clause] * exp2f(clause_output[clause] - clause_output_max);
467
+ }
468
+
469
+ if (log2f(fabs(weighted_clause_output_sum)) + clause_output_max >= log2f(THRESHOLD)) {
470
+ float sign = (1 - 2 * (weighted_clause_output_sum < 0));
471
+ class_sum[class_id] = sign*THRESHOLD;
472
+ } else {
473
+ class_sum[class_id] = weighted_clause_output_sum * exp2f(clause_output_max);
474
+ }
475
+ } else {
476
+ class_sum[class_id] = 0;
477
+ }
478
+ }
479
+ #else
480
+ for (int clause = index; clause < CLAUSES; clause += stride) {
481
+ if (clause_output[clause]) {
482
+ for (int class_id = 0; class_id < number_of_outputs; ++class_id) {
483
+ atomicAdd(&class_sum[class_id], (float) clause_weights[class_id*CLAUSES + clause] * clause_output[clause]);
484
+ }
485
+ }
486
+ }
487
+ #endif
488
+ }
489
+
490
+ __global__ void rescale_final(int number_of_outputs, float *clause_output_max, float *class_sum)
491
+ {
492
+ int index = blockIdx.x * blockDim.x + threadIdx.x;
493
+ int stride = blockDim.x * gridDim.x;
494
+
495
+ // Add up the votes from each clause
496
+
497
+ if (clause_output_max[0] > NEG_INFINITY) {
498
+ for (int class_id = index; class_id < number_of_outputs; class_id += stride) {
499
+ float rescaled_abs_class_sum = log2f(fabsf(class_sum[class_id])) + clause_output_max[0];
500
+ if (rescaled_abs_class_sum >= log2f(THRESHOLD)) {
501
+ if (class_sum[class_id] >= 0) {
502
+ class_sum[class_id] = THRESHOLD;
503
+ } else {
504
+ class_sum[class_id] = -1*THRESHOLD;
505
+ }
506
+ } else {
507
+ class_sum[class_id] = class_sum[class_id] * exp2f(clause_output_max[0]);
385
508
  }
386
509
  }
387
510
  }
388
511
  }
389
512
 
390
513
  // Update state of Tsetlin Automata team
391
- __global__ void update_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, int *component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, int *class_sum, int *X, int *y, int example)
514
+ __global__ void update_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, float *component_output, int depth, int *hierarchy_structure_factors, int *hierarchy_structure_type, float *class_sum, int *X, int *y, int example)
392
515
  {
393
516
  int index = blockIdx.x * blockDim.x + threadIdx.x;
394
517
  int stride = blockDim.x * gridDim.x;
@@ -408,7 +531,6 @@ code_update = """
408
531
  int component = clause_component % COMPONENTS;
409
532
 
410
533
  // Get state of current clause component
411
- // This one must be updated for reuse of TAs within OR group
412
534
 
413
535
  int component_remainder = component;
414
536
  int feature_chunk_base = 0;
@@ -419,29 +541,33 @@ code_update = """
419
541
  int depth_d_node_index = component_remainder % hierarchy_structure_factors[d];
420
542
  component_remainder = component_remainder / hierarchy_structure_factors[d];
421
543
 
422
- if (hierarchy_structure_type[d] != 1) {
544
+ if ((hierarchy_structure_type[d] != OR_ALTERNATIVES) && (hierarchy_structure_type[d] != AND_ALTERNATIVES)) {
423
545
  feature_chunk_base += size_feature_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
424
546
  size_feature_chunk_base *= hierarchy_structure_factors[d];
425
547
  }
426
548
 
427
- if (hierarchy_structure_type[d] != 2) {
549
+ if (hierarchy_structure_type[d] != OR_GROUP) {
428
550
  ta_chunk_base += size_ta_chunk_base * depth_d_node_index * TA_CHUNKS_PER_LEAF;
429
551
  size_ta_chunk_base *= hierarchy_structure_factors[d];
430
552
  }
431
553
  }
432
554
 
433
555
  // Get state of current ta team component
434
- unsigned int *ta_state = &global_ta_state[clause*COMPONENTS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
556
+ unsigned int *ta_state = &global_ta_state[clause*TA_TEAMS*TA_CHUNKS_PER_LEAF*STATE_BITS + ta_chunk_base*STATE_BITS];
435
557
 
436
558
  for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
437
- int local_class_sum = class_sum[class_id];
559
+ float local_class_sum = class_sum[class_id];
438
560
  if (local_class_sum > THRESHOLD) {
439
561
  local_class_sum = THRESHOLD;
440
562
  } else if (local_class_sum < -THRESHOLD) {
441
563
  local_class_sum = -THRESHOLD;
442
564
  }
443
565
 
444
- update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component], &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
566
+ #if LOG_SCALE == 1
567
+ update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component] != NEG_INFINITY, &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
568
+ #else
569
+ update_component_hierarchy(&localState, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], ta_state, component_output[clause_component] > 0, &Xi[feature_chunk_base], y[example*number_of_outputs + class_id], local_class_sum);
570
+ #endif
445
571
  }
446
572
  }
447
573
 
@@ -449,7 +575,7 @@ code_update = """
449
575
  }
450
576
 
451
577
  // Update state of Tsetlin Automata team
452
- __global__ void update_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights, int *clause_output, int *class_sum, int *y, int example)
578
+ __global__ void update_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights, float *clause_output, float *class_sum, int *y, int example)
453
579
  {
454
580
  int index = blockIdx.x * blockDim.x + threadIdx.x;
455
581
  int stride = blockDim.x * gridDim.x;
@@ -459,13 +585,18 @@ code_update = """
459
585
 
460
586
  for (unsigned long long clause = index; clause < CLAUSES; clause += stride) {
461
587
  for (unsigned long long class_id = 0; class_id < number_of_outputs; ++class_id) {
462
- int local_class_sum = class_sum[class_id];
588
+ float local_class_sum = class_sum[class_id];
463
589
  if (local_class_sum > THRESHOLD) {
464
590
  local_class_sum = THRESHOLD;
465
591
  } else if (local_class_sum < -THRESHOLD) {
466
592
  local_class_sum = -THRESHOLD;
467
593
  }
468
- update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], clause_output[clause], y[example*number_of_outputs + class_id], local_class_sum);
594
+
595
+ #if LOG_SCALE == 1
596
+ update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], clause_output[clause] != NEG_INFINITY, y[example*number_of_outputs + class_id], local_class_sum);
597
+ #else
598
+ update_clause_weight(&localState, tm_type, number_of_outputs, &clause_weights[class_id*CLAUSES + clause], clause_output[clause] > 0, y[example*number_of_outputs + class_id], local_class_sum);
599
+ #endif
469
600
  }
470
601
  }
471
602
 
@@ -477,7 +608,7 @@ code_update = """
477
608
  code_prepare = """
478
609
  extern "C"
479
610
  {
480
- __global__ void prepare_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights, int *class_sum)
611
+ __global__ void prepare_weights(curandState *state, int tm_type, int number_of_outputs, int *clause_weights)
481
612
  {
482
613
  int index = blockIdx.x * blockDim.x + threadIdx.x;
483
614
  int stride = blockDim.x * gridDim.x;
@@ -501,17 +632,14 @@ code_prepare = """
501
632
  state[index] = localState;
502
633
  }
503
634
 
504
- __global__ void prepare_hierarchy(curandState *state, int number_of_outputs, unsigned int *global_ta_state, int *clause_weights, int *class_sum)
635
+ __global__ void prepare_hierarchy(int number_of_outputs, unsigned int *global_ta_state)
505
636
  {
506
637
  int index = blockIdx.x * blockDim.x + threadIdx.x;
507
638
  int stride = blockDim.x * gridDim.x;
508
639
 
509
- curandState localState = state[index];
510
-
511
- // Evaluate each clause component (leaf) in separate threads
512
- for (int clause_component = index; clause_component < CLAUSES*COMPONENTS; clause_component += stride) {
513
- // Get state of current clause component
514
- unsigned int *ta_state = &global_ta_state[clause_component*TA_CHUNKS_PER_LEAF*STATE_BITS];
640
+ for (int clause_team = index; clause_team < CLAUSES*TA_TEAMS; clause_team += stride) {
641
+ // Get state of current ta team
642
+ unsigned int *ta_state = &global_ta_state[clause_team*TA_CHUNKS_PER_LEAF*STATE_BITS];
515
643
  for (int ta_chunk = 0; ta_chunk < TA_CHUNKS_PER_LEAF; ++ta_chunk) {
516
644
  for (int b = 0; b < STATE_BITS-1; ++b) {
517
645
  ta_state[ta_chunk*STATE_BITS + b] = ~0;
@@ -519,8 +647,6 @@ code_prepare = """
519
647
  ta_state[ta_chunk*STATE_BITS + STATE_BITS - 1] = 0;
520
648
  }
521
649
  }
522
-
523
- state[index] = localState;
524
650
  }
525
651
  }
526
652
  """
@@ -589,9 +715,9 @@ code_clauses = """
589
715
  int index = blockIdx.x * blockDim.x + threadIdx.x;
590
716
  int stride = blockDim.x * gridDim.x;
591
717
 
592
- for (unsigned long long i = index; i < 1LLU * CLAUSES * COMPONENTS * LITERALS_PER_LEAF; i += stride) {
593
- unsigned long long clause = i / (COMPONENTS * LITERALS_PER_LEAF);
594
- unsigned long long comp = (i / LITERALS_PER_LEAF) % COMPONENTS;
718
+ for (unsigned long long i = index; i < 1LLU * CLAUSES * TA_TEAMS * LITERALS_PER_LEAF; i += stride) {
719
+ unsigned long long clause = i / (TA_TEAMS * LITERALS_PER_LEAF);
720
+ unsigned long long comp = (i / LITERALS_PER_LEAF) % TA_TEAMS;
595
721
  unsigned long long ta_idx = i % LITERALS_PER_LEAF;
596
722
 
597
723
  int chunk = ta_idx / 32;
@@ -600,14 +726,14 @@ code_clauses = """
600
726
  unsigned int state = 0;
601
727
  for (int b = 0; b < STATE_BITS; ++b) {
602
728
  unsigned int plane = global_ta_state[
603
- (clause * COMPONENTS * TA_CHUNKS_PER_LEAF * STATE_BITS) +
729
+ (clause * TA_TEAMS * TA_CHUNKS_PER_LEAF * STATE_BITS) +
604
730
  (comp * TA_CHUNKS_PER_LEAF * STATE_BITS) +
605
731
  (chunk * STATE_BITS) + b
606
732
  ];
607
733
  if (plane & (1U << bit_pos)) state |= (1U << b);
608
734
  }
609
735
 
610
- unpacked_states[(clause * COMPONENTS * LITERALS_PER_LEAF) + (comp * LITERALS_PER_LEAF) + ta_idx] = state;
736
+ unpacked_states[(clause * TA_TEAMS * LITERALS_PER_LEAF) + (comp * LITERALS_PER_LEAF) + ta_idx] = state;
611
737
  }
612
738
  }
613
739
  """