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