Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

A (one dimensional) cellular automaton is a function1 F : Σ → Σ with the property that there is a K > 0 such that F (x)i depends only on the 2K + 1 coordinates xi−K , xi−K+1, . . . , xi−1, xi, xi+1, . . . , xi+K . A periodic point of σ is any x such that σ^p (x) = x for some p ∈ N, and a periodic point of F is any x such that F^q (x) = x for some q ∈ N. Given a cellular automaton F, a point x ∈ Σ is jointly periodic if there are p, q ∈ N such that σ^p (x) = F^q (x) = x, that is, it is a periodic point under both functions.

This project aims to explore the nature of one-dimensional Cellular Automata, in the hope of finding the structure of cellular automata through its periodic points.

2034 views
License: MIT
ubuntu2004
1
/*
2
* Copyright (C) 2004 Bryant Lee
3
*
4
* This file is part of FDense.
5
*
6
* FDense is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* FDense is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with FDense; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
/* Main function
22
* FDense program takes as input N (shift size), k (shift period), the c.a.
23
* rule f, and m. It determines whether f is m-dense where m-dense means
24
* that every word of length m appears in a jointly periodic point. If it
25
* is not m-dense, it lists the words that do not appear in jointly periodic
26
* points.
27
*
28
* Written by: Bryant Lee
29
* Date: 9/01/05
30
*/
31
32
#define USEARRAY 0
33
#define DEBUG 0
34
35
//Standard C++
36
#include <string.h>
37
#include <iostream>
38
#include <iomanip>
39
#include <fstream> //for file ops
40
41
//C
42
#include <stdlib.h> //for atoi
43
#include <math.h> //for pow
44
45
//STL
46
#include <vector>
47
#include <list>
48
#include <map>
49
50
//local
51
#include "StringOps.h"
52
#include "Comp.h"
53
#include "StorageKey.h"
54
#include "StorageVal.h"
55
#include "RecNode.h"
56
57
#include "GroupData.h"
58
#include "MList.h"
59
60
/*
61
* Function definitions
62
*/
63
void convertPeriodList(const string &strInput, vector<int> &periodList);
64
void exhaustiveExp(unsigned int shiftSize, const vector<int> &periodList,
65
unsigned int density, Comp *comp,
66
list<MList> &recList, MList &unionList, string &prefix,
67
vector<string> &commandbuffer);
68
void exhaustiveExpTwoShift(unsigned int shiftSize,
69
const vector<int> &periodList, unsigned int density,
70
Comp *comp, list<MList> &recList, MList &unionList,
71
string &prefix, vector<string> &commandbuffer);
72
void clearStorageNodes(vector<StorageVal*> &table);
73
void clearRecList(list<RecNode*> &recList);
74
75
void output(unsigned int shiftSize, int density, string &prefix,
76
const vector<int> &periodList,
77
Comp * comp, list<MList> &recList, MList &unionList,
78
vector<string> &commandbuffer);
79
void groupoutput(int density, string &prefix, vector<string> &commandbuffer,
80
vector<GroupData> &groupdata);
81
82
83
void findDivisors(unsigned int x, vector<int> &divisorsList);
84
85
bool leastPeriod(byte *word, unsigned int currPeriod,
86
const vector<int> &divisorsList);
87
bool leastPeriod(unsigned int word, unsigned int currPeriod,
88
const vector<int> &divisorsList);
89
void makeMPrefixList(vector<bool> &m_table, MList &record, unsigned int shiftSize);
90
91
/*
92
* GLOBAL variables
93
*/
94
int UINTSIZE = 32;
95
96
int VERBOSE = 0; //display non-appearing m-words for each individual K
97
98
//boolean that determines whether output is given after each completed experiment (after each K)
99
//or only at end
100
bool OUTPUT_AFTER_EACH = false;
101
102
//determine whether the output is in the "group" format or the normal format
103
bool GROUP = false;
104
105
//main
106
int main() {
107
//book-keeping variables
108
unsigned int shiftSize; //# symbols in shift
109
string prefix; //prefix for output files
110
string strInput, strInput2, strInput3; //temp variables
111
string outoption; //output after each or at end
112
113
vector<int> periodList; //list of periods
114
unsigned int i = 0, temp; //counter
115
116
//results variables
117
list<MList> recList; //list of prefixes not seen, this is per K value
118
MList unionList = MList(0); //list of prefixes not seen, over all K values
119
120
//computation variables
121
Comp *comp = NULL; //composition to apply
122
unsigned int density;
123
124
//hold the command strings
125
vector<string> commandbuffer;
126
int commandbufferit;
127
128
//storage for the "group" option
129
vector<GroupData> groupdata;
130
unsigned int groupdatait;
131
132
//grab all input from cin and put in an array of strings
133
while(!cin.eof()) {
134
std::getline(cin, strInput);
135
commandbuffer.push_back(strInput);
136
}
137
138
commandbufferit = 0;
139
140
//get "output after each" or "output at end"
141
outoption = commandbuffer[commandbufferit++];
142
trim(outoption);
143
transform(outoption.begin(), outoption.end(), outoption.begin(), tolower);
144
145
if(outoption == "output after each") {
146
OUTPUT_AFTER_EACH = true;
147
}
148
else if(outoption == "output at end") {
149
OUTPUT_AFTER_EACH = false;
150
}
151
else {
152
cout << "Error on line 1: invalid value for output mode\n";
153
goto cleanup;
154
}
155
156
//get "group" or "no group"
157
strInput = commandbuffer[commandbufferit++];
158
trim(strInput);
159
transform(strInput.begin(), strInput.end(), strInput.begin(), tolower);
160
161
if(strInput == "group") {
162
GROUP = true;
163
}
164
else if(strInput == "no group") {
165
GROUP = false;
166
}
167
else {
168
cout << "Error on line 2: invalid value for group mode\n";
169
goto cleanup;
170
}
171
172
//get filename prefix
173
prefix = commandbuffer[commandbufferit++];
174
trim(prefix);
175
176
//get N, the number of symbols in the full shift
177
strInput = commandbuffer[commandbufferit++];
178
trim(strInput);
179
shiftSize = atoi(strInput.c_str());
180
181
//get set of K, the periodicities to be tested
182
strInput = commandbuffer[commandbufferit++];
183
convertPeriodList(strInput, periodList);
184
185
//get m, to check for m-dense
186
strInput = commandbuffer[commandbufferit++];
187
trim(strInput);
188
density = atoi(strInput.c_str());
189
190
//Allocate composition object
191
comp = new Comp(shiftSize);
192
193
//get "Begin Definitions"
194
strInput = commandbuffer[commandbufferit++];
195
196
//make it lowercase
197
trim(strInput);
198
transform(strInput.begin(), strInput.end(), strInput.begin(), tolower);
199
200
if(strInput.compare("begin definitions") != 0) {
201
cout << "ERROR: Expecting \"BEGIN DEFINITIONS\"\n";
202
goto cleanup;
203
}
204
205
//read definitions
206
while(1) {
207
strInput = commandbuffer[commandbufferit++];
208
209
//strInput2 is lowercased and trimmed
210
strInput2.resize(strInput.length());
211
transform(strInput.begin(), strInput.end(), strInput2.begin(), tolower);
212
trim(strInput2);
213
214
//strInput3 is lowercased and NOT TRIMMED
215
strInput3.resize(strInput.length());
216
transform(strInput.begin(), strInput.end(), strInput3.begin(), tolower);
217
218
if(strInput2 == "" || (strInput2[0] == '/' && strInput2[1] == '/')) {
219
//ignore blank lines and allow comment out
220
}
221
else if(strInput2 == "begin commands") {
222
break; //BREAK
223
}
224
else {
225
i = 0;
226
227
while(i < strInput.length()) {
228
if(strInput[i] == '=') {
229
break;
230
}
231
232
i++;
233
}
234
235
if(strInput2[0] == 'o' && strInput2[1] == 'p' && strInput2[2] == 't') {
236
temp = strInput3.find("opt");
237
temp += 3;
238
239
comp->addFunc(strInput.substr(i+1, strInput.length() - (i+1)),
240
strInput.substr(temp, i-temp), true);
241
}
242
else {
243
comp->addFunc(strInput.substr(i+1, strInput.length() - (i+1)),
244
strInput.substr(0,i), false);
245
}
246
}
247
}
248
249
//read all the valid commands and store in groupdata array
250
while(commandbufferit < (int)commandbuffer.size()) {
251
strInput = commandbuffer[commandbufferit++];
252
trim(strInput);
253
254
//ignore blank lines and allow comment out with "//"
255
if(strInput != "" && !(strInput[0] == '/' && strInput[1] == '/')) {
256
GroupData gd;
257
258
gd.name = strInput;
259
groupdata.push_back(gd);
260
}
261
}
262
263
//iterate and execute commands
264
for(groupdatait = 0; groupdatait < groupdata.size(); groupdatait++) {
265
strInput = groupdata[groupdatait].name;
266
267
//set composition
268
if(!comp->setComposition(strInput)) {
269
cout << "ERROR: Command \"" << strInput
270
<< "\" references undefined function\n";
271
goto cleanup;
272
}
273
274
int maxshiftperiod = 0;
275
for(i = 0; i < periodList.size(); i++)
276
maxshiftperiod = (maxshiftperiod < periodList[i] ?
277
periodList[i] : maxshiftperiod);
278
279
//do experiment
280
if(shiftSize == 2
281
&& sizeof(unsigned int) == 4
282
&& !USEARRAY
283
&& maxshiftperiod <= 32) //if shift period goes > 32 then must use array representation
284
exhaustiveExpTwoShift(shiftSize, periodList, density, comp, recList,
285
unionList, prefix, commandbuffer);
286
else
287
exhaustiveExp(shiftSize, periodList, density, comp, recList, unionList, prefix, commandbuffer);
288
289
if(!OUTPUT_AFTER_EACH)
290
output(shiftSize, density, prefix, periodList, comp,
291
recList, unionList, commandbuffer);
292
293
groupdata[groupdatait].recList = recList;
294
groupdata[groupdatait].unionList = unionList;
295
groupdata[groupdatait].pending = false;
296
297
//clear list of prefixes
298
recList.clear();
299
300
if(OUTPUT_AFTER_EACH) {
301
groupoutput(density, prefix, commandbuffer, groupdata);
302
}
303
}
304
305
//Do the group output (assuming output at end)
306
if(!OUTPUT_AFTER_EACH) {
307
groupoutput(density, prefix, commandbuffer, groupdata);
308
}
309
310
//cleanup and exit
311
cleanup:
312
313
//delete composition (and the functions in the Comp object's storage)
314
delete comp;
315
316
return 0;
317
}
318
319
/*
320
* Group output
321
*/
322
323
void groupoutput(int density, string &prefix, vector<string> &commandbuffer,
324
vector<GroupData> &groupdata) {
325
int commandbufferit;
326
int groupdatait;
327
328
if(GROUP) {
329
ofstream fout;
330
string fname = prefix + "group.txt";
331
fout.open(fname.c_str(), ios::trunc | ios::out);
332
333
if(!fout.is_open()) {
334
cout << "ERROR: could not create file " << fname << "\n";
335
}
336
337
fout << "FDense 3.67\n\n";
338
339
//copy of the input
340
fout << "INPUT\n";
341
fout << "--------------------\n";
342
for(commandbufferit = 0; commandbufferit < (int)commandbuffer.size(); commandbufferit++) {
343
string test;
344
test = commandbuffer[commandbufferit];
345
trim(test);
346
if(test != "") {
347
fout << commandbuffer[commandbufferit] << "\n";
348
}
349
}
350
fout << "--------------------\n";
351
fout << "\n";
352
353
fout << "For m = " << density << " the following maps were found to have m-dense jointly periodic points of (not least) shift period k, "
354
<< "for the following k:" << "\n";
355
fout << "\n";
356
357
for(groupdatait = 0; groupdatait < (int)groupdata.size(); groupdatait++) {
358
bool none = true;
359
360
fout << "Map: " << groupdata[groupdatait].name << "\n";
361
fout << "----" << "\n";
362
363
if(groupdata[groupdatait].pending) {
364
fout << "PENDING" << "\n";
365
}
366
else {
367
list<MList>::const_iterator it;
368
for(it = groupdata[groupdatait].recList.begin(); it != groupdata[groupdatait].recList.end(); it++) {
369
if((*(it->List.begin())).compare("m-dense") == 0) {
370
fout << it->currPeriod << "\n";
371
none = false;
372
}
373
}
374
375
if(none) {
376
fout << "none" << "\n";
377
}
378
}
379
380
fout << "\n";
381
}
382
383
fout.close();
384
}
385
}
386
387
388
/*
389
* Full output
390
*/
391
392
void output(unsigned int shiftSize, int density, string &prefix,
393
const vector<int> &periodList, Comp * comp, list<MList> &recList,
394
MList &unionList, vector<string> &commandbuffer) {
395
list<MList>::const_iterator it;
396
//unsigned int i;
397
unsigned int commandbufferit;
398
399
if(!GROUP) {
400
401
//output
402
ofstream fout;
403
string fname = prefix + comp->returnName() + ".txt";
404
fout.open(fname.c_str(), ios::trunc | ios::out);
405
406
if(!fout.is_open()) {
407
cout << "ERROR: could not create file " << fname << "\n";
408
return;
409
}
410
411
//HEADER
412
fout << "FDense 3.67\n";
413
414
/*
415
fout << "N = " << shiftSize << "\n";
416
fout << "K = ";
417
for(i = 0; i < periodList.size(); i++) {
418
fout << periodList[i];
419
if(i != periodList.size() - 1)
420
fout << ",";
421
}
422
fout << "\n";
423
fout << "m = " << density;
424
fout << "\n";
425
*/
426
427
fout << "\n";
428
429
//copy of the input
430
fout << "INPUT\n";
431
fout << "--------------------\n";
432
for(commandbufferit = 0; commandbufferit < commandbuffer.size(); commandbufferit++) {
433
string test;
434
test = commandbuffer[commandbufferit];
435
trim(test);
436
if(test != "") {
437
fout << commandbuffer[commandbufferit] << "\n";
438
}
439
}
440
fout << "--------------------\n";
441
fout << "\n";
442
443
//fill on right side, show in fixed notation
444
fout << setiosflags(ios::left | ios::fixed);
445
446
fout << "COMMAND:\n";
447
fout << comp->returnName() << "\n";
448
fout << "WITH DEFINITIONS:\n";
449
comp->printDefinitions(fout);
450
fout << "\n";
451
452
fout << "Outcomes Summary\n";
453
for(it = recList.begin(); it != recList.end(); it++) {
454
fout << "K=" << it->currPeriod << " ";
455
if(it->pending) {
456
fout << "PENDING";
457
}
458
else {
459
if((*(it->List.begin())).compare("m-dense") == 0) {
460
fout << "m-dense";
461
}
462
else {
463
fout << "not m-dense";
464
}
465
}
466
fout << "\n";
467
}
468
fout << "\n";
469
470
fout << "List of m-words not appearing in jointly periodic points\n\n";
471
472
fout << "For union of all K (excluding those that are PENDING)\n\n";
473
list<string>::const_iterator subit;
474
for(subit = unionList.List.begin(); subit != unionList.List.end(); subit++) {
475
fout << *subit << "\n";
476
}
477
fout << "\n";
478
479
if(VERBOSE) {
480
fout << "For each particular value of K\n\n";
481
482
for(it = recList.begin(); it != recList.end(); it++) {
483
fout << "K = " << it->currPeriod << "\n";
484
485
if(it->pending) {
486
fout << "PENDING" << "\n";
487
fout << "\n";
488
}
489
else {
490
for(subit = it->List.begin(); subit != it->List.end(); subit++) {
491
fout << *subit << "\n";
492
}
493
fout << "\n";
494
}
495
}
496
}
497
498
//DONE
499
fout.close();
500
}
501
}
502
503
void exhaustiveExp(unsigned int shiftSize, const vector<int> &periodList,
504
unsigned int density, Comp *comp,
505
list<MList> &recList, MList &unionList, string &prefix,
506
vector<string> &commandbuffer) {
507
unsigned int i = 0, j = 0; //k = 0; //counters
508
unsigned int currPeriod;
509
510
list<StorageKey> orbitList;
511
list<StorageKey> periodicPoints;
512
513
vector<int> table; //table for storing points, checking for intersections
514
vector<bool> global_m_table(pow(shiftSize,density), false); //table for storing m-words not found in union over all K
515
516
list<MList>::iterator recIterator;
517
518
if(DEBUG)
519
cout << "Arrays\n";
520
521
//make a list of MList nodes, one per K value
522
for(i = 0; i < periodList.size(); i++) {
523
recList.push_back(MList(periodList[i]));
524
}
525
526
//initialize recIterator
527
recIterator = recList.begin();
528
529
for(i = 0; i < periodList.size(); i++) {
530
currPeriod = periodList[i];
531
byte itWord[currPeriod]; //iterating word
532
533
MList *record = &(*recIterator);
534
535
if(DEBUG)
536
cout << "currPeriod = " << currPeriod << "\n";
537
538
//set table size
539
table.resize(pow(shiftSize,currPeriod), -2); //initialize to -2
540
541
if(DEBUG)
542
cout << "Allocated table\n";
543
544
//zero the itWord
545
for(j = 0; j < currPeriod; j++) {
546
itWord[j] = 0;
547
}
548
549
while(true) {
550
byte cWord[currPeriod]; //curr word
551
byte output[currPeriod]; //helper word
552
unsigned int period = 0, preperiod = 0;
553
int rt;
554
bool halt = false;
555
556
while(halt != true &&
557
table[StorageKey(itWord,currPeriod).hash(shiftSize)] != -2)
558
{
559
halt = iterateWord(itWord, currPeriod, shiftSize);
560
}
561
562
if(halt == true)
563
break; //exit loop
564
565
//Set current word
566
copyWord(cWord, itWord, currPeriod);
567
568
StorageKey sk1 = StorageKey(cWord, currPeriod);
569
570
table[sk1.hash(shiftSize)] = 0;
571
572
orbitList.push_back(sk1);
573
574
//DEBUG
575
//cout << "\n-- Start orbit --\n";
576
//printArray(cWord, currPeriod);
577
578
//Perform experiment
579
j = 1;
580
while(true) {
581
comp->image(cWord, currPeriod, output);
582
copyWord(cWord, output, currPeriod);
583
584
//DEBUG
585
//printArray(cWord, currPeriod);
586
587
StorageKey sk2 = StorageKey(cWord, currPeriod);
588
589
rt = table[sk2.hash(shiftSize)];
590
if(rt != -2) {
591
break;
592
}
593
else {
594
table[sk2.hash(shiftSize)] = j;
595
orbitList.push_back(sk2);
596
}
597
598
j++;
599
}
600
601
if(rt == -1) {
602
//returned to a point we've seen
603
//none of these points can be periodic
604
605
list<StorageKey>::iterator it;
606
for(it = orbitList.begin(); it != orbitList.end(); it++) {
607
table[it->hash(shiftSize)] = -1;
608
}
609
}
610
else {
611
//we circled back to an active point
612
period = j - rt;
613
preperiod = rt;
614
615
list<StorageKey>::iterator it;
616
for(it = orbitList.begin(); it != orbitList.end(); it++) {
617
table[it->hash(shiftSize)] = -1; //mark as seen
618
619
if(preperiod > 0) {
620
preperiod--;
621
}
622
else {
623
periodicPoints.push_back(*it);
624
}
625
}
626
}
627
628
//cout << "Clearing list\n";
629
orbitList.clear();
630
}
631
632
//cout << "Clearing table\n";
633
table.clear();
634
635
//DEBUG
636
/*
637
{
638
cout << "\n\nPeriodic points\n";
639
list<StorageKey>::iterator it;
640
for(it = periodicPoints.begin(); it != periodicPoints.end(); it++) {
641
printArray(it->word, currPeriod);
642
}
643
}
644
*/
645
//DEBUG
646
647
//DEBUG: make a fake point for testing
648
/*
649
periodicPoints.clear();
650
byte t_arr[7];
651
t_arr[0] = 1;
652
t_arr[1] = 2;
653
t_arr[2] = 0;
654
t_arr[3] = 1;
655
t_arr[4] = 1;
656
t_arr[5] = 1;
657
t_arr[6] = 1;
658
periodicPoints.push_back(StorageKey(t_arr, 7));
659
*/
660
//DEBUG
661
662
//now cross off all m_words that do not exist in periodic point
663
664
vector<bool> m_table(pow(shiftSize,density), false); //table of all m_words (for this particular K)
665
byte m_word[density];
666
StorageKey hasher(m_word, density);
667
unsigned int location;
668
669
list<StorageKey>::iterator it;
670
for(it = periodicPoints.begin(); it != periodicPoints.end(); it++) {
671
672
for(location = 0; location < currPeriod; location++) {
673
674
//read the word
675
for(j = 0; j < density; j++) {
676
hasher.word[j] = it->word[(j + location) % currPeriod];
677
}
678
679
//MAKE SURE TO USE hash_baseB SO THEY HASH TO THE RIGHT PLACE
680
m_table[hasher.hash_baseB(shiftSize)] = true; //for this particular K
681
global_m_table[hasher.hash_baseB(shiftSize)] = true; //for all K
682
}
683
}
684
685
makeMPrefixList(m_table, (*record), shiftSize);
686
687
unionList.List.clear(); //clear the list, it will be reset from the complete global table that has all the info
688
makeMPrefixList(global_m_table, unionList, shiftSize);
689
690
//clear periodicpoints list
691
periodicPoints.clear();
692
693
record->pending = false;
694
695
//advance recIterator to next in list
696
recIterator++;
697
698
if(OUTPUT_AFTER_EACH) {
699
output(shiftSize, density, prefix, periodList, comp, recList, unionList,
700
commandbuffer);
701
}
702
}
703
}
704
705
void makeMPrefixList(vector<bool> &m_table, MList &record, unsigned int shiftSize) {
706
unsigned int j; //counter
707
708
//DEBUG: make a fake table for testing
709
/*
710
for(j = 0; j < m_table.size(); j++)
711
m_table[j] = false;
712
713
for(j = 0; j <= 1; j++) {
714
m_table[j] = true;
715
}
716
for(j = 12; j <= 27; j++) {
717
m_table[j] = true;
718
}
719
for(j = 52; j < m_table.size(); j++) {
720
m_table[j] = true;
721
}
722
*/
723
//DEBUG
724
725
//DEBUG: print the m_table
726
/*
727
cout <<"\n\nm_table\n";
728
for(j = 0; j < m_table.size(); j++) {
729
if(m_table[j]) {
730
unsigned int t;
731
for(t = m_table.size() / shiftSize; t >= 1; t /= shiftSize) {
732
cout << (j / t) % shiftSize;
733
if(t > 1)
734
cout << ",";
735
}
736
cout << "\n";
737
}
738
}
739
*/
740
//DEBUG
741
742
//now list the m words lexicographically with truncate
743
unsigned int count_true = 0; //count true's, lets us know if table full
744
for(j = 0; j < m_table.size(); j++) {
745
if(!m_table[j]) {
746
string m_prefix = "";
747
748
if(j % shiftSize == 0) { //has a zero at lsb so this might be cut to a prefix
749
//t = shiftSize ^ (numzeros on right in j in base shiftsize)
750
unsigned int t;
751
for(t = shiftSize; (j / t) % shiftSize == 0
752
&& t < m_table.size(); t *= shiftSize) {
753
}
754
755
//count is how many adjacent elements are false (counting this one)
756
unsigned int count;
757
for(count = 1; count < t && !m_table[j + count]; count++) {
758
}
759
760
//s is the largest power of shiftsize that is <= count
761
unsigned int s;
762
for(s = shiftSize; s <= count; s *= shiftSize) {
763
}
764
s /= shiftSize; //adjust since the for loop goes 1 further
765
766
int spacing = 0; //count up to four, then add a space
767
768
//create the correct prefix
769
for(t = m_table.size() / shiftSize; t >= 1; t /= shiftSize) {
770
char temp_c[80];
771
772
if(t >= s) {
773
sprintf(temp_c, "%d", (j / t) % shiftSize);
774
m_prefix += string(temp_c);
775
}
776
else
777
m_prefix += "-";
778
779
if(spacing % 4 == 3) //on every fourth char, add a space
780
m_prefix += " ";
781
782
spacing++;
783
}
784
785
// j JUMPS s SPACES AHEAD because these s elements constitute
786
// one prefix, but at the end of the loop j increments 1 more,
787
// so we need to increment by s - 1
788
j += (s - 1);
789
790
}
791
else { //not a prefix
792
unsigned int t;
793
794
int spacing = 0;
795
796
for(t = m_table.size() / shiftSize; t >= 1; t /= shiftSize) {
797
char temp_c[80];
798
799
sprintf(temp_c, "%d", (j / t) % shiftSize);
800
m_prefix += string(temp_c);
801
802
if(spacing % 4 == 3)
803
m_prefix += " ";
804
805
spacing++;
806
}
807
}
808
809
//push back a prefix of non-appearing word
810
record.List.push_back(m_prefix);
811
}
812
else {
813
count_true++;
814
815
//push back m-dense
816
if(count_true == m_table.size()) {
817
record.List.push_back("m-dense");
818
}
819
}
820
}
821
}
822
823
void exhaustiveExpTwoShift(unsigned int shiftSize,
824
const vector<int> &periodList,
825
unsigned int density,
826
Comp *comp, list<MList> &recList, MList &unionList,
827
string &prefix, vector<string> &commandbuffer) {
828
unsigned int i = 0, j = 0; //k = 0; //counters
829
unsigned int currPeriod, numTrials;
830
831
list<unsigned int> orbitList;
832
list<unsigned int> periodicPoints;
833
834
vector<int> table; //table for storing points, checking for intersections
835
vector<bool> global_m_table(pow(shiftSize,density), false); //table for storing m-words not found in union over all K
836
837
list<MList>::iterator recIterator;
838
839
if(DEBUG)
840
cout << "Special case 2-shift\n";
841
842
//make a list of MList nodes, one per K value
843
for(i = 0; i < periodList.size(); i++) {
844
recList.push_back(MList(periodList[i]));
845
}
846
847
//initialize recIterator
848
recIterator = recList.begin();
849
850
for(i = 0; i < periodList.size(); i++) {
851
currPeriod = periodList[i];
852
unsigned int itWord = 0; //iterating word
853
854
MList *record = &(*recIterator);
855
856
numTrials = (int) pow(2, currPeriod);
857
858
table.resize(numTrials, -2);
859
860
while(true) {
861
unsigned int cWord = 0; //curr word
862
unsigned int output = 0; //helper word
863
unsigned int period = 0, preperiod = 0;
864
int rt;
865
866
while(itWord != numTrials &&
867
table[itWord] != -2) {
868
itWord++;
869
}
870
871
if(itWord == numTrials)
872
break; //exit loop
873
874
//Set current word
875
cWord = itWord;
876
877
table[cWord] = 0;
878
orbitList.push_back(cWord);
879
880
//DEBUG
881
//cout << "-- start orbit --\n";
882
//printUInt(cWord, currPeriod);
883
884
//Perform experiment
885
j = 1;
886
while(true) {
887
comp->image(&cWord, currPeriod, &output, 1);
888
889
cWord = output;
890
891
//DEBUG
892
//printUInt(cWord, currPeriod);
893
894
rt = table[cWord];
895
if(rt != -2) {
896
break;
897
}
898
else {
899
table[cWord] = j;
900
orbitList.push_back(cWord);
901
}
902
903
j++;
904
}
905
906
//DEBUG
907
//cout << "-- end orbit --\n";
908
909
if(rt == -1) {
910
//returned to a point we've seen
911
//none of these points can be periodic
912
913
list<unsigned int>::iterator it;
914
for(it = orbitList.begin(); it != orbitList.end(); it++) {
915
table[*it] = -1;
916
}
917
}
918
else {
919
//we circled back to an active point
920
period = j - rt;
921
preperiod = rt;
922
923
list<unsigned int>::iterator it;
924
for(it = orbitList.begin(); it != orbitList.end(); it++) {
925
table[*it] = -1;
926
927
if(preperiod > 0) {
928
preperiod--;
929
}
930
else {
931
periodicPoints.push_back(*it);
932
}
933
}
934
}
935
936
//cout << "Clearing list\n";
937
orbitList.clear();
938
}
939
940
//cout << "Clearing table\n";
941
table.clear();
942
943
//DEBUG
944
/*
945
{
946
cout << "\n\nPeriodic points\n";
947
list<unsigned int>::iterator it;
948
for(it = periodicPoints.begin(); it != periodicPoints.end(); it++) {
949
printUInt(*it, currPeriod);
950
}
951
}
952
*/
953
//DEBUG
954
955
//DEBUG: make up the periodicpoint
956
/*
957
periodicPoints.clear();
958
periodicPoints.push_back(23);
959
*/
960
//DEBUG
961
962
//now cross off all m_words that exist in periodic point
963
964
vector<bool> m_table(pow(2,density), false); //table of all m_words
965
byte m_word[density];
966
StorageKey hasher(m_word, density);
967
unsigned int location;
968
969
list<unsigned int>::iterator it;
970
for(it = periodicPoints.begin(); it != periodicPoints.end(); it++) {
971
972
for(location = 0; location < currPeriod; location++) {
973
974
//read the word
975
for(j = 0; j < density; j++) {
976
int index = (j + location) % currPeriod;
977
978
hasher.word[j] = (*it & (1 << index)) >> index;
979
}
980
981
//MAKE SURE TO USE hash_baseB SO THEY HASH TO THE RIGHT PLACE
982
m_table[hasher.hash_baseB(2)] = true; //for this K
983
global_m_table[hasher.hash_baseB(2)] = true; //for union of K
984
}
985
}
986
987
makeMPrefixList(m_table, (*record), shiftSize);
988
989
unionList.List.clear(); //clear the list, it will be reset from the complete global table that has all the info
990
makeMPrefixList(global_m_table, unionList, shiftSize);
991
992
//clear periodicPoints
993
periodicPoints.clear();
994
995
record->pending = false;
996
//advance recIterator to next in list
997
recIterator++;
998
999
if(OUTPUT_AFTER_EACH) {
1000
output(shiftSize, density, prefix, periodList, comp, recList, unionList,
1001
commandbuffer);
1002
}
1003
}
1004
}
1005
1006
void convertPeriodList(const string &strInput,
1007
vector<int> &periodList) {
1008
vector<string> strList; //all terms
1009
vector<string> subList; //vector representation of an "[a,b]" term
1010
unsigned int strListLength = 0, i = 0;
1011
1012
split(strInput,';', strList);
1013
strListLength = strList.size();
1014
1015
for(i = 0; i < strListLength; i++) {
1016
string *temp = &(strList[i]);
1017
1018
trim(*temp);
1019
1020
if((*temp)[0] == '[') {
1021
int j, low, high;
1022
1023
temp->erase(0,1); //remove '['
1024
temp->erase(temp->length() - 1, 1); //remove ']'
1025
1026
split(*temp, ',', subList);
1027
1028
trim(subList[0]);
1029
trim(subList[1]);
1030
1031
low = atoi(subList[0].c_str());
1032
high = atoi(subList[1].c_str());
1033
1034
for(j = low; j <= high; j++) {
1035
periodList.push_back(j);
1036
}
1037
1038
subList.clear();
1039
}
1040
else {
1041
periodList.push_back(atoi(temp->c_str()));
1042
}
1043
}
1044
}
1045
1046
/*
1047
* Delete the nodes pointed to by ptrs in recList
1048
*/
1049
void clearRecList(list<RecNode*> &recList) {
1050
list<RecNode*>::iterator it;
1051
1052
for(it = recList.begin(); it != recList.end(); it++) {
1053
delete (*it);
1054
}
1055
}
1056
1057
/*
1058
* Delete the nodes pointed to by the values in the table
1059
*/
1060
void clearStorageNodes(vector<StorageVal*> &table) {
1061
vector<StorageVal*>::iterator it;
1062
1063
for(it = table.begin(); it != table.end(); it++) {
1064
delete (*it);
1065
}
1066
}
1067
1068
/*
1069
* Find divisors of X, excluding X itself
1070
*/
1071
void findDivisors(unsigned int x, vector<int> &divisorsList) {
1072
unsigned int i = 2;
1073
unsigned int halfX = x/2;
1074
1075
divisorsList.clear();
1076
1077
if(x > 1) {
1078
divisorsList.push_back(1);
1079
}
1080
1081
for(i = 2; i <= halfX; i++) {
1082
if(x % i == 0) {
1083
divisorsList.push_back(i);
1084
}
1085
}
1086
}
1087
1088
/*
1089
* returns true if this word has least period p
1090
*/
1091
bool leastPeriod(byte *word, unsigned int currPeriod,
1092
const vector<int> &divisorsList) {
1093
bool result = false;
1094
unsigned int i, j, k;
1095
1096
if(currPeriod == 1)
1097
return true;
1098
1099
//for every divisor d
1100
for(i = 0; i < divisorsList.size(); i++) {
1101
unsigned int d = divisorsList[i];
1102
1103
result = false;
1104
1105
//check in chunks of length d
1106
for(j = 0; j < currPeriod; j+= d) {
1107
//check that this chunk is same as other chunks
1108
for(k = 0; k < d; k++) {
1109
if(word[k + j] != word[k]) {
1110
result = true;
1111
break;
1112
}
1113
}
1114
1115
if(result == true)
1116
break;
1117
}
1118
1119
if(result == false)
1120
break;
1121
}
1122
1123
return result;
1124
}
1125
1126
/*
1127
* returns true if this word has least period p
1128
*/
1129
bool leastPeriod(unsigned int word, unsigned int currPeriod,
1130
const vector<int> &divisorsList) {
1131
bool result = false;
1132
unsigned int i, j, k;
1133
1134
if(currPeriod == 1)
1135
return true;
1136
1137
//for every divisor d
1138
for(i = 0; i < divisorsList.size(); i++) {
1139
unsigned int d = divisorsList[i];
1140
1141
result = false;
1142
1143
//check in chunks of length d
1144
for(j = 0; j < currPeriod; j+= d) {
1145
//check that this chunk is same as other chunks
1146
for(k = 0; k < d; k++) {
1147
if(((word >> (k + j)) & 1) != ((word >> k) & 1)) {
1148
result = true;
1149
break;
1150
}
1151
}
1152
1153
if(result == true)
1154
break;
1155
}
1156
1157
if(result == false)
1158
break;
1159
}
1160
1161
return result;
1162
}
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179